• 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 "priority_queue.h"
17 #include <chrono>
18 #include <functional>
19 #include <gtest/gtest.h>
20 #include <memory>
21 #include <mutex>
22 #include <queue>
23 #include <set>
24 #include <shared_mutex>
25 #include <string>
26 #include <thread>
27 
28 namespace OHOS::Test {
29 using namespace testing::ext;
30 using namespace OHOS;
31 using TaskId = uint64_t;
32 using Task = std::function<void()>;
33 using Duration = std::chrono::steady_clock::duration;
34 using Time = std::chrono::steady_clock::time_point;
35 static constexpr Duration INVALID_INTERVAL = std::chrono::milliseconds(0);
36 static constexpr uint64_t UNLIMITED_TIMES = std::numeric_limits<uint64_t>::max();
37 static constexpr TaskId INVALID_TASK_ID = static_cast<uint64_t>(0);
38 static constexpr uint32_t SHORT_INTERVAL = 100; // ms
39 class PriorityQueueTest : public testing::Test {
40 public:
41     struct TestTask {
__anon1573afca0102OHOS::Test::PriorityQueueTest::TestTask42         std::function<void()> exec = []() {};
43         Duration interval = INVALID_INTERVAL;
44         uint64_t times = UNLIMITED_TIMES;
45         TaskId taskId = INVALID_TASK_ID;
46         TestTask() = default;
47 
ValidOHOS::Test::PriorityQueueTest::TestTask48         bool Valid() const
49         {
50             return taskId != INVALID_TASK_ID;
51         }
52     };
53     static void SetUpTestCase(void);
54     static void TearDownTestCase(void);
55     void SetUp();
56     void TearDown();
57 
58 protected:
59     static PriorityQueue<PriorityQueueTest::TestTask, Time, TaskId> priorityqueue_;
60     static PriorityQueue<PriorityQueueTest::TestTask, Time, TaskId>::PQMatrix pqMatrix;
61 };
62 using TestTask = PriorityQueueTest::TestTask;
63 PriorityQueue<TestTask, Time, TaskId> PriorityQueueTest::priorityqueue_ =
64     PriorityQueue<TestTask, Time, TaskId>(TestTask());
65 PriorityQueue<TestTask, Time, TaskId>::PQMatrix PriorityQueueTest::pqMatrix =
66     PriorityQueue<TestTask, Time, TaskId>::PQMatrix(TestTask(), INVALID_TASK_ID);
67 
SetUpTestCase(void)68 void PriorityQueueTest::SetUpTestCase(void) { }
69 
TearDownTestCase(void)70 void PriorityQueueTest::TearDownTestCase(void) { }
71 
SetUp(void)72 void PriorityQueueTest::SetUp(void) { }
73 
TearDown(void)74 void PriorityQueueTest::TearDown(void)
75 {
76     priorityqueue_.Clean();
77 }
78 
79 /**
80  * @tc.name: PQMatrix_001
81  * @tc.desc: test the PQMatrix(_Tsk task, _Tid id) function.
82  * @tc.type: FUNC
83  * @tc.require:
84  * @tc.author: suoqilong
85  */
86 HWTEST_F(PriorityQueueTest, PQMatrix_001, TestSize.Level1)
87 {
88     TestTask testTask;
89     auto id = testTask.taskId;
90     EXPECT_EQ(pqMatrix.id_, id);
91 }
92 
93 /**
94  * @tc.name: PushPopSize_001
95  * @tc.desc: Invalid test task.
96  * @tc.type: FUNC
97  * @tc.require:
98  * @tc.author: suoqilong
99  */
100 HWTEST_F(PriorityQueueTest, PushPopSize_001, TestSize.Level1)
101 {
102     TestTask testTask;
103     auto id = testTask.taskId;
104     auto timely = std::chrono::seconds(0);
105     auto ret = priorityqueue_.Push(testTask, id, std::chrono::steady_clock::now() + timely);
106     EXPECT_EQ(ret, false);
107     auto retSize = priorityqueue_.Size();
108     EXPECT_EQ(retSize, 0u);
109     auto retPop = priorityqueue_.Pop();
110     EXPECT_EQ(retPop.taskId, INVALID_TASK_ID);
111     retSize = priorityqueue_.Size();
112     EXPECT_EQ(retSize, 0u);
113 }
114 
115 /**
116  * @tc.name: PushPopSize_002
117  * @tc.desc: Testing a single task.
118  * @tc.type: FUNC
119  * @tc.require:
120  * @tc.author: suoqilong
121  */
122 HWTEST_F(PriorityQueueTest, PushPopSize_002, TestSize.Level1)
123 {
124     TestTask testTask;
125     auto id = ++(testTask.taskId);
126     auto timely = std::chrono::seconds(0);
127     auto ret = priorityqueue_.Push(testTask, id, std::chrono::steady_clock::now() + timely);
128     EXPECT_EQ(ret, true);
129     auto retSize = priorityqueue_.Size();
130     EXPECT_EQ(retSize, 1u);
131     auto retPop = priorityqueue_.Pop();
132     EXPECT_EQ(retPop.taskId, id);
133     retSize = priorityqueue_.Size();
134     EXPECT_EQ(retSize, 0u);
135 }
136 
137 /**
138  * @tc.name: PushPopSize_003
139  * @tc.desc: Testing multiple tasks.
140  * @tc.type: FUNC
141  * @tc.require:
142  * @tc.author: suoqilong
143  */
144 HWTEST_F(PriorityQueueTest, PushPopSize_003, TestSize.Level1)
145 {
146     TestTask testTask;
147     for (int i = 0; i < 10; ++i) {
148         auto timely = std::chrono::seconds(0);
149         auto id = ++(testTask.taskId);
150         auto ret = priorityqueue_.Push(testTask, id, std::chrono::steady_clock::now() + timely);
151         EXPECT_EQ(ret, true);
152     }
153     auto retSize = priorityqueue_.Size();
154     EXPECT_EQ(retSize, 10u);
155     auto retPop = priorityqueue_.Pop();
156     EXPECT_EQ(retPop.taskId, 1);
157     retSize = priorityqueue_.Size();
158     EXPECT_EQ(retSize, 9u);
159 }
160 
161 /**
162  * @tc.name: PushPopSize_004
163  * @tc.desc: Test the delay task.
164  * @tc.type: FUNC
165  * @tc.require:
166  * @tc.author: suoqilong
167  */
168 HWTEST_F(PriorityQueueTest, PushPopSize_004, TestSize.Level1)
169 {
170     TestTask testTask;
171     testTask.times = 1;
172     for (int i = 0; i < 5; ++i) {
173         auto delay = std::chrono::milliseconds(SHORT_INTERVAL);
174         auto id = ++(testTask.taskId);
175         auto ret = priorityqueue_.Push(testTask, id, std::chrono::steady_clock::now() + delay);
176         EXPECT_EQ(ret, true);
177     }
178     for (int i = 0; i < 5; ++i) {
179         auto timely = std::chrono::seconds(0);
180         auto id = ++(testTask.taskId);
181         auto ret = priorityqueue_.Push(testTask, id, std::chrono::steady_clock::now() + timely);
182         EXPECT_EQ(ret, true);
183     }
184     auto retSize = priorityqueue_.Size();
185     EXPECT_EQ(retSize, 10u);
186     for (int i = 0; i < 5; ++i) {
187         auto retPop = priorityqueue_.Pop();
188         EXPECT_EQ(retPop.taskId, i + 6);
189     }
190     for (int i = 0; i < 5; ++i) {
191         auto retPop = priorityqueue_.Pop();
192         EXPECT_EQ(retPop.taskId, i + 1);
193     }
194     retSize = priorityqueue_.Size();
195     EXPECT_EQ(retSize, 0u);
196 }
197 
198 /**
199  * @tc.name: PushPopSize_005
200  * @tc.desc: Test the delay task.
201  * @tc.type: FUNC
202  * @tc.require:
203  * @tc.author: suoqilong
204  */
205 HWTEST_F(PriorityQueueTest, PushPopSize_005, TestSize.Level1)
206 {
207     TestTask testTask;
208     testTask.times = 1;
209     auto delay = std::chrono::milliseconds(SHORT_INTERVAL);
210     auto id = ++(testTask.taskId);
211     auto ret = priorityqueue_.Push(testTask, id, std::chrono::steady_clock::now() + delay);
212     EXPECT_EQ(ret, true);
213     auto retSize = priorityqueue_.Size();
214     EXPECT_EQ(retSize, 1u);
215     auto delayA = std::chrono::steady_clock::now();
216     auto retPop = priorityqueue_.Pop();
217     EXPECT_EQ(retPop.taskId, id);
218     auto delayB = std::chrono::steady_clock::now();
219     auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(delayB - delayA).count();
220     auto delayms = std::chrono::duration_cast<std::chrono::milliseconds>(delay).count();
221     EXPECT_LT(diff, delayms * 1.5);
222     retSize = priorityqueue_.Size();
223     EXPECT_EQ(retSize, 0u);
224 }
225 
226 /**
227  * @tc.name: Find_001
228  * @tc.desc: Invalid test task.
229  * @tc.type: FUNC
230  * @tc.require:
231  * @tc.author: suoqilong
232  */
233 HWTEST_F(PriorityQueueTest, Find_001, TestSize.Level1)
234 {
235     TestTask testTask;
236     auto id = testTask.taskId;
237     auto timely = std::chrono::seconds(0);
238     auto ret = priorityqueue_.Push(testTask, id, std::chrono::steady_clock::now() + timely);
239     EXPECT_EQ(ret, false);
240     auto retFind = priorityqueue_.Find(id);
241     EXPECT_EQ(retFind.taskId, INVALID_TASK_ID);
242 }
243 
244 /**
245  * @tc.name: Find_002
246  * @tc.desc: test the priority_queue _Tsk Find(_Tid id) function.
247  * @tc.type: FUNC
248  * @tc.require:
249  * @tc.author: suoqilong
250  */
251 HWTEST_F(PriorityQueueTest, Find_002, TestSize.Level1)
252 {
253     TestTask testTask;
254     for (int i = 0; i < 10; ++i) {
255         auto timely = std::chrono::seconds(0);
256         auto id = ++(testTask.taskId);
257         auto ret = priorityqueue_.Push(testTask, id, std::chrono::steady_clock::now() + timely);
258         EXPECT_EQ(ret, true);
259     }
260     auto retSize = priorityqueue_.Size();
261     EXPECT_EQ(retSize, 10u);
262     auto retFind = priorityqueue_.Find(5);
263     EXPECT_EQ(retFind.taskId, 5);
264     retFind = priorityqueue_.Find(20);
265     EXPECT_EQ(retFind.taskId, INVALID_TASK_ID);
266 }
267 
268 /**
269  * @tc.name: Update_001
270  * @tc.desc: Invalid test task.
271  * @tc.type: FUNC
272  * @tc.require:
273  * @tc.author: suoqilong
274  */
275 HWTEST_F(PriorityQueueTest, Update_001, TestSize.Level1)
276 {
__anon1573afca0202(TestTask &) 277     auto updater = [](TestTask &) {
278         return std::pair { false, Time() };
279     };
280     auto delay = std::chrono::milliseconds(SHORT_INTERVAL);
281     TestTask testTask;
282     testTask.times = 3;
283     auto id = testTask.taskId;
284     auto ret = priorityqueue_.Push(testTask, id, std::chrono::steady_clock::now() + delay);
285     EXPECT_EQ(ret, false);
286     auto retUpdate = priorityqueue_.Update(id, updater);
287     EXPECT_EQ(retUpdate, false);
288 }
289 
290 /**
291  * @tc.name: Update_002
292  * @tc.desc: Test normal tasks.
293  * @tc.type: FUNC
294  * @tc.require:
295  * @tc.author: suoqilong
296  */
297 HWTEST_F(PriorityQueueTest, Update_002, TestSize.Level1)
298 {
__anon1573afca0302(TestTask &) 299     auto updater = [](TestTask &) {
300         return std::pair { false, Time() };
301     };
302     auto delay = std::chrono::milliseconds(SHORT_INTERVAL);
303     TestTask testTask;
304     testTask.times = 3;
305     auto id = ++(testTask.taskId);
306     auto ret = priorityqueue_.Push(testTask, id, std::chrono::steady_clock::now() + delay);
307     EXPECT_EQ(ret, true);
308     auto retUpdate = priorityqueue_.Update(id, updater);
309     EXPECT_EQ(retUpdate, true);
310 }
311 
312 /**
313  * @tc.name: Update_003
314  * @tc.desc: Test the running tasks.
315  * @tc.type: FUNC
316  * @tc.require:
317  * @tc.author: suoqilong
318  */
319 HWTEST_F(PriorityQueueTest, Update_003, TestSize.Level1)
320 {
__anon1573afca0402(TestTask &) 321     auto updater = [](TestTask &) {
322         return std::pair { false, Time() };
323     };
324     auto delay = std::chrono::milliseconds(SHORT_INTERVAL);
325     TestTask testTask;
326     testTask.times = 3;
327     auto id = ++(testTask.taskId);
328     auto ret = priorityqueue_.Push(testTask, id, std::chrono::steady_clock::now() + delay);
329     EXPECT_EQ(ret, true);
330     auto retPop = priorityqueue_.Pop();
331     auto retUpdate = priorityqueue_.Update(retPop.taskId, updater);
332     EXPECT_EQ(retUpdate, false);
333 }
334 
335 /**
336  * @tc.name: Update_004
337  * @tc.desc: Test the running tasks.
338  * @tc.type: FUNC
339  * @tc.require:
340  * @tc.author: suoqilong
341  */
342 HWTEST_F(PriorityQueueTest, Update_004, TestSize.Level1)
343 {
__anon1573afca0502(TestTask &) 344     auto updater = [](TestTask &) {
345         return std::pair { true, Time() };
346     };
347     auto delay = std::chrono::milliseconds(SHORT_INTERVAL);
348     TestTask testTask;
349     testTask.times = 3;
350     auto id = ++(testTask.taskId);
351     auto ret = priorityqueue_.Push(testTask, id, std::chrono::steady_clock::now() + delay);
352     EXPECT_EQ(ret, true);
353     auto retPop = priorityqueue_.Pop();
354     auto retUpdate = priorityqueue_.Update(retPop.taskId, updater);
355     EXPECT_EQ(retUpdate, true);
356 }
357 
358 /**
359  * @tc.name: Update_005
360  * @tc.desc: Test the running and finish tasks.
361  * @tc.type: FUNC
362  * @tc.require:
363  * @tc.author: suoqilong
364  */
365 HWTEST_F(PriorityQueueTest, Update_005, TestSize.Level1)
366 {
__anon1573afca0602(TestTask &) 367     auto updater = [](TestTask &) {
368         return std::pair { false, Time() };
369     };
370     auto delay = std::chrono::milliseconds(SHORT_INTERVAL);
371     TestTask testTask;
372     testTask.times = 3;
373     auto id = ++(testTask.taskId);
374     auto ret = priorityqueue_.Push(testTask, id, std::chrono::steady_clock::now() + delay);
375     EXPECT_EQ(ret, true);
376     auto retPop = priorityqueue_.Pop();
377     priorityqueue_.Finish(id);
378     auto retUpdate = priorityqueue_.Update(retPop.taskId, updater);
379     EXPECT_EQ(retUpdate, false);
380 }
381 
382 /**
383  * @tc.name: Update_006
384  * @tc.desc: Test the running and finish tasks.
385  * @tc.type: FUNC
386  * @tc.require:
387  * @tc.author: suoqilong
388  */
389 HWTEST_F(PriorityQueueTest, Update_006, TestSize.Level1)
390 {
__anon1573afca0702(TestTask &) 391     auto updater = [](TestTask &) {
392         return std::pair { true, Time() };
393     };
394     auto delay = std::chrono::milliseconds(SHORT_INTERVAL);
395     TestTask testTask;
396     testTask.times = 3;
397     auto id = ++(testTask.taskId);
398     auto ret = priorityqueue_.Push(testTask, id, std::chrono::steady_clock::now() + delay);
399     EXPECT_EQ(ret, true);
400     auto retPop = priorityqueue_.Pop();
401     priorityqueue_.Finish(id);
402     auto retUpdate = priorityqueue_.Update(retPop.taskId, updater);
403     EXPECT_EQ(retUpdate, false);
404 }
405 
406 /**
407  * @tc.name: Remove_001
408  * @tc.desc: Invalid test task.
409  * @tc.type: FUNC
410  * @tc.require:
411  * @tc.author: suoqilong
412  */
413 HWTEST_F(PriorityQueueTest, Remove_001, TestSize.Level1)
414 {
415     TestTask testTask;
416     auto id = testTask.taskId;
417     auto delay = std::chrono::milliseconds(SHORT_INTERVAL);
418     auto ret = priorityqueue_.Push(testTask, id, std::chrono::steady_clock::now() + delay);
419     EXPECT_EQ(ret, false);
420     auto retRemove = priorityqueue_.Remove(id, false);
421     EXPECT_EQ(retRemove, false);
422     auto retSize = priorityqueue_.Size();
423     EXPECT_EQ(retSize, 0u);
424 }
425 
426 /**
427  * @tc.name: Remove_002
428  * @tc.desc: Single and don't wait test task.
429  * @tc.type: FUNC
430  * @tc.require:
431  * @tc.author: suoqilong
432  */
433 HWTEST_F(PriorityQueueTest, Remove_002, TestSize.Level1)
434 {
435     TestTask testTask;
436     auto id = ++(testTask.taskId);
437     auto delay = std::chrono::milliseconds(SHORT_INTERVAL);
438     auto ret = priorityqueue_.Push(testTask, id, std::chrono::steady_clock::now() + delay);
439     EXPECT_EQ(ret, true);
440     auto retSize = priorityqueue_.Size();
441     EXPECT_EQ(retSize, 1u);
442     auto retRemove = priorityqueue_.Remove(id, false);
443     EXPECT_EQ(retRemove, true);
444     retSize = priorityqueue_.Size();
445     EXPECT_EQ(retSize, 0u);
446 }
447 
448 /**
449  * @tc.name: Remove_003
450  * @tc.desc: Single and wait test task.
451  * @tc.type: FUNC
452  * @tc.require:
453  * @tc.author: suoqilong
454  */
455 HWTEST_F(PriorityQueueTest, Remove_003, TestSize.Level1)
456 {
457     TestTask testTask;
458     auto id = ++(testTask.taskId);
459     auto delay = std::chrono::milliseconds(SHORT_INTERVAL);
460     auto ret = priorityqueue_.Push(testTask, id, std::chrono::steady_clock::now() + delay);
461     EXPECT_EQ(ret, true);
462     auto retSize = priorityqueue_.Size();
463     EXPECT_EQ(retSize, 1u);
464     priorityqueue_.Finish(id);
465     auto retRemove = priorityqueue_.Remove(id, true);
466     EXPECT_EQ(retRemove, true);
467     retSize = priorityqueue_.Size();
468     EXPECT_EQ(retSize, 0u);
469 }
470 
471 /**
472  * @tc.name: Clean_001
473  * @tc.desc: Testing a single task.
474  * @tc.type: FUNC
475  * @tc.require:
476  * @tc.author: suoqilong
477  */
478 HWTEST_F(PriorityQueueTest, Clean_001, TestSize.Level1)
479 {
480     TestTask testTask;
481     auto timely = std::chrono::seconds(0);
482     auto id = ++(testTask.taskId);
483     auto ret = priorityqueue_.Push(testTask, id, std::chrono::steady_clock::now() + timely);
484     EXPECT_EQ(ret, true);
485     auto retSize = priorityqueue_.Size();
486     EXPECT_EQ(retSize, 1u);
487     priorityqueue_.Clean();
488     retSize = priorityqueue_.Size();
489     EXPECT_EQ(retSize, 0u);
490 }
491 
492 /**
493  * @tc.name: Clean_002
494  * @tc.desc: Testing multiple tasks.
495  * @tc.type: FUNC
496  * @tc.require:
497  * @tc.author: suoqilong
498  */
499 HWTEST_F(PriorityQueueTest, Clean_002, TestSize.Level1)
500 {
501     TestTask testTask;
502     for (int i = 0; i < 10; ++i) {
503         auto timely = std::chrono::seconds(0);
504         auto id = ++(testTask.taskId);
505         auto ret = priorityqueue_.Push(testTask, id, std::chrono::steady_clock::now() + timely);
506         EXPECT_EQ(ret, true);
507     }
508     auto retSize = priorityqueue_.Size();
509     EXPECT_EQ(retSize, 10u);
510     priorityqueue_.Clean();
511     retSize = priorityqueue_.Size();
512     EXPECT_EQ(retSize, 0u);
513 }
514 
515 /**
516  * @tc.name: Finish_001
517  * @tc.desc: test the priority_queue void Finish(_Tid id) function.
518  * @tc.type: FUNC
519  * @tc.require:
520  * @tc.author: suoqilong
521  */
522 HWTEST_F(PriorityQueueTest, Finish_001, TestSize.Level1)
523 {
524     TestTask testTask;
525     auto id = ++(testTask.taskId);
526     auto delay = std::chrono::milliseconds(SHORT_INTERVAL);
527     auto ret = priorityqueue_.Push(testTask, id, std::chrono::steady_clock::now() + delay);
528     EXPECT_EQ(ret, true);
529     auto retSize = priorityqueue_.Size();
530     EXPECT_EQ(retSize, 1u);
531     priorityqueue_.Finish(id); // Marking Finish
532     auto retRemove = priorityqueue_.Remove(id, true);
533     EXPECT_EQ(retRemove, true);
534     retSize = priorityqueue_.Size();
535     EXPECT_EQ(retSize, 0u);
536 }
537 } // namespace OHOS::Test
538