use std::process;
use {Csv, CsvData, qcheck};
use workdir::Workdir;
fn no_headers(cmd: &mut process::Command) {
cmd.arg("--no-headers");
}
fn pad(cmd: &mut process::Command) {
cmd.arg("--pad");
}
fn run_cat<X, Y, Z, F>(test_name: &str, which: &str, rows1: X, rows2: Y,
modify_cmd: F) -> Z
where X: Csv, Y: Csv, Z: Csv, F: FnOnce(&mut process::Command) {
let wrk = Workdir::new(test_name);
wrk.create("in1.csv", rows1);
wrk.create("in2.csv", rows2);
let mut cmd = wrk.command("cat");
modify_cmd(cmd.arg(which).arg("in1.csv").arg("in2.csv"));
wrk.read_stdout(&mut cmd)
}
#[test]
fn prop_cat_rows() {
fn p(rows: CsvData) -> bool {
let expected = rows.clone();
let (rows1, rows2) =
if rows.is_empty() {
(vec![], vec![])
} else {
let (rows1, rows2) = rows.split_at(rows.len() / 2);
(rows1.to_vec(), rows2.to_vec())
};
let got: CsvData = run_cat("cat_rows", "rows",
rows1, rows2, no_headers);
rassert_eq!(got, expected)
}
qcheck(p as fn(CsvData) -> bool);
}
#[test]
fn cat_rows_space() {
let rows = vec![svec!["\u{0085}"]];
let expected = rows.clone();
let (rows1, rows2) =
if rows.is_empty() {
(vec![], vec![])
} else {
let (rows1, rows2) = rows.split_at(rows.len() / 2);
(rows1.to_vec(), rows2.to_vec())
};
let got: Vec<Vec<String>> =
run_cat("cat_rows_space", "rows", rows1, rows2, no_headers);
assert_eq!(got, expected);
}
#[test]
fn cat_rows_headers() {
let rows1 = vec![svec!["h1", "h2"], svec!["a", "b"]];
let rows2 = vec![svec!["h1", "h2"], svec!["y", "z"]];
let mut expected = rows1.clone();
expected.extend(rows2.clone().into_iter().skip(1));
let got: Vec<Vec<String>> = run_cat("cat_rows_headers", "rows",
rows1, rows2, |_| ());
assert_eq!(got, expected);
}
#[test]
fn prop_cat_cols() {
fn p(rows1: CsvData, rows2: CsvData) -> bool {
let got: Vec<Vec<String>> = run_cat(
"cat_cols", "columns", rows1.clone(), rows2.clone(), no_headers);
let mut expected: Vec<Vec<String>> = vec![];
let (rows1, rows2) = (rows1.to_vecs().into_iter(),
rows2.to_vecs().into_iter());
for (mut r1, r2) in rows1.zip(rows2) {
r1.extend(r2.into_iter());
expected.push(r1);
}
rassert_eq!(got, expected)
}
qcheck(p as fn(CsvData, CsvData) -> bool);
}
#[test]
fn cat_cols_headers() {
let rows1 = vec![svec!["h1", "h2"], svec!["a", "b"]];
let rows2 = vec![svec!["h3", "h4"], svec!["y", "z"]];
let expected = vec![
svec!["h1", "h2", "h3", "h4"],
svec!["a", "b", "y", "z"],
];
let got: Vec<Vec<String>> = run_cat("cat_cols_headers", "columns",
rows1, rows2, |_| ());
assert_eq!(got, expected);
}
#[test]
fn cat_cols_no_pad() {
let rows1 = vec![svec!["a", "b"]];
let rows2 = vec![svec!["y", "z"], svec!["y", "z"]];
let expected = vec![
svec!["a", "b", "y", "z"],
];
let got: Vec<Vec<String>> = run_cat("cat_cols_headers", "columns",
rows1, rows2, no_headers);
assert_eq!(got, expected);
}
#[test]
fn cat_cols_pad() {
let rows1 = vec![svec!["a", "b"]];
let rows2 = vec![svec!["y", "z"], svec!["y", "z"]];
let expected = vec![
svec!["a", "b", "y", "z"],
svec!["", "", "y", "z"],
];
let got: Vec<Vec<String>> = run_cat("cat_cols_headers", "columns",
rows1, rows2, pad);
assert_eq!(got, expected);
}