1 // Copyright (c) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 #[macro_export]
15 macro_rules! async_client_test_on_tcp {
16     (
17         HTTP;
18         $(ClientNum: $client_num: expr,)?
19         $(Request: {
20             Method: $method: expr,
21             Version: $req_version: expr,
22             Path: $path: expr,
23             $(
24                 Header: $req_n: expr, $req_v: expr,
25             )*
26             Body: $req_body: expr,
27         },
28         Response: {
29             Status: $status: expr,
30             Version: $resp_version: expr,
31             $(
32                 Header: $resp_n: expr, $resp_v: expr,
33             )*
34             Body: $resp_body: expr,
35         },)*
36     ) => {{
37 
38         // The number of servers may be variable based on the number of servers set by the user.
39         // However, clippy checks that the variable does not need to be variable.
40         #[allow(unused_mut, unused_assignments)]
41         let mut server_num = 1;
42         $(server_num = $client_num;)?
43         let mut handles_vec = vec![];
44 
45         start_tcp_server!(
46             ASYNC;
47             Proxy: false,
48             ServerNum: server_num,
49             Handles: handles_vec,
50             $(Request: {
51                 Method: $method,
52                 Version: $req_version,
53                 Path: $path,
54                 $(
55                     Header: $req_n, $req_v,
56                 )*
57                 Header: "Accept", "*/*",
58                 Body: $req_body,
59             },
60             Response: {
61                 Status: $status,
62                 Version: $resp_version,
63                 $(
64                     Header: $resp_n, $resp_v,
65                 )*
66                 Body: $resp_body,
67             },)*
68         );
69 
70         let mut shut_downs = vec![];
71         async_client_assert_on_tcp!(
72             HTTP;
73             ServerNum: server_num,
74             Handles: handles_vec,
75             ShutDownHandles: shut_downs,
76             $(Request: {
77                 Method: $method,
78                 Version: $req_version,
79                 Path: $path,
80                 $(
81                     Header: $req_n, $req_v,
82                 )*
83                 Body: $req_body,
84             },
85             Response: {
86                 Status: $status,
87                 Version: $resp_version,
88                 $(
89                     Header: $resp_n, $resp_v,
90                 )*
91                 Body: $resp_body,
92             },)*
93         );
94 
95         for shutdown_handle in shut_downs {
96             ylong_runtime::block_on(shutdown_handle).expect("Runtime wait for server shutdown failed");
97         }
98     }};
99 
100 }
101 
102 #[macro_export]
103 macro_rules! async_client_assert_on_tcp {
104     (
105         HTTP;
106         ServerNum: $server_num: expr,
107         Handles: $handle_vec: expr,
108         ShutDownHandles: $shut_downs: expr,
109         $(Request: {
110             Method: $method: expr,
111             Version: $req_version: expr,
112             Path: $path: expr,
113             $(
114             Header: $req_n: expr, $req_v: expr,
115             )*
116             Body: $req_body: expr,
117         },
118         Response: {
119             Status: $status: expr,
120             Version: $resp_version: expr,
121             $(
122             Header: $resp_n: expr, $resp_v: expr,
123             )*
124             Body: $resp_body: expr,
125         },)*
126     ) => {{
127         let client = ylong_http_client::async_impl::Client::new();
128         let client = std::sync::Arc::new(client);
129         for _i in 0..$server_num {
130             let handle = $handle_vec.pop().expect("No more handles !");
131             let client = std::sync::Arc::clone(&client);
132             let shutdown_handle = ylong_runtime::spawn(async move {
133                 async_client_assertions_on_tcp!(
134                     ServerHandle: handle,
135                     ClientRef: client,
136                     $(Request: {
137                         Method: $method,
138                         Version: $req_version,
139                         Path: $path,
140                         $(
141                             Header: $req_n, $req_v,
142                         )*
143                         Body: $req_body,
144                     },
145                     Response: {
146                         Status: $status,
147                         Version: $resp_version,
148                         $(
149                             Header: $resp_n, $resp_v,
150                         )*
151                         Body: $resp_body,
152                     },)*
153                 );
154                 handle.server_shutdown.recv().expect("server send order failed !");
155             });
156             $shut_downs.push(shutdown_handle);
157         }
158     }}
159 }
160 
161 #[macro_export]
162 macro_rules! async_client_assertions_on_tcp {
163     (
164         ServerHandle: $handle:expr,
165         ClientRef: $client:expr,
166         $(Request: {
167             Method: $method: expr,
168             Version: $req_version: expr,
169             Path: $path: expr,
170             $(
171             Header: $req_n: expr, $req_v: expr,
172             )*
173             Body: $req_body: expr,
174         },
175         Response: {
176             Status: $status: expr,
177             Version: $resp_version: expr,
178             $(
179             Header: $resp_n: expr, $resp_v: expr,
180             )*
181             Body: $resp_body: expr,
182         },)*
183     ) => {
184         $(
185             {
186                 let request = build_client_request!(
187                     Request: {
188                         Method: $method,
189                         Version: $req_version,
190                         Path: $path,
191                         Addr: $handle.addr.as_str(),
192                         $(
193                             Header: $req_n, $req_v,
194                         )*
195                         Body: $req_body,
196                     },
197                 );
198 
199                 let mut response = $client
200                     .request(request)
201                     .await
202                     .expect("Request send failed");
203 
204                 assert_eq!(response.status().as_u16(), $status, "Assert response status code failed") ;
205                 assert_eq!(response.version().as_str(), $resp_version, "Assert response version failed");
206                 $(assert_eq!(
207                     response
208                         .headers()
209                         .get($resp_n)
210                         .expect(format!("Get response header \"{}\" failed", $resp_n).as_str())
211                         .to_string()
212                         .expect(format!("Convert response header \"{}\"into string failed", $resp_n).as_str()),
213                     $resp_v,
214                     "Assert response header \"{}\" failed", $resp_n,
215                 );)*
216                 let mut buf = [0u8; 4096];
217                 let mut size = 0;
218                 loop {
219                     let read = response
220                         .data(&mut buf[size..]).await
221                         .expect("Response body read failed");
222                     if read == 0 {
223                         break;
224                     }
225                     size += read;
226                 }
227                 assert_eq!(&buf[..size], $resp_body.as_bytes(), "Assert response body failed");
228             }
229         )*
230     }
231 }
232