Skip to content

Commit d7616ee

Browse files
committed
test: Add test coverage for endpoint manager
1 parent 280ed60 commit d7616ee

File tree

1 file changed

+167
-1
lines changed

1 file changed

+167
-1
lines changed

tests/integration/blockchain/transports/endpoint_manager.rs

Lines changed: 167 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use mockito::Server;
22
use reqwest_middleware::{ClientBuilder, ClientWithMiddleware};
3-
use reqwest_retry::policies::ExponentialBackoff;
3+
use reqwest_retry::{policies::ExponentialBackoff, RetryTransientMiddleware};
44
use serde::Serialize;
55
use serde_json::{json, Value};
66
use std::sync::Arc;
@@ -333,3 +333,169 @@ async fn test_rotate_url_connection_failure() {
333333
&vec![invalid_url.to_string()]
334334
);
335335
}
336+
337+
#[tokio::test]
338+
async fn test_update_client() {
339+
let mut server = Server::new_async().await;
340+
341+
// Set up two different responses to differentiate between clients
342+
let initial_mock = server
343+
.mock("POST", "/")
344+
.with_status(200)
345+
.with_header("content-type", "application/json")
346+
.with_body(r#"{"jsonrpc": "2.0", "result": "initial_client", "id": 1}"#)
347+
.expect(1)
348+
.create_async()
349+
.await;
350+
351+
let mut manager =
352+
EndpointManager::new(get_mock_client_builder(), server.url().as_ref(), vec![]);
353+
354+
// Test initial client
355+
let transport = MockTransport::new();
356+
let initial_result = manager
357+
.send_raw_request(&transport, "test_method", Some(json!(["param1"])))
358+
.await
359+
.unwrap();
360+
assert_eq!(initial_result["result"], "initial_client");
361+
initial_mock.assert();
362+
363+
// Set up mock for new client
364+
let updated_mock = server
365+
.mock("POST", "/")
366+
.with_status(200)
367+
.with_header("content-type", "application/json")
368+
.with_body(r#"{"jsonrpc": "2.0", "result": "updated_client", "id": 1}"#)
369+
.expect(1)
370+
.create_async()
371+
.await;
372+
373+
// Create and update to new client with different configuration
374+
let new_client = ClientBuilder::new(reqwest::Client::new())
375+
.with(RetryTransientMiddleware::new_with_policy(
376+
ExponentialBackoff::builder().build_with_max_retries(3),
377+
))
378+
.build();
379+
manager.update_client(new_client);
380+
381+
// Test updated client
382+
let updated_result = manager
383+
.send_raw_request(&transport, "test_method", Some(json!(["param1"])))
384+
.await
385+
.unwrap();
386+
assert_eq!(updated_result["result"], "updated_client");
387+
updated_mock.assert();
388+
}
389+
390+
#[tokio::test]
391+
async fn test_set_retry_policy() {
392+
let mut server = Server::new_async().await;
393+
394+
// Set up a sequence of responses to test retry behavior
395+
let retry_mock = server
396+
.mock("POST", "/")
397+
.with_status(429) // Too Many Requests
398+
.with_body("Rate limited")
399+
.expect(2) // Expect 2 retries
400+
.create_async()
401+
.await;
402+
403+
let success_mock = server
404+
.mock("POST", "/")
405+
.with_status(200)
406+
.with_header("content-type", "application/json")
407+
.with_body(r#"{"jsonrpc": "2.0", "result": "success_after_retry", "id": 1}"#)
408+
.expect(1)
409+
.create_async()
410+
.await;
411+
412+
let mut manager = EndpointManager::new(
413+
get_mock_client_builder(), // Initial client with no retry policy
414+
server.url().as_ref(),
415+
vec![],
416+
);
417+
418+
// Set a custom retry policy with exactly 2 retries
419+
let retry_policy = ExponentialBackoff::builder().build_with_max_retries(2);
420+
421+
manager.set_retry_policy(retry_policy, TransientErrorRetryStrategy);
422+
423+
// Make request that should trigger retries
424+
let transport = MockTransport::new();
425+
let result = manager
426+
.send_raw_request(&transport, "test_method", Some(json!(["param1"])))
427+
.await
428+
.unwrap();
429+
430+
// Verify that we got the successful response after retries
431+
assert_eq!(result["result"], "success_after_retry");
432+
433+
// Verify that both mocks were called the expected number of times
434+
retry_mock.assert();
435+
success_mock.assert();
436+
}
437+
438+
#[tokio::test]
439+
async fn test_send_raw_request_network_error() {
440+
// Set up with an invalid primary URL that will cause a network error
441+
let invalid_url = "http://invalid-domain-that-will-fail:12345";
442+
let mut valid_server = Server::new_async().await;
443+
444+
// Set up mock for fallback server
445+
let success_mock = valid_server
446+
.mock("POST", "/")
447+
.with_status(200)
448+
.with_header("content-type", "application/json")
449+
.with_body(r#"{"jsonrpc": "2.0", "result": "success", "id": 1}"#)
450+
.expect(1)
451+
.create_async()
452+
.await;
453+
454+
let manager = EndpointManager::new(
455+
get_mock_client_builder(),
456+
invalid_url,
457+
vec![valid_server.url()], // Add valid fallback URL
458+
);
459+
let transport = MockTransport::new();
460+
461+
// Send request - should fail first with network error, then rotate and succeed
462+
let result = manager
463+
.send_raw_request(&transport, "test_method", Some(json!(["param1"])))
464+
.await;
465+
466+
// Verify success after rotation
467+
assert!(result.is_ok());
468+
let response = result.unwrap();
469+
assert_eq!(response["result"], "success");
470+
success_mock.assert();
471+
472+
// Verify URL rotation occurred
473+
assert_eq!(&*manager.active_url.read().await, &valid_server.url());
474+
}
475+
476+
#[tokio::test]
477+
async fn test_send_raw_request_network_error_no_fallback() {
478+
// Set up with an invalid URL and no fallbacks
479+
let invalid_url = "http://invalid-domain-that-will-fail:12345";
480+
let manager = EndpointManager::new(
481+
get_mock_client_builder(),
482+
invalid_url,
483+
vec![], // No fallback URLs
484+
);
485+
let transport = MockTransport::new();
486+
487+
// Send request - should fail with network error and no rotation possible
488+
let result = manager
489+
.send_raw_request(&transport, "test_method", Some(json!(["param1"])))
490+
.await;
491+
492+
// Verify error
493+
assert!(result.is_err());
494+
assert!(result
495+
.unwrap_err()
496+
.to_string()
497+
.contains("Failed to send request"));
498+
499+
// Verify URL didn't change
500+
assert_eq!(&*manager.active_url.read().await, invalid_url);
501+
}

0 commit comments

Comments
 (0)