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_on_tcp { 16 ( 17 HTTP; 18 $(ClientNum: $client_num: expr,)? 19 $(Request: { 20 Method: $method: expr, 21 Version: $req_version: expr, 22 Path: $path: expr, 23 $( 24 Header: $req_n: expr, $req_v: expr, 25 )* 26 Body: $req_body: expr, 27 }, 28 Response: { 29 Status: $status: expr, 30 Version: $resp_version: expr, 31 $( 32 Header: $resp_n: expr, $resp_v: expr, 33 )* 34 Body: $resp_body: expr, 35 },)* 36 ) => {{ 37 38 // The number of servers may be variable based on the number of servers set by the user. 39 // However, clippy checks that the variable does not need to be variable. 40 #[allow(unused_mut, unused_assignments)] 41 let mut server_num = 1; 42 $(server_num = $client_num;)? 43 let mut handles_vec = vec![]; 44 45 start_tcp_server!( 46 ASYNC; 47 Proxy: false, 48 ServerNum: server_num, 49 Handles: handles_vec, 50 $(Request: { 51 Method: $method, 52 Version: $req_version, 53 Path: $path, 54 $( 55 Header: $req_n, $req_v, 56 )* 57 Header: "Accept", "*/*", 58 Body: $req_body, 59 }, 60 Response: { 61 Status: $status, 62 Version: $resp_version, 63 $( 64 Header: $resp_n, $resp_v, 65 )* 66 Body: $resp_body, 67 },)* 68 ); 69 70 let mut shut_downs = vec![]; 71 async_client_assert_on_tcp!( 72 HTTP; 73 ServerNum: server_num, 74 Handles: handles_vec, 75 ShutDownHandles: shut_downs, 76 $(Request: { 77 Method: $method, 78 Version: $req_version, 79 Path: $path, 80 $( 81 Header: $req_n, $req_v, 82 )* 83 Body: $req_body, 84 }, 85 Response: { 86 Status: $status, 87 Version: $resp_version, 88 $( 89 Header: $resp_n, $resp_v, 90 )* 91 Body: $resp_body, 92 },)* 93 ); 94 95 for shutdown_handle in shut_downs { 96 ylong_runtime::block_on(shutdown_handle).expect("Runtime wait for server shutdown failed"); 97 } 98 }}; 99 100 } 101 102 #[macro_export] 103 macro_rules! async_client_assert_on_tcp { 104 ( 105 HTTP; 106 ServerNum: $server_num: expr, 107 Handles: $handle_vec: expr, 108 ShutDownHandles: $shut_downs: expr, 109 $(Request: { 110 Method: $method: expr, 111 Version: $req_version: expr, 112 Path: $path: 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: $resp_version: expr, 121 $( 122 Header: $resp_n: expr, $resp_v: expr, 123 )* 124 Body: $resp_body: expr, 125 },)* 126 ) => {{ 127 let client = ylong_http_client::async_impl::Client::new(); 128 let client = std::sync::Arc::new(client); 129 for _i in 0..$server_num { 130 let handle = $handle_vec.pop().expect("No more handles !"); 131 let client = std::sync::Arc::clone(&client); 132 let shutdown_handle = ylong_runtime::spawn(async move { 133 async_client_assertions_on_tcp!( 134 ServerHandle: handle, 135 ClientRef: client, 136 $(Request: { 137 Method: $method, 138 Version: $req_version, 139 Path: $path, 140 $( 141 Header: $req_n, $req_v, 142 )* 143 Body: $req_body, 144 }, 145 Response: { 146 Status: $status, 147 Version: $resp_version, 148 $( 149 Header: $resp_n, $resp_v, 150 )* 151 Body: $resp_body, 152 },)* 153 ); 154 handle.server_shutdown.recv().expect("server send order failed !"); 155 }); 156 $shut_downs.push(shutdown_handle); 157 } 158 }} 159 } 160 161 #[macro_export] 162 macro_rules! async_client_assertions_on_tcp { 163 ( 164 ServerHandle: $handle:expr, 165 ClientRef: $client:expr, 166 $(Request: { 167 Method: $method: expr, 168 Version: $req_version: expr, 169 Path: $path: expr, 170 $( 171 Header: $req_n: expr, $req_v: expr, 172 )* 173 Body: $req_body: expr, 174 }, 175 Response: { 176 Status: $status: expr, 177 Version: $resp_version: expr, 178 $( 179 Header: $resp_n: expr, $resp_v: expr, 180 )* 181 Body: $resp_body: expr, 182 },)* 183 ) => { 184 $( 185 { 186 let request = build_client_request!( 187 Request: { 188 Method: $method, 189 Version: $req_version, 190 Path: $path, 191 Addr: $handle.addr.as_str(), 192 $( 193 Header: $req_n, $req_v, 194 )* 195 Body: $req_body, 196 }, 197 ); 198 199 let mut response = $client 200 .request(request) 201 .await 202 .expect("Request send failed"); 203 204 assert_eq!(response.status().as_u16(), $status, "Assert response status code failed") ; 205 assert_eq!(response.version().as_str(), $resp_version, "Assert response version failed"); 206 $(assert_eq!( 207 response 208 .headers() 209 .get($resp_n) 210 .expect(format!("Get response header \"{}\" failed", $resp_n).as_str()) 211 .to_string() 212 .expect(format!("Convert response header \"{}\"into string failed", $resp_n).as_str()), 213 $resp_v, 214 "Assert response header \"{}\" failed", $resp_n, 215 );)* 216 let mut buf = [0u8; 4096]; 217 let mut size = 0; 218 loop { 219 let read = response 220 .data(&mut buf[size..]).await 221 .expect("Response body read failed"); 222 if read == 0 { 223 break; 224 } 225 size += read; 226 } 227 assert_eq!(&buf[..size], $resp_body.as_bytes(), "Assert response body failed"); 228 } 229 )* 230 } 231 } 232