coliru

A minimal, flexible, dotfile installer
git clone https://git.ashermorgan.net/coliru/
Log | Files | Refs | README

commit 314cf9940496f884d17acb59b14578268c111fe2
parent 8b0c22d1aa1118c407a948ea848197f346c3865a
Author: Asher Morgan <59518073+ashermorgan@users.noreply.github.com>
Date:   Thu,  4 Jul 2024 13:06:00 -0700

Refactor e2e tests

Use copy_manifest function to automatically edit dotfiles as needed by different
tests, particularly SSH e2e tests.

Diffstat:
MREADME.md | 4++--
Rexamples/bashrc -> examples/basic/bashrc | 0
Rexamples/gitconfig -> examples/basic/gitconfig | 0
Rexamples/manifest.yml -> examples/basic/manifest.yml | 0
Aexamples/basic/script.bat | 2++
Aexamples/basic/script.sh | 3+++
Rexamples/vimrc -> examples/basic/vimrc | 0
Dexamples/script.bat | 3---
Dexamples/script.sh | 4----
Aexamples/test/bashrc | 1+
Aexamples/test/gitconfig | 1+
Rexamples/manifest-invalid.yml -> examples/test/invalid.yml | 0
Aexamples/test/manifest.yml | 27+++++++++++++++++++++++++++
Aexamples/test/scripts/script.bat | 4++++
Aexamples/test/scripts/script.sh | 4++++
Aexamples/test/vimrc | 1+
Msrc/manifest.rs | 27+++++++++++++++------------
Dsrc/utils.rs | 367-------------------------------------------------------------------------------
Mtests/basic.rs | 61+++++++++++++++++++++++++++++++++++++++++++++----------------
Mtests/common/mod.rs | 85++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
Mtests/local.rs | 288++++++++++++++++++++++++++++++++++++++-----------------------------------------
Mtests/ssh.rs | 145++++++++++++++++++++++++++++++++++++++-----------------------------------------
22 files changed, 366 insertions(+), 661 deletions(-)

diff --git a/README.md b/README.md @@ -34,8 +34,8 @@ Finally, the run command executes a script (`src`) from the command line, using `$COLIRU_RULES` will be expanded into a space-delimited list of the current tag rules. -Example YAML manifest (see [`examples/manifest.yml`](examples/manifest.yml) for -more details): +Example YAML manifest (see +[`examples/basic/manifest.yml`](examples/basic/manifest.yml) for more details): ```yml steps: diff --git a/examples/bashrc b/examples/basic/bashrc diff --git a/examples/gitconfig b/examples/basic/gitconfig diff --git a/examples/manifest.yml b/examples/basic/manifest.yml diff --git a/examples/basic/script.bat b/examples/basic/script.bat @@ -0,0 +1,2 @@ +@ECHO OFF +ECHO script.bat called with %* diff --git a/examples/basic/script.sh b/examples/basic/script.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env sh + +echo "script.sh called with $@" diff --git a/examples/vimrc b/examples/basic/vimrc diff --git a/examples/script.bat b/examples/script.bat @@ -1,3 +0,0 @@ -@ECHO OFF -ECHO script.bat called with %* -ECHO script.bat called with %* > log.txt diff --git a/examples/script.sh b/examples/script.sh @@ -1,4 +0,0 @@ -#!/usr/bin/env sh - -echo "script.sh called with $@" -echo "script.sh called with $@" > log.txt diff --git a/examples/test/bashrc b/examples/test/bashrc @@ -0,0 +1 @@ +bash #1 diff --git a/examples/test/gitconfig b/examples/test/gitconfig @@ -0,0 +1 @@ +git #1 diff --git a/examples/manifest-invalid.yml b/examples/test/invalid.yml diff --git a/examples/test/manifest.yml b/examples/test/manifest.yml @@ -0,0 +1,27 @@ +# Note: copy_manifest() updates replaces ~/ and scripts/ with unique paths for +# ssh e2e tests and Windows tests to ensure test dotfiles are isolated + +steps: + - copy: + - src: gitconfig + dst: ~/.gitconfig + tags: [ windows, linux, macos ] + + - link: + - src: bashrc + dst: ~/.bashrc + - src: vimrc + dst: ~/.vimrc + run: + - src: scripts/script.sh + prefix: sh + postfix: arg1 $COLIRU_RULES + tags: [ linux, macos ] + + - link: + - src: vimrc + dst: ~/_vimrc + run: + - src: scripts/script.bat + postfix: arg1 $COLIRU_RULES + tags: [ windows ] diff --git a/examples/test/scripts/script.bat b/examples/test/scripts/script.bat @@ -0,0 +1,4 @@ +@ECHO OFF +ECHO script.bat called with %* +REM Windows doesn't support ~/, but it will be edited by copy_manifest() +ECHO script.bat called with %* > ~/log.txt diff --git a/examples/test/scripts/script.sh b/examples/test/scripts/script.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env sh + +echo "script.sh called with $@" +echo "script.sh called with $@" > ~/log.txt diff --git a/examples/test/vimrc b/examples/test/vimrc @@ -0,0 +1 @@ +vim #1 diff --git a/src/manifest.rs b/src/manifest.rs @@ -69,36 +69,39 @@ mod tests { #[test] #[cfg(target_family = "unix")] fn parse_manifest_file_missing() { + let manifest_path = Path::new("examples/test/missing.yml"); let expected = "No such file or directory (os error 2)"; - let actual = parse_manifest_file(Path::new("examples/missing.yml")); + let actual = parse_manifest_file(manifest_path); assert_eq!(actual, Err(String::from(expected))); } #[test] #[cfg(target_family = "windows")] fn parse_manifest_file_missing() { + let manifest_path = Path::new("examples/test/missing.yml"); let exp = "The system cannot find the file specified. (os error 2)"; - let actual = parse_manifest_file(Path::new("examples/missing.yml")); + let actual = parse_manifest_file(manifest_path); assert_eq!(actual, Err(String::from(exp))); } #[test] fn parse_manifest_file_invalid() { - let path = Path::new("examples/manifest-invalid.yml"); + let manifest_path = Path::new("examples/test/invalid.yml"); let exp = "steps[0].copy[0]: missing field `src` at line 5 column 7"; - let actual = parse_manifest_file(path); + let actual = parse_manifest_file(manifest_path); assert_eq!(actual, Err(String::from(exp))); } #[test] fn parse_manifest_file_valid() { + let manifest_path = Path::new("examples/test/manifest.yml"); let expected = Manifest { steps: vec![ Step { copy: vec![ CopyLinkOptions { src: String::from("gitconfig"), - dst: String::from("~/.gitconfig.coliru"), + dst: String::from("~/.gitconfig"), }, ], link: vec![], @@ -114,16 +117,16 @@ mod tests { link: vec![ CopyLinkOptions { src: String::from("bashrc"), - dst: String::from("~/.bashrc.coliru"), + dst: String::from("~/.bashrc"), }, CopyLinkOptions { src: String::from("vimrc"), - dst: String::from("~/.vimrc.coliru"), + dst: String::from("~/.vimrc"), }, ], run: vec![ RunOptions { - src: String::from("script.sh"), + src: String::from("scripts/script.sh"), prefix: String::from("sh"), postfix: String::from("arg1 $COLIRU_RULES"), }, @@ -135,12 +138,12 @@ mod tests { link: vec![ CopyLinkOptions { src: String::from("vimrc"), - dst: String::from("~/_vimrc.coliru"), + dst: String::from("~/_vimrc"), }, ], run: vec![ RunOptions { - src: String::from("script.bat"), + src: String::from("scripts/script.bat"), prefix: String::from(""), postfix: String::from("arg1 $COLIRU_RULES"), }, @@ -148,9 +151,9 @@ mod tests { tags: vec![String::from("windows")], }, ], - base_dir: PathBuf::from("examples"), + base_dir: PathBuf::from("examples/test"), }; - let actual = parse_manifest_file(Path::new("examples/manifest.yml")); + let actual = parse_manifest_file(manifest_path); assert_eq!(actual, Ok(expected)); } } diff --git a/src/utils.rs b/src/utils.rs @@ -1,367 +0,0 @@ -use shellexpand::tilde; -use std::io; -use std::fs; -#[cfg(target_family = "unix")] -use std::os::unix::fs::symlink; -use std::path::{PathBuf, absolute}; -use std::process::Command; - -/// Copies the contents of a local file to another local file. -/// -/// Tildes are expanded if present and the destination file is overwritten if -/// necessary. -pub fn copy_file(src: &str, dst: &str) -> io::Result<()> { - if absolute(src)? == absolute(dst)? { return Ok(()); } - let _dst = prepare_path(dst)?; - fs::copy(src, _dst)?; - Ok(()) -} - -/// Creates a symbolic link to a local file. -/// -/// Tildes are expanded if present and the destination file is overwritten if -/// necessary. On non-Unix platforms, a hard link will be created instead. -#[cfg(target_family = "unix")] -pub fn link_file(src: &str, dst: &str) -> io::Result<()> { - if absolute(src)? == absolute(dst)? { return Ok(()); } - let _dst = prepare_path(dst)?; - symlink(fs::canonicalize(src)?, _dst)?; - Ok(()) -} -#[cfg(not(target_family = "unix"))] -pub fn link_file(src: &str, dst: &str) -> io::Result<()> { - if absolute(src)? == absolute(dst)? { return Ok(()); } - let _dst = prepare_path(dst)?; - fs::hard_link(src, _dst)?; - Ok(()) -} - -/// 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(); - if let Some(_path) = _dst.parent() { - fs::create_dir_all(_path)?; - } - if fs::symlink_metadata(&_dst).is_ok() { - // Check for existing files, including broken symlinks - fs::remove_file(&_dst)?; - } - Ok(_dst) -} - -/// 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> -{ - // Use absolute() to avoid incompatible "UNC" paths on Windows: - // https://github.com/rust-lang/rust/issues/42869 - let _path = absolute(path).map_err(|why| why.to_string())?; - let status; - if cfg!(target_family = "unix") { - status = Command::new("sh") - .arg("-c") - .arg(format!("{} {} {}", prefix, _path.display(), postfix)) - .status() - .map_err(|why| why.to_string())?; - } else { - status = Command::new("powershell") - .args(["-ExecutionPolicy", "Bypass", "-Command"]) - .arg(format!("{} {} {}", prefix, _path.display(), postfix)) - .status() - .map_err(|why| why.to_string())?; - } - if status.success() { - Ok(()) - } else { - Err(format!("Process exited with {status}")) - } -} - -#[cfg(test)] -#[path = "../tests/common/mod.rs"] -mod common; - -#[cfg(test)] -mod tests { - use super::*; - use common::{setup_integration, write_file}; - - #[test] - fn test_copy_file_create_dirs() { - let tmp = setup_integration("test_copy_file_create_dirs"); - - let src = &tmp.dir.join("foo"); - let dst = &tmp.dir.join("dir1").join("dir2").join("bar"); - write_file(src, "old contents of foo"); - - let result = copy_file(src.to_str().unwrap(), dst.to_str().unwrap()); - - write_file(src, "new contents of foo"); - let contents = fs::read_to_string(dst).unwrap(); - assert_eq!(result.is_ok(), true); - assert_eq!(contents, "old contents of foo"); - } - - #[test] - fn test_copy_file_same_file() { - let tmp = setup_integration("test_copy_file_same_file"); - - let src = &tmp.dir.join("foo"); - let dst = &tmp.dir.join("foo"); - write_file(src, "contents of foo"); - - let result = copy_file(src.to_str().unwrap(), dst.to_str().unwrap()); - - let contents = fs::read_to_string(dst).unwrap(); - assert_eq!(result.is_ok(), true); - assert_eq!(contents, "contents of foo"); - } - - #[test] - fn test_copy_file_existing_file() { - let tmp = setup_integration("test_copy_file_existing_file"); - - let src = &tmp.dir.join("foo"); - let dst = &tmp.dir.join("bar"); - write_file(src, "old contents of foo"); - write_file(dst, "old contents of bar"); - - let result = copy_file(src.to_str().unwrap(), dst.to_str().unwrap()); - - write_file(src, "new contents of foo"); - let contents = fs::read_to_string(dst).unwrap(); - assert_eq!(result.is_ok(), true); - assert_eq!(contents, "old contents of foo"); - } - - #[test] - #[cfg(target_family = "unix")] - fn test_copy_file_existing_broken_symlink() { - let tmp = setup_integration("test_copy_file_existing_broken_symlink"); - - let src = &tmp.dir.join("foo"); - let dst = &tmp.dir.join("bar"); - write_file(src, "old contents of foo"); - symlink("missing", dst).unwrap(); - - let result = copy_file(src.to_str().unwrap(), dst.to_str().unwrap()); - - write_file(src, "new contents of foo"); - let contents = fs::read_to_string(dst).unwrap(); - assert_eq!(result.is_ok(), true); - assert_eq!(contents, "old contents of foo"); - } - - #[test] - #[cfg(target_family = "unix")] - fn test_copy_file_tilde_expansion() { - let tmp = setup_integration("test_copy_file_tilde_expansion"); - - let src = &tmp.dir.join("foo"); - let dst = &tmp.dir.join("dir").join("bar"); - let dst_tilde = "~/test_copy_file_tilde_expansion/dir/bar"; - write_file(src, "old contents of foo"); - - let result = copy_file(src.to_str().unwrap(), dst_tilde); - - write_file(src, "new contents of foo"); - let contents = fs::read_to_string(dst).unwrap(); - assert_eq!(result.is_ok(), true); - assert_eq!(contents, "old contents of foo"); - } - - #[test] - fn test_link_file_create_dirs() { - let tmp = setup_integration("test_link_file_create_dirs"); - - let src = &tmp.dir.join("foo"); - let dst = &tmp.dir.join("dir1").join("dir2").join("bar"); - write_file(src, "old contents of foo"); - - let result = link_file(src.to_str().unwrap(), dst.to_str().unwrap()); - - write_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] - fn test_link_file_same_file() { - let tmp = setup_integration("test_link_file_same_file"); - - let src = &tmp.dir.join("foo"); - let dst = &tmp.dir.join("foo"); - write_file(src, "contents of foo"); - - let result = link_file(src.to_str().unwrap(), dst.to_str().unwrap()); - - let contents = fs::read_to_string(dst).unwrap(); - assert_eq!(result.is_ok(), true); - assert_eq!(contents, "contents of foo"); - } - - #[test] - fn test_link_file_existing_file() { - let tmp = setup_integration("test_link_file_existing_file"); - - let src = &tmp.dir.join("foo"); - let dst = &tmp.dir.join("bar"); - write_file(src, "old contents of foo"); - write_file(dst, "old contents of bar"); - - let result = link_file(src.to_str().unwrap(), dst.to_str().unwrap()); - - write_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_existing_broken_symlink() { - let tmp = setup_integration("test_link_file_existing_broken_symlink"); - - let src = &tmp.dir.join("foo"); - let dst = &tmp.dir.join("bar"); - write_file(src, "old contents of foo"); - symlink("missing", dst).unwrap(); - - let result = link_file(src.to_str().unwrap(), dst.to_str().unwrap()); - - write_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_tilde_expansion() { - let tmp = setup_integration("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"; - write_file(src, "old contents of foo"); - - let result = link_file(src.to_str().unwrap(), dst_tilde); - - write_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 dir = PathBuf::from("tests/.temp/ssh/test_link_file_relative_source"); - fs::create_dir_all(&dir).unwrap(); - - let src = absolute(&dir.join("foo")).unwrap(); - let src_rel = "tests/.temp/ssh/test_link_file_relative_source/foo"; - let dst = &dir.join("dir1").join("dir2").join("bar"); - write_file(&src, "old contents of foo"); - - let result = link_file(src_rel, dst.to_str().unwrap()); - - write_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 - - fs::remove_dir_all(&dir).unwrap(); - } - - #[test] - #[cfg(target_family = "unix")] - fn test_run_script_successful() { - let tmp = setup_integration("test_run_script_successful"); - - let src = &tmp.dir.join("foo"); - write_file(src, "exit 0"); - - let result = run_script(src.to_str().unwrap(), "sh", ""); - - assert_eq!(result.is_ok(), true); - } - - #[test] - #[cfg(target_family = "windows")] - fn test_run_script_successful() { - let tmp = setup_integration("test_run_script_successful"); - - let src = &tmp.dir.join("foo.bat"); - write_file(src, "exit 0"); - - let result = run_script(src.to_str().unwrap(), "", ""); - - assert_eq!(result.is_ok(), true); - } - - #[test] - #[cfg(target_family = "unix")] - fn test_run_script_failure() { - let tmp = setup_integration("test_run_script_failure"); - - let src = &tmp.dir.join("foo"); - write_file(src, "exit 2"); - - let result = run_script(src.to_str().unwrap(), "sh", ""); - - assert_eq!(result.is_ok(), false); - assert_eq!(result.unwrap_err(), "Process exited with exit status: 2"); - } - - #[test] - #[cfg(target_family = "windows")] - fn test_run_script_failure() { - let tmp = setup_integration("test_run_script_failure"); - - let src = &tmp.dir.join("foo.bat"); - write_file(src, "exit 1"); - - let result = run_script(src.to_str().unwrap(), "", ""); - - assert_eq!(result.is_ok(), false); - assert_eq!(result.unwrap_err(), "Process exited with exit code: 1"); - } - - #[test] - #[cfg(target_family = "unix")] - fn test_run_script_postfix() { - let tmp = setup_integration("test_run_script_postfix"); - - let src = &tmp.dir.join("foo"); - let dst = &tmp.dir.join("bar"); - write_file(src, &format!("echo $@ > {}", dst.to_str().unwrap())); - - let result = run_script(src.to_str().unwrap(), "sh", "arg1 arg2"); - - let contents = fs::read_to_string(dst).unwrap(); - assert_eq!(result.is_ok(), true); - assert_eq!(contents, "arg1 arg2\n"); - } - - #[test] - #[cfg(target_family = "windows")] - fn test_run_script_postfix() { - let tmp = setup_integration("test_run_script_postfix"); - - let src = &tmp.dir.join("foo.bat"); - let dst = &tmp.dir.join("bar"); - write_file(src, &format!("echo %* > {}", dst.to_str().unwrap())); - - let result = run_script(src.to_str().unwrap(), "", "arg1 arg2"); - - let contents = fs::read_to_string(dst).unwrap(); - assert_eq!(result.is_ok(), true); - assert_eq!(contents, "arg1 arg2 \r\n"); - } -} diff --git a/tests/basic.rs b/tests/basic.rs @@ -8,7 +8,7 @@ use std::env::consts::EXE_SUFFIX; #[test] fn test_basic_help() { - let (_dirs, mut cmd) = setup_e2e("test_basic_help"); + let (_dirs, mut cmd) = setup_e2e_local("test_basic_help"); cmd.arg("--help"); let expected = format!("\ A minimal, flexible, dotfile installer @@ -32,59 +32,88 @@ Options: #[test] fn test_basic_empty_manifest() { - let (dirs, mut cmd) = setup_e2e("test_basic_empty_manifest"); + let (dirs, mut cmd) = setup_e2e_local("test_basic_empty_manifest"); cmd.args(["manifest.yml"]); write_file(&dirs.local.join("manifest.yml"), ""); let expected = "Error: missing field `steps`\n"; - assert_eq!(&stdout_to_string(&mut cmd), ""); assert_eq!(&stderr_to_string(&mut cmd), expected); + assert_eq!(&stdout_to_string(&mut cmd), ""); } #[test] #[cfg(target_family = "unix")] fn test_basic_missing_manifest() { - let (_dirs, mut cmd) = setup_e2e("test_basic_missing_manifest"); + let (_dirs, mut cmd) = setup_e2e_local("test_basic_missing_manifest"); cmd.args(["missing.yml"]); let expected = "Error: No such file or directory (os error 2)\n"; - assert_eq!(&stdout_to_string(&mut cmd), ""); assert_eq!(&stderr_to_string(&mut cmd), expected); + assert_eq!(&stdout_to_string(&mut cmd), ""); } #[test] #[cfg(target_family = "windows")] fn test_basic_missing_manifest() { - let (_dirs, mut cmd) = setup_e2e("test_basic_missing_manifest"); + let (_dirs, mut cmd) = setup_e2e_local("test_basic_missing_manifest"); cmd.args(["missing.yml"]); let expected = "Error: The system cannot find the file specified. \ (os error 2)\n"; - assert_eq!(&stdout_to_string(&mut cmd), ""); assert_eq!(&stderr_to_string(&mut cmd), expected); + assert_eq!(&stdout_to_string(&mut cmd), ""); } #[test] +#[cfg(target_family = "unix")] fn test_basic_absolute_manifest() { - let (dirs, mut cmd) = setup_e2e("test_basic_absolute_manifest"); + let (dirs, mut cmd) = setup_e2e_local("test_basic_absolute_manifest"); let manifest_path = dirs.local.join("manifest.yml"); cmd.args([&manifest_path.to_str().unwrap(), "--dry-run", "-t", "linux"]); - copy_manifest(&dirs.local, "~/"); let expected = "\ -[1/3] Copy gitconfig to ~/.gitconfig.coliru (DRY RUN) -[2/3] Link bashrc to ~/.bashrc.coliru (DRY RUN) -[2/3] Link vimrc to ~/.vimrc.coliru (DRY RUN) +[1/3] Copy gitconfig to ~/.gitconfig (DRY RUN) +[2/3] Link bashrc to ~/.bashrc (DRY RUN) +[2/3] Link vimrc to ~/.vimrc (DRY RUN) [2/3] Run sh script.sh arg1 linux (DRY RUN) "; + assert_eq!(&stderr_to_string(&mut cmd), ""); assert_eq!(&stdout_to_string(&mut cmd), expected); + + // Assert files are correctly copied/linked/run + let bash_exists = dirs.home.join(".bashrc").exists(); + let git_exists = dirs.home.join(".gitconfig").exists(); + let vim1_exists = dirs.home.join(".vimrc").exists(); + let vim2_exists = dirs.home.join("_vimrc").exists(); + let log_exists = dirs.home.join("log.txt").exists(); + assert_eq!(bash_exists, false); + assert_eq!(git_exists, false); + assert_eq!(vim1_exists, false); + assert_eq!(vim2_exists, false); + assert_eq!(log_exists, false); +} + +#[test] +#[cfg(target_family = "windows")] +fn test_basic_absolute_manifest() { + let (dirs, mut cmd) = setup_e2e_local("test_basic_absolute_manifest"); + let manifest_path = dirs.local.join("manifest.yml"); + cmd.args([&manifest_path.to_str().unwrap(), "--dry-run", "-t", "linux"]); + + let expected = "\ +[1/3] Copy gitconfig to .gitconfig (DRY RUN) +[2/3] Link bashrc to .bashrc (DRY RUN) +[2/3] Link vimrc to .vimrc (DRY RUN) +[2/3] Run sh script.sh arg1 linux (DRY RUN) +"; assert_eq!(&stderr_to_string(&mut cmd), ""); + assert_eq!(&stdout_to_string(&mut cmd), expected); // Assert files are correctly copied/linked/run - let bash_exists = dirs.local.join(".bashrc.coliru").exists(); - let git_exists = dirs.local.join(".gitconfig.coliru").exists(); - let vim1_exists = dirs.local.join(".vimrc.coliru").exists(); - let vim2_exists = dirs.local.join("_vimrc.coliru").exists(); + let bash_exists = dirs.local.join(".bashrc").exists(); + let git_exists = dirs.local.join(".gitconfig").exists(); + let vim1_exists = dirs.local.join(".vimrc").exists(); + let vim2_exists = dirs.local.join("_vimrc").exists(); let log_exists = dirs.local.join("log.txt").exists(); assert_eq!(bash_exists, false); assert_eq!(git_exists, false); diff --git a/tests/common/mod.rs b/tests/common/mod.rs @@ -11,7 +11,7 @@ pub const SSH_HOST: &str = "test@localhost"; // TODO: add explicit port /// A set of temporary directories that are automatically deleted when the value /// is dropped -pub struct TempDir { +pub struct TempDirs { /// A temporary directory that is located at or in $HOME on Unix pub home: PathBuf, @@ -21,15 +21,15 @@ pub struct TempDir { /// A temporary directory that is mounted to the SSH server under $HOME pub ssh: PathBuf, } -impl Drop for TempDir { +impl Drop for TempDirs { fn drop(&mut self) { fs::remove_dir_all(&self.ssh).unwrap(); fs::remove_dir_all(&self.local).unwrap(); fs::remove_dir_all(&self.home).unwrap(); } } -impl TempDir { - fn new(name: &str) -> TempDir { +impl TempDirs { + fn new(name: &str) -> TempDirs { // The CWD of the current process is always the repository root let dir = env::current_dir().unwrap().join("tests").join(".temp"); @@ -45,7 +45,7 @@ impl TempDir { fs::create_dir_all(&local).unwrap(); fs::create_dir_all(&ssh).unwrap(); - TempDir { home, local, ssh } + TempDirs { home, local, ssh } } } @@ -54,8 +54,8 @@ impl TempDir { /// On Unix, $HOME is set to the parent directory of the home temporary /// directory, which is the same for all integration tests. This prevents issues /// when tests are run in multiple threads. -pub fn setup_integration(name: &str) -> TempDir { - let dirs = TempDir::new(name); +pub fn setup_integration(name: &str) -> TempDirs { + let dirs = TempDirs::new(name); if cfg!(target_family = "unix") { env::set_var("HOME", dirs.home.parent().unwrap()); } @@ -66,8 +66,8 @@ pub fn setup_integration(name: &str) -> TempDir { /// /// The Command's CWD is set to the local temporary directory, and on Unix, the /// Command's $HOME variable is set to the home temporary directory. -pub fn setup_e2e(name: &str) -> (TempDir, Command) { - let dirs = TempDir::new(name); +fn setup_e2e(name: &str) -> (TempDirs, Command) { + let dirs = TempDirs::new(name); let exe = env::current_exe().unwrap().parent().unwrap().to_path_buf() .join(format!("../coliru{}", env::consts::EXE_SUFFIX)); @@ -80,37 +80,60 @@ pub fn setup_e2e(name: &str) -> (TempDir, Command) { (dirs, cmd) } -/// Initializes temporary directories and a coliru Command with the --host -/// argument set for e2e tests -pub fn setup_e2e_ssh(name: &str) -> (TempDir, Command) { +/// Initializes temporary directories and a coliru Command for local e2e tests +/// +/// A test dotfile repo is copied to the local folder, to be installed to $HOME +/// on Unix and CWD on Windows. +pub fn setup_e2e_local(name: &str) -> (TempDirs, Command) { + let (dirs, cmd) = setup_e2e(name); + + // It's difficult to mock $HOME on Windows, so install dotfiles in CWD + let home_dir = if cfg!(target_family = "unix") { "~/" } else { "" }; + copy_manifest(&dirs.local, home_dir, ""); + + (dirs, cmd) +} + +/// Initializes temporary directories and a coliru Command for ssh e2e tests +/// +/// A test dotfile repo is copied to the local folder, to be installed to +/// ~/test_name/ with scripts copied to ~/.coliru/test_name/, and the --host +/// argument is set to the test SSH server. +pub fn setup_e2e_ssh(name: &str) -> (TempDirs, Command) { let (dirs, mut cmd) = setup_e2e(name); cmd.args(["--host", SSH_HOST]); + + // Replace ~/ and scripts/ with custom directory to isolate SSH tests + copy_manifest(&dirs.local, &format!("~/{name}/"), &format!("{name}/")); + (dirs, cmd) } /// Create a basic manifest file and its associated dotfiles in a directory /// -/// All occurances of the string "~/" in examples/manifest.yml will be replaced -/// with the value of home_dir. -pub fn copy_manifest(dir: &Path, home_dir: &str) { - // Copy files from examples +/// All occurrences of the string "~/" and "scripts/" (e.g. in manifest.yml and +/// scripts/*) will be replaced with the value of home_dir and script_dir +/// respectively to ensures that dotfiles are isolated across tests when +/// necessary. +pub fn copy_manifest(dir: &Path, home_dir: &str, script_dir: &str) { let examples = env::current_exe().unwrap().parent().unwrap().to_path_buf() - .join("../../../examples"); - let copy_file = |name: &str| { - fs::copy(examples.join(name), &dir.join(name)).unwrap(); + .join("../../../examples/test"); + + let copy_file = |path: &str| { + let mut contents = read_file(&examples.join(path)); + contents = contents.replace("~/", home_dir); + contents = contents.replace("scripts/", script_dir); + let dst = path.replace("scripts/", script_dir); + write_file(&dir.join(dst), &contents); }; - copy_file("script.bat"); - copy_file("script.sh"); - - // Create manifest file with "~/" replaced for home_dir - let mut manifest = read_file(&examples.join("manifest.yml")); - manifest = manifest.replace("~/", home_dir); - write_file(&dir.join("manifest.yml"), &manifest); - - // Create simplified config files - write_file(&dir.join("bashrc"), "bash #1"); - write_file(&dir.join("gitconfig"), "git #1"); - write_file(&dir.join("vimrc"), "vim #1"); + + copy_file("manifest.yml"); + fs::create_dir_all(&dir.join(script_dir)).unwrap(); + copy_file("scripts/script.bat"); + copy_file("scripts/script.sh"); + copy_file("bashrc"); + copy_file("gitconfig"); + copy_file("vimrc"); } diff --git a/tests/local.rs b/tests/local.rs @@ -9,14 +9,13 @@ use std::fs::remove_file; #[test] #[cfg(target_family = "unix")] fn test_local_standard() { - let (dirs, mut cmd) = setup_e2e("test_local_standard"); + let (dirs, mut cmd) = setup_e2e_local("test_local_standard"); cmd.args(["manifest.yml", "-t", "linux"]); - copy_manifest(&dirs.local, "~/"); let expected = "\ -[1/3] Copy gitconfig to ~/.gitconfig.coliru -[2/3] Link bashrc to ~/.bashrc.coliru -[2/3] Link vimrc to ~/.vimrc.coliru +[1/3] Copy gitconfig to ~/.gitconfig +[2/3] Link bashrc to ~/.bashrc +[2/3] Link vimrc to ~/.vimrc [2/3] Run sh script.sh arg1 linux script.sh called with arg1 linux "; @@ -24,17 +23,17 @@ script.sh called with arg1 linux assert_eq!(&stdout_to_string(&mut cmd), expected); // Assert files are correctly copied/linked/run - write_file(&dirs.local.join("bashrc"), "bash #2"); - write_file(&dirs.local.join("gitconfig"), "git #2"); - write_file(&dirs.local.join("vimrc"), "vim #2"); - let bash_contents = read_file(&dirs.home.join(".bashrc.coliru")); - let git_contents = read_file(&dirs.home.join(".gitconfig.coliru")); - let vim1_contents = read_file(&dirs.home.join(".vimrc.coliru")); - let vim2_exists = dirs.home.join("_vimrc.coliru").exists(); - let log_contents = read_file(&dirs.local.join("log.txt")); - assert_eq!(bash_contents, "bash #2"); - assert_eq!(git_contents, "git #1"); - assert_eq!(vim1_contents, "vim #2"); + write_file(&dirs.local.join("bashrc"), "bash #2\n"); + write_file(&dirs.local.join("gitconfig"), "git #2\n"); + write_file(&dirs.local.join("vimrc"), "vim #2\n"); + let bash_contents = read_file(&dirs.home.join(".bashrc")); + let git_contents = read_file(&dirs.home.join(".gitconfig")); + let vim1_contents = read_file(&dirs.home.join(".vimrc")); + let vim2_exists = dirs.home.join("_vimrc").exists(); + let log_contents = read_file(&dirs.home.join("log.txt")); + assert_eq!(bash_contents, "bash #2\n"); + assert_eq!(git_contents, "git #1\n"); + assert_eq!(vim1_contents, "vim #2\n"); assert_eq!(vim2_exists, false); assert_eq!(log_contents, "script.sh called with arg1 linux\n"); } @@ -42,13 +41,12 @@ script.sh called with arg1 linux #[test] #[cfg(target_family = "windows")] fn test_local_standard() { - let (dirs, mut cmd) = setup_e2e("test_local_standard"); + let (dirs, mut cmd) = setup_e2e_local("test_local_standard"); cmd.args(["manifest.yml", "-t", "windows"]); - copy_manifest(&dirs.local, ""); let expected = "\ -[1/3] Copy gitconfig to .gitconfig.coliru -[3/3] Link vimrc to _vimrc.coliru +[1/3] Copy gitconfig to .gitconfig +[3/3] Link vimrc to _vimrc [3/3] Run script.bat arg1 windows script.bat called with arg1 windows\r "; @@ -56,30 +54,29 @@ script.bat called with arg1 windows\r assert_eq!(&stdout_to_string(&mut cmd), expected); // Assert files are correctly copied/linked/run - write_file(&dirs.local.join("gitconfig"), "git #2"); - write_file(&dirs.local.join("vimrc"), "vim #2"); - let bash_exists = dirs.local.join(".bashrc.coliru").exists(); - let git_contents = read_file(&dirs.local.join(".gitconfig.coliru")); - let vim1_exists = dirs.local.join(".vimrc.coliru").exists(); - let vim2_contents = read_file(&dirs.local.join("_vimrc.coliru")); + write_file(&dirs.local.join("gitconfig"), "git #2\r\n"); + write_file(&dirs.local.join("vimrc"), "vim #2\r\n"); + let bash_exists = dirs.local.join(".bashrc").exists(); + let git_contents = read_file(&dirs.local.join(".gitconfig")); + let vim1_exists = dirs.local.join(".vimrc").exists(); + let vim2_contents = read_file(&dirs.local.join("_vimrc")); let log_contents = read_file(&dirs.local.join("log.txt")); assert_eq!(bash_exists, false); - assert_eq!(git_contents, "git #1"); + assert_eq!(git_contents, "git #1\r\n"); assert_eq!(vim1_exists, false); - assert_eq!(vim2_contents, "vim #2"); + assert_eq!(vim2_contents, "vim #2\r\n"); assert_eq!(log_contents, "script.bat called with arg1 windows \r\n"); } #[test] #[cfg(target_family = "unix")] fn test_local_run_alternate_tag_rules_1() { - let (dirs, mut cmd) = setup_e2e("test_local_run_alternate_tag_rules_1"); + let (dirs, mut cmd) = setup_e2e_local("test_local_run_alternate_tag_rules_1"); cmd.args(["manifest.yml", "-t", "linux", "^windows"]); - copy_manifest(&dirs.local, "~/"); let expected = "\ -[2/3] Link bashrc to ~/.bashrc.coliru -[2/3] Link vimrc to ~/.vimrc.coliru +[2/3] Link bashrc to ~/.bashrc +[2/3] Link vimrc to ~/.vimrc [2/3] Run sh script.sh arg1 linux ^windows script.sh called with arg1 linux ^windows "; @@ -87,16 +84,16 @@ script.sh called with arg1 linux ^windows assert_eq!(&stdout_to_string(&mut cmd), expected); // Assert files are correctly copied/linked/run - write_file(&dirs.local.join("bashrc"), "bash #2"); - write_file(&dirs.local.join("vimrc"), "vim #2"); - let bash_contents = read_file(&dirs.home.join(".bashrc.coliru")); - let git_exists = dirs.home.join(".gitconfig.coliru").exists(); - let vim1_contents = read_file(&dirs.home.join(".vimrc.coliru")); - let vim2_exists = dirs.home.join("_vimrc.coliru").exists(); - let log_contents = read_file(&dirs.local.join("log.txt")); - assert_eq!(bash_contents, "bash #2"); + write_file(&dirs.local.join("bashrc"), "bash #2\n"); + write_file(&dirs.local.join("vimrc"), "vim #2\n"); + let bash_contents = read_file(&dirs.home.join(".bashrc")); + let git_exists = dirs.home.join(".gitconfig").exists(); + let vim1_contents = read_file(&dirs.home.join(".vimrc")); + let vim2_exists = dirs.home.join("_vimrc").exists(); + let log_contents = read_file(&dirs.home.join("log.txt")); + assert_eq!(bash_contents, "bash #2\n"); assert_eq!(git_exists, false); - assert_eq!(vim1_contents, "vim #2"); + assert_eq!(vim1_contents, "vim #2\n"); assert_eq!(vim2_exists, false); assert_eq!(log_contents, "script.sh called with arg1 linux ^windows\n"); } @@ -104,14 +101,13 @@ script.sh called with arg1 linux ^windows #[test] #[cfg(target_family = "unix")] fn test_local_run_alternate_tag_rules_2() { - let (dirs, mut cmd) = setup_e2e("test_local_run_alternate_tag_rules_2"); + let (dirs, mut cmd) = setup_e2e_local("test_local_run_alternate_tag_rules_2"); cmd.args(["manifest.yml", "-t", "macos"]); - copy_manifest(&dirs.local, "~/"); let expected = "\ -[1/3] Copy gitconfig to ~/.gitconfig.coliru -[2/3] Link bashrc to ~/.bashrc.coliru -[2/3] Link vimrc to ~/.vimrc.coliru +[1/3] Copy gitconfig to ~/.gitconfig +[2/3] Link bashrc to ~/.bashrc +[2/3] Link vimrc to ~/.vimrc [2/3] Run sh script.sh arg1 macos script.sh called with arg1 macos "; @@ -119,17 +115,17 @@ script.sh called with arg1 macos assert_eq!(&stdout_to_string(&mut cmd), expected); // Assert files are correctly copied/linked/run - write_file(&dirs.local.join("bashrc"), "bash #2"); - write_file(&dirs.local.join("gitconfig"), "git #2"); - write_file(&dirs.local.join("vimrc"), "vim #2"); - let bash_contents = read_file(&dirs.home.join(".bashrc.coliru")); - let git_contents = read_file(&dirs.home.join(".gitconfig.coliru")); - let vim1_contents = read_file(&dirs.home.join(".vimrc.coliru")); - let vim2_exists = dirs.home.join("_vimrc.coliru").exists(); - let log_contents = read_file(&dirs.local.join("log.txt")); - assert_eq!(bash_contents, "bash #2"); - assert_eq!(git_contents, "git #1"); - assert_eq!(vim1_contents, "vim #2"); + write_file(&dirs.local.join("bashrc"), "bash #2\n"); + write_file(&dirs.local.join("gitconfig"), "git #2\n"); + write_file(&dirs.local.join("vimrc"), "vim #2\n"); + let bash_contents = read_file(&dirs.home.join(".bashrc")); + let git_contents = read_file(&dirs.home.join(".gitconfig")); + let vim1_contents = read_file(&dirs.home.join(".vimrc")); + let vim2_exists = dirs.home.join("_vimrc").exists(); + let log_contents = read_file(&dirs.home.join("log.txt")); + assert_eq!(bash_contents, "bash #2\n"); + assert_eq!(git_contents, "git #1\n"); + assert_eq!(vim1_contents, "vim #2\n"); assert_eq!(vim2_exists, false); assert_eq!(log_contents, "script.sh called with arg1 macos\n"); } @@ -137,25 +133,24 @@ script.sh called with arg1 macos #[test] #[cfg(target_family = "unix")] fn test_local_dry_run() { - let (dirs, mut cmd) = setup_e2e("test_local_dry_run"); + let (dirs, mut cmd) = setup_e2e_local("test_local_dry_run"); cmd.args(["manifest.yml", "--dry-run", "-t", "linux"]); - copy_manifest(&dirs.local, "~/"); let expected = "\ -[1/3] Copy gitconfig to ~/.gitconfig.coliru (DRY RUN) -[2/3] Link bashrc to ~/.bashrc.coliru (DRY RUN) -[2/3] Link vimrc to ~/.vimrc.coliru (DRY RUN) +[1/3] Copy gitconfig to ~/.gitconfig (DRY RUN) +[2/3] Link bashrc to ~/.bashrc (DRY RUN) +[2/3] Link vimrc to ~/.vimrc (DRY RUN) [2/3] Run sh script.sh arg1 linux (DRY RUN) "; assert_eq!(&stderr_to_string(&mut cmd), ""); assert_eq!(&stdout_to_string(&mut cmd), expected); // Assert files are correctly copied/linked/run - let bash_exists = dirs.home.join(".bashrc.coliru").exists(); - let git_exists = dirs.home.join(".gitconfig.coliru").exists(); - let vim1_exists = dirs.home.join(".vimrc.coliru").exists(); - let vim2_exists = dirs.home.join("_vimrc.coliru").exists(); - let log_exists = dirs.local.join("log.txt").exists(); + let bash_exists = dirs.home.join(".bashrc").exists(); + let git_exists = dirs.home.join(".gitconfig").exists(); + let vim1_exists = dirs.home.join(".vimrc").exists(); + let vim2_exists = dirs.home.join("_vimrc").exists(); + let log_exists = dirs.home.join("log.txt").exists(); assert_eq!(bash_exists, false); assert_eq!(git_exists, false); assert_eq!(vim1_exists, false); @@ -166,23 +161,22 @@ fn test_local_dry_run() { #[test] #[cfg(target_family = "windows")] fn test_local_dry_run() { - let (dirs, mut cmd) = setup_e2e("test_local_dry_run"); + let (dirs, mut cmd) = setup_e2e_local("test_local_dry_run"); cmd.args(["manifest.yml", "--dry-run", "-t", "windows"]); - copy_manifest(&dirs.local, ""); let expected = "\ -[1/3] Copy gitconfig to .gitconfig.coliru (DRY RUN) -[3/3] Link vimrc to _vimrc.coliru (DRY RUN) +[1/3] Copy gitconfig to .gitconfig (DRY RUN) +[3/3] Link vimrc to _vimrc (DRY RUN) [3/3] Run script.bat arg1 windows (DRY RUN) "; assert_eq!(&stderr_to_string(&mut cmd), ""); assert_eq!(&stdout_to_string(&mut cmd), expected); // Assert files are correctly copied/linked/run - let bash_exists = dirs.local.join(".bashrc.coliru").exists(); - let git_exists = dirs.local.join(".gitconfig.coliru").exists(); - let vim1_exists = dirs.local.join(".vimrc.coliru").exists(); - let vim2_exists = dirs.local.join("_vimrc.coliru").exists(); + let bash_exists = dirs.local.join(".bashrc").exists(); + let git_exists = dirs.local.join(".gitconfig").exists(); + let vim1_exists = dirs.local.join(".vimrc").exists(); + let vim2_exists = dirs.local.join("_vimrc").exists(); let log_exists = dirs.local.join("log.txt").exists(); assert_eq!(bash_exists, false); assert_eq!(git_exists, false); @@ -194,14 +188,13 @@ fn test_local_dry_run() { #[test] #[cfg(target_family = "unix")] fn test_local_copy() { - let (dirs, mut cmd) = setup_e2e("test_local_copy"); + let (dirs, mut cmd) = setup_e2e_local("test_local_copy"); cmd.args(["manifest.yml", "--copy", "-t", "linux"]); - copy_manifest(&dirs.local, "~/"); let expected = "\ -[1/3] Copy gitconfig to ~/.gitconfig.coliru -[2/3] Copy bashrc to ~/.bashrc.coliru -[2/3] Copy vimrc to ~/.vimrc.coliru +[1/3] Copy gitconfig to ~/.gitconfig +[2/3] Copy bashrc to ~/.bashrc +[2/3] Copy vimrc to ~/.vimrc [2/3] Run sh script.sh arg1 linux script.sh called with arg1 linux "; @@ -209,17 +202,17 @@ script.sh called with arg1 linux assert_eq!(&stdout_to_string(&mut cmd), expected); // Assert files are correctly copied/linked/run - write_file(&dirs.local.join("bashrc"), "bash #2"); - write_file(&dirs.local.join("gitconfig"), "git #2"); - write_file(&dirs.local.join("vimrc"), "vim #2"); - let bash_contents = read_file(&dirs.home.join(".bashrc.coliru")); - let git_contents = read_file(&dirs.home.join(".gitconfig.coliru")); - let vim1_contents = read_file(&dirs.home.join(".vimrc.coliru")); - let vim2_exists = dirs.home.join("_vimrc.coliru").exists(); - let log_contents = read_file(&dirs.local.join("log.txt")); - assert_eq!(bash_contents, "bash #1"); - assert_eq!(git_contents, "git #1"); - assert_eq!(vim1_contents, "vim #1"); + write_file(&dirs.local.join("bashrc"), "bash #2\n"); + write_file(&dirs.local.join("gitconfig"), "git #2\n"); + write_file(&dirs.local.join("vimrc"), "vim #2\n"); + let bash_contents = read_file(&dirs.home.join(".bashrc")); + let git_contents = read_file(&dirs.home.join(".gitconfig")); + let vim1_contents = read_file(&dirs.home.join(".vimrc")); + let vim2_exists = dirs.home.join("_vimrc").exists(); + let log_contents = read_file(&dirs.home.join("log.txt")); + assert_eq!(bash_contents, "bash #1\n"); + assert_eq!(git_contents, "git #1\n"); + assert_eq!(vim1_contents, "vim #1\n"); assert_eq!(vim2_exists, false); assert_eq!(log_contents, "script.sh called with arg1 linux\n"); } @@ -227,13 +220,12 @@ script.sh called with arg1 linux #[test] #[cfg(target_family = "windows")] fn test_local_copy() { - let (dirs, mut cmd) = setup_e2e("test_local_copy"); + let (dirs, mut cmd) = setup_e2e_local("test_local_copy"); cmd.args(["manifest.yml", "--copy", "-t", "windows"]); - copy_manifest(&dirs.local, ""); let expected = "\ -[1/3] Copy gitconfig to .gitconfig.coliru -[3/3] Copy vimrc to _vimrc.coliru +[1/3] Copy gitconfig to .gitconfig +[3/3] Copy vimrc to _vimrc [3/3] Run script.bat arg1 windows script.bat called with arg1 windows\r "; @@ -241,32 +233,31 @@ script.bat called with arg1 windows\r assert_eq!(&stdout_to_string(&mut cmd), expected); // Assert files are correctly copied/linked/run - write_file(&dirs.local.join("gitconfig"), "git #2"); - write_file(&dirs.local.join("vimrc"), "vim #2"); - let bash_exists = dirs.local.join(".bashrc.coliru").exists(); - let git_contents = read_file(&dirs.local.join(".gitconfig.coliru")); - let vim1_exists = dirs.local.join(".vimrc.coliru").exists(); - let vim2_contents = read_file(&dirs.local.join("_vimrc.coliru")); + write_file(&dirs.local.join("gitconfig"), "git #2\r\n"); + write_file(&dirs.local.join("vimrc"), "vim #2\r\n"); + let bash_exists = dirs.local.join(".bashrc").exists(); + let git_contents = read_file(&dirs.local.join(".gitconfig")); + let vim1_exists = dirs.local.join(".vimrc").exists(); + let vim2_contents = read_file(&dirs.local.join("_vimrc")); let log_contents = read_file(&dirs.local.join("log.txt")); assert_eq!(bash_exists, false); - assert_eq!(git_contents, "git #1"); + assert_eq!(git_contents, "git #1\r\n"); assert_eq!(vim1_exists, false); - assert_eq!(vim2_contents, "vim #1"); + assert_eq!(vim2_contents, "vim #1\r\n"); assert_eq!(log_contents, "script.bat called with arg1 windows \r\n"); } #[test] #[cfg(target_family = "unix")] fn test_local_run_failure() { - let (dirs, mut cmd) = setup_e2e("test_local_run_failure"); + let (dirs, mut cmd) = setup_e2e_local("test_local_run_failure"); cmd.args(["manifest.yml", "-t", "linux"]); - copy_manifest(&dirs.local, "~/"); write_file(&dirs.local.join("script.sh"), "exit 1"); let expected_stdout = "\ -[1/3] Copy gitconfig to ~/.gitconfig.coliru -[2/3] Link bashrc to ~/.bashrc.coliru -[2/3] Link vimrc to ~/.vimrc.coliru +[1/3] Copy gitconfig to ~/.gitconfig +[2/3] Link bashrc to ~/.bashrc +[2/3] Link vimrc to ~/.vimrc [2/3] Run sh script.sh arg1 linux "; let expected_stderr = " Error: Process exited with exit status: 1\n"; @@ -274,30 +265,29 @@ fn test_local_run_failure() { assert_eq!(&stdout_to_string(&mut cmd), expected_stdout); // Assert files are correctly copied/linked/run - write_file(&dirs.local.join("bashrc"), "bash #2"); - write_file(&dirs.local.join("gitconfig"), "git #2"); - write_file(&dirs.local.join("vimrc"), "vim #2"); - let bash_contents = read_file(&dirs.home.join(".bashrc.coliru")); - let git_contents = read_file(&dirs.home.join(".gitconfig.coliru")); - let vim1_contents = read_file(&dirs.home.join(".vimrc.coliru")); - let vim2_exists = dirs.home.join("_vimrc.coliru").exists(); - assert_eq!(bash_contents, "bash #2"); - assert_eq!(git_contents, "git #1"); - assert_eq!(vim1_contents, "vim #2"); + write_file(&dirs.local.join("bashrc"), "bash #2\n"); + write_file(&dirs.local.join("gitconfig"), "git #2\n"); + write_file(&dirs.local.join("vimrc"), "vim #2\n"); + let bash_contents = read_file(&dirs.home.join(".bashrc")); + let git_contents = read_file(&dirs.home.join(".gitconfig")); + let vim1_contents = read_file(&dirs.home.join(".vimrc")); + let vim2_exists = dirs.home.join("_vimrc").exists(); + assert_eq!(bash_contents, "bash #2\n"); + assert_eq!(git_contents, "git #1\n"); + assert_eq!(vim1_contents, "vim #2\n"); assert_eq!(vim2_exists, false); } #[test] #[cfg(target_family = "windows")] fn test_local_run_failure() { - let (dirs, mut cmd) = setup_e2e("test_local_run_failure"); + let (dirs, mut cmd) = setup_e2e_local("test_local_run_failure"); cmd.args(["manifest.yml", "-t", "windows"]); - copy_manifest(&dirs.local, ""); write_file(&dirs.local.join("script.bat"), "@echo off\r\nexit 1"); let expected_stdout = "\ -[1/3] Copy gitconfig to .gitconfig.coliru -[3/3] Link vimrc to _vimrc.coliru +[1/3] Copy gitconfig to .gitconfig +[3/3] Link vimrc to _vimrc [3/3] Run script.bat arg1 windows "; let expected_stderr = " Error: Process exited with exit code: 1\n"; @@ -305,30 +295,29 @@ fn test_local_run_failure() { assert_eq!(&stdout_to_string(&mut cmd), expected_stdout); // Assert files are correctly copied/linked/run - write_file(&dirs.local.join("gitconfig"), "git #2"); - write_file(&dirs.local.join("vimrc"), "vim #2"); - let bash_exists = dirs.local.join(".bashrc.coliru").exists(); - let git_contents = read_file(&dirs.local.join(".gitconfig.coliru")); - let vim1_exists = dirs.local.join(".vimrc.coliru").exists(); - let vim2_contents = read_file(&dirs.local.join("_vimrc.coliru")); + write_file(&dirs.local.join("gitconfig"), "git #2\r\n"); + write_file(&dirs.local.join("vimrc"), "vim #2\r\n"); + let bash_exists = dirs.local.join(".bashrc").exists(); + let git_contents = read_file(&dirs.local.join(".gitconfig")); + let vim1_exists = dirs.local.join(".vimrc").exists(); + let vim2_contents = read_file(&dirs.local.join("_vimrc")); assert_eq!(bash_exists, false); - assert_eq!(git_contents, "git #1"); + assert_eq!(git_contents, "git #1\r\n"); assert_eq!(vim1_exists, false); - assert_eq!(vim2_contents, "vim #2"); + assert_eq!(vim2_contents, "vim #2\r\n"); } #[test] #[cfg(target_family = "unix")] fn test_local_missing_file() { - let (dirs, mut cmd) = setup_e2e("test_local_missing_file"); + let (dirs, mut cmd) = setup_e2e_local("test_local_missing_file"); cmd.args(["manifest.yml", "-t", "linux"]); - copy_manifest(&dirs.local, "~/"); remove_file(&dirs.local.join("vimrc")).unwrap(); let expected_stdout = "\ -[1/3] Copy gitconfig to ~/.gitconfig.coliru -[2/3] Link bashrc to ~/.bashrc.coliru -[2/3] Link vimrc to ~/.vimrc.coliru +[1/3] Copy gitconfig to ~/.gitconfig +[2/3] Link bashrc to ~/.bashrc +[2/3] Link vimrc to ~/.vimrc [2/3] Run sh script.sh arg1 linux script.sh called with arg1 linux "; @@ -337,27 +326,26 @@ script.sh called with arg1 linux assert_eq!(&stdout_to_string(&mut cmd), expected_stdout); // Assert files are correctly copied/linked/run - write_file(&dirs.local.join("bashrc"), "bash #2"); - write_file(&dirs.local.join("gitconfig"), "git #2"); - let bash_contents = read_file(&dirs.home.join(".bashrc.coliru")); - let git_contents = read_file(&dirs.home.join(".gitconfig.coliru")); - let log_contents = read_file(&dirs.local.join("log.txt")); - assert_eq!(bash_contents, "bash #2"); - assert_eq!(git_contents, "git #1"); + write_file(&dirs.local.join("bashrc"), "bash #2\n"); + write_file(&dirs.local.join("gitconfig"), "git #2\n"); + let bash_contents = read_file(&dirs.home.join(".bashrc")); + let git_contents = read_file(&dirs.home.join(".gitconfig")); + let log_contents = read_file(&dirs.home.join("log.txt")); + assert_eq!(bash_contents, "bash #2\n"); + assert_eq!(git_contents, "git #1\n"); assert_eq!(log_contents, "script.sh called with arg1 linux\n"); } #[test] #[cfg(target_family = "windows")] fn test_local_missing_file() { - let (dirs, mut cmd) = setup_e2e("test_local_missing_file"); + let (dirs, mut cmd) = setup_e2e_local("test_local_missing_file"); cmd.args(["manifest.yml", "-t", "windows"]); - copy_manifest(&dirs.local, ""); remove_file(&dirs.local.join("vimrc")).unwrap(); let expected_stdout = "\ -[1/3] Copy gitconfig to .gitconfig.coliru -[3/3] Link vimrc to _vimrc.coliru +[1/3] Copy gitconfig to .gitconfig +[3/3] Link vimrc to _vimrc [3/3] Run script.bat arg1 windows script.bat called with arg1 windows\r "; @@ -367,11 +355,11 @@ script.bat called with arg1 windows\r assert_eq!(&stdout_to_string(&mut cmd), expected_stdout); // Assert files are correctly copied/linked/run - write_file(&dirs.local.join("gitconfig"), "git #2"); - let bash_exists = dirs.local.join(".bashrc.coliru").exists(); - let git_contents = read_file(&dirs.local.join(".gitconfig.coliru")); + write_file(&dirs.local.join("gitconfig"), "git #2\r\n"); + let bash_exists = dirs.local.join(".bashrc").exists(); + let git_contents = read_file(&dirs.local.join(".gitconfig")); let log_contents = read_file(&dirs.local.join("log.txt")); assert_eq!(bash_exists, false); - assert_eq!(git_contents, "git #1"); + assert_eq!(git_contents, "git #1\r\n"); assert_eq!(log_contents, "script.bat called with arg1 windows \r\n"); } diff --git a/tests/ssh.rs b/tests/ssh.rs @@ -11,27 +11,26 @@ use std::fs::remove_file; fn test_ssh_standard() { let (dirs, mut cmd) = setup_e2e_ssh("test_ssh_standard"); cmd.args(["manifest.yml", "-t", "linux"]); - copy_manifest(&dirs.local, "~/test_ssh_standard/"); let expected_stdout = format!("\ -[1/3] Copy gitconfig to {SSH_HOST}:~/test_ssh_standard/.gitconfig.coliru -[2/3] Copy bashrc to {SSH_HOST}:~/test_ssh_standard/.bashrc.coliru -[2/3] Copy vimrc to {SSH_HOST}:~/test_ssh_standard/.vimrc.coliru -[2/3] Run sh script.sh arg1 linux on {SSH_HOST} +[1/3] Copy gitconfig to {SSH_HOST}:~/test_ssh_standard/.gitconfig +[2/3] Copy bashrc to {SSH_HOST}:~/test_ssh_standard/.bashrc +[2/3] Copy vimrc to {SSH_HOST}:~/test_ssh_standard/.vimrc +[2/3] Run sh test_ssh_standard/script.sh arg1 linux on {SSH_HOST} "); let expected_stderr = " Error: not implemented\n"; assert_eq!(&stderr_to_string(&mut cmd), expected_stderr); assert_eq!(stdout_to_string(&mut cmd), expected_stdout); // Assert files are correctly copied/run - let bash_contents = read_file(&dirs.ssh.join(".bashrc.coliru")); - let git_contents = read_file(&dirs.ssh.join(".gitconfig.coliru")); - let vim1_contents = read_file(&dirs.ssh.join(".vimrc.coliru")); - let vim2_exists = dirs.ssh.join("_vimrc.coliru").exists(); + let bash_contents = read_file(&dirs.ssh.join(".bashrc")); + let git_contents = read_file(&dirs.ssh.join(".gitconfig")); + let vim1_contents = read_file(&dirs.ssh.join(".vimrc")); + let vim2_exists = dirs.ssh.join("_vimrc").exists(); // let log_contents = read_file(&dirs.local.join("log.txt")); - assert_eq!(bash_contents, "bash #1"); - assert_eq!(git_contents, "git #1"); - assert_eq!(vim1_contents, "vim #1"); + assert_eq!(bash_contents, "bash #1\n"); + assert_eq!(git_contents, "git #1\n"); + assert_eq!(vim1_contents, "vim #1\n"); assert_eq!(vim2_exists, false); // assert_eq!(log_contents, "script.sh called with arg1 linux\n"); } @@ -41,26 +40,25 @@ fn test_ssh_standard() { fn test_ssh_run_alternate_tag_rules_1() { let (dirs, mut cmd) = setup_e2e_ssh("test_ssh_run_alternate_tag_rules_1"); cmd.args(["manifest.yml", "-t", "linux", "^windows"]); - copy_manifest(&dirs.local, "~/test_ssh_run_alternate_tag_rules_1/"); let expected_stdout = format!("\ -[2/3] Copy bashrc to {SSH_HOST}:~/test_ssh_run_alternate_tag_rules_1/.bashrc.coliru -[2/3] Copy vimrc to {SSH_HOST}:~/test_ssh_run_alternate_tag_rules_1/.vimrc.coliru -[2/3] Run sh script.sh arg1 linux ^windows on {SSH_HOST} +[2/3] Copy bashrc to {SSH_HOST}:~/test_ssh_run_alternate_tag_rules_1/.bashrc +[2/3] Copy vimrc to {SSH_HOST}:~/test_ssh_run_alternate_tag_rules_1/.vimrc +[2/3] Run sh test_ssh_run_alternate_tag_rules_1/script.sh arg1 linux ^windows on {SSH_HOST} "); let expected_stderr = " Error: not implemented\n"; assert_eq!(&stderr_to_string(&mut cmd), expected_stderr); assert_eq!(stdout_to_string(&mut cmd), expected_stdout); // Assert files are correctly copied/run - let bash_contents = read_file(&dirs.ssh.join(".bashrc.coliru")); - let git_exists = dirs.ssh.join(".gitconfig.coliru").exists(); - let vim1_contents = read_file(&dirs.ssh.join(".vimrc.coliru")); - let vim2_exists = dirs.ssh.join("_vimrc.coliru").exists(); + let bash_contents = read_file(&dirs.ssh.join(".bashrc")); + let git_exists = dirs.ssh.join(".gitconfig").exists(); + let vim1_contents = read_file(&dirs.ssh.join(".vimrc")); + let vim2_exists = dirs.ssh.join("_vimrc").exists(); // let log_contents = read_file(&dirs.local.join("log.txt")); - assert_eq!(bash_contents, "bash #1"); + assert_eq!(bash_contents, "bash #1\n"); assert_eq!(git_exists, false); - assert_eq!(vim1_contents, "vim #1"); + assert_eq!(vim1_contents, "vim #1\n"); assert_eq!(vim2_exists, false); // assert_eq!(log_contents, "script.sh called with arg1 linux ^windows\n"); } @@ -70,27 +68,26 @@ fn test_ssh_run_alternate_tag_rules_1() { fn test_ssh_run_alternate_tag_rules_2() { let (dirs, mut cmd) = setup_e2e_ssh("test_ssh_run_alternate_tag_rules_2"); cmd.args(["manifest.yml", "-t", "macos"]); - copy_manifest(&dirs.local, "~/test_ssh_run_alternate_tag_rules_2/"); let expected_stdout = format!("\ -[1/3] Copy gitconfig to {SSH_HOST}:~/test_ssh_run_alternate_tag_rules_2/.gitconfig.coliru -[2/3] Copy bashrc to {SSH_HOST}:~/test_ssh_run_alternate_tag_rules_2/.bashrc.coliru -[2/3] Copy vimrc to {SSH_HOST}:~/test_ssh_run_alternate_tag_rules_2/.vimrc.coliru -[2/3] Run sh script.sh arg1 macos on {SSH_HOST} +[1/3] Copy gitconfig to {SSH_HOST}:~/test_ssh_run_alternate_tag_rules_2/.gitconfig +[2/3] Copy bashrc to {SSH_HOST}:~/test_ssh_run_alternate_tag_rules_2/.bashrc +[2/3] Copy vimrc to {SSH_HOST}:~/test_ssh_run_alternate_tag_rules_2/.vimrc +[2/3] Run sh test_ssh_run_alternate_tag_rules_2/script.sh arg1 macos on {SSH_HOST} "); let expected_stderr = " Error: not implemented\n"; assert_eq!(&stderr_to_string(&mut cmd), expected_stderr); assert_eq!(stdout_to_string(&mut cmd), expected_stdout); // Assert files are correctly copied/run - let bash_contents = read_file(&dirs.ssh.join(".bashrc.coliru")); - let git_contents = read_file(&dirs.ssh.join(".gitconfig.coliru")); - let vim1_contents = read_file(&dirs.ssh.join(".vimrc.coliru")); - let vim2_exists = dirs.ssh.join("_vimrc.coliru").exists(); + let bash_contents = read_file(&dirs.ssh.join(".bashrc")); + let git_contents = read_file(&dirs.ssh.join(".gitconfig")); + let vim1_contents = read_file(&dirs.ssh.join(".vimrc")); + let vim2_exists = dirs.ssh.join("_vimrc").exists(); // let log_contents = read_file(&dirs.local.join("log.txt")); - assert_eq!(bash_contents, "bash #1"); - assert_eq!(git_contents, "git #1"); - assert_eq!(vim1_contents, "vim #1"); + assert_eq!(bash_contents, "bash #1\n"); + assert_eq!(git_contents, "git #1\n"); + assert_eq!(vim1_contents, "vim #1\n"); assert_eq!(vim2_exists, false); // assert_eq!(log_contents, "script.sh called with arg1 macos\n"); } @@ -99,22 +96,21 @@ fn test_ssh_run_alternate_tag_rules_2() { fn test_ssh_dry_run() { let (dirs, mut cmd) = setup_e2e_ssh("test_ssh_dry_run"); cmd.args(["manifest.yml", "--dry-run", "-t", "linux"]); - copy_manifest(&dirs.local, "~/test_ssh_dry_run/"); let expected = format!("\ -[1/3] Copy gitconfig to {SSH_HOST}:~/test_ssh_dry_run/.gitconfig.coliru (DRY RUN) -[2/3] Copy bashrc to {SSH_HOST}:~/test_ssh_dry_run/.bashrc.coliru (DRY RUN) -[2/3] Copy vimrc to {SSH_HOST}:~/test_ssh_dry_run/.vimrc.coliru (DRY RUN) -[2/3] Run sh script.sh arg1 linux on {SSH_HOST} (DRY RUN) +[1/3] Copy gitconfig to {SSH_HOST}:~/test_ssh_dry_run/.gitconfig (DRY RUN) +[2/3] Copy bashrc to {SSH_HOST}:~/test_ssh_dry_run/.bashrc (DRY RUN) +[2/3] Copy vimrc to {SSH_HOST}:~/test_ssh_dry_run/.vimrc (DRY RUN) +[2/3] Run sh test_ssh_dry_run/script.sh arg1 linux on {SSH_HOST} (DRY RUN) "); assert_eq!(&stderr_to_string(&mut cmd), ""); assert_eq!(stdout_to_string(&mut cmd), expected); // Assert files are correctly copied/run - let bash_exists = dirs.ssh.join(".bashrc.coliru").exists(); - let git_exists = dirs.ssh.join(".gitconfig.coliru").exists(); - let vim1_exists = dirs.ssh.join(".vimrc.coliru").exists(); - let vim2_exists = dirs.ssh.join("_vimrc.coliru").exists(); + let bash_exists = dirs.ssh.join(".bashrc").exists(); + let git_exists = dirs.ssh.join(".gitconfig").exists(); + let vim1_exists = dirs.ssh.join(".vimrc").exists(); + let vim2_exists = dirs.ssh.join("_vimrc").exists(); // let log_exists = dirs.local.join("log.txt").exists(); assert_eq!(bash_exists, false); assert_eq!(git_exists, false); @@ -128,27 +124,26 @@ fn test_ssh_dry_run() { fn test_ssh_copy() { let (dirs, mut cmd) = setup_e2e_ssh("test_ssh_copy"); cmd.args(["manifest.yml", "--copy", "-t", "linux"]); - copy_manifest(&dirs.local, "~/test_ssh_copy/"); let expected_stdout = format!("\ -[1/3] Copy gitconfig to {SSH_HOST}:~/test_ssh_copy/.gitconfig.coliru -[2/3] Copy bashrc to {SSH_HOST}:~/test_ssh_copy/.bashrc.coliru -[2/3] Copy vimrc to {SSH_HOST}:~/test_ssh_copy/.vimrc.coliru -[2/3] Run sh script.sh arg1 linux on {SSH_HOST} +[1/3] Copy gitconfig to {SSH_HOST}:~/test_ssh_copy/.gitconfig +[2/3] Copy bashrc to {SSH_HOST}:~/test_ssh_copy/.bashrc +[2/3] Copy vimrc to {SSH_HOST}:~/test_ssh_copy/.vimrc +[2/3] Run sh test_ssh_copy/script.sh arg1 linux on {SSH_HOST} "); let expected_stderr = " Error: not implemented\n"; assert_eq!(&stderr_to_string(&mut cmd), expected_stderr); assert_eq!(stdout_to_string(&mut cmd), expected_stdout); // Assert files are correctly copied/run - let bash_contents = read_file(&dirs.ssh.join(".bashrc.coliru")); - let git_contents = read_file(&dirs.ssh.join(".gitconfig.coliru")); - let vim1_contents = read_file(&dirs.ssh.join(".vimrc.coliru")); - let vim2_exists = dirs.ssh.join("_vimrc.coliru").exists(); + let bash_contents = read_file(&dirs.ssh.join(".bashrc")); + let git_contents = read_file(&dirs.ssh.join(".gitconfig")); + let vim1_contents = read_file(&dirs.ssh.join(".vimrc")); + let vim2_exists = dirs.ssh.join("_vimrc").exists(); // let log_contents = read_file(&dirs.local.join("log.txt")); - assert_eq!(bash_contents, "bash #1"); - assert_eq!(git_contents, "git #1"); - assert_eq!(vim1_contents, "vim #1"); + assert_eq!(bash_contents, "bash #1\n"); + assert_eq!(git_contents, "git #1\n"); + assert_eq!(vim1_contents, "vim #1\n"); assert_eq!(vim2_exists, false); // assert_eq!(log_contents, "script.sh called with arg1 linux\n"); } @@ -158,27 +153,26 @@ fn test_ssh_copy() { fn test_ssh_run_failure() { let (dirs, mut cmd) = setup_e2e_ssh("test_ssh_run_failure"); cmd.args(["manifest.yml", "-t", "linux"]); - copy_manifest(&dirs.local, "~/test_ssh_run_failure/"); write_file(&dirs.local.join("script.sh"), "exit 1"); let expected_stdout = format!("\ -[1/3] Copy gitconfig to {SSH_HOST}:~/test_ssh_run_failure/.gitconfig.coliru -[2/3] Copy bashrc to {SSH_HOST}:~/test_ssh_run_failure/.bashrc.coliru -[2/3] Copy vimrc to {SSH_HOST}:~/test_ssh_run_failure/.vimrc.coliru -[2/3] Run sh script.sh arg1 linux on {SSH_HOST} +[1/3] Copy gitconfig to {SSH_HOST}:~/test_ssh_run_failure/.gitconfig +[2/3] Copy bashrc to {SSH_HOST}:~/test_ssh_run_failure/.bashrc +[2/3] Copy vimrc to {SSH_HOST}:~/test_ssh_run_failure/.vimrc +[2/3] Run sh test_ssh_run_failure/script.sh arg1 linux on {SSH_HOST} "); let expected_stderr = " Error: not implemented\n"; assert_eq!(&stderr_to_string(&mut cmd), expected_stderr); assert_eq!(stdout_to_string(&mut cmd), expected_stdout); // Assert files are correctly copied/run - let bash_contents = read_file(&dirs.ssh.join(".bashrc.coliru")); - let git_contents = read_file(&dirs.ssh.join(".gitconfig.coliru")); - let vim1_contents = read_file(&dirs.ssh.join(".vimrc.coliru")); - let vim2_exists = dirs.ssh.join("_vimrc.coliru").exists(); - assert_eq!(bash_contents, "bash #1"); - assert_eq!(git_contents, "git #1"); - assert_eq!(vim1_contents, "vim #1"); + let bash_contents = read_file(&dirs.ssh.join(".bashrc")); + let git_contents = read_file(&dirs.ssh.join(".gitconfig")); + let vim1_contents = read_file(&dirs.ssh.join(".vimrc")); + let vim2_exists = dirs.ssh.join("_vimrc").exists(); + assert_eq!(bash_contents, "bash #1\n"); + assert_eq!(git_contents, "git #1\n"); + assert_eq!(vim1_contents, "vim #1\n"); assert_eq!(vim2_exists, false); } @@ -187,14 +181,13 @@ fn test_ssh_run_failure() { fn test_ssh_missing_file() { let (dirs, mut cmd) = setup_e2e_ssh("test_ssh_missing_file"); cmd.args(["manifest.yml", "-t", "linux"]); - copy_manifest(&dirs.local, "~/test_ssh_missing_file/"); remove_file(&dirs.local.join("vimrc")).unwrap(); let expected_stdout = format!("\ -[1/3] Copy gitconfig to {SSH_HOST}:~/test_ssh_missing_file/.gitconfig.coliru -[2/3] Copy bashrc to {SSH_HOST}:~/test_ssh_missing_file/.bashrc.coliru -[2/3] Copy vimrc to {SSH_HOST}:~/test_ssh_missing_file/.vimrc.coliru -[2/3] Run sh script.sh arg1 linux on {SSH_HOST} +[1/3] Copy gitconfig to {SSH_HOST}:~/test_ssh_missing_file/.gitconfig +[2/3] Copy bashrc to {SSH_HOST}:~/test_ssh_missing_file/.bashrc +[2/3] Copy vimrc to {SSH_HOST}:~/test_ssh_missing_file/.vimrc +[2/3] Run sh test_ssh_missing_file/script.sh arg1 linux on {SSH_HOST} "); let expected_stderr = " Error: No such file or directory (os error 2) Error: not implemented @@ -203,10 +196,10 @@ fn test_ssh_missing_file() { assert_eq!(stdout_to_string(&mut cmd), expected_stdout); // Assert files are correctly copied/run - let bash_contents = read_file(&dirs.ssh.join(".bashrc.coliru")); - let git_contents = read_file(&dirs.ssh.join(".gitconfig.coliru")); + let bash_contents = read_file(&dirs.ssh.join(".bashrc")); + let git_contents = read_file(&dirs.ssh.join(".gitconfig")); // let log_contents = read_file(&dirs.ssh.join("log.txt")); - assert_eq!(bash_contents, "bash #1"); - assert_eq!(git_contents, "git #1"); + assert_eq!(bash_contents, "bash #1\n"); + assert_eq!(git_contents, "git #1\n"); // assert_eq!(log_contents, "script.sh called with arg1 linux\n"); }