增加 payload replay for snapshot,20260313 迭代
This commit is contained in:
@@ -170,6 +170,7 @@ fn apnic_tree_full_stats_serial() {
|
||||
validation_time,
|
||||
timing: None,
|
||||
download_log: None,
|
||||
replay_archive_index: None,
|
||||
rrdp_dedup: true,
|
||||
rrdp_repo_cache: std::sync::Mutex::new(std::collections::HashMap::new()),
|
||||
rsync_dedup: true,
|
||||
|
||||
69
tests/test_cli_payload_replay_smoke.rs
Normal file
69
tests/test_cli_payload_replay_smoke.rs
Normal file
@@ -0,0 +1,69 @@
|
||||
use std::process::Command;
|
||||
|
||||
#[test]
|
||||
fn cli_payload_replay_root_only_smoke_writes_report_json() {
|
||||
let bin = env!("CARGO_BIN_EXE_rpki");
|
||||
let db_dir = tempfile::tempdir().expect("db tempdir");
|
||||
let out_dir = tempfile::tempdir().expect("out tempdir");
|
||||
let report_path = out_dir.path().join("report.json");
|
||||
|
||||
let tal_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("tests/fixtures/tal/apnic-rfc7730-https.tal");
|
||||
let ta_path =
|
||||
std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/ta/apnic-ta.cer");
|
||||
let archive_root = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("target/live/payload_replay/payload-archive");
|
||||
let locks_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("target/live/payload_replay/locks.json");
|
||||
|
||||
assert!(
|
||||
archive_root.is_dir(),
|
||||
"payload replay archive missing: {}",
|
||||
archive_root.display()
|
||||
);
|
||||
assert!(
|
||||
locks_path.is_file(),
|
||||
"payload replay locks missing: {}",
|
||||
locks_path.display()
|
||||
);
|
||||
|
||||
let out = Command::new(bin)
|
||||
.args([
|
||||
"--db",
|
||||
db_dir.path().to_string_lossy().as_ref(),
|
||||
"--tal-path",
|
||||
tal_path.to_string_lossy().as_ref(),
|
||||
"--ta-path",
|
||||
ta_path.to_string_lossy().as_ref(),
|
||||
"--payload-replay-archive",
|
||||
archive_root.to_string_lossy().as_ref(),
|
||||
"--payload-replay-locks",
|
||||
locks_path.to_string_lossy().as_ref(),
|
||||
"--validation-time",
|
||||
"2026-03-13T02:30:00Z",
|
||||
"--max-depth",
|
||||
"0",
|
||||
"--max-instances",
|
||||
"1",
|
||||
"--report-json",
|
||||
report_path.to_string_lossy().as_ref(),
|
||||
])
|
||||
.output()
|
||||
.expect("run replay cli");
|
||||
|
||||
assert!(
|
||||
out.status.success(),
|
||||
"cli failed: status={}\nstdout={}\nstderr={}",
|
||||
out.status,
|
||||
String::from_utf8_lossy(&out.stdout),
|
||||
String::from_utf8_lossy(&out.stderr)
|
||||
);
|
||||
|
||||
let bytes = std::fs::read(&report_path).expect("read report json");
|
||||
let v: serde_json::Value = serde_json::from_slice(&bytes).expect("parse report json");
|
||||
assert_eq!(v["format_version"], 2);
|
||||
assert!(v["tree"]["instances_processed"].as_u64().unwrap_or(0) >= 1);
|
||||
assert!(v.get("publication_points").is_some());
|
||||
assert!(v.get("downloads").is_some());
|
||||
assert!(v.get("download_stats").is_some());
|
||||
}
|
||||
124
tests/test_payload_replay_tools.rs
Normal file
124
tests/test_payload_replay_tools.rs
Normal file
@@ -0,0 +1,124 @@
|
||||
use std::process::Command;
|
||||
|
||||
#[test]
|
||||
fn report_to_routinator_csv_exports_sorted_rows() {
|
||||
let dir = tempfile::tempdir().expect("tempdir");
|
||||
let report = dir.path().join("report.json");
|
||||
let out_csv = dir.path().join("vrps.csv");
|
||||
std::fs::write(
|
||||
&report,
|
||||
r#"{
|
||||
"format_version": 2,
|
||||
"meta": {"validation_time_rfc3339_utc": "2026-03-13T02:30:00Z"},
|
||||
"policy": {},
|
||||
"tree": {"instances_processed": 0, "instances_failed": 0, "warnings": []},
|
||||
"publication_points": [],
|
||||
"vrps": [
|
||||
{"asn": 64497, "prefix": "203.0.113.0/24", "max_length": 24},
|
||||
{"asn": 64496, "prefix": "192.0.2.0/24", "max_length": 24}
|
||||
],
|
||||
"aspas": [],
|
||||
"downloads": [],
|
||||
"download_stats": {"events_total": 0, "by_kind": {}}
|
||||
}"#,
|
||||
)
|
||||
.expect("write report");
|
||||
|
||||
let script = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("scripts/payload_replay/report_to_routinator_csv.py");
|
||||
let out = Command::new("python3")
|
||||
.arg(&script)
|
||||
.args([
|
||||
"--report",
|
||||
report.to_string_lossy().as_ref(),
|
||||
"--out",
|
||||
out_csv.to_string_lossy().as_ref(),
|
||||
"--trust-anchor",
|
||||
"apnic",
|
||||
])
|
||||
.output()
|
||||
.expect("run export script");
|
||||
|
||||
assert!(
|
||||
out.status.success(),
|
||||
"script failed: status={}\nstdout={}\nstderr={}",
|
||||
out.status,
|
||||
String::from_utf8_lossy(&out.stdout),
|
||||
String::from_utf8_lossy(&out.stderr)
|
||||
);
|
||||
|
||||
let csv = std::fs::read_to_string(&out_csv).expect("read csv");
|
||||
let lines: Vec<_> = csv.lines().collect();
|
||||
assert_eq!(lines[0], "ASN,IP Prefix,Max Length,Trust Anchor");
|
||||
assert_eq!(lines[1], "AS64496,192.0.2.0/24,24,apnic");
|
||||
assert_eq!(lines[2], "AS64497,203.0.113.0/24,24,apnic");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn compare_with_routinator_record_reports_diff_counts() {
|
||||
let dir = tempfile::tempdir().expect("tempdir");
|
||||
let ours = dir.path().join("ours.csv");
|
||||
let record = dir.path().join("record.csv");
|
||||
let summary = dir.path().join("summary.md");
|
||||
let only_ours = dir.path().join("only_ours.csv");
|
||||
let only_record = dir.path().join("only_record.csv");
|
||||
|
||||
std::fs::write(
|
||||
&ours,
|
||||
"ASN,IP Prefix,Max Length,Trust Anchor\nAS64496,192.0.2.0/24,24,apnic\nAS64497,198.51.100.0/24,24,apnic\n",
|
||||
)
|
||||
.expect("write ours csv");
|
||||
std::fs::write(
|
||||
&record,
|
||||
"ASN,IP Prefix,Max Length,Trust Anchor\nAS64496,192.0.2.0/24,24,apnic\nAS64498,203.0.113.0/24,24,apnic\n",
|
||||
)
|
||||
.expect("write record csv");
|
||||
|
||||
let script = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("scripts/payload_replay/compare_with_routinator_record.sh");
|
||||
let out = Command::new(&script)
|
||||
.args([
|
||||
ours.to_string_lossy().as_ref(),
|
||||
record.to_string_lossy().as_ref(),
|
||||
summary.to_string_lossy().as_ref(),
|
||||
only_ours.to_string_lossy().as_ref(),
|
||||
only_record.to_string_lossy().as_ref(),
|
||||
])
|
||||
.output()
|
||||
.expect("run compare script");
|
||||
|
||||
assert!(
|
||||
out.status.success(),
|
||||
"script failed: status={}\nstdout={}\nstderr={}",
|
||||
out.status,
|
||||
String::from_utf8_lossy(&out.stdout),
|
||||
String::from_utf8_lossy(&out.stderr)
|
||||
);
|
||||
|
||||
let summary_text = std::fs::read_to_string(&summary).expect("read summary");
|
||||
assert!(
|
||||
summary_text.contains("| ours_total | 2 |"),
|
||||
"{summary_text}"
|
||||
);
|
||||
assert!(
|
||||
summary_text.contains("| record_total | 2 |"),
|
||||
"{summary_text}"
|
||||
);
|
||||
assert!(
|
||||
summary_text.contains("| intersection | 1 |"),
|
||||
"{summary_text}"
|
||||
);
|
||||
assert!(
|
||||
summary_text.contains("| only_in_ours | 1 |"),
|
||||
"{summary_text}"
|
||||
);
|
||||
assert!(
|
||||
summary_text.contains("| only_in_record | 1 |"),
|
||||
"{summary_text}"
|
||||
);
|
||||
|
||||
let only_ours_text = std::fs::read_to_string(&only_ours).expect("read only ours csv");
|
||||
assert!(only_ours_text.contains("AS64497,198.51.100.0/24,24,apnic"));
|
||||
let only_record_text = std::fs::read_to_string(&only_record).expect("read only record csv");
|
||||
assert!(only_record_text.contains("AS64498,203.0.113.0/24,24,apnic"));
|
||||
}
|
||||
Reference in New Issue
Block a user