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