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 Host: $host, 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, cliipy 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: ylong_server_fn, 74 ); 75 76 let mut shut_downs = vec![]; 77 sync_client_assert!( 78 HTTPS; 79 Tls: $tls_config, 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 RuntimeThreads: $thread_num: expr, 109 $(ClientNum: $client_num: expr,)? 110 $(Request: { 111 Method: $method: expr, 112 Host: $host: 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: $version: expr, 121 $( 122 Header: $resp_n: expr, $resp_v: expr, 123 )* 124 Body: $resp_body: expr, 125 },)* 126 ) => {{ 127 define_service_handle!(HTTP;); 128 set_server_fn!( 129 SYNC; 130 ylong_server_fn, 131 $(Request: { 132 Method: $method, 133 Host: $host, 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, cliipy 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: ylong_server_fn, 163 ); 164 165 let mut shut_downs = vec![]; 166 sync_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! sync_client_assert { 199 ( 200 HTTPS; 201 Tls: $tls_config: 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::sync_impl::Client::builder() 224 .tls_ca_file($tls_config) 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 sync_client_assertions!( 233 ServerHandle: handle, 234 ClientRef: client, 235 $(Request: { 236 Method: $method, 237 Host: $host, 238 $( 239 Header: $req_n, $req_v, 240 )* 241 Body: $req_body, 242 }, 243 Response: { 244 Status: $status, 245 Version: $version, 246 $( 247 Header: $resp_n, $resp_v, 248 )* 249 Body: $resp_body, 250 },)* 251 ); 252 let shutdown_handle = $runtime.spawn(async move { 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 = ylong_http_client::sync_impl::Client::new(); 282 let client = 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 sync_client_assertions!( 287 ServerHandle: handle, 288 ClientRef: client, 289 $(Request: { 290 Method: $method, 291 Host: $host, 292 $( 293 Header: $req_n, $req_v, 294 )* 295 Body: $req_body, 296 }, 297 Response: { 298 Status: $status, 299 Version: $version, 300 $( 301 Header: $resp_n, $resp_v, 302 )* 303 Body: $resp_body, 304 },)* 305 ); 306 let shutdown_handle = $runtime.spawn(async move { 307 ensure_server_shutdown!(ServerHandle: handle); 308 }); 309 $shut_downs.push(shutdown_handle); 310 } 311 312 }} 313 } 314 315 #[macro_export] 316 macro_rules! sync_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_request!( 339 Request: { 340 Method: $method, 341 Host: $host, 342 Port: $handle.port, 343 $( 344 Header: $req_n, $req_v, 345 )* 346 Body: $req_body, 347 }, 348 ); 349 let mut response = $client 350 .request(request) 351 .expect("Request send failed"); 352 assert_eq!(response.status().as_u16(), $status, "Assert response status code failed"); 353 assert_eq!(response.version().as_str(), $version, "Assert response version failed"); 354 $(assert_eq!( 355 response 356 .headers() 357 .get($resp_n) 358 .expect(format!("Get response header \"{}\" failed", $resp_n).as_str()) 359 .to_str() 360 .expect(format!("Convert response header \"{}\"into string failed", $resp_n).as_str()), 361 $resp_v, 362 "Assert response header \"{}\" failed", $resp_n, 363 );)* 364 let mut buf = [0u8; 4096]; 365 let mut size = 0; 366 loop { 367 let read = response 368 .body_mut() 369 .data(&mut buf[size..]) 370 .expect("Response body read failed"); 371 if read == 0 { 372 break; 373 } 374 size += read; 375 } 376 assert_eq!(&buf[..size], $resp_body.as_bytes(), "Assert response body failed"); 377 )* 378 }; 379 } 380