// file: crates/ksp-onchain-transport-lib/tests/release_completeness.rs // version: 6 //! Release-level completeness canaries for the `0.2.1` HTTP foundation contract. #[test] fn release_registry_partition_matches_the_audited_http_plan() { let mut foundation = 0_usize; let mut accounts_tokens_cluster = 0_usize; let mut transactions = 0_usize; let mut blocks_economics = 0_usize; let mut historical_in_current = 0_usize; for descriptor in ksp_onchain_transport_lib::current_http_rpc_methods() { match descriptor.coverage_release() { ksp_onchain_transport_lib::HttpRpcCoverageRelease::V0_2_1 => foundation += 1, ksp_onchain_transport_lib::HttpRpcCoverageRelease::V0_2_2 => accounts_tokens_cluster += 1, ksp_onchain_transport_lib::HttpRpcCoverageRelease::V0_2_3 => transactions += 1, ksp_onchain_transport_lib::HttpRpcCoverageRelease::V0_2_4 => blocks_economics += 1, ksp_onchain_transport_lib::HttpRpcCoverageRelease::Historical => historical_in_current += 1, } } assert_eq!(ksp_onchain_transport_lib::current_http_rpc_methods().len(), 52); assert_eq!(ksp_onchain_transport_lib::historical_http_rpc_methods().len(), 14); assert_eq!(foundation, 4); assert_eq!(accounts_tokens_cluster, 22); assert_eq!(transactions, 11); assert_eq!(blocks_economics, 15); assert_eq!(historical_in_current, 0); } #[test] fn release_foundation_canaries_and_historical_statuses_are_exact() { let mut foundation_names = std::vec::Vec::<&str>::new(); for descriptor in ksp_onchain_transport_lib::current_http_rpc_methods() { if descriptor.coverage_release() == ksp_onchain_transport_lib::HttpRpcCoverageRelease::V0_2_1 { foundation_names.push(descriptor.method()); assert_eq!(descriptor.runtime_status(), ksp_onchain_transport_lib::RpcRuntimeStatus::Supported); } } foundation_names.sort_unstable(); assert_eq!(foundation_names, std::vec!["getBalance", "getGenesisHash", "getHealth", "getVersion"]); for descriptor in ksp_onchain_transport_lib::historical_http_rpc_methods() { assert_eq!(descriptor.documentation_status(), ksp_onchain_transport_lib::RpcDocumentationStatus::Deprecated); assert_eq!(descriptor.runtime_status(), ksp_onchain_transport_lib::RpcRuntimeStatus::Removed); assert_eq!(descriptor.coverage_release(), ksp_onchain_transport_lib::HttpRpcCoverageRelease::Historical); assert_eq!(descriptor.transport_retry_class(), ksp_onchain_transport_lib::TransportRetryClass::NotApplicable); } } #[test] fn release_pre_003_accounts_subset_is_exact_without_advancing_other_v0_2_2_families() { let mut account_names = std::vec::Vec::<&str>::new(); for descriptor in ksp_onchain_transport_lib::current_http_rpc_methods() { if descriptor.coverage_release() == ksp_onchain_transport_lib::HttpRpcCoverageRelease::V0_2_2 && descriptor.category() == ksp_onchain_transport_lib::HttpRpcCategory::Accounts { account_names.push(descriptor.method()); assert_eq!(descriptor.operation_kind(), ksp_onchain_transport_lib::RpcOperationKind::Read); assert_eq!(descriptor.transport_retry_class(), ksp_onchain_transport_lib::TransportRetryClass::RetrySafe); } } account_names.sort_unstable(); assert_eq!( account_names, std::vec!["getAccountInfo", "getLargestAccounts", "getMinimumBalanceForRentExemption", "getMultipleAccounts", "getProgramAccounts",], ); } #[test] fn release_pre_004_tokens_subset_is_exact_and_retry_safe() { let mut token_names = std::vec::Vec::<&str>::new(); for descriptor in ksp_onchain_transport_lib::current_http_rpc_methods() { if descriptor.coverage_release() == ksp_onchain_transport_lib::HttpRpcCoverageRelease::V0_2_2 && descriptor.category() == ksp_onchain_transport_lib::HttpRpcCategory::Tokens { token_names.push(descriptor.method()); assert_eq!(descriptor.operation_kind(), ksp_onchain_transport_lib::RpcOperationKind::Read); assert_eq!(descriptor.transport_retry_class(), ksp_onchain_transport_lib::TransportRetryClass::RetrySafe); } } token_names.sort_unstable(); assert_eq!( token_names, std::vec!["getTokenAccountBalance", "getTokenAccountsByDelegate", "getTokenAccountsByOwner", "getTokenLargestAccounts", "getTokenSupply",], ); } #[test] fn release_pre_005_simple_cluster_subset_is_exact_and_retry_safe() { let expected = std::vec![ "getClusterNodes", "getEpochInfo", "getEpochSchedule", "getHighestSnapshotSlot", "getIdentity", "getMaxRetransmitSlot", "getMaxShredInsertSlot", ]; let deferred = std::vec!["getLeaderSchedule", "getSlot", "getSlotLeader", "getSlotLeaders", "getVoteAccounts"]; for method_name in &expected { let descriptor = ksp_onchain_transport_lib::find_http_rpc_method(method_name).expect("pre.005 cluster descriptor must exist"); assert_eq!(descriptor.category(), ksp_onchain_transport_lib::HttpRpcCategory::Cluster); assert_eq!(descriptor.coverage_release(), ksp_onchain_transport_lib::HttpRpcCoverageRelease::V0_2_2); assert_eq!(descriptor.operation_kind(), ksp_onchain_transport_lib::RpcOperationKind::Read); assert_eq!(descriptor.transport_retry_class(), ksp_onchain_transport_lib::TransportRetryClass::RetrySafe); } for method_name in &deferred { let descriptor = ksp_onchain_transport_lib::find_http_rpc_method(method_name).expect("pre.006 cluster descriptor must remain registered"); assert_eq!(descriptor.coverage_release(), ksp_onchain_transport_lib::HttpRpcCoverageRelease::V0_2_2); } assert_eq!(expected.len(), 7); assert_eq!(deferred.len(), 5); } #[test] fn release_pre_006_completes_cluster_subset_exactly_and_retry_safe() { let mut expected = std::vec![ "getClusterNodes", "getEpochInfo", "getEpochSchedule", "getHighestSnapshotSlot", "getIdentity", "getLeaderSchedule", "getMaxRetransmitSlot", "getMaxShredInsertSlot", "getSlot", "getSlotLeader", "getSlotLeaders", "getVoteAccounts", ]; let mut actual = std::vec::Vec::new(); for descriptor in ksp_onchain_transport_lib::current_http_rpc_methods() { if descriptor.coverage_release() == ksp_onchain_transport_lib::HttpRpcCoverageRelease::V0_2_2 && descriptor.category() == ksp_onchain_transport_lib::HttpRpcCategory::Cluster { actual.push(descriptor.method()); assert_eq!(descriptor.operation_kind(), ksp_onchain_transport_lib::RpcOperationKind::Read); assert_eq!(descriptor.transport_retry_class(), ksp_onchain_transport_lib::TransportRetryClass::RetrySafe); } } actual.sort_unstable(); expected.sort_unstable(); assert_eq!(actual, expected); assert_eq!(actual.len(), 12); } #[test] fn release_pre_007_v0_2_2_exact_set_is_complete_without_advancing_future_releases() { let mut expected = std::vec![ "getAccountInfo", "getClusterNodes", "getEpochInfo", "getEpochSchedule", "getHighestSnapshotSlot", "getIdentity", "getLargestAccounts", "getLeaderSchedule", "getMaxRetransmitSlot", "getMaxShredInsertSlot", "getMinimumBalanceForRentExemption", "getMultipleAccounts", "getProgramAccounts", "getSlot", "getSlotLeader", "getSlotLeaders", "getTokenAccountBalance", "getTokenAccountsByDelegate", "getTokenAccountsByOwner", "getTokenLargestAccounts", "getTokenSupply", "getVoteAccounts", ]; let mut actual = std::vec::Vec::new(); let mut future_transactions = 0_usize; let mut future_blocks_economics = 0_usize; for descriptor in ksp_onchain_transport_lib::current_http_rpc_methods() { match descriptor.coverage_release() { ksp_onchain_transport_lib::HttpRpcCoverageRelease::V0_2_2 => { actual.push(descriptor.method()); assert_eq!(descriptor.documentation_status(), ksp_onchain_transport_lib::RpcDocumentationStatus::Stable); assert_eq!(descriptor.runtime_status(), ksp_onchain_transport_lib::RpcRuntimeStatus::Supported); assert_eq!(descriptor.operation_kind(), ksp_onchain_transport_lib::RpcOperationKind::Read); assert_eq!(descriptor.transport_retry_class(), ksp_onchain_transport_lib::TransportRetryClass::RetrySafe); }, ksp_onchain_transport_lib::HttpRpcCoverageRelease::V0_2_3 => future_transactions += 1, ksp_onchain_transport_lib::HttpRpcCoverageRelease::V0_2_4 => future_blocks_economics += 1, _ => {}, } } actual.sort_unstable(); expected.sort_unstable(); assert_eq!(actual, expected); assert_eq!(actual.len(), 22); assert_eq!(future_transactions, 11); assert_eq!(future_blocks_economics, 15); }