16dbb5987Sopenharmony_ci// Copyright (c) 2023 Huawei Device Co., Ltd.
26dbb5987Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License");
36dbb5987Sopenharmony_ci// you may not use this file except in compliance with the License.
46dbb5987Sopenharmony_ci// You may obtain a copy of the License at
56dbb5987Sopenharmony_ci//
66dbb5987Sopenharmony_ci//     http://www.apache.org/licenses/LICENSE-2.0
76dbb5987Sopenharmony_ci//
86dbb5987Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software
96dbb5987Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS,
106dbb5987Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
116dbb5987Sopenharmony_ci// See the License for the specific language governing permissions and
126dbb5987Sopenharmony_ci// limitations under the License.
136dbb5987Sopenharmony_ci
146dbb5987Sopenharmony_ci#[cfg(feature = "async")]
156dbb5987Sopenharmony_cimod async_utils;
166dbb5987Sopenharmony_ci
176dbb5987Sopenharmony_ci#[cfg(feature = "sync")]
186dbb5987Sopenharmony_cimod sync_utils;
196dbb5987Sopenharmony_ci
206dbb5987Sopenharmony_ciuse tokio::runtime::Runtime;
216dbb5987Sopenharmony_ci
226dbb5987Sopenharmony_cimacro_rules! define_service_handle {
236dbb5987Sopenharmony_ci    (
246dbb5987Sopenharmony_ci        HTTP;
256dbb5987Sopenharmony_ci    ) => {
266dbb5987Sopenharmony_ci        use tokio::sync::mpsc::{Receiver, Sender};
276dbb5987Sopenharmony_ci
286dbb5987Sopenharmony_ci        pub struct HttpHandle {
296dbb5987Sopenharmony_ci            pub port: u16,
306dbb5987Sopenharmony_ci
316dbb5987Sopenharmony_ci            // This channel allows the server to notify the client when it is up and running.
326dbb5987Sopenharmony_ci            pub server_start: Receiver<()>,
336dbb5987Sopenharmony_ci
346dbb5987Sopenharmony_ci            // This channel allows the client to notify the server when it is ready to shut down.
356dbb5987Sopenharmony_ci            pub client_shutdown: Sender<()>,
366dbb5987Sopenharmony_ci
376dbb5987Sopenharmony_ci            // This channel allows the server to notify the client when it has shut down.
386dbb5987Sopenharmony_ci            pub server_shutdown: Receiver<()>,
396dbb5987Sopenharmony_ci        }
406dbb5987Sopenharmony_ci    };
416dbb5987Sopenharmony_ci    (
426dbb5987Sopenharmony_ci        HTTPS;
436dbb5987Sopenharmony_ci    ) => {
446dbb5987Sopenharmony_ci        pub struct TlsHandle {
456dbb5987Sopenharmony_ci            pub port: u16,
466dbb5987Sopenharmony_ci        }
476dbb5987Sopenharmony_ci    };
486dbb5987Sopenharmony_ci}
496dbb5987Sopenharmony_ci
506dbb5987Sopenharmony_ci#[macro_export]
516dbb5987Sopenharmony_cimacro_rules! start_server {
526dbb5987Sopenharmony_ci    (
536dbb5987Sopenharmony_ci        HTTPS;
546dbb5987Sopenharmony_ci        ServerNum: $server_num: expr,
556dbb5987Sopenharmony_ci        Runtime: $runtime: expr,
566dbb5987Sopenharmony_ci        Handles: $handle_vec: expr,
576dbb5987Sopenharmony_ci        ServeFnName: $service_fn: ident,
586dbb5987Sopenharmony_ci    ) => {{
596dbb5987Sopenharmony_ci        for _i in 0..$server_num {
606dbb5987Sopenharmony_ci            let (tx, rx) = std::sync::mpsc::channel();
616dbb5987Sopenharmony_ci            let server_handle = $runtime.spawn(async move {
626dbb5987Sopenharmony_ci                let handle = start_http_server!(
636dbb5987Sopenharmony_ci                    HTTPS;
646dbb5987Sopenharmony_ci                    $service_fn
656dbb5987Sopenharmony_ci                );
666dbb5987Sopenharmony_ci                tx.send(handle)
676dbb5987Sopenharmony_ci                    .expect("Failed to send the handle to the test thread.");
686dbb5987Sopenharmony_ci            });
696dbb5987Sopenharmony_ci            $runtime
706dbb5987Sopenharmony_ci                .block_on(server_handle)
716dbb5987Sopenharmony_ci                .expect("Runtime start server coroutine failed");
726dbb5987Sopenharmony_ci            let handle = rx
736dbb5987Sopenharmony_ci                .recv()
746dbb5987Sopenharmony_ci                .expect("Handle send channel (Server-Half) be closed unexpectedly");
756dbb5987Sopenharmony_ci            $handle_vec.push(handle);
766dbb5987Sopenharmony_ci        }
776dbb5987Sopenharmony_ci    }};
786dbb5987Sopenharmony_ci    (
796dbb5987Sopenharmony_ci        HTTP;
806dbb5987Sopenharmony_ci        ServerNum: $server_num: expr,
816dbb5987Sopenharmony_ci        Runtime: $runtime: expr,
826dbb5987Sopenharmony_ci        Handles: $handle_vec: expr,
836dbb5987Sopenharmony_ci        ServeFnName: $service_fn: ident,
846dbb5987Sopenharmony_ci    ) => {{
856dbb5987Sopenharmony_ci        for _i in 0..$server_num {
866dbb5987Sopenharmony_ci            let (tx, rx) = std::sync::mpsc::channel();
876dbb5987Sopenharmony_ci            let server_handle = $runtime.spawn(async move {
886dbb5987Sopenharmony_ci                let mut handle = start_http_server!(
896dbb5987Sopenharmony_ci                    HTTP;
906dbb5987Sopenharmony_ci                    $service_fn
916dbb5987Sopenharmony_ci                );
926dbb5987Sopenharmony_ci                handle
936dbb5987Sopenharmony_ci                    .server_start
946dbb5987Sopenharmony_ci                    .recv()
956dbb5987Sopenharmony_ci                    .await
966dbb5987Sopenharmony_ci                    .expect("Start channel (Server-Half) be closed unexpectedly");
976dbb5987Sopenharmony_ci                tx.send(handle)
986dbb5987Sopenharmony_ci                    .expect("Failed to send the handle to the test thread.");
996dbb5987Sopenharmony_ci            });
1006dbb5987Sopenharmony_ci            $runtime
1016dbb5987Sopenharmony_ci                .block_on(server_handle)
1026dbb5987Sopenharmony_ci                .expect("Runtime start server coroutine failed");
1036dbb5987Sopenharmony_ci            let handle = rx
1046dbb5987Sopenharmony_ci                .recv()
1056dbb5987Sopenharmony_ci                .expect("Handle send channel (Server-Half) be closed unexpectedly");
1066dbb5987Sopenharmony_ci            $handle_vec.push(handle);
1076dbb5987Sopenharmony_ci        }
1086dbb5987Sopenharmony_ci    }};
1096dbb5987Sopenharmony_ci}
1106dbb5987Sopenharmony_ci
1116dbb5987Sopenharmony_ci#[macro_export]
1126dbb5987Sopenharmony_cimacro_rules! start_http_server {
1136dbb5987Sopenharmony_ci    (
1146dbb5987Sopenharmony_ci        HTTP;
1156dbb5987Sopenharmony_ci        $server_fn: ident
1166dbb5987Sopenharmony_ci    ) => {{
1176dbb5987Sopenharmony_ci        use hyper::service::{make_service_fn, service_fn};
1186dbb5987Sopenharmony_ci        use std::convert::Infallible;
1196dbb5987Sopenharmony_ci        use tokio::sync::mpsc::channel;
1206dbb5987Sopenharmony_ci
1216dbb5987Sopenharmony_ci        let (start_tx, start_rx) = channel::<()>(1);
1226dbb5987Sopenharmony_ci        let (client_tx, mut client_rx) = channel::<()>(1);
1236dbb5987Sopenharmony_ci        let (server_tx, server_rx) = channel::<()>(1);
1246dbb5987Sopenharmony_ci
1256dbb5987Sopenharmony_ci        let tcp_listener = std::net::TcpListener::bind("127.0.0.1:0").expect("server bind port failed !");
1266dbb5987Sopenharmony_ci        let addr = tcp_listener.local_addr().expect("get server local address failed!");
1276dbb5987Sopenharmony_ci        let port = addr.port();
1286dbb5987Sopenharmony_ci        let server = hyper::Server::from_tcp(tcp_listener).expect("build hyper server from tcp listener failed !");
1296dbb5987Sopenharmony_ci
1306dbb5987Sopenharmony_ci        tokio::spawn(async move {
1316dbb5987Sopenharmony_ci            let make_svc =
1326dbb5987Sopenharmony_ci                make_service_fn(|_conn| async { Ok::<_, Infallible>(service_fn($server_fn)) });
1336dbb5987Sopenharmony_ci            server
1346dbb5987Sopenharmony_ci                .serve(make_svc)
1356dbb5987Sopenharmony_ci                .with_graceful_shutdown(async {
1366dbb5987Sopenharmony_ci                    start_tx
1376dbb5987Sopenharmony_ci                        .send(())
1386dbb5987Sopenharmony_ci                        .await
1396dbb5987Sopenharmony_ci                        .expect("Start channel (Client-Half) be closed unexpectedly");
1406dbb5987Sopenharmony_ci                    client_rx
1416dbb5987Sopenharmony_ci                        .recv()
1426dbb5987Sopenharmony_ci                        .await
1436dbb5987Sopenharmony_ci                        .expect("Client channel (Client-Half) be closed unexpectedly");
1446dbb5987Sopenharmony_ci                })
1456dbb5987Sopenharmony_ci                .await
1466dbb5987Sopenharmony_ci                .expect("Start server failed");
1476dbb5987Sopenharmony_ci            server_tx
1486dbb5987Sopenharmony_ci                .send(())
1496dbb5987Sopenharmony_ci                .await
1506dbb5987Sopenharmony_ci                .expect("Server channel (Client-Half) be closed unexpectedly");
1516dbb5987Sopenharmony_ci        });
1526dbb5987Sopenharmony_ci
1536dbb5987Sopenharmony_ci        HttpHandle {
1546dbb5987Sopenharmony_ci            port,
1556dbb5987Sopenharmony_ci            server_start: start_rx,
1566dbb5987Sopenharmony_ci            client_shutdown: client_tx,
1576dbb5987Sopenharmony_ci            server_shutdown: server_rx,
1586dbb5987Sopenharmony_ci        }
1596dbb5987Sopenharmony_ci    }};
1606dbb5987Sopenharmony_ci    (
1616dbb5987Sopenharmony_ci        HTTPS;
1626dbb5987Sopenharmony_ci        $service_fn: ident
1636dbb5987Sopenharmony_ci    ) => {{
1646dbb5987Sopenharmony_ci        let mut port = 10000;
1656dbb5987Sopenharmony_ci        let listener = loop {
1666dbb5987Sopenharmony_ci            let addr = std::net::SocketAddr::from(([127, 0, 0, 1], port));
1676dbb5987Sopenharmony_ci            match tokio::net::TcpListener::bind(addr).await {
1686dbb5987Sopenharmony_ci                Ok(listener) => break listener,
1696dbb5987Sopenharmony_ci                Err(_) => {
1706dbb5987Sopenharmony_ci                    port += 1;
1716dbb5987Sopenharmony_ci                    if port == u16::MAX {
1726dbb5987Sopenharmony_ci                        port = 10000;
1736dbb5987Sopenharmony_ci                    }
1746dbb5987Sopenharmony_ci                    continue;
1756dbb5987Sopenharmony_ci                }
1766dbb5987Sopenharmony_ci            }
1776dbb5987Sopenharmony_ci        };
1786dbb5987Sopenharmony_ci        let port = listener.local_addr().unwrap().port();
1796dbb5987Sopenharmony_ci
1806dbb5987Sopenharmony_ci        tokio::spawn(async move {
1816dbb5987Sopenharmony_ci            let mut acceptor = openssl::ssl::SslAcceptor::mozilla_intermediate(openssl::ssl::SslMethod::tls())
1826dbb5987Sopenharmony_ci                .expect("SslAcceptorBuilder error");
1836dbb5987Sopenharmony_ci            acceptor
1846dbb5987Sopenharmony_ci                .set_session_id_context(b"test")
1856dbb5987Sopenharmony_ci                .expect("Set session id error");
1866dbb5987Sopenharmony_ci            acceptor
1876dbb5987Sopenharmony_ci                .set_private_key_file("tests/file/key.pem", openssl::ssl::SslFiletype::PEM)
1886dbb5987Sopenharmony_ci                .expect("Set private key error");
1896dbb5987Sopenharmony_ci            acceptor
1906dbb5987Sopenharmony_ci                .set_certificate_chain_file("tests/file/cert.pem")
1916dbb5987Sopenharmony_ci                .expect("Set cert error");
1926dbb5987Sopenharmony_ci            acceptor.set_alpn_protos(b"\x08http/1.1").unwrap();
1936dbb5987Sopenharmony_ci            acceptor.set_alpn_select_callback(|_, client| {
1946dbb5987Sopenharmony_ci                openssl::ssl::select_next_proto(b"\x08http/1.1", client).ok_or(openssl::ssl::AlpnError::NOACK)
1956dbb5987Sopenharmony_ci            });
1966dbb5987Sopenharmony_ci
1976dbb5987Sopenharmony_ci            let acceptor = acceptor.build();
1986dbb5987Sopenharmony_ci
1996dbb5987Sopenharmony_ci            let (stream, _) = listener.accept().await.expect("TCP listener accept error");
2006dbb5987Sopenharmony_ci            let ssl = openssl::ssl::Ssl::new(acceptor.context()).expect("Ssl Error");
2016dbb5987Sopenharmony_ci            let mut stream = tokio_openssl::SslStream::new(ssl, stream).expect("SslStream Error");
2026dbb5987Sopenharmony_ci            core::pin::Pin::new(&mut stream).accept().await.unwrap(); // SSL negotiation finished successfully
2036dbb5987Sopenharmony_ci
2046dbb5987Sopenharmony_ci            hyper::server::conn::Http::new()
2056dbb5987Sopenharmony_ci                .http1_only(true)
2066dbb5987Sopenharmony_ci                .http1_keep_alive(true)
2076dbb5987Sopenharmony_ci                .serve_connection(stream, hyper::service::service_fn($service_fn))
2086dbb5987Sopenharmony_ci                .await
2096dbb5987Sopenharmony_ci        });
2106dbb5987Sopenharmony_ci
2116dbb5987Sopenharmony_ci        TlsHandle {
2126dbb5987Sopenharmony_ci            port,
2136dbb5987Sopenharmony_ci        }
2146dbb5987Sopenharmony_ci    }};
2156dbb5987Sopenharmony_ci}
2166dbb5987Sopenharmony_ci
2176dbb5987Sopenharmony_ci/// Creates a `Request`.
2186dbb5987Sopenharmony_ci#[macro_export]
2196dbb5987Sopenharmony_ci#[cfg(feature = "sync")]
2206dbb5987Sopenharmony_cimacro_rules! ylong_request {
2216dbb5987Sopenharmony_ci    (
2226dbb5987Sopenharmony_ci        Request: {
2236dbb5987Sopenharmony_ci            Method: $method: expr,
2246dbb5987Sopenharmony_ci            Host: $host: expr,
2256dbb5987Sopenharmony_ci            Port: $port: expr,
2266dbb5987Sopenharmony_ci            $(
2276dbb5987Sopenharmony_ci                Header: $req_n: expr, $req_v: expr,
2286dbb5987Sopenharmony_ci            )*
2296dbb5987Sopenharmony_ci            Body: $req_body: expr,
2306dbb5987Sopenharmony_ci        },
2316dbb5987Sopenharmony_ci    ) => {
2326dbb5987Sopenharmony_ci        ylong_http::request::RequestBuilder::new()
2336dbb5987Sopenharmony_ci            .method($method)
2346dbb5987Sopenharmony_ci            .url(format!("{}:{}", $host, $port).as_str())
2356dbb5987Sopenharmony_ci            $(.header($req_n, $req_v))*
2366dbb5987Sopenharmony_ci            .body(ylong_http::body::TextBody::from_bytes($req_body.as_bytes()))
2376dbb5987Sopenharmony_ci            .expect("Request build failed")
2386dbb5987Sopenharmony_ci    };
2396dbb5987Sopenharmony_ci}
2406dbb5987Sopenharmony_ci
2416dbb5987Sopenharmony_ci/// Creates a `Request`.
2426dbb5987Sopenharmony_ci#[macro_export]
2436dbb5987Sopenharmony_ci#[cfg(feature = "async")]
2446dbb5987Sopenharmony_cimacro_rules! ylong_request {
2456dbb5987Sopenharmony_ci    (
2466dbb5987Sopenharmony_ci        Request: {
2476dbb5987Sopenharmony_ci            Method: $method: expr,
2486dbb5987Sopenharmony_ci            Host: $host: expr,
2496dbb5987Sopenharmony_ci            Port: $port: expr,
2506dbb5987Sopenharmony_ci            $(
2516dbb5987Sopenharmony_ci                Header: $req_n: expr, $req_v: expr,
2526dbb5987Sopenharmony_ci            )*
2536dbb5987Sopenharmony_ci            Body: $req_body: expr,
2546dbb5987Sopenharmony_ci        },
2556dbb5987Sopenharmony_ci    ) => {
2566dbb5987Sopenharmony_ci        ylong_http_client::async_impl::RequestBuilder::new()
2576dbb5987Sopenharmony_ci             .method($method)
2586dbb5987Sopenharmony_ci             .url(format!("{}:{}", $host, $port).as_str())
2596dbb5987Sopenharmony_ci             $(.header($req_n, $req_v))*
2606dbb5987Sopenharmony_ci             .body(ylong_http_client::async_impl::Body::slice($req_body.as_bytes()))
2616dbb5987Sopenharmony_ci             .expect("Request build failed")
2626dbb5987Sopenharmony_ci    };
2636dbb5987Sopenharmony_ci}
2646dbb5987Sopenharmony_ci
2656dbb5987Sopenharmony_ci/// Sets server async function.
2666dbb5987Sopenharmony_ci#[macro_export]
2676dbb5987Sopenharmony_cimacro_rules! set_server_fn {
2686dbb5987Sopenharmony_ci    (
2696dbb5987Sopenharmony_ci        ASYNC;
2706dbb5987Sopenharmony_ci        $server_fn_name: ident,
2716dbb5987Sopenharmony_ci        $(Request: {
2726dbb5987Sopenharmony_ci            Method: $method: expr,
2736dbb5987Sopenharmony_ci            $(
2746dbb5987Sopenharmony_ci                Header: $req_n: expr, $req_v: expr,
2756dbb5987Sopenharmony_ci            )*
2766dbb5987Sopenharmony_ci            Body: $req_body: expr,
2776dbb5987Sopenharmony_ci        },
2786dbb5987Sopenharmony_ci        Response: {
2796dbb5987Sopenharmony_ci            Status: $status: expr,
2806dbb5987Sopenharmony_ci            Version: $version: expr,
2816dbb5987Sopenharmony_ci            $(
2826dbb5987Sopenharmony_ci                Header: $resp_n: expr, $resp_v: expr,
2836dbb5987Sopenharmony_ci            )*
2846dbb5987Sopenharmony_ci            Body: $resp_body: expr,
2856dbb5987Sopenharmony_ci        },)*
2866dbb5987Sopenharmony_ci    ) => {
2876dbb5987Sopenharmony_ci        async fn $server_fn_name(request: hyper::Request<hyper::Body>) -> Result<hyper::Response<hyper::Body>, std::convert::Infallible> {
2886dbb5987Sopenharmony_ci            match request.method().as_str() {
2896dbb5987Sopenharmony_ci                // TODO If there are requests with the same Method, an error will be reported for creating two identical match branches.
2906dbb5987Sopenharmony_ci                $(
2916dbb5987Sopenharmony_ci                    $method => {
2926dbb5987Sopenharmony_ci                        assert_eq!($method, request.method().as_str(), "Assert request method failed");
2936dbb5987Sopenharmony_ci                        assert_eq!(
2946dbb5987Sopenharmony_ci                            "/",
2956dbb5987Sopenharmony_ci                            request.uri().to_string(),
2966dbb5987Sopenharmony_ci                            "Assert request host failed",
2976dbb5987Sopenharmony_ci                        );
2986dbb5987Sopenharmony_ci                        assert_eq!(
2996dbb5987Sopenharmony_ci                            $version,
3006dbb5987Sopenharmony_ci                            format!("{:?}", request.version()),
3016dbb5987Sopenharmony_ci                            "Assert request version failed",
3026dbb5987Sopenharmony_ci                        );
3036dbb5987Sopenharmony_ci                        $(assert_eq!(
3046dbb5987Sopenharmony_ci                            $req_v,
3056dbb5987Sopenharmony_ci                            request
3066dbb5987Sopenharmony_ci                                .headers()
3076dbb5987Sopenharmony_ci                                .get($req_n)
3086dbb5987Sopenharmony_ci                                .expect(format!("Get request header \"{}\" failed", $req_n).as_str())
3096dbb5987Sopenharmony_ci                                .to_str()
3106dbb5987Sopenharmony_ci                                .expect(format!("Convert request header \"{}\" into string failed", $req_n).as_str()),
3116dbb5987Sopenharmony_ci                            "Assert request header {} failed", $req_n,
3126dbb5987Sopenharmony_ci                        );)*
3136dbb5987Sopenharmony_ci                        let body = hyper::body::to_bytes(request.into_body()).await
3146dbb5987Sopenharmony_ci                            .expect("Get request body failed");
3156dbb5987Sopenharmony_ci                        assert_eq!($req_body.as_bytes(), body, "Assert request body failed");
3166dbb5987Sopenharmony_ci                        Ok(
3176dbb5987Sopenharmony_ci                            hyper::Response::builder()
3186dbb5987Sopenharmony_ci                                .version(hyper::Version::HTTP_11)
3196dbb5987Sopenharmony_ci                                .status($status)
3206dbb5987Sopenharmony_ci                                $(.header($resp_n, $resp_v))*
3216dbb5987Sopenharmony_ci                                .body($resp_body.into())
3226dbb5987Sopenharmony_ci                                .expect("Build response failed")
3236dbb5987Sopenharmony_ci                        )
3246dbb5987Sopenharmony_ci                    },
3256dbb5987Sopenharmony_ci                )*
3266dbb5987Sopenharmony_ci                _ => {panic!("Unrecognized METHOD !");},
3276dbb5987Sopenharmony_ci            }
3286dbb5987Sopenharmony_ci        }
3296dbb5987Sopenharmony_ci
3306dbb5987Sopenharmony_ci    };
3316dbb5987Sopenharmony_ci    (
3326dbb5987Sopenharmony_ci        SYNC;
3336dbb5987Sopenharmony_ci        $server_fn_name: ident,
3346dbb5987Sopenharmony_ci        $(Request: {
3356dbb5987Sopenharmony_ci            Method: $method: expr,
3366dbb5987Sopenharmony_ci            $(
3376dbb5987Sopenharmony_ci                Header: $req_n: expr, $req_v: expr,
3386dbb5987Sopenharmony_ci            )*
3396dbb5987Sopenharmony_ci            Body: $req_body: expr,
3406dbb5987Sopenharmony_ci        },
3416dbb5987Sopenharmony_ci        Response: {
3426dbb5987Sopenharmony_ci            Status: $status: expr,
3436dbb5987Sopenharmony_ci            Version: $version: expr,
3446dbb5987Sopenharmony_ci            $(
3456dbb5987Sopenharmony_ci                Header: $resp_n: expr, $resp_v: expr,
3466dbb5987Sopenharmony_ci            )*
3476dbb5987Sopenharmony_ci            Body: $resp_body: expr,
3486dbb5987Sopenharmony_ci        },)*
3496dbb5987Sopenharmony_ci    ) => {
3506dbb5987Sopenharmony_ci        async fn $server_fn_name(request: hyper::Request<hyper::Body>) -> Result<hyper::Response<hyper::Body>, std::convert::Infallible> {
3516dbb5987Sopenharmony_ci            match request.method().as_str() {
3526dbb5987Sopenharmony_ci                // TODO If there are requests with the same Method, an error will be reported for creating two identical match branches.
3536dbb5987Sopenharmony_ci                $(
3546dbb5987Sopenharmony_ci                    $method => {
3556dbb5987Sopenharmony_ci                        assert_eq!($method, request.method().as_str(), "Assert request method failed");
3566dbb5987Sopenharmony_ci                        assert_eq!(
3576dbb5987Sopenharmony_ci                            "/",
3586dbb5987Sopenharmony_ci                            request.uri().to_string(),
3596dbb5987Sopenharmony_ci                            "Assert request uri failed",
3606dbb5987Sopenharmony_ci                        );
3616dbb5987Sopenharmony_ci                        assert_eq!(
3626dbb5987Sopenharmony_ci                            $version,
3636dbb5987Sopenharmony_ci                            format!("{:?}", request.version()),
3646dbb5987Sopenharmony_ci                            "Assert request version failed",
3656dbb5987Sopenharmony_ci                        );
3666dbb5987Sopenharmony_ci                        $(assert_eq!(
3676dbb5987Sopenharmony_ci                            $req_v,
3686dbb5987Sopenharmony_ci                            request
3696dbb5987Sopenharmony_ci                                .headers()
3706dbb5987Sopenharmony_ci                                .get($req_n)
3716dbb5987Sopenharmony_ci                                .expect(format!("Get request header \"{}\" failed", $req_n).as_str())
3726dbb5987Sopenharmony_ci                                .to_str()
3736dbb5987Sopenharmony_ci                                .expect(format!("Convert request header \"{}\" into string failed", $req_n).as_str()),
3746dbb5987Sopenharmony_ci                            "Assert request header {} failed", $req_n,
3756dbb5987Sopenharmony_ci                        );)*
3766dbb5987Sopenharmony_ci                        let body = hyper::body::to_bytes(request.into_body()).await
3776dbb5987Sopenharmony_ci                            .expect("Get request body failed");
3786dbb5987Sopenharmony_ci                        assert_eq!($req_body.as_bytes(), body, "Assert request body failed");
3796dbb5987Sopenharmony_ci                        Ok(
3806dbb5987Sopenharmony_ci                            hyper::Response::builder()
3816dbb5987Sopenharmony_ci                                .version(hyper::Version::HTTP_11)
3826dbb5987Sopenharmony_ci                                .status($status)
3836dbb5987Sopenharmony_ci                                $(.header($resp_n, $resp_v))*
3846dbb5987Sopenharmony_ci                                .body($resp_body.into())
3856dbb5987Sopenharmony_ci                                .expect("Build response failed")
3866dbb5987Sopenharmony_ci                        )
3876dbb5987Sopenharmony_ci                    },
3886dbb5987Sopenharmony_ci                )*
3896dbb5987Sopenharmony_ci                _ => {panic!("Unrecognized METHOD !");},
3906dbb5987Sopenharmony_ci            }
3916dbb5987Sopenharmony_ci        }
3926dbb5987Sopenharmony_ci
3936dbb5987Sopenharmony_ci    };
3946dbb5987Sopenharmony_ci}
3956dbb5987Sopenharmony_ci
3966dbb5987Sopenharmony_ci#[macro_export]
3976dbb5987Sopenharmony_cimacro_rules! ensure_server_shutdown {
3986dbb5987Sopenharmony_ci    (ServerHandle: $handle:expr) => {
3996dbb5987Sopenharmony_ci        $handle
4006dbb5987Sopenharmony_ci            .client_shutdown
4016dbb5987Sopenharmony_ci            .send(())
4026dbb5987Sopenharmony_ci            .await
4036dbb5987Sopenharmony_ci            .expect("Client channel (Server-Half) be closed unexpectedly");
4046dbb5987Sopenharmony_ci        $handle
4056dbb5987Sopenharmony_ci            .server_shutdown
4066dbb5987Sopenharmony_ci            .recv()
4076dbb5987Sopenharmony_ci            .await
4086dbb5987Sopenharmony_ci            .expect("Server channel (Server-Half) be closed unexpectedly");
4096dbb5987Sopenharmony_ci    };
4106dbb5987Sopenharmony_ci}
4116dbb5987Sopenharmony_ci
4126dbb5987Sopenharmony_cipub fn init_test_work_runtime(thread_num: usize) -> Runtime {
4136dbb5987Sopenharmony_ci    tokio::runtime::Builder::new_multi_thread()
4146dbb5987Sopenharmony_ci        .worker_threads(thread_num)
4156dbb5987Sopenharmony_ci        .enable_all()
4166dbb5987Sopenharmony_ci        .build()
4176dbb5987Sopenharmony_ci        .expect("Build runtime failed.")
4186dbb5987Sopenharmony_ci}
419