commit 0f5dfafbf7097df7bc083618c5bc9f52eddae03e
parent 032be5169b408b2913d7ea182df464bacad8575b
Author: Asher Morgan <59518073+ashermorgan@users.noreply.github.com>
Date: Tue, 25 Jun 2024 16:40:10 -0700
Update util unit tests and setup integration tests
Diffstat:
3 files changed, 160 insertions(+), 45 deletions(-)
diff --git a/src/utils.rs b/src/utils.rs
@@ -33,7 +33,7 @@ pub fn link_file(src: &str, dst: &str) -> io::Result<()> {
Ok(())
}
-/// Create the parent directories of a path and return the path with tildes
+/// Creates the parent directories of a path and return the path with tildes
/// expanded.
fn prepare_path(path: &str) -> io::Result<PathBuf> {
let _dst: PathBuf = (&tilde(path).to_mut()).into();
@@ -47,7 +47,7 @@ fn prepare_path(path: &str) -> io::Result<PathBuf> {
Ok(_dst)
}
-/// Execute a local shell script, optionally with a command prefix or postfix.
+/// Executes a local shell script, optionally with a command prefix or postfix.
///
/// Uses sh on Unix and PowerShell on Windows.
pub fn run_script(path: &str, prefix: &str, postfix: &str) -> Result<(), String>
@@ -84,22 +84,43 @@ mod tests {
use std::io::Write;
use std::path::Path;
- // Adapted from ripgrep tests (crates/ignore/src/lib.rs)
- struct TempDir(PathBuf);
+ /// Stores the path to a temporary directory that is automatically deleted
+ /// when the value is dropped.
+ ///
+ /// Adapted from ripgrep's tests (crates/ignore/src/lib.rs)
+ struct TempDir {
+ dir: PathBuf
+ }
impl Drop for TempDir {
fn drop(&mut self) {
- fs::remove_dir_all(&self.0).unwrap();
+ fs::remove_dir_all(&self.dir).unwrap();
}
}
impl TempDir {
- // Will cause a panic if name has already been used
- fn create(name: &str) -> TempDir {
- let path = env::temp_dir().join("coliru-tests").join(name);
- fs::create_dir_all(&path).unwrap();
- TempDir(path)
+ fn new(name: &str) -> TempDir {
+ let dir = env::temp_dir().join("coliru-tests").join(name);
+ assert_eq!(dir.exists(), false);
+ fs::create_dir_all(&dir).unwrap();
+ TempDir { dir }
+ }
+ }
+
+ /// Creates a temporary directory with a certain name and sets $HOME and the
+ /// CWD to the parent directory.
+ ///
+ /// All tests in this module use the same values for $HOME and the CWD,
+ /// which prevents issues when tests are run in multiple threads.
+ fn setup(name: &str) -> TempDir {
+ let dir = TempDir::new(name);
+ let root = dir.dir.parent().unwrap();
+ env::set_current_dir(root).unwrap();
+ if cfg!(target_family = "unix") {
+ env::set_var("HOME", root);
}
+ dir
}
+ /// Create (or overwrite) a file with certain contents.
fn create_file(path: &Path, contents: &str) {
let mut file = fs::File::create(path).unwrap();
file.write_all(contents.as_bytes()).unwrap();
@@ -107,10 +128,10 @@ mod tests {
#[test]
fn test_copy_file_create_dirs() {
- let tmp = TempDir::create("test_copy_file_create_dirs");
+ let tmp = setup("test_copy_file_create_dirs");
- let src = &tmp.0.join("foo");
- let dst = &tmp.0.join("dir1").join("dir2").join("bar");
+ let src = &tmp.dir.join("foo");
+ let dst = &tmp.dir.join("dir1").join("dir2").join("bar");
create_file(src, "old contents of foo");
let result = copy_file(src.to_str().unwrap(), dst.to_str().unwrap());
@@ -123,10 +144,10 @@ mod tests {
#[test]
fn test_copy_file_existing_file() {
- let tmp = TempDir::create("test_copy_file_existing_file");
+ let tmp = setup("test_copy_file_existing_file");
- let src = &tmp.0.join("foo");
- let dst = &tmp.0.join("bar");
+ let src = &tmp.dir.join("foo");
+ let dst = &tmp.dir.join("bar");
create_file(src, "old contents of foo");
create_file(dst, "old contents of bar");
@@ -141,10 +162,10 @@ mod tests {
#[test]
#[cfg(target_family = "unix")]
fn test_copy_file_existing_broken_symlink() {
- let tmp = TempDir::create("test_copy_file_existing_broken_symlink");
+ let tmp = setup("test_copy_file_existing_broken_symlink");
- let src = &tmp.0.join("foo");
- let dst = &tmp.0.join("bar");
+ let src = &tmp.dir.join("foo");
+ let dst = &tmp.dir.join("bar");
create_file(src, "old contents of foo");
symlink("missing", dst).unwrap();
@@ -159,14 +180,14 @@ mod tests {
#[test]
#[cfg(target_family = "unix")]
fn test_copy_file_tilde_expansion() {
- let tmp = TempDir::create("test_copy_file_tilde_expansion");
+ let tmp = setup("test_copy_file_tilde_expansion");
- let src = &tmp.0.join("foo");
- let dst = &tmp.0.join("dir1").join("dir2").join("bar");
+ let src = &tmp.dir.join("foo");
+ let dst = &tmp.dir.join("dir").join("bar");
+ let dst_tilde = "~/test_copy_file_tilde_expansion/dir/bar";
create_file(src, "old contents of foo");
- env::set_var("HOME", tmp.0.join("dir1").to_str().unwrap());
- let result = copy_file(src.to_str().unwrap(), "~/dir2/bar");
+ let result = copy_file(src.to_str().unwrap(), dst_tilde);
create_file(src, "new contents of foo");
let contents = fs::read_to_string(dst).unwrap();
@@ -177,10 +198,10 @@ mod tests {
#[test]
#[cfg(target_family = "unix")]
fn test_link_file_create_dirs() {
- let tmp = TempDir::create("test_link_file_create_dirs");
+ let tmp = setup("test_link_file_create_dirs");
- let src = &tmp.0.join("foo");
- let dst = &tmp.0.join("dir1").join("dir2").join("bar");
+ let src = &tmp.dir.join("foo");
+ let dst = &tmp.dir.join("dir1").join("dir2").join("bar");
create_file(src, "old contents of foo");
let result = link_file(src.to_str().unwrap(), dst.to_str().unwrap());
@@ -194,10 +215,10 @@ mod tests {
#[test]
#[cfg(target_family = "unix")]
fn test_link_file_existing_file() {
- let tmp = TempDir::create("test_link_file_existing_file");
+ let tmp = setup("test_link_file_existing_file");
- let src = &tmp.0.join("foo");
- let dst = &tmp.0.join("bar");
+ let src = &tmp.dir.join("foo");
+ let dst = &tmp.dir.join("bar");
create_file(src, "old contents of foo");
create_file(dst, "old contents of bar");
@@ -212,10 +233,10 @@ mod tests {
#[test]
#[cfg(target_family = "unix")]
fn test_link_file_existing_broken_symlink() {
- let tmp = TempDir::create("test_link_file_existing_broken_symlink");
+ let tmp = setup("test_link_file_existing_broken_symlink");
- let src = &tmp.0.join("foo");
- let dst = &tmp.0.join("bar");
+ let src = &tmp.dir.join("foo");
+ let dst = &tmp.dir.join("bar");
create_file(src, "old contents of foo");
symlink("missing", dst).unwrap();
@@ -230,27 +251,47 @@ mod tests {
#[test]
#[cfg(target_family = "unix")]
fn test_link_file_tilde_expansion() {
- let tmp = TempDir::create("test_link_file_tilde_expansion");
+ let tmp = setup("test_link_file_tilde_expansion");
+
+ let src = &tmp.dir.join("foo");
+ let dst = &tmp.dir.join("dir").join("bar");
+ let dst_tilde = "~/test_link_file_tilde_expansion/dir/bar";
+ create_file(src, "old contents of foo");
+
+ let result = link_file(src.to_str().unwrap(), dst_tilde);
+
+ create_file(src, "new contents of foo");
+ let contents = fs::read_to_string(dst).unwrap();
+ assert_eq!(result.is_ok(), true);
+ assert_eq!(contents, "new contents of foo");
+ }
+
+ #[test]
+ #[cfg(target_family = "unix")]
+ fn test_link_file_relative_source() {
+ let tmp = setup("test_link_file_relative_source");
- let src = &tmp.0.join("foo");
- let dst = &tmp.0.join("dir1").join("dir2").join("bar");
+ let src = &tmp.dir.join("foo");
+ let src_rel = "test_link_file_relative_source/foo";
+ let dst = &tmp.dir.join("dir1").join("dir2").join("bar");
create_file(src, "old contents of foo");
- env::set_var("HOME", tmp.0.join("dir1").to_str().unwrap());
- let result = link_file(src.to_str().unwrap(), "~/dir2/bar");
+ let result = link_file(src_rel, dst.to_str().unwrap());
create_file(src, "new contents of foo");
let contents = fs::read_to_string(dst).unwrap();
+ let link = fs::read_link(dst).unwrap();
assert_eq!(result.is_ok(), true);
assert_eq!(contents, "new contents of foo");
+ assert_eq!(&link, src); // src changed to absolute path
}
#[test]
#[cfg(target_family = "unix")]
fn test_run_script_successful() {
- let tmp = TempDir::create("test_run_script_successful");
+ let tmp = setup("test_run_script_successful");
- let src = &tmp.0.join("foo");
+ let src = &tmp.dir.join("foo");
create_file(src, "exit 0");
let result = run_script(src.to_str().unwrap(), "bash", "");
@@ -261,9 +302,9 @@ mod tests {
#[test]
#[cfg(target_family = "unix")]
fn test_run_script_failure() {
- let tmp = TempDir::create("test_run_script_failure");
+ let tmp = setup("test_run_script_failure");
- let src = &tmp.0.join("foo");
+ let src = &tmp.dir.join("foo");
create_file(src, "exit 2");
let result = run_script(src.to_str().unwrap(), "bash", "");
@@ -275,10 +316,10 @@ mod tests {
#[test]
#[cfg(target_family = "unix")]
fn test_run_script_postfix() {
- let tmp = TempDir::create("test_run_script_postfix");
+ let tmp = setup("test_run_script_postfix");
- let src = &tmp.0.join("foo");
- let dst = &tmp.0.join("bar");
+ let src = &tmp.dir.join("foo");
+ let dst = &tmp.dir.join("bar");
create_file(src, &format!("echo $@ > {}", dst.to_str().unwrap()));
let result = run_script(src.to_str().unwrap(), "bash", "arg1 arg2");
diff --git a/tests/basic.rs b/tests/basic.rs
@@ -0,0 +1,25 @@
+mod common;
+
+use common::{get_output, setup};
+
+#[test]
+fn test_help() {
+ let (_dir, mut cmd) = setup("test_help");
+ cmd.arg("--help");
+ let expected = "\
+A minimal, flexible, dotfile installer
+
+Usage: coliru [OPTIONS] <MANIFEST>
+
+Arguments:
+ <MANIFEST> The path to the coliru YAML manifest file
+
+Options:
+ -t, --tag-rules [<TAG_RULES>...] The set of tag rules to enforce
+ -c, --copy Interpret link commands as copy commands
+ -n, --dry-run Do a trial run without any permanent changes
+ -h, --help Print help
+ -V, --version Print version
+";
+ assert_eq!(&get_output(&mut cmd), expected);
+}
diff --git a/tests/common/mod.rs b/tests/common/mod.rs
@@ -0,0 +1,49 @@
+use std::env;
+use std::fs;
+use std::path::PathBuf;
+use std::process::Command;
+
+/// Stores the path to a temporary directory that is automatically deleted
+/// when the value is dropped.
+///
+/// Adapted from ripgrep's tests (crates/ignore/src/lib.rs)
+pub struct TempDir {
+ dir: PathBuf
+}
+impl Drop for TempDir {
+ fn drop(&mut self) {
+ fs::remove_dir_all(&self.dir).unwrap();
+ }
+}
+impl TempDir {
+ fn new(name: &str) -> TempDir {
+ let dir = env::temp_dir().join("coliru-tests").join(name);
+ assert_eq!(dir.exists(), false);
+ fs::create_dir_all(&dir).unwrap();
+ TempDir { dir }
+ }
+}
+
+/// Creates a temporary directory with a certain name and create a new coliru
+/// Command with $HOME and the CWD set the the temporary directory.
+///
+/// Adapted from ripgrep's tests (tests/utils.rs)
+pub fn setup(name: &str) -> (TempDir, Command) {
+ let dir = TempDir::new(name);
+
+ let exe = env::current_exe().unwrap().parent().unwrap().to_path_buf()
+ .join(format!("../coliru{}", env::consts::EXE_SUFFIX));
+ let mut cmd = Command::new(exe);
+ cmd.current_dir(&dir.dir);
+
+ if cfg!(target_family = "unix") {
+ cmd.env("HOME", &dir.dir);
+ }
+
+ (dir, cmd)
+}
+
+/// Returns the stdout of a command as a String.
+pub fn get_output(cmd: &mut Command) -> String {
+ String::from_utf8_lossy(&cmd.output().unwrap().stdout).into_owned()
+}