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")); }