Skip to content

Commit

Permalink
Merge pull request #90 from kana-rus/add_testing_oneshot_with
Browse files Browse the repository at this point in the history
Add testing oneshot with
  • Loading branch information
kanarus authored Feb 15, 2024
2 parents e04e224 + ae499c5 commit 642d58d
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 84 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ tokio = { version = "1", features = ["full"] }

```rust,no_run
use ohkami::prelude::*;
use ohkami::typed::status::{NoContent};
use ohkami::typed::status::NoContent;
async fn health_check() -> NoContent {
NoContent
Expand Down Expand Up @@ -119,7 +119,7 @@ async fn create_user(body: CreateUserRequest<'_>) -> Created<User> {
})
}
```
`#[Query]`, `#[Payload( 〜 )]` implements `FromRequest` trait for the struct.
`#[Query]`, `#[Payload( 〜 )]` derives `FromRequest` trait impl for the struct.

( with path params : `({path params}, {FromRequest value}s...)` )

Expand Down
2 changes: 1 addition & 1 deletion ohkami/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ features = ["rt_tokio", "custom-header"]

[dependencies]
ohkami_lib = { version = "=0.1.1", path = "../ohkami_lib" }
ohkami_macros = { version = "=0.5.1", path = "../ohkami_macros" }
ohkami_macros = { version = "=0.5.2", path = "../ohkami_macros" }
tokio = { version = "1", optional = true, features = ["net", "rt", "io-util", "sync"] }
async-std = { version = "1", optional = true }
byte_reader = { version = "2.0.0", features = ["text"] }
Expand Down
36 changes: 18 additions & 18 deletions ohkami/src/ohkami/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,11 @@ use crate::Method;
///
/// fn my_ohkami() -> Ohkami {
/// let api_ohkami = Ohkami::with((Auth,), (
/// "/users".
/// POST(create_user),
/// "/users/:id".
/// GET(get_user_by_id).
/// PATCH(update_user),
/// "/users"
/// .POST(create_user),
/// "/users/:id"
/// .GET(get_user_by_id)
/// .PATCH(update_user),
/// ));
///
/// Ohkami::new((
Expand Down Expand Up @@ -119,7 +119,7 @@ use crate::Method;
/// todo!()
/// }
/// ```
#[cfg_attr(all(feature="DEBUG", test), derive(Clone))]
#[cfg_attr(feature="testing", derive(Clone))]
pub struct Ohkami {
pub(crate) routes: TrieRouter,

Expand All @@ -128,7 +128,7 @@ pub struct Ohkami {
}

impl Ohkami {
/// - `routes` is tuple of routing item :
/// - `routes` is a tuple of routing items :
///
/// ```
/// # use ohkami::Route;
Expand All @@ -139,11 +139,11 @@ impl Ohkami {
/// #
/// # let _ =
/// (
/// "/a".
/// GET(handler1).
/// POST(handler2),
/// "/b".
/// PUT(handler3),
/// "/a"
/// .GET(handler1)
/// .POST(handler2),
/// "/b"
/// .PUT(handler3),
/// //...
/// )
/// # ;
Expand Down Expand Up @@ -176,7 +176,7 @@ impl Ohkami {
///
/// <br/>
///
/// - `routes` is tuple of routing item :
/// - `routes` is a tuple of routing items :
///
/// ```
/// # use ohkami::Route;
Expand All @@ -187,11 +187,11 @@ impl Ohkami {
/// #
/// # let _ =
/// (
/// "/a".
/// GET(handler1).
/// POST(handler2),
/// "/b".
/// PUT(handler3),
/// "/a"
/// .GET(handler1)
/// .POST(handler2),
/// "/b"
/// .PUT(handler3),
/// //...
/// )
/// # ;
Expand Down
84 changes: 84 additions & 0 deletions ohkami/src/ohkami/router/_test.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![allow(non_snake_case)]
#![cfg(all(feature="testing", feature="utils"))]
use crate::prelude::*;
use crate::testing::*;
Expand Down Expand Up @@ -246,3 +247,86 @@ fn my_ohkami() -> Ohkami {
o.oneshot(req).await;
assert_eq!(*N().lock().unwrap(), 4);
}


#[crate::__rt__::test] async fn test_global_fangs_registration() {
use std::sync::{OnceLock, Mutex};

async fn h() -> &'static str {"Hello"}

fn N() -> &'static Mutex<usize> {
static N: OnceLock<Mutex<usize>> = OnceLock::new();
N.get_or_init(|| Mutex::new(0))
}

struct APIIncrement;
impl FrontFang for APIIncrement {
fn bite(&self, _: &mut Request) -> impl std::future::Future<Output = Result<(), Response>> + Send {
*N().lock().unwrap() += 1;
async {Ok(())}
}
}

struct GlobalIncrement;
impl FrontFang for GlobalIncrement {
fn bite(&self, _: &mut Request) -> impl std::future::Future<Output = Result<(), Response>> + Send {
*N().lock().unwrap() += 2;
async {Ok(())}
}
}

struct NotFoundIncrement;
impl BackFang for NotFoundIncrement {
fn bite(&self, res: &mut Response, _req: &Request) -> impl std::future::Future<Output = Result<(), Response>> + Send {
if res.status == Status::NotFound {
*N().lock().unwrap() += 3;
}
async {Ok(())}
}
}

let o = Ohkami::new((
"/healthz".GET(h),
"/api".By(Ohkami::with(APIIncrement, (
"/a".GET(h),
"/b".GET(h),
)))
));


dbg!(o.clone().into_router());
dbg!(o.clone().into_router().into_radix());


let req = TestRequest::GET("/healthz");
o.oneshot_with((), req).await;
assert_eq!(*N().lock().unwrap(), 0);

let req = TestRequest::GET("/healthz");
o.oneshot_with((NotFoundIncrement,), req).await;
assert_eq!(*N().lock().unwrap(), 0);

let req = TestRequest::GET("/healthz");
o.oneshot_with((GlobalIncrement, NotFoundIncrement), req).await;
assert_eq!(*N().lock().unwrap(), 2);

let req = TestRequest::GET("/healthy");
o.oneshot_with((NotFoundIncrement,), req).await;
assert_eq!(*N().lock().unwrap(), 5);

let req = TestRequest::GET("/healthy");
o.oneshot_with((GlobalIncrement, NotFoundIncrement), req).await;
assert_eq!(*N().lock().unwrap(), 10);

let req = TestRequest::GET("/api/a");
o.oneshot_with((GlobalIncrement, NotFoundIncrement), req).await;
assert_eq!(*N().lock().unwrap(), 13);

let req = TestRequest::GET("/api/b");
o.oneshot_with((NotFoundIncrement,), req).await;
assert_eq!(*N().lock().unwrap(), 14);

let req = TestRequest::GET("/api/c");
o.oneshot_with((GlobalIncrement, NotFoundIncrement), req).await;
assert_eq!(*N().lock().unwrap(), 19);
}
72 changes: 14 additions & 58 deletions ohkami/src/testing/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
//! ```
use crate::{Response, Request, Ohkami, Status, Method};
use crate::fang::Fangs;
use crate::response::ResponseHeader;

use std::borrow::Cow;
Expand All @@ -36,10 +37,10 @@ use std::{pin::Pin, future::Future, format as f};


pub trait Testing {
fn oneshot(&self, req: TestRequest) -> Oneshot;

// #[cfg(feature="websocket")]
// fn oneshot_and_on_upgrade(&self, req: TestRequest) -> OneshotAndUpgraded;
fn oneshot_with<T>(&self, global_fangs: impl Fangs<T>, req: TestRequest) -> Oneshot;
fn oneshot(&self, req: TestRequest) -> Oneshot {
self.oneshot_with((), req)
}
}

pub struct Oneshot(
Expand All @@ -52,72 +53,27 @@ pub struct Oneshot(
}

impl Testing for Ohkami {
fn oneshot(&self, request: TestRequest) -> Oneshot {
fn oneshot_with<T>(&self, global_fangs: impl Fangs<T>, req: TestRequest) -> Oneshot {
let router = {
let mut router = self.routes.clone();
for (methods, fang) in &self.fangs {
router.apply_fang(methods, fang.clone())
let mut trie = self.clone().into_router();
for (methods, fang) in global_fangs.collect() {
trie.register_global_fang(methods, fang)
}
router.into_radix()
trie.into_radix()
};

let res = async move {
let mut req = Request::init();
let mut req = unsafe {Pin::new_unchecked(&mut req)};
req.as_mut().read(&mut &request.encode()[..]).await;
let mut request = Request::init();
let mut request = unsafe {Pin::new_unchecked(&mut request)};
request.as_mut().read(&mut &req.encode()[..]).await;

#[cfg(not(feature="websocket"))]
let res = router.handle(&mut req).await;
#[cfg(feature="websocket")]
let (res, _) = router.handle(&mut req).await;
let res = router.handle(&mut request).await;

TestResponse::new(res)
};

Oneshot(Box::new(res))
}

// #[cfg(feature="websocket")]
// fn oneshot_and_on_upgrade(
// &self,
// request: TestRequest,
//
// ) -> OneshotAndUpgraded {
// use crate::websocket::{reserve_upgrade_in_test, assume_upgradable_in_test, WebSocketContext};
//
// let router = {
// let mut router = self.routes.clone();
// for (methods, fang) in &self.fangs {
// router = router.apply_fang(methods, fang.clone())
// }
// router.into_radix()
// };
//
// let res_and_socket = async move {
// let mut req = Request::init();
// let mut req = unsafe {Pin::new_unchecked(&mut req)};
// req.as_mut().read(&mut &request.encode_request()[..]).await;
//
// let (res, upgrade_id) = router.handle(Context::new(), &mut req).await;
// match upgrade_id {
// None => (TestResponse::new(res), None),
// Some(id) => {
// let (client, server) = TestStream::new_pair();
// unsafe {reserve_upgrade_in_test(id, server)};
//
// let server = assume_upgradable_in_test(id).await;
// let ctx = WebSocketContext::new(Context {
// upgrade_id,
// ..Context::new()
// }, &mut req);
//
// (TestResponse::new(res), Some(TestWebSocket::new(client)))
// },
// }
// };
//
// OneshotAndUpgraded(Box::new(res_and_socket))
// }
}

pub struct TestRequest {
Expand Down
2 changes: 1 addition & 1 deletion ohkami_macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ proc-macro = true

[package]
name = "ohkami_macros"
version = "0.5.1"
version = "0.5.2"
edition = "2021"
authors = ["kanarus <[email protected]>"]
description = "Proc macros for ohkami - intuitive and declarative web framework"
Expand Down
6 changes: 2 additions & 4 deletions ohkami_macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,9 @@ pub fn Query(_: proc_macro::TokenStream, data: proc_macro::TokenStream) -> proc_
///
/// ```ignore
/// use ohkami::prelude::*;
/// use ohkami::serde::Deserialize;
/// use ohkami::typed::{Payload}; // <--
/// use ohkami::typed::Payload; // <--
///
/// #[Payload(JSON)]
/// #[derive(Deserialize)]
/// #[Payload(JSOND)]
/// struct HelloRequest<'req> {
/// name: &'req str,
/// n_repeat: Option<usize>,
Expand Down

0 comments on commit 642d58d

Please sign in to comment.