test(csv): add RFC 4180 edge case tests for CSV quote handling

Audit confirms the csv crate correctly handles all RFC 4180 cases:
- Embedded commas in quoted fields
- Escaped quotes ("") within quoted fields
- Embedded newlines in quoted fields
- Combined commas + escaped quotes

No bugs found — added 4 regression tests to document compliance.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Edward Langley
2026-04-08 23:58:30 -07:00
parent 11bcc5d04d
commit ad9ea30fc2

View File

@ -214,6 +214,70 @@ mod tests {
assert_eq!(records[0]["Name"], Value::String("A".to_string())); assert_eq!(records[0]["Name"], Value::String("A".to_string()));
} }
// ── RFC 4180 edge cases ───────────────────────────────────────────
#[test]
fn rfc4180_embedded_comma_in_quoted_field() {
let (path, _dir) = create_temp_csv(
"Name,Address,Value\n\"Smith, John\",\"123 Main St, Apt 4\",100",
);
let records = parse_csv(&path).unwrap();
assert_eq!(records.len(), 1);
assert_eq!(
records[0]["Name"],
Value::String("Smith, John".to_string())
);
assert_eq!(
records[0]["Address"],
Value::String("123 Main St, Apt 4".to_string())
);
}
#[test]
fn rfc4180_escaped_quotes_in_field() {
// RFC 4180: doubled quotes ("") inside a quoted field represent a literal quote
let (path, _dir) = create_temp_csv(
"Name,Description,Value\nWidget,\"A \"\"great\"\" product\",10",
);
let records = parse_csv(&path).unwrap();
assert_eq!(records.len(), 1);
assert_eq!(
records[0]["Description"],
Value::String("A \"great\" product".to_string())
);
}
#[test]
fn rfc4180_newline_in_quoted_field() {
// RFC 4180: quoted fields may contain newlines
let (path, _dir) = create_temp_csv(
"Name,Notes,Value\n\"Widget\",\"Line 1\nLine 2\",10",
);
let records = parse_csv(&path).unwrap();
assert_eq!(records.len(), 1);
assert_eq!(
records[0]["Notes"],
Value::String("Line 1\nLine 2".to_string())
);
}
#[test]
fn rfc4180_embedded_comma_and_quotes_combined() {
let (path, _dir) = create_temp_csv(
"Name,Desc\n\"Smith, \"\"Jr.\"\"\",\"Said \"\"hello, world\"\"\"",
);
let records = parse_csv(&path).unwrap();
assert_eq!(records.len(), 1);
assert_eq!(
records[0]["Name"],
Value::String("Smith, \"Jr.\"".to_string())
);
assert_eq!(
records[0]["Desc"],
Value::String("Said \"hello, world\"".to_string())
);
}
#[test] #[test]
fn parse_checking_csv_format() { fn parse_checking_csv_format() {
// Simulates the format of /Users/edwlan/Downloads/Checking1.csv // Simulates the format of /Users/edwlan/Downloads/Checking1.csv