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! sync_client_test_case {
16     (
17         HTTPS;
18         Tls: $tls_config: expr,
19         RuntimeThreads: $thread_num: expr,
20         $(ClientNum: $client_num: expr,)?
21         $(Request: {
22             Method: $method: expr,
23             Host: $host: expr,
24             $(
25                 Header: $req_n: expr, $req_v: expr,
26             )*
27             Body: $req_body: expr,
28         },
29         Response: {
30             Status: $status: expr,
31             Version: $version: expr,
32             $(
33                 Header: $resp_n: expr, $resp_v: expr,
34             )*
35             Body: $resp_body: expr,
36         },)*
37     ) => {{
38         define_service_handle!(HTTPS;);
39         set_server_fn!(
40             SYNC;
41             ylong_server_fn,
42             $(Request: {
43                 Method: $method,
44                 $(
45                     Header: $req_n, $req_v,
46                 )*
47                 Body: $req_body,
48             },
49             Response: {
50                 Status: $status,
51                 Version: $version,
52                 $(
53                     Header: $resp_n, $resp_v,
54                 )*
55                 Body: $resp_body,
56             },)*
57         );
58 
59         let runtime = init_test_work_runtime($thread_num);
60         // The number of servers may be variable based on the number of servers set by the user.
61         // However, cliipy checks that the variable does not need to be variable.
62         #[allow(unused_mut, unused_assignments)]
63         let mut server_num = 1;
64         $(server_num = $client_num;)?
65 
66         let mut handles_vec = vec![];
67         start_server!(
68             HTTPS;
69             ServerNum: server_num,
70             Runtime: runtime,
71             Handles: handles_vec,
72             ServeFnName: ylong_server_fn,
73         );
74 
75         let mut shut_downs = vec![];
76         sync_client_assert!(
77             HTTPS;
78             Tls: $tls_config,
79             Runtime: runtime,
80             ServerNum: server_num,
81             Handles: handles_vec,
82             ShutDownHandles: shut_downs,
83             $(Request: {
84                 Method: $method,
85                 Host: $host,
86                 $(
87                     Header: $req_n, $req_v,
88                 )*
89                 Body: $req_body,
90             },
91             Response: {
92                 Status: $status,
93                 Version: $version,
94                 $(
95                     Header: $resp_n, $resp_v,
96                 )*
97                 Body: $resp_body,
98             },)*
99         );
100 
101         for shutdown_handle in shut_downs {
102             runtime.block_on(shutdown_handle).expect("Runtime wait for server shutdown failed");
103         }
104     }};
105     (
106         HTTP;
107         RuntimeThreads: $thread_num: expr,
108         $(ClientNum: $client_num: expr,)?
109         $(Request: {
110             Method: $method: expr,
111             Host: $host: expr,
112             $(
113                 Header: $req_n: expr, $req_v: expr,
114             )*
115             Body: $req_body: expr,
116         },
117         Response: {
118             Status: $status: expr,
119             Version: $version: expr,
120             $(
121                 Header: $resp_n: expr, $resp_v: expr,
122             )*
123             Body: $resp_body: expr,
124         },)*
125     ) => {{
126         define_service_handle!(HTTP;);
127         set_server_fn!(
128             SYNC;
129             ylong_server_fn,
130             $(Request: {
131                 Method: $method,
132                 $(
133                     Header: $req_n, $req_v,
134                 )*
135                 Body: $req_body,
136             },
137             Response: {
138                 Status: $status,
139                 Version: $version,
140                 $(
141                     Header: $resp_n, $resp_v,
142                 )*
143                 Body: $resp_body,
144             },)*
145         );
146 
147         let runtime = init_test_work_runtime($thread_num);
148         // The number of servers may be variable based on the number of servers set by the user.
149         // However, cliipy checks that the variable does not need to be variable.
150         #[allow(unused_mut, unused_assignments)]
151         let mut server_num = 1;
152         $(server_num = $client_num;)?
153         let mut handles_vec = vec![];
154 
155         start_server!(
156             HTTP;
157             ServerNum: server_num,
158             Runtime: runtime,
159             Handles: handles_vec,
160             ServeFnName: ylong_server_fn,
161         );
162 
163         let mut shut_downs = vec![];
164         sync_client_assert!(
165             HTTP;
166             Runtime: runtime,
167             ServerNum: server_num,
168             Handles: handles_vec,
169             ShutDownHandles: shut_downs,
170             $(Request: {
171                 Method: $method,
172                 Host: $host,
173                 $(
174                     Header: $req_n, $req_v,
175                 )*
176                 Body: $req_body,
177             },
178             Response: {
179                 Status: $status,
180                 Version: $version,
181                 $(
182                     Header: $resp_n, $resp_v,
183                 )*
184                 Body: $resp_body,
185             },)*
186         );
187 
188         for shutdown_handle in shut_downs {
189             runtime.block_on(shutdown_handle).expect("Runtime wait for server shutdown failed");
190         }
191     }};
192 
193 }
194 
195 #[macro_export]
196 macro_rules! sync_client_assert {
197     (
198         HTTPS;
199         Tls: $tls_config: expr,
200         Runtime: $runtime: expr,
201         ServerNum: $server_num: expr,
202         Handles: $handle_vec: expr,
203         ShutDownHandles: $shut_downs: expr,
204         $(Request: {
205             Method: $method: expr,
206             Host: $host: expr,
207             $(
208             Header: $req_n: expr, $req_v: expr,
209             )*
210             Body: $req_body: expr,
211         },
212         Response: {
213             Status: $status: expr,
214             Version: $version: expr,
215             $(
216             Header: $resp_n: expr, $resp_v: expr,
217             )*
218             Body: $resp_body: expr,
219         },)*
220     ) => {{
221         let client = ylong_http_client::sync_impl::Client::builder()
222             .tls_ca_file($tls_config)
223             .danger_accept_invalid_hostnames(true)
224             .build()
225             .unwrap();
226         let client = std::sync::Arc::new(client);
227         for _i in 0..$server_num {
228             let handle = $handle_vec.pop().expect("No more handles !");
229             let client = std::sync::Arc::clone(&client);
230             sync_client_assertions!(
231                 ServerHandle: handle,
232                 ClientRef: client,
233                 $(Request: {
234                     Method: $method,
235                     Host: $host,
236                     $(
237                         Header: $req_n, $req_v,
238                     )*
239                     Body: $req_body,
240                 },
241                 Response: {
242                     Status: $status,
243                     Version: $version,
244                     $(
245                         Header: $resp_n, $resp_v,
246                     )*
247                     Body: $resp_body,
248                 },)*
249             );
250             let shutdown_handle = $runtime.spawn(async move {
251 
252             });
253             $shut_downs.push(shutdown_handle);
254         }
255     }};
256     (
257         HTTP;
258         Runtime: $runtime: expr,
259         ServerNum: $server_num: expr,
260         Handles: $handle_vec: expr,
261         ShutDownHandles: $shut_downs: expr,
262         $(Request: {
263             Method: $method: expr,
264             Host: $host: expr,
265             $(
266             Header: $req_n: expr, $req_v: expr,
267             )*
268             Body: $req_body: expr,
269         },
270         Response: {
271             Status: $status: expr,
272             Version: $version: expr,
273             $(
274             Header: $resp_n: expr, $resp_v: expr,
275             )*
276             Body: $resp_body: expr,
277         },)*
278     ) => {{
279         let client = ylong_http_client::sync_impl::Client::new();
280         let client = Arc::new(client);
281         for _i in 0..$server_num {
282             let mut handle = $handle_vec.pop().expect("No more handles !");
283             let client = std::sync::Arc::clone(&client);
284             sync_client_assertions!(
285                 ServerHandle: handle,
286                 ClientRef: client,
287                 $(Request: {
288                     Method: $method,
289                     Host: $host,
290                     $(
291                         Header: $req_n, $req_v,
292                     )*
293                     Body: $req_body,
294                 },
295                 Response: {
296                     Status: $status,
297                     Version: $version,
298                     $(
299                         Header: $resp_n, $resp_v,
300                     )*
301                     Body: $resp_body,
302                 },)*
303             );
304             let shutdown_handle = $runtime.spawn(async move {
305                 ensure_server_shutdown!(ServerHandle: handle);
306             });
307             $shut_downs.push(shutdown_handle);
308         }
309 
310     }}
311 }
312 
313 #[macro_export]
314 macro_rules! sync_client_assertions {
315     (
316         ServerHandle: $handle:expr,
317         ClientRef: $client:expr,
318         $(Request: {
319             Method: $method: expr,
320             Host: $host: expr,
321             $(
322             Header: $req_n: expr, $req_v: expr,
323             )*
324             Body: $req_body: expr,
325         },
326         Response: {
327             Status: $status: expr,
328             Version: $version: expr,
329             $(
330             Header: $resp_n: expr, $resp_v: expr,
331             )*
332             Body: $resp_body: expr,
333         },)*
334     ) => {
335         $(
336             let request = ylong_request!(
337                 Request: {
338                     Method: $method,
339                     Host: $host,
340                     Port: $handle.port,
341                     $(
342                         Header: $req_n, $req_v,
343                     )*
344                     Body: $req_body,
345                 },
346             );
347             let mut response = $client
348                 .request(request)
349                 .expect("Request send failed");
350             assert_eq!(response.status().as_u16(), $status, "Assert response status code failed");
351             assert_eq!(response.version().as_str(), $version, "Assert response version failed");
352             $(assert_eq!(
353                 response
354                     .headers()
355                     .get($resp_n)
356                     .expect(format!("Get response header \"{}\" failed", $resp_n).as_str())
357                     .to_string()
358                     .expect(format!("Convert response header \"{}\"into string failed", $resp_n).as_str()),
359                 $resp_v,
360                 "Assert response header \"{}\" failed", $resp_n,
361             );)*
362             let mut buf = [0u8; 4096];
363             let mut size = 0;
364             loop {
365                 let read = response
366                     .body_mut()
367                     .data(&mut buf[size..])
368                     .expect("Response body read failed");
369                 if read == 0 {
370                     break;
371                 }
372                 size += read;
373             }
374             assert_eq!(&buf[..size], $resp_body.as_bytes(), "Assert response body failed");
375         )*
376     };
377 }
378