Skip to content

Commit

Permalink
rest of the rest of the
Browse files Browse the repository at this point in the history
  • Loading branch information
adamspofford-dfinity committed Aug 22, 2024
1 parent 46aa1cc commit 6befbf7
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 136 deletions.
112 changes: 10 additions & 102 deletions ic-agent/src/agent/agent_test.rs
Original file line number Diff line number Diff line change
@@ -1,102 +1,45 @@
// Disable these tests without the reqwest feature.
#![cfg(feature = "reqwest")]

use self::mock::{
assert_mock, assert_single_mock, assert_single_mock_count, mock, mock_additional,
};
use crate::{
agent::{http_transport::ReqwestTransport, Status},
export::Principal,
Agent, AgentError, Certificate,
};
use crate::{agent::Status, export::Principal, Agent, AgentError, Certificate};
use candid::{Encode, Nat};
use futures_util::FutureExt;
use ic_certification::{Delegation, Label};
use ic_transport_types::{
NodeSignature, QueryResponse, RejectCode, RejectResponse, ReplyResponse, TransportCallResponse,
};
use reqwest::Client;
use std::{collections::BTreeMap, str::FromStr, sync::Arc, time::Duration};
#[cfg(all(target_family = "wasm", feature = "wasm-bindgen"))]
use wasm_bindgen_test::wasm_bindgen_test;

use crate::agent::http_transport::route_provider::{RoundRobinRouteProvider, RouteProvider};
use crate::agent::route_provider::{RoundRobinRouteProvider, RouteProvider};
#[cfg(all(target_family = "wasm", feature = "wasm-bindgen"))]
wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);

fn make_transport(url: &str) -> ReqwestTransport {
let transport = ReqwestTransport::create(url).unwrap();
#[cfg(feature = "experimental_sync_call")]
{
transport.with_use_call_v3_endpoint()
}
#[cfg(not(feature = "experimental_sync_call"))]
{
transport
}
}

fn make_agent(url: &str) -> Agent {
Agent::builder()
.with_transport(make_transport(url))
.with_verify_query_signatures(false)
.build()
.unwrap()
let builder = Agent::builder().with_url(url);
#[cfg(feature = "experimental_sync_call")]
let builder = builder.with_call_v3_endpoint();
builder.with_verify_query_signatures(false).build().unwrap()
}

fn make_agent_with_route_provider(
route_provider: Arc<dyn RouteProvider>,
tcp_retries: usize,
) -> Agent {
let client = Client::builder()
.build()
.expect("Could not create HTTP client.");
Agent::builder()
.with_transport(
ReqwestTransport::create_with_client_route(route_provider, client)
.unwrap()
.with_max_tcp_errors_retries(tcp_retries),
)
.with_verify_query_signatures(false)
.build()
.unwrap()
}

#[cfg(feature = "hyper")]
fn make_agent_with_hyper_transport_route_provider(
route_provider: Arc<dyn RouteProvider>,
tcp_retries: usize,
) -> Agent {
use super::http_transport::HyperTransport;
use http_body_util::Full;
use hyper_rustls::{HttpsConnector, HttpsConnectorBuilder};
use hyper_util::{
client::legacy::{connect::HttpConnector, Client as LegacyClient},
rt::TokioExecutor,
};
use std::collections::VecDeque;

let connector = HttpsConnectorBuilder::new()
.with_webpki_roots()
.https_or_http()
.enable_http1()
.enable_http2()
.build();
let client: LegacyClient<HttpsConnector<HttpConnector>, Full<VecDeque<u8>>> =
LegacyClient::builder(TokioExecutor::new()).build(connector);
let transport = HyperTransport::create_with_service_route(route_provider, client)
.unwrap()
.with_max_tcp_errors_retries(tcp_retries);
Agent::builder()
.with_transport(transport)
.with_arc_route_provider(route_provider)
.with_max_tcp_error_retries(tcp_retries)
.with_verify_query_signatures(false)
.build()
.unwrap()
}

fn make_untimed_agent(url: &str) -> Agent {
Agent::builder()
.with_transport(ReqwestTransport::create(url).unwrap())
.with_url(url)
.with_verify_query_signatures(false)
.with_ingress_expiry(Some(Duration::from_secs(u32::MAX as _)))
.build()
Expand All @@ -105,7 +48,7 @@ fn make_untimed_agent(url: &str) -> Agent {

fn make_certifying_agent(url: &str) -> Agent {
Agent::builder()
.with_transport(ReqwestTransport::create(url).unwrap())
.with_url(url)
.with_ingress_expiry(Some(Duration::from_secs(u32::MAX as _)))
.build()
.unwrap()
Expand Down Expand Up @@ -426,41 +369,6 @@ async fn reqwest_client_status_okay_when_request_retried() -> Result<(), AgentEr
Ok(())
}

#[cfg_attr(not(target_family = "wasm"), tokio::test)]
#[cfg(feature = "hyper")]
async fn hyper_client_status_okay_when_request_retried() -> Result<(), AgentError> {
let map = BTreeMap::new();
let response = serde_cbor::Value::Map(map);
let (read_mock, url) = mock(
"GET",
"/api/v2/status",
200,
serde_cbor::to_vec(&response)?,
Some("application/cbor"),
)
.await;
// Without retry request should fail.
let non_working_url = "http://127.0.0.1:4444";
let tcp_retries = 0;
let route_provider = RoundRobinRouteProvider::new(vec![non_working_url, &url]).unwrap();
let agent =
make_agent_with_hyper_transport_route_provider(Arc::new(route_provider), tcp_retries);
let result = agent.status().await;
assert!(result.is_err());

// With retry request should succeed.
let tcp_retries = 1;
let route_provider = RoundRobinRouteProvider::new(vec![non_working_url, &url]).unwrap();
let agent =
make_agent_with_hyper_transport_route_provider(Arc::new(route_provider), tcp_retries);
let result = agent.status().await;

assert_mock(read_mock).await;

assert!(result.is_ok());
Ok(())
}

#[cfg_attr(not(target_family = "wasm"), tokio::test)]
#[cfg_attr(target_family = "wasm", wasm_bindgen_test)]
// test that the agent (re)tries to reach the server.
Expand Down
12 changes: 12 additions & 0 deletions ic-agent/src/agent/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,4 +123,16 @@ impl AgentBuilder {
self.config.use_call_v3_endpoint = true;
self
}

/// Retry up to the specified number of times upon encountering underlying TCP errors.
pub fn with_max_tcp_error_retries(mut self, retries: usize) -> Self {
self.config.max_tcp_error_retries = retries;
self
}

/// Don't accept HTTP bodies any larger than `max_size` bytes.
pub fn with_max_response_body_size(mut self, max_size: usize) -> Self {
self.config.max_response_body_size = Some(max_size);
self
}
}
49 changes: 19 additions & 30 deletions ic-agent/src/agent/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1891,10 +1891,10 @@ impl<'agent> IntoFuture for UpdateBuilder<'agent> {
}
}

#[cfg(all(test, feature = "reqwest", not(target_family = "wasm")))]
#[cfg(all(test, not(target_family = "wasm")))]
mod offline_tests {
use super::*;
use futures_util::future::pending;
use tokio::net::TcpListener;
// Any tests that involve the network should go in agent_test, not here.

#[test]
Expand All @@ -1921,36 +1921,25 @@ mod offline_tests {

#[tokio::test]
async fn client_ratelimit() {
struct SlowTransport(Arc<Mutex<usize>>);
impl Transport for SlowTransport {
fn call(
&self,
_effective_canister_id: Principal,
_envelope: Vec<u8>,
) -> AgentFuture<TransportCallResponse> {
*self.0.lock().unwrap() += 1;
Box::pin(pending())
}
fn query(&self, _: Principal, _: Vec<u8>) -> AgentFuture<Vec<u8>> {
*self.0.lock().unwrap() += 1;
Box::pin(pending())
}
fn read_state(&self, _: Principal, _: Vec<u8>) -> AgentFuture<Vec<u8>> {
*self.0.lock().unwrap() += 1;
Box::pin(pending())
}
fn read_subnet_state(&self, _: Principal, _: Vec<u8>) -> AgentFuture<Vec<u8>> {
*self.0.lock().unwrap() += 1;
Box::pin(pending())
}
fn status(&self) -> AgentFuture<Vec<u8>> {
*self.0.lock().unwrap() += 1;
Box::pin(pending())
}
}
let mock_server = TcpListener::bind("127.0.0.1:0").await.unwrap();
let count = Arc::new(Mutex::new(0));
let port = mock_server.local_addr().unwrap().port();
tokio::spawn({
let count = count.clone();
async move {
loop {
let (mut conn, _) = mock_server.accept().await.unwrap();
*count.lock().unwrap() += 1;
tokio::spawn(
// read all data, never reply
async move { tokio::io::copy(&mut conn, &mut tokio::io::sink()).await },
);
}
}
});
let agent = Agent::builder()
.with_transport(SlowTransport(count.clone()))
.with_http_client(Client::builder().http1_only().build().unwrap())
.with_url(format!("http://127.0.0.1:{port}"))
.with_max_concurrent_requests(2)
.build()
.unwrap();
Expand Down
4 changes: 0 additions & 4 deletions ic-agent/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,6 @@
)]
#![cfg_attr(not(target_family = "wasm"), warn(clippy::future_not_send))]
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]

#[cfg(all(feature = "hyper", target_family = "wasm"))]
compile_error!("Feature `hyper` cannot be used from WASM.");

pub mod agent;
pub mod export;
pub mod identity;
Expand Down

0 comments on commit 6befbf7

Please sign in to comment.