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