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 
16 #include<cstring>
17 #include<string>
18 
19 #include "gtest/gtest.h"
20 
21 #include "platform/threadpool/include/thread.h"
22 #include "platform/threadpool/include/thread_pool.h"
23 #include "platform/time/include/time.h"
24 #include "utils/log/aie_log.h"
25 
26 using namespace OHOS::AI;
27 using namespace std;
28 using namespace testing::ext;
29 
30 namespace {
31     const int STOP_TIME = 100;
32     const time_t HUNG_TIME = 15;
33     const int SIZE = 70000;
34     const int SIZE_MIN = 0;
35     const int INVALID_THREAD_ID = -1;
36     const string WORKER_DEFAULT_NAME("WorkerDefaultName");
37 }
38 
39 class ThreadPoolTest : public testing::Test {
40 public:
41     // SetUpTestCase:The preset action of the test suite is executed before the first TestCase
SetUpTestCase()42     static void SetUpTestCase() {};
43 
44     // TearDownTestCase:The test suite cleanup action is executed after the last TestCase
TearDownTestCase()45     static void TearDownTestCase() {};
46 
47     // SetUp:Execute before each test case
SetUp()48     void SetUp() {};
49 
50     // TearDown:Execute after each test case
TearDown()51     void TearDown() {};
52 };
53 
54 class CWorker : public IWorker {
55 public:
GetName() const56     const char *GetName() const override
57     {
58         return "CWorker";
59     }
60 
OneAction()61     bool OneAction() override
62     {
63         StepSleepMs(THREAD_SLEEP_MS);
64         HILOGD("[Test]Worker OneAction after sleep");
65         return true;
66     }
67 
Initialize()68     bool Initialize() override
69     {
70         HILOGD("[Test]Worker Initialize success");
71         return true;
72     }
73 };
74 
75 class MultiWorker : public IWorker {
76 public:
MultiWorker(const string & workerName)77     explicit MultiWorker(const string &workerName) : workerName_(workerName)
78     {
79     }
80 
81     ~MultiWorker() override = default;
82 
GetName() const83     const char *GetName() const override
84     {
85         return workerName_.c_str();
86     }
87 
OneAction()88     bool OneAction() override
89     {
90         StepSleepMs(THREAD_SLEEP_MS);
91         HILOGD("[Test]Worker(%s) OneAction success.", GetName());
92         return true;
93     }
94 
Initialize()95     bool Initialize() override
96     {
97         HILOGD("[Test]Worker(%s) Initialize success.", GetName());
98         return true;
99     }
100 
Uninitialize()101     void Uninitialize() override
102     {
103         HILOGD("[Test]Worker(%s) Uninitialize success.", GetName());
104     }
105 
106 private:
107     string workerName_ = WORKER_DEFAULT_NAME;
108 };
109 
110 /**
111  * @tc.name: TestWorker001
112  * @tc.desc: Test worker Initialize/GetStackSize/Status/GetThreadId functions.
113  * @tc.type: FUNC
114  * @tc.require: AR000F77TL
115  */
116 HWTEST_F(ThreadPoolTest, TestWorker001, TestSize.Level1)
117 {
118     HILOGD("[Test]Test worker begin");
119     CWorker worker;
120     worker.Initialize();
121     ASSERT_FALSE(worker.isHung(HUNG_TIME));
122     ASSERT_EQ(worker.GetStackSize(), THREAD_DEFAULT_STACK_SIZE);
123     ASSERT_EQ(worker.Status(), 0);
124     ASSERT_EQ(static_cast<int>(worker.GetThreadId()), INVALID_THREAD_ID);
125     Thread thread;
126     worker.SetThread(&thread);
127     HILOGD("[Test]Test worker end, GetThreadId is %lu.", worker.GetThreadId());
128 }
129 
130 /**
131  * @tc.name: TestThread001
132  * @tc.desc: Test thread StartThread/IsRunning/IsActive/StopThread functions.
133  * @tc.type: FUNC
134  * @tc.require: AR000F77TL
135  */
136 HWTEST_F(ThreadPoolTest, TestThread001, TestSize.Level1)
137 {
138     HILOGD("[Test]Test thread1 begin");
139     Thread testThread;
140     unsigned long id = testThread.GetThreadId();
141     HILOGD("[Test]Thread id %lu.", id);
142     testThread.SetStackSize(SIZE);
143     CWorker worker;
144     ASSERT_TRUE(testThread.StartThread(&worker));
145     id = testThread.GetThreadId();
146     HILOGD("[Test]Thread id %lu.", id);
147     ASSERT_TRUE(testThread.IsRunning());
148     ASSERT_TRUE(testThread.IsActive());
149     ASSERT_TRUE(testThread.StopThread(STOP_TIME));
150     ASSERT_FALSE(testThread.IsRunning());
151     ASSERT_FALSE(testThread.IsActive());
152     HILOGD("[Test]Test thread1 end.");
153 }
154 
155 /**
156  * @tc.name: ThreadPoolTest001
157  * @tc.desc: Test ThreadPool SetStackSize/getStackSize functions.
158  * @tc.type: FUNC
159  * @tc.require: AR000F77TL
160  */
161 HWTEST_F(ThreadPoolTest, ThreadPoolTest001, TestSize.Level1)
162 {
163     HILOGD("[Test]ThreadPoolTest001 begin");
164     ThreadPool *threadPool = ThreadPool::GetInstance();
165     ASSERT_EQ(threadPool->getStackSize(), 0);
166     threadPool->SetStackSize(SIZE);
167     ASSERT_EQ(threadPool->getStackSize(), SIZE);
168     threadPool->SetStackSize(SIZE_MIN);
169     HILOGD("[Test]ThreadPoolTest001 end");
170 }
171 
172 /**
173  * @tc.name: ThreadPoolTest002
174  * @tc.desc: Test ThreadPool Pop method.
175  * @tc.type: FUNC
176  * @tc.require: AR000F77TL
177  */
178 HWTEST_F(ThreadPoolTest, ThreadPoolTest002, TestSize.Level1)
179 {
180     HILOGD("[Test]ThreadPoolTest002 begin");
181     ThreadPool *threadPool = ThreadPool::GetInstance();
182     ASSERT_NE(threadPool, nullptr);
183     std::shared_ptr<Thread> oneThread = threadPool->Pop();
184     ASSERT_NE(oneThread, nullptr);
185     HILOGD("[Test]ThreadPoolTest002 end");
186 }
187 
188 /**
189  * @tc.name: ThreadPoolTest003
190  * @tc.desc: Test ThreadPool Push method.
191  * @tc.type: FUNC
192  * @tc.require: AR000F77TL
193  */
194 HWTEST_F(ThreadPoolTest, ThreadPoolTest003, TestSize.Level1)
195 {
196     HILOGD("[Test]ThreadPoolTest003 begin");
197     ThreadPool *threadPool = ThreadPool::GetInstance();
198     ASSERT_NE(threadPool, nullptr);
199     std::shared_ptr<Thread> oneThread = threadPool->Pop();
200     threadPool->Push(oneThread);
201     HILOGD("[Test]ThreadPoolTest003 end");
202 }
203 
204 /**
205  * @tc.name: TestThreadWithManyWorker001
206  * @tc.desc: Test pop/push thread, and start/stop thread
207  * @tc.type: FUNC
208  * @tc.require: AR000F77TL
209  */
210 HWTEST_F(ThreadPoolTest, TestThreadWithManyWorker001, TestSize.Level1)
211 {
212     HILOGD("[Test]Test worker begin");
213     string workerName("MultiWorker");
214     int maxThreadNum = 10;
215     MultiWorker *workerList[maxThreadNum];
216     std::shared_ptr<Thread> threadList[maxThreadNum];
217     ThreadPool *threadPool = ThreadPool::GetInstance();
218     ASSERT_NE(threadPool, nullptr);
219     for (int i = 0; i < maxThreadNum; i++) {
220         string tempWorkerName = workerName + to_string(i);
221         AIE_NEW(workerList[i], MultiWorker(tempWorkerName));
222         threadList[i] = threadPool->Pop();
223         ASSERT_TRUE(threadList[i]->StartThread(workerList[i]));
224     }
225     for (int i = 0; i < maxThreadNum; i++) {
226         threadList[i]->StopThread();
227         threadPool->Push(threadList[i]);
228         AIE_DELETE(workerList[i]);
229     }
230     threadPool->ReleaseInstance();
231 }
232