use crate::common::*;
use std::process::Command;
#[test]
fn packing_the_filesystem_root_is_a_usage_error_that_says_why() {
let dir = tmp_dir();
let out = dir.join("root.tar");
let st = Command::new(STUFFR)
.args(["pack", "/", "-o", out.to_str().unwrap()])
.output()
.unwrap();
assert_eq!(
st.status.code(),
Some(2),
"packing `/` is the caller's mistake, not an i/o failure; stderr: {}",
String::from_utf8_lossy(&st.stderr)
);
let stderr = String::from_utf8_lossy(&st.stderr);
assert!(
stderr.contains("no final path component"),
"the message must say what is wrong with `/`: {stderr}"
);
assert!(
!out.exists(),
"the refusal happens before the destination is opened"
);
}
#[test]
fn a_nonexistent_dotdot_path_is_reported_as_an_io_error() {
let dir = tmp_dir();
let out = dir.join("dd.tar");
let missing = dir.join("nosuch/..");
let st = Command::new(STUFFR)
.args([
"pack",
missing.to_str().unwrap(),
"-o",
out.to_str().unwrap(),
])
.output()
.unwrap();
assert_eq!(
st.status.code(),
Some(1),
"a path that does not exist is an i/o error, whatever its final component; \
stderr: {}",
String::from_utf8_lossy(&st.stderr)
);
assert!(!out.exists());
}
#[cfg(unix)]
#[test]
fn pack_of_dot_from_a_symlinked_directory_names_entries_after_the_real_one() {
let dir = tmp_dir();
std::fs::create_dir_all(dir.join("real/src")).unwrap();
std::fs::write(dir.join("real/src/main.rs"), b"fn main() {}").unwrap();
std::os::unix::fs::symlink("real", dir.join("proj")).unwrap();
let out = dir.join("sym.tar");
let st = Command::new(STUFFR)
.current_dir(dir.join("proj"))
.args(["pack", ".", "-o", out.to_str().unwrap()])
.output()
.unwrap();
assert!(
st.status.success(),
"stderr: {}",
String::from_utf8_lossy(&st.stderr)
);
let listed = run_output(&["list", out.to_str().unwrap()]);
let text = String::from_utf8_lossy(&listed.stdout);
assert!(
text.contains("real/src/main.rs"),
"`.` resolves through the symlink, so entries sit under the real directory's \
name: {text}"
);
assert!(
!text.contains("proj/"),
"nothing may be named after the link itself: {text}"
);
}