20260605 移除audit rule index和DB trace

This commit is contained in:
2026-06-05 16:02:25 +08:00
parent 9579f65501
commit e597c7c124
29 changed files with 4032 additions and 2298 deletions

View File

@@ -10,6 +10,10 @@ fn sha256_hex(input: &[u8]) -> String {
hex::encode(compute_sha256_32(input))
}
fn sha256_32(input: &[u8]) -> [u8; 32] {
compute_sha256_32(input)
}
#[test]
fn parse_work_db_blob_mode_accepts_supported_values() {
assert_eq!(default_work_db_blob_mode(), WorkDbBlobMode::Disabled);
@@ -41,6 +45,61 @@ fn parse_work_db_blob_mode_accepts_supported_values() {
assert_eq!(parse_work_db_blob_mode("unexpected"), None);
}
#[test]
fn parse_work_db_memory_profile_accepts_supported_values() {
assert_eq!(
parse_work_db_memory_profile("default"),
Some(WorkDbMemoryProfile::Default)
);
assert_eq!(
parse_work_db_memory_profile("none"),
Some(WorkDbMemoryProfile::Default)
);
assert_eq!(
parse_work_db_memory_profile("compact"),
Some(WorkDbMemoryProfile::Compact)
);
assert_eq!(
parse_work_db_memory_profile("low-memory"),
Some(WorkDbMemoryProfile::Compact)
);
assert_eq!(parse_work_db_memory_profile("unexpected"), None);
}
#[test]
fn vcir_field_size_breakdown_counts_local_outputs_and_artifacts() {
let vcir = sample_vcir("rsync://example.test/repo/current.mft");
let breakdown = VcirFieldSizeBreakdown::from_vcir(&vcir);
assert_eq!(breakdown.local_output_count, 2);
assert_eq!(
breakdown.local_output_payload_json_bytes,
vcir.local_outputs
.iter()
.map(|output| output.payload_json().len() as u64)
.sum::<u64>()
);
assert_eq!(
breakdown.local_output_rule_hash_hex_bytes,
vcir.local_outputs.len() as u64 * 64
);
assert_eq!(breakdown.related_artifact_count, 2);
assert!(breakdown.related_artifact_uri_bytes > 0);
assert_eq!(breakdown.child_entry_count, 1);
assert!(breakdown.child_entry_uri_bytes > 0);
assert_eq!(
breakdown.local_output_old_projection_bytes(),
breakdown.local_output_source_type_bytes
+ breakdown.local_output_source_hash_hex_bytes
+ breakdown.local_output_source_ee_hash_hex_bytes
+ breakdown.local_output_payload_json_bytes
+ breakdown.local_output_rule_hash_hex_bytes
);
assert!(
breakdown.local_output_old_projection_bytes()
> breakdown.local_output_typed_projection_bytes()
);
}
fn sample_repository_view_entry(rsync_uri: &str, bytes: &[u8]) -> RepositoryViewEntry {
RepositoryViewEntry {
rsync_uri: rsync_uri.to_string(),
@@ -126,28 +185,37 @@ fn sample_vcir(manifest_rsync_uri: &str) -> ValidatedCaInstanceResult {
}],
local_outputs: vec![
VcirLocalOutput {
output_id: "vrp-1".to_string(),
output_type: VcirOutputType::Vrp,
item_effective_until: pack_time(12),
source_object_uri: "rsync://example.test/repo/object.roa".to_string(),
source_object_type: "roa".to_string(),
source_object_hash: sha256_hex(&roa_bytes),
source_ee_cert_hash: sha256_hex(&ee_bytes),
payload_json: r#"{"asn":64496,"prefix":"203.0.113.0/24"}"#.to_string(),
rule_hash: sha256_hex(b"vrp-rule-1"),
validation_path_hint: vec![manifest_rsync_uri.to_string()],
source_object_type: VcirSourceObjectType::Roa,
source_object_hash: sha256_32(&roa_bytes),
source_ee_cert_hash: sha256_32(&ee_bytes),
payload: VcirLocalOutputPayload::Vrp {
asn: 64496,
afi: crate::data_model::roa::RoaAfi::Ipv4,
prefix_len: 24,
addr: {
let mut addr = [0u8; 16];
addr[..4].copy_from_slice(&[203, 0, 113, 0]);
addr
},
max_length: 24,
},
rule_hash: sha256_32(b"vrp-rule-1"),
},
VcirLocalOutput {
output_id: "aspa-1".to_string(),
output_type: VcirOutputType::Aspa,
item_effective_until: pack_time(10),
source_object_uri: "rsync://example.test/repo/object.asa".to_string(),
source_object_type: "aspa".to_string(),
source_object_hash: sha256_hex(b"aspa-object"),
source_ee_cert_hash: sha256_hex(b"aspa-ee-cert"),
payload_json: r#"{"customer_as":64496,"providers":[64497]}"#.to_string(),
rule_hash: sha256_hex(b"aspa-rule-1"),
validation_path_hint: vec![manifest_rsync_uri.to_string()],
source_object_type: VcirSourceObjectType::Aspa,
source_object_hash: sha256_32(b"aspa-object"),
source_ee_cert_hash: sha256_32(b"aspa-ee-cert"),
payload: VcirLocalOutputPayload::Aspa {
customer_as_id: 64496,
provider_as_ids: vec![64497],
},
rule_hash: sha256_32(b"aspa-rule-1"),
},
],
related_artifacts: vec![
@@ -230,34 +298,6 @@ fn vcir_ccr_manifest_projection_validate_rejects_invalid_fields() {
));
}
fn sample_audit_rule_entry(kind: AuditRuleKind) -> AuditRuleIndexEntry {
AuditRuleIndexEntry {
kind,
rule_hash: sha256_hex(match kind {
AuditRuleKind::Roa => b"roa-index-rule",
AuditRuleKind::Aspa => b"aspa-index-rule",
AuditRuleKind::RouterKey => b"router-key-index-rule",
}),
manifest_rsync_uri: "rsync://example.test/repo/current.mft".to_string(),
source_object_uri: match kind {
AuditRuleKind::Roa => "rsync://example.test/repo/object.roa".to_string(),
AuditRuleKind::Aspa => "rsync://example.test/repo/object.asa".to_string(),
AuditRuleKind::RouterKey => "rsync://example.test/repo/router.cer".to_string(),
},
source_object_hash: sha256_hex(match kind {
AuditRuleKind::Roa => b"roa-object",
AuditRuleKind::Aspa => b"aspa-object",
AuditRuleKind::RouterKey => b"router-key-object",
}),
output_id: match kind {
AuditRuleKind::Roa => "vrp-1".to_string(),
AuditRuleKind::Aspa => "aspa-1".to_string(),
AuditRuleKind::RouterKey => "router-key-1".to_string(),
},
item_effective_until: pack_time(12),
}
}
fn sample_rrdp_source_record(notify_uri: &str) -> RrdpSourceRecord {
RrdpSourceRecord {
notify_uri: notify_uri.to_string(),
@@ -464,6 +504,32 @@ fn repo_bytes_db_is_physically_separate_from_external_raw_store() {
);
}
#[test]
fn memory_snapshot_includes_work_db_and_external_stores() {
let td = tempfile::tempdir().expect("tempdir");
let store = RocksStore::open_with_external_stores(
&td.path().join("main-db"),
Some(&td.path().join("raw-store.db")),
Some(&td.path().join("repo-bytes.db")),
)
.expect("open store");
let snapshot = store.memory_snapshot();
let labels: Vec<&str> = snapshot
.databases
.iter()
.map(|db| db.label.as_str())
.collect();
assert_eq!(labels, vec!["work-db", "raw-store.db", "repo-bytes.db"]);
assert!(
snapshot.databases[0]
.column_families
.iter()
.any(|cf| cf.name == CF_REPOSITORY_VIEW)
);
serde_json::to_value(&snapshot).expect("serialize memory snapshot");
}
#[test]
fn put_blob_bytes_batch_accepts_empty_batch_with_external_raw_store() {
let td = tempfile::tempdir().expect("tempdir");
@@ -784,106 +850,111 @@ fn list_vcirs_returns_all_entries() {
}
#[test]
fn audit_rule_index_roundtrip_for_roa_aspa_and_router_key() {
fn summarize_vcir_storage_aggregates_values_and_field_sizes() {
let td = tempfile::tempdir().expect("tempdir");
let store = RocksStore::open(td.path()).expect("open rocksdb");
let roa = sample_audit_rule_entry(AuditRuleKind::Roa);
let aspa = sample_audit_rule_entry(AuditRuleKind::Aspa);
let router_key = sample_audit_rule_entry(AuditRuleKind::RouterKey);
store
.put_audit_rule_index_entry(&roa)
.expect("put roa audit rule entry");
store
.put_audit_rule_index_entry(&aspa)
.expect("put aspa audit rule entry");
store
.put_audit_rule_index_entry(&router_key)
.expect("put router key audit rule entry");
let vcir1 = sample_vcir("rsync://example.test/repo/a.mft");
let vcir2 = sample_vcir("rsync://example.test/repo/b.mft");
store.put_vcir(&vcir1).expect("put vcir1");
store.put_vcir(&vcir2).expect("put vcir2");
let got_roa = store
.get_audit_rule_index_entry(AuditRuleKind::Roa, &roa.rule_hash)
.expect("get roa audit rule entry")
.expect("roa entry exists");
let got_aspa = store
.get_audit_rule_index_entry(AuditRuleKind::Aspa, &aspa.rule_hash)
.expect("get aspa audit rule entry")
.expect("aspa entry exists");
let got_router_key = store
.get_audit_rule_index_entry(AuditRuleKind::RouterKey, &router_key.rule_hash)
.expect("get router key audit rule entry")
.expect("router key entry exists");
assert_eq!(got_roa, roa);
assert_eq!(got_aspa, aspa);
assert_eq!(got_router_key, router_key);
let summary = store.summarize_vcir_storage().expect("summarize vcirs");
let mut expected_fields = VcirFieldSizeBreakdown::default();
expected_fields.add_assign(&VcirFieldSizeBreakdown::from_vcir(&vcir1));
expected_fields.add_assign(&VcirFieldSizeBreakdown::from_vcir(&vcir2));
store
.delete_audit_rule_index_entry(AuditRuleKind::Roa, &roa.rule_hash)
.expect("delete roa audit rule entry");
assert_eq!(summary.entry_count, 2);
assert!(summary.vcir_value_bytes > 0);
assert!(summary.vcir_value_bytes_max > 0);
assert!(summary.vcir_value_bytes_max_manifest_rsync_uri.is_some());
assert_eq!(summary.top_entries_by_vcir_value_bytes.len(), 2);
assert!(
store
.get_audit_rule_index_entry(AuditRuleKind::Roa, &roa.rule_hash)
.expect("get deleted roa audit rule entry")
.is_none()
summary.top_entries_by_vcir_value_bytes[0].vcir_value_bytes
>= summary.top_entries_by_vcir_value_bytes[1].vcir_value_bytes
);
assert_eq!(summary.field_sizes, expected_fields);
assert!(summary.core_fields.manifest_rsync_uri_bytes > 0);
assert!(summary.ccr_projection.manifest_sha256_bytes > 0);
assert!(summary.child_resources.effective_ip_resource_cbor_bytes > 0);
assert_eq!(
summary.local_output_old_projection_bytes,
expected_fields.local_output_old_projection_bytes()
);
assert_eq!(
summary.local_output_typed_projection_bytes,
expected_fields.local_output_typed_projection_bytes()
);
assert_eq!(
summary.local_output_projection_saved_bytes,
expected_fields.local_output_projection_saved_bytes()
);
let mut invalid = sample_audit_rule_entry(AuditRuleKind::Roa);
invalid.rule_hash = "bad".to_string();
let err = store
.put_audit_rule_index_entry(&invalid)
.expect_err("invalid audit rule hash must fail");
assert!(err.to_string().contains("64-character"));
}
#[test]
fn replace_vcir_and_audit_rule_indexes_replaces_previous_entries_in_one_step() {
fn replace_vcir_and_manifest_replay_meta_replaces_current_entry() {
let td = tempfile::tempdir().expect("tempdir");
let store = RocksStore::open(td.path()).expect("open rocksdb");
let mut previous = sample_vcir("rsync://example.test/repo/current.mft");
previous.local_outputs = vec![VcirLocalOutput {
output_id: "old-output".to_string(),
output_type: VcirOutputType::Vrp,
item_effective_until: pack_time(10),
source_object_uri: "rsync://example.test/repo/old.roa".to_string(),
source_object_type: "roa".to_string(),
source_object_hash: sha256_hex(b"old-roa"),
source_ee_cert_hash: sha256_hex(b"old-ee"),
payload_json: "{}".to_string(),
rule_hash: sha256_hex(b"old-rule"),
validation_path_hint: vec![previous.manifest_rsync_uri.clone()],
source_object_type: VcirSourceObjectType::Roa,
source_object_hash: sha256_32(b"old-roa"),
source_ee_cert_hash: sha256_32(b"old-ee"),
payload: VcirLocalOutputPayload::Vrp {
asn: 64496,
afi: crate::data_model::roa::RoaAfi::Ipv4,
prefix_len: 24,
addr: {
let mut addr = [0u8; 16];
addr[..4].copy_from_slice(&[203, 0, 113, 0]);
addr
},
max_length: 24,
},
rule_hash: sha256_32(b"old-rule"),
}];
previous.summary.local_vrp_count = 1;
previous.summary.local_aspa_count = 0;
previous.summary.local_router_key_count = 0;
store
.replace_vcir_and_audit_rule_indexes(None, &previous)
let previous_timing = store
.replace_vcir_and_manifest_replay_meta(&previous)
.expect("store previous vcir");
assert!(
store
.get_audit_rule_index_entry(AuditRuleKind::Roa, &previous.local_outputs[0].rule_hash)
.expect("get old audit entry")
.is_some()
assert!(previous_timing.vcir_value_bytes > 0);
assert!(previous_timing.replay_meta_value_bytes > 0);
assert_eq!(
previous_timing.total_encoded_bytes,
previous_timing.vcir_value_bytes + previous_timing.replay_meta_value_bytes
);
let mut current = sample_vcir("rsync://example.test/repo/current.mft");
current.local_outputs = vec![VcirLocalOutput {
output_id: "new-output".to_string(),
output_type: VcirOutputType::Aspa,
item_effective_until: pack_time(11),
source_object_uri: "rsync://example.test/repo/new.asa".to_string(),
source_object_type: "aspa".to_string(),
source_object_hash: sha256_hex(b"new-aspa"),
source_ee_cert_hash: sha256_hex(b"new-ee"),
payload_json: "{}".to_string(),
rule_hash: sha256_hex(b"new-rule"),
validation_path_hint: vec![current.manifest_rsync_uri.clone()],
source_object_type: VcirSourceObjectType::Aspa,
source_object_hash: sha256_32(b"new-aspa"),
source_ee_cert_hash: sha256_32(b"new-ee"),
payload: VcirLocalOutputPayload::Aspa {
customer_as_id: 64496,
provider_as_ids: vec![64497],
},
rule_hash: sha256_32(b"new-rule"),
}];
current.summary.local_vrp_count = 0;
current.summary.local_aspa_count = 1;
store
.replace_vcir_and_audit_rule_indexes(Some(&previous), &current)
.expect("replace vcir and audit indexes");
let current_timing = store
.replace_vcir_and_manifest_replay_meta(&current)
.expect("replace vcir and replay meta");
assert!(current_timing.vcir_value_bytes > 0);
assert!(current_timing.replay_meta_value_bytes > 0);
assert_eq!(
current_timing.total_encoded_bytes,
current_timing.vcir_value_bytes + current_timing.replay_meta_value_bytes
);
let got = store
.get_vcir(&current.manifest_rsync_uri)
@@ -902,18 +973,6 @@ fn replace_vcir_and_audit_rule_indexes_replaces_previous_entries_in_one_step() {
replay_meta.manifest_sha256,
current.ccr_manifest_projection.manifest_sha256
);
assert!(
store
.get_audit_rule_index_entry(AuditRuleKind::Roa, &previous.local_outputs[0].rule_hash)
.expect("get deleted old audit entry")
.is_none()
);
assert!(
store
.get_audit_rule_index_entry(AuditRuleKind::Aspa, &current.local_outputs[0].rule_hash)
.expect("get new audit entry")
.is_some()
);
}
#[test]