From 94cbeed16dc716f799c500ec40f098b99a0adfa9 Mon Sep 17 00:00:00 2001 From: Tiga Ultraman Date: Fri, 30 Jun 2023 09:33:46 +0800 Subject: [PATCH] rebuild client sdv test Signed-off-by: Tiga Ultraman --- ylong_http_client/Cargo.toml | 22 +- ylong_http_client/src/lib.rs | 2 +- ylong_http_client/tests/common/async_utils.rs | 394 +++++++++++++ ylong_http_client/tests/common/mod.rs | 517 ++++++++---------- ylong_http_client/tests/common/sync_utils.rs | 380 +++++++++++++ ylong_http_client/tests/helper.rs | 387 ------------- .../{sdv_client.rs => sdv_async_http.rs} | 149 ++--- ...ttps_c_ssl.rs => sdv_async_https_c_ssl.rs} | 118 +--- ylong_http_client/tests/sdv_sync_http.rs | 98 ++++ .../tests/sdv_sync_https_c_ssl.rs | 90 +++ 10 files changed, 1267 insertions(+), 890 deletions(-) create mode 100644 ylong_http_client/tests/common/async_utils.rs create mode 100644 ylong_http_client/tests/common/sync_utils.rs delete mode 100644 ylong_http_client/tests/helper.rs rename ylong_http_client/tests/{sdv_client.rs => sdv_async_http.rs} (57%) rename ylong_http_client/tests/{sdv_https_c_ssl.rs => sdv_async_https_c_ssl.rs} (63%) create mode 100644 ylong_http_client/tests/sdv_sync_http.rs create mode 100644 ylong_http_client/tests/sdv_sync_https_c_ssl.rs diff --git a/ylong_http_client/Cargo.toml b/ylong_http_client/Cargo.toml index 56cec58..2f9dabe 100644 --- a/ylong_http_client/Cargo.toml +++ b/ylong_http_client/Cargo.toml @@ -91,11 +91,21 @@ path = "examples/sync_proxy_http.rs" required-features = ["sync", "http1_1"] [[test]] -name = "sdv_client" -path = "./tests/sdv_client.rs" -required-features = ["sync", "async", "http1_1", "tokio_base"] +name = "sdv_async_http" +path = "./tests/sdv_async_http.rs" +required-features = ["async", "http1_1", "tokio_base"] + +[[test]] +name = "sdv_sync_http" +path = "./tests/sdv_sync_http.rs" +required-features = ["sync", "http1_1", "tokio_base"] + +[[test]] +name = "sdv_async_https_c_ssl" +path = "./tests/sdv_async_https_c_ssl.rs" +required-features = ["async", "http1_1", "c_openssl_1_1", "tokio_base"] [[test]] -name = "sdv_https_c_ssl" -path = "./tests/sdv_https_c_ssl.rs" -required-features = ["sync", "async", "http1_1", "c_openssl_1_1", "tokio_base"] +name = "sdv_sync_https_c_ssl" +path = "./tests/sdv_sync_https_c_ssl.rs" +required-features = ["sync", "http1_1", "c_openssl_1_1", "tokio_base"] diff --git a/ylong_http_client/src/lib.rs b/ylong_http_client/src/lib.rs index 1b1adfb..3c5441c 100644 --- a/ylong_http_client/src/lib.rs +++ b/ylong_http_client/src/lib.rs @@ -61,7 +61,7 @@ pub mod util; ))] pub use util::*; -#[cfg(feature = "tokio_base")] +#[cfg(all(feature = "tokio_base", feature = "async"))] pub(crate) use tokio::{ io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, ReadBuf}, net::TcpStream, diff --git a/ylong_http_client/tests/common/async_utils.rs b/ylong_http_client/tests/common/async_utils.rs new file mode 100644 index 0000000..f8a6e83 --- /dev/null +++ b/ylong_http_client/tests/common/async_utils.rs @@ -0,0 +1,394 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#![cfg(feature = "async")] + +use std::sync::Arc; +use ylong_http_client::async_impl::Client; + +#[macro_export] +macro_rules! async_client_test_case { + ( + HTTPS; + ServeFnName: $server_fn_name: ident, + Tls: $tls_config: expr, + RuntimeThreads: $thread_num: expr, + $(ClientNum: $client_num: expr,)? + $(Request: { + Method: $method: expr, + Host: $host: expr, + $( + Header: $req_n: expr, $req_v: expr, + )* + Body: $req_body: expr, + }, + Response: { + Status: $status: expr, + Version: $version: expr, + $( + Header: $resp_n: expr, $resp_v: expr, + )* + Body: $resp_body: expr, + },)* + ) => {{ + set_server_fn!( + ASYNC; + $server_fn_name, + $(Request: { + Method: $method, + $( + Header: $req_n, $req_v, + )* + Body: $req_body, + }, + Response: { + Status: $status, + Version: $version, + $( + Header: $resp_n, $resp_v, + )* + Body: $resp_body, + },)* + ); + + let runtime = init_test_work_runtime($thread_num); + // The number of servers may be variable based on the number of servers set by the user. + // However, cliipy checks that the variable does not need to be variable. + #[allow(unused_mut, unused_assignments)] + let mut server_num = 1; + $(server_num = $client_num;)? + + let mut handles_vec = vec![]; + start_server!( + HTTPS; + ServerNum: server_num, + Runtime: runtime, + Handles: handles_vec, + ServeFnName: $server_fn_name, + ); + + let mut shut_downs = vec![]; + async_client_assert!( + HTTPS; + Tls: $tls_config, + Runtime: runtime, + ServerNum: server_num, + Handles: handles_vec, + ShutDownHandles: shut_downs, + $(Request: { + Method: $method, + Host: $host, + $( + Header: $req_n, $req_v, + )* + Body: $req_body, + }, + Response: { + Status: $status, + Version: $version, + $( + Header: $resp_n, $resp_v, + )* + Body: $resp_body, + },)* + ); + + for shutdown_handle in shut_downs { + runtime.block_on(shutdown_handle).expect("Runtime wait for server shutdown failed"); + } + }}; + ( + HTTP; + ServeFnName: $server_fn_name: ident, + RuntimeThreads: $thread_num: expr, + $(ClientNum: $client_num: expr,)? + $(Request: { + Method: $method: expr, + Host: $host: expr, + $( + Header: $req_n: expr, $req_v: expr, + )* + Body: $req_body: expr, + }, + Response: { + Status: $status: expr, + Version: $version: expr, + $( + Header: $resp_n: expr, $resp_v: expr, + )* + Body: $resp_body: expr, + },)* + ) => {{ + set_server_fn!( + ASYNC; + $server_fn_name, + $(Request: { + Method: $method, + $( + Header: $req_n, $req_v, + )* + Body: $req_body, + }, + Response: { + Status: $status, + Version: $version, + $( + Header: $resp_n, $resp_v, + )* + Body: $resp_body, + },)* + ); + + let runtime = init_test_work_runtime($thread_num); + // The number of servers may be variable based on the number of servers set by the user. + // However, cliipy checks that the variable does not need to be variable. + #[allow(unused_mut, unused_assignments)] + let mut server_num = 1; + $(server_num = $client_num;)? + let mut handles_vec = vec![]; + + start_server!( + HTTP; + ServerNum: server_num, + Runtime: runtime, + Handles: handles_vec, + ServeFnName: $server_fn_name, + ); + + let mut shut_downs = vec![]; + async_client_assert!( + HTTP; + Runtime: runtime, + ServerNum: server_num, + Handles: handles_vec, + ShutDownHandles: shut_downs, + $(Request: { + Method: $method, + Host: $host, + $( + Header: $req_n, $req_v, + )* + Body: $req_body, + }, + Response: { + Status: $status, + Version: $version, + $( + Header: $resp_n, $resp_v, + )* + Body: $resp_body, + },)* + ); + + for shutdown_handle in shut_downs { + runtime.block_on(shutdown_handle).expect("Runtime wait for server shutdown failed"); + } + }}; + +} + +#[macro_export] +macro_rules! async_client_assert { + ( + HTTPS; + Tls: $tls_config: expr, + Runtime: $runtime: expr, + ServerNum: $server_num: expr, + Handles: $handle_vec: expr, + ShutDownHandles: $shut_downs: expr, + $(Request: { + Method: $method: expr, + Host: $host: expr, + $( + Header: $req_n: expr, $req_v: expr, + )* + Body: $req_body: expr, + }, + Response: { + Status: $status: expr, + Version: $version: expr, + $( + Header: $resp_n: expr, $resp_v: expr, + )* + Body: $resp_body: expr, + },)* + ) => {{ + let client = async_build_https_client($tls_config); + for _i in 0..$server_num { + let handle = $handle_vec.pop().expect("No more handles !"); + let client = std::sync::Arc::clone(&client); + let shutdown_handle = $runtime.spawn(async move { + async_client_assertions!( + ServerHandle: handle, + ClientRef: client, + $(Request: { + Method: $method, + Host: $host, + $( + Header: $req_n, $req_v, + )* + Body: $req_body, + }, + Response: { + Status: $status, + Version: $version, + $( + Header: $resp_n, $resp_v, + )* + Body: $resp_body, + },)* + ); + }); + $shut_downs.push(shutdown_handle); + } + }}; + ( + HTTP; + Runtime: $runtime: expr, + ServerNum: $server_num: expr, + Handles: $handle_vec: expr, + ShutDownHandles: $shut_downs: expr, + $(Request: { + Method: $method: expr, + Host: $host: expr, + $( + Header: $req_n: expr, $req_v: expr, + )* + Body: $req_body: expr, + }, + Response: { + Status: $status: expr, + Version: $version: expr, + $( + Header: $resp_n: expr, $resp_v: expr, + )* + Body: $resp_body: expr, + },)* + ) => {{ + let client = async_build_http_client(); + for _i in 0..$server_num { + let mut handle = $handle_vec.pop().expect("No more handles !"); + let client = std::sync::Arc::clone(&client); + let shutdown_handle = $runtime.spawn(async move { + async_client_assertions!( + ServerHandle: handle, + ClientRef: client, + $(Request: { + Method: $method, + Host: $host, + $( + Header: $req_n, $req_v, + )* + Body: $req_body, + }, + Response: { + Status: $status, + Version: $version, + $( + Header: $resp_n, $resp_v, + )* + Body: $resp_body, + },)* + ); + ensure_server_shutdown!(ServerHandle: handle); + }); + $shut_downs.push(shutdown_handle); + } + }} +} + +#[macro_export] +macro_rules! async_client_assertions { + ( + ServerHandle: $handle:expr, + ClientRef: $client:expr, + $(Request: { + Method: $method: expr, + Host: $host: expr, + $( + Header: $req_n: expr, $req_v: expr, + )* + Body: $req_body: expr, + }, + Response: { + Status: $status: expr, + Version: $version: expr, + $( + Header: $resp_n: expr, $resp_v: expr, + )* + Body: $resp_body: expr, + },)* + ) => { + $( + let request = ylong_request!( + Request: { + Method: $method, + Host: $host, + Port: $handle.port, + $( + Header: $req_n, $req_v, + )* + Body: $req_body, + }, + ); + + let mut response = $client + .request(request) + .await + .expect("Request send failed"); + + assert_eq!(response.status().as_u16(), $status, "Assert response status code failed") ; + assert_eq!(response.version().as_str(), $version, "Assert response version failed"); + $(assert_eq!( + response + .headers() + .get($resp_n) + .expect(format!("Get response header \"{}\" failed", $resp_n).as_str()) + .to_str() + .expect(format!("Convert response header \"{}\"into string failed", $resp_n).as_str()), + $resp_v, + "Assert response header \"{}\" failed", $resp_n, + );)* + let mut buf = [0u8; 4096]; + let mut size = 0; + loop { + let read = response + .body_mut() + .data(&mut buf[size..]).await + .expect("Response body read failed"); + if read == 0 { + break; + } + size += read; + } + assert_eq!(&buf[..size], $resp_body.as_bytes(), "Assert response body failed"); + )* + } +} + +#[cfg(feature = "c_openssl_1_1")] +pub fn async_build_https_client(tls_config: &str) -> Arc { + let client = ylong_http_client::async_impl::Client::builder() + .set_ca_file(tls_config) + .build() + .unwrap(); + std::sync::Arc::new(client) +} + +#[cfg(not(feature = "c_openssl_1_1"))] +pub fn async_build_http_client() -> Arc { + let client = ylong_http_client::async_impl::Client::new(); + Arc::new(client) +} diff --git a/ylong_http_client/tests/common/mod.rs b/ylong_http_client/tests/common/mod.rs index 69adb0e..8decb05 100644 --- a/ylong_http_client/tests/common/mod.rs +++ b/ylong_http_client/tests/common/mod.rs @@ -13,12 +13,105 @@ * limitations under the License. */ +#[cfg(feature = "async")] +mod async_utils; + +#[cfg(feature = "sync")] +mod sync_utils; + +#[cfg(all(feature = "async", not(feature = "c_openssl_1_1")))] +pub use async_utils::async_build_http_client; + +#[cfg(all(feature = "async", feature = "c_openssl_1_1"))] +pub use async_utils::async_build_https_client; + +use tokio::runtime::Runtime; + +#[cfg(not(feature = "c_openssl_1_1"))] +use tokio::sync::mpsc::{Receiver, Sender}; + /// Server handle. -pub struct Handle { +#[cfg(feature = "c_openssl_1_1")] +pub struct TlsHandle { pub port: u16, } +#[cfg(not(feature = "c_openssl_1_1"))] +pub struct HttpHandle { + pub port: u16, + + // This channel allows the server to notify the client when it is up and running. + pub server_start: Receiver<()>, + + // This channel allows the client to notify the server when it is ready to shut down. + pub client_shutdown: Sender<()>, + + // This channel allows the server to notify the client when it has shut down. + pub server_shutdown: Receiver<()>, +} + +#[macro_export] +macro_rules! start_http_server { + ($server_fn: ident) => {{ + use hyper::service::{make_service_fn, service_fn}; + use hyper::Server; + use std::convert::Infallible; + use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + use tokio::sync::mpsc::channel; + + let (start_tx, start_rx) = channel::<()>(1); + let (client_tx, mut client_rx) = channel::<()>(1); + let (server_tx, server_rx) = channel::<()>(1); + let mut port = 10000; + + let server = loop { + let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), port); + match Server::try_bind(&addr) { + Ok(server) => break server, + Err(_) => { + port += 1; + if port == u16::MAX { + port = 10000; + } + continue; + } + } + }; + + tokio::spawn(async move { + let make_svc = + make_service_fn(|_conn| async { Ok::<_, Infallible>(service_fn($server_fn)) }); + server + .serve(make_svc) + .with_graceful_shutdown(async { + start_tx + .send(()) + .await + .expect("Start channel (Client-Half) be closed unexpectedly"); + client_rx + .recv() + .await + .expect("Client channel (Client-Half) be closed unexpectedly"); + }) + .await + .expect("Start server failed"); + server_tx + .send(()) + .await + .expect("Server channel (Client-Half) be closed unexpectedly"); + }); + + HttpHandle { + port, + server_start: start_rx, + client_shutdown: client_tx, + server_shutdown: server_rx, + } + }}; +} + /// Creates a `Request`. +#[macro_export] macro_rules! ylong_request { ( Request: { @@ -31,7 +124,7 @@ macro_rules! ylong_request { Body: $req_body: expr, }, ) => { - ylong_http_client::RequestBuilder::new() + ylong_http::request::RequestBuilder::new() .method($method) .url(format!("{}:{}", $host, $port).as_str()) $(.header($req_n, $req_v))* @@ -41,8 +134,74 @@ macro_rules! ylong_request { } /// Sets server async function. +#[macro_export] macro_rules! set_server_fn { ( + ASYNC; + $server_fn_name: ident, + $(Request: { + Method: $method: expr, + $( + Header: $req_n: expr, $req_v: expr, + )* + Body: $req_body: expr, + }, + Response: { + Status: $status: expr, + Version: $version: expr, + $( + Header: $resp_n: expr, $resp_v: expr, + )* + Body: $resp_body: expr, + },)* + ) => { + async fn $server_fn_name(request: hyper::Request) -> Result, std::convert::Infallible> { + match request.method().as_str() { + // TODO If there are requests with the same Method, an error will be reported for creating two identical match branches. + $( + $method => { + assert_eq!($method, request.method().as_str(), "Assert request method failed"); + + assert_eq!( + "/", + request.uri().to_string(), + "Assert request host failed", + ); + assert_eq!( + $version, + format!("{:?}", request.version()), + "Assert request version failed", + ); + $(assert_eq!( + $req_v, + request + .headers() + .get($req_n) + .expect(format!("Get request header \"{}\" failed", $req_n).as_str()) + .to_str() + .expect(format!("Convert request header \"{}\" into string failed", $req_n).as_str()), + "Assert request header {} failed", $req_n, + );)* + let body = hyper::body::to_bytes(request.into_body()).await + .expect("Get request body failed"); + assert_eq!($req_body.as_bytes(), body, "Assert request body failed"); + Ok( + hyper::Response::builder() + .version(hyper::Version::HTTP_11) + .status($status) + $(.header($resp_n, $resp_v))* + .body($resp_body.into()) + .expect("Build response failed") + ) + }, + )* + _ => {panic!("Unrecognized METHOD !");}, + } + } + + }; + ( + SYNC; $server_fn_name: ident, $(Request: { Method: $method: expr, @@ -63,9 +222,11 @@ macro_rules! set_server_fn { ) => { async fn $server_fn_name(request: hyper::Request) -> Result, std::convert::Infallible> { match request.method().as_str() { + // TODO If there are requests with the same Method, an error will be reported for creating two identical match branches. $( $method => { assert_eq!($method, request.method().as_str(), "Assert request method failed"); + assert_eq!( $host, request.uri().host().expect("Uri in request do not have a host."), @@ -106,7 +267,8 @@ macro_rules! set_server_fn { }; } -macro_rules! get_handle { +#[cfg(feature = "c_openssl_1_1")] +macro_rules! start_tls_server { ($service_fn: ident) => {{ let mut port = 10000; let listener = loop { @@ -155,318 +317,87 @@ macro_rules! get_handle { .await }); - Handle { + TlsHandle { port, } }}; } -macro_rules! ylong_client_test_case { +#[macro_export] +macro_rules! start_server { ( - Tls: $tls_config: expr, - RuntimeThreads: $thread_num: expr, - $(ClientNum: $client_num: expr,)? - IsAsync: $is_async: expr, - $(Request: { - Method: $method: expr, - Host: $host: expr, - $( - Header: $req_n: expr, $req_v: expr, - )* - Body: $req_body: expr, - }, - Response: { - Status: $status: expr, - Version: $version: expr, - $( - Header: $resp_n: expr, $resp_v: expr, - )* - Body: $resp_body: expr, - },)* + HTTPS; + ServerNum: $server_num: expr, + Runtime: $runtime: expr, + Handles: $handle_vec: expr, + ServeFnName: $service_fn: ident, ) => {{ - set_server_fn!( - ylong_server_fn, - $(Request: { - Method: $method, - Host: $host, - $( - Header: $req_n, $req_v, - )* - Body: $req_body, - }, - Response: { - Status: $status, - Version: $version, - $( - Header: $resp_n, $resp_v, - )* - Body: $resp_body, - },)* - ); - - let runtime = tokio::runtime::Builder::new_multi_thread() - .worker_threads($thread_num) - .enable_all() - .build() - .expect("Build runtime failed."); - - // The number of servers may be variable based on the number of servers set by the user. - // However, cliipy checks that the variable does not need to be variable. - #[allow(unused_mut, unused_assignments)] - let mut server_num = 1; - $(server_num = $client_num;)? - - let mut handles_vec = vec![]; - for _i in 0.. server_num { + for _i in 0..$server_num { let (tx, rx) = std::sync::mpsc::channel(); - let server_handle = runtime.spawn(async move { - let handle = get_handle!(ylong_server_fn); - // handle - // .server_start - // .recv() - // .await - // .expect("Start channel (Server-Half) be closed unexpectedly"); + let server_handle = $runtime.spawn(async move { + let handle = start_tls_server!($service_fn); tx.send(handle) .expect("Failed to send the handle to the test thread."); }); - runtime + $runtime .block_on(server_handle) .expect("Runtime start server coroutine failed"); let handle = rx .recv() .expect("Handle send channel (Server-Half) be closed unexpectedly"); - handles_vec.push(handle); - } - - let mut shut_downs = vec![]; - if $is_async { - let client = ylong_http_client::async_impl::Client::builder() - .set_ca_file($tls_config) - .build() - .unwrap(); - let client = std::sync::Arc::new(client); - for _i in 0..server_num { - let handle = handles_vec.pop().expect("No more handles !"); - - ylong_client_test_case!( - Runtime: runtime, - AsyncClient: client, - ServerHandle: handle, - ShutDownHandles: shut_downs, - $(Request: { - Method: $method, - Host: $host, - $( - Header: $req_n, $req_v, - )* - Body: $req_body, - }, - Response: { - Status: $status, - Version: $version, - $( - Header: $resp_n, $resp_v, - )* - Body: $resp_body, - },)* - ) - } - } else { - let client = ylong_http_client::sync_impl::Client::builder() - .set_ca_file($tls_config) - .build() - .unwrap(); - let client = std::sync::Arc::new(client); - for _i in 0..server_num { - let handle = handles_vec.pop().expect("No more handles !"); - ylong_client_test_case!( - Runtime: runtime, - SyncClient: client, - ServerHandle: handle, - ShutDownHandles: shut_downs, - $(Request: { - Method: $method, - Host: $host, - $( - Header: $req_n, $req_v, - )* - Body: $req_body, - }, - Response: { - Status: $status, - Version: $version, - $( - Header: $resp_n, $resp_v, - )* - Body: $resp_body, - },)* - ) - } - } - for shutdown_handle in shut_downs { - runtime.block_on(shutdown_handle).expect("Runtime wait for server shutdown failed"); + $handle_vec.push(handle); } }}; ( + HTTP; + ServerNum: $server_num: expr, Runtime: $runtime: expr, - AsyncClient: $async_client: expr, - ServerHandle: $handle:expr, - ShutDownHandles: $shut_downs: expr, - $(Request: { - Method: $method: expr, - Host: $host: expr, - $( - Header: $req_n: expr, $req_v: expr, - )* - Body: $req_body: expr, - }, - Response: { - Status: $status: expr, - Version: $version: expr, - $( - Header: $resp_n: expr, $resp_v: expr, - )* - Body: $resp_body: expr, - },)* + Handles: $handle_vec: expr, + ServeFnName: $service_fn: ident, ) => {{ - use ylong_http_client::async_impl::Body; - let client = std::sync::Arc::clone(&$async_client); - let shutdown_handle = $runtime.spawn(async move { - $( - let request = ylong_request!( - Request: { - Method: $method, - Host: $host, - Port: $handle.port, - $( - Header: $req_n, $req_v, - )* - Body: $req_body, - }, - ); - - let mut response = client - .request(request) + for _i in 0..$server_num { + let (tx, rx) = std::sync::mpsc::channel(); + let server_handle = $runtime.spawn(async move { + let mut handle = start_http_server!($service_fn); + handle + .server_start + .recv() .await - .expect("Request send failed"); - - assert_eq!(response.status().as_u16(), $status, "Assert response status code failed"); - assert_eq!(response.version().as_str(), $version, "Assert response version failed"); - $(assert_eq!( - response - .headers() - .get($resp_n) - .expect(format!("Get response header \"{}\" failed", $resp_n).as_str()) - .to_str() - .expect(format!("Convert response header \"{}\"into string failed", $resp_n).as_str()), - $resp_v, - "Assert response header \"{}\" failed", $resp_n, - );)* - let mut buf = [0u8; 4096]; - let mut size = 0; - loop { - let read = response - .body_mut() - .data(&mut buf[size..]).await - .expect("Response body read failed"); - if read == 0 { - break; - } - size += read; - } - assert_eq!(&buf[..size], $resp_body.as_bytes(), "Assert response body failed"); - )* - // $handle - // .client_shutdown - // .send(()) - // .await - // .expect("Client channel (Server-Half) be closed unexpectedly"); - // $handle - // .server_shutdown - // .recv() - // .await - // .expect("Server channel (Server-Half) be closed unexpectedly"); - }); - $shut_downs.push(shutdown_handle); + .expect("Start channel (Server-Half) be closed unexpectedly"); + tx.send(handle) + .expect("Failed to send the handle to the test thread."); + }); + $runtime + .block_on(server_handle) + .expect("Runtime start server coroutine failed"); + let handle = rx + .recv() + .expect("Handle send channel (Server-Half) be closed unexpectedly"); + $handle_vec.push(handle); + } }}; +} - ( - Runtime: $runtime: expr, - SyncClient: $sync_client: expr, - ServerHandle: $handle:expr, - ShutDownHandles: $shut_downs: expr, - $(Request: { - Method: $method: expr, - Host: $host: expr, - $( - Header: $req_n: expr, $req_v: expr, - )* - Body: $req_body: expr, - }, - Response: { - Status: $status: expr, - Version: $version: expr, - $( - Header: $resp_n: expr, $resp_v: expr, - )* - Body: $resp_body: expr, - },)* - ) => {{ - use ylong_http_client::sync_impl::Body; - let client = std::sync::Arc::clone(&$sync_client); - $( - let request = ylong_request!( - Request: { - Method: $method, - Host: $host, - Port: $handle.port, - $( - Header: $req_n, $req_v, - )* - Body: $req_body, - }, - ); - let mut response = client - .request(request) - .expect("Request send failed"); - assert_eq!(response.status().as_u16(), $status, "Assert response status code failed"); - assert_eq!(response.version().as_str(), $version, "Assert response version failed"); - $(assert_eq!( - response - .headers() - .get($resp_n) - .expect(format!("Get response header \"{}\" failed", $resp_n).as_str()) - .to_str() - .expect(format!("Convert response header \"{}\"into string failed", $resp_n).as_str()), - $resp_v, - "Assert response header \"{}\" failed", $resp_n, - );)* - let mut buf = [0u8; 4096]; - let mut size = 0; - loop { - let read = response - .body_mut() - .data(&mut buf[size..]) - .expect("Response body read failed"); - if read == 0 { - break; - } - size += read; - } - assert_eq!(&buf[..size], $resp_body.as_bytes(), "Assert response body failed"); - )* - let shutdown_handle = $runtime.spawn(async move { - // $handle - // .client_shutdown - // .send(()) - // .await - // .expect("Client channel (Server-Half) be closed unexpectedly"); - // $handle - // .server_shutdown - // .recv() - // .await - // .expect("Server channel (Server-Half) be closed unexpectedly"); - }); - $shut_downs.push(shutdown_handle); - }}; +#[macro_export] +macro_rules! ensure_server_shutdown { + (ServerHandle: $handle:expr) => { + $handle + .client_shutdown + .send(()) + .await + .expect("Client channel (Server-Half) be closed unexpectedly"); + $handle + .server_shutdown + .recv() + .await + .expect("Server channel (Server-Half) be closed unexpectedly"); + }; +} + +pub fn init_test_work_runtime(thread_num: usize) -> Runtime { + tokio::runtime::Builder::new_multi_thread() + .worker_threads(thread_num) + .enable_all() + .build() + .expect("Build runtime failed.") } diff --git a/ylong_http_client/tests/common/sync_utils.rs b/ylong_http_client/tests/common/sync_utils.rs new file mode 100644 index 0000000..c0c82ac --- /dev/null +++ b/ylong_http_client/tests/common/sync_utils.rs @@ -0,0 +1,380 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#![cfg(feature = "sync")] + +#[macro_export] +macro_rules! sync_client_test_case { + ( + HTTPS; + Tls: $tls_config: expr, + RuntimeThreads: $thread_num: expr, + $(ClientNum: $client_num: expr,)? + $(Request: { + Method: $method: expr, + Host: $host: expr, + $( + Header: $req_n: expr, $req_v: expr, + )* + Body: $req_body: expr, + }, + Response: { + Status: $status: expr, + Version: $version: expr, + $( + Header: $resp_n: expr, $resp_v: expr, + )* + Body: $resp_body: expr, + },)* + ) => {{ + set_server_fn!( + SYNC; + ylong_server_fn, + $(Request: { + Method: $method, + Host: $host, + $( + Header: $req_n, $req_v, + )* + Body: $req_body, + }, + Response: { + Status: $status, + Version: $version, + $( + Header: $resp_n, $resp_v, + )* + Body: $resp_body, + },)* + ); + + let runtime = init_test_work_runtime($thread_num); + // The number of servers may be variable based on the number of servers set by the user. + // However, cliipy checks that the variable does not need to be variable. + #[allow(unused_mut, unused_assignments)] + let mut server_num = 1; + $(server_num = $client_num;)? + + let mut handles_vec = vec![]; + start_server!( + HTTPS; + ServerNum: server_num, + Runtime: runtime, + Handles: handles_vec, + ServeFnName: ylong_server_fn, + ); + + let mut shut_downs = vec![]; + sync_client_assert!( + HTTPS; + Tls: $tls_config, + Runtime: runtime, + ServerNum: server_num, + Handles: handles_vec, + ShutDownHandles: shut_downs, + $(Request: { + Method: $method, + Host: $host, + $( + Header: $req_n, $req_v, + )* + Body: $req_body, + }, + Response: { + Status: $status, + Version: $version, + $( + Header: $resp_n, $resp_v, + )* + Body: $resp_body, + },)* + ); + + for shutdown_handle in shut_downs { + runtime.block_on(shutdown_handle).expect("Runtime wait for server shutdown failed"); + } + }}; + ( + HTTP; + RuntimeThreads: $thread_num: expr, + $(ClientNum: $client_num: expr,)? + $(Request: { + Method: $method: expr, + Host: $host: expr, + $( + Header: $req_n: expr, $req_v: expr, + )* + Body: $req_body: expr, + }, + Response: { + Status: $status: expr, + Version: $version: expr, + $( + Header: $resp_n: expr, $resp_v: expr, + )* + Body: $resp_body: expr, + },)* + ) => {{ + set_server_fn!( + SYNC; + ylong_server_fn, + $(Request: { + Method: $method, + Host: $host, + $( + Header: $req_n, $req_v, + )* + Body: $req_body, + }, + Response: { + Status: $status, + Version: $version, + $( + Header: $resp_n, $resp_v, + )* + Body: $resp_body, + },)* + ); + + let runtime = init_test_work_runtime($thread_num); + // The number of servers may be variable based on the number of servers set by the user. + // However, cliipy checks that the variable does not need to be variable. + #[allow(unused_mut, unused_assignments)] + let mut server_num = 1; + $(server_num = $client_num;)? + let mut handles_vec = vec![]; + + start_server!( + HTTP; + ServerNum: server_num, + Runtime: runtime, + Handles: handles_vec, + ServeFnName: ylong_server_fn, + ); + + let mut shut_downs = vec![]; + sync_client_assert!( + HTTP; + Runtime: runtime, + ServerNum: server_num, + Handles: handles_vec, + ShutDownHandles: shut_downs, + $(Request: { + Method: $method, + Host: $host, + $( + Header: $req_n, $req_v, + )* + Body: $req_body, + }, + Response: { + Status: $status, + Version: $version, + $( + Header: $resp_n, $resp_v, + )* + Body: $resp_body, + },)* + ); + + for shutdown_handle in shut_downs { + runtime.block_on(shutdown_handle).expect("Runtime wait for server shutdown failed"); + } + }}; + +} + +#[macro_export] +macro_rules! sync_client_assert { + ( + HTTPS; + Tls: $tls_config: expr, + Runtime: $runtime: expr, + ServerNum: $server_num: expr, + Handles: $handle_vec: expr, + ShutDownHandles: $shut_downs: expr, + $(Request: { + Method: $method: expr, + Host: $host: expr, + $( + Header: $req_n: expr, $req_v: expr, + )* + Body: $req_body: expr, + }, + Response: { + Status: $status: expr, + Version: $version: expr, + $( + Header: $resp_n: expr, $resp_v: expr, + )* + Body: $resp_body: expr, + },)* + ) => {{ + let client = ylong_http_client::sync_impl::Client::builder() + .set_ca_file($tls_config) + .build() + .unwrap(); + let client = std::sync::Arc::new(client); + for _i in 0..$server_num { + let handle = $handle_vec.pop().expect("No more handles !"); + let client = std::sync::Arc::clone(&client); + sync_client_assertions!( + ServerHandle: handle, + ClientRef: client, + $(Request: { + Method: $method, + Host: $host, + $( + Header: $req_n, $req_v, + )* + Body: $req_body, + }, + Response: { + Status: $status, + Version: $version, + $( + Header: $resp_n, $resp_v, + )* + Body: $resp_body, + },)* + ); + let shutdown_handle = $runtime.spawn(async move { + + }); + $shut_downs.push(shutdown_handle); + } + }}; + ( + HTTP; + Runtime: $runtime: expr, + ServerNum: $server_num: expr, + Handles: $handle_vec: expr, + ShutDownHandles: $shut_downs: expr, + $(Request: { + Method: $method: expr, + Host: $host: expr, + $( + Header: $req_n: expr, $req_v: expr, + )* + Body: $req_body: expr, + }, + Response: { + Status: $status: expr, + Version: $version: expr, + $( + Header: $resp_n: expr, $resp_v: expr, + )* + Body: $resp_body: expr, + },)* + ) => {{ + let client = ylong_http_client::sync_impl::Client::new(); + let client = Arc::new(client); + for _i in 0..$server_num { + let mut handle = $handle_vec.pop().expect("No more handles !"); + let client = std::sync::Arc::clone(&client); + sync_client_assertions!( + ServerHandle: handle, + ClientRef: client, + $(Request: { + Method: $method, + Host: $host, + $( + Header: $req_n, $req_v, + )* + Body: $req_body, + }, + Response: { + Status: $status, + Version: $version, + $( + Header: $resp_n, $resp_v, + )* + Body: $resp_body, + },)* + ); + let shutdown_handle = $runtime.spawn(async move { + ensure_server_shutdown!(ServerHandle: handle); + }); + $shut_downs.push(shutdown_handle); + } + + }} +} + +#[macro_export] +macro_rules! sync_client_assertions { + ( + ServerHandle: $handle:expr, + ClientRef: $client:expr, + $(Request: { + Method: $method: expr, + Host: $host: expr, + $( + Header: $req_n: expr, $req_v: expr, + )* + Body: $req_body: expr, + }, + Response: { + Status: $status: expr, + Version: $version: expr, + $( + Header: $resp_n: expr, $resp_v: expr, + )* + Body: $resp_body: expr, + },)* + ) => { + $( + let request = ylong_request!( + Request: { + Method: $method, + Host: $host, + Port: $handle.port, + $( + Header: $req_n, $req_v, + )* + Body: $req_body, + }, + ); + let mut response = $client + .request(request) + .expect("Request send failed"); + assert_eq!(response.status().as_u16(), $status, "Assert response status code failed"); + assert_eq!(response.version().as_str(), $version, "Assert response version failed"); + $(assert_eq!( + response + .headers() + .get($resp_n) + .expect(format!("Get response header \"{}\" failed", $resp_n).as_str()) + .to_str() + .expect(format!("Convert response header \"{}\"into string failed", $resp_n).as_str()), + $resp_v, + "Assert response header \"{}\" failed", $resp_n, + );)* + let mut buf = [0u8; 4096]; + let mut size = 0; + loop { + let read = response + .body_mut() + .data(&mut buf[size..]) + .expect("Response body read failed"); + if read == 0 { + break; + } + size += read; + } + assert_eq!(&buf[..size], $resp_body.as_bytes(), "Assert response body failed"); + )* + }; +} diff --git a/ylong_http_client/tests/helper.rs b/ylong_http_client/tests/helper.rs deleted file mode 100644 index 87fc5b4..0000000 --- a/ylong_http_client/tests/helper.rs +++ /dev/null @@ -1,387 +0,0 @@ -/* - * Copyright (c) 2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -use tokio::sync::mpsc::{Receiver, Sender}; - -pub struct Handle { - pub port: u16, - - // This channel allows the server to notify the client when it is up and running. - pub server_start: Receiver<()>, - - // This channel allows the client to notify the server when it is ready to shut down. - pub client_shutdown: Sender<()>, - - // This channel allows the server to notify the client when it has shut down. - pub server_shutdown: Receiver<()>, -} - -#[macro_export] -macro_rules! start_local_test_server { - ($server_fn: ident) => {{ - use hyper::service::{make_service_fn, service_fn}; - use hyper::Server; - use std::convert::Infallible; - use std::net::{IpAddr, Ipv4Addr, SocketAddr}; - use tokio::sync::mpsc::channel; - - let (start_tx, start_rx) = channel::<()>(1); - let (client_tx, mut client_rx) = channel::<()>(1); - let (server_tx, server_rx) = channel::<()>(1); - let mut port = 10000; - - let server = loop { - let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), port); - match Server::try_bind(&addr) { - Ok(server) => break server, - Err(_) => { - port += 1; - if port == u16::MAX { - port = 10000; - } - continue; - } - } - }; - - tokio::spawn(async move { - let make_svc = - make_service_fn(|_conn| async { Ok::<_, Infallible>(service_fn($server_fn)) }); - server - .serve(make_svc) - .with_graceful_shutdown(async { - start_tx - .send(()) - .await - .expect("Start channel (Client-Half) be closed unexpectedly"); - client_rx - .recv() - .await - .expect("Client channel (Client-Half) be closed unexpectedly"); - }) - .await - .expect("Start server failed"); - server_tx - .send(()) - .await - .expect("Server channel (Client-Half) be closed unexpectedly"); - }); - - Handle { - port, - server_start: start_rx, - client_shutdown: client_tx, - server_shutdown: server_rx, - } - }}; -} - -#[macro_export] -macro_rules! ylong_client_test_case { - ( - RuntimeThreads: $thread_num: expr, - $(ClientNum: $client_num: expr,)? - IsAsync: $is_async: expr, - $(Request: { - Method: $method: expr, - Host: $host: expr, - $( - Header: $req_n: expr, $req_v: expr, - )* - Body: $req_body: expr, - }, - Response: { - Status: $status: expr, - Version: $version: expr, - $( - Header: $resp_n: expr, $resp_v: expr, - )* - Body: $resp_body: expr, - },)* - ) => {{ - async fn server_fn(request: Request) -> Result, Infallible> { - - match request.method().as_str() { - $( - $method => { - assert_eq!($method, request.method().as_str(), "Assert request method failed"); - assert_eq!( - $host, - request.uri().host().expect("Uri in request do not have a host."), - "Assert request host failed", - ); - assert_eq!( - $version, - format!("{:?}", request.version()), - "Assert request version failed", - ); - $(assert_eq!( - $req_v, - request - .headers() - .get($req_n) - .expect(format!("Get request header \"{}\" failed", $req_n).as_str()) - .to_str() - .expect(format!("Convert request header \"{}\" into string failed", $req_n).as_str()), - "Assert request header {} failed", $req_n, - );)* - let body = hyper::body::to_bytes(request.into_body()).await - .expect("Get request body failed"); - assert_eq!($req_body.as_bytes(), body, "Assert request body failed"); - - Ok( - Response::builder() - .version(hyper::Version::HTTP_11) - .status($status) - $(.header($resp_n, $resp_v))* - .body($resp_body.into()) - .expect("Build response failed") - ) - }, - )* - _ => {panic!("Unrecognized METHOD!");}, - } - } - let runtime = tokio::runtime::Builder::new_multi_thread() - .worker_threads($thread_num) - .enable_all() - .build() - .expect("Build runtime failed."); - - // The number of servers may vary based on the user's configuration. - // However, Clippy checks to ensure that this variable doesn't need to be mutable. - #[allow(unused_mut, unused_assignments)] - let mut server_num = 1; - $(server_num = $client_num;)? - - let mut handles_vec = vec![]; - for _i in 0.. server_num { - let (tx, rx) = std::sync::mpsc::channel(); - let server_handle = runtime.spawn(async move { - let mut handle = start_local_test_server!(server_fn); - handle.server_start.recv().await.expect("Start channel (Server-Half) be closed unexpectedly"); - tx.send(handle).expect("Failed to send the handle to the test thread."); - }); - runtime.block_on(server_handle).expect("Runtime start server coroutine failed"); - let handle = rx.recv().expect("Handle send channel (Server-Half) be closed unexpectedly"); - handles_vec.push(handle); - } - - let mut shut_downs = vec![]; - if $is_async { - let client = ylong_http_client::async_impl::Client::new(); - let client = Arc::new(client); - for _i in 0..server_num { - let mut handle = handles_vec.pop().expect("No more handles !"); - - ylong_client_test_case!( - Runtime: runtime, - AsyncClient: client, - ServerHandle: handle, - ShutDownHandles: shut_downs, - $(Request: { - Method: $method, - Host: $host, - $( - Header: $req_n, $req_v, - )* - Body: $req_body, - }, - Response: { - Status: $status, - Version: $version, - $( - Header: $resp_n, $resp_v, - )* - Body: $resp_body, - },)* - ) - } - } else { - let client = ylong_http_client::sync_impl::Client::new(); - let client = Arc::new(client); - for _i in 0..server_num { - let mut handle = handles_vec.pop().expect("No more handles !"); - ylong_client_test_case!( - Runtime: runtime, - SyncClient: client, - ServerHandle: handle, - ShutDownHandles: shut_downs, - $(Request: { - Method: $method, - Host: $host, - $( - Header: $req_n, $req_v, - )* - Body: $req_body, - }, - Response: { - Status: $status, - Version: $version, - $( - Header: $resp_n, $resp_v, - )* - Body: $resp_body, - },)* - ) - } - } - for shutdown_handle in shut_downs { - runtime.block_on(shutdown_handle).expect("Runtime wait for server shutdown failed"); - } - }}; - - ( - Runtime: $runtime: expr, - AsyncClient: $async_client: expr, - ServerHandle: $handle:expr, - ShutDownHandles: $shut_downs: expr, - $(Request: { - Method: $method: expr, - Host: $host: expr, - $( - Header: $req_n: expr, $req_v: expr, - )* - Body: $req_body: expr, - }, - Response: { - Status: $status: expr, - Version: $version: expr, - $( - Header: $resp_n: expr, $resp_v: expr, - )* - Body: $resp_body: expr, - },)* - ) => {{ - let client = Arc::clone(&$async_client); - let shutdown_handle = $runtime.spawn(async move { - $( - let request = RequestBuilder::new() - .method($method) - .url(format!("{}:{}", $host, $handle.port).as_str()) - $(.header($req_n, $req_v))* - .body(TextBody::from_bytes($req_body.as_bytes())) - .expect("Request build failed"); - let mut response = client - .request(request) - .await - .expect("Request send failed"); - assert_eq!(response.status().as_u16(), $status, "Assert response status code failed"); - assert_eq!(response.version().as_str(), $version, "Assert response version failed"); - $(assert_eq!( - response - .headers() - .get($resp_n) - .expect(format!("Get response header \"{}\" failed", $resp_n).as_str()) - .to_str() - .expect(format!("Convert response header \"{}\"into string failed", $resp_n).as_str()), - $resp_v, - "Assert response header \"{}\" failed", $resp_n, - );)* - let mut buf = [0u8; 4096]; - let mut size = 0; - loop { - let read = response - .body_mut() - .data(&mut buf[size..]).await - .expect("Response body read failed"); - if read == 0 { - break; - } - size += read; - } - assert_eq!(&buf[..size], $resp_body.as_bytes(), "Assert response body failed"); - )* - $handle - .client_shutdown - .send(()) - .await - .expect("Client channel (Server-Half) be closed unexpectedly"); - $handle - .server_shutdown - .recv() - .await - .expect("Server channel (Server-Half) be closed unexpectedly"); - }); - $shut_downs.push(shutdown_handle); - }}; - - ( - Runtime: $runtime: expr, - SyncClient: $sync_client: expr, - ServerHandle: $handle:expr, - ShutDownHandles: $shut_downs: expr, - $(Request: { - Method: $method: expr, - Host: $host: expr, - $( - Header: $req_n: expr, $req_v: expr, - )* - Body: $req_body: expr, - }, - Response: { - Status: $status: expr, - Version: $version: expr, - $( - Header: $resp_n: expr, $resp_v: expr, - )* - Body: $resp_body: expr, - },)* - ) => {{ - let client = Arc::clone(&$sync_client); - $( - let request = RequestBuilder::new() - .method($method) - .url(format!("{}:{}", $host, $handle.port).as_str()) - $(.header($req_n, $req_v))* - .body(TextBody::from_bytes($req_body.as_bytes())) - .expect("Request build failed"); - let mut response = client - .request(request) - .expect("Request send failed"); - assert_eq!(response.status().as_u16(), $status, "Assert response status code failed"); - assert_eq!(response.version().as_str(), $version, "Assert response version failed"); - $(assert_eq!( - response - .headers() - .get($resp_n) - .expect(format!("Get response header \"{}\" failed", $resp_n).as_str()) - .to_str() - .expect(format!("Convert response header \"{}\"into string failed", $resp_n).as_str()), - $resp_v, - "Assert response header \"{}\" failed", $resp_n, - );)* - let mut buf = [0u8; 4096]; - let mut size = 0; - loop { - let read = response - .body_mut() - .data(&mut buf[size..]) - .expect("Response body read failed"); - if read == 0 { - break; - } - size += read; - } - assert_eq!(&buf[..size], $resp_body.as_bytes(), "Assert response body failed"); - )* - let shutdown_handle = $runtime.spawn(async move { - $handle.client_shutdown.send(()).await.expect("Client channel (Server-Half) be closed unexpectedly"); - $handle.server_shutdown.recv().await.expect("Server channel (Server-Half) be closed unexpectedly"); - }); - $shut_downs.push(shutdown_handle); - }} - -} diff --git a/ylong_http_client/tests/sdv_client.rs b/ylong_http_client/tests/sdv_async_http.rs similarity index 57% rename from ylong_http_client/tests/sdv_client.rs rename to ylong_http_client/tests/sdv_async_http.rs index 960d86a..0281702 100644 --- a/ylong_http_client/tests/sdv_client.rs +++ b/ylong_http_client/tests/sdv_async_http.rs @@ -13,17 +13,15 @@ * limitations under the License. */ -#![cfg(not(feature = "__tls"))] +#![cfg(all(feature = "async", not(feature = "c_openssl_1_1")))] -use hyper::{Body, Request, Response}; -use std::convert::Infallible; -use std::sync::Arc; -use ylong_http::body::async_impl::Body as AsyncBody; -use ylong_http_client::{RequestBuilder, TextBody}; +#[macro_use] +mod common; -mod helper; -use helper::Handle; -use ylong_http::body::sync_impl::Body as SyncBody; +use crate::common::async_build_http_client; +use crate::common::init_test_work_runtime; +use crate::common::HttpHandle; +use ylong_http::body::async_impl::Body as AsyncBody; /// SDV test cases for `async::Client`. /// @@ -39,13 +37,13 @@ use ylong_http::body::sync_impl::Body as SyncBody; #[test] fn sdv_async_client_send_request() { // `GET` request - ylong_client_test_case!( + async_client_test_case!( + HTTP; + ServeFnName: ylong_server_fn, RuntimeThreads: 1, - IsAsync: true, Request: { Method: "GET", - Host: "127.0.0.1", - Header: "Host", "127.0.0.1", + Host: "http://127.0.0.1", Header: "Content-Length", "6", Body: "Hello!", }, @@ -58,13 +56,13 @@ fn sdv_async_client_send_request() { ); // `HEAD` request. - ylong_client_test_case!( + async_client_test_case!( + HTTP; + ServeFnName: ylong_server_fn, RuntimeThreads: 1, - IsAsync: true, Request: { Method: "HEAD", - Host: "127.0.0.1", - Header: "Host", "127.0.0.1", + Host: "http://127.0.0.1", Header: "Content-Length", "6", Body: "Hello!", }, @@ -76,13 +74,13 @@ fn sdv_async_client_send_request() { ); // `Post` Request. - ylong_client_test_case!( + async_client_test_case!( + HTTP; + ServeFnName: ylong_server_fn, RuntimeThreads: 1, - IsAsync: true, Request: { Method: "POST", - Host: "127.0.0.1", - Header: "Host", "127.0.0.1", + Host: "http://127.0.0.1", Header: "Content-Length", "6", Body: "Hello!", }, @@ -95,13 +93,13 @@ fn sdv_async_client_send_request() { ); // `HEAD` request without body. - ylong_client_test_case!( + async_client_test_case!( + HTTP; + ServeFnName: ylong_server_fn, RuntimeThreads: 1, - IsAsync: true, Request: { Method: "HEAD", - Host: "127.0.0.1", - Header: "Host", "127.0.0.1", + Host: "http://127.0.0.1", Body: "", }, Response: { @@ -112,13 +110,13 @@ fn sdv_async_client_send_request() { ); // `PUT` request. - ylong_client_test_case!( + async_client_test_case!( + HTTP; + ServeFnName: ylong_server_fn, RuntimeThreads: 1, - IsAsync: true, Request: { Method: "PUT", - Host: "127.0.0.1", - Header: "Host", "127.0.0.1", + Host: "http://127.0.0.1", Header: "Content-Length", "6", Body: "Hello!", }, @@ -141,13 +139,13 @@ fn sdv_async_client_send_request() { /// 5. Shuts down the server. #[test] fn sdv_client_send_request_repeatedly() { - ylong_client_test_case!( + async_client_test_case!( + HTTP; + ServeFnName: ylong_server_fn, RuntimeThreads: 2, - IsAsync: true, Request: { Method: "GET", - Host: "127.0.0.1", - Header: "Host", "127.0.0.1", + Host: "http://127.0.0.1", Header: "Content-Length", "6", Body: "Hello!", }, @@ -159,8 +157,7 @@ fn sdv_client_send_request_repeatedly() { }, Request: { Method: "POST", - Host: "127.0.0.1", - Header: "Host", "127.0.0.1", + Host: "http://127.0.0.1", Header: "Content-Length", "6", Body: "Hello!", }, @@ -183,75 +180,14 @@ fn sdv_client_send_request_repeatedly() { /// 5. Shuts down the servers. #[test] fn sdv_client_making_multiple_connections() { - ylong_client_test_case!( + async_client_test_case!( + HTTP; + ServeFnName: ylong_server_fn, RuntimeThreads: 2, ClientNum: 5, - IsAsync: true, - Request: { - Method: "GET", - Host: "127.0.0.1", - Header: "Host", "127.0.0.1", - Header: "Content-Length", "6", - Body: "Hello!", - }, - Response: { - Status: 201, - Version: "HTTP/1.1", - Header: "Content-Length", "11", - Body: "METHOD GET!", - }, - ); -} - -/// SDV test cases for `sync::Client`. -/// -/// # Brief -/// 1. Creates a runtime to host the server. -/// 2. Creates a server within the runtime coroutine. -/// 3. Creates a sync::Client. -/// 4. The client sends a request to the the server. -/// 5. Verifies the response returned by the server. -/// 6. Shuts down the server. -#[test] -fn sdv_synchronized_client_send_request() { - // `PUT` request. - ylong_client_test_case!( - RuntimeThreads: 2, - IsAsync: false, - Request: { - Method: "PUT", - Host: "127.0.0.1", - Header: "Host", "127.0.0.1", - Header: "Content-Length", "6", - Body: "Hello!", - }, - Response: { - Status: 200, - Version: "HTTP/1.1", - Header: "Content-Length", "3", - Body: "Hi!", - }, - ); -} - -/// SDV test cases for `sync::Client`. -/// -/// # Brief -/// 1. Creates a runtime to host the server. -/// 2. Creates a server within the runtime coroutine. -/// 3. Creates a sync::Client. -/// 4. The client sends requests to the the server repeatedly. -/// 5. Verifies each response returned by the server. -/// 6. Shuts down the server. -#[test] -fn sdv_synchronized_client_send_request_repeatedly() { - ylong_client_test_case!( - RuntimeThreads: 2, - IsAsync: false, Request: { Method: "GET", - Host: "127.0.0.1", - Header: "Host", "127.0.0.1", + Host: "http://127.0.0.1", Header: "Content-Length", "6", Body: "Hello!", }, @@ -261,18 +197,5 @@ fn sdv_synchronized_client_send_request_repeatedly() { Header: "Content-Length", "11", Body: "METHOD GET!", }, - Request: { - Method: "POST", - Host: "127.0.0.1", - Header: "Host", "127.0.0.1", - Header: "Content-Length", "6", - Body: "Hello!", - }, - Response: { - Status: 201, - Version: "HTTP/1.1", - Header: "Content-Length", "12", - Body: "METHOD POST!", - }, ); } diff --git a/ylong_http_client/tests/sdv_https_c_ssl.rs b/ylong_http_client/tests/sdv_async_https_c_ssl.rs similarity index 63% rename from ylong_http_client/tests/sdv_https_c_ssl.rs rename to ylong_http_client/tests/sdv_async_https_c_ssl.rs index 590503f..22dc081 100644 --- a/ylong_http_client/tests/sdv_https_c_ssl.rs +++ b/ylong_http_client/tests/sdv_async_https_c_ssl.rs @@ -13,11 +13,16 @@ * limitations under the License. */ +#![cfg(all(feature = "async", feature = "c_openssl_1_1"))] + #[macro_use] mod common; -use common::Handle; +use crate::common::async_build_https_client; +use crate::common::init_test_work_runtime; +use common::TlsHandle; use std::path::PathBuf; +use ylong_http_client::Body; // TODO: Add doc for sdv tests. #[test] @@ -27,14 +32,14 @@ fn sdv_async_client_send_request() { path.push("tests/file/root-ca.pem"); // `GET` request - ylong_client_test_case!( + async_client_test_case!( + HTTPS; + ServeFnName: ylong_server_fn, Tls: path.to_str().unwrap(), RuntimeThreads: 1, - IsAsync: true, Request: { Method: "GET", Host: "127.0.0.1", - Header: "Host", "127.0.0.1", Header: "Content-Length", "6", Body: "Hello!", }, @@ -47,14 +52,14 @@ fn sdv_async_client_send_request() { ); // `HEAD` request. - ylong_client_test_case!( + async_client_test_case!( + HTTPS; + ServeFnName: ylong_server_fn, Tls: path.to_str().unwrap(), RuntimeThreads: 1, - IsAsync: true, Request: { Method: "HEAD", Host: "127.0.0.1", - Header: "Host", "127.0.0.1", Header: "Content-Length", "6", Body: "Hello!", }, @@ -66,14 +71,14 @@ fn sdv_async_client_send_request() { ); // `Post` Request. - ylong_client_test_case!( + async_client_test_case!( + HTTPS; + ServeFnName: ylong_server_fn, Tls: path.to_str().unwrap(), RuntimeThreads: 1, - IsAsync: true, Request: { Method: "POST", Host: "127.0.0.1", - Header: "Host", "127.0.0.1", Header: "Content-Length", "6", Body: "Hello!", }, @@ -86,14 +91,14 @@ fn sdv_async_client_send_request() { ); // `HEAD` request without body. - ylong_client_test_case!( + async_client_test_case!( + HTTPS; + ServeFnName: ylong_server_fn, Tls: path.to_str().unwrap(), RuntimeThreads: 1, - IsAsync: true, Request: { Method: "HEAD", Host: "127.0.0.1", - Header: "Host", "127.0.0.1", Body: "", }, Response: { @@ -104,14 +109,14 @@ fn sdv_async_client_send_request() { ); // `PUT` request. - ylong_client_test_case!( + async_client_test_case!( + HTTPS; + ServeFnName: ylong_server_fn, Tls: path.to_str().unwrap(), RuntimeThreads: 1, - IsAsync: true, Request: { Method: "PUT", Host: "127.0.0.1", - Header: "Host", "127.0.0.1", Header: "Content-Length", "6", Body: "Hello!", }, @@ -130,14 +135,14 @@ fn sdv_client_send_request_repeatedly() { let mut path = PathBuf::from(dir); path.push("tests/file/root-ca.pem"); - ylong_client_test_case!( + async_client_test_case!( + HTTPS; + ServeFnName: ylong_server_fn, Tls: path.to_str().unwrap(), RuntimeThreads: 2, - IsAsync: true, Request: { Method: "GET", Host: "127.0.0.1", - Header: "Host", "127.0.0.1", Header: "Content-Length", "6", Body: "Hello!", }, @@ -150,7 +155,6 @@ fn sdv_client_send_request_repeatedly() { Request: { Method: "POST", Host: "127.0.0.1", - Header: "Host", "127.0.0.1", Header: "Content-Length", "6", Body: "Hello!", }, @@ -169,68 +173,15 @@ fn sdv_client_making_multiple_connections() { let mut path = PathBuf::from(dir); path.push("tests/file/root-ca.pem"); - ylong_client_test_case!( - Tls: path.to_str().unwrap(), - RuntimeThreads: 2, - ClientNum: 5, - IsAsync: true, - Request: { - Method: "GET", - Host: "127.0.0.1", - Header: "Host", "127.0.0.1", - Header: "Content-Length", "6", - Body: "Hello!", - }, - Response: { - Status: 201, - Version: "HTTP/1.1", - Header: "Content-Length", "11", - Body: "METHOD GET!", - }, - ); -} - -#[test] -fn sdv_synchronized_client_send_request() { - let dir = env!("CARGO_MANIFEST_DIR"); - let mut path = PathBuf::from(dir); - path.push("tests/file/root-ca.pem"); - - // `PUT` request. - ylong_client_test_case!( + async_client_test_case!( + HTTPS; + ServeFnName: ylong_server_fn, Tls: path.to_str().unwrap(), RuntimeThreads: 2, - IsAsync: false, - Request: { - Method: "PUT", - Host: "127.0.0.1", - Header: "Host", "127.0.0.1", - Header: "Content-Length", "6", - Body: "Hello!", - }, - Response: { - Status: 200, - Version: "HTTP/1.1", - Header: "Content-Length", "3", - Body: "Hi!", - }, - ); -} - -#[test] -fn sdv_synchronized_client_send_request_repeatedly() { - let dir = env!("CARGO_MANIFEST_DIR"); - let mut path = PathBuf::from(dir); - path.push("tests/file/root-ca.pem"); - - ylong_client_test_case!( - Tls: path.to_str().unwrap(), - RuntimeThreads: 2, - IsAsync: false, + ClientNum: 5, Request: { Method: "GET", Host: "127.0.0.1", - Header: "Host", "127.0.0.1", Header: "Content-Length", "6", Body: "Hello!", }, @@ -240,18 +191,5 @@ fn sdv_synchronized_client_send_request_repeatedly() { Header: "Content-Length", "11", Body: "METHOD GET!", }, - Request: { - Method: "POST", - Host: "127.0.0.1", - Header: "Host", "127.0.0.1", - Header: "Content-Length", "6", - Body: "Hello!", - }, - Response: { - Status: 201, - Version: "HTTP/1.1", - Header: "Content-Length", "12", - Body: "METHOD POST!", - }, ); } diff --git a/ylong_http_client/tests/sdv_sync_http.rs b/ylong_http_client/tests/sdv_sync_http.rs new file mode 100644 index 0000000..078035e --- /dev/null +++ b/ylong_http_client/tests/sdv_sync_http.rs @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#![cfg(all(not(feature = "__tls"), feature = "sync"))] + +#[macro_use] +mod common; + +use crate::common::init_test_work_runtime; +use crate::common::HttpHandle; +use std::sync::Arc; +use ylong_http_client::sync_impl::Body; + +/// SDV test cases for `sync::Client`. +/// +/// # Brief +/// 1. Creates a runtime to host the server. +/// 2. Creates a server within the runtime coroutine. +/// 3. Creates a sync::Client. +/// 4. The client sends a request to the the server. +/// 5. Verifies the response returned by the server. +/// 6. Shuts down the server. +#[test] +fn sdv_synchronized_client_send_request() { + // `PUT` request. + sync_client_test_case!( + HTTP; + RuntimeThreads: 2, + Request: { + Method: "PUT", + Host: "127.0.0.1", + Header: "Host", "127.0.0.1", + Header: "Content-Length", "6", + Body: "Hello!", + }, + Response: { + Status: 200, + Version: "HTTP/1.1", + Header: "Content-Length", "3", + Body: "Hi!", + }, + ); +} + +/// SDV test cases for `sync::Client`. +/// +/// # Brief +/// 1. Creates a runtime to host the server. +/// 2. Creates a server within the runtime coroutine. +/// 3. Creates a sync::Client. +/// 4. The client sends requests to the the server repeatedly. +/// 5. Verifies each response returned by the server. +/// 6. Shuts down the server. +#[test] +fn sdv_synchronized_client_send_request_repeatedly() { + sync_client_test_case!( + HTTP; + RuntimeThreads: 2, + Request: { + Method: "GET", + Host: "127.0.0.1", + Header: "Host", "127.0.0.1", + Header: "Content-Length", "6", + Body: "Hello!", + }, + Response: { + Status: 201, + Version: "HTTP/1.1", + Header: "Content-Length", "11", + Body: "METHOD GET!", + }, + Request: { + Method: "POST", + Host: "127.0.0.1", + Header: "Host", "127.0.0.1", + Header: "Content-Length", "6", + Body: "Hello!", + }, + Response: { + Status: 201, + Version: "HTTP/1.1", + Header: "Content-Length", "12", + Body: "METHOD POST!", + }, + ); +} diff --git a/ylong_http_client/tests/sdv_sync_https_c_ssl.rs b/ylong_http_client/tests/sdv_sync_https_c_ssl.rs new file mode 100644 index 0000000..11e1735 --- /dev/null +++ b/ylong_http_client/tests/sdv_sync_https_c_ssl.rs @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#![cfg(all(feature = "sync", feature = "c_openssl_1_1"))] + +use crate::common::init_test_work_runtime; +use common::TlsHandle; +use std::path::PathBuf; +use ylong_http_client::sync_impl::Body; + +#[macro_use] +mod common; + +#[test] +fn sdv_synchronized_client_send_request() { + let dir = env!("CARGO_MANIFEST_DIR"); + let mut path = PathBuf::from(dir); + path.push("tests/file/root-ca.pem"); + + // `PUT` request. + sync_client_test_case!( + HTTPS; + Tls: path.to_str().unwrap(), + RuntimeThreads: 2, + Request: { + Method: "PUT", + Host: "127.0.0.1", + Header: "Host", "127.0.0.1", + Header: "Content-Length", "6", + Body: "Hello!", + }, + Response: { + Status: 200, + Version: "HTTP/1.1", + Header: "Content-Length", "3", + Body: "Hi!", + }, + ); +} + +#[test] +fn sdv_synchronized_client_send_request_repeatedly() { + let dir = env!("CARGO_MANIFEST_DIR"); + let mut path = PathBuf::from(dir); + path.push("tests/file/root-ca.pem"); + + sync_client_test_case!( + HTTPS; + Tls: path.to_str().unwrap(), + RuntimeThreads: 2, + Request: { + Method: "GET", + Host: "127.0.0.1", + Header: "Host", "127.0.0.1", + Header: "Content-Length", "6", + Body: "Hello!", + }, + Response: { + Status: 201, + Version: "HTTP/1.1", + Header: "Content-Length", "11", + Body: "METHOD GET!", + }, + Request: { + Method: "POST", + Host: "127.0.0.1", + Header: "Host", "127.0.0.1", + Header: "Content-Length", "6", + Body: "Hello!", + }, + Response: { + Status: 201, + Version: "HTTP/1.1", + Header: "Content-Length", "12", + Body: "METHOD POST!", + }, + ); +} -- Gitee