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 .max_h1_conn_number(10) 225 .tls_ca_file($ca_file) 226 .danger_accept_invalid_hostnames(true) 227 .build() 228 .unwrap(); 229 let client = std::sync::Arc::new(client); 230 for _i in 0..$server_num { 231 let handle = $handle_vec.pop().expect("No more handles !"); 232 let client = std::sync::Arc::clone(&client); 233 let shutdown_handle = $runtime.spawn(async move { 234 async_client_assertions!( 235 ServerHandle: handle, 236 ClientRef: client, 237 $(Request: { 238 Method: $method, 239 Host: $host, 240 $( 241 Header: $req_n, $req_v, 242 )* 243 Body: $req_body, 244 }, 245 Response: { 246 Status: $status, 247 Version: $version, 248 $( 249 Header: $resp_n, $resp_v, 250 )* 251 Body: $resp_body, 252 },)* 253 ); 254 }); 255 $shut_downs.push(shutdown_handle); 256 } 257 }}; 258 ( 259 HTTP; 260 Runtime: $runtime: expr, 261 ServerNum: $server_num: expr, 262 Handles: $handle_vec: expr, 263 ShutDownHandles: $shut_downs: expr, 264 $(Request: { 265 Method: $method: expr, 266 Host: $host: expr, 267 $( 268 Header: $req_n: expr, $req_v: expr, 269 )* 270 Body: $req_body: expr, 271 }, 272 Response: { 273 Status: $status: expr, 274 Version: $version: expr, 275 $( 276 Header: $resp_n: expr, $resp_v: expr, 277 )* 278 Body: $resp_body: expr, 279 },)* 280 ) => {{ 281 //let client = async_build_http_client(); 282 let client = ylong_http_client::async_impl::Client::new(); 283 let client = std::sync::Arc::new(client); 284 for _i in 0..$server_num { 285 let mut handle = $handle_vec.pop().expect("No more handles !"); 286 let client = std::sync::Arc::clone(&client); 287 let shutdown_handle = $runtime.spawn(async move { 288 async_client_assertions!( 289 ServerHandle: handle, 290 ClientRef: client, 291 $(Request: { 292 Method: $method, 293 Host: $host, 294 $( 295 Header: $req_n, $req_v, 296 )* 297 Body: $req_body, 298 }, 299 Response: { 300 Status: $status, 301 Version: $version, 302 $( 303 Header: $resp_n, $resp_v, 304 )* 305 Body: $resp_body, 306 },)* 307 ); 308 ensure_server_shutdown!(ServerHandle: handle); 309 }); 310 $shut_downs.push(shutdown_handle); 311 } 312 }} 313 } 314 315 #[macro_export] 316 macro_rules! async_client_assertions { 317 ( 318 ServerHandle: $handle:expr, 319 ClientRef: $client:expr, 320 $(Request: { 321 Method: $method: expr, 322 Host: $host: expr, 323 $( 324 Header: $req_n: expr, $req_v: expr, 325 )* 326 Body: $req_body: expr, 327 }, 328 Response: { 329 Status: $status: expr, 330 Version: $version: expr, 331 $( 332 Header: $resp_n: expr, $resp_v: expr, 333 )* 334 Body: $resp_body: expr, 335 },)* 336 ) => { 337 $( 338 let request = ylong_http_client::async_impl::Request::builder() 339 .method($method) 340 .url(format!("{}:{}", $host, $handle.port).as_str()) 341 $(.header($req_n, $req_v))* 342 .body(ylong_http_client::async_impl::Body::slice($req_body)) 343 .expect("Request build failed"); 344 345 let mut response = $client 346 .request(request) 347 .await 348 .expect("Request send failed"); 349 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 .data(&mut buf[size..]).await 367 .expect("Response body read failed"); 368 if read == 0 { 369 break; 370 } 371 size += read; 372 } 373 assert_eq!(&buf[..size], $resp_body.as_bytes(), "Assert response body failed"); 374 )* 375 } 376 } 377