use rpki::data_model::manifest::ManifestObject; use rpki::data_model::rc::{AsIdOrRange, AsIdentifierChoice, AsResourceSet, ResourceCertificate}; use rpki::data_model::ta::{TaCertificate, TaCertificateParsed, TaCertificateProfileError}; use rpki::data_model::tal::{Tal, TalDecodeError, TalProfileError}; use rpki::data_model::roa::{IpPrefix, RoaAfi}; #[test] fn tal_validate_profile_noop_is_callable() { let raw = std::fs::read("tests/fixtures/tal/apnic-rfc7730-https.tal").expect("read tal"); let tal = Tal::decode_bytes(&raw).expect("decode tal"); tal.validate_profile().expect("validate_profile is no-op"); } #[test] fn tal_invalid_uri_after_valid_uri_is_reported_as_missing_separator() { let s = "https://example.invalid/ta.cer\nnot a url\n\nAQ==\n"; assert!(matches!( Tal::decode_bytes(s.as_bytes()), Err(TalDecodeError::Validate( TalProfileError::MissingSeparatorEmptyLine )) )); } #[test] fn tal_missing_separator_empty_line_is_rejected() { let s = "https://example.invalid/ta.cer\nAQ==\n"; assert!(matches!( Tal::decode_bytes(s.as_bytes()), Err(TalDecodeError::Validate( TalProfileError::MissingSeparatorEmptyLine )) )); } #[test] fn tal_missing_spki_is_rejected() { let s = "https://example.invalid/ta.cer\n\n\n"; assert!(matches!( Tal::decode_bytes(s.as_bytes()), Err(TalDecodeError::Validate(TalProfileError::MissingSpki)) )); } #[test] fn tal_missing_separator_due_to_eof_is_rejected() { // One URI and then EOF: should fail at the mandatory empty-line separator check. let s = "https://example.invalid/ta.cer"; assert!(matches!( Tal::decode_bytes(s.as_bytes()), Err(TalDecodeError::Validate( TalProfileError::MissingSeparatorEmptyLine )) )); } #[test] fn ta_validate_profile_noop_is_callable() { let der = std::fs::read("tests/fixtures/ta/apnic-ta.cer").expect("read ta"); let ta = TaCertificate::decode_der(&der).expect("decode ta"); ta.validate_profile().expect("validate_profile is no-op"); } #[test] fn ta_parsed_validate_profile_rejects_ee_resource_certificate() { // Extract an embedded EE certificate from a real manifest fixture and feed it into the TA // profile validator to hit the `NotCa` branch in `TaCertificateParsed::validate_profile`. let mft_der = std::fs::read( "tests/fixtures/repository/ca.rg.net/rpki/RGnet-OU/bW-_qXU9uNhGQz21NR2ansB8lr0.mft", ) .expect("read manifest fixture"); let mft = ManifestObject::decode_der(&mft_der).expect("decode manifest"); let ee_der = mft.signed_object.signed_data.certificates[0] .resource_cert .raw_der .clone(); let rc_parsed = ResourceCertificate::parse_der(&ee_der).expect("parse embedded EE cert"); let ta_parsed = TaCertificateParsed { rc_parsed }; let err = ta_parsed.validate_profile().unwrap_err(); assert!(matches!(err, TaCertificateProfileError::NotCa)); } #[test] fn ta_rc_constraints_exercise_rdi_non_empty_branch() { let der = std::fs::read("tests/fixtures/ta/apnic-ta.cer").expect("read ta"); let ta = TaCertificate::decode_der(&der).expect("decode ta"); let mut rc = ta.rc_ca.clone(); rc.tbs.extensions.as_resources = Some(AsResourceSet { asnum: rc .tbs .extensions .as_resources .as_ref() .and_then(|v| v.asnum.clone()), rdi: Some(AsIdentifierChoice::AsIdsOrRanges(vec![AsIdOrRange::Id( 64496, )])), }); TaCertificate::validate_rc_constraints(&rc).expect("constraints should still pass"); } #[test] fn audit_helpers_format_roa_ip_prefix_smoke() { let v4 = IpPrefix { afi: RoaAfi::Ipv4, prefix_len: 24, addr: vec![192, 0, 2, 0], }; assert_eq!(rpki::audit::format_roa_ip_prefix(&v4), "192.0.2.0/24"); let v6 = IpPrefix { afi: RoaAfi::Ipv6, prefix_len: 32, addr: vec![0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; assert!(rpki::audit::format_roa_ip_prefix(&v6).ends_with("/32")); let bad = IpPrefix { afi: RoaAfi::Ipv4, prefix_len: 8, addr: vec![1, 2, 3], }; assert!(rpki::audit::format_roa_ip_prefix(&bad).starts_with("ipv4:")); } #[test] fn audit_helpers_sha256_hex_smoke() { let h = rpki::audit::sha256_hex(b"abc"); assert_eq!(h.len(), 64); let bytes = [0x11u8; 32]; let h2 = rpki::audit::sha256_hex_from_32(&bytes); assert_eq!(h2, "11".repeat(32)); }