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