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