// file: crates/ksp-store-api/tests/release_completeness.rs // version: 1 //! Release-level boundary and completeness canaries for the `0.3.1` Store API RAW surface. #[test] fn pre_007_exact_crate_root_export_inventory_is_stable() { let crate_root = include_str!("../src/lib.rs"); let mut actual = std::vec::Vec::new(); for line in crate_root.lines() { let trimmed = line.trim(); if trimmed.starts_with("pub use ") { actual.push(trimmed); } } actual.sort_unstable(); let mut expected = std::vec![ "pub use ksp_core_lib::Error;", "pub use ksp_core_lib::ErrorCode;", "pub use ksp_core_lib::ErrorContext;", "pub use ksp_core_lib::Pubkey;", "pub use ksp_core_lib::Result;", "pub use self::capability::StoreApiFuture;", "pub use self::capability::raw_account::RawAccountObservationRead;", "pub use self::capability::raw_account::RawAccountObservationWrite;", "pub use self::capability::raw_account::RawAccountStateRead;", "pub use self::capability::raw_account::RawAccountStateWrite;", "pub use self::capability::raw_retention::RawTransactionRetentionRead;", "pub use self::capability::raw_retention::RawTransactionRetentionWrite;", "pub use self::capability::raw_transaction::RawTransactionObservationRead;", "pub use self::capability::raw_transaction::RawTransactionObservationWrite;", "pub use self::capability::raw_transaction::RawTransactionRead;", "pub use self::capability::raw_transaction::RawTransactionWrite;", "pub use self::error::ERROR_CODE_RAW_CONFLICT;", "pub use self::error::ERROR_CODE_RAW_MODEL_INVALID;", "pub use self::error::ERROR_CODE_RAW_PAYLOAD_INVALID;", "pub use self::error::ERROR_CODE_RAW_PROVENANCE_INVALID;", "pub use self::error::ERROR_CODE_RAW_QUERY_INVALID;", "pub use self::error::ERROR_CODE_RAW_RETENTION_INVALID;", "pub use self::model::raw_account::RawAccountObservation;", "pub use self::model::raw_account::RawAccountState;", "pub use self::model::raw_account::RawAccountStateReference;", "pub use self::model::raw_outcome::RawAcquisitionWriteOutcome;", "pub use self::model::raw_outcome::RawEntityWriteOutcome;", "pub use self::model::raw_outcome::RawObservationWriteOutcome;", "pub use self::model::raw_pagination::MAX_RAW_PAGE_CURSOR_BYTES;", "pub use self::model::raw_pagination::RawAccountStateQuery;", "pub use self::model::raw_pagination::RawPage;", "pub use self::model::raw_pagination::RawPageCursor;", "pub use self::model::raw_pagination::RawPageLimit;", "pub use self::model::raw_pagination::RawPageRequest;", "pub use self::model::raw_pagination::RawSlotRange;", "pub use self::model::raw_pagination::RawSortDirection;", "pub use self::model::raw_pagination::RawTransactionQuery;", "pub use self::model::raw_primitives::MAX_RAW_ACCOUNT_DATA_BYTES;", "pub use self::model::raw_primitives::MAX_RAW_CODE_BYTES;", "pub use self::model::raw_primitives::MAX_RAW_PAYLOAD_BYTES;", "pub use self::model::raw_primitives::MAX_RAW_SOURCE_PAYLOAD_BYTES;", "pub use self::model::raw_primitives::MAX_RAW_UNIX_MILLIS;", "pub use self::model::raw_primitives::RawAcquisitionOrigin;", "pub use self::model::raw_primitives::RawAcquisitionProvenance;", "pub use self::model::raw_primitives::RawContentHash;", "pub use self::model::raw_primitives::RawFormatId;", "pub use self::model::raw_primitives::RawNetworkId;", "pub use self::model::raw_primitives::RawObservationKey;", "pub use self::model::raw_primitives::RawPayload;", "pub use self::model::raw_primitives::RawProvenanceCode;", "pub use self::model::raw_primitives::RawTimestamp;", "pub use self::model::raw_primitives::RawTransactionSignature;", "pub use self::model::raw_retention::RawRetentionState;", "pub use self::model::raw_retention::RawRetentionWriteOutcome;", "pub use self::model::raw_retention::RawTransactionAcquisitionMode;", "pub use self::model::raw_retention::RawTransactionRetentionTransition;", "pub use self::model::raw_retention::RawTransactionTombstone;", "pub use self::model::raw_transaction::RawTransaction;", "pub use self::model::raw_transaction::RawTransactionObservation;", "pub use self::model::raw_transaction::RawTransactionReference;", ]; expected.sort_unstable(); assert_eq!(actual, expected); assert!(!crate_root.contains("pub mod ")); return; } #[test] fn pre_007_exact_production_module_inventory_is_raw_only() -> std::io::Result<()> { let root = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("src"); assert_eq!(rust_file_names(root.as_path())?, std::vec!["capability.rs", "error.rs", "lib.rs", "model.rs"]); assert_eq!( rust_file_names(root.join("model").as_path())?, std::vec!["raw_account.rs", "raw_outcome.rs", "raw_pagination.rs", "raw_primitives.rs", "raw_retention.rs", "raw_transaction.rs"] ); assert_eq!(rust_file_names(root.join("capability").as_path())?, std::vec!["raw_account.rs", "raw_retention.rs", "raw_transaction.rs"]); return std::result::Result::Ok(()); } #[test] fn pre_007_public_evolutive_enums_remain_non_exhaustive() { let sources = [ include_str!("../src/model/raw_outcome.rs"), include_str!("../src/model/raw_pagination.rs"), include_str!("../src/model/raw_primitives.rs"), include_str!("../src/model/raw_retention.rs"), ]; for enum_name in [ "RawAcquisitionOrigin", "RawEntityWriteOutcome", "RawObservationWriteOutcome", "RawRetentionState", "RawRetentionWriteOutcome", "RawSortDirection", "RawTransactionAcquisitionMode", ] { assert_non_exhaustive(&sources, enum_name); } return; } #[test] fn pre_007_interface_store_ownership_and_negative_scope_remain_explicit() { let interface_root = include_str!("../../ksp-interface-lib/src/lib.rs"); let store_sources = [ include_str!("../src/lib.rs"), include_str!("../src/model.rs"), include_str!("../src/model/raw_account.rs"), include_str!("../src/model/raw_outcome.rs"), include_str!("../src/model/raw_pagination.rs"), include_str!("../src/model/raw_primitives.rs"), include_str!("../src/model/raw_retention.rs"), include_str!("../src/model/raw_transaction.rs"), include_str!("../src/capability.rs"), include_str!("../src/capability/raw_account.rs"), include_str!("../src/capability/raw_retention.rs"), include_str!("../src/capability/raw_transaction.rs"), ]; for persistent_name in ["RawTransaction", "RawAccountState", "RawRetentionState", "RawTransactionTombstone"] { assert!(!interface_root.contains(persistent_name), "persistent Store model leaked into Interface crate root: {persistent_name}"); } for source in store_sources { for forbidden in [ "RawLogNotification", "RawSlotEvent", "RawVoteEvent", "YellowstoneEntry", "StructuralInstruction", "StructuralTransaction", "DecodedInstruction", "DomainRecord", "ProgramInstructionDecoder", "PostgresStore", "MySqlStore", "StoreBackend", ] { assert!(!source.contains(forbidden), "deferred or backend-specific Store surface detected: {forbidden}"); } } return; } #[test] fn pre_007_capability_inventory_stays_fine_grained_without_runtime_facade() { let sources = [ include_str!("../src/capability/raw_account.rs"), include_str!("../src/capability/raw_retention.rs"), include_str!("../src/capability/raw_transaction.rs"), ]; let mut traits = std::vec::Vec::new(); for source in sources { for line in source.lines() { let trimmed = line.trim(); if trimmed.starts_with("pub trait ") { traits.push(trimmed); } } } traits.sort_unstable(); let mut expected = std::vec![ "pub trait RawAccountObservationRead: std::marker::Send + std::marker::Sync {", "pub trait RawAccountObservationWrite: std::marker::Send + std::marker::Sync {", "pub trait RawAccountStateRead: std::marker::Send + std::marker::Sync {", "pub trait RawAccountStateWrite: std::marker::Send + std::marker::Sync {", "pub trait RawTransactionObservationRead: std::marker::Send + std::marker::Sync {", "pub trait RawTransactionObservationWrite: std::marker::Send + std::marker::Sync {", "pub trait RawTransactionRead: std::marker::Send + std::marker::Sync {", "pub trait RawTransactionRetentionRead: std::marker::Send + std::marker::Sync {", "pub trait RawTransactionRetentionWrite: std::marker::Send + std::marker::Sync {", "pub trait RawTransactionWrite: std::marker::Send + std::marker::Sync {", ]; expected.sort_unstable(); assert_eq!(traits, expected); return; } fn assert_non_exhaustive(sources: &[&str], enum_name: &str) { let needle = "#[non_exhaustive]\n"; let declaration = std::format!("pub enum {enum_name}"); let mut found = false; for source in sources { if let std::option::Option::Some(position) = source.find(declaration.as_str()) { let prefix = &source[..position]; let attribute_position = prefix.rfind(needle); assert!(attribute_position.is_some(), "public evolutive enum is missing #[non_exhaustive]: {enum_name}"); found = true; } } assert!(found, "public evolutive enum not found: {enum_name}"); return; } fn rust_file_names(directory: &std::path::Path) -> std::io::Result> { let entries = std::fs::read_dir(directory)?; let mut names = std::vec::Vec::new(); for entry in entries { let entry = entry?; if !entry.file_type()?.is_file() { continue; } let name = match entry.file_name().into_string() { std::result::Result::Ok(value) => value, std::result::Result::Err(_) => continue, }; if name.ends_with(".rs") { names.push(name); } } names.sort_unstable(); return std::result::Result::Ok(names); }