#![allow(clippy::unwrap_used)]
#![allow(clippy::expect_used)]
use std::path::PathBuf;
use crate::installer::dry_run::{
DiffPreview, DryRunContext, DryRunSummary, FileChange, FileChangeType, PackageOperation,
ServiceOperation, UserGroupOperation,
};
#[test]
fn test_DRYRUN_COV_mode_changed_diff() {
let change = FileChange {
path: PathBuf::from("/etc/app.conf"),
before: Some("content".to_string()),
after: Some("content".to_string()),
mode: Some(0o755),
change_type: FileChangeType::ModeChanged,
};
let diff = change.to_diff();
assert!(diff.contains("--- a/etc/app.conf"));
assert!(diff.contains("+++ b/etc/app.conf"));
assert!(diff.contains("# chmod 755"));
}
#[test]
fn test_DRYRUN_COV_mode_changed_no_mode() {
let change = FileChange {
path: PathBuf::from("/etc/app.conf"),
before: Some("content".to_string()),
after: Some("content".to_string()),
mode: None,
change_type: FileChangeType::ModeChanged,
};
let diff = change.to_diff();
assert!(diff.contains("--- a/etc/app.conf"));
assert!(diff.contains("+++ b/etc/app.conf"));
assert!(!diff.contains("chmod"));
}
#[test]
fn test_DRYRUN_COV_unified_diff_identical_content() {
let change = FileChange::modified("/etc/same.txt", "line1\nline2\n", "line1\nline2\n");
let diff = change.to_diff();
assert!(diff.contains("--- a/etc/same.txt"));
assert!(diff.contains("+++ b/etc/same.txt"));
assert!(!diff.contains("@@"));
}
#[test]
fn test_DRYRUN_COV_unified_diff_only_additions() {
let change = FileChange::modified("/etc/grow.txt", "line1\n", "line1\nline2\nline3\n");
let diff = change.to_diff();
assert!(diff.contains("@@"));
assert!(diff.contains("+line2"));
assert!(diff.contains("+line3"));
}
#[test]
fn test_DRYRUN_COV_unified_diff_only_removals() {
let change = FileChange::modified("/etc/shrink.txt", "line1\nline2\nline3\n", "line1\n");
let diff = change.to_diff();
assert!(diff.contains("@@"));
assert!(diff.contains("-line2"));
assert!(diff.contains("-line3"));
}
#[test]
fn test_DRYRUN_COV_unified_diff_common_prefix_and_suffix() {
let before = "header\nold_middle\nfooter\n";
let after = "header\nnew_middle\nfooter\n";
let change = FileChange::modified("/etc/middle.txt", before, after);
let diff = change.to_diff();
assert!(diff.contains("-old_middle"));
assert!(diff.contains("+new_middle"));
assert!(!diff.contains("-header"));
assert!(!diff.contains("+header"));
}
#[test]
fn test_DRYRUN_COV_unified_diff_empty_before() {
let change = FileChange::modified("/etc/new.txt", "", "new content\n");
let diff = change.to_diff();
assert!(diff.contains("+new content"));
}
#[test]
fn test_DRYRUN_COV_unified_diff_empty_after() {
let change = FileChange::modified("/etc/empty.txt", "old content\n", "");
let diff = change.to_diff();
assert!(diff.contains("-old content"));
}
#[test]
fn test_DRYRUN_COV_created_multiline() {
let change = FileChange::created("/etc/multi.conf", "a\nb\nc\n", Some(0o644));
let diff = change.to_diff();
assert!(diff.contains("@@ -0,0 +1,3 @@"));
assert!(diff.contains("+a"));
assert!(diff.contains("+b"));
assert!(diff.contains("+c"));
}
#[test]
fn test_DRYRUN_COV_deleted_multiline() {
let change = FileChange::deleted("/tmp/old.conf", "x\ny\nz\n");
let diff = change.to_diff();
assert!(diff.contains("@@ -1,3 +0,0 @@"));
assert!(diff.contains("-x"));
assert!(diff.contains("-y"));
assert!(diff.contains("-z"));
}
#[test]
fn test_DRYRUN_COV_created_single_line() {
let change = FileChange::created("/etc/one.txt", "only line", None);
let diff = change.to_diff();
assert!(diff.contains("@@ -0,0 +1,1 @@"));
assert!(diff.contains("+only line"));
}
#[test]
fn test_DRYRUN_COV_package_install_without_version() {
let op = PackageOperation::install("curl", None);
assert_eq!(op.to_diff_line(), "+ curl");
}
#[test]
fn test_DRYRUN_COV_package_upgrade() {
let op = PackageOperation::Upgrade {
name: "nginx".to_string(),
from_version: Some("1.20".to_string()),
to_version: Some("1.24".to_string()),
};
assert_eq!(op.to_diff_line(), "~ nginx (1.20 -> 1.24)");
}
#[test]
fn test_DRYRUN_COV_package_upgrade_unknown_versions() {
let op = PackageOperation::Upgrade {
name: "nginx".to_string(),
from_version: None,
to_version: None,
};
assert_eq!(op.to_diff_line(), "~ nginx (? -> ?)");
}
#[test]
fn test_DRYRUN_COV_package_remove() {
let op = PackageOperation::remove("old-pkg");
assert_eq!(op.to_diff_line(), "- old-pkg");
}
#[test]
fn test_DRYRUN_COV_service_disable() {
let op = ServiceOperation::Disable {
name: "apache2".to_string(),
};
assert_eq!(op.to_diff_line(), "- systemctl enable apache2");
}
#[test]
fn test_DRYRUN_COV_service_stop() {
let op = ServiceOperation::Stop {
name: "mysql".to_string(),
};
assert_eq!(op.to_diff_line(), "- systemctl start mysql");
}
#[test]
fn test_DRYRUN_COV_service_restart() {
let op = ServiceOperation::Restart {
name: "nginx".to_string(),
};
assert_eq!(op.to_diff_line(), "~ systemctl restart nginx");
}
#[test]
fn test_DRYRUN_COV_service_enable() {
let op = ServiceOperation::Enable {
name: "docker".to_string(),
};
assert_eq!(op.to_diff_line(), "+ systemctl enable docker");
}
#[test]
fn test_DRYRUN_COV_service_start() {
let op = ServiceOperation::Start {
name: "redis".to_string(),
};
assert_eq!(op.to_diff_line(), "+ systemctl start redis");
}
#[test]
fn test_DRYRUN_COV_remove_from_group() {
let op = UserGroupOperation::RemoveFromGroup {
user: "alice".to_string(),
group: "sudo".to_string(),
};
assert_eq!(op.to_diff_line(), "- gpasswd -d alice sudo");
}
#[test]
fn test_DRYRUN_COV_create_user_no_groups() {
let op = UserGroupOperation::CreateUser {
name: "deploy".to_string(),
groups: vec![],
};
assert_eq!(op.to_diff_line(), "+ useradd deploy");
}
#[test]
fn test_DRYRUN_COV_create_user_with_groups() {
let op = UserGroupOperation::CreateUser {
name: "deploy".to_string(),
groups: vec!["docker".to_string(), "www-data".to_string()],
};
assert_eq!(op.to_diff_line(), "+ useradd -G docker,www-data deploy");
}
#[test]
fn test_DRYRUN_COV_create_group() {
let op = UserGroupOperation::CreateGroup {
name: "myapp".to_string(),
};
assert_eq!(op.to_diff_line(), "+ groupadd myapp");
}
#[test]
fn test_DRYRUN_COV_add_to_group() {
let op = UserGroupOperation::AddToGroup {
user: "bob".to_string(),
group: "staff".to_string(),
};
assert_eq!(op.to_diff_line(), "+ usermod -aG staff bob");
}
#[test]
fn test_DRYRUN_COV_simulate_file_modify() {
let mut ctx = DryRunContext::new();
ctx.simulate_file_modify("/etc/config.yml", "old: val\n", "new: val\n");
let summary = ctx.summary();
assert_eq!(summary.files_modified, 1);
assert_eq!(summary.files_created, 0);
}
#[test]
fn test_DRYRUN_COV_simulate_file_delete() {
let mut ctx = DryRunContext::new();
ctx.simulate_file_delete("/tmp/trash.txt", "garbage\n");
let summary = ctx.summary();
assert_eq!(summary.files_deleted, 1);
}
#[test]
fn test_DRYRUN_COV_simulate_service_start() {
let mut ctx = DryRunContext::new();
ctx.simulate_service_start("postgres");
let ops = ctx.service_operations();
assert_eq!(ops.len(), 1);
assert!(matches!(&ops[0], ServiceOperation::Start { name } if name == "postgres"));
}
#[test]
fn test_DRYRUN_COV_file_changes_iterator() {
let mut ctx = DryRunContext::new();
ctx.simulate_file_write("/a.txt", "a", None);
ctx.simulate_file_write("/b.txt", "b", None);
let changes: Vec<_> = ctx.file_changes().collect();
assert_eq!(changes.len(), 2);
}
#[test]
fn test_DRYRUN_COV_package_operations_accessor() {
let mut ctx = DryRunContext::new();
ctx.simulate_package_install("pkg1", Some("1.0"));
ctx.simulate_package_install("pkg2", None);
ctx.simulate_package_remove("old-pkg");
let ops = ctx.package_operations();
assert_eq!(ops.len(), 3);
}
#[test]
fn test_DRYRUN_COV_user_group_operations_accessor() {
let mut ctx = DryRunContext::new();
ctx.simulate_add_to_group("user1", "group1");
ctx.simulate_add_to_group("user2", "group2");
let ops = ctx.user_group_operations();
assert_eq!(ops.len(), 2);
}
#[test]
fn test_DRYRUN_COV_summary_has_changes_true_from_packages() {
let summary = DryRunSummary {
packages_installed: 1,
..Default::default()
};
assert!(summary.has_changes());
}
#[test]
include!("dry_run_tests_tests_DRYRUN.rs");