rpki/tests/test_multi_rir_case_info.rs

191 lines
6.7 KiB
Rust

use std::fs;
use std::process::Command;
fn multi_rir_bundle_root() -> std::path::PathBuf {
std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("../../rpki/target/live/20260316-112341-multi-final3")
}
fn helper_script() -> std::path::PathBuf {
std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("scripts/payload_replay/multi_rir_case_info.py")
}
fn wrapper_script() -> std::path::PathBuf {
std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("scripts/payload_replay/run_multi_rir_replay_case.sh")
}
#[test]
fn multi_rir_case_info_resolves_all_five_rirs_and_timings() {
let bundle_root = multi_rir_bundle_root();
assert!(bundle_root.is_dir(), "bundle root missing: {}", bundle_root.display());
let expected = [
("afrinic", "afrinic", "afrinic.tal", "afrinic-ta.cer"),
("apnic", "apnic", "apnic-rfc7730-https.tal", "apnic-ta.cer"),
("arin", "arin", "arin.tal", "arin-ta.cer"),
("lacnic", "lacnic", "lacnic.tal", "lacnic-ta.cer"),
("ripe", "ripe", "ripe-ncc.tal", "ripe-ncc-ta.cer"),
];
for (rir, trust_anchor, tal_suffix, ta_suffix) in expected {
let out = Command::new("python3")
.arg(helper_script())
.args([
"--bundle-root",
bundle_root.to_string_lossy().as_ref(),
"--rir",
rir,
])
.output()
.expect("run helper script");
assert!(
out.status.success(),
"helper failed for {rir}: status={}\nstdout={}\nstderr={}",
out.status,
String::from_utf8_lossy(&out.stdout),
String::from_utf8_lossy(&out.stderr)
);
let json: serde_json::Value =
serde_json::from_slice(&out.stdout).expect("parse helper json");
assert_eq!(json["rir"].as_str(), Some(rir));
assert_eq!(json["trust_anchor"].as_str(), Some(trust_anchor));
assert!(json["base_archive"].as_str().unwrap_or("").ends_with("base-payload-archive"));
assert!(json["delta_archive"].as_str().unwrap_or("").ends_with("payload-delta-archive"));
assert!(json["base_locks"].as_str().unwrap_or("").ends_with("base-locks.json"));
assert!(json["delta_locks"].as_str().unwrap_or("").ends_with("locks-delta.json"));
assert!(json["tal_path"].as_str().unwrap_or("").ends_with(tal_suffix));
assert!(json["ta_path"].as_str().unwrap_or("").ends_with(ta_suffix));
assert!(json["validation_times"]["snapshot"].as_str().unwrap_or("").contains("T"));
assert!(json["validation_times"]["delta"].as_str().unwrap_or("").contains("T"));
assert!(json["routinator_timings"]["base_replay_seconds"]
.as_f64()
.unwrap_or(0.0)
> 0.0);
assert!(json["routinator_timings"]["delta_replay_seconds"]
.as_f64()
.unwrap_or(0.0)
> 0.0);
}
}
#[test]
fn multi_rir_case_info_prefers_lock_validation_time_over_replay_started_at() {
let td = tempfile::tempdir().expect("tempdir");
let bundle_root = td.path();
let rir_root = bundle_root.join("apnic");
fs::create_dir_all(rir_root.join("base-payload-archive")).expect("base archive dir");
fs::create_dir_all(rir_root.join("payload-delta-archive")).expect("delta archive dir");
fs::create_dir_all(rir_root.join("timings")).expect("timings dir");
fs::write(
bundle_root.join("timing-summary.json"),
r#"{"apnic":{"durations":{"base-replay":1.5,"delta-replay":2.5}}}"#,
)
.expect("write timing summary");
fs::write(
rir_root.join("base-locks.json"),
r#"{"version":1,"capture":"base-cap","validationTime":"2026-03-16T11:49:15+08:00","rrdp":{},"rsync":{}}"#,
)
.expect("write base locks");
fs::write(
rir_root.join("locks-delta.json"),
r#"{"version":1,"capture":"delta-cap","baseCapture":"base-cap","baseLocksSha256":"deadbeef","validationTime":"2026-03-16T12:14:10+08:00","rrdp":{},"rsync":{}}"#,
)
.expect("write delta locks");
fs::write(
rir_root.join("timings/base-replay.json"),
r#"{"startedAt":"2099-01-01T00:00:00Z","durationSeconds":1.5}"#,
)
.expect("write base timing");
fs::write(
rir_root.join("timings/delta-replay.json"),
r#"{"startedAt":"2099-01-02T00:00:00Z","durationSeconds":2.5}"#,
)
.expect("write delta timing");
for rel in [
"base-vrps.csv",
"record-delta.csv",
"replay-delta.csv",
"verification.json",
"README.md",
] {
fs::write(rir_root.join(rel), "placeholder
").expect("write required file");
}
let repo_root = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
let out = Command::new("python3")
.arg(helper_script())
.args([
"--bundle-root",
bundle_root.to_string_lossy().as_ref(),
"--repo-root",
repo_root.to_string_lossy().as_ref(),
"--rir",
"apnic",
])
.output()
.expect("run helper script");
assert!(
out.status.success(),
"helper failed: status={}
stdout={}
stderr={}",
out.status,
String::from_utf8_lossy(&out.stdout),
String::from_utf8_lossy(&out.stderr)
);
let json: serde_json::Value = serde_json::from_slice(&out.stdout).expect("parse helper json");
assert_eq!(
json["validation_times"]["snapshot"].as_str(),
Some("2026-03-16T11:49:15+08:00")
);
assert_eq!(
json["validation_times"]["delta"].as_str(),
Some("2026-03-16T12:14:10+08:00")
);
assert_eq!(
json["timing_started_at"]["snapshot_replay"].as_str(),
Some("2099-01-01T00:00:00Z")
);
assert_eq!(
json["timing_started_at"]["delta_replay"].as_str(),
Some("2099-01-02T00:00:00Z")
);
}
#[test]
fn multi_rir_wrapper_describe_mode_works_for_ripe() {
let bundle_root = multi_rir_bundle_root();
assert!(bundle_root.is_dir(), "bundle root missing: {}", bundle_root.display());
let out = Command::new(wrapper_script())
.env("BUNDLE_ROOT", &bundle_root)
.args(["ripe", "describe"])
.output()
.expect("run wrapper script");
assert!(
out.status.success(),
"wrapper failed: status={}\nstdout={}\nstderr={}",
out.status,
String::from_utf8_lossy(&out.stdout),
String::from_utf8_lossy(&out.stderr)
);
let json: serde_json::Value =
serde_json::from_slice(&out.stdout).expect("parse wrapper describe json");
assert_eq!(json["rir"].as_str(), Some("ripe"));
assert_eq!(json["trust_anchor"].as_str(), Some("ripe"));
assert!(json["verification_json"]
.as_str()
.unwrap_or("")
.ends_with("verification.json"));
}