Files
khadhroony-solana-project/crates/ksp-offchain-transport-lib/unit_tests/provider.rs
2026-08-25 19:45:06 +02:00

78 lines
4.0 KiB
Rust

// file: crates/ksp-offchain-transport-lib/unit_tests/provider.rs
// version: 1
#[test]
fn provider_id_is_opaque_bounded_and_stable() -> ksp_core_lib::Result<()> {
let id = match crate::PriceProviderId::new("coingecko-main") {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
assert_eq!(id.as_str(), "coingecko-main");
assert_eq!(id.to_string(), "coingecko-main");
for invalid in ["", "CoinGecko", "coin gecko", "coin/gecko", "é"] {
assert!(crate::PriceProviderId::new(invalid).is_err());
}
return std::result::Result::Ok(());
}
#[test]
fn provider_descriptor_preserves_semantics_auth_limits_and_informational_quota() -> ksp_core_lib::Result<()> {
let id = match crate::PriceProviderId::new("provider-a") {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let rate_limit = match crate::PriceProviderRateLimit::fixed(1, 2, std::option::Option::None, crate::PriceProviderRateLimitScope::Ip) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let quota = match crate::PriceProviderLongTermQuota::new(10_000, crate::PriceProviderQuotaPeriod::Month, crate::PriceProviderQuotaUnit::Credits) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let descriptor = match crate::PriceProviderDescriptor::new(
id,
"Provider A",
crate::PriceSemantics::AggregatedMarket,
crate::PriceProviderAuthMode::OptionalApiKey,
rate_limit,
std::option::Option::Some(quota),
true,
) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
assert_eq!(descriptor.display_name(), "Provider A");
assert_eq!(descriptor.semantics(), crate::PriceSemantics::AggregatedMarket);
assert_eq!(descriptor.auth_mode(), crate::PriceProviderAuthMode::OptionalApiKey);
assert_eq!(descriptor.rate_limit(), rate_limit);
assert_eq!(descriptor.long_term_quota(), std::option::Option::Some(quota));
assert!(descriptor.supports_sol_usd());
return std::result::Result::Ok(());
}
#[test]
fn provider_limit_descriptors_reject_zero_and_model_dynamic_scope() {
assert!(crate::PriceProviderRateLimit::fixed(0, 1, std::option::Option::None, crate::PriceProviderRateLimitScope::Ip).is_err());
assert!(crate::PriceProviderRateLimit::fixed(1, 0, std::option::Option::None, crate::PriceProviderRateLimitScope::Ip).is_err());
assert!(crate::PriceProviderRateLimit::fixed(1, 1, std::option::Option::Some(0), crate::PriceProviderRateLimitScope::Ip).is_err());
let dynamic = crate::PriceProviderRateLimit::dynamic(crate::PriceProviderRateLimitScope::Ip);
assert_eq!(dynamic.kind(), crate::PriceProviderRateLimitKind::Dynamic);
assert_eq!(dynamic.scope(), crate::PriceProviderRateLimitScope::Ip);
assert_eq!(dynamic.requests(), std::option::Option::None);
assert_eq!(dynamic.window_seconds(), std::option::Option::None);
assert_eq!(dynamic.burst(), std::option::Option::None);
}
#[test]
fn provider_availability_keeps_cooldown_and_outage_distinct() -> ksp_core_lib::Result<()> {
let id = match crate::PriceProviderId::new("jupiter") {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let retry_at = crate::PriceTimestamp::from_unix_millis(1_777_777_777_000);
let state = crate::PriceProviderState::new(id, crate::PriceProviderAvailability::CoolingDown { retry_at });
assert_eq!(state.availability(), crate::PriceProviderAvailability::CoolingDown { retry_at });
assert_ne!(state.availability(), crate::PriceProviderAvailability::TemporarilyUnavailable { retry_at: std::option::Option::Some(retry_at) });
return std::result::Result::Ok(());
}