use std::collections::HashMap; use rpki::data_model::tal::Tal; use rpki::sync::rrdp::Fetcher; use rpki::validation::from_tal::{FromTalError, discover_root_ca_instance_from_tal_url}; #[derive(Default)] struct MapFetcher { map: HashMap, String>>, } impl Fetcher for MapFetcher { fn fetch(&self, uri: &str) -> Result, String> { self.map .get(uri) .cloned() .unwrap_or_else(|| Err(format!("no fixture for uri: {uri}"))) } } #[test] fn discover_root_ca_instance_from_tal_url_succeeds_with_apnic_fixtures() { let tal_url = "https://example.test/apnic.tal"; let tal_bytes = std::fs::read("tests/fixtures/tal/apnic-rfc7730-https.tal").expect("read tal fixture"); let tal = Tal::decode_bytes(&tal_bytes).expect("decode tal fixture"); let ta_der = std::fs::read("tests/fixtures/ta/apnic-ta.cer").expect("read ta fixture"); let mut fetcher = MapFetcher::default(); fetcher .map .insert(tal_url.to_string(), Ok(tal_bytes.clone())); for u in &tal.ta_uris { fetcher.map.insert(u.as_str().to_string(), Ok(ta_der.clone())); } let out = discover_root_ca_instance_from_tal_url(&fetcher, tal_url).expect("discover root"); assert_eq!(out.tal_url.as_deref(), Some(tal_url)); assert!(!out.ca_instance.rsync_base_uri.is_empty()); assert!(!out.ca_instance.manifest_rsync_uri.is_empty()); assert!(!out.ca_instance.publication_point_rsync_uri.is_empty()); } #[test] fn discover_root_ca_instance_from_tal_url_returns_ta_fetch_error_when_all_candidates_fail() { let tal_url = "https://example.test/apnic.tal"; let tal_bytes = std::fs::read("tests/fixtures/tal/apnic-rfc7730-https.tal").expect("read tal fixture"); let tal = Tal::decode_bytes(&tal_bytes).expect("decode tal fixture"); let mut fetcher = MapFetcher::default(); fetcher .map .insert(tal_url.to_string(), Ok(tal_bytes)); for u in &tal.ta_uris { fetcher.map.insert( u.as_str().to_string(), Err("simulated TA fetch failure".to_string()), ); } let err = discover_root_ca_instance_from_tal_url(&fetcher, tal_url).unwrap_err(); match err { FromTalError::TaFetch(s) => { assert!(s.contains("fetch"), "{s}"); } other => panic!("unexpected error: {other}"), } }