• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 #include "thread_pool.h"
17 #include <chrono>
18 #include <cstdio>
19 
20 using namespace testing::ext;
21 using namespace OHOS;
22 
23 class UtilsThreadPoolTest : public testing::Test
24 {
25 public :
26     static void SetUpTestCase(void);
27     static void TearDownTestCase(void);
28     void SetUp();
29     void TearDown();
30 };
31 
32 int g_times = 0;
33 bool g_ready = false;
34 std::mutex g_mutex;
35 std::condition_variable g_cv;
36 
SetUpTestCase(void)37 void UtilsThreadPoolTest::SetUpTestCase(void)
38 {
39     // step 2: input testsuit setup step
40 }
41 
TearDownTestCase(void)42 void UtilsThreadPoolTest::TearDownTestCase(void)
43 {
44     // step 2: input testsuit teardown step
45 }
46 
SetUp(void)47 void UtilsThreadPoolTest::SetUp(void)
48 {
49     // recover
50     g_times = 0;
51     g_ready = false;
52 }
53 
TearDown(void)54 void UtilsThreadPoolTest::TearDown(void)
55 {
56     // recover
57     g_times = 0;
58     g_ready = false;
59 
60 }
61 
62 HWTEST_F(UtilsThreadPoolTest, test_01, TestSize.Level0)
63 {
64     ThreadPool pool;
65     EXPECT_EQ(pool.GetName(), "");
66     EXPECT_EQ((int)pool.GetMaxTaskNum(), 0);
67     EXPECT_EQ((int)pool.GetThreadsNum(), 0);
68     EXPECT_EQ((int)pool.GetCurTaskNum(), 0);
69 }
70 
71 HWTEST_F(UtilsThreadPoolTest, test_02, TestSize.Level0)
72 {
73     ThreadPool pool("test_02_pool");
74     EXPECT_EQ(pool.GetName(), "test_02_pool");
75     EXPECT_EQ((int)pool.GetMaxTaskNum(), 0);
76     EXPECT_EQ((int)pool.GetThreadsNum(), 0);
77     EXPECT_EQ((int)pool.GetCurTaskNum(), 0);
78 }
79 
80 HWTEST_F(UtilsThreadPoolTest, test_03, TestSize.Level0)
81 {
82     ThreadPool pool("test_02_pool");
83     pool.SetMaxTaskNum(10);
84     EXPECT_EQ(pool.GetName(), "test_02_pool");
85     EXPECT_EQ((int)pool.GetMaxTaskNum(), 10);
86     EXPECT_EQ((int)pool.GetThreadsNum(), 0);
87     EXPECT_EQ((int)pool.GetCurTaskNum(), 0);
88 }
89 
90 HWTEST_F(UtilsThreadPoolTest, test_04, TestSize.Level0)
91 {
92     ThreadPool pool;
93     pool.Start(4);
94     EXPECT_EQ(pool.GetName(), "");
95     EXPECT_EQ((int)pool.GetMaxTaskNum(), 0);
96     EXPECT_EQ((int)pool.GetThreadsNum(), 4);
97     EXPECT_EQ((int)pool.GetCurTaskNum(), 0);
98 
99     // add no task, g_times has no change
100     EXPECT_EQ(g_times, 0);
101     pool.Stop();
102 }
103 
TestFuncAddOneTime(int & i)104 void TestFuncAddOneTime(int& i)
105 {
106     ++g_times;
107 }
108 
TestFuncSubOneTime(int & i)109 void TestFuncSubOneTime(int& i)
110 {
111     --g_times;
112 }
113 
114 // simple task, total task num less than the MaxTaskNum
115 HWTEST_F(UtilsThreadPoolTest, test_05, TestSize.Level0)
116 {
117     ThreadPool pool;
118     pool.Start(5);
119     EXPECT_EQ(pool.GetName(), "");
120     EXPECT_EQ((int)pool.GetThreadsNum(), 5);
121     EXPECT_EQ((int)pool.GetCurTaskNum(), 0);
122 
123     for (int i = 0; i < 3; ++i)
124     {
125         auto task = std::bind(TestFuncAddOneTime, i);
126         pool.AddTask(task);
127     }
128 
129     for (int i = 0; i < 2; ++i)
130     {
131         auto task = std::bind(TestFuncSubOneTime, i);
132         pool.AddTask(task);
133     }
134 
135     sleep(1);
136     EXPECT_EQ((int)pool.GetCurTaskNum(), 0);
137     // add 5 task, add 3 times and sub 2 times
138     EXPECT_EQ(g_times, 1);
139     pool.Stop();
140 }
141 
142 // simaple task, total task num exceed the MaxTaskNum and the threads num
143 HWTEST_F(UtilsThreadPoolTest, test_06, TestSize.Level0)
144 {
145     ThreadPool pool;
146     pool.Start(5);
147     EXPECT_EQ(pool.GetName(), "");
148     EXPECT_EQ((int)pool.GetThreadsNum(), 5);
149     EXPECT_EQ((int)pool.GetCurTaskNum(), 0);
150 
151     pool.SetMaxTaskNum(10);
152 
153     for (int i = 0; i < 8; ++i)
154     {
155         auto task = std::bind(TestFuncAddOneTime, i);
156         pool.AddTask(task);
157     }
158 
159     for (int i = 0; i < 7; ++i)
160     {
161         auto task = std::bind(TestFuncSubOneTime, i);
162         pool.AddTask(task);
163     }
164 
165     sleep(1);
166     // 1 second should be enough to complete these tasks. if not, this case would be fail
167     EXPECT_EQ((int)pool.GetCurTaskNum(), 0);
168     // add 5 task, add 3 times and sub 2 times
169     EXPECT_EQ(g_times, 1);
170     pool.Stop();
171 }
172 
TestFuncAddWait(int & i)173 void TestFuncAddWait(int& i)
174 {
175     ++g_times;
176     printf("after func:%s0%d called, :%d\n", __func__, i, g_times);
177     std::unique_lock<std::mutex> lk(g_mutex);
178     g_cv.wait(lk, [] {return g_ready;});
179     printf("func:%s0%d received ready signal!\n", __func__, i);
180 }
181 
TestFuncSubWait(int & i)182 void TestFuncSubWait(int& i)
183 {
184     --g_times;
185     printf("after func:%s0%d called, :%d\n", __func__, i, g_times);
186     std::unique_lock<std::mutex> lk(g_mutex);
187     g_cv.wait(lk, [] {return g_ready;});
188     printf("func:%s0%d received ready signal!\n", __func__, i);
189 }
190 
191 // complex task, wait for notify by the main thread
192 // total task num less than the threads num and the MaxTaskNum
193 HWTEST_F(UtilsThreadPoolTest, test_07, TestSize.Level0)
194 {
195     ThreadPool pool;
196     pool.Start(5);
197     EXPECT_EQ(pool.GetName(), "");
198     EXPECT_EQ((int)pool.GetThreadsNum(), 5);
199     EXPECT_EQ((int)pool.GetCurTaskNum(), 0);
200 
201     for (int i = 0; i < 3; ++i)
202     {
203         auto task = std::bind(TestFuncAddWait, i);
204         pool.AddTask(task);
205     }
206 
207     for (int i = 0; i < 2; ++i)
208     {
209         auto task = std::bind(TestFuncSubWait, i);
210         pool.AddTask(task);
211     }
212 
213     std::this_thread::sleep_for(std::chrono::seconds(1)); // release cpu proactively, let the task threads go into wait
214     {
215         std::lock_guard<std::mutex> lk(g_mutex);
216         g_ready = true;
217     }
218 
219     g_cv.notify_all();
220 
221     // these tasks are endless Loop, 5 threads process 5 tasks, zero task remains in the task queue
222     EXPECT_EQ((int)pool.GetCurTaskNum(), 0);
223     // add 5 task, add 3 times and sub 2 times
224     EXPECT_EQ(g_times, 1);
225     pool.Stop();
226 }
227 
228 HWTEST_F(UtilsThreadPoolTest, test_08, TestSize.Level0)
229 {
230     ThreadPool pool;
231     pool.Start(5);
232     EXPECT_EQ(pool.GetName(), "");
233     EXPECT_EQ((int)pool.GetThreadsNum(), 5);
234     EXPECT_EQ((int)pool.GetCurTaskNum(), 0);
235 
236     pool.SetMaxTaskNum(10);
237 
238     // ADD 15 tasks
239     for (int i = 0; i < 8; ++i)
240     {
241         auto task = std::bind(TestFuncAddWait, i);
242         pool.AddTask(task);
243     }
244 
245     for (int i = 0; i < 7; ++i)
246     {
247         auto task = std::bind(TestFuncSubWait, i);
248         pool.AddTask(task);
249     }
250 
251     sleep(1);
252     // at this time, the first 5 tasks execute and wait for notify, the rest 10 tasks stay in the task queue.
253     EXPECT_EQ((int)pool.GetCurTaskNum(), 10);
254     // FIFO,
255     EXPECT_EQ(g_times, 5);
256 
257     // notify_all
258     {
259         std::lock_guard<std::mutex> lk(g_mutex);
260         g_ready = true;
261     }
262     g_cv.notify_all();
263 
264     // after noity, task thread wake up, and g_ready is true, new tasks didn't need to wait
265     sleep(1);
266     // these tasks are endless Loop, and total num of task exceed the MaxTaskNum
267     EXPECT_EQ((int)pool.GetCurTaskNum(), 0);
268     EXPECT_EQ(g_times, 1);
269     pool.Stop();
270 }
271 
272