diff --git a/src/net/mod.rs b/src/net/mod.rs index b98df06..89691a5 100644 --- a/src/net/mod.rs +++ b/src/net/mod.rs @@ -7,15 +7,14 @@ mod system; pub use result::{Error, Result}; -pub use system::{MatchOn, Net}; -use system::{Mocked, Unmocked}; +pub use system::{MatchOn, MockNet, Net}; /// Creates a new `Net`. -pub const fn new() -> Net { - Net::::new() +pub const fn new() -> Net { + Net::new() } /// Creates a new `MockNet` for use in tests. -pub fn mock() -> Net { - Net::::new() +pub fn mock() -> MockNet { + Net::mock() } diff --git a/src/net/system.rs b/src/net/system.rs index 4af771f..4776e46 100644 --- a/src/net/system.rs +++ b/src/net/system.rs @@ -1,12 +1,15 @@ // -use std::{marker::PhantomData, sync::RwLock}; +use std::{marker::PhantomData, ops::Deref, sync::RwLock}; use super::{Error, Result}; pub trait NetType {} +#[derive(Debug)] pub struct Mocked; impl NetType for Mocked {} + +#[derive(Debug)] pub struct Unmocked; impl NetType for Unmocked {} @@ -21,19 +24,73 @@ pub enum MatchOn { } #[derive(Debug)] -pub struct Plan { +struct Plan { request: reqwest::Request, response: reqwest::Response, match_on: Vec, } #[derive(Debug)] -pub struct Net { +pub struct Net { + inner: InnerNet, + mock: Option>, +} +impl Net { + // constructors + pub(super) const fn new() -> Self { + Self { + inner: InnerNet::::new(), + mock: None, + } + } + + pub(super) const fn mock() -> MockNet { + MockNet { + inner: InnerNet::::new(), + } + } +} +impl Net { + // public interface + pub fn client(&self) -> reqwest::Client { + self.inner.client() + } + + pub async fn send(&self, request: reqwest::RequestBuilder) -> Result { + match &self.mock { + Some(mock) => mock.send(request).await, + None => self.inner.send(request).await, + } + } +} + +#[derive(Debug)] +pub struct MockNet { + inner: InnerNet, +} +impl Deref for MockNet { + type Target = InnerNet; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} +impl From for Net { + fn from(mock_net: MockNet) -> Self { + Self { + inner: InnerNet::::new(), + mock: Some(mock_net.inner), + } + } +} + +#[derive(Debug)] +pub struct InnerNet { _type: PhantomData, plans: RwLock, } -impl Net { - pub(crate) const fn new() -> Self { +impl InnerNet { + const fn new() -> Self { Self { _type: PhantomData, plans: RwLock::new(vec![]), @@ -45,13 +102,13 @@ impl Net { } } -impl Net { +impl InnerNet { pub fn client(&self) -> reqwest::Client { Default::default() } } -impl Net { - pub(crate) const fn new() -> Self { +impl InnerNet { + const fn new() -> Self { Self { _type: PhantomData, plans: RwLock::new(vec![]), @@ -135,7 +192,7 @@ impl Net { Ok(()) } } -impl Drop for Net { +impl Drop for InnerNet { fn drop(&mut self) { let Ok(read_plans) = self.plans.read() else { return; @@ -145,7 +202,7 @@ impl Drop for Net { } pub struct OnRequest<'net> { - net: &'net Net, + net: &'net InnerNet, request: reqwest::Request, match_on: Vec, } diff --git a/tests/net.rs b/tests/net.rs index 8e5dcfd..248dc56 100644 --- a/tests/net.rs +++ b/tests/net.rs @@ -1,6 +1,6 @@ use assert2::let_assert; // -use kxio::net::{Error, MatchOn}; +use kxio::net::{Error, MatchOn, Net}; #[tokio::test] async fn test_get_url() { @@ -21,7 +21,10 @@ async fn test_get_url() { .expect("on request, respond"); //when - let response = net.send(client.get(url)).await.expect("response"); + let response = Net::from(net) + .send(client.get(url)) + .await + .expect("response"); //then assert_eq!(response.status(), http::StatusCode::OK); @@ -78,7 +81,10 @@ async fn test_post_url() { .expect("on request, respond"); //when - let response = net.send(client.post(url)).await.expect("reponse"); + let response = Net::from(net) + .send(client.post(url)) + .await + .expect("reponse"); //then assert_eq!(response.status(), http::StatusCode::OK); @@ -109,7 +115,7 @@ async fn test_post_by_method() { //when // This request is a different url - but should still match - let response = net + let response = Net::from(net) .send(client.post("https://some.other.url")) .await .expect("response"); @@ -143,7 +149,10 @@ async fn test_post_by_url() { //when // This request is a GET, not POST - but should still match - let response = net.send(client.get(url)).await.expect("response"); + let response = Net::from(net) + .send(client.get(url)) + .await + .expect("response"); //then assert_eq!(response.status(), http::StatusCode::OK); @@ -179,7 +188,7 @@ async fn test_post_by_body() { //when // This request is a GET, not POST - but should still match - let response = net + let response = Net::from(net) .send(client.get("https://some.other.url").body("match on body")) .await .expect("response"); @@ -222,7 +231,7 @@ async fn test_post_by_headers() { //when // This request is a GET, not POST - but should still match - let response = net + let response = Net::from(net) .send( client .get("https://some.other.url") @@ -261,7 +270,7 @@ async fn test_unused_post() { //when // don't send the planned request - // let _response = net.send(client.post(url)).await.expect("send"); + // let _response = Net::from(net).send(client.post(url)).await.expect("send"); //then // Drop implementation for net should panic