• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "ffrt_inner.h"
20 #include "c/loop.h"
21 #define private public
22 #include "sync/poller.h"
23 #undef private
24 #include "util.h"
25 #include "../common.h"
26 
27 using namespace std;
28 using namespace ffrt;
29 using namespace testing;
30 #ifdef HWTEST_TESTING_EXT_ENABLE
31 using namespace testing::ext;
32 #endif
33 
34 class PollerTest : public testing::Test {
35 protected:
SetUpTestCase()36     static void SetUpTestCase()
37     {
38     }
39 
TearDownTestCase()40     static void TearDownTestCase()
41     {
42     }
43 
SetUp()44     void SetUp() override
45     {
46     }
47 
TearDown()48     void TearDown() override
49     {
50     }
51 };
52 
Testfun(void * data)53 static void Testfun(void* data)
54 {
55     int* testData = static_cast<int*>(data);
56     *testData += 1;
57     printf("%d, timeout callback\n", *testData);
58 }
59 static void (*g_cb)(void*) = Testfun;
60 
61 /*
62  * 测试用例名称:poll_once_batch_timeout
63  * 测试用例描述:PollOnce批量超时测试
64  * 预置条件    :无
65  * 操作步骤    :1、调用注册接口
66                 2、单次调用PollOnce
67  * 预期结果    :1、超时任务全部从队列中清除
68                 2、当实际超时时间很长,但是传入超时时间很短,应该按传入时间执行
69  */
70 HWTEST_F(PollerTest, poll_once_batch_timeout, TestSize.Level1)
71 {
72     Poller poller;
73     // 1、组装timeMap_
74     static int result0 = 0;
75     int* xf = &result0;
76     void* data = xf;
77     uint64_t timeout = 10;
78     uint64_t timeout1 = 11;
79     uint64_t timeout2 = 12;
80     uint64_t sleepTime = 25000;
81     poller.RegisterTimer(timeout, data, g_cb, false);
82     poller.RegisterTimer(timeout1, data, g_cb, false);
83     poller.RegisterTimer(timeout2, data, g_cb, false);
84     // 调用PollOnce,预计timerMap_为空,全部清除
85     usleep(sleepTime);
86     poller.PollOnce(1);
87     EXPECT_EQ(true, poller.DetermineEmptyMap());
88 
89     uint64_t timeout3 = 10000;
90     uint64_t timeout4 = 100;
91     int loopNum = 2;
92     poller.RegisterTimer(timeout3, data, g_cb, false);
93     TimePoint start = std::chrono::steady_clock::now();
94     for (int i = 0; i < loopNum; ++i) {
95         poller.PollOnce(timeout4);
96     }
97     TimePoint end = std::chrono::steady_clock::now();
98     int m = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
99     // 预计等待时间为100,可能有几毫秒的误差
100     EXPECT_EQ(true, m >= timeout4 && m < timeout3);
101 }
102 
103 /*
104  * 测试用例名称:poll_once_batch_timeout
105  * 测试用例描述:PollOnce批量超时测试
106  * 预置条件    :无
107  * 操作步骤    :1、调用注册接口,注册repeat为true的timer
108                 2、创建两个线程,并发PollerOnce和Unregister
109  * 预期结果    :1、任务全部从队列中清除
110  */
111 HWTEST_F(PollerTest, unregister_timer_001, TestSize.Level1)
112 {
113     Poller poller;
114     // 1、组装timeMap_
115     static int result0 = 0;
116     int* xf = &result0;
117     void* data = xf;
118     uint64_t timeout = 1;
119     uint64_t sleepTime = 2500;
120     int maxIter = 100;
121     // 2、 创建两个线程,并发PollerOnce和Unregister
122     for (int i = 0; i < maxIter; i++) {
123         int timerHandle = poller.RegisterTimer(timeout, data, g_cb, true);
124         EXPECT_FALSE(poller.timerMap_.empty());
125         auto boundPollonce = std::bind(&Poller::PollOnce, &poller, timeout);
126         auto boundUnregister = std::bind(&Poller::UnregisterTimer, &poller, timerHandle);
127         usleep(sleepTime);
128         std::thread thread1(boundPollonce);
129         std::thread thread2(boundUnregister);
130         thread1.join();
131         thread2.join();
132         EXPECT_TRUE(poller.timerMap_.empty());
133         EXPECT_TRUE(poller.executedHandle_.empty());
134         poller.timerMap_.clear();
135         poller.executedHandle_.clear();
136     }
137 }
138 
139 std::mutex g_mutexRegister;
140 std::condition_variable g_cvRegister;
141 
WaitCallback(void * data)142 void WaitCallback(void* data)
143 {
144     int* dependency = reinterpret_cast<int*>(data);
145     while (*dependency != 1) {
146         std::this_thread::yield();
147     }
148 }
149 
EmptyCallback(void * data)150 void EmptyCallback(void* data) {}
151 
152 /*
153  * 测试用例名称:multi_timer_dependency
154  * 测试用例描述:poller批量超时回调依赖测试
155  * 预置条件    :构造三个超时时间相同的timer,回调A依赖回调B执行完成,回调B依赖timer C取消成功,三者并发
156  * 操作步骤    :1、调用PollOnce接口
157  * 预期结果    :1、三个回调执行完成,没有卡死现象
158  */
159 HWTEST_F(PollerTest, multi_timer_dependency, TestSize.Level1)
160 {
161     int dependency = 0;
__anon52d4ac2d0102null162     ffrt::task_handle handle = ffrt::submit_h([&] {
163         std::unique_lock lk(g_mutexRegister);
164         g_cvRegister.wait(lk);
165         dependency = 1;
166     });
167 
168     TimePoint timeout = std::chrono::steady_clock::now() + std::chrono::milliseconds(100);
169     TimerDataWithCb data(&dependency, WaitCallback, nullptr, false, 100);
170     data.handle = 0;
171 
172     Poller poller;
173     poller.timerMap_.emplace(timeout, data);
174 
175     data.handle++;
176     data.cb = EmptyCallback;
177     poller.timerMap_.emplace(timeout, data);
178 
__anon52d4ac2d0202null179     std::thread th1([&] { poller.PollOnce(-1); });
__anon52d4ac2d0302null180     std::thread th2([&] {
181         usleep(100 * 1000);
182         poller.UnregisterTimer(1);
183         g_cvRegister.notify_all();
184     });
185 
186     th1.join();
187     th2.join();
188     ffrt::wait({handle});
189 }
190 
191 /*
192  * 测试用例名称:multi_timer_dependency_unregister_self
193  * 测试用例描述:poller批量超时回调,解注册自身依赖测试
194  * 预置条件    :构造两个超时时间相同的timer,回调A依赖回调B执行完成,回调B依赖另一个线程的timer A取消成功,三者并发
195  * 操作步骤    :调用PollOnce接口
196  * 预期结果    :三个回调执行完成,没有卡死现象
197  */
198 HWTEST_F(PollerTest, multi_timer_dependency_unregister_self, TestSize.Level1)
199 {
200     int dependency = 0;
201 
202     TimePoint timeout = std::chrono::steady_clock::now() + std::chrono::milliseconds(100);
203     TimerDataWithCb data(&dependency, WaitCallback, nullptr, false, 100);
204     data.handle = 0;
205 
206     Poller poller;
207     poller.timerMap_.emplace(timeout, data);
208 
209     data.handle++;
210     data.cb = EmptyCallback;
211     poller.timerMap_.emplace(timeout, data);
212 
__anon52d4ac2d0402null213     ffrt::task_handle handle = ffrt::submit_h([&] {
214         std::unique_lock lk(g_mutexRegister);
215         g_cvRegister.wait(lk);
216         poller.IsTimerReady();
217         dependency = 1;
218     });
219 
__anon52d4ac2d0502null220     std::thread th1([&] { poller.PollOnce(-1); });
__anon52d4ac2d0602null221     std::thread th2([&] {
222         usleep(100 * 1000);
223         g_cvRegister.notify_all();
224         poller.UnregisterTimer(0);
225     });
226 
227     th1.join();
228     th2.join();
229     ffrt::wait({handle});
230 }
231 
232 /*
233  * 测试用例名称 : fetch_cached_event_unmask DoTaskFdAdd
234  * 测试用例描述 : 遍历本地events缓存,并提出缓存event
235  * 预置条件     : 无
236  * 操作步骤     :
237  * 预期结果     :
238  */
239 HWTEST_F(PollerTest, TestCacheDelFd001, TestSize.Level1)
240 {
241     Poller poller;
242     CPUEUTask* currTask = static_cast<CPUEUTask*>(malloc(sizeof(CPUEUTask)));
243     int fd = 1001;
244     int fd1 = 1002;
245     poller.CacheDelFd(fd, currTask);
246     poller.CacheDelFd(fd1, currTask);
247     std::unique_ptr<struct WakeDataWithCb> maskWakeData = std::make_unique<WakeDataWithCb>(fd, nullptr,
248         nullptr, currTask);
249     std::unique_ptr<struct WakeDataWithCb> maskWakeData1 = std::make_unique<WakeDataWithCb>(fd1, nullptr,
250         nullptr, currTask);
251     poller.CacheMaskWakeData(currTask, maskWakeData);
252     poller.CacheMaskWakeData(currTask, maskWakeData1);
253 
254     EXPECT_EQ(2, poller.m_delFdCacheMap.size());
255     EXPECT_EQ(1, poller.m_maskWakeDataWithCbMap.size());
256     EXPECT_EQ(2, poller.m_maskWakeDataWithCbMap[currTask].size());
257 
258     poller.ClearMaskWakeDataWithCbCacheWithFd(currTask, fd);
259     EXPECT_EQ(2, poller.m_delFdCacheMap.size());
260     EXPECT_EQ(1, poller.m_maskWakeDataWithCbMap.size());
261     EXPECT_EQ(1, poller.m_maskWakeDataWithCbMap[currTask].size());
262 
263     poller.ClearMaskWakeDataWithCbCacheWithFd(currTask, fd1);
264     EXPECT_EQ(2, poller.m_delFdCacheMap.size());
265     EXPECT_EQ(0, poller.m_maskWakeDataWithCbMap.size());
266     EXPECT_EQ(0, poller.m_maskWakeDataWithCbMap[currTask].size());
267 
268     free(currTask);
269 }
270 
271 /*
272  * 测试用例名称 : fetch_cached_event_unmask DoTaskFdAdd
273  * 测试用例描述 : 遍历本地events缓存,并提出缓存event
274  * 预置条件     : 无
275  * 操作步骤     :
276  * 预期结果     :
277  */
278 HWTEST_F(PollerTest, TestCacheDelFd002, TestSize.Level1)
279 {
280     Poller poller;
281     CPUEUTask* currTask = static_cast<CPUEUTask*>(malloc(sizeof(CPUEUTask)));
282     int fd = 1001;
283     int fd1 = 1002;
284     poller.m_delFdCacheMap.emplace(fd, currTask);
285     poller.m_delFdCacheMap.emplace(fd1, currTask);
286     std::unique_ptr<struct WakeDataWithCb> maskWakeData = std::make_unique<WakeDataWithCb>(fd, nullptr,
287         nullptr, currTask);
288     std::unique_ptr<struct WakeDataWithCb> maskWakeData1 = std::make_unique<WakeDataWithCb>(fd1, nullptr,
289         nullptr, currTask);
290     poller.m_maskWakeDataWithCbMap[currTask].emplace_back(std::move(maskWakeData));
291     poller.m_maskWakeDataWithCbMap[currTask].emplace_back(std::move(maskWakeData1));
292 
293     EXPECT_EQ(2, poller.m_delFdCacheMap.size());
294     EXPECT_EQ(1, poller.m_maskWakeDataWithCbMap.size());
295     EXPECT_EQ(2, poller.m_maskWakeDataWithCbMap[currTask].size());
296 
297     poller.ClearMaskWakeDataWithCbCache(currTask);
298 
299     EXPECT_EQ(0, poller.m_delFdCacheMap.size());
300     EXPECT_EQ(0, poller.m_maskWakeDataWithCbMap.size());
301     EXPECT_EQ(0, poller.m_maskWakeDataWithCbMap[currTask].size());
302 
303     free(currTask);
304 }
305 
306 /*
307  * 测试用例名称 : fetch_cached_event_unmask DoTaskFdAdd
308  * 测试用例描述 : 遍历本地events缓存,并提出缓存event
309  * 预置条件     : 无
310  * 操作步骤     :
311  * 预期结果     :
312  */
313 HWTEST_F(PollerTest, TestCacheDelFd003, TestSize.Level1)
314 {
315     Poller poller;
316     CPUEUTask* currTask = static_cast<CPUEUTask*>(malloc(sizeof(CPUEUTask)));
317     int fd = 1001;
318     int fd1 = 1002;
319     poller.m_delFdCacheMap.emplace(fd, currTask);
320     poller.m_delFdCacheMap.emplace(fd1, currTask);
321     std::unique_ptr<struct WakeDataWithCb> maskWakeData = std::make_unique<WakeDataWithCb>(fd, nullptr,
322         nullptr, currTask);
323     std::unique_ptr<struct WakeDataWithCb> maskWakeData1 = std::make_unique<WakeDataWithCb>(fd1, nullptr,
324         nullptr, currTask);
325     poller.m_maskWakeDataWithCbMap[currTask].emplace_back(std::move(maskWakeData));
326     poller.m_maskWakeDataWithCbMap[currTask].emplace_back(std::move(maskWakeData1));
327 
328     EXPECT_EQ(2, poller.m_delFdCacheMap.size());
329     EXPECT_EQ(1, poller.m_maskWakeDataWithCbMap.size());
330     EXPECT_EQ(2, poller.m_maskWakeDataWithCbMap[currTask].size());
331 
332     poller.ClearDelFdCache(fd);
333     EXPECT_EQ(1, poller.m_delFdCacheMap.size());
334     EXPECT_EQ(1, poller.m_maskWakeDataWithCbMap.size());
335     EXPECT_EQ(1, poller.m_maskWakeDataWithCbMap[currTask].size());
336 
337     poller.ClearDelFdCache(fd1);
338     EXPECT_EQ(0, poller.m_delFdCacheMap.size());
339     EXPECT_EQ(0, poller.m_maskWakeDataWithCbMap.size());
340     EXPECT_EQ(0, poller.m_maskWakeDataWithCbMap[currTask].size());
341 
342     free(currTask);
343 }