v0.2.1-pre.002
This commit is contained in:
117
crates/ksp-onchain-transport-lib/unit_tests/json_rpc.rs
Normal file
117
crates/ksp-onchain-transport-lib/unit_tests/json_rpc.rs
Normal file
@@ -0,0 +1,117 @@
|
||||
// file: crates/ksp-onchain-transport-lib/unit_tests/json_rpc.rs
|
||||
// version: 1
|
||||
|
||||
#[test]
|
||||
fn request_serialization_matches_json_rpc_2_0_shape() {
|
||||
let request = super::JsonRpcRequest::new(7, "getBalance", std::vec![serde_json::json!("Address111"), serde_json::json!({"commitment":"confirmed"})])
|
||||
.expect("valid request must construct");
|
||||
let encoded = request.to_json_string().expect("serializable request must encode");
|
||||
let value: serde_json::Value = serde_json::from_str(encoded.as_str()).expect("encoded request must remain JSON");
|
||||
assert_eq!(value["jsonrpc"], serde_json::json!("2.0"));
|
||||
assert_eq!(value["id"], serde_json::json!(7));
|
||||
assert_eq!(value["method"], serde_json::json!("getBalance"));
|
||||
assert_eq!(value["params"].as_array().expect("params must be an array").len(), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn request_rejects_empty_or_untrimmed_method() {
|
||||
assert!(super::JsonRpcRequest::new(1, "", std::vec![]).is_err());
|
||||
assert!(super::JsonRpcRequest::new(1, " getHealth", std::vec![]).is_err());
|
||||
}
|
||||
|
||||
#[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"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn response_parser_preserves_rpc_error_payload() {
|
||||
let response = super::parse_json_rpc_response_text(
|
||||
r#"{"jsonrpc":"2.0","error":{"code":-32005,"message":"Node is unhealthy","data":{"numSlotsBehind":12}},"id":4}"#,
|
||||
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"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn response_parser_rejects_id_mismatch() {
|
||||
let error = super::parse_json_rpc_response_text(r#"{"jsonrpc":"2.0","result":"ok","id":2}"#, 1).expect_err("mismatched id must fail");
|
||||
assert_eq!(error.code(), crate::ERROR_CODE_JSON_RPC_PROTOCOL_INVALID);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn response_parser_rejects_wrong_protocol_version() {
|
||||
let error = super::parse_json_rpc_response_text(r#"{"jsonrpc":"1.0","result":"ok","id":1}"#, 1).expect_err("wrong version must fail");
|
||||
assert_eq!(error.code(), crate::ERROR_CODE_JSON_RPC_PROTOCOL_INVALID);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn response_parser_rejects_both_result_and_error() {
|
||||
let error = super::parse_json_rpc_response_text(r#"{"jsonrpc":"2.0","result":"ok","error":{"code":-1,"message":"bad"},"id":1}"#, 1)
|
||||
.expect_err("mutually exclusive fields must fail");
|
||||
assert_eq!(error.code(), crate::ERROR_CODE_JSON_RPC_PROTOCOL_INVALID);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn response_parser_rejects_missing_result_and_error() {
|
||||
let error = super::parse_json_rpc_response_text(r#"{"jsonrpc":"2.0","id":1}"#, 1).expect_err("missing outcome must fail");
|
||||
assert_eq!(error.code(), crate::ERROR_CODE_JSON_RPC_PROTOCOL_INVALID);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn response_parser_distinguishes_invalid_json_from_protocol_error() {
|
||||
let error = super::parse_json_rpc_response_text("not-json", 1).expect_err("invalid JSON must fail decoding");
|
||||
assert_eq!(error.code(), crate::ERROR_CODE_JSON_DECODE_FAILED);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_error_maps_to_shared_ksp_error_without_copying_remote_payload_into_context() {
|
||||
let response = super::parse_json_rpc_response_text(
|
||||
r#"{"jsonrpc":"2.0","error":{"code":-32000,"message":"SECRET-CANARY","data":{"payload":"SECRET-DATA"}},"id":1}"#,
|
||||
1,
|
||||
)
|
||||
.expect("valid error envelope must parse");
|
||||
let error = response.into_result().expect_err("RPC application error must map to KSP error");
|
||||
assert_eq!(error.code(), crate::ERROR_CODE_RPC_APPLICATION_ERROR);
|
||||
let rendered = format!("{error:?}");
|
||||
assert!(!rendered.contains("SECRET-CANARY"));
|
||||
assert!(!rendered.contains("SECRET-DATA"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn request_debug_omits_parameter_payloads() {
|
||||
let request = super::JsonRpcRequest::new(1, "sendTransaction", std::vec![serde_json::json!("SIGNED-TRANSACTION-SECRET-CANARY")])
|
||||
.expect("test request must construct");
|
||||
let rendered = format!("{request:?}");
|
||||
assert!(rendered.contains("sendTransaction"));
|
||||
assert!(rendered.contains("param_count"));
|
||||
assert!(!rendered.contains("SIGNED-TRANSACTION-SECRET-CANARY"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn response_debug_omits_result_and_remote_error_payloads() {
|
||||
let success = super::parse_json_rpc_response_text(r#"{"jsonrpc":"2.0","result":{"secret":"RESULT-SECRET-CANARY"},"id":1}"#, 1)
|
||||
.expect("test success response must parse");
|
||||
let success_rendered = format!("{success:?}");
|
||||
assert!(!success_rendered.contains("RESULT-SECRET-CANARY"));
|
||||
let failure = super::parse_json_rpc_response_text(
|
||||
r#"{"jsonrpc":"2.0","error":{"code":-32000,"message":"MESSAGE-SECRET-CANARY","data":{"secret":"DATA-SECRET-CANARY"}},"id":2}"#,
|
||||
2,
|
||||
)
|
||||
.expect("test error response must parse");
|
||||
let failure_rendered = format!("{failure:?}");
|
||||
assert!(!failure_rendered.contains("MESSAGE-SECRET-CANARY"));
|
||||
assert!(!failure_rendered.contains("DATA-SECRET-CANARY"));
|
||||
}
|
||||
121
crates/ksp-onchain-transport-lib/unit_tests/rpc_method.rs
Normal file
121
crates/ksp-onchain-transport-lib/unit_tests/rpc_method.rs
Normal file
@@ -0,0 +1,121 @@
|
||||
// file: crates/ksp-onchain-transport-lib/unit_tests/rpc_method.rs
|
||||
// version: 1
|
||||
|
||||
#[test]
|
||||
fn audited_registry_has_expected_current_and_historical_counts() {
|
||||
assert_eq!(super::current_http_rpc_methods().len(), 52);
|
||||
assert_eq!(super::historical_http_rpc_methods().len(), 14);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn audited_registry_method_names_are_unique() {
|
||||
let mut names = std::collections::BTreeSet::<&str>::new();
|
||||
for descriptor in super::current_http_rpc_methods() {
|
||||
assert!(names.insert(descriptor.method()), "duplicate current method {}", descriptor.method());
|
||||
}
|
||||
for descriptor in super::historical_http_rpc_methods() {
|
||||
assert!(names.insert(descriptor.method()), "duplicate historical method {}", descriptor.method());
|
||||
}
|
||||
assert_eq!(names.len(), 66);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn coverage_release_counts_match_recalibrated_matrix() {
|
||||
let mut foundation = 0_usize;
|
||||
let mut accounts_tokens_cluster = 0_usize;
|
||||
let mut transactions = 0_usize;
|
||||
let mut blocks_economics = 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"),
|
||||
}
|
||||
}
|
||||
assert_eq!(foundation, 4);
|
||||
assert_eq!(accounts_tokens_cluster, 22);
|
||||
assert_eq!(transactions, 11);
|
||||
assert_eq!(blocks_economics, 15);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn foundation_canary_assignment_is_exact() {
|
||||
let mut names = std::vec::Vec::<&str>::new();
|
||||
for descriptor in super::current_http_rpc_methods() {
|
||||
if descriptor.coverage_release() == super::HttpRpcCoverageRelease::V0_2_1 {
|
||||
names.push(descriptor.method());
|
||||
}
|
||||
}
|
||||
names.sort_unstable();
|
||||
assert_eq!(names, std::vec!["getBalance", "getGenesisHash", "getHealth", "getVersion"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn historical_methods_are_deprecated_removed_and_not_retryable() {
|
||||
for descriptor in super::historical_http_rpc_methods() {
|
||||
assert_eq!(descriptor.documentation_status(), super::RpcDocumentationStatus::Deprecated);
|
||||
assert_eq!(descriptor.runtime_status(), super::RpcRuntimeStatus::Removed);
|
||||
assert_eq!(descriptor.transport_retry_class(), super::TransportRetryClass::NotApplicable);
|
||||
assert_eq!(descriptor.coverage_release(), super::HttpRpcCoverageRelease::Historical);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_transaction_and_get_block_track_deprecated_legacy_request_form() {
|
||||
let get_transaction = super::find_http_rpc_method("getTransaction").expect("getTransaction descriptor must exist");
|
||||
let get_block = super::find_http_rpc_method("getBlock").expect("getBlock descriptor must exist");
|
||||
assert!(get_transaction.request_form_status().has_deprecated_legacy());
|
||||
assert!(get_block.request_form_status().has_deprecated_legacy());
|
||||
let get_balance = super::find_http_rpc_method("getBalance").expect("getBalance descriptor must exist");
|
||||
assert!(!get_balance.request_form_status().has_deprecated_legacy());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn write_submission_methods_are_never_retry_after_ambiguous_dispatch() {
|
||||
for method in ["sendTransaction", "requestAirdrop"] {
|
||||
let descriptor = super::find_http_rpc_method(method).expect("write descriptor must exist");
|
||||
assert_eq!(descriptor.operation_kind(), super::RpcOperationKind::WriteSubmission);
|
||||
assert_eq!(descriptor.transport_retry_class(), super::TransportRetryClass::NeverAfterDispatch);
|
||||
}
|
||||
let simulation = super::find_http_rpc_method("simulateTransaction").expect("simulation descriptor must exist");
|
||||
assert_eq!(simulation.operation_kind(), super::RpcOperationKind::Simulation);
|
||||
assert_eq!(simulation.transport_retry_class(), super::TransportRetryClass::RetrySafe);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn removed_method_support_check_returns_method_removed_error() {
|
||||
let descriptor = super::find_http_rpc_method("confirmTransaction").expect("historical descriptor must exist");
|
||||
let error = descriptor.ensure_runtime_supported().expect_err("removed method must not be callable");
|
||||
assert_eq!(error.code(), crate::ERROR_CODE_METHOD_REMOVED);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stable_supported_method_passes_runtime_support_check() {
|
||||
let descriptor = super::find_http_rpc_method("getHealth").expect("current descriptor must exist");
|
||||
assert!(descriptor.ensure_runtime_supported().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn supported_unstable_descriptor_executes_central_warning_path() {
|
||||
let descriptor = super::HttpRpcMethodDescriptor::new(
|
||||
"experimentalMethod",
|
||||
super::HttpRpcCategory::Cluster,
|
||||
"experimental_method",
|
||||
super::RpcDocumentationStatus::Unstable,
|
||||
super::RpcRuntimeStatus::Supported,
|
||||
super::RpcRequestFormStatus::Stable,
|
||||
super::RpcOperationKind::Read,
|
||||
super::TransportRetryClass::RetrySafe,
|
||||
std::option::Option::None,
|
||||
super::HttpRpcCoverageRelease::V0_2_1,
|
||||
);
|
||||
assert!(descriptor.requires_method_usage_warning());
|
||||
assert!(descriptor.ensure_runtime_supported().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lookup_rejects_unknown_method_without_affecting_raw_provider_extensions() {
|
||||
assert!(super::find_http_rpc_method("providerCustomMethod").is_none());
|
||||
}
|
||||
207
crates/ksp-onchain-transport-lib/unit_tests/settings.rs
Normal file
207
crates/ksp-onchain-transport-lib/unit_tests/settings.rs
Normal file
@@ -0,0 +1,207 @@
|
||||
// file: crates/ksp-onchain-transport-lib/unit_tests/settings.rs
|
||||
// version: 1
|
||||
|
||||
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) -> super::HttpTransportSettings {
|
||||
let url = super::HttpEndpointUrl::parse(url_text).expect("test URL must be valid");
|
||||
let limits = super::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 = super::HttpEndpointRoleSettings::new(super::HttpRoleName::new("default"), true, std::vec![super::HttpRequestKind::wildcard()], 100, limits);
|
||||
let endpoint = super::HttpEndpointSettings::new(
|
||||
"devnet_public",
|
||||
true,
|
||||
super::HttpProviderName::new("solana-public"),
|
||||
super::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 super::HttpTransportSettings::new(
|
||||
std::vec![endpoint],
|
||||
super::HttpRetrySettings::new(2, std::time::Duration::from_millis(100), std::time::Duration::from_secs(2)),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn endpoint_url_accepts_http_and_https() {
|
||||
assert!(super::HttpEndpointUrl::parse("https://api.devnet.solana.com").is_ok());
|
||||
assert!(super::HttpEndpointUrl::parse("http://127.0.0.1:8899").is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn endpoint_url_rejects_non_http_schemes() {
|
||||
let result = super::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 = super::HttpEndpointUrl::parse("https://provider.invalid/rpc?api-key=SECRET-CANARY").expect("test URL must parse");
|
||||
let rendered = format!("{url:?}");
|
||||
assert!(rendered.contains("<redacted>"));
|
||||
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(<redacted>)"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transport_settings_require_one_enabled_endpoint() {
|
||||
let url = super::HttpEndpointUrl::parse("https://api.devnet.solana.com").expect("test URL must parse");
|
||||
let role = super::HttpEndpointRoleSettings::new(
|
||||
super::HttpRoleName::new("default"),
|
||||
true,
|
||||
std::vec![super::HttpRequestKind::wildcard()],
|
||||
100,
|
||||
super::HttpRoleLimits::new(std::option::Option::None, std::option::Option::None, std::option::Option::None, std::option::Option::None),
|
||||
);
|
||||
let endpoint = super::HttpEndpointSettings::new(
|
||||
"disabled",
|
||||
false,
|
||||
super::HttpProviderName::new("provider"),
|
||||
super::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 = super::HttpTransportSettings::new(
|
||||
std::vec![endpoint],
|
||||
super::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 = super::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 = super::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 = super::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 = super::HttpEndpointRoleSettings::new(
|
||||
super::HttpRoleName::new("default"),
|
||||
true,
|
||||
std::vec![super::HttpRequestKind::wildcard(), super::HttpRequestKind::new("get_balance")],
|
||||
100,
|
||||
endpoint.roles()[0].limits().clone(),
|
||||
);
|
||||
let modified_endpoint = super::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 = super::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 = super::HttpEndpointRoleSettings::new(
|
||||
super::HttpRoleName::new("default"),
|
||||
true,
|
||||
std::vec![super::HttpRequestKind::wildcard()],
|
||||
100,
|
||||
super::HttpRoleLimits::new(std::option::Option::None, std::option::Option::Some(non_zero(2)), std::option::Option::None, std::option::Option::None),
|
||||
);
|
||||
let modified_endpoint = super::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 = super::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 = super::HttpTransportSettings::new(
|
||||
base.endpoints().to_vec(),
|
||||
super::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 = super::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 = super::HttpTransportSettings::new(std::vec![modified_endpoint], base.retry().clone());
|
||||
assert!(settings.validate().is_err());
|
||||
}
|
||||
Reference in New Issue
Block a user