20260711 补充P1缓存与证书profile回归

This commit is contained in:
2026-07-12 07:15:32 +08:00
parent 1ce897dbff
commit 4a64fa7900
3 changed files with 272 additions and 0 deletions

View File

@@ -4346,6 +4346,58 @@ mod tests {
));
}
#[test]
fn roa_validation_cache_view_blocks_before_safe_reuse_time() {
let validation_time = fixed_time("2026-06-05T00:00:00Z");
let issuer_der = b"issuer-ca";
let crl_bytes = b"current-crl".to_vec();
let crl_hash = sha256_32(&crl_bytes);
let roa_hash = [0x11; 32];
let vcir = sample_roa_cache_vcir(
issuer_der,
crl_hash,
roa_hash,
fixed_time("2026-06-07T00:00:00Z"),
fixed_time("2026-06-08T00:00:00Z"),
);
let mut projection = sample_roa_cache_projection(&vcir, roa_hash);
projection.entries[0].earliest_safe_reuse_time_unix =
Some(fixed_time("2026-06-06T00:00:00Z").unix_timestamp());
let view = RoaValidationCacheView::from_projection(&projection, validation_time);
let file = PackFile::from_bytes_with_sha256(TEST_ROA_URI, vec![0x01], roa_hash);
let mut crl_cache = sample_crl_cache(crl_bytes);
assert!(matches!(
view.lookup(&file, &mut crl_cache, issuer_der, validation_time),
RoaCacheLookupResult::ExpiredBlocked
));
}
#[test]
fn roa_validation_cache_view_treats_legacy_entry_without_lower_bound_as_miss() {
let validation_time = fixed_time("2026-06-05T00:00:00Z");
let issuer_der = b"issuer-ca";
let crl_hash = sha256_32(b"current-crl");
let roa_hash = [0x11; 32];
let vcir = sample_roa_cache_vcir(
issuer_der,
crl_hash,
roa_hash,
fixed_time("2026-06-07T00:00:00Z"),
fixed_time("2026-06-08T00:00:00Z"),
);
let mut projection = sample_roa_cache_projection(&vcir, roa_hash);
projection.entries[0].earliest_safe_reuse_time_unix = None;
let view = RoaValidationCacheView::from_projection(&projection, validation_time);
let file = PackFile::from_bytes_with_sha256(TEST_ROA_URI, vec![0x01], roa_hash);
let mut crl_cache = sample_crl_cache(b"current-crl".to_vec());
assert!(matches!(
view.lookup(&file, &mut crl_cache, issuer_der, validation_time),
RoaCacheLookupResult::Miss
));
}
#[test]
fn roa_validation_cache_stats_records_vcir_miss_to_timing() {
let stats = RoaValidationCacheStats::for_input(RoaValidationCacheInput::enabled(None), 3);

View File

@@ -775,6 +775,22 @@ fn put_vcir_for_failed_fetch_reuse(
.expect("put reusable VCIR");
}
fn sample_ca_for_failed_fetch_reuse(vcir: &ValidatedCaInstanceResult) -> CaInstanceHandle {
CaInstanceHandle {
depth: 0,
tal_id: "test-tal".to_string(),
parent_manifest_rsync_uri: None,
ca_certificate: CaCertificateRef::inline_der(Vec::new()),
ca_certificate_rsync_uri: None,
effective_ip_resources: None,
effective_as_resources: None,
rsync_base_uri: "rsync://example.test/repo/issuer/".to_string(),
manifest_rsync_uri: vcir.manifest_rsync_uri.clone(),
publication_point_rsync_uri: "rsync://example.test/repo/issuer/".to_string(),
rrdp_notification_uri: Some("https://example.test/notify.xml".to_string()),
}
}
#[test]
fn never_http_fetcher_returns_error() {
let f = NeverHttpFetcher;
@@ -3937,6 +3953,79 @@ fn project_current_instance_vcir_reuses_local_outputs_and_restores_children() {
);
}
#[test]
fn project_current_instance_vcir_does_not_reuse_without_identity() {
let now = time::OffsetDateTime::now_utc();
let child_cert_hash = sha256_hex(b"child-cert");
let vcir = sample_vcir_for_projection(now, &child_cert_hash);
let store_dir = tempfile::tempdir().expect("store dir");
let store = RocksStore::open(store_dir.path()).expect("open rocksdb");
store.put_vcir(&vcir).expect("put legacy-style VCIR");
let ca = sample_ca_for_failed_fetch_reuse(&vcir);
let projection = project_current_instance_vcir_on_failed_fetch(
&store,
&ca,
&ManifestFreshError::RepoSyncFailed {
detail: "synthetic".to_string(),
},
&Policy::default(),
now,
)
.expect("project VCIR");
assert_eq!(
projection.source,
PublicationPointSource::FailedFetchNoCache
);
assert!(projection.objects.vrps.is_empty());
assert!(projection.discovered_children.is_empty());
assert!(
projection
.warnings
.iter()
.any(|warning| warning.message.contains("reuse identity is missing"))
);
}
#[test]
fn project_current_instance_vcir_does_not_reuse_when_ta_context_changes() {
let now = time::OffsetDateTime::now_utc();
let child_cert_hash = sha256_hex(b"child-cert");
let vcir = sample_vcir_for_projection(now, &child_cert_hash);
let store_dir = tempfile::tempdir().expect("store dir");
let store = RocksStore::open(store_dir.path()).expect("open rocksdb");
let policy = Policy::default();
let original_ca = sample_ca_for_failed_fetch_reuse(&vcir);
put_vcir_for_failed_fetch_reuse(&store, &original_ca, &policy, &vcir);
let mut changed_ca = original_ca;
changed_ca.tal_id = "different-tal".to_string();
let projection = project_current_instance_vcir_on_failed_fetch(
&store,
&changed_ca,
&ManifestFreshError::RepoSyncFailed {
detail: "synthetic".to_string(),
},
&policy,
now,
)
.expect("project VCIR");
assert_eq!(
projection.source,
PublicationPointSource::FailedFetchNoCache
);
assert!(projection.objects.vrps.is_empty());
assert!(projection.discovered_children.is_empty());
assert!(
projection
.warnings
.iter()
.any(|warning| warning.message.contains("identity does not match"))
);
}
#[test]
fn project_current_instance_vcir_returns_no_output_when_instance_gate_expired() {
let now = time::OffsetDateTime::now_utc();