20260605 移除audit rule index和DB trace
This commit is contained in:
@@ -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), ¤t)
|
||||
.expect("replace vcir and audit indexes");
|
||||
let current_timing = store
|
||||
.replace_vcir_and_manifest_replay_meta(¤t)
|
||||
.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(¤t.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, ¤t.local_outputs[0].rule_hash)
|
||||
.expect("get new audit entry")
|
||||
.is_some()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user