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