// file: crates/ksp-program-api/tests/release_completeness.rs // version: 1 //! Release-level completeness canaries for the `0.2.14` Program API foundation. #[test] fn pre_005_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 self::program_instruction_decode::ProgramInstructionDecodeOutcome;", "pub use self::program_instruction_decode::ProgramInstructionRecognition;", "pub use self::program_instruction_decoder::ProgramInstructionDecoder;", "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 ksp_interface_lib::ProgramAccountMeta;", "pub use ksp_interface_lib::ProgramInstruction;", ]; expected.sort_unstable(); assert_eq!(actual, expected); assert!(!crate_root.contains("pub mod ")); return; } #[test] fn pre_005_production_module_inventory_is_instruction_only() -> std::io::Result<()> { let source_root = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("src"); let entries = match std::fs::read_dir(source_root) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; let mut names = std::vec::Vec::new(); for entry in entries { let entry = match entry { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; let file_type = match entry.file_type() { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; if !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(); assert_eq!(names, std::vec!["lib.rs", "program_instruction_decode.rs", "program_instruction_decoder.rs"]); return std::result::Result::Ok(()); } #[test] fn pre_005_public_enum_and_trait_inventory_remains_open_world() { let sources = [ include_str!("../src/lib.rs"), include_str!("../src/program_instruction_decode.rs"), include_str!("../src/program_instruction_decoder.rs"), ]; let mut public_enums = std::vec::Vec::new(); let mut public_traits = std::vec::Vec::new(); for source in sources { for line in source.lines() { let trimmed = line.trim(); if trimmed.starts_with("pub enum ") { public_enums.push(trimmed); } if trimmed.starts_with("pub trait ") { public_traits.push(trimmed); } } } public_enums.sort_unstable(); public_traits.sort_unstable(); assert_eq!( public_enums, std::vec!["pub enum ProgramInstructionDecodeOutcome {", "pub enum ProgramInstructionRecognition {"] ); assert_eq!(public_traits, std::vec!["pub trait ProgramInstructionDecoder: Send + Sync {"]); let decode_source = include_str!("../src/program_instruction_decode.rs"); assert!(decode_source.contains("#[non_exhaustive]\npub enum ProgramInstructionRecognition")); assert!(decode_source.contains("#[non_exhaustive]\npub enum ProgramInstructionDecodeOutcome")); return; } #[test] fn pre_005_production_sources_have_no_registry_preparer_codec_or_runtime_creep() { let sources = [ include_str!("../src/lib.rs"), include_str!("../src/program_instruction_decode.rs"), include_str!("../src/program_instruction_decoder.rs"), ]; for source in sources { for forbidden in [ "pub enum ProgramKind", "pub struct ProgramRegistry", "pub trait ProgramAccountDecoder", "pub trait ProgramEventDecoder", "pub trait ProgramReturnDataDecoder", "pub trait ProgramExecutionPreparer", "std::any::Any", "serde::", "serde_json::", "borsh::", "bincode::", "wincode::", "ksp_logging_lib::", "tracing::", "reqwest::", "tokio::", "tonic::", "tauri::", "std::env::", "std::fs::", "std::net::", "dyn ProgramInstructionDecoder", "dyn crate::ProgramInstructionDecoder", ] { assert!(!source.contains(forbidden), "forbidden Program API production surface detected: {forbidden}"); } } return; }