rpki/tests/test_cir_wrapper_m6.rs

191 lines
7.0 KiB
Rust

use std::path::PathBuf;
use std::process::Command;
use std::os::unix::fs::MetadataExt;
fn wrapper_path() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("scripts/cir/cir-rsync-wrapper")
}
fn real_rsync() -> Option<String> {
let candidate = "/usr/bin/rsync";
if std::path::Path::new(candidate).exists() {
return Some(candidate.to_string());
}
None
}
#[test]
fn cir_rsync_wrapper_passes_through_help() {
let Some(real) = real_rsync() else {
return;
};
let out = Command::new(wrapper_path())
.env("REAL_RSYNC_BIN", real)
.arg("-h")
.output()
.expect("run wrapper -h");
assert!(out.status.success(), "stderr={}", String::from_utf8_lossy(&out.stderr));
let stdout = String::from_utf8_lossy(&out.stdout);
let stderr = String::from_utf8_lossy(&out.stderr);
assert!(stdout.contains("rsync") || stderr.contains("rsync"));
}
#[test]
fn cir_rsync_wrapper_rewrites_rsync_source_to_mirror_tree() {
let Some(real) = real_rsync() else {
return;
};
let td = tempfile::tempdir().expect("tempdir");
let mirror_root = td.path().join("mirror");
let dest_root = td.path().join("dest");
let repo_root = mirror_root.join("example.net").join("repo");
std::fs::create_dir_all(repo_root.join("nested")).expect("mkdirs");
std::fs::write(repo_root.join("a.roa"), b"roa").expect("write roa");
std::fs::write(repo_root.join("nested").join("b.txt"), b"txt").expect("write txt");
std::fs::create_dir_all(&dest_root).expect("mkdir dest");
let out = Command::new(wrapper_path())
.env("REAL_RSYNC_BIN", real)
.env("CIR_MIRROR_ROOT", &mirror_root)
.args([
"-rt",
"--address",
"127.0.0.1",
"--contimeout=10",
"--include=*/",
"--include=*.roa",
"--exclude=*",
"rsync://example.net/repo/",
dest_root.to_string_lossy().as_ref(),
])
.output()
.expect("run wrapper rewrite");
assert!(out.status.success(), "stderr={}", String::from_utf8_lossy(&out.stderr));
assert_eq!(std::fs::read(dest_root.join("a.roa")).expect("read copied roa"), b"roa");
assert!(!dest_root.join("nested").join("b.txt").exists());
}
#[test]
fn cir_rsync_wrapper_rewrites_module_root_without_trailing_slash_as_contents() {
let Some(real) = real_rsync() else {
return;
};
let td = tempfile::tempdir().expect("tempdir");
let mirror_root = td.path().join("mirror");
let dest_root = td.path().join("dest");
let repo_root = mirror_root.join("example.net").join("repo");
std::fs::create_dir_all(repo_root.join("sub")).expect("mkdirs");
std::fs::write(repo_root.join("root.cer"), b"cer").expect("write cer");
std::fs::write(repo_root.join("sub").join("child.roa"), b"roa").expect("write roa");
std::fs::create_dir_all(&dest_root).expect("mkdir dest");
let out = Command::new(wrapper_path())
.env("REAL_RSYNC_BIN", real)
.env("CIR_MIRROR_ROOT", &mirror_root)
.args([
"-rt",
"--include=*/",
"--include=*.cer",
"--include=*.roa",
"--exclude=*",
"rsync://example.net/repo",
dest_root.to_string_lossy().as_ref(),
])
.output()
.expect("run wrapper rewrite");
assert!(out.status.success(), "stderr={}", String::from_utf8_lossy(&out.stderr));
assert_eq!(std::fs::read(dest_root.join("root.cer")).expect("read copied root cer"), b"cer");
assert_eq!(
std::fs::read(dest_root.join("sub").join("child.roa")).expect("read copied child roa"),
b"roa"
);
assert!(!dest_root.join("repo").exists(), "module root must not be nested under destination");
}
#[test]
fn cir_rsync_wrapper_requires_mirror_root_for_rsync_source() {
let Some(real) = real_rsync() else {
return;
};
let td = tempfile::tempdir().expect("tempdir");
let dest_root = td.path().join("dest");
std::fs::create_dir_all(&dest_root).expect("mkdir dest");
let out = Command::new(wrapper_path())
.env("REAL_RSYNC_BIN", real)
.args(["-rt", "rsync://example.net/repo/", dest_root.to_string_lossy().as_ref()])
.output()
.expect("run wrapper missing env");
assert!(!out.status.success());
assert!(String::from_utf8_lossy(&out.stderr).contains("CIR_MIRROR_ROOT"));
}
#[test]
fn cir_rsync_wrapper_leaves_local_source_untouched() {
let Some(real) = real_rsync() else {
return;
};
let td = tempfile::tempdir().expect("tempdir");
let src_root = td.path().join("src");
let dest_root = td.path().join("dest");
std::fs::create_dir_all(&src_root).expect("mkdir src");
std::fs::create_dir_all(&dest_root).expect("mkdir dest");
std::fs::write(src_root.join("x.cer"), b"x").expect("write source");
let out = Command::new(wrapper_path())
.env("REAL_RSYNC_BIN", real)
.args([
"-rt",
src_root.to_string_lossy().as_ref(),
dest_root.to_string_lossy().as_ref(),
])
.output()
.expect("run wrapper local passthrough");
assert!(out.status.success(), "stderr={}", String::from_utf8_lossy(&out.stderr));
assert_eq!(std::fs::read(dest_root.join("src").join("x.cer")).expect("read copied file"), b"x");
}
#[test]
fn cir_rsync_wrapper_local_link_mode_uses_hardlinks_for_rewritten_sources() {
let Some(real) = real_rsync() else {
return;
};
let td = tempfile::tempdir().expect("tempdir");
let mirror_root = td.path().join("mirror");
let dest_root = td.path().join("dest");
let repo_root = mirror_root.join("example.net").join("repo");
std::fs::create_dir_all(repo_root.join("nested")).expect("mkdirs");
let src_file = repo_root.join("a.roa");
let src_nested = repo_root.join("nested").join("b.cer");
std::fs::write(&src_file, b"roa").expect("write roa");
std::fs::write(&src_nested, b"cer").expect("write cer");
std::fs::create_dir_all(&dest_root).expect("mkdir dest");
let out = Command::new(wrapper_path())
.env("REAL_RSYNC_BIN", real)
.env("CIR_MIRROR_ROOT", &mirror_root)
.env("CIR_LOCAL_LINK_MODE", "1")
.args([
"-rt",
"--delete",
"--include=*/",
"--include=*.roa",
"--include=*.cer",
"--exclude=*",
"rsync://example.net/repo/",
dest_root.to_string_lossy().as_ref(),
])
.output()
.expect("run wrapper local-link mode");
assert!(out.status.success(), "stderr={}", String::from_utf8_lossy(&out.stderr));
let dst_file = dest_root.join("a.roa");
let dst_nested = dest_root.join("nested").join("b.cer");
assert_eq!(std::fs::read(&dst_file).expect("read dest roa"), b"roa");
assert_eq!(std::fs::read(&dst_nested).expect("read dest cer"), b"cer");
let src_meta = std::fs::metadata(&src_file).expect("src metadata");
let dst_meta = std::fs::metadata(&dst_file).expect("dst metadata");
assert_eq!(src_meta.ino(), dst_meta.ino(), "expected hardlinked destination file");
}