test(08-01): add directory round-trip integration tests
- test_roundtrip_directory: full directory tree with permissions verification - test_roundtrip_mixed_files_and_dirs: mixed file + directory pack/unpack - test_inspect_shows_directory_info: inspect output contains dir/file types and permissions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,7 +5,9 @@
|
|||||||
//! All tests use `tempdir()` for isolation (auto-cleanup, parallel-safe).
|
//! All tests use `tempdir()` for isolation (auto-cleanup, parallel-safe).
|
||||||
|
|
||||||
use assert_cmd::Command;
|
use assert_cmd::Command;
|
||||||
|
use predicates::prelude::*;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
use std::os::unix::fs::PermissionsExt;
|
||||||
use tempfile::tempdir;
|
use tempfile::tempdir;
|
||||||
|
|
||||||
/// Helper: get a Command for the encrypted_archive binary.
|
/// Helper: get a Command for the encrypted_archive binary.
|
||||||
@@ -190,3 +192,136 @@ fn test_roundtrip_no_compress_flag() {
|
|||||||
let extracted = fs::read(output_dir.join("data.apk")).unwrap();
|
let extracted = fs::read(output_dir.join("data.apk")).unwrap();
|
||||||
assert_eq!(extracted, data);
|
assert_eq!(extracted, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Directory round-trip: pack a directory tree, unpack, verify files, empty dirs, and permissions.
|
||||||
|
#[test]
|
||||||
|
fn test_roundtrip_directory() {
|
||||||
|
let dir = tempdir().unwrap();
|
||||||
|
let testdir = dir.path().join("testdir");
|
||||||
|
let subdir = testdir.join("subdir");
|
||||||
|
let emptydir = testdir.join("empty");
|
||||||
|
let archive = dir.path().join("archive.bin");
|
||||||
|
let output_dir = dir.path().join("output");
|
||||||
|
|
||||||
|
// Create directory structure
|
||||||
|
fs::create_dir_all(&subdir).unwrap();
|
||||||
|
fs::create_dir_all(&emptydir).unwrap();
|
||||||
|
|
||||||
|
fs::write(testdir.join("hello.txt"), b"Hello from dir").unwrap();
|
||||||
|
fs::write(subdir.join("nested.txt"), b"Nested file").unwrap();
|
||||||
|
|
||||||
|
// Set specific permissions
|
||||||
|
fs::set_permissions(&testdir, fs::Permissions::from_mode(0o755)).unwrap();
|
||||||
|
fs::set_permissions(testdir.join("hello.txt"), fs::Permissions::from_mode(0o644)).unwrap();
|
||||||
|
fs::set_permissions(&subdir, fs::Permissions::from_mode(0o755)).unwrap();
|
||||||
|
fs::set_permissions(subdir.join("nested.txt"), fs::Permissions::from_mode(0o755)).unwrap();
|
||||||
|
fs::set_permissions(&emptydir, fs::Permissions::from_mode(0o700)).unwrap();
|
||||||
|
|
||||||
|
// Pack directory
|
||||||
|
cmd()
|
||||||
|
.args(["pack", testdir.to_str().unwrap(), "-o", archive.to_str().unwrap()])
|
||||||
|
.assert()
|
||||||
|
.success();
|
||||||
|
|
||||||
|
// Unpack
|
||||||
|
cmd()
|
||||||
|
.args(["unpack", archive.to_str().unwrap(), "-o", output_dir.to_str().unwrap()])
|
||||||
|
.assert()
|
||||||
|
.success();
|
||||||
|
|
||||||
|
// Verify file contents
|
||||||
|
let hello = fs::read(output_dir.join("testdir/hello.txt")).unwrap();
|
||||||
|
assert_eq!(hello, b"Hello from dir");
|
||||||
|
|
||||||
|
let nested = fs::read(output_dir.join("testdir/subdir/nested.txt")).unwrap();
|
||||||
|
assert_eq!(nested, b"Nested file");
|
||||||
|
|
||||||
|
// Verify empty directory exists
|
||||||
|
assert!(
|
||||||
|
output_dir.join("testdir/empty").is_dir(),
|
||||||
|
"Empty directory should be recreated"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Verify permissions
|
||||||
|
let nested_mode = fs::metadata(output_dir.join("testdir/subdir/nested.txt"))
|
||||||
|
.unwrap()
|
||||||
|
.permissions()
|
||||||
|
.mode()
|
||||||
|
& 0o7777;
|
||||||
|
assert_eq!(nested_mode, 0o755, "nested.txt should have mode 0755");
|
||||||
|
|
||||||
|
let empty_mode = fs::metadata(output_dir.join("testdir/empty"))
|
||||||
|
.unwrap()
|
||||||
|
.permissions()
|
||||||
|
.mode()
|
||||||
|
& 0o7777;
|
||||||
|
assert_eq!(empty_mode, 0o700, "empty dir should have mode 0700");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Mixed files and directories: pack both a standalone file and a directory, verify round-trip.
|
||||||
|
#[test]
|
||||||
|
fn test_roundtrip_mixed_files_and_dirs() {
|
||||||
|
let dir = tempdir().unwrap();
|
||||||
|
let standalone = dir.path().join("standalone.txt");
|
||||||
|
let mydir = dir.path().join("mydir");
|
||||||
|
let archive = dir.path().join("archive.bin");
|
||||||
|
let output_dir = dir.path().join("output");
|
||||||
|
|
||||||
|
fs::write(&standalone, b"Standalone").unwrap();
|
||||||
|
fs::create_dir_all(&mydir).unwrap();
|
||||||
|
fs::write(mydir.join("inner.txt"), b"Inner").unwrap();
|
||||||
|
|
||||||
|
// Pack both file and directory
|
||||||
|
cmd()
|
||||||
|
.args([
|
||||||
|
"pack",
|
||||||
|
standalone.to_str().unwrap(),
|
||||||
|
mydir.to_str().unwrap(),
|
||||||
|
"-o",
|
||||||
|
archive.to_str().unwrap(),
|
||||||
|
])
|
||||||
|
.assert()
|
||||||
|
.success();
|
||||||
|
|
||||||
|
// Unpack
|
||||||
|
cmd()
|
||||||
|
.args(["unpack", archive.to_str().unwrap(), "-o", output_dir.to_str().unwrap()])
|
||||||
|
.assert()
|
||||||
|
.success();
|
||||||
|
|
||||||
|
// Verify both entries
|
||||||
|
assert_eq!(
|
||||||
|
fs::read(output_dir.join("standalone.txt")).unwrap(),
|
||||||
|
b"Standalone"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
fs::read(output_dir.join("mydir/inner.txt")).unwrap(),
|
||||||
|
b"Inner"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Inspect shows directory info: entry type and permissions for directory entries.
|
||||||
|
#[test]
|
||||||
|
fn test_inspect_shows_directory_info() {
|
||||||
|
let dir = tempdir().unwrap();
|
||||||
|
let testdir = dir.path().join("testdir");
|
||||||
|
let archive = dir.path().join("archive.bin");
|
||||||
|
|
||||||
|
fs::create_dir_all(&testdir).unwrap();
|
||||||
|
fs::write(testdir.join("file.txt"), b"content").unwrap();
|
||||||
|
|
||||||
|
cmd()
|
||||||
|
.args(["pack", testdir.to_str().unwrap(), "-o", archive.to_str().unwrap()])
|
||||||
|
.assert()
|
||||||
|
.success();
|
||||||
|
|
||||||
|
// Inspect and check output contains directory info
|
||||||
|
cmd()
|
||||||
|
.args(["inspect", archive.to_str().unwrap()])
|
||||||
|
.assert()
|
||||||
|
.success()
|
||||||
|
.stdout(predicate::str::contains("dir"))
|
||||||
|
.stdout(predicate::str::contains("file"))
|
||||||
|
.stdout(predicate::str::contains("0755").or(predicate::str::contains("0775")))
|
||||||
|
.stdout(predicate::str::contains("Permissions:"));
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user