use assert_fs::{
fixture::ChildPath,
prelude::{FileWriteStr, PathAssert, PathChild},
TempDir,
};
use predicates::prelude::predicate;
use std::path::PathBuf;
use std::process;
use std::str::FromStr as _;
fn putter_cmd() -> process::Command {
let exe = PathBuf::from_str(env!("CARGO_BIN_EXE_putter")).expect("putter path");
process::Command::new(exe)
}
mod bad_manifest_prints_error {
use serde_json::json;
use super::*;
struct Scenario {
source_dir: TempDir,
manifest_file: ChildPath,
state_file: ChildPath,
}
impl Scenario {
fn init() -> anyhow::Result<Scenario> {
let source_dir = TempDir::new()?;
let manifest_file = source_dir.child("manifest.json");
manifest_file.write_str(
&json!({
"files": []
})
.to_string(),
)?;
let state_file = source_dir.child("state.json");
Ok(Scenario {
source_dir,
manifest_file,
state_file,
})
}
fn close(self) -> anyhow::Result<()> {
self.source_dir.close()?;
Ok(())
}
}
macro_rules! assert_output {
($scenario:expr, $output:expr) => {
let manifest = $scenario.manifest_file.path().display();
let expected_stderr = format!(
r#"Error: error loading manifest from {manifest}
Caused by:
missing field `version` at line 1 column 12
"#
);
assert!(!$output.status.success());
assert_eq!(&String::from_utf8($output.stdout)?, "");
assert!(String::from_utf8($output.stderr)?.starts_with(&expected_stderr));
};
}
#[test]
fn check() -> anyhow::Result<()> {
testing_logger::setup();
let scenario = Scenario::init()?;
let output = putter_cmd()
.arg("check")
.arg("--state-file")
.arg(scenario.state_file.path())
.arg(scenario.manifest_file.path())
.output()?;
assert_output!(scenario, output);
scenario.close()
}
#[test]
fn apply_dry_run() -> anyhow::Result<()> {
testing_logger::setup();
let scenario = Scenario::init()?;
let output = putter_cmd()
.arg("apply")
.arg("--state-file")
.arg(scenario.state_file.path())
.arg("--dry-run")
.arg(scenario.manifest_file.path())
.output()?;
assert_output!(scenario, output);
scenario.close()
}
#[test]
fn apply() -> anyhow::Result<()> {
testing_logger::setup();
let scenario = Scenario::init()?;
let output = putter_cmd()
.arg("apply")
.arg("--state-file")
.arg(scenario.state_file.path())
.arg(scenario.manifest_file.path())
.output()?;
assert_output!(scenario, output);
scenario.close()
}
}
mod symlink_no_collision_empty_state {
use serde_json::json;
use super::*;
struct Scenario {
source_dir: TempDir,
target_dir: TempDir,
source_file: ChildPath,
target_file: ChildPath,
manifest_file: ChildPath,
state_file: ChildPath,
}
impl Scenario {
fn init() -> anyhow::Result<Scenario> {
let source_dir = TempDir::new()?;
let target_dir = TempDir::new()?;
let source_file = source_dir.child("s_file");
let target_file = target_dir.child("t_file");
source_file.write_str("content")?;
let manifest_file = source_dir.child("manifest.json");
manifest_file.write_str(
&json!({
"version": "1",
"files": [
{
"source": source_file.to_path_buf(),
"target": target_file.to_path_buf()
}
]
})
.to_string(),
)?;
let state_file = source_dir.child("state.json");
Ok(Scenario {
source_dir,
target_dir,
source_file,
target_file,
manifest_file,
state_file,
})
}
fn close(self) -> anyhow::Result<()> {
self.source_file.assert(predicate::path::exists());
self.source_dir.close()?;
self.target_dir.close()?;
Ok(())
}
}
#[test]
fn check() -> anyhow::Result<()> {
testing_logger::setup();
let scenario = Scenario::init()?;
let output = putter_cmd()
.arg("check")
.arg("--state-file")
.arg(scenario.state_file.path())
.arg(scenario.manifest_file.path())
.output()?;
assert!(output.status.success());
assert_eq!(&String::from_utf8(output.stdout)?, "");
assert_eq!(&String::from_utf8(output.stderr)?, "");
scenario.target_file.assert(predicate::path::missing());
scenario.close()
}
#[test]
fn apply_dry_run() -> anyhow::Result<()> {
testing_logger::setup();
let scenario = Scenario::init()?;
let output = putter_cmd()
.arg("apply")
.arg("--state-file")
.arg(scenario.state_file.path())
.arg("--dry-run")
.arg(scenario.manifest_file.path())
.output()?;
assert!(output.status.success());
assert_eq!(&String::from_utf8(output.stdout)?, "");
assert_eq!(&String::from_utf8(output.stderr)?, "");
scenario.target_file.assert(predicate::path::missing());
scenario.close()
}
#[test]
fn apply() -> anyhow::Result<()> {
testing_logger::setup();
let scenario = Scenario::init()?;
let output = putter_cmd()
.arg("apply")
.arg("--state-file")
.arg(scenario.state_file.path())
.arg(scenario.manifest_file.path())
.output()?;
assert!(output.status.success());
assert_eq!(&String::from_utf8(output.stdout)?, "");
assert_eq!(&String::from_utf8(output.stderr)?, "");
scenario
.target_file
.assert(predicate::path::is_symlink())
.assert("content");
scenario.close()
}
}