v0.2.1-pre.002-fix.001

This commit is contained in:
2026-08-17 18:46:52 +02:00
parent 0cff0406ab
commit d3fc0c6d69
8 changed files with 209 additions and 33 deletions

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-onchain-transport-lib/src/settings.rs
// version: 1
// version: 2
/// Runtime HTTP endpoint URL owned by Transport.
///
@@ -475,13 +475,13 @@ fn validate_endpoint(endpoint: &crate::HttpEndpointSettings, endpoint_index: usi
if endpoint.request_timeout().is_zero() {
return invalid_settings("HTTP request timeout must be greater than zero", format!("endpoints[{endpoint_index}].request_timeout").as_str());
}
if let std::option::Option::Some(max_idle) = endpoint.max_idle_connections_per_host() {
if max_idle == 0 {
return invalid_settings(
"max idle connections per host must be greater than zero when configured",
format!("endpoints[{endpoint_index}].max_idle_connections_per_host").as_str(),
);
}
if let std::option::Option::Some(max_idle) = endpoint.max_idle_connections_per_host()
&& max_idle == 0
{
return invalid_settings(
"max idle connections per host must be greater than zero when configured",
format!("endpoints[{endpoint_index}].max_idle_connections_per_host").as_str(),
);
}
if endpoint.roles().is_empty() {
return invalid_settings("HTTP endpoint must declare at least one role", format!("endpoints[{endpoint_index}].roles").as_str());
@@ -548,13 +548,13 @@ fn validate_role(role: &crate::HttpEndpointRoleSettings, endpoint_index: usize,
format!("endpoints[{endpoint_index}].roles[{role_index}].limits.burst_capacity").as_str(),
);
}
if let std::option::Option::Some(pause) = role.limits().pause_after_rate_limit() {
if pause.is_zero() {
return invalid_settings(
"rate-limit cooldown must be greater than zero when configured",
format!("endpoints[{endpoint_index}].roles[{role_index}].limits.pause_after_rate_limit").as_str(),
);
}
if let std::option::Option::Some(pause) = role.limits().pause_after_rate_limit()
&& pause.is_zero()
{
return invalid_settings(
"rate-limit cooldown must be greater than zero when configured",
format!("endpoints[{endpoint_index}].roles[{role_index}].limits.pause_after_rate_limit").as_str(),
);
}
return std::result::Result::Ok(());
}

View File

@@ -1,5 +1,7 @@
// file: crates/ksp-onchain-transport-lib/tests/dependency_boundary.rs
// version: 1
// version: 2
//! Integration canary for the direct dependency firewall of `ksp-onchain-transport-lib`.
#[test]
fn transport_manifest_preserves_ksp_dependency_firewall() {

View File

@@ -1,5 +1,7 @@
// file: crates/ksp-onchain-transport-lib/tests/public_api.rs
// version: 1
// version: 2
//! Integration tests for the public `ksp-onchain-transport-lib` consumer contract.
#[test]
fn public_settings_contract_is_constructible_without_config_dependency() {

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-onchain-transport-lib/unit_tests/json_rpc.rs
// version: 1
// version: 2
#[test]
fn request_serialization_matches_json_rpc_2_0_shape() {
@@ -22,9 +22,9 @@ fn request_rejects_empty_or_untrimmed_method() {
#[test]
fn response_parser_preserves_null_success_result() {
let response = super::parse_json_rpc_response_text(r#"{"jsonrpc":"2.0","result":null,"id":9}"#, 9).expect("null result is a valid success payload");
match response {
super::JsonRpcResponse::Success(success) => assert!(success.result().is_null()),
super::JsonRpcResponse::Error(_) => assert!(false, "success response must not parse as error"),
assert!(matches!(&response, super::JsonRpcResponse::Success(_)), "success response must not parse as error");
if let super::JsonRpcResponse::Success(success) = response {
assert!(success.result().is_null());
}
}
@@ -35,13 +35,11 @@ fn response_parser_preserves_rpc_error_payload() {
4,
)
.expect("valid JSON-RPC error envelope must parse");
match response {
super::JsonRpcResponse::Error(error_response) => {
assert_eq!(error_response.error().code(), -32005);
assert_eq!(error_response.error().message(), "Node is unhealthy");
assert_eq!(error_response.error().data(), std::option::Option::Some(&serde_json::json!({"numSlotsBehind":12})));
},
super::JsonRpcResponse::Success(_) => assert!(false, "RPC error response must not parse as success"),
assert!(matches!(&response, super::JsonRpcResponse::Error(_)), "RPC error response must not parse as success");
if let super::JsonRpcResponse::Error(error_response) = response {
assert_eq!(error_response.error().code(), -32005);
assert_eq!(error_response.error().message(), "Node is unhealthy");
assert_eq!(error_response.error().data(), std::option::Option::Some(&serde_json::json!({"numSlotsBehind":12})));
}
}

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-onchain-transport-lib/unit_tests/rpc_method.rs
// version: 1
// version: 2
#[test]
fn audited_registry_has_expected_current_and_historical_counts() {
@@ -25,15 +25,17 @@ fn coverage_release_counts_match_recalibrated_matrix() {
let mut accounts_tokens_cluster = 0_usize;
let mut transactions = 0_usize;
let mut blocks_economics = 0_usize;
let mut historical = 0_usize;
for descriptor in super::current_http_rpc_methods() {
match descriptor.coverage_release() {
super::HttpRpcCoverageRelease::V0_2_1 => foundation += 1,
super::HttpRpcCoverageRelease::V0_2_2 => accounts_tokens_cluster += 1,
super::HttpRpcCoverageRelease::V0_2_3 => transactions += 1,
super::HttpRpcCoverageRelease::V0_2_4 => blocks_economics += 1,
super::HttpRpcCoverageRelease::Historical => assert!(false, "current method must not be historical"),
super::HttpRpcCoverageRelease::Historical => historical += 1,
}
}
assert_eq!(historical, 0);
assert_eq!(foundation, 4);
assert_eq!(accounts_tokens_cluster, 22);
assert_eq!(transactions, 11);