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#include <gtest/gtest.h>
16#include <pthread.h>
17#include <sys/eventfd.h>
18
19#include "begetctl.h"
20#include "init.h"
21#include "init_hashmap.h"
22#include "init_param.h"
23#include "init_utils.h"
24#include "le_epoll.h"
25#include "le_loop.h"
26#include "le_socket.h"
27#include "le_task.h"
28#include "loop_event.h"
29#include "param_manager.h"
30#include "param_message.h"
31#include "param_utils.h"
32#include "trigger_manager.h"
33
34using namespace testing::ext;
35using namespace std;
36
37using HashTab = struct {
38    HashNodeCompare nodeCompare;
39    HashKeyCompare keyCompare;
40    HashNodeFunction nodeHash;
41    HashKeyFunction keyHash;
42    HashNodeOnFree nodeFree;
43    int maxBucket;
44    uint32_t tableId;
45    HashNode *buckets[0];
46};
47
48static LE_STATUS TestHandleTaskEvent(const LoopHandle loop, const TaskHandle task, uint32_t oper)
49{
50    return LE_SUCCESS;
51}
52
53static void OnReceiveRequest(const TaskHandle task, const uint8_t *buffer, uint32_t nread)
54{
55    UNUSED(task);
56    UNUSED(buffer);
57    UNUSED(nread);
58}
59
60static void ProcessAsyncEvent(const TaskHandle taskHandle, uint64_t eventId, const uint8_t *buffer, uint32_t buffLen)
61{
62    UNUSED(taskHandle);
63    UNUSED(eventId);
64    UNUSED(buffer);
65    UNUSED(buffLen);
66}
67
68static int IncomingConnect(LoopHandle loop, TaskHandle server)
69{
70    UNUSED(loop);
71    UNUSED(server);
72    return 0;
73}
74
75static void ProcessWatchEventTest(WatcherHandle taskHandle, int fd, uint32_t *events, const void *context)
76{
77    UNUSED(taskHandle);
78    UNUSED(fd);
79    UNUSED(events);
80    UNUSED(context);
81}
82
83namespace init_ut {
84class LoopEventUnittest : public testing::Test {
85public:
86    LoopEventUnittest() {};
87    virtual ~LoopEventUnittest() {};
88    static void SetUpTestCase(void) {};
89    static void TearDownTestCase(void) {};
90    void SetUp() {};
91    void TearDown() {};
92    void TestBody(void) {};
93    int CreateServerTask()
94    {
95        CheckTaskFlags(nullptr, EVENT_WRITE);
96        ParamStreamInfo info = {};
97        info.server = const_cast<char *>(PIPE_NAME);
98        info.close = nullptr;
99        info.recvMessage = nullptr;
100        info.incomingConnect = OnIncomingConnect;
101        return ParamServerCreate(&serverTask_, &info);
102    }
103
104    void StreamTaskTest ()
105    {
106        LE_StreamInfo streamInfo = {};
107        streamInfo.recvMessage = OnReceiveRequest;
108        streamInfo.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_CONNECT | TASK_TEST;
109        streamInfo.server = (char *)"/data/testpipea";
110        TaskHandle clientTaskHandle = nullptr;
111        LE_AcceptStreamClient(LE_GetDefaultLoop(), (TaskHandle)serverTask_, &clientTaskHandle, &streamInfo);
112        if (clientTaskHandle == nullptr) {
113            return;
114        }
115        ((StreamConnectTask *)clientTaskHandle)->stream.base.handleEvent(LE_GetDefaultLoop(),
116            (TaskHandle)clientTaskHandle, 0);
117        ((StreamConnectTask *)clientTaskHandle)->stream.base.handleEvent(LE_GetDefaultLoop(),
118            (TaskHandle)clientTaskHandle, EVENT_READ);
119
120        TaskHandle clientTaskHandlec = nullptr;
121        streamInfo.baseInfo.flags = TASK_STREAM | TASK_TCP | TASK_SERVER;
122        streamInfo.server = (char *)"0.0.0.0:10110";
123        LE_CreateStreamClient(LE_GetDefaultLoop(), &clientTaskHandlec, &streamInfo);
124        if (clientTaskHandlec == nullptr) {
125            return;
126        }
127        TaskHandle clientTaskHandled = nullptr;
128        streamInfo.baseInfo.flags = TASK_STREAM | TASK_TCP | TASK_CONNECT;
129        streamInfo.server = (char *)"127.0.0.1:10111";
130        LE_CreateStreamClient(LE_GetDefaultLoop(), &clientTaskHandled, &streamInfo);
131        if (clientTaskHandled == nullptr) {
132            return;
133        }
134    }
135    void LeTaskTest()
136    {
137        LE_StreamServerInfo info = {};
138        info.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_SERVER | TASK_TEST;
139        info.server = (char *)"/data/testpipe";
140        info.baseInfo.close = nullptr;
141        info.incommingConnect = IncomingConnect;
142        LE_CreateStreamServer(LE_GetDefaultLoop(), &serverTask_, &info);
143        if (serverTask_ == nullptr) {
144            return;
145        }
146        ((StreamServerTask *)serverTask_)->base.handleEvent(LE_GetDefaultLoop(), serverTask_, EVENT_READ);
147
148        uint64_t eventId = 0;
149        ParamStreamInfo paramStreamInfo = {};
150        paramStreamInfo.flags = PARAM_TEST_FLAGS;
151        paramStreamInfo.server = nullptr;
152        paramStreamInfo.close = nullptr;
153        paramStreamInfo.recvMessage = ProcessMessage;
154        paramStreamInfo.incomingConnect = nullptr;
155        ParamTaskPtr client = nullptr;
156        int ret = ParamStreamCreate(&client, serverTask_, &paramStreamInfo, sizeof(ParamWatcher));
157        PARAM_CHECK(ret == 0, return, "Failed to create client");
158
159        BufferHandle handle = LE_CreateBuffer(LE_GetDefaultLoop(), 1 + sizeof(eventId));
160        LE_Buffer *buffer = (LE_Buffer *)handle;
161        AddBuffer((StreamTask *)client, buffer);
162        ((StreamConnectTask *)client)->stream.base.handleEvent(LE_GetDefaultLoop(), (TaskHandle)(client), EVENT_WRITE);
163        EXPECT_NE(LE_GetSendResult(handle), 0);
164
165        ParamMessage *request = (ParamMessage *)CreateParamMessage(MSG_SET_PARAM, "name", sizeof(ParamMessage));
166        ((StreamConnectTask *)client)->recvMessage(LE_GetDefaultLoop(), reinterpret_cast<uint8_t *>(request),
167            sizeof(ParamMessage));
168
169        LE_Buffer *next = nullptr;
170        EXPECT_EQ(GetNextBuffer((StreamTask *)client, next), nullptr);
171        ParamWatcher *watcher = (ParamWatcher *)ParamGetTaskUserData(client);
172        PARAM_CHECK(watcher != nullptr, return, "Failed to get watcher");
173        OH_ListInit(&watcher->triggerHead);
174        LE_FreeBuffer(LE_GetDefaultLoop(), (TaskHandle)client, nullptr);
175        return;
176    }
177    void ProcessEventTest()
178    {
179        ProcessEvent((EventLoop *)LE_GetDefaultLoop(), 1, EVENT_READ);
180        LE_BaseInfo info = {TASK_EVENT, nullptr};
181        int testfd = 65535; // 65535 is not exist fd
182        BaseTask *task = CreateTask(LE_GetDefaultLoop(), testfd, &info, sizeof(StreamClientTask));
183        if (task != nullptr) {
184            task->handleEvent = TestHandleTaskEvent;
185            ProcessEvent((EventLoop *)LE_GetDefaultLoop(), testfd, EVENT_READ);
186        }
187    }
188    void ProcessasynEvent()
189    {
190        TaskHandle asynHandle = nullptr;
191        LE_CreateAsyncTask(LE_GetDefaultLoop(), &asynHandle, ProcessAsyncEvent);
192        if (asynHandle == nullptr) {
193            return;
194        }
195        ((AsyncEventTask *)asynHandle)->stream.base.handleEvent(LE_GetDefaultLoop(), asynHandle, EVENT_READ);
196        ((AsyncEventTask *)asynHandle)->stream.base.handleEvent(LE_GetDefaultLoop(), asynHandle, EVENT_WRITE);
197        LE_StopAsyncTask(LE_GetDefaultLoop(), asynHandle);
198    }
199    void ProcessWatcherTask()
200    {
201        WatcherHandle handle = nullptr;
202        LE_WatchInfo info = {};
203        info.fd = -1;
204        info.flags = WATCHER_ONCE;
205        info.events = EVENT_READ;
206        info.processEvent = ProcessWatchEventTest;
207        LE_StartWatcher(LE_GetDefaultLoop(), &handle, &info, nullptr);
208        if (handle == nullptr) {
209            return;
210        }
211        ((WatcherTask *)handle)->base.handleEvent(LE_GetDefaultLoop(), (TaskHandle)handle, EVENT_READ);
212        ((WatcherTask *)handle)->base.handleEvent(LE_GetDefaultLoop(), (TaskHandle)handle, 0);
213        ((WatcherTask *)handle)->base.flags = WATCHER_ONCE;
214        ((WatcherTask *)handle)->base.handleEvent(LE_GetDefaultLoop(), (TaskHandle)handle, EVENT_READ);
215        LE_RemoveWatcher(LE_GetDefaultLoop(), handle);
216    }
217    void CreateSocketTest()
218    {
219        ParamTaskPtr serverTask = nullptr;
220        LE_StreamServerInfo info = {};
221        info.baseInfo.flags = TASK_PIPE | TASK_CONNECT | TASK_TEST;
222        info.server = (char *)"/data/testpipe";
223        info.baseInfo.close = nullptr;
224        info.incommingConnect = IncomingConnect;
225        info.socketId = 1111; // 1111 is test fd
226        LE_CreateStreamServer(LE_GetDefaultLoop(), &serverTask, &info);
227        EXPECT_NE(serverTask, nullptr);
228        if (serverTask == nullptr) {
229            return;
230        }
231        ((StreamServerTask *)serverTask)->base.taskId.fd = -1;
232        OnIncomingConnect(LE_GetDefaultLoop(), serverTask);
233        LE_GetSocketFd(serverTask);
234        AcceptSocket(-1, TASK_PIPE);
235        AcceptSocket(-1, TASK_TCP);
236        AcceptSocket(-1, TASK_TEST);
237    }
238
239private:
240    ParamTaskPtr serverTask_ = nullptr;
241};
242
243HWTEST_F(LoopEventUnittest, Init_LeTaskTest_001, TestSize.Level1)
244{
245    LoopEventUnittest loopevtest = LoopEventUnittest();
246    loopevtest.LeTaskTest();
247}
248HWTEST_F(LoopEventUnittest, Init_TestRunServer_001, TestSize.Level1)
249{
250    LoopEventUnittest loopevtest = LoopEventUnittest();
251    loopevtest.ProcessEventTest();
252}
253HWTEST_F(LoopEventUnittest, Init_TestProcessasynEvent_001, TestSize.Level1)
254{
255    LoopEventUnittest loopevtest = LoopEventUnittest();
256    loopevtest.ProcessasynEvent();
257}
258HWTEST_F(LoopEventUnittest, Init_TestCreateSocketTest_001, TestSize.Level1)
259{
260    LoopEventUnittest loopevtest = LoopEventUnittest();
261    loopevtest.CreateSocketTest();
262}
263HWTEST_F(LoopEventUnittest, Init_TestProcessWatcherTask_001, TestSize.Level1)
264{
265    LoopEventUnittest loopevtest = LoopEventUnittest();
266    loopevtest.ProcessWatcherTask();
267}
268
269static LoopHandle g_loop = nullptr;
270static int g_timeCount = 0;
271static void Test_ProcessTimer(const TimerHandle taskHandle, void *context)
272{
273    g_timeCount++;
274    printf("Test_ProcessTimer %d\n", g_timeCount);
275    if (g_timeCount > 1) {
276        LE_StopLoop(g_loop);
277    }
278}
279
280HWTEST_F(LoopEventUnittest, Init_TestLoopAbnormal_001, TestSize.Level1)
281{
282    LE_StartWatcher(nullptr, nullptr, nullptr, nullptr);
283    LE_WatchInfo info = {};
284        info.fd = -1;
285        info.flags = WATCHER_ONCE;
286        info.events = EVENT_READ;
287        info.processEvent = nullptr;
288    LE_StartWatcher(LE_GetDefaultLoop(), nullptr, &info, nullptr);
289    LE_StartWatcher(LE_GetDefaultLoop(), nullptr, nullptr, nullptr);
290}
291
292HWTEST_F(LoopEventUnittest, Init_TestLoopIdle_001, TestSize.Level1)
293{
294    int ret = LE_DelayProc(LE_GetDefaultLoop(), nullptr, nullptr);
295    ASSERT_NE(ret, 0);
296    LE_DelIdle(nullptr);
297}
298
299HWTEST_F(LoopEventUnittest, Init_TestLEFreeBuffer_001, TestSize.Level1)
300{
301    uint64_t eventId = 0;
302    BufferHandle handle = LE_CreateBuffer(LE_GetDefaultLoop(), 1 + sizeof(eventId));
303    ASSERT_NE(handle, nullptr);
304    LE_FreeBuffer(LE_GetDefaultLoop(), nullptr, handle);
305}
306}  // namespace init_ut
307