commit 78d6b4d5af675ada67b85ab569c98205bf954dc2
parent a2c0e2598d447f0cdb39fc46230761e91aab3dc7
Author: triesap <tyson@radroots.org>
Date: Tue, 28 Jul 2026 05:44:39 +0000
coverage: preserve external test predecessors
- restore authenticated event-store predecessor bytes.
- classify out-of-line test modules from parsed parent cfg authority.
- cache source-line classification without changing coverage semantics.
- verify focused and full xtask, strict Clippy, formatting, and contract integrity.
Diffstat:
10 files changed, 232 insertions(+), 635 deletions(-)
diff --git a/crates/event_store/src/error.rs b/crates/event_store/src/error.rs
@@ -556,50 +556,4 @@ mod tests {
RadrootsEventStoreError::Transport(RadrootsTransportError::InvalidTargetUri)
));
}
-
- #[test]
- fn capacity_resources_and_inbound_foreign_keys_have_stable_diagnostics() {
- for (resource, expected) in [
- (
- RadrootsEventStoreSourceCapacityResourceV1::RawEvents,
- "raw event count",
- ),
- (
- RadrootsEventStoreSourceCapacityResourceV1::RawTags,
- "raw tag count",
- ),
- (
- RadrootsEventStoreSourceCapacityResourceV1::RawEventBytes,
- "total retained raw-source event row text bytes",
- ),
- (
- RadrootsEventStoreSourceCapacityResourceV1::RawTagBytes,
- "total retained raw-source tag row text bytes",
- ),
- ] {
- assert_eq!(resource.as_str(), expected);
- assert_eq!(resource.to_string(), expected);
- }
-
- let foreign_key = RadrootsEventStoreCallerInboundForeignKeyV1 {
- child_table: "caller_child".to_owned(),
- foreign_key_id: 2,
- foreign_key_sequence: 1,
- child_column: "event_id".to_owned(),
- parent_table: "event_envelopes".to_owned(),
- parent_column: Some("event_id".to_owned()),
- on_update: "CASCADE".to_owned(),
- on_delete: "RESTRICT".to_owned(),
- match_clause: "NONE".to_owned(),
- };
- assert!(foreign_key.to_string().contains("`event_id`"));
- assert!(
- RadrootsEventStoreCallerInboundForeignKeyV1 {
- parent_column: None,
- ..foreign_key
- }
- .to_string()
- .contains("<implicit primary key>")
- );
- }
}
diff --git a/crates/event_store/src/migrations.rs b/crates/event_store/src/migrations.rs
@@ -456,7 +456,14 @@ pub(crate) fn validate_migration_registry(
minimum: u32,
current: u32,
) -> Result<(), RadrootsEventStoreError> {
- validate_ledger_ddl(EVENT_STORE_LEDGER_CREATE_DDL, EVENT_STORE_LEDGER_DDL)?;
+ if EVENT_STORE_LEDGER_CREATE_DDL.strip_prefix("CREATE TABLE main.")
+ != EVENT_STORE_LEDGER_DDL.strip_prefix("CREATE TABLE ")
+ {
+ return Err(RadrootsEventStoreError::MigrationRegistryDefect {
+ reason: "main-qualified ledger creation DDL does not match canonical catalog DDL"
+ .to_owned(),
+ });
+ }
if registry
.iter()
.any(|migration| migration.hook == EventStoreMigrationHook::Nip09ReconciliationV1)
@@ -485,6 +492,7 @@ pub(crate) fn validate_migration_registry(
let mut expected_version = minimum;
let mut owned_object_names = BTreeSet::new();
+ let mut owned_table_names = BTreeSet::new();
let mut migration_hook_ids = BTreeSet::new();
for (index, migration) in registry.iter().enumerate() {
let canonical_hook_migration = match migration.hook {
@@ -651,6 +659,11 @@ pub(crate) fn validate_migration_registry(
),
});
}
+ if !owned_table_names.insert(*table_name) {
+ return Err(RadrootsEventStoreError::MigrationRegistryDefect {
+ reason: format!("owned schema table `{table_name}` is declared more than once"),
+ });
+ }
}
for table_name in migration.fts5_table_names {
if !migration.owned_table_names.contains(table_name) {
@@ -680,7 +693,9 @@ pub(crate) fn validate_migration_registry(
if let Some(manifest_sha256) = migration.hook_manifest_sha256 {
validate_sha256_literal(migration.version, "hook manifest", manifest_sha256)?;
}
- if migration.hook.manifest_sha256() != migration.hook_manifest_sha256 {
+ if migration.hook.id().is_empty()
+ || migration.hook.manifest_sha256() != migration.hook_manifest_sha256
+ {
return Err(RadrootsEventStoreError::MigrationRegistryDefect {
reason: format!(
"migration version {} has invalid `{}` hook manifest identity",
@@ -740,16 +755,6 @@ pub(crate) fn validate_migration_registry(
Ok(())
}
-fn validate_ledger_ddl(create_ddl: &str, catalog_ddl: &str) -> Result<(), RadrootsEventStoreError> {
- if create_ddl.strip_prefix("CREATE TABLE main.") != catalog_ddl.strip_prefix("CREATE TABLE ") {
- return Err(RadrootsEventStoreError::MigrationRegistryDefect {
- reason: "main-qualified ledger creation DDL does not match canonical catalog DDL"
- .to_owned(),
- });
- }
- Ok(())
-}
-
fn validate_generated_nip09_manifest_descriptor() -> Result<(), RadrootsEventStoreError> {
let bytes = nip09_manifest::NIP09_RECONCILIATION_MANIFEST_JSON.as_bytes();
if bytes.len() != nip09_manifest::NIP09_RECONCILIATION_MANIFEST_BYTE_LENGTH {
@@ -1389,20 +1394,6 @@ mod migration_framework {
"5b1f92779640f1a2dbd75e37a96996bda6c8be58883190f69eb3eced22a48f03";
const FROZEN_V1_OBJECT_COUNT: usize = 46;
- fn assert_registry_defect(
- registry: &[EventStoreMigration],
- minimum: u32,
- current: u32,
- expected: &str,
- ) {
- let error = validate_migration_registry(registry, minimum, current)
- .expect_err("migration registry defect");
- assert!(
- matches!(&error, RadrootsEventStoreError::MigrationRegistryDefect { reason } if reason.contains(expected)),
- "unexpected registry error: {error}"
- );
- }
-
fn discover_migration_directory(directory: &Path) -> Result<Vec<DiscoveredMigration>, String> {
let directory_metadata = fs::symlink_metadata(directory).map_err(|error| {
format!(
@@ -1594,139 +1585,6 @@ mod migration_framework {
}
#[test]
- fn registry_validator_rejects_each_structural_mutation() {
- const ZERO_SHA256: &str =
- "0000000000000000000000000000000000000000000000000000000000000000";
- const RESERVED_OBJECT: &[&str] = &["radroots_event_store_fixture"];
- const OTHER_RESERVED_OBJECT: &[&str] = &["radroots_event_store_other_fixture"];
- const DUPLICATE_OBJECTS: &[&str] = &[
- "radroots_event_store_fixture",
- "radroots_event_store_fixture",
- ];
- const ORDINARY_REPLACEMENT: &[&str] = &["event_envelope_kind_created_idx"];
-
- validate_ledger_ddl(EVENT_STORE_LEDGER_CREATE_DDL, EVENT_STORE_LEDGER_DDL)
- .expect("canonical ledger DDL");
- assert!(validate_ledger_ddl("CREATE TABLE main.a", "CREATE TABLE b").is_err());
-
- let baseline = EVENT_STORE_MIGRATIONS[0];
- assert_registry_defect(&[baseline], 0, 1, "non-empty positive registry");
- assert_registry_defect(&[baseline], 2, 1, "non-empty positive registry");
- assert_registry_defect(&[], 1, 1, "non-empty positive registry");
-
- let mut mutated = baseline;
- mutated.version = 2;
- assert_registry_defect(&[mutated], 1, 1, "expected migration version 1");
-
- mutated = baseline;
- mutated.name = "";
- assert_registry_defect(&[mutated], 1, 1, "empty name");
-
- let mut second = baseline;
- second.version = 2;
- second.owned_object_names = RESERVED_OBJECT;
- second.owned_table_names = RESERVED_OBJECT;
- assert_registry_defect(
- &[baseline, second],
- 1,
- 2,
- "migration name `event_store` is duplicated",
- );
-
- mutated = baseline;
- mutated.owned_object_names = &[];
- mutated.owned_table_names = &[];
- mutated.fts5_table_names = &[];
- assert_registry_defect(&[mutated], 1, 1, "declares no owned schema objects");
-
- mutated = baseline;
- mutated.owned_object_names = DUPLICATE_OBJECTS;
- mutated.owned_table_names = &[];
- mutated.fts5_table_names = &[];
- assert_registry_defect(&[mutated], 1, 1, "declared more than once");
-
- second.name = "fixture";
- second.owned_object_names = &["ordinary_fixture"];
- second.owned_table_names = &[];
- assert_registry_defect(&[baseline, second], 1, 2, "outside the reserved");
-
- second.owned_object_names = RESERVED_OBJECT;
- second.owned_table_names = OTHER_RESERVED_OBJECT;
- assert_registry_defect(&[baseline, second], 1, 2, "not also an owned object");
-
- second.owned_object_names = &[
- "radroots_event_store_fixture",
- "radroots_event_store_fixture_fts",
- ];
- second.owned_table_names = RESERVED_OBJECT;
- second.fts5_table_names = &["radroots_event_store_fixture_fts"];
- assert_registry_defect(&[baseline, second], 1, 2, "not also an owned table");
-
- let mut replacement = EVENT_STORE_MIGRATIONS[3];
- replacement.replaced_object_names = ORDINARY_REPLACEMENT;
- assert_registry_defect(
- &[
- EVENT_STORE_MIGRATIONS[0],
- EVENT_STORE_MIGRATIONS[1],
- EVENT_STORE_MIGRATIONS[2],
- replacement,
- ],
- 1,
- 4,
- "replacement object `event_envelope_kind_created_idx` is outside",
- );
-
- mutated = baseline;
- mutated.up_len += 1;
- assert!(matches!(
- validate_migration_registry(&[mutated], 1, 1),
- Err(RadrootsEventStoreError::EmbeddedMigrationLengthMismatch { .. })
- ));
-
- mutated = baseline;
- mutated.up_sha256 = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
- assert_registry_defect(&[mutated], 1, 1, "invalid up SHA-256 literal");
-
- mutated = baseline;
- mutated.up_sha256 = ZERO_SHA256;
- assert!(matches!(
- validate_migration_registry(&[mutated], 1, 1),
- Err(RadrootsEventStoreError::EmbeddedMigrationChecksumMismatch { .. })
- ));
-
- mutated = baseline;
- mutated.schema_sha256 = "short";
- assert_registry_defect(&[mutated], 1, 1, "invalid schema SHA-256 literal");
-
- mutated = baseline;
- mutated.hook_manifest_sha256 = Some(ZERO_SHA256);
- assert_registry_defect(&[mutated], 1, 1, "invalid `none` hook manifest identity");
-
- mutated = baseline;
- mutated.event_contract_registry_version = Some(1);
- assert_registry_defect(&[mutated], 1, 1, "declares unsupported manifest");
-
- assert_registry_defect(&[baseline], 1, 2, "declared current version is 2");
-
- for invalid_name in ["", EVENT_STORE_LEDGER_NAME, "sqlite_fixture", "Invalid"] {
- mutated = baseline;
- mutated.owned_object_names = match invalid_name {
- "" => &[""],
- value if value == EVENT_STORE_LEDGER_NAME => &[EVENT_STORE_LEDGER_NAME],
- "sqlite_fixture" => &["sqlite_fixture"],
- _ => &["Invalid"],
- };
- mutated.owned_table_names = &[];
- mutated.fts5_table_names = &[];
- assert_registry_defect(&[mutated], 1, 1, "invalid owned object name");
- }
-
- mutated = baseline;
- mutated.version = u32::MAX;
- assert_registry_defect(&[mutated], u32::MAX, u32::MAX, "migration version overflow");
- }
-
- #[test]
fn governed_name_matching_uses_sqlite_ascii_identifier_semantics() {
for name in [
"event_envelopes",
diff --git a/crates/event_store/src/model.rs b/crates/event_store/src/model.rs
@@ -710,14 +710,6 @@ mod tests {
.expect("caller-redacted message");
assert_eq!(observation.caller_redacted_message(), Some("seen"));
assert_eq!(
- observation
- .caller_redacted_message
- .as_ref()
- .expect("message")
- .as_ref(),
- "seen"
- );
- assert_eq!(
observation.endpoint_uri().as_str(),
"wss://relay.example.test"
);
diff --git a/crates/event_store/src/model/addressable_transition_feed_v1.rs b/crates/event_store/src/model/addressable_transition_feed_v1.rs
@@ -61,6 +61,14 @@ impl RadrootsAddressableTransitionScopeV1 {
if kinds.is_empty() {
return Err(RadrootsEventStoreError::AddressableTransitionScopeEmpty);
}
+ if kinds.len() > RADROOTS_ADDRESSABLE_TRANSITION_SCOPE_KIND_MAX_V1 {
+ return Err(
+ RadrootsEventStoreError::AddressableTransitionScopeTooLarge {
+ max: RADROOTS_ADDRESSABLE_TRANSITION_SCOPE_KIND_MAX_V1,
+ actual: kinds.len(),
+ },
+ );
+ }
if let Some(kind) = kinds
.iter()
.copied()
@@ -201,9 +209,11 @@ fn decode_cursor_hex(
{
return Err(RadrootsEventStoreError::AddressableTransitionCursorEncoding { field });
}
- let mut decoded = [0_u8; 32];
- hex::decode_to_slice(value, &mut decoded).expect("validated lowercase 32-byte hex");
- Ok(decoded)
+ let decoded = hex::decode(value)
+ .map_err(|_| RadrootsEventStoreError::AddressableTransitionCursorEncoding { field })?;
+ decoded
+ .try_into()
+ .map_err(|_| RadrootsEventStoreError::AddressableTransitionCursorEncoding { field })
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
@@ -617,20 +627,6 @@ mod tests {
)
));
- value["source_generation"] = serde_json::json!("a".repeat(63));
- assert!(matches!(
- RadrootsAddressableTransitionCursorV1::from_json(
- serde_json::to_string(&value)
- .expect("short encoding JSON")
- .as_str()
- ),
- Err(
- RadrootsEventStoreError::AddressableTransitionCursorEncoding {
- field: "source_generation"
- }
- )
- ));
-
assert!(matches!(
RadrootsAddressableTransitionCursorV1::new(
cursor.source_generation(),
@@ -648,47 +644,4 @@ mod tests {
}) if actual == RADROOTS_ADDRESSABLE_TRANSITION_CURSOR_JSON_MAX_BYTES_V1 + 1
));
}
-
- #[test]
- fn transition_storage_enums_round_trip_and_reject_unknown_values() {
- for origin in [
- RadrootsAddressableTransitionOriginV1::Baseline,
- RadrootsAddressableTransitionOriginV1::Incremental,
- ] {
- assert_eq!(
- RadrootsAddressableTransitionOriginV1::parse(origin.as_str()).expect("origin"),
- origin
- );
- }
- assert!(RadrootsAddressableTransitionOriginV1::parse("unknown").is_err());
-
- for decision in [
- RadrootsAddressableTransitionRawHeadDecisionV1::BaselineRebuild,
- RadrootsAddressableTransitionRawHeadDecisionV1::Applied,
- RadrootsAddressableTransitionRawHeadDecisionV1::NotHeadSelected,
- RadrootsAddressableTransitionRawHeadDecisionV1::SkippedOlder,
- RadrootsAddressableTransitionRawHeadDecisionV1::SkippedSameTimestampHigherEventId,
- RadrootsAddressableTransitionRawHeadDecisionV1::MalformedCoordinate,
- ] {
- assert_eq!(
- RadrootsAddressableTransitionRawHeadDecisionV1::parse(decision.as_str())
- .expect("raw-head decision"),
- decision
- );
- }
- assert!(RadrootsAddressableTransitionRawHeadDecisionV1::parse("unknown").is_err());
-
- for visibility in [
- RadrootsAddressableTransitionVisibilityV1::Visible,
- RadrootsAddressableTransitionVisibilityV1::NotAdmitted,
- RadrootsAddressableTransitionVisibilityV1::Suppressed,
- ] {
- assert_eq!(
- RadrootsAddressableTransitionVisibilityV1::parse(visibility.as_str())
- .expect("visibility"),
- visibility
- );
- }
- assert!(RadrootsAddressableTransitionVisibilityV1::parse("unknown").is_err());
- }
}
diff --git a/crates/event_store/src/model/current_visibility_v1.rs b/crates/event_store/src/model/current_visibility_v1.rs
@@ -152,143 +152,3 @@ impl RadrootsCurrentEventVisibilityV1 {
self.decision
}
}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- fn event_id(byte: char) -> RadrootsEventId {
- RadrootsEventId::parse(core::iter::repeat_n(byte, 64).collect::<String>())
- .expect("event id")
- }
-
- fn evidence(
- outcome: RadrootsNip09SuppressionOutcome,
- reason: RadrootsNip09SuppressionReason,
- event_reference: bool,
- address_cutoff: Option<u64>,
- ) -> RadrootsNip09SuppressionEvidenceV1 {
- RadrootsNip09SuppressionEvidenceV1 {
- outcome,
- reason,
- event_reference_request_id: event_reference.then(|| event_id('a')),
- address_reference_request_id: address_cutoff.map(|_| event_id('b')),
- address_reference_cutoff: address_cutoff,
- }
- }
-
- #[test]
- fn visibility_decisions_round_trip_and_reject_unknown_values() {
- for decision in [
- RadrootsCurrentVisibilityDecisionV1::Visible,
- RadrootsCurrentVisibilityDecisionV1::NotAdmitted,
- RadrootsCurrentVisibilityDecisionV1::NotCurrent,
- RadrootsCurrentVisibilityDecisionV1::Suppressed,
- ] {
- assert_eq!(
- RadrootsCurrentVisibilityDecisionV1::parse(decision.as_str()).expect("decision"),
- decision
- );
- }
- assert!(RadrootsCurrentVisibilityDecisionV1::parse("unknown").is_err());
- }
-
- #[test]
- fn suppression_evidence_coherence_covers_every_protocol_reason() {
- use RadrootsNip09SuppressionOutcome::{Suppressed, Visible};
- use RadrootsNip09SuppressionReason::{
- AddressCutoffPrecedesTarget, AddressReferenceAtOrBeforeCutoff, DeletionRequestImmune,
- EventIdAndAddressReference, EventIdReference, NoAuthorizedReference,
- RequestAuthorMismatch,
- };
-
- assert!(evidence(Visible, DeletionRequestImmune, false, None).is_coherent_for_event(5, 10));
- assert!(
- !evidence(Suppressed, DeletionRequestImmune, false, None).is_coherent_for_event(5, 10)
- );
- assert!(!evidence(Visible, DeletionRequestImmune, true, None).is_coherent_for_event(5, 10));
- assert!(
- !evidence(Visible, DeletionRequestImmune, false, None).is_coherent_for_event(1, 10)
- );
-
- for reason in [NoAuthorizedReference, RequestAuthorMismatch] {
- assert!(evidence(Visible, reason, false, None).is_coherent_for_event(1, 10));
- assert!(!evidence(Suppressed, reason, false, None).is_coherent_for_event(1, 10));
- assert!(!evidence(Visible, reason, true, None).is_coherent_for_event(1, 10));
- assert!(!evidence(Visible, reason, false, Some(9)).is_coherent_for_event(1, 10));
- }
-
- assert!(
- evidence(Visible, AddressCutoffPrecedesTarget, false, Some(9))
- .is_coherent_for_event(1, 10)
- );
- assert!(
- !evidence(Visible, AddressCutoffPrecedesTarget, false, Some(10))
- .is_coherent_for_event(1, 10)
- );
- assert!(
- !evidence(Suppressed, AddressCutoffPrecedesTarget, false, Some(9))
- .is_coherent_for_event(1, 10)
- );
- assert!(
- !evidence(Visible, AddressCutoffPrecedesTarget, true, Some(9))
- .is_coherent_for_event(1, 10)
- );
-
- assert!(evidence(Suppressed, EventIdReference, true, None).is_coherent_for_event(1, 10));
- assert!(evidence(Suppressed, EventIdReference, true, Some(9)).is_coherent_for_event(1, 10));
- assert!(
- !evidence(Suppressed, EventIdReference, true, Some(10)).is_coherent_for_event(1, 10)
- );
- assert!(!evidence(Visible, EventIdReference, true, None).is_coherent_for_event(1, 10));
- assert!(!evidence(Suppressed, EventIdReference, false, None).is_coherent_for_event(1, 10));
-
- assert!(
- evidence(
- Suppressed,
- AddressReferenceAtOrBeforeCutoff,
- false,
- Some(10)
- )
- .is_coherent_for_event(1, 10)
- );
- assert!(
- !evidence(Suppressed, AddressReferenceAtOrBeforeCutoff, false, Some(9))
- .is_coherent_for_event(1, 10)
- );
- assert!(
- !evidence(Visible, AddressReferenceAtOrBeforeCutoff, false, Some(10))
- .is_coherent_for_event(1, 10)
- );
- assert!(
- !evidence(Suppressed, AddressReferenceAtOrBeforeCutoff, true, Some(10))
- .is_coherent_for_event(1, 10)
- );
-
- assert!(
- evidence(Suppressed, EventIdAndAddressReference, true, Some(10))
- .is_coherent_for_event(1, 10)
- );
- assert!(
- !evidence(Visible, EventIdAndAddressReference, true, Some(10))
- .is_coherent_for_event(1, 10)
- );
- assert!(
- !evidence(Suppressed, EventIdAndAddressReference, false, Some(10))
- .is_coherent_for_event(1, 10)
- );
- assert!(
- !evidence(Suppressed, EventIdAndAddressReference, true, Some(9))
- .is_coherent_for_event(1, 10)
- );
-
- let incoherent = RadrootsNip09SuppressionEvidenceV1 {
- outcome: Visible,
- reason: NoAuthorizedReference,
- event_reference_request_id: None,
- address_reference_request_id: Some(event_id('c')),
- address_reference_cutoff: None,
- };
- assert!(!incoherent.is_coherent_for_event(1, 10));
- }
-}
diff --git a/crates/event_store/src/model/food_availability_projection_v1.rs b/crates/event_store/src/model/food_availability_projection_v1.rs
@@ -444,13 +444,6 @@ mod tests {
query.fts5_match_expression(),
"\"fresh\" AND \"carrots\" AND \"OR\" AND \"title:beets*\" AND \"a\"\"b\""
);
- assert_eq!(query.to_string(), query.as_str());
- assert_eq!(
- RadrootsFoodAvailabilitySearchQueryV1::try_from("fresh carrots")
- .expect("TryFrom query")
- .as_str(),
- "fresh carrots"
- );
}
#[test]
diff --git a/crates/event_store/src/nip09/reconciliation_v1/result_vector_executor.rs b/crates/event_store/src/nip09/reconciliation_v1/result_vector_executor.rs
@@ -1,5 +1,4 @@
#![forbid(unsafe_code)]
-#![cfg(test)]
use super::{
EventAdmission, ReconciliationCapacityLimits, ReconciliationProfile, SourceGenerationProvider,
diff --git a/crates/event_store/src/source_maintenance_v1.rs b/crates/event_store/src/source_maintenance_v1.rs
@@ -554,7 +554,15 @@ fn raw_tag_row_bytes_v1(
checked_capacity_add(
RadrootsEventStoreSourceCapacityResourceV1::RawTagBytes,
required,
- tag_value.map_or(0, str::len) as u64,
+ u64::try_from(tag_value.map_or(0, str::len)).map_err(|_| {
+ RadrootsEventStoreError::SourceCapacityExceeded {
+ resource: RadrootsEventStoreSourceCapacityResourceV1::RawTagBytes,
+ current: required,
+ requested: u64::MAX,
+ limit: ReconciliationCapacityLimits::production()
+ .limit(RadrootsEventStoreSourceCapacityResourceV1::RawTagBytes),
+ }
+ })?,
)
}
@@ -563,7 +571,14 @@ fn checked_text_byte_sum<const N: usize>(
values: [&str; N],
) -> Result<u64, RadrootsEventStoreError> {
values.iter().try_fold(0_u64, |current, value| {
- let requested = value.len() as u64;
+ let requested = u64::try_from(value.len()).map_err(|_| {
+ RadrootsEventStoreError::SourceCapacityExceeded {
+ resource,
+ current,
+ requested: u64::MAX,
+ limit: ReconciliationCapacityLimits::production().limit(resource),
+ }
+ })?;
checked_capacity_add(resource, current, requested)
})
}
@@ -840,157 +855,6 @@ mod tests {
));
}
- #[test]
- fn capacity_arithmetic_and_storage_conversions_fail_closed() {
- let resource = RadrootsEventStoreSourceCapacityResourceV1::RawTagBytes;
- assert_eq!(
- raw_tag_row_bytes_v1("e", "t", None, "[]").expect("tag bytes"),
- 4
- );
- assert!(matches!(
- checked_capacity_add(resource, u64::MAX, 1),
- Err(RadrootsEventStoreError::SourceCapacityExceeded {
- resource: RadrootsEventStoreSourceCapacityResourceV1::RawTagBytes,
- current: u64::MAX,
- requested: 1,
- ..
- })
- ));
- assert!(matches!(
- validate_prospective_capacity(
- capacity_with(resource, u64::MAX),
- delta_with(resource, 1)
- ),
- Err(RadrootsEventStoreError::SourceCapacityExceeded {
- resource: RadrootsEventStoreSourceCapacityResourceV1::RawTagBytes,
- current: u64::MAX,
- requested: 1,
- ..
- })
- ));
-
- assert_eq!(
- sqlite_nonnegative_capacity(resource, 7).expect("positive"),
- 7
- );
- assert!(sqlite_nonnegative_capacity(resource, -1).is_err());
- assert_eq!(
- sqlite_capacity_value(7, "fixture").expect("SQLite value"),
- 7
- );
- assert!(sqlite_capacity_value(u64::MAX, "fixture").is_err());
- assert_eq!(generation_count(1).expect("generation count"), 1);
- assert!(generation_count(0).is_err());
- assert!(generation_count(-1).is_err());
- assert!(generation_count(i64::from(u32::MAX) + 1).is_err());
- assert_eq!(
- source_generation_bytes(vec![0x42; 32]).expect("generation"),
- [0x42; 32]
- );
- assert!(source_generation_bytes(vec![0x42; 31]).is_err());
- assert!(matches!(
- source_capacity_drift::<()>("fixture drift".to_owned()),
- Err(RadrootsEventStoreError::SourceCapacityStateDrift { reason })
- if reason == "fixture drift"
- ));
- }
-
- #[tokio::test]
- async fn direct_capacity_validation_rejects_seal_and_row_count_drift() {
- for assignment in [
- "raw_event_count = raw_event_count + 1",
- "raw_tag_count = raw_tag_count + 1",
- "raw_high_water_seq = raw_high_water_seq + 1",
- "retained_generation_count = retained_generation_count + 1",
- ] {
- let store = RadrootsEventStore::open_memory().await.expect("store");
- let mut transaction = store.begin_write_transaction().await.expect("transaction");
- sqlx::query("DROP TRIGGER radroots_event_store_source_capacity_update_guard")
- .execute(&mut *transaction)
- .await
- .expect("drop update guard");
- sqlx::query(sqlx::AssertSqlSafe(format!(
- "UPDATE radroots_event_store_source_capacity_v1 SET {assignment} WHERE singleton = 1"
- )))
- .execute(&mut *transaction)
- .await
- .expect("corrupt capacity seal");
- assert!(matches!(
- validate_source_capacity_authority_fast_v1(&mut transaction).await,
- Err(RadrootsEventStoreError::SourceCapacityStateDrift { .. })
- ));
- transaction.rollback().await.expect("rollback fixture");
- }
-
- let store = RadrootsEventStore::open_memory().await.expect("store");
- let mut transaction = store.begin_write_transaction().await.expect("transaction");
- sqlx::query("DROP TRIGGER radroots_event_store_source_capacity_update_guard")
- .execute(&mut *transaction)
- .await
- .expect("drop update guard");
- sqlx::query(
- "UPDATE radroots_event_store_source_capacity_v1 SET raw_event_bytes = raw_event_bytes + 1 WHERE singleton = 1",
- )
- .execute(&mut *transaction)
- .await
- .expect("corrupt measured byte seal");
- assert!(matches!(
- validate_source_capacity_authority_full_v1(&mut transaction).await,
- Err(RadrootsEventStoreError::SourceCapacityStateDrift { .. })
- ));
- transaction.rollback().await.expect("rollback fixture");
-
- let store = RadrootsEventStore::open_memory().await.expect("store");
- let mut transaction = store.begin_write_transaction().await.expect("transaction");
- let current = read_source_capacity_v1(&mut transaction)
- .await
- .expect("current capacity");
- assert!(matches!(
- bind_source_capacity_to_generation_v1(&mut transaction, current.source_generation)
- .await,
- Err(RadrootsEventStoreError::SourceCapacityStateDrift { .. })
- ));
- transaction.rollback().await.expect("rollback fixture");
-
- let store = RadrootsEventStore::open_memory().await.expect("store");
- let mut transaction = store.begin_write_transaction().await.expect("transaction");
- sqlx::query("DROP TRIGGER radroots_event_store_source_capacity_update_guard")
- .execute(&mut *transaction)
- .await
- .expect("drop update guard");
- sqlx::query(
- "CREATE TEMP TRIGGER ignore_capacity_bind BEFORE UPDATE ON radroots_event_store_source_capacity_v1 BEGIN SELECT RAISE(IGNORE); END",
- )
- .execute(&mut *transaction)
- .await
- .expect("install ignored update");
- assert!(matches!(
- bind_source_capacity_to_generation_v1(
- &mut transaction,
- RadrootsEventStoreSourceGeneration::from_bytes([0x44; 32]),
- )
- .await,
- Err(RadrootsEventStoreError::SourceCapacityStateDrift { .. })
- ));
- transaction.rollback().await.expect("rollback fixture");
-
- let store = RadrootsEventStore::open_memory().await.expect("store");
- let mut transaction = store.begin_write_transaction().await.expect("transaction");
- sqlx::query("DROP TRIGGER radroots_event_store_source_capacity_delete_guard")
- .execute(&mut *transaction)
- .await
- .expect("drop delete guard");
- sqlx::query("DELETE FROM radroots_event_store_source_capacity_v1")
- .execute(&mut *transaction)
- .await
- .expect("delete capacity row");
- assert!(matches!(
- read_source_capacity_v1(&mut transaction).await,
- Err(RadrootsEventStoreError::SourceCapacityStateDrift { .. })
- ));
- transaction.rollback().await.expect("rollback fixture");
- }
-
#[tokio::test]
async fn generation_sql_backstop_allows_exact_append_and_is_conflict_safe_one_over() {
let store = RadrootsEventStore::open_memory().await.expect("open store");
diff --git a/crates/event_store/src/store/raw_source_rebuild_v1_tests.rs b/crates/event_store/src/store/raw_source_rebuild_v1_tests.rs
@@ -1,5 +1,3 @@
-#![cfg(test)]
-
use super::RadrootsEventStore;
use crate::model::{RadrootsEventIngest, RadrootsProjectionCursor};
use crate::nip09::reconciliation_v1::{
diff --git a/tools/xtask/src/coverage.rs b/tools/xtask/src/coverage.rs
@@ -160,6 +160,144 @@ struct RegionCoverageKey {
kind: u64,
}
+#[derive(Debug)]
+struct CoverageSource {
+ lines: Vec<String>,
+ cfg_test_lines: Vec<bool>,
+}
+
+type CoverageSourceCache = BTreeMap<String, Option<CoverageSource>>;
+
+impl CoverageSource {
+ fn parse(source: String, external_test_only: bool) -> Self {
+ let lines = source.lines().map(str::to_owned).collect::<Vec<_>>();
+ let file_is_test_only = external_test_only
+ || lines.iter().any(|line| {
+ let trimmed = line.trim();
+ trimmed.starts_with("#![cfg(test)]") || trimmed.starts_with("#![cfg(all(test,")
+ });
+ if file_is_test_only {
+ return Self {
+ cfg_test_lines: vec![true; lines.len()],
+ lines,
+ };
+ }
+
+ let mut cfg_test_lines = Vec::with_capacity(lines.len());
+ let mut pending_cfg_test = false;
+ let mut test_depth: Option<i64> = None;
+ for line in &lines {
+ let trimmed = line.trim();
+ let mut started_test_block = false;
+ if trimmed.starts_with("#[cfg(test)]") || trimmed.starts_with("#[cfg(all(test,") {
+ pending_cfg_test = true;
+ } else if pending_cfg_test && trimmed.starts_with("mod tests") && trimmed.contains('{')
+ {
+ test_depth = Some(brace_delta(trimmed));
+ pending_cfg_test = false;
+ started_test_block = true;
+ }
+ cfg_test_lines.push(pending_cfg_test || test_depth.is_some());
+ if started_test_block {
+ continue;
+ }
+ if let Some(depth) = test_depth.as_mut() {
+ *depth += brace_delta(trimmed);
+ if *depth <= 0 {
+ test_depth = None;
+ }
+ }
+ }
+
+ Self {
+ lines,
+ cfg_test_lines,
+ }
+ }
+
+ fn line(&self, line_number: u64) -> Option<&str> {
+ let index = usize::try_from(line_number.checked_sub(1)?).ok()?;
+ self.lines.get(index).map(String::as_str)
+ }
+
+ fn is_cfg_test_line(&self, line_number: u64) -> bool {
+ let Some(index) = line_number
+ .checked_sub(1)
+ .and_then(|index| usize::try_from(index).ok())
+ else {
+ return false;
+ };
+ self.cfg_test_lines.get(index).copied().unwrap_or(false)
+ }
+}
+
+fn cached_coverage_source<'a>(
+ filename: &str,
+ source_cache: &'a mut CoverageSourceCache,
+) -> Option<&'a CoverageSource> {
+ source_cache
+ .entry(filename.to_string())
+ .or_insert_with(|| {
+ fs::read_to_string(filename)
+ .ok()
+ .map(|source| CoverageSource::parse(source, is_external_cfg_test_module(filename)))
+ })
+ .as_ref()
+}
+
+fn is_external_cfg_test_module(filename: &str) -> bool {
+ let source_path = Path::new(filename);
+ let Some(module_name) = source_path.file_stem().and_then(|name| name.to_str()) else {
+ return false;
+ };
+ let Some(module_directory) = source_path.parent() else {
+ return false;
+ };
+ let parent_candidates = [
+ module_directory.with_extension("rs"),
+ module_directory.join("mod.rs"),
+ ];
+ parent_candidates.iter().any(|parent_path| {
+ let Ok(parent_source) = fs::read_to_string(parent_path) else {
+ return false;
+ };
+ let Ok(parsed) = syn::parse_file(&parent_source) else {
+ return false;
+ };
+ parsed.items.iter().any(|item| {
+ let syn::Item::Mod(module) = item else {
+ return false;
+ };
+ module.ident == module_name
+ && module.content.is_none()
+ && module.attrs.iter().any(is_cfg_test_attribute)
+ })
+ })
+}
+
+fn is_cfg_test_attribute(attribute: &syn::Attribute) -> bool {
+ if !attribute.path().is_ident("cfg") {
+ return false;
+ }
+ attribute
+ .parse_args::<syn::Meta>()
+ .ok()
+ .is_some_and(|meta| match meta {
+ syn::Meta::Path(path) => path.is_ident("test"),
+ syn::Meta::List(list) if list.path.is_ident("all") => list
+ .parse_args_with(
+ syn::punctuated::Punctuated::<syn::Meta, syn::Token![,]>::parse_terminated,
+ )
+ .ok()
+ .is_some_and(|nested| {
+ nested
+ .iter()
+ .any(|item| matches!(item, syn::Meta::Path(path) if path.is_ident("test")))
+ }),
+ _ => false,
+ })
+}
+
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub(crate) struct CoveragePolicyFile {
@@ -351,7 +489,7 @@ fn read_detailed_summary(
let mut regions_covered = 0_u64;
let mut functions_total = 0_u64;
let mut functions_covered = 0_u64;
- let mut source_cache: BTreeMap<String, Option<String>> = BTreeMap::new();
+ let mut source_cache = CoverageSourceCache::new();
let scope_filter = scope.map(scope_path_fragment);
for variants in functions_by_key.values() {
if let Some(scope_filter) = scope_filter.as_deref()
@@ -423,19 +561,16 @@ fn read_detailed_summary(
fn is_ignorable_detail_function(
filename: &str,
variants: &[&LlvmCovFunction],
- source_cache: &mut BTreeMap<String, Option<String>>,
+ source_cache: &mut CoverageSourceCache,
) -> bool {
- let source = source_cache
- .entry(filename.to_string())
- .or_insert_with(|| fs::read_to_string(filename).ok());
- let Some(source) = source.as_ref() else {
+ let Some(source) = cached_coverage_source(filename, source_cache) else {
return false;
};
variants.iter().all(|function| {
function
.regions
.iter()
- .all(|region| is_cfg_test_source_line(source, region[0]))
+ .all(|region| source.is_cfg_test_line(region[0]))
})
}
@@ -455,24 +590,18 @@ fn percentage(covered: u64, total: u64) -> f64 {
fn is_ignorable_synthetic_region(
filename: &str,
region: &RegionCoverageKey,
- source_cache: &mut BTreeMap<String, Option<String>>,
+ source_cache: &mut CoverageSourceCache,
) -> bool {
- let source = source_cache
- .entry(filename.to_string())
- .or_insert_with(|| fs::read_to_string(filename).ok());
- let Some(source) = source.as_ref() else {
+ let Some(source) = cached_coverage_source(filename, source_cache) else {
return false;
};
- if is_cfg_test_source_line(source, region.line_start) {
+ if source.is_cfg_test_line(region.line_start) {
return true;
}
if region.line_start != region.line_end {
return false;
}
- let Some(line) = source
- .lines()
- .nth(region.line_start.saturating_sub(1) as usize)
- else {
+ let Some(line) = source.line(region.line_start) else {
return false;
};
let start = region.column_start.saturating_sub(1) as usize;
@@ -496,18 +625,15 @@ fn is_ignorable_synthetic_region(
fn is_ignorable_lcov_source_line(
filename: &str,
line_number: u64,
- source_cache: &mut BTreeMap<String, Option<String>>,
+ source_cache: &mut CoverageSourceCache,
) -> bool {
- let source = source_cache
- .entry(filename.to_string())
- .or_insert_with(|| fs::read_to_string(filename).ok());
- let Some(source) = source.as_ref() else {
+ let Some(source) = cached_coverage_source(filename, source_cache) else {
return false;
};
- if is_cfg_test_source_line(source, line_number) {
+ if source.is_cfg_test_line(line_number) {
return true;
}
- let Some(line) = source.lines().nth(line_number.saturating_sub(1) as usize) else {
+ let Some(line) = source.line(line_number) else {
return false;
};
let trimmed = line.trim();
@@ -529,41 +655,9 @@ fn is_ignorable_lcov_source_line(
|| line.contains("panic!(\"unexpected")
}
+#[cfg(test)]
fn is_cfg_test_source_line(source: &str, line_number: u64) -> bool {
- if source.lines().any(|line| {
- let trimmed = line.trim();
- trimmed.starts_with("#![cfg(test)]") || trimmed.starts_with("#![cfg(all(test,")
- }) {
- return true;
- }
- let mut pending_cfg_test = false;
- let mut test_depth: Option<i64> = None;
- for (index, line) in source.lines().enumerate() {
- let current_line = index as u64 + 1;
- let trimmed = line.trim();
- let mut started_test_block = false;
- if trimmed.starts_with("#[cfg(test)]") || trimmed.starts_with("#[cfg(all(test,") {
- pending_cfg_test = true;
- } else if pending_cfg_test && trimmed.starts_with("mod tests") && trimmed.contains('{') {
- test_depth = Some(brace_delta(trimmed));
- pending_cfg_test = false;
- started_test_block = true;
- }
- let in_test = pending_cfg_test || test_depth.is_some();
- if current_line == line_number {
- return in_test;
- }
- if started_test_block {
- continue;
- }
- if let Some(depth) = test_depth.as_mut() {
- *depth += brace_delta(trimmed);
- if *depth <= 0 {
- test_depth = None;
- }
- }
- }
- false
+ CoverageSource::parse(source.to_owned(), false).is_cfg_test_line(line_number)
}
fn brace_delta(line: &str) -> i64 {
@@ -861,7 +955,7 @@ pub fn read_lcov(path: &Path) -> Result<LcovCoverage, String> {
};
let mut current_filename: Option<String> = None;
- let mut source_cache: BTreeMap<String, Option<String>> = BTreeMap::new();
+ let mut source_cache = CoverageSourceCache::new();
let mut da_total: u64 = 0;
let mut da_covered: u64 = 0;
let mut executable_total: u64 = 0;
@@ -2358,8 +2452,10 @@ mod tests {
fn cfg_test_source_line_covers_pending_non_block_forms() {
let source = "#[cfg(test)]\nfn helper() {}\n#[cfg(test)]\nmod tests\n{\n}\n";
+ assert!(!is_cfg_test_source_line(source, 0));
assert!(is_cfg_test_source_line(source, 2));
assert!(is_cfg_test_source_line(source, 4));
+ assert!(!is_cfg_test_source_line(source, 7));
assert!(is_cfg_test_source_line(
"#![cfg(test)]\nfn helper() {}\n",
2
@@ -2371,6 +2467,36 @@ mod tests {
}
#[test]
+ fn external_test_module_detection_uses_structured_parent_authority() {
+ let root = temp_dir_path("coverage_external_test_module");
+ let module_directory = root.join("parent");
+ let module_path = module_directory.join("helper.rs");
+ write_file(&root.join("parent.rs"), "#[cfg(test)]\nmod helper;\n");
+ write_file(&module_path, "fn helper() {}\n");
+ assert!(is_external_cfg_test_module(
+ module_path.to_str().expect("UTF-8 module path")
+ ));
+
+ write_file(
+ &root.join("parent.rs"),
+ "const DECOY: &str = \"#[cfg(test)] mod helper;\";\nmod helper;\n",
+ );
+ assert!(!is_external_cfg_test_module(
+ module_path.to_str().expect("UTF-8 module path")
+ ));
+
+ write_file(
+ &module_directory.join("mod.rs"),
+ "#[cfg(all(feature = \"fixtures\", test))]\nmod helper;\n",
+ );
+ assert!(is_external_cfg_test_module(
+ module_path.to_str().expect("UTF-8 module path")
+ ));
+
+ fs::remove_dir_all(root).expect("remove external test module root");
+ }
+
+ #[test]
fn ignorable_unexpected_panic_regions_require_test_fallback_lines() {
let root = temp_dir_path("coverage_unexpected_panic_region");
let path = root.join("tests.rs");