v0.3.13-pre.006
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/runtime_resources.rs
|
||||
// version: 17
|
||||
// version: 18
|
||||
|
||||
fn grpc_endpoint(cluster: &str) -> std::option::Option<ksp_onchain_transport_lib::YellowstoneGrpcEndpointSettings> {
|
||||
return grpc_endpoint_with_identity(cluster, "yellowstone-fixture", "fixture-provider");
|
||||
@@ -62,6 +62,54 @@ fn http_pool(cluster: &str, role_name: &str, request_kind: &str) -> std::option:
|
||||
};
|
||||
}
|
||||
|
||||
fn http_polling_pool_with_identity(
|
||||
cluster: &str,
|
||||
role_name: &str,
|
||||
endpoint_name: &str,
|
||||
provider: &str,
|
||||
request_kinds: &[&str],
|
||||
) -> std::option::Option<ksp_onchain_transport_lib::HttpTransportPool> {
|
||||
let url = match ksp_onchain_transport_lib::HttpEndpointUrl::parse("https://fixture.invalid/poll?token=HTTP-POLL-SECRET-CANARY") {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return std::option::Option::None,
|
||||
};
|
||||
let role = ksp_onchain_transport_lib::HttpEndpointRoleSettings::new(
|
||||
ksp_onchain_transport_lib::HttpRoleName::new(role_name),
|
||||
true,
|
||||
request_kinds.iter().map(|value| return ksp_onchain_transport_lib::HttpRequestKind::new(*value)).collect(),
|
||||
10,
|
||||
ksp_onchain_transport_lib::HttpRoleLimits::new(
|
||||
std::option::Option::None,
|
||||
std::option::Option::None,
|
||||
std::option::Option::None,
|
||||
std::option::Option::None,
|
||||
),
|
||||
);
|
||||
let endpoint = ksp_onchain_transport_lib::HttpEndpointSettings::new(
|
||||
endpoint_name,
|
||||
true,
|
||||
ksp_onchain_transport_lib::HttpProviderName::new(provider),
|
||||
ksp_onchain_transport_lib::HttpClusterName::new(cluster),
|
||||
url,
|
||||
std::time::Duration::from_secs(1),
|
||||
std::time::Duration::from_secs(2),
|
||||
std::option::Option::Some(4),
|
||||
std::vec![role],
|
||||
);
|
||||
let settings = ksp_onchain_transport_lib::HttpTransportSettings::new(
|
||||
std::vec![endpoint],
|
||||
ksp_onchain_transport_lib::HttpRetrySettings::new(1, std::time::Duration::from_millis(10), std::time::Duration::from_millis(20)),
|
||||
);
|
||||
return match ksp_onchain_transport_lib::HttpTransportPool::new(settings) {
|
||||
std::result::Result::Ok(value) => std::option::Option::Some(value),
|
||||
std::result::Result::Err(_) => std::option::Option::None,
|
||||
};
|
||||
}
|
||||
|
||||
fn http_polling_pool(cluster: &str) -> std::option::Option<ksp_onchain_transport_lib::HttpTransportPool> {
|
||||
return http_polling_pool_with_identity(cluster, "live-poll", "poll-fixture", "fixture-provider", &["get_block", "get_blocks_with_limit", "get_slot"]);
|
||||
}
|
||||
|
||||
fn ws_endpoint(
|
||||
cluster: &str,
|
||||
endpoint_name: &str,
|
||||
@@ -2670,3 +2718,183 @@ async fn pre_009_abort_joins_in_flight_hydration_and_clears_pending_projection()
|
||||
assert_eq!(cleaned.processing_frontier_slot(), std::option::Option::None);
|
||||
return;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn v0_3_13_pre_006_http_block_polling_source_validates_bounds_capabilities_and_logical_identity() {
|
||||
let pool = match http_polling_pool("devnet") {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => return,
|
||||
};
|
||||
let source = match crate::RawTransactionIngestHttpBlockPollingSource::new(
|
||||
pool.clone(),
|
||||
ksp_onchain_transport_lib::HttpRoleName::new("live-poll"),
|
||||
ksp_onchain_transport_lib::SolanaCommitment::Confirmed,
|
||||
) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return,
|
||||
};
|
||||
let same_identity_different_timing = match crate::RawTransactionIngestHttpBlockPollingSource::new_with_limits(
|
||||
pool,
|
||||
ksp_onchain_transport_lib::HttpRoleName::new("live-poll"),
|
||||
ksp_onchain_transport_lib::SolanaCommitment::Confirmed,
|
||||
std::time::Duration::from_secs(2),
|
||||
256,
|
||||
) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return,
|
||||
};
|
||||
assert_eq!(source.source_key, same_identity_different_timing.source_key);
|
||||
assert_eq!(source.network.as_str(), "devnet");
|
||||
assert_eq!(source.poll_interval, crate::DEFAULT_RAW_TRANSACTION_INGEST_HTTP_POLL_INTERVAL);
|
||||
assert_eq!(source.max_discovered_blocks_per_cycle, crate::DEFAULT_RAW_TRANSACTION_INGEST_HTTP_POLL_MAX_BLOCKS_PER_CYCLE);
|
||||
let different_endpoint_pool = match http_polling_pool_with_identity(
|
||||
"devnet",
|
||||
"live-poll",
|
||||
"poll-fixture-other",
|
||||
"fixture-provider",
|
||||
&["get_block", "get_blocks_with_limit", "get_slot"],
|
||||
) {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => return,
|
||||
};
|
||||
let different_endpoint = match crate::RawTransactionIngestHttpBlockPollingSource::new(
|
||||
different_endpoint_pool,
|
||||
ksp_onchain_transport_lib::HttpRoleName::new("live-poll"),
|
||||
ksp_onchain_transport_lib::SolanaCommitment::Confirmed,
|
||||
) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return,
|
||||
};
|
||||
assert_ne!(source.source_key, different_endpoint.source_key);
|
||||
let processed = crate::RawTransactionIngestHttpBlockPollingSource::new(
|
||||
match http_polling_pool("devnet") {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => return,
|
||||
},
|
||||
ksp_onchain_transport_lib::HttpRoleName::new("live-poll"),
|
||||
ksp_onchain_transport_lib::SolanaCommitment::Processed,
|
||||
);
|
||||
assert!(processed.is_err());
|
||||
let too_fast = crate::RawTransactionIngestHttpBlockPollingSource::new_with_limits(
|
||||
match http_polling_pool("devnet") {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => return,
|
||||
},
|
||||
ksp_onchain_transport_lib::HttpRoleName::new("live-poll"),
|
||||
ksp_onchain_transport_lib::SolanaCommitment::Confirmed,
|
||||
std::time::Duration::from_millis(99),
|
||||
128,
|
||||
);
|
||||
assert!(too_fast.is_err());
|
||||
let too_slow = crate::RawTransactionIngestHttpBlockPollingSource::new_with_limits(
|
||||
match http_polling_pool("devnet") {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => return,
|
||||
},
|
||||
ksp_onchain_transport_lib::HttpRoleName::new("live-poll"),
|
||||
ksp_onchain_transport_lib::SolanaCommitment::Confirmed,
|
||||
std::time::Duration::from_millis(30_001),
|
||||
128,
|
||||
);
|
||||
assert!(too_slow.is_err());
|
||||
for invalid_limit in [0_u16, 1025_u16] {
|
||||
let invalid = crate::RawTransactionIngestHttpBlockPollingSource::new_with_limits(
|
||||
match http_polling_pool("devnet") {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => return,
|
||||
},
|
||||
ksp_onchain_transport_lib::HttpRoleName::new("live-poll"),
|
||||
ksp_onchain_transport_lib::SolanaCommitment::Confirmed,
|
||||
std::time::Duration::from_secs(1),
|
||||
invalid_limit,
|
||||
);
|
||||
assert!(invalid.is_err());
|
||||
}
|
||||
let missing_capability_pool = match http_polling_pool_with_identity("devnet", "live-poll", "poll-missing", "fixture-provider", &["get_block", "get_slot"]) {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => return,
|
||||
};
|
||||
let missing_capability = crate::RawTransactionIngestHttpBlockPollingSource::new(
|
||||
missing_capability_pool,
|
||||
ksp_onchain_transport_lib::HttpRoleName::new("live-poll"),
|
||||
ksp_onchain_transport_lib::SolanaCommitment::Confirmed,
|
||||
);
|
||||
assert!(missing_capability.is_err());
|
||||
let debug = std::format!("{source:?}");
|
||||
assert!(!debug.contains("HTTP-POLL-SECRET-CANARY"));
|
||||
assert!(!debug.contains("fixture.invalid"));
|
||||
return;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn v0_3_13_pre_006_http_block_polling_discovery_never_moves_before_run_frontier_and_requires_strict_order() {
|
||||
assert!(super::validate_http_block_polling_discovery(100, &[]).is_ok());
|
||||
assert!(super::validate_http_block_polling_discovery(100, &[100, 102, 105]).is_ok());
|
||||
assert!(super::validate_http_block_polling_discovery(100, &[99]).is_err());
|
||||
assert!(super::validate_http_block_polling_discovery(100, &[100, 100]).is_err());
|
||||
assert!(super::validate_http_block_polling_discovery(100, &[102, 101]).is_err());
|
||||
return;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn v0_3_13_pre_006_http_block_polling_qualifies_legacy_v0_v1_and_rejects_ambiguous_or_future_versions() {
|
||||
let cases = [
|
||||
(ksp_onchain_transport_lib::SolanaTransactionVersion::Legacy, ksp_raw_transaction_lib::RawTransactionVersion::Legacy),
|
||||
(ksp_onchain_transport_lib::SolanaTransactionVersion::Number(0), ksp_raw_transaction_lib::RawTransactionVersion::Number(0)),
|
||||
(ksp_onchain_transport_lib::SolanaTransactionVersion::Number(1), ksp_raw_transaction_lib::RawTransactionVersion::Number(1)),
|
||||
];
|
||||
for (wire, expected) in cases {
|
||||
let qualified = super::qualify_http_block_polling_version(&ksp_onchain_transport_lib::SolanaWireField::Value(wire));
|
||||
let qualified = match qualified {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return,
|
||||
};
|
||||
let qualified = match qualified {
|
||||
ksp_raw_transaction_lib::RawTransactionWireField::Value(value) => value,
|
||||
_ => return,
|
||||
};
|
||||
assert_eq!(qualified, expected);
|
||||
}
|
||||
assert!(
|
||||
super::qualify_http_block_polling_version(&ksp_onchain_transport_lib::SolanaWireField::Value(
|
||||
ksp_onchain_transport_lib::SolanaTransactionVersion::Number(2),
|
||||
))
|
||||
.is_err()
|
||||
);
|
||||
assert!(super::qualify_http_block_polling_version(&ksp_onchain_transport_lib::SolanaWireField::Omitted).is_err());
|
||||
assert!(super::qualify_http_block_polling_version(&ksp_onchain_transport_lib::SolanaWireField::Null).is_err());
|
||||
return;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn v0_3_13_pre_006_runtime_resources_reject_duplicate_http_polling_identity_even_when_timing_differs() {
|
||||
let first = match crate::RawTransactionIngestHttpBlockPollingSource::new(
|
||||
match http_polling_pool("devnet") {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => return,
|
||||
},
|
||||
ksp_onchain_transport_lib::HttpRoleName::new("live-poll"),
|
||||
ksp_onchain_transport_lib::SolanaCommitment::Confirmed,
|
||||
) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return,
|
||||
};
|
||||
let duplicate = match crate::RawTransactionIngestHttpBlockPollingSource::new_with_limits(
|
||||
match http_polling_pool("devnet") {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => return,
|
||||
},
|
||||
ksp_onchain_transport_lib::HttpRoleName::new("live-poll"),
|
||||
ksp_onchain_transport_lib::SolanaCommitment::Confirmed,
|
||||
std::time::Duration::from_secs(2),
|
||||
256,
|
||||
) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return,
|
||||
};
|
||||
let mut resources = crate::RawTransactionIngestRuntimeResources::from_http_block_polling_source(first);
|
||||
let pushed = resources.try_push_http_block_polling_source(duplicate);
|
||||
assert!(pushed.is_err());
|
||||
assert_eq!(resources.source_count(), 1);
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user