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 #include <gtest/gtest.h>
16 
17 #include "block_data.h"
18 #include "executor_pool.h"
19 
20 namespace OHOS::Test {
21 using namespace testing::ext;
22 using namespace OHOS;
23 using duration = std::chrono::steady_clock::duration;
24 class ExecutorPoolTest : public testing::Test {
25 public:
26     struct Data {
27         std::mutex mutex_;
28         int data = 0;
AddOHOS::Test::ExecutorPoolTest::Data29         void Add()
30         {
31             std::lock_guard<std::mutex> lockGuard(mutex_);
32             data++;
33         }
34     };
35     static constexpr uint32_t SHORT_INTERVAL = 100; // ms
36     static constexpr uint32_t LONG_INTERVAL = 1;    // s
37     static std::shared_ptr<ExecutorPool> executorPool_;
SetUpTestCase(void)38     static void SetUpTestCase(void){};
TearDownTestCase(void)39     static void TearDownTestCase(void)
40     {
41         executorPool_ = nullptr;
42     };
SetUp()43     void SetUp(){};
TearDown()44     void TearDown() {}
45 };
46 std::shared_ptr<ExecutorPool> ExecutorPoolTest::executorPool_ = std::make_shared<ExecutorPool>(12, 5);
47 
48 /**
49 * @tc.name: Execute
50 * @tc.desc:
51 * @tc.type: FUNC
52 * @tc.require:
53 * @tc.author: CRJ
54 */
55 HWTEST_F(ExecutorPoolTest, Execute, TestSize.Level0)
56 {
57     auto expiredTime = std::chrono::milliseconds(SHORT_INTERVAL);
58     int testData = 10;
59     auto blockData = std::make_shared<BlockData<int>>(LONG_INTERVAL, testData);
__anon319724040102() 60     auto atTaskId1 = executorPool_->Schedule(expiredTime, [blockData]() {
61         int testData = 11;
62         blockData->SetValue(testData);
63     });
64     ASSERT_EQ(blockData->GetValue(), 11);
65     blockData->Clear();
__anon319724040202() 66     auto atTaskId2 = executorPool_->Schedule(expiredTime, [blockData]() {
67         int testData = 12;
68         blockData->SetValue(testData);
69     });
70     ASSERT_EQ(blockData->GetValue(), 12);
71     ASSERT_NE(atTaskId1, atTaskId2);
72 }
73 
74 /**
75 * @tc.name: Schedule
76 * @tc.desc:
77 * @tc.type: FUNC
78 * @tc.require:
79 * @tc.author: CRJ
80 */
81 HWTEST_F(ExecutorPoolTest, Schedule, TestSize.Level0)
82 {
83     auto expiredTime = std::chrono::milliseconds(SHORT_INTERVAL);
84     auto testData = std::make_shared<Data>();
85     auto taskId = executorPool_->Schedule(
__anon319724040302null86         [testData] {
87             testData->Add();
88         },
89         expiredTime);
90     ASSERT_NE(taskId, ExecutorPool::INVALID_TASK_ID);
91     std::this_thread::sleep_for(std::chrono::milliseconds(SHORT_INTERVAL * 10));
92     ASSERT_EQ(testData->data, 10);
93     executorPool_->Remove(taskId);
94 }
95 
96 /**
97 * @tc.name: MultiSchedule
98 * @tc.desc:
99 * @tc.type: FUNC
100 * @tc.require:
101 * @tc.author: CRJ
102 */
103 HWTEST_F(ExecutorPoolTest, MultiSchedule, TestSize.Level0)
104 {
105     auto data = std::make_shared<Data>();
__anon319724040402null106     auto task = [data] {
107         data->Add();
108     };
109     std::set<ExecutorPool::TaskId> ids;
110     for (int i = 0; i < 10; ++i) {
111         auto id = executorPool_->Schedule(task, std::chrono::seconds(0), std::chrono::seconds(LONG_INTERVAL), 10);
112         ASSERT_EQ(ids.count(id), 0);
113         ids.insert(id);
114     }
115     std::this_thread::sleep_for(std::chrono::seconds(LONG_INTERVAL * 10));
116     ASSERT_EQ(data->data, 100);
117     for (auto id : ids) {
118         executorPool_->Remove(id);
119     }
120 }
121 /**
122 * @tc.name: Remove
123 * @tc.desc:
124 * @tc.type: FUNC
125 * @tc.require:
126 * @tc.author: CRJ
127 */
128 HWTEST_F(ExecutorPoolTest, Remove, TestSize.Level0)
129 {
130     auto expiredTime = std::chrono::milliseconds(SHORT_INTERVAL);
131     auto data = std::make_shared<Data>();
__anon319724040502null132     auto task = [data] {
133         data->Add();
134     };
135     auto temp = executorPool_->Schedule(task, expiredTime * 2);
136     std::this_thread::sleep_for(std::chrono::milliseconds(SHORT_INTERVAL));
137     ASSERT_EQ(data->data, 1);
138     ASSERT_TRUE(executorPool_->Remove(temp));
139     std::this_thread::sleep_for(expiredTime * 4);
140     ASSERT_EQ(data->data, 1);
141 }
142 /**
143 * @tc.name: Reset
144 * @tc.desc:
145 * @tc.type: FUNC
146 * @tc.require:
147 * @tc.author: CRJ
148 */
149 HWTEST_F(ExecutorPoolTest, Reset, TestSize.Level0)
150 {
151     auto expiredTime = std::chrono::milliseconds(SHORT_INTERVAL);
152     auto data = std::make_shared<Data>();
__anon319724040602null153     auto task = [data] {
154         data->Add();
155     };
156     auto temp = executorPool_->Schedule(task, expiredTime * 2);
157     std::this_thread::sleep_for(std::chrono::milliseconds(SHORT_INTERVAL));
158     ASSERT_EQ(data->data, 1);
159     ASSERT_EQ(executorPool_->Reset(temp, std::chrono::milliseconds(expiredTime * 2)), temp);
160     std::this_thread::sleep_for(std::chrono::milliseconds(expiredTime * 5));
161     ASSERT_EQ(data->data, 3);
162     executorPool_->Remove(temp);
163 }
164 
165 /**
166 * @tc.name: MaxEqualsOne
167 * @tc.desc:
168 * @tc.type: FUNC
169 * @tc.require:
170 * @tc.author: CRJ
171 */
172 HWTEST_F(ExecutorPoolTest, MaxEqualsOne, TestSize.Level0)
173 {
174     auto executors = std::make_shared<ExecutorPool>(1, 0);
175     std::atomic<int> testNum = 1;
__anon319724040702null176     auto delayTask = [&testNum] {
177         testNum++;
178     };
__anon319724040802null179     auto task = [&testNum] {
180         testNum += 2;
181     };
182     executors->Schedule(std::chrono::milliseconds(SHORT_INTERVAL * 2), delayTask);
183     ASSERT_EQ(testNum, 1);
184     executors->Execute(task);
185     std::this_thread::sleep_for(std::chrono::milliseconds(SHORT_INTERVAL));
186     ASSERT_EQ(testNum, 3);
187     std::this_thread::sleep_for(std::chrono::milliseconds(SHORT_INTERVAL * 2));
188     ASSERT_EQ(testNum, 4);
189 }
190 
191 /**
192 * @tc.name: RemoveInExcuteTask
193 * @tc.desc: test remove task when the task is running.
194 * @tc.type: FUNC
195 * @tc.require:
196 * @tc.author: ht
197 */
198 HWTEST_F(ExecutorPoolTest, RemoveWhenExcute, TestSize.Level0)
199 {
200     auto executors = std::make_shared<ExecutorPool>(1, 1);
201     auto taskId = ExecutorPool::INVALID_TASK_ID;
202     std::atomic<int> flag = 0;
203     taskId = executors->Schedule(
__anon319724040902() 204         [executors, &taskId, &flag]() {
205             flag++;
206             executors->Remove(taskId, false);
207             taskId = ExecutorPool::INVALID_TASK_ID;
208         },
209         std::chrono::seconds(0), std::chrono::milliseconds(SHORT_INTERVAL), 10);
210     std::this_thread::sleep_for(std::chrono::seconds(LONG_INTERVAL));
211     ASSERT_EQ(taskId, ExecutorPool::INVALID_TASK_ID);
212     ASSERT_EQ(flag, 1);
213 }
214 } // namespace OHOS::Test
215