ic-backup 0.3.1

Host-side snapshot backup and same-release recovery for Internet Computer canisters
Documentation
use super::*;
use crate::test_support::temp_path;
use std::fs;

#[cfg(unix)]
#[test]
fn staging_preserves_exact_bytes_checksums_and_private_permissions() {
    use std::os::unix::fs::PermissionsExt;
    let root = temp_path("ic-backup-stage");
    fs::create_dir_all(root.join("source/nested")).expect("create source");
    fs::write(root.join("source/nested/state.bin"), b"state bytes").expect("write source");
    let destination = root.join("staged");
    let expected = checksum_directory(&root.join("source")).expect("source checksum");
    let actual = stage_relative_path(&root, Path::new("source"), &destination).expect("stage tree");
    assert_eq!(actual, expected);
    assert_eq!(
        fs::read(destination.join("nested/state.bin")).expect("staged bytes"),
        b"state bytes"
    );
    assert_eq!(
        fs::metadata(&destination)
            .expect("directory permissions")
            .permissions()
            .mode()
            & 0o777,
        0o700
    );
    assert_eq!(
        fs::metadata(destination.join("nested/state.bin"))
            .expect("file permissions")
            .permissions()
            .mode()
            & 0o777,
        0o600
    );
    assert!(
        matches!(stage_relative_path(&root, Path::new("source"), &destination), Err(ArtifactError::Io(ref error)) if error.kind() == io::ErrorKind::AlreadyExists)
    );
    let escaped = root.join("escaped");
    assert!(matches!(
        stage_relative_path(&root, Path::new("../source"), &escaped),
        Err(ArtifactError::UnsupportedEntry { .. })
    ));
    assert!(!escaped.exists());
    assert_eq!(
        checksum_relative_path(&root, Path::new("source")).expect("relative checksum"),
        expected
    );
    fs::remove_dir_all(root).expect("remove successful fixture");
}

#[cfg(unix)]
#[test]
fn non_utf8_tree_names_reject_instead_of_collapsing_path_identity() {
    use std::{ffi::OsStr, os::unix::ffi::OsStrExt};
    let root = temp_path("ic-backup-non-utf8");
    fs::create_dir(&root).expect("create tree");
    fs::write(root.join(OsStr::from_bytes(b"\xff")), b"bytes").expect("write non UTF-8 name");
    assert!(matches!(
        checksum_directory(&root),
        Err(ArtifactError::NonUtf8Path { .. })
    ));
    fs::remove_dir_all(root).expect("remove successful fixture");
}