// file: crates/ksp-onchain-transport-lib/unit_tests/settings.rs // version: 2 fn non_zero(value: u32) -> std::num::NonZeroU32 { return std::num::NonZeroU32::new(value).expect("test non-zero value must remain non-zero"); } fn valid_settings(url_text: &str) -> crate::HttpTransportSettings { let url = crate::HttpEndpointUrl::parse(url_text).expect("test URL must be valid"); let limits = crate::HttpRoleLimits::new( std::option::Option::Some(non_zero(10)), std::option::Option::Some(non_zero(20)), std::option::Option::Some(non_zero(4)), std::option::Option::Some(std::time::Duration::from_millis(500)), ); let role = crate::HttpEndpointRoleSettings::new(crate::HttpRoleName::new("default"), true, std::vec![crate::HttpRequestKind::wildcard()], 100, limits); let endpoint = crate::HttpEndpointSettings::new( "devnet_public", true, crate::HttpProviderName::new("solana-public"), crate::HttpClusterName::new("devnet"), url, std::time::Duration::from_secs(5), std::time::Duration::from_secs(15), std::option::Option::Some(8), std::vec![role], ); return crate::HttpTransportSettings::new( std::vec![endpoint], crate::HttpRetrySettings::new(2, std::time::Duration::from_millis(100), std::time::Duration::from_secs(2)), ); } #[test] fn endpoint_url_accepts_http_and_https() { assert!(crate::HttpEndpointUrl::parse("https://api.devnet.solana.com").is_ok()); assert!(crate::HttpEndpointUrl::parse("http://127.0.0.1:8899").is_ok()); } #[test] fn endpoint_url_rejects_non_http_schemes() { let result = crate::HttpEndpointUrl::parse("ws://api.devnet.solana.com"); let error = result.expect_err("WebSocket URL must not be accepted by HTTP settings"); assert_eq!(error.code(), crate::ERROR_CODE_INVALID_SETTINGS); } #[test] fn endpoint_url_debug_redacts_secret_material() { let url = crate::HttpEndpointUrl::parse("https://provider.invalid/rpc?api-key=SECRET-CANARY").expect("test URL must parse"); let rendered = format!("{url:?}"); assert!(rendered.contains("")); assert!(!rendered.contains("SECRET-CANARY")); assert!(!rendered.contains("provider.invalid")); } #[test] fn valid_transport_settings_pass_validation() { let settings = valid_settings("https://api.devnet.solana.com"); assert!(settings.validate().is_ok()); } #[test] fn transport_settings_debug_does_not_leak_endpoint_url() { let settings = valid_settings("https://provider.invalid/rpc?api-key=SECRET-CANARY"); let rendered = format!("{settings:?}"); assert!(!rendered.contains("SECRET-CANARY")); assert!(!rendered.contains("provider.invalid")); assert!(rendered.contains("HttpEndpointUrl()")); } #[test] fn transport_settings_require_one_enabled_endpoint() { let url = crate::HttpEndpointUrl::parse("https://api.devnet.solana.com").expect("test URL must parse"); let role = crate::HttpEndpointRoleSettings::new( crate::HttpRoleName::new("default"), true, std::vec![crate::HttpRequestKind::wildcard()], 100, crate::HttpRoleLimits::new(std::option::Option::None, std::option::Option::None, std::option::Option::None, std::option::Option::None), ); let endpoint = crate::HttpEndpointSettings::new( "disabled", false, crate::HttpProviderName::new("provider"), crate::HttpClusterName::new("devnet"), url, std::time::Duration::from_secs(1), std::time::Duration::from_secs(1), std::option::Option::None, std::vec![role], ); let settings = crate::HttpTransportSettings::new( std::vec![endpoint], crate::HttpRetrySettings::new(1, std::time::Duration::from_millis(1), std::time::Duration::from_millis(2)), ); let error = settings.validate().expect_err("all-disabled settings must fail"); assert_eq!(error.code(), crate::ERROR_CODE_INVALID_SETTINGS); } #[test] fn transport_settings_reject_duplicate_endpoint_names() { let first = valid_settings("https://one.invalid"); let second = valid_settings("https://two.invalid"); let settings = crate::HttpTransportSettings::new(std::vec![first.endpoints()[0].clone(), second.endpoints()[0].clone()], first.retry().clone()); let error = settings.validate().expect_err("duplicate endpoint names must fail"); assert_eq!(error.code(), crate::ERROR_CODE_INVALID_SETTINGS); } #[test] fn transport_settings_reject_duplicate_roles() { let base = valid_settings("https://api.devnet.solana.com"); let endpoint = &base.endpoints()[0]; let duplicated_endpoint = crate::HttpEndpointSettings::new( endpoint.name(), true, endpoint.provider().clone(), endpoint.cluster().clone(), endpoint.url().clone(), endpoint.connect_timeout(), endpoint.request_timeout(), endpoint.max_idle_connections_per_host(), std::vec![endpoint.roles()[0].clone(), endpoint.roles()[0].clone()], ); let settings = crate::HttpTransportSettings::new(std::vec![duplicated_endpoint], base.retry().clone()); assert!(settings.validate().is_err()); } #[test] fn transport_settings_reject_wildcard_mixed_with_specific_kind() { let base = valid_settings("https://api.devnet.solana.com"); let endpoint = &base.endpoints()[0]; let role = crate::HttpEndpointRoleSettings::new( crate::HttpRoleName::new("default"), true, std::vec![crate::HttpRequestKind::wildcard(), crate::HttpRequestKind::new("get_balance")], 100, endpoint.roles()[0].limits().clone(), ); let modified_endpoint = crate::HttpEndpointSettings::new( endpoint.name(), true, endpoint.provider().clone(), endpoint.cluster().clone(), endpoint.url().clone(), endpoint.connect_timeout(), endpoint.request_timeout(), endpoint.max_idle_connections_per_host(), std::vec![role], ); let settings = crate::HttpTransportSettings::new(std::vec![modified_endpoint], base.retry().clone()); assert!(settings.validate().is_err()); } #[test] fn transport_settings_reject_burst_without_rps() { let base = valid_settings("https://api.devnet.solana.com"); let endpoint = &base.endpoints()[0]; let role = crate::HttpEndpointRoleSettings::new( crate::HttpRoleName::new("default"), true, std::vec![crate::HttpRequestKind::wildcard()], 100, crate::HttpRoleLimits::new(std::option::Option::None, std::option::Option::Some(non_zero(2)), std::option::Option::None, std::option::Option::None), ); let modified_endpoint = crate::HttpEndpointSettings::new( endpoint.name(), true, endpoint.provider().clone(), endpoint.cluster().clone(), endpoint.url().clone(), endpoint.connect_timeout(), endpoint.request_timeout(), endpoint.max_idle_connections_per_host(), std::vec![role], ); let settings = crate::HttpTransportSettings::new(std::vec![modified_endpoint], base.retry().clone()); assert!(settings.validate().is_err()); } #[test] fn transport_settings_reject_reversed_retry_backoff() { let base = valid_settings("https://api.devnet.solana.com"); let settings = crate::HttpTransportSettings::new( base.endpoints().to_vec(), crate::HttpRetrySettings::new(2, std::time::Duration::from_secs(2), std::time::Duration::from_secs(1)), ); assert!(settings.validate().is_err()); } #[test] fn transport_settings_reject_zero_request_timeout() { let base = valid_settings("https://api.devnet.solana.com"); let endpoint = &base.endpoints()[0]; let modified_endpoint = crate::HttpEndpointSettings::new( endpoint.name(), true, endpoint.provider().clone(), endpoint.cluster().clone(), endpoint.url().clone(), endpoint.connect_timeout(), std::time::Duration::ZERO, endpoint.max_idle_connections_per_host(), endpoint.roles().to_vec(), ); let settings = crate::HttpTransportSettings::new(std::vec![modified_endpoint], base.retry().clone()); assert!(settings.validate().is_err()); }