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 <gtest/gtest.h>
17 #include <thread>
18 #include <sys/eventfd.h>
19 #include <cstdarg>
20
21 #include "begetctl.h"
22 #include "cJSON.h"
23 #include "init.h"
24 #include "init_hashmap.h"
25 #include "init_param.h"
26 #include "init_utils.h"
27 #include "le_epoll.h"
28 #include "le_loop.h"
29 #include "le_socket.h"
30 #include "le_task.h"
31 #include "loop_event.h"
32 #include "param_manager.h"
33 #include "param_message.h"
34 #include "param_utils.h"
35 #include "trigger_manager.h"
36
37 using namespace testing::ext;
38 using namespace std;
39
40 namespace init_ut {
41 const std::string TCP_SERVER = "127.0.0.1:7777";
42 const std::string PIPE_SERVER = STARTUP_INIT_UT_PATH "/dev/unix/socket/testsocket";
43 const std::string WATCHER_FILE = STARTUP_INIT_UT_PATH "/test_watcher_file";
44 const std::string FORMAT_STR = "{ \"cmd\":%d, \"message\":\"%s\" }";
45
46 static LoopHandle g_loopClient_ = nullptr;
47 static LoopHandle g_loopServer_ = nullptr;
48 static int g_maxCount = 0;
49 static int g_timeCount = 0;
50 static int g_cmd = 2;
DecodeMessage(const char * buffer,size_t nread,uint32_t & cmd)51 static void DecodeMessage(const char *buffer, size_t nread, uint32_t &cmd)
52 {
53 cJSON *root = cJSON_ParseWithLength(buffer, nread);
54 if (root == nullptr) {
55 EXPECT_NE(root, nullptr);
56 printf("Invalid message %s \n", buffer);
57 return;
58 }
59 printf("Message: %s \n", cJSON_GetStringValue(cJSON_GetObjectItem(root, "message")));
60 cmd = cJSON_GetNumberValue(cJSON_GetObjectItem(root, "cmd"));
61 printf("cmd: %d \n", cmd);
62 cJSON_Delete(root);
63 return;
64 }
65
SendMessage(const LoopHandle loopHandle,const TaskHandle taskHandle,const char * message,...)66 static void SendMessage(const LoopHandle loopHandle, const TaskHandle taskHandle, const char *message, ...)
67 {
68 uint32_t bufferSize = 1024; // 1024 buffer size
69 BufferHandle handle = LE_CreateBuffer(loopHandle, bufferSize);
70 char *buffer = (char *)LE_GetBufferInfo(handle, nullptr, &bufferSize);
71
72 va_list vargs;
73 va_start(vargs, message);
74 if (vsnprintf_s(buffer, bufferSize, bufferSize - 1, message, vargs) == -1) {
75 LE_FreeBuffer(loopHandle, taskHandle, handle);
76 va_end(vargs);
77 EXPECT_EQ(1, 0);
78 return;
79 }
80 va_end(vargs);
81 int ret = LE_Send(loopHandle, taskHandle, handle, bufferSize);
82 EXPECT_EQ(ret, 0);
83 }
84
TestOnClose(const TaskHandle taskHandle)85 static void TestOnClose(const TaskHandle taskHandle)
86 {
87 }
88
TestOnReceiveRequest(const TaskHandle task,const uint8_t * buffer,uint32_t nread)89 static void TestOnReceiveRequest(const TaskHandle task, const uint8_t *buffer, uint32_t nread)
90 {
91 EXPECT_NE(buffer, nullptr);
92 if (buffer == nullptr) {
93 return;
94 }
95 printf("Server receive message %s \n", reinterpret_cast<const char *>(buffer));
96 uint32_t cmd = 0;
97 DecodeMessage(reinterpret_cast<const char *>(buffer), nread, cmd);
98 SendMessage(g_loopServer_, task, reinterpret_cast<const char *>(buffer));
99 }
100
TestClientOnReceiveRequest(const TaskHandle task,const uint8_t * buffer,uint32_t nread)101 static void TestClientOnReceiveRequest(const TaskHandle task, const uint8_t *buffer, uint32_t nread)
102 {
103 printf("Client receive message %s \n", reinterpret_cast<const char *>(buffer));
104 EXPECT_NE(buffer, nullptr);
105 if (buffer == nullptr) {
106 return;
107 }
108 uint32_t cmd = 0;
109 DecodeMessage(reinterpret_cast<const char *>(buffer), nread, cmd);
110 if (cmd == 5 || cmd == 2) { // 2 5 close server
111 LE_StopLoop(g_loopClient_);
112 }
113 }
114
TestSendMessageComplete(const TaskHandle taskHandle,BufferHandle handle)115 static void TestSendMessageComplete(const TaskHandle taskHandle, BufferHandle handle)
116 {
117 printf("SendMessage result %d \n", LE_GetSendResult(handle));
118 uint32_t bufferSize = 1024; // 1024 buffer size
119 char *buffer = (char *)LE_GetBufferInfo(handle, nullptr, &bufferSize);
120 uint32_t cmd = 0;
121 DecodeMessage(reinterpret_cast<const char *>(buffer), bufferSize, cmd);
122 if (cmd == 5) { // 5 close server
123 LE_StopLoop(g_loopServer_);
124 }
125 }
126
TestTcpIncomingConnect(LoopHandle loop,TaskHandle server)127 static int TestTcpIncomingConnect(LoopHandle loop, TaskHandle server)
128 {
129 PARAM_CHECK(server != nullptr, return -1, "Error server");
130 printf("Tcp connect incoming \n");
131 TaskHandle stream;
132 LE_StreamInfo info = {};
133 info.baseInfo.flags = TASK_STREAM | TASK_TCP | TASK_CONNECT;
134 info.baseInfo.close = TestOnClose;
135 info.baseInfo.userDataSize = 0;
136 info.disConnectComplete = nullptr;
137 info.sendMessageComplete = TestSendMessageComplete;
138 info.recvMessage = TestOnReceiveRequest;
139 LE_STATUS ret = LE_AcceptStreamClient(loop, server, &stream, &info);
140 EXPECT_EQ(ret, 0);
141 return 0;
142 }
143
TestPipIncomingConnect(LoopHandle loop,TaskHandle server)144 static int TestPipIncomingConnect(LoopHandle loop, TaskHandle server)
145 {
146 PARAM_CHECK(server != nullptr, return -1, "Error server");
147 printf("Pipe connect incoming \n");
148 TaskHandle stream;
149 LE_StreamInfo info = {};
150 info.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_CONNECT;
151 info.baseInfo.close = TestOnClose;
152 info.baseInfo.userDataSize = 0;
153 info.disConnectComplete = nullptr;
154 info.sendMessageComplete = TestSendMessageComplete;
155 info.recvMessage = TestOnReceiveRequest;
156 LE_STATUS ret = LE_AcceptStreamClient(loop, server, &stream, &info);
157 EXPECT_EQ(ret, 0);
158 return 0;
159 }
160
TestConnectComplete(const TaskHandle client)161 static void TestConnectComplete(const TaskHandle client)
162 {
163 printf("Connect complete \n");
164 }
165
TestDisConnectComplete(const TaskHandle client)166 static void TestDisConnectComplete(const TaskHandle client)
167 {
168 printf("DisConnect complete \n");
169 LE_StopLoop(g_loopClient_);
170 }
171
TestProcessTimer(const TimerHandle taskHandle,void * context)172 static void TestProcessTimer(const TimerHandle taskHandle, void *context)
173 {
174 g_timeCount++;
175 printf("ProcessTimer %d\n", g_timeCount);
176 if (g_maxCount == 2) { // 2 stop
177 if (g_timeCount >= g_maxCount) {
178 LE_StopLoop(g_loopClient_);
179 }
180 }
181 if (g_maxCount == 3) { // 3 stop timer
182 if (g_timeCount >= g_maxCount) {
183 LE_StopTimer(g_loopClient_, taskHandle);
184 LE_StopLoop(g_loopClient_);
185 }
186 }
187 if (g_maxCount == 10) { // 10 write watcher file
188 FILE *tmpFile = fopen(WATCHER_FILE.c_str(), "wr");
189 if (tmpFile != nullptr) {
190 fprintf(tmpFile, "%s", "test watcher file 22222222222");
191 (void)fflush(tmpFile);
192 fclose(tmpFile);
193 }
194 LE_StopTimer(g_loopClient_, taskHandle);
195 LE_StopLoop(g_loopClient_);
196 }
197 }
198
ProcessWatchEventTest(WatcherHandle taskHandle,int fd,uint32_t * events,const void * context)199 static void ProcessWatchEventTest(WatcherHandle taskHandle, int fd, uint32_t *events, const void *context)
200 {
201 UNUSED(taskHandle);
202 UNUSED(fd);
203 UNUSED(events);
204 UNUSED(context);
205 printf("Process watcher event \n");
206 LE_StopLoop(g_loopClient_);
207 }
208
209 class LoopServerUnitTest : public testing::Test {
210 public:
LoopServerUnitTest()211 LoopServerUnitTest() {};
~LoopServerUnitTest()212 virtual ~LoopServerUnitTest() {};
SetUpTestCase(void)213 static void SetUpTestCase(void) {};
TearDownTestCase(void)214 static void TearDownTestCase(void) {};
SetUp()215 void SetUp() {};
TearDown()216 void TearDown() {};
TestBody(void)217 void TestBody(void) {};
218
219 // for thread to create tcp\pipe server
RunServer(void)220 void RunServer(void)
221 {
222 TaskHandle tcpServer = nullptr;
223 TaskHandle pipeServer = nullptr;
224 LE_STATUS ret = LE_CreateLoop(&g_loopServer_);
225 EXPECT_EQ(ret, 0);
226 // create server for tcp
227 LE_StreamServerInfo info = {};
228 info.baseInfo.flags = TASK_STREAM | TASK_TCP | TASK_SERVER;
229 info.socketId = -1;
230 info.server = const_cast<char *>(TCP_SERVER.c_str());
231 info.baseInfo.close = TestOnClose;
232 info.incommingConnect = TestTcpIncomingConnect;
233 ret = LE_CreateStreamServer(g_loopServer_, &tcpServer, &info);
234 EXPECT_EQ(ret, 0);
235
236 info.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_SERVER;
237 info.socketId = -1;
238 info.server = const_cast<char *>(PIPE_SERVER.c_str());
239 info.baseInfo.close = TestOnClose;
240 info.incommingConnect = TestPipIncomingConnect;
241 ret = LE_CreateStreamServer(g_loopServer_, &pipeServer, &info);
242 EXPECT_EQ(ret, 0);
243
244 printf("Run server pipeServer_ \n");
245 // run loop for server
246 LE_RunLoop(g_loopServer_);
247
248 printf("Run server pipeServer_ \n");
249 LE_CloseStreamTask(g_loopServer_, pipeServer);
250 pipeServer = nullptr;
251 LE_CloseStreamTask(g_loopServer_, tcpServer);
252 tcpServer = nullptr;
253 LE_CloseLoop(g_loopServer_);
254 g_loopServer_ = nullptr;
255 }
256
StartServer()257 void StartServer()
258 {
259 std::thread(&LoopServerUnitTest::RunServer, this).detach();
260 sleep(1);
261 }
262
CreateConnect(const char * tcpServer,uint32_t flags)263 TaskHandle CreateConnect(const char *tcpServer, uint32_t flags)
264 {
265 if (g_loopClient_ == nullptr) {
266 LE_STATUS ret = LE_CreateLoop(&g_loopClient_);
267 EXPECT_EQ(ret, 0);
268 }
269
270 TaskHandle task = nullptr;
271 LE_StreamInfo info = {};
272 info.baseInfo.flags = TASK_STREAM | flags | TASK_CONNECT;
273 info.server = const_cast<char *>(tcpServer);
274 info.baseInfo.userDataSize = 0;
275 info.baseInfo.close = TestOnClose;
276 info.disConnectComplete = TestDisConnectComplete;
277 info.connectComplete = TestConnectComplete;
278 info.sendMessageComplete = nullptr;
279 info.recvMessage = TestClientOnReceiveRequest;
280 LE_STATUS status = LE_CreateStreamClient(g_loopClient_, &task, &info);
281 EXPECT_EQ(status, 0);
282 return task;
283 }
284
CreateWatcherTask(int fd,const char * fileName)285 WatcherHandle CreateWatcherTask(int fd, const char *fileName)
286 {
287 if (g_loopClient_ == nullptr) {
288 LE_STATUS ret = LE_CreateLoop(&g_loopClient_);
289 EXPECT_EQ(ret, 0);
290 }
291 WatcherHandle handle = nullptr;
292 LE_WatchInfo info = {};
293 info.fd = fd;
294 info.flags = WATCHER_ONCE;
295 info.events = EVENT_READ | EVENT_WRITE;
296 info.processEvent = ProcessWatchEventTest;
297 LE_STATUS status = LE_StartWatcher(g_loopClient_, &handle, &info, nullptr);
298 EXPECT_EQ(status, 0);
299 return handle;
300 }
301
CreateTimerTask(int repeat)302 TimerHandle CreateTimerTask(int repeat)
303 {
304 if (g_loopClient_ == nullptr) {
305 LE_STATUS ret = LE_CreateLoop(&g_loopClient_);
306 EXPECT_EQ(ret, 0);
307 }
308 TimerHandle timer = nullptr;
309 int ret = LE_CreateTimer(g_loopClient_, &timer, TestProcessTimer, nullptr);
310 EXPECT_EQ(ret, 0);
311 ret = LE_StartTimer(g_loopClient_, timer, 500, repeat); // 500 ms
312 EXPECT_EQ(ret, 0);
313 return timer;
314 }
315 private:
316 std::thread *serverThread_ = nullptr;
317 };
318
319 HWTEST_F(LoopServerUnitTest, Init_TestRunServer_001, TestSize.Level1)
320 {
321 LoopServerUnitTest test;
322 test.StartServer();
323 }
324
325 HWTEST_F(LoopServerUnitTest, Init_TestPipConnect_001, TestSize.Level1)
326 {
327 g_cmd = 2; // 2 only close client
328 LoopServerUnitTest test;
329 TaskHandle pipe = test.CreateConnect(PIPE_SERVER.c_str(), TASK_PIPE);
330 EXPECT_NE(pipe, nullptr);
331 SendMessage(g_loopClient_, pipe, FORMAT_STR.c_str(), g_cmd, "connect success");
332 LE_RunLoop(g_loopClient_);
333 LE_CloseStreamTask(g_loopClient_, pipe);
334 LE_CloseLoop(g_loopClient_);
335 g_loopClient_ = nullptr;
336 }
337
338 HWTEST_F(LoopServerUnitTest, Init_TestTcpConnect_001, TestSize.Level1)
339 {
340 g_cmd = 2; // 2 only close client
341 LoopServerUnitTest test;
342 TaskHandle tcp = test.CreateConnect(TCP_SERVER.c_str(), TASK_TCP);
343 EXPECT_NE(tcp, nullptr);
344 SendMessage(g_loopClient_, tcp, FORMAT_STR.c_str(), g_cmd, "connect success");
345 LE_RunLoop(g_loopClient_);
346 LE_CloseStreamTask(g_loopClient_, tcp);
347 LE_CloseLoop(g_loopClient_);
348 g_loopClient_ = nullptr;
349 }
350
351 HWTEST_F(LoopServerUnitTest, Init_TestTimer_001, TestSize.Level1)
352 {
353 LoopServerUnitTest test;
354 g_maxCount = 2; // 2 stop
355 TimerHandle timer = test.CreateTimerTask(2);
356 EXPECT_NE(timer, nullptr);
357 LE_RunLoop(g_loopClient_);
358 LE_CloseLoop(g_loopClient_);
359 g_loopClient_ = nullptr;
360 }
361
362 HWTEST_F(LoopServerUnitTest, Init_TestTimer_002, TestSize.Level1)
363 {
364 LoopServerUnitTest test;
365 g_maxCount = 3; // 3 stop timer
366 TimerHandle timer = test.CreateTimerTask(3);
367 EXPECT_NE(timer, nullptr);
368 LE_RunLoop(g_loopClient_);
369 LE_CloseLoop(g_loopClient_);
370 g_loopClient_ = nullptr;
371 }
372
373 HWTEST_F(LoopServerUnitTest, Init_TestWatcher_001, TestSize.Level1)
374 {
375 int fd = open(WATCHER_FILE.c_str(), O_RDWR | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
376 if (fd >= 0) {
377 write(fd, WATCHER_FILE.c_str(), WATCHER_FILE.size());
378 }
379 EXPECT_GE(fd, 0);
380 printf("Watcher fd %d \n", fd);
381 LoopServerUnitTest test;
382 WatcherHandle watcher = test.CreateWatcherTask(3, WATCHER_FILE.c_str());
383 EXPECT_NE(watcher, nullptr);
384 g_maxCount = 10; // 10 write watcher file
385 TimerHandle timer = test.CreateTimerTask(1);
386 EXPECT_NE(timer, nullptr);
387
388 LE_RunLoop(g_loopClient_);
389 LE_RemoveWatcher(g_loopClient_, watcher);
390 close(fd);
391 LE_CloseLoop(g_loopClient_);
392 g_loopClient_ = nullptr;
393 }
394
395 HWTEST_F(LoopServerUnitTest, Init_TestStopServer_001, TestSize.Level1)
396 {
397 g_cmd = 5; // 5 close server
398 LoopServerUnitTest test;
399 TaskHandle pip = test.CreateConnect(PIPE_SERVER.c_str(), TASK_PIPE);
400 EXPECT_NE(pip, nullptr);
401 SendMessage(g_loopClient_, pip, FORMAT_STR.c_str(), g_cmd, "connect success");
402 LE_RunLoop(g_loopClient_);
403 LE_CloseStreamTask(g_loopClient_, pip);
404 LE_CloseLoop(g_loopClient_);
405 g_loopClient_ = nullptr;
406 }
407
408 HWTEST_F(LoopServerUnitTest, Init_TestServerTimeout_001, TestSize.Level1)
409 {
410 int flag = TASK_STREAM | TASK_PIPE | TASK_SERVER | TASK_TEST;
411 int serverSock = CreateSocket(flag, "/data/test1pipe");
412 EXPECT_NE(serverSock, -1);
413 int ret = AcceptSocket(serverSock, flag);
414 EXPECT_EQ(ret, -1);
415 }
416 } // namespace init_ut
417