1 /*
2  * Copyright (c) 2023 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 <thread>
17 #include <chrono>
18 #include <gtest/gtest.h>
19 #ifndef WITH_NO_MOCKER
20 #include <mockcpp/mockcpp.hpp>
21 #endif
22 #include <sys/epoll.h>
23 #include <sys/eventfd.h>
24 #include "ffrt_inner.h"
25 #include "c/loop.h"
26 #include "util/event_handler_adapter.h"
27 #include "../common.h"
28 
29 using namespace std;
30 using namespace ffrt;
31 using namespace testing;
32 #ifdef HWTEST_TESTING_EXT_ENABLE
33 using namespace testing::ext;
34 #endif
35 
36 class LoopTest : public testing::Test {
37 protected:
SetUpTestCase()38     static void SetUpTestCase()
39     {
40     }
41 
TearDownTestCase()42     static void TearDownTestCase()
43     {
44     }
45 
SetUp()46     virtual void SetUp()
47     {
48     }
49 
TearDown()50     virtual void TearDown()
51     {
52     }
53 };
54 
ThreadFunc(void* p)55 void* ThreadFunc(void* p)
56 {
57     int ret = ffrt_loop_run(p);
58     EXPECT_EQ(ret, 0);
59     return nullptr;
60 }
61 
62 /*
63  * 测试用例名称:loop_null_queue_create_fail
64  * 测试用例描述:非法队列创建loop失败
65  * 预置条件    :无
66  * 操作步骤    :1、创建loop失败
67  *
68  * 预期结果    :创建失败
69  */
HWTEST_F(LoopTest, loop_null_queue_create_fail, TestSize.Level1)70 HWTEST_F(LoopTest, loop_null_queue_create_fail, TestSize.Level1)
71 {
72     auto loop = ffrt_loop_create(nullptr);
73     EXPECT_EQ(loop, nullptr);
74 }
75 
76 /*
77  * 测试用例名称:loop_serial_queue_create_succ
78  * 测试用例描述:serial队列创建loop失败
79  * 预置条件    :1、调用串行队列创建接口创建serial队列
80  * 操作步骤    :1、创建loop
81  *
82  * 预期结果    :创建失败
83  */
HWTEST_F(LoopTest, loop_serial_queue_create_succ, TestSize.Level1)84 HWTEST_F(LoopTest, loop_serial_queue_create_succ, TestSize.Level1)
85 {
86     ffrt_queue_attr_t queue_attr;
87     (void)ffrt_queue_attr_init(&queue_attr);
88     ffrt_queue_t queue_handle = ffrt_queue_create(ffrt_queue_serial, "test_queue", &queue_attr);
89 
90     auto loop = ffrt_loop_create(queue_handle);
91     EXPECT_EQ(loop, nullptr);
92 
93     ffrt_queue_attr_destroy(&queue_attr);
94     ffrt_queue_destroy(queue_handle);
95 }
96 
97 /*
98  * 测试用例名称:loop_concurrent_queue_create_succ
99  * 测试用例描述:无任务concurrent队列创建loop成功
100  * 预置条件    :1、调用串行队列创建接口创建concurrent队列
101  * 操作步骤    :1、创建loop
102  *
103  * 预期结果    :执行成功
104  */
HWTEST_F(LoopTest, loop_concurrent_queue_create_succ, TestSize.Level1)105 HWTEST_F(LoopTest, loop_concurrent_queue_create_succ, TestSize.Level1)
106 {
107     ffrt_queue_attr_t queue_attr;
108     (void)ffrt_queue_attr_init(&queue_attr);
109     ffrt_queue_t queue_handle = ffrt_queue_create(ffrt_queue_concurrent, "test_queue", &queue_attr);
110 
111     auto loop = ffrt_loop_create(queue_handle);
112     EXPECT_NE(loop, nullptr);
113 
114     int ret = ffrt_loop_destroy(loop);
115     EXPECT_EQ(ret, 0);
116 
117     ffrt_queue_attr_destroy(&queue_attr);
118     ffrt_queue_destroy(queue_handle);
119 }
120 
121 /*
122  * 测试用例名称:loop_concurrent_queue_create_fail
123  * 测试用例描述:有任务队列创建loop失败
124  * 预置条件    :1、调用串行队列创建接口创建concurrent队列
125  *              2、创建loop前向队列提交任务
126  * 操作步骤    :1、创建loop
127  *
128  * 预期结果    :创建失败
129  */
HWTEST_F(LoopTest, loop_concurrent_queue_create_fail, TestSize.Level1)130 HWTEST_F(LoopTest, loop_concurrent_queue_create_fail, TestSize.Level1)
131 {
132     ffrt_queue_attr_t queue_attr;
133     (void)ffrt_queue_attr_init(&queue_attr);
134     ffrt_queue_t queue_handle = ffrt_queue_create(ffrt_queue_concurrent, "test_queue", &queue_attr);
135 
136     int result1 = 0;
137     std::function<void()>&& basicFunc1 = [&result1]() { result1 += 10; };
138     ffrt_queue_submit(queue_handle, create_function_wrapper(basicFunc1, ffrt_function_kind_queue), nullptr);
139 
140     auto loop = ffrt_loop_create(queue_handle);
141     EXPECT_EQ(loop, nullptr);
142 
143     ffrt_queue_attr_destroy(&queue_attr);
144     ffrt_queue_destroy(queue_handle);
145 }
146 
147 /*
148  * 测试用例名称:loop_run_fail
149  * 测试用例描述:非法loop run失败
150  * 操作步骤    :1、执行loop run
151  *
152  * 预期结果    :执行失败
153  */
HWTEST_F(LoopTest, loop_run_fail, TestSize.Level1)154 HWTEST_F(LoopTest, loop_run_fail, TestSize.Level1)
155 {
156     int ret = ffrt_loop_run(nullptr);
157     EXPECT_NE(ret, 0);
158 }
159 
160 /*
161  * 测试用例名称:loop_destroy_fail
162  * 测试用例描述:非法loop destroy失败
163  * 操作步骤    :1、执行loop run
164  *
165  * 预期结果    :执行失败
166  */
HWTEST_F(LoopTest, loop_destroy_fail, TestSize.Level1)167 HWTEST_F(LoopTest, loop_destroy_fail, TestSize.Level1)
168 {
169     int ret = ffrt_loop_destroy(nullptr);
170     EXPECT_NE(ret, 0);
171 }
172 
173 /*
174  * 测试用例名称:loop_run_destroy_success
175  * 测试用例描述:正常loop run成功、destroy
176  * 预置条件    :1、调用串行队列创建接口创建concurrent队列
177  *              2、用队列创建loop
178  * 操作步骤    :1、启动线程执行loop run
179  *              2、销毁loop成功
180  * 预期结果    :执行成功
181  */
HWTEST_F(LoopTest, loop_run_destroy_success, TestSize.Level1)182 HWTEST_F(LoopTest, loop_run_destroy_success, TestSize.Level1)
183 {
184     const uint64_t sleepTime = 250000;
185     ffrt_queue_attr_t queue_attr;
186     (void)ffrt_queue_attr_init(&queue_attr);
187     ffrt_queue_t queue_handle = ffrt_queue_create(ffrt_queue_concurrent, "test_queue", &queue_attr);
188 
189     auto loop = ffrt_loop_create(queue_handle);
190     EXPECT_NE(loop, nullptr);
191 
192     pthread_t thread;
193     pthread_create(&thread, 0, ThreadFunc, loop);
194 
195     ffrt_loop_stop(loop);
196     usleep(sleepTime);
197     int ret = ffrt_loop_destroy(loop);
198     EXPECT_EQ(ret, 0);
199 
200     ffrt_queue_attr_destroy(&queue_attr);
201     ffrt_queue_destroy(queue_handle);
202 }
203 
204 struct TestData {
205     int fd;
206     uint64_t expected;
207 };
208 
TestCallBack(void* token, uint32_t event)209 static void TestCallBack(void* token, uint32_t event)
210 {
211     struct TestData* testData = reinterpret_cast<TestData*>(token);
212     uint64_t value = 0;
213     ssize_t n = read(testData->fd, &value, sizeof(uint64_t));
214     EXPECT_EQ(n, sizeof(value));
215     EXPECT_EQ(value, testData->expected);
216 }
217 
AddFdListener(void* handler, uint32_t fd, uint32_t event, void* data, ffrt_poller_cb cb)218 int AddFdListener(void* handler, uint32_t fd, uint32_t event, void* data, ffrt_poller_cb cb)
219 {
220     return 0;
221 }
222 
RemoveFdListener(void* handler, uint32_t fd)223 int RemoveFdListener(void* handler, uint32_t fd)
224 {
225     return 0;
226 }
227 
HWTEST_F(LoopTest, ffrt_add_and_remove_fd, TestSize.Level1)228 HWTEST_F(LoopTest, ffrt_add_and_remove_fd, TestSize.Level1)
229 {
230     ffrt_queue_attr_t queue_attr;
231     (void)ffrt_queue_attr_init(&queue_attr); // 初始化属性,必须
232     ffrt_queue_t queue_handle = ffrt_queue_create(
233         static_cast<ffrt_queue_type_t>(ffrt_queue_eventhandler_interactive), "test_queue", &queue_attr);
234 #ifndef WITH_NO_MOCKER
235     MOCKER(ffrt_get_main_queue).stubs().will(returnValue(queue_handle));
236 #endif
237 
238     EventHandlerAdapter::Instance()->AddFdListener = AddFdListener;
239     EventHandlerAdapter::Instance()->RemoveFdListener = RemoveFdListener;
240 
241     ffrt_queue_t mainQueue = ffrt_get_main_queue();
242     auto loop = ffrt_loop_create(mainQueue);
243     EXPECT_TRUE(loop != nullptr);
244     ffrt_loop_run(loop);
245     int ret = 0;
246     int testFd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
247     uint64_t expected = 0xabacadae;
248     struct TestData testData {.fd = testFd, .expected = expected};
249     ret = ffrt_loop_epoll_ctl(loop, EPOLL_CTL_ADD, testFd, EPOLLIN, (void*)(&testData), TestCallBack);
250     EXPECT_EQ(ret, 0);
251     ssize_t n = write(testFd, &expected, sizeof(uint64_t));
252     EXPECT_EQ(n, sizeof(uint64_t));
253     usleep(25000);
254 
255     ret = ffrt_loop_epoll_ctl(loop, EPOLL_CTL_DEL, testFd, 0, nullptr, nullptr);
256     EXPECT_EQ(ret, 0);
257 
258     ffrt_loop_stop(loop);
259     ffrt_loop_destroy(loop);
260 
261 #ifndef WITH_NO_MOCKER
262     GlobalMockObject::reset();
263     GlobalMockObject::verify();
264 #endif
265 }
266