diff options
Diffstat (limited to 'vendor/csv/tests')
-rw-r--r-- | vendor/csv/tests/tests.rs | 511 |
1 files changed, 511 insertions, 0 deletions
diff --git a/vendor/csv/tests/tests.rs b/vendor/csv/tests/tests.rs new file mode 100644 index 000000000..ba7395440 --- /dev/null +++ b/vendor/csv/tests/tests.rs @@ -0,0 +1,511 @@ +#![allow(dead_code)] + +use csv::Reader; + +use std::env; +use std::io::{self, Read, Write}; +use std::path::PathBuf; +use std::process::{self, Command}; + +static STRANGE: &'static str = include_str!("../examples/data/strange.csv"); +static USPOP: &'static str = include_str!("../examples/data/uspop.csv"); +static USPOP_NULL: &'static str = + include_str!("../examples/data/uspop-null.csv"); +static USPOP_LATIN1: &'static [u8] = + include_bytes!("../examples/data/uspop-latin1.csv"); +static WORLDPOP: &'static str = + include_str!("../examples/data/bench/worldcitiespop.csv"); +static SMALLPOP: &'static str = include_str!("../examples/data/smallpop.csv"); +static SMALLPOP_COLON: &'static str = + include_str!("../examples/data/smallpop-colon.csv"); +static SMALLPOP_NO_HEADERS: &'static str = + include_str!("../examples/data/smallpop-no-headers.csv"); + +#[test] +fn cookbook_read_basic() { + let mut cmd = cmd_for_example("cookbook-read-basic"); + let out = cmd_output_with(&mut cmd, SMALLPOP.as_bytes()); + assert_eq!(out.stdout().lines().count(), 10); +} + +#[test] +fn cookbook_read_serde() { + let mut cmd = cmd_for_example("cookbook-read-serde"); + let out = cmd_output_with(&mut cmd, SMALLPOP.as_bytes()); + assert_eq!(out.stdout().lines().count(), 10); +} + +#[test] +fn cookbook_read_colon() { + let mut cmd = cmd_for_example("cookbook-read-colon"); + let out = cmd_output_with(&mut cmd, SMALLPOP_COLON.as_bytes()); + assert_eq!(out.stdout().lines().count(), 10); +} + +#[test] +fn cookbook_read_no_headers() { + let mut cmd = cmd_for_example("cookbook-read-no-headers"); + let out = cmd_output_with(&mut cmd, SMALLPOP_NO_HEADERS.as_bytes()); + assert_eq!(out.stdout().lines().count(), 10); +} + +#[test] +fn cookbook_write_basic() { + let mut cmd = cmd_for_example("cookbook-write-basic"); + let out = cmd_output(&mut cmd); + assert_eq!(out.stdout().lines().count(), 3); +} + +#[test] +fn cookbook_write_serde() { + let mut cmd = cmd_for_example("cookbook-write-serde"); + let out = cmd_output(&mut cmd); + assert_eq!(out.stdout().lines().count(), 3); +} + +#[test] +fn tutorial_setup_01() { + let mut cmd = cmd_for_example("tutorial-setup-01"); + let out = cmd_output_with(&mut cmd, USPOP.as_bytes()); + assert_eq!(out.stdout().lines().count(), 100); +} + +#[test] +fn tutorial_error_01() { + let mut cmd = cmd_for_example("tutorial-error-01"); + let out = cmd_output_with(&mut cmd, USPOP.as_bytes()); + assert_eq!(out.stdout().lines().count(), 100); +} + +#[test] +fn tutorial_error_01_errored() { + let data = "\ +header1,header2 +foo,bar +quux,baz,foobar +"; + let mut cmd = cmd_for_example("tutorial-error-01"); + let out = cmd_output_with(&mut cmd, data.as_bytes()); + assert!(out.stderr().contains("thread 'main' panicked")); +} + +#[test] +fn tutorial_error_02() { + let mut cmd = cmd_for_example("tutorial-error-02"); + let out = cmd_output_with(&mut cmd, USPOP.as_bytes()); + assert_eq!(out.stdout().lines().count(), 100); +} + +#[test] +fn tutorial_error_02_errored() { + let data = "\ +header1,header2 +foo,bar +quux,baz,foobar +"; + let mut cmd = cmd_for_example("tutorial-error-02"); + let out = cmd_output_with(&mut cmd, data.as_bytes()); + assert!(out.stdout_failed().contains("error reading CSV from <stdin>")); +} + +#[test] +fn tutorial_error_03() { + let mut cmd = cmd_for_example("tutorial-error-03"); + let out = cmd_output_with(&mut cmd, USPOP.as_bytes()); + assert_eq!(out.stdout().lines().count(), 100); +} + +#[test] +fn tutorial_error_03_errored() { + let data = "\ +header1,header2 +foo,bar +quux,baz,foobar +"; + let mut cmd = cmd_for_example("tutorial-error-03"); + let out = cmd_output_with(&mut cmd, data.as_bytes()); + assert!(out.stdout_failed().contains("CSV error:")); +} + +#[test] +fn tutorial_error_04() { + let mut cmd = cmd_for_example("tutorial-error-04"); + let out = cmd_output_with(&mut cmd, USPOP.as_bytes()); + assert_eq!(out.stdout().lines().count(), 100); +} + +#[test] +fn tutorial_error_04_errored() { + let data = "\ +header1,header2 +foo,bar +quux,baz,foobar +"; + let mut cmd = cmd_for_example("tutorial-error-04"); + let out = cmd_output_with(&mut cmd, data.as_bytes()); + assert!(out.stdout_failed().contains("CSV error:")); +} + +#[test] +fn tutorial_read_01() { + let mut cmd = cmd_for_example("tutorial-read-01"); + cmd.arg(data_dir().join("uspop.csv")); + let out = cmd_output(&mut cmd); + assert_eq!(out.stdout().lines().count(), 100); +} + +#[test] +fn tutorial_read_headers_01() { + let mut cmd = cmd_for_example("tutorial-read-headers-01"); + let out = cmd_output_with(&mut cmd, USPOP.as_bytes()); + assert_eq!(out.stdout().lines().count(), 101); +} + +#[test] +fn tutorial_read_headers_02() { + let mut cmd = cmd_for_example("tutorial-read-headers-02"); + let out = cmd_output_with(&mut cmd, USPOP.as_bytes()); + assert_eq!(out.stdout().lines().count(), 102); +} + +#[test] +fn tutorial_read_delimiter_01() { + let mut cmd = cmd_for_example("tutorial-read-delimiter-01"); + let out = cmd_output_with(&mut cmd, STRANGE.as_bytes()); + assert_eq!(out.stdout().lines().count(), 6); +} + +#[test] +fn tutorial_read_serde_01() { + let mut cmd = cmd_for_example("tutorial-read-serde-01"); + let out = cmd_output_with(&mut cmd, USPOP.as_bytes()); + assert_eq!(out.stdout().lines().count(), 100); + assert!(out.stdout().lines().all(|x| x.contains("pop:"))); +} + +#[test] +fn tutorial_read_serde_02() { + let mut cmd = cmd_for_example("tutorial-read-serde-02"); + let out = cmd_output_with(&mut cmd, USPOP.as_bytes()); + assert_eq!(out.stdout().lines().count(), 100); + assert!(out.stdout().lines().all(|x| x.starts_with("("))); +} + +#[test] +fn tutorial_read_serde_03() { + let mut cmd = cmd_for_example("tutorial-read-serde-03"); + let out = cmd_output_with(&mut cmd, USPOP.as_bytes()); + assert_eq!(out.stdout().lines().count(), 100); + assert!(out.stdout().lines().all(|x| x.contains("\"City\":"))); +} + +#[test] +fn tutorial_read_serde_04() { + let mut cmd = cmd_for_example("tutorial-read-serde-04"); + let out = cmd_output_with(&mut cmd, USPOP.as_bytes()); + assert_eq!(out.stdout().lines().count(), 100); + assert!(out.stdout().lines().all(|x| x.starts_with("Record { latitude:"))); +} + +#[test] +fn tutorial_read_serde_05_invalid() { + let mut cmd = cmd_for_example("tutorial-read-serde-invalid-01"); + let out = cmd_output_with(&mut cmd, USPOP.as_bytes()); + assert_eq!(out.stdout().lines().count(), 100); + assert!(out.stdout().lines().all(|x| x.starts_with("Record { latitude:"))); +} + +#[test] +fn tutorial_read_serde_05_invalid_errored() { + let mut cmd = cmd_for_example("tutorial-read-serde-invalid-01"); + let out = cmd_output_with(&mut cmd, USPOP_NULL.as_bytes()); + assert!(out.stdout_failed().contains("CSV deserialize error:")); +} + +#[test] +fn tutorial_read_serde_invalid_06() { + let mut cmd = cmd_for_example("tutorial-read-serde-invalid-02"); + let out = cmd_output_with(&mut cmd, USPOP_NULL.as_bytes()); + assert_eq!(out.stdout().lines().count(), 100); + assert!(out.stdout().lines().all(|x| x.starts_with("Record { latitude:"))); +} + +#[test] +fn tutorial_write_01() { + let mut cmd = cmd_for_example("tutorial-write-01"); + let out = cmd_output(&mut cmd); + assert_eq!(out.stdout().lines().count(), 4); +} + +#[test] +fn tutorial_write_delimiter_01() { + let mut cmd = cmd_for_example("tutorial-write-delimiter-01"); + let out = cmd_output(&mut cmd); + assert_eq!(out.stdout().lines().count(), 4); + assert!(out.stdout().lines().all(|x| x.contains('\t'))); +} + +#[test] +fn tutorial_write_serde_01() { + let mut cmd = cmd_for_example("tutorial-write-serde-01"); + let out = cmd_output(&mut cmd); + assert_eq!(out.stdout().lines().count(), 4); +} + +#[test] +fn tutorial_write_serde_02() { + let mut cmd = cmd_for_example("tutorial-write-serde-02"); + let out = cmd_output(&mut cmd); + assert_eq!(out.stdout().lines().count(), 4); +} + +#[test] +fn tutorial_pipeline_search_01() { + let mut cmd = cmd_for_example("tutorial-pipeline-search-01"); + cmd.arg("MA"); + let out = cmd_output_with(&mut cmd, USPOP.as_bytes()); + assert_eq!(out.stdout().lines().count(), 2); +} + +#[test] +fn tutorial_pipeline_search_01_errored() { + let mut cmd = cmd_for_example("tutorial-pipeline-search-01"); + cmd.arg("MA"); + let out = cmd_output_with(&mut cmd, USPOP_LATIN1); + assert!(out.stdout_failed().contains("invalid utf-8")); +} + +#[test] +fn tutorial_pipeline_search_02() { + let mut cmd = cmd_for_example("tutorial-pipeline-search-02"); + cmd.arg("MA"); + let out = cmd_output_with(&mut cmd, USPOP_LATIN1); + assert_eq!(out.stdout().lines().count(), 2); +} + +#[test] +fn tutorial_pipeline_pop_01() { + let mut cmd = cmd_for_example("tutorial-pipeline-pop-01"); + cmd.arg("100000"); + let out = cmd_output_with(&mut cmd, USPOP.as_bytes()); + assert_eq!(out.stdout().lines().count(), 4); +} + +#[test] +fn tutorial_perf_alloc_01() { + let mut cmd = cmd_for_example("tutorial-perf-alloc-01"); + let out = cmd_output_with(&mut cmd, WORLDPOP.as_bytes()); + assert_eq!(out.stdout(), "11\n"); +} + +#[test] +fn tutorial_perf_alloc_02() { + let mut cmd = cmd_for_example("tutorial-perf-alloc-02"); + let out = cmd_output_with(&mut cmd, WORLDPOP.as_bytes()); + assert_eq!(out.stdout(), "11\n"); +} + +#[test] +fn tutorial_perf_alloc_03() { + let mut cmd = cmd_for_example("tutorial-perf-alloc-03"); + let out = cmd_output_with(&mut cmd, WORLDPOP.as_bytes()); + assert_eq!(out.stdout(), "11\n"); +} + +#[test] +fn tutorial_perf_serde_01() { + let mut cmd = cmd_for_example("tutorial-perf-serde-01"); + let out = cmd_output_with(&mut cmd, WORLDPOP.as_bytes()); + assert_eq!(out.stdout(), "11\n"); +} + +#[test] +fn tutorial_perf_serde_02() { + let mut cmd = cmd_for_example("tutorial-perf-serde-02"); + let out = cmd_output_with(&mut cmd, WORLDPOP.as_bytes()); + assert_eq!(out.stdout(), "11\n"); +} + +#[test] +fn tutorial_perf_serde_03() { + let mut cmd = cmd_for_example("tutorial-perf-serde-03"); + let out = cmd_output_with(&mut cmd, WORLDPOP.as_bytes()); + assert_eq!(out.stdout(), "11\n"); +} + +#[test] +fn tutorial_perf_core_01() { + let mut cmd = cmd_for_example("tutorial-perf-core-01"); + let out = cmd_output_with(&mut cmd, WORLDPOP.as_bytes()); + assert_eq!(out.stdout(), "11\n"); +} + +#[test] +fn no_infinite_loop_on_io_errors() { + struct FailingRead; + impl Read for FailingRead { + fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> { + Err(io::Error::new(io::ErrorKind::Other, "Broken reader")) + } + } + + let mut record_results = Reader::from_reader(FailingRead).into_records(); + let first_result = record_results.next(); + assert!( + matches!(&first_result, Some(Err(e)) if matches!(e.kind(), csv::ErrorKind::Io(_))) + ); + assert!(record_results.next().is_none()); +} + +// Helper functions follow. + +/// Return the target/debug directory path. +fn debug_dir() -> PathBuf { + env::current_exe() + .expect("test binary path") + .parent() + .expect("test binary directory") + .parent() + .expect("example binary directory") + .to_path_buf() +} + +/// Return the directory containing the example test binaries. +fn example_bin_dir() -> PathBuf { + debug_dir().join("examples") +} + +/// Return the repo root directory path. +fn repo_dir() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")) +} + +/// Return the directory containing the example data. +fn data_dir() -> PathBuf { + repo_dir().join("examples").join("data") +} + +/// Return a command ready to execute the given example test binary. +/// +/// The command's current directory is set to the repo root. +fn cmd_for_example(name: &str) -> Command { + let mut cmd = Command::new(example_bin_dir().join(name)); + cmd.current_dir(repo_dir()); + cmd +} + +/// Return the (stdout, stderr) of running the command as a string. +/// +/// If the command has a non-zero exit code, then this function panics. +fn cmd_output(cmd: &mut Command) -> Output { + cmd.stdout(process::Stdio::piped()); + cmd.stderr(process::Stdio::piped()); + let child = cmd.spawn().expect("command spawns successfully"); + Output::new(cmd, child) +} + +/// Like cmd_output, but sends the given data as stdin to the given child. +fn cmd_output_with(cmd: &mut Command, data: &[u8]) -> Output { + cmd.stdin(process::Stdio::piped()); + cmd.stdout(process::Stdio::piped()); + cmd.stderr(process::Stdio::piped()); + let mut child = cmd.spawn().expect("command spawns successfully"); + { + let stdin = child.stdin.as_mut().expect("failed to get stdin"); + stdin.write_all(data).expect("failed to write to stdin"); + } + Output::new(cmd, child) +} + +struct Output { + stdout: String, + stderr: String, + command: String, + status: process::ExitStatus, +} + +impl Output { + /// Return the (stdout, stderr) of running the given child as a string. + /// + /// If the command has a non-zero exit code, then this function panics. + fn new(cmd: &mut Command, child: process::Child) -> Output { + let out = child.wait_with_output().expect("command runs successfully"); + let stdout = + String::from_utf8(out.stdout).expect("valid utf-8 (stdout)"); + let stderr = + String::from_utf8(out.stderr).expect("valid utf-8 (stderr)"); + Output { + stdout: stdout, + stderr: stderr, + command: format!("{:?}", cmd), + status: out.status, + } + } + + fn stdout(&self) -> &str { + if !self.status.success() { + panic!( + "\n\n==== {:?} ====\n\ + command failed but expected success!\ + \n\ncwd: {}\ + \n\nstatus: {}\ + \n\nstdout: {}\ + \n\nstderr: {}\ + \n\n=====\n", + self.command, + repo_dir().display(), + self.status, + self.stdout, + self.stderr + ); + } + &self.stdout + } + + fn stdout_failed(&self) -> &str { + if self.status.success() { + panic!( + "\n\n==== {:?} ====\n\ + command succeeded but expected failure!\ + \n\ncwd: {}\ + \n\nstatus: {}\ + \n\nstdout: {}\ + \n\nstderr: {}\ + \n\n=====\n", + self.command, + repo_dir().display(), + self.status, + self.stdout, + self.stderr + ); + } + &self.stdout + } + + fn stderr(&self) -> &str { + if self.status.success() { + panic!( + "\n\n==== {:?} ====\n\ + command succeeded but expected failure!\ + \n\ncwd: {}\ + \n\nstatus: {}\ + \n\nstdout: {}\ + \n\nstderr: {}\ + \n\n=====\n", + self.command, + repo_dir().display(), + self.status, + self.stdout, + self.stderr + ); + } + &self.stderr + } +} + +/// Consume the reader given into a string. +fn read_to_string<R: io::Read>(mut rdr: R) -> String { + let mut s = String::new(); + rdr.read_to_string(&mut s).unwrap(); + s +} |