1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <hwext/gtest-ext.h>
17 #include <hwext/gtest-tag.h>
18 #include <netinet/in.h>
19 #include <sys/socket.h>
20
21 #include "http_server.h"
22 #include "http_socket.h"
23 #include "rpc/rpc_server.h"
24 #include "string_help.h"
25
26 using namespace testing::ext;
27 namespace SysTuning {
28 namespace TraceStreamer {
29 using namespace SysTuning::base;
30 #define UNUSED(expr) \
31 do { \
32 static_cast<void>(expr); \
33 } while (0)
34
35 const uint32_t MAX_TESET_BUF_SIZE = 1024;
36 std::string g_parserData = "sugov:0-178 ( 178) [001] .... 28462.257501: cpu_frequency: state=816000 cpu_id=0 \n";
37 std::string g_sqlQuery("select * from measure;");
38 char g_clientRecvBuf[MAX_TESET_BUF_SIZE] = {0};
39 class HttpServerTest : public ::testing::Test {
40 public:
SetUp()41 void SetUp()
42 {
43 stream_.InitFilter();
44 }
TearDown()45 void TearDown() {}
46
47 public:
48 TraceStreamerSelector stream_ = {};
49 };
50
ResultCallbackFunc(const std::string result,int num)51 void ResultCallbackFunc(const std::string result, int num)
52 {
53 // unused
54 UNUSED(result);
55 }
56
HttpServerThread(void * arg)57 void* HttpServerThread(void* arg)
58 {
59 HttpServer* httpServer = static_cast<HttpServer*>(arg);
60 httpServer->Run();
61 TS_LOGI("Server thread end");
62 pthread_exit(nullptr);
63 }
64
HttpClient(const char * buf)65 int HttpClient(const char* buf)
66 {
67 struct sockaddr_in addr;
68 addr.sin_family = AF_INET;
69 addr.sin_addr.s_addr = htons(INADDR_ANY);
70 const uint16_t listenPort = 9001;
71 addr.sin_port = htons(listenPort);
72 struct timeval recvTimeout = {1, 100000};
73
74 int sockfd = socket(AF_INET, SOCK_STREAM, 0);
75 if (sockfd < 0) {
76 TS_LOGI("CreateSocket socket error");
77 return -1;
78 }
79
80 int ret = connect(sockfd, (struct sockaddr*)(&addr), sizeof(struct sockaddr));
81 if (ret < 0) {
82 TS_LOGE("Connect error");
83 return -1;
84 }
85
86 ret = send(sockfd, buf, strlen(buf), 0);
87 if (ret < 0) {
88 TS_LOGE("Send error");
89 return -1;
90 }
91
92 if (!memset_s(g_clientRecvBuf, strlen(g_clientRecvBuf), 0, strlen(g_clientRecvBuf))) {
93 TS_LOGE("memset_s error");
94 return -1;
95 }
96 int index = 0;
97 ret = setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char*)(&recvTimeout), sizeof(recvTimeout));
98 if (ret != 0) {
99 TS_LOGE("set recv time out error");
100 return -1;
101 }
102 while (1) {
103 ret = recv(sockfd, g_clientRecvBuf + index, MAX_TESET_BUF_SIZE, 0);
104 if (ret < 0) {
105 TS_LOGE("Recv timeout");
106 break;
107 }
108 index += ret;
109 }
110 return 0;
111 }
112
113 /**
114 * @tc.name: HttpCorrectRequest
115 * @tc.desc: HTTP correct request
116 * @tc.type: FUNC
117 */
118 HWTEST_F(HttpServerTest, HttpCorrectRequest, TestSize.Level1)
119 {
120 TS_LOGI("test21-1");
121 HttpServer httpServer;
122 RpcServer rpcServer;
123 pthread_t pthreadId = 0;
124 int ret = 0;
125
126 ret = rpcServer.ParseData((const uint8_t*)g_parserData.c_str(), g_parserData.length(), ResultCallbackFunc);
127 ret = rpcServer.ParseDataOver(nullptr, 0, ResultCallbackFunc);
128 ret = rpcServer.SqlQuery((const uint8_t*)g_sqlQuery.c_str(), g_sqlQuery.length(), ResultCallbackFunc);
129
130 httpServer.RegisterRpcFunction(&rpcServer);
131 ret = pthread_create(&pthreadId, nullptr, HttpServerThread, &httpServer);
132 if (ret != 0) {
133 TS_LOGE("Server pthread create fail");
134 pthread_exit(nullptr);
135 }
136
137 sleep(1);
138 std::string bufToSend =
139 "GET /sqlquery HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Length:\
140 23\r\n\r\nselect * from measure\r\n";
141
142 ret = HttpClient(bufToSend.c_str());
143 if (ret < 0) {
144 TS_LOGE("Client fail");
145 }
146 httpServer.Exit();
147 ret = pthread_join(pthreadId, nullptr);
148 if (ret != 0) {
149 TS_LOGE("Server pthread jion fail");
150 }
151 char targetStr[MAX_TESET_BUF_SIZE] = {
152 "HTTP/1.1 200 OK\r\nConnection: Keep-Alive\r\nContent-Type: application/json\r\nTransfer-Encoding: "
153 "chunked\r\n\r\n62\r\nok\r\n{\"columns\":[\"type\",\"ts\",\"value\",\"filter_id\"],\"values\":[[\"measure\","
154 "28462257501000,816000,0]]}"
155 "\r\n\r\n0\r\n\r\n"};
156
157 EXPECT_STREQ(targetStr, g_clientRecvBuf);
158 }
159 /**
160 * @tc.name: OthreAgreement
161 * @tc.desc: Use http1 1. Agreements other than agreements
162 * @tc.type: FUNC
163 */
164 HWTEST_F(HttpServerTest, OthreAgreement, TestSize.Level1)
165 {
166 TS_LOGI("test21-2");
167 HttpServer httpServer;
168 RpcServer rpcServer;
169 pthread_t pthreadId = 0;
170 int ret = 0;
171
172 httpServer.RegisterRpcFunction(&rpcServer);
173 ret = pthread_create(&pthreadId, nullptr, HttpServerThread, &httpServer);
174 if (ret != 0) {
175 TS_LOGE("Server pthread create fail");
176 pthread_exit(nullptr);
177 }
178
179 sleep(1);
180 std::string bufToSend =
181 "GET /sqlquery HTTP/0.9\r\nHost: 127.0.0.1\r\nContent-Length:\
182 23\r\n\r\nselect * from measure\r\n";
183
184 ret = HttpClient(bufToSend.c_str());
185 if (ret < 0) {
186 TS_LOGE("Client fail");
187 }
188 httpServer.Exit();
189 ret = pthread_join(pthreadId, nullptr);
190 if (ret != 0) {
191 TS_LOGE("Server pthread jion fail");
192 }
193 char targetStr[MAX_TESET_BUF_SIZE] = {"HTTP/1.1 400 Bad Request\r\nConnection: Keep-Alive\r\n\r\n"};
194 EXPECT_STREQ(targetStr, g_clientRecvBuf);
195 }
196
197 /**
198 * @tc.name: OthreProtocols
199 * @tc.desc: Use protocols other than GET and POST
200 * @tc.type: FUNC
201 */
202 HWTEST_F(HttpServerTest, OthreProtocols, TestSize.Level1)
203 {
204 TS_LOGI("test21-3");
205 HttpServer httpServer;
206 RpcServer rpcServer;
207 pthread_t pthreadId = 0;
208 int ret = 0;
209
210 httpServer.RegisterRpcFunction(&rpcServer);
211 ret = pthread_create(&pthreadId, nullptr, HttpServerThread, &httpServer);
212 if (ret != 0) {
213 TS_LOGE("Server pthread create fail");
214 pthread_exit(nullptr);
215 }
216
217 sleep(1);
218 std::string bufToSend =
219 "HEAD /sqlquery HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Length:\
220 23\r\n\r\nselect * from measure\r\n";
221
222 ret = HttpClient(bufToSend.c_str());
223 if (ret < 0) {
224 TS_LOGE("Client fail");
225 }
226 httpServer.Exit();
227 ret = pthread_join(pthreadId, nullptr);
228 if (ret != 0) {
229 TS_LOGE("Server pthread jion fail");
230 }
231 char targetStr[MAX_TESET_BUF_SIZE] = {"HTTP/1.1 405 Method Not Allowed\r\nConnection: Keep-Alive\r\n\r\n"};
232 EXPECT_STREQ(targetStr, g_clientRecvBuf);
233 }
234
235 /**
236 * @tc.name: RequestLineFormatError
237 * @tc.desc: Request line format error
238 * @tc.type: FUNC
239 */
240 HWTEST_F(HttpServerTest, RequestLineFormatError, TestSize.Level1)
241 {
242 TS_LOGI("test21-4");
243 HttpServer httpServer;
244 RpcServer rpcServer;
245 pthread_t pthreadId = 0;
246 int ret = 0;
247
248 httpServer.RegisterRpcFunction(&rpcServer);
249 ret = pthread_create(&pthreadId, nullptr, HttpServerThread, &httpServer);
250 if (ret != 0) {
251 TS_LOGE("Server pthread create fail");
252 pthread_exit(nullptr);
253 }
254
255 sleep(1);
256 std::string bufToSend =
257 "POST /sqlqueryHTTP/0.9\r\nHost: 127.0.0.1\r\nContent-Length:\
258 20\r\n\r\nselect * from meta\r\n";
259
260 ret = HttpClient(bufToSend.c_str());
261 if (ret < 0) {
262 TS_LOGE("Client fail");
263 }
264 httpServer.Exit();
265 ret = pthread_join(pthreadId, nullptr);
266 if (ret != 0) {
267 TS_LOGE("Server pthread jion fail");
268 }
269 char targetStr[MAX_TESET_BUF_SIZE] = {"HTTP/1.1 400 Bad Request\r\nConnection: Keep-Alive\r\n\r\n"};
270 EXPECT_STREQ(targetStr, g_clientRecvBuf);
271 }
272
273 /**
274 * @tc.name: RequestIsNotRPC
275 * @tc.desc: The URI of HTTP request is not the method of RPC
276 * @tc.type: FUNC
277 */
278 HWTEST_F(HttpServerTest, RequestIsNotRPC, TestSize.Level1)
279 {
280 TS_LOGI("test21-5");
281 HttpServer httpServer;
282 RpcServer rpcServer;
283 pthread_t pthreadId = 0;
284 int ret = 0;
285
286 httpServer.RegisterRpcFunction(&rpcServer);
287 ret = pthread_create(&pthreadId, nullptr, HttpServerThread, &httpServer);
288 if (ret != 0) {
289 TS_LOGE("Server pthread create fail");
290 pthread_exit(nullptr);
291 }
292
293 sleep(1);
294 std::string bufToSend =
295 "POST /query HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Length:20\r\n\r\n\
296 select * from meta\r\n";
297
298 ret = HttpClient(bufToSend.c_str());
299 if (ret < 0) {
300 TS_LOGE("Client fail");
301 }
302 httpServer.Exit();
303 ret = pthread_join(pthreadId, nullptr);
304 if (ret != 0) {
305 TS_LOGE("Server pthread jion fail");
306 }
307 char targetStr[MAX_TESET_BUF_SIZE] = {"HTTP/1.1 404 Not Found\r\nConnection: Keep-Alive\r\n\r\n"};
308 EXPECT_STREQ(targetStr, g_clientRecvBuf);
309 }
310 /**
311 * @tc.name: RequestTimeout
312 * @tc.desc: Incomplete request content data
313 * @tc.type: FUNC
314 */
315 HWTEST_F(HttpServerTest, RequestTimeout, TestSize.Level1)
316 {
317 TS_LOGI("test21-6");
318 HttpServer httpServer;
319 RpcServer rpcServer;
320 pthread_t pthreadId = 0;
321 int ret = 0;
322
323 httpServer.RegisterRpcFunction(&rpcServer);
324 ret = pthread_create(&pthreadId, nullptr, HttpServerThread, &httpServer);
325 if (ret != 0) {
326 TS_LOGE("Server pthread create fail");
327 pthread_exit(nullptr);
328 }
329
330 sleep(1);
331 std::string buf =
332 "GET /sqlquery HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Length:\
333 28\r\n\r\nselect * from measure\r\n";
334
335 ret = HttpClient(buf.c_str());
336 if (ret < 0) {
337 TS_LOGE("Client fail");
338 }
339 httpServer.Exit();
340 ret = pthread_join(pthreadId, nullptr);
341 if (ret != 0) {
342 TS_LOGE("Server pthread jion fail");
343 }
344 char targetStr[MAX_TESET_BUF_SIZE] = {"HTTP/1.1 408 Request Time-out\r\nConnection: Keep-Alive\r\n\r\n"};
345 EXPECT_STREQ(targetStr, g_clientRecvBuf);
346 }
347 } // namespace TraceStreamer
348 } // namespace SysTuning