diff options
| author | Stefan Kreutz <mail@skreutz.com> | 2026-04-30 10:10:46 +0200 |
|---|---|---|
| committer | Stefan Kreutz <mail@skreutz.com> | 2026-04-30 10:10:46 +0200 |
| commit | 46a3d2ba70decd1931e13c190bfa49217e57718d (patch) | |
| tree | 49bc767c52d0cb4cf8443782cae1cc641ef59343 /tests | |
| parent | 47421e41def84ab92a52906f01266b1044fbfe29 (diff) | |
| download | temp-postgres-46a3d2ba70decd1931e13c190bfa49217e57718d.tar.gz | |
Rewrite in async Rust
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/cli.rs | 356 |
1 files changed, 356 insertions, 0 deletions
diff --git a/tests/cli.rs b/tests/cli.rs new file mode 100644 index 0000000..0b99f8b --- /dev/null +++ b/tests/cli.rs @@ -0,0 +1,356 @@ +//! Command-line interface integration test. + +use std::{ + process::{Child, Stdio}, + time::Duration, +}; + +use assert_cmd::{Command, prelude::*}; +use assert_fs::TempDir; +use predicates::prelude::*; +use testresult::TestResult; + +#[test] +fn short_help() -> TestResult { + Command::cargo_bin("temp-postgres")? + .arg("-h") + .assert() + .success() + .stdout(predicate::str::contains("Usage")) + .stderr(predicate::str::is_empty()); + Ok(()) +} + +#[test] +fn long_help() -> TestResult { + Command::cargo_bin("temp-postgres")? + .arg("--help") + .assert() + .success() + .stdout(predicate::str::contains("Usage")) + .stderr(predicate::str::is_empty()); + Ok(()) +} + +#[test] +fn short_version() -> TestResult { + Command::cargo_bin("temp-postgres")? + .arg("-V") + .assert() + .success() + .stdout(predicate::str::is_match( + r#"^temp-postgres [0-9]+\.[0-9]+\.[0-9]+\n$"#, + )?) + .stderr(predicate::str::is_empty()); + Ok(()) +} + +#[test] +fn long_version() -> TestResult { + Command::cargo_bin("temp-postgres")? + .arg("--version") + .assert() + .success() + .stdout(predicate::str::is_match( + r#"^temp-postgres [0-9]+\.[0-9]+\.[0-9]+-[0-9a-f]{7}(-dirty)?\n$"#, + )?) + .stderr(predicate::str::is_empty()); + Ok(()) +} + +#[test] +fn wrapped_true() -> TestResult { + Command::cargo_bin("temp-postgres")? + .arg("--") + .arg("true") + .assert() + .success() + .stdout(predicate::str::is_empty()) + .stderr(predicate::str::contains("PGHOST")); + Ok(()) +} + +#[test] +fn wrapped_false() -> TestResult { + Command::cargo_bin("temp-postgres")? + .arg("--") + .arg("false") + .assert() + .failure() + .stdout(predicate::str::is_empty()) + .stderr(predicate::str::contains("Wrapped command exited error")); + Ok(()) +} + +#[test] +fn log_level_off() -> TestResult { + Command::cargo_bin("temp-postgres")? + .arg("--log-level") + .arg("off") + .arg("--") + .arg("true") + .assert() + .success() + .stdout(predicate::str::is_empty()) + .stderr(predicate::str::is_empty()); + Ok(()) +} + +#[test] +fn no_such_flag() -> TestResult { + Command::cargo_bin("temp-postgres")? + .arg("--foo") + .assert() + .code(2) + .stdout(predicate::str::is_empty()) + .stderr(predicate::str::contains("unexpected argument")); + Ok(()) +} + +#[test] +fn unexpected_argument() -> TestResult { + Command::cargo_bin("temp-postgres")? + .arg("foo") + .assert() + .code(2) + .stdout(predicate::str::is_empty()) + .stderr(predicate::str::contains("unexpected argument")); + Ok(()) +} + +#[test] +fn missing_username_argument() -> TestResult { + Command::cargo_bin("temp-postgres")? + .arg("--username") + .assert() + .code(2) + .stdout(predicate::str::is_empty()) + .stderr(predicate::str::contains("--username")); + Ok(()) +} + +#[test] +fn empty_username_argument() -> TestResult { + Command::cargo_bin("temp-postgres")? + .arg("--username") + .arg("") + .assert() + .code(2) + .stdout(predicate::str::is_empty()) + .stderr(predicate::str::contains("--username")); + Ok(()) +} + +#[test] +fn symlink() -> TestResult { + let tmp_dir = TempDir::new()?; + let symlink = tmp_dir.join("db"); + let child = std::process::Command::cargo_bin("temp-postgres")? + .arg("--username") + .arg("alex") + .arg("--dbname") + .arg("myproject") + .arg("--symlink") + .arg(&symlink) + .stdin(Stdio::null()) + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .spawn()?; + for i in (0..100).rev() { + std::thread::sleep(Duration::from_millis(200)); + if symlink.exists() { + break; + } else if i > 0 { + continue; + } else { + panic!("symlink not created in time"); + } + } + Command::new("psql") + .arg("--no-psqlrc") + .arg("--no-align") + .arg("--tuples-only") + .arg("--host") + .arg(&symlink) + .arg("--dbname") + .arg("myproject") + .arg("--username") + .arg("alex") + .write_stdin("SELECT current_database(), usename FROM pg_user;") + .assert() + .success() + .stdout(predicate::str::is_match(r#"^myproject|alex\n$"#)?) + .stderr(predicate::str::is_empty()); + interrupt(&child); + child.wait_with_output()?.assert().code(130); + Ok(()) +} + +#[test] +fn interrupted() -> TestResult { + let tmp_dir = TempDir::new()?; + let symlink = tmp_dir.join("db"); + let child = std::process::Command::cargo_bin("temp-postgres")? + .arg("--symlink") + .arg(&symlink) + .stdin(Stdio::null()) + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .spawn()?; + for i in (0..100).rev() { + std::thread::sleep(Duration::from_millis(200)); + if symlink.exists() { + break; + } else if i > 0 { + continue; + } else { + panic!("symlink not created in time"); + } + } + interrupt(&child); + child.wait_with_output()?.assert().code(130); + Ok(()) +} + +#[test] +fn interrupted_empty_command() -> TestResult { + let tmp_dir = TempDir::new()?; + let symlink = tmp_dir.join("db"); + let child = std::process::Command::cargo_bin("temp-postgres")? + .arg("--symlink") + .arg(&symlink) + .arg("--") + .stdin(Stdio::null()) + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .spawn()?; + for i in (0..100).rev() { + std::thread::sleep(Duration::from_millis(200)); + if symlink.exists() { + break; + } else if i > 0 { + continue; + } else { + panic!("symlink not created in time"); + } + } + interrupt(&child); + child.wait_with_output()?.assert().code(130); + Ok(()) +} + +#[test] +fn interrupted_sleep_command() -> TestResult { + let tmp_dir = TempDir::new()?; + let symlink = tmp_dir.join("db"); + let child = std::process::Command::cargo_bin("temp-postgres")? + .arg("--symlink") + .arg(&symlink) + .arg("--") + .arg("sleep") + .arg("30") + .stdin(Stdio::null()) + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .spawn()?; + for i in (0..100).rev() { + std::thread::sleep(Duration::from_millis(200)); + if symlink.exists() { + break; + } else if i > 0 { + continue; + } else { + panic!("symlink not created in time"); + } + } + interrupt(&child); + child.wait_with_output()?.assert().code(130); + Ok(()) +} + +#[test] +fn wrapped_cat() -> TestResult { + assert_cmd::Command::cargo_bin("temp-postgres")? + .arg("--") + .arg("cat") + .write_stdin("foo") + .assert() + .success() + .stdout(predicate::str::is_match(r#"^foo$"#)?) + .stderr(predicate::str::contains("PGHOST")); + Ok(()) +} + +#[test] +fn wrapped_psql_with_username() -> TestResult { + assert_cmd::Command::cargo_bin("temp-postgres")? + .arg("--username") + .arg("alex") + .arg("--") + .arg("psql") + .arg("--no-psqlrc") + .arg("--no-align") + .arg("--tuples-only") + .write_stdin("SELECT current_database(), usename FROM pg_user;") + .assert() + .success() + .stdout(predicate::str::is_match(r#"^alex|alex\n$"#)?) + .stderr(predicate::str::contains("PGHOST")); + Ok(()) +} + +#[test] +fn wrapped_psql_with_username_and_dbname() -> TestResult { + assert_cmd::Command::cargo_bin("temp-postgres")? + .arg("--username") + .arg("alex") + .arg("--dbname") + .arg("myproject") + .arg("--") + .arg("psql") + .arg("--no-psqlrc") + .arg("--no-align") + .arg("--tuples-only") + .write_stdin("SELECT current_database(), usename FROM pg_user;") + .assert() + .success() + .stdout(predicate::str::is_match(r#"^myproject|alex\n$"#)?) + .stderr(predicate::str::contains("PGHOST")); + Ok(()) +} + +#[test] +fn wrapped_psql_with_database_url() -> TestResult { + assert_cmd::Command::cargo_bin("temp-postgres")? + .arg("--username") + .arg("alex") + .arg("--dbname") + .arg("myproject") + .arg("--") + .arg("env") + .arg("--unset") + .arg("PGHOST") + .arg("--unset") + .arg("PGDATABASE") + .arg("--unset") + .arg("PGUSER") + .arg("--") + .arg("bash") + .arg("-c") + .arg("psql --no-psqlrc --no-align --tuples-only \"$DATABASE_URL\"") + .write_stdin("SELECT current_database(), usename FROM pg_user;") + .assert() + .success() + .stdout(predicate::str::is_match(r#"^myproject|alex\n$"#)?) + .stderr(predicate::str::contains("PGHOST")); + Ok(()) +} + +fn interrupt(child: &Child) { + // std::os::unix::process::ChildExt::send_signal is nightly-only experimental + nix::sys::signal::kill( + nix::unistd::Pid::from_raw(child.id() as i32), + nix::sys::signal::Signal::SIGINT, + ) + .unwrap(); +} |