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_ex.h"
17 #include <iostream>
18 #include <cstdio>
19 #include <sys/prctl.h>
20 using namespace testing::ext;
21 using namespace std;
22
23 namespace OHOS {
24 namespace {
25 static int times = 0;
26 using ThreadRunFunc = bool (*)(int& data);
27
28 class UtilsThreadTest : public testing::Test {
29 public:
30 static void SetUpTestCase(void);
31 static void TearDownTestCase(void);
32 void SetUp();
33 void TearDown();
34 };
35
SetUpTestCase(void)36 void UtilsThreadTest::SetUpTestCase(void)
37 {
38 // input testsuit setup step
39 }
40
TearDownTestCase(void)41 void UtilsThreadTest::TearDownTestCase(void)
42 {
43 // input testsuit teardown step
44 }
45
SetUp(void)46 void UtilsThreadTest::SetUp(void)
47 {
48 // recover times
49 times = 0;
50 }
51
TearDown(void)52 void UtilsThreadTest::TearDown(void)
53 {
54 // recover times
55 times = 0;
56 }
57
TestRun01(int & data)58 bool TestRun01(int& data)
59 {
60 ++data;
61 return false;
62 }
63
TestRun02(int & data)64 bool TestRun02(int& data)
65 {
66 ++data;
67 return true;
68 }
69
TestRun03(int & data)70 bool TestRun03(int& data)
71 {
72 static const int TRY_TIMES = 10;
73 if (times <= TRY_TIMES) {
74 ++data;
75 return true;
76 }
77
78 return false;
79 }
80
81 constexpr int DEFAULT_PRIO = 0;
82 const std::string& DEFAULT_THREAD_NAME = "default";
83
84 class TestThread : public OHOS::Thread {
85 public:
TestThread(const int data,const bool readyToWork,ThreadRunFunc runFunc)86 TestThread(const int data, const bool readyToWork, ThreadRunFunc runFunc)
87 : data_(data), priority_(DEFAULT_PRIO), name_(DEFAULT_THREAD_NAME), readyToWork_(readyToWork), runFunc_(runFunc)
88 {};
89
90 TestThread() = delete;
~TestThread()91 ~TestThread() {}
92
93 bool ReadyToWork() override;
94
95 int data_;
96 int priority_;
97 std::string name_;
98 protected:
99 bool Run() override;
100
101 private:
102 bool readyToWork_;
103 ThreadRunFunc runFunc_;
104 };
105
ReadyToWork()106 bool TestThread::ReadyToWork()
107 {
108 return readyToWork_;
109 }
110
Run()111 bool TestThread::Run()
112 {
113 priority_ = getpriority(PRIO_PROCESS, 0);
114 char threadName[MAX_THREAD_NAME_LEN + 1] = {0};
115 prctl(PR_GET_NAME, threadName, 0, 0);
116 name_ = threadName;
117
118 if (runFunc_ != nullptr) {
119 return (*runFunc_)(data_);
120 }
121
122 return false;
123 }
124
125 /*
126 * @tc.name: testThread001
127 * @tc.desc: ThreadTest
128 */
129 HWTEST_F(UtilsThreadTest, testThread001, TestSize.Level0)
130 {
131 times = 0;
132 std::unique_ptr<TestThread> test = std::make_unique<TestThread>(0, false, TestRun01);
133 ThreadStatus status = test->Start("test_thread_01", THREAD_PROI_LOW, 1024);
134 EXPECT_EQ(status == ThreadStatus::OK, true);
135
136 pthread_t thread = test->GetThread();
137
138 // pthread_equal return non-zero if equal
139 EXPECT_EQ(pthread_equal(thread, -1) != 0, (test->IsRunning() ? false : true));
140
141 // ReadyToWork return false, RUN will not be called!
142 EXPECT_EQ(test->priority_, DEFAULT_PRIO);
143 EXPECT_EQ(test->name_, DEFAULT_THREAD_NAME);
144
145 // get stacksize of thread, may be different because of system memory align
146 EXPECT_EQ(test->data_, 0);
147 test->NotifyExitSync();
148 sleep(1);
149 EXPECT_EQ(pthread_equal(test->GetThread(), -1) != 0, (test->IsRunning() ? false : true));
150 }
151
152 /*
153 * @tc.name: testThread002
154 * @tc.desc: ThreadTest
155 */
156 HWTEST_F(UtilsThreadTest, testThread002, TestSize.Level0)
157 {
158 times = 0;
159 std::unique_ptr<TestThread> test = std::make_unique<TestThread>(0, true, TestRun01);
160 ThreadStatus status = test->Start("test_thread_02", THREAD_PROI_LOW, 1024);
161
162 EXPECT_EQ(status == ThreadStatus::OK, true);
163
164 sleep(1); // let the new thread has chance to run
165
166 // pthread_equal return non-zero if equal, RUN return false,may exit already
167 EXPECT_EQ(pthread_equal(test->GetThread(), -1) != 0, (test->IsRunning() ? false : true));
168
169 // ReadyToWork return true, RUN will be called!
170 EXPECT_EQ(test->priority_, THREAD_PROI_LOW);
171 EXPECT_EQ(test->name_, "test_thread_02");
172
173 EXPECT_EQ(test->data_, 1);
174 test->NotifyExitSync();
175 sleep(1);
176 EXPECT_EQ(pthread_equal(test->GetThread(), -1) != 0, (test->IsRunning() ? false : true));
177 }
178
179 /*
180 * @tc.name: testThread003
181 * @tc.desc: ThreadTest
182 */
183 HWTEST_F(UtilsThreadTest, testThread003, TestSize.Level0)
184 {
185 times = 0;
186 std::unique_ptr<TestThread> test = std::make_unique<TestThread>(0, false, TestRun02);
187 ThreadStatus status = test->Start("test_thread_03", THREAD_PROI_LOW, 1024);
188 EXPECT_EQ(status == ThreadStatus::OK, true);
189
190 pthread_t thread = test->GetThread();
191
192 // pthread_equal return non-zero if equal
193 EXPECT_EQ(pthread_equal(thread , -1) != 0, (test->IsRunning() ? false : true));
194
195 // ReadyToWork return false, RUN will not be called!
196 EXPECT_EQ(test->priority_, DEFAULT_PRIO);
197 EXPECT_EQ(test->name_, DEFAULT_THREAD_NAME);
198
199 EXPECT_EQ(test->data_, 0);
200 test->NotifyExitSync();
201 sleep(1);
202 EXPECT_EQ(pthread_equal(test->GetThread(), -1) != 0, (test->IsRunning() ? false : true));
203 }
204
205 /*
206 * @tc.name: testThread004
207 * @tc.desc: ThreadTest
208 */
209 HWTEST_F(UtilsThreadTest, testThread004, TestSize.Level0)
210 {
211 times = 0;
212 std::unique_ptr<TestThread> test = std::make_unique<TestThread>(0, true, TestRun02);
213 ThreadStatus status = test->Start("test_thread_04", THREAD_PROI_LOW, 1024);
214
215 EXPECT_EQ(status == ThreadStatus::OK, true);
216
217 sleep(1); // let the new thread has chance to run
218
219 // pthread_equal return non-zero if equal, RUN return false,may exit already
220 EXPECT_EQ(pthread_equal(test->GetThread(), -1) != 0, (test->IsRunning() ? false : true));
221
222 // ReadyToWork return true, RUN will be called!
223 EXPECT_EQ(test->priority_, THREAD_PROI_LOW);
224 EXPECT_EQ(test->name_, "test_thread_04");
225
226 EXPECT_GT(test->data_, 1);
227 test->NotifyExitSync();
228 sleep(1);
229 EXPECT_EQ(pthread_equal(test->GetThread(), -1) != 0, (test->IsRunning() ? false : true));
230 }
231
232 /*
233 * @tc.name: testThread005
234 * @tc.desc: ThreadTest
235 */
236 HWTEST_F(UtilsThreadTest, testThread005, TestSize.Level0)
237 {
238 times = 0;
239 std::unique_ptr<TestThread> test = std::make_unique<TestThread>(0, false, TestRun03);
240 ThreadStatus status = test->Start("test_thread_05", THREAD_PROI_LOW, 1024);
241 EXPECT_EQ(status == ThreadStatus::OK, true);
242
243 pthread_t thread = test->GetThread();
244
245 // pthread_equal return non-zero if equal
246 EXPECT_EQ(pthread_equal(thread , -1) != 0, (test->IsRunning() ? false : true));
247
248 // ReadyToWork return false, RUN will not be called!
249 EXPECT_EQ(test->priority_, DEFAULT_PRIO);
250 EXPECT_EQ(test->name_, DEFAULT_THREAD_NAME);
251
252 EXPECT_EQ(test->data_, 0);
253 test->NotifyExitSync();
254 sleep(1);
255 EXPECT_EQ(pthread_equal(test->GetThread(), -1) != 0, (test->IsRunning() ? false : true));
256 }
257
258 /*
259 * @tc.name: testThread006
260 * @tc.desc: ThreadTest
261 */
262 HWTEST_F(UtilsThreadTest, testThread006, TestSize.Level0)
263 {
264 times = 0;
265 std::unique_ptr<TestThread> test = std::make_unique<TestThread>(0, true, TestRun03);
266 ThreadStatus status = test->Start("test_thread_06", THREAD_PROI_LOW, 1024);
267
268 EXPECT_EQ(status == ThreadStatus::OK, true);
269
270 sleep(1); // let the new thread has chance to run
271
272 // pthread_equal return non-zero if equal, RUN return false,may exit already
273 EXPECT_EQ(pthread_equal(test->GetThread(), -1) != 0, (test->IsRunning() ? false : true));
274
275 // ReadyToWork return true, RUN will be called!
276 EXPECT_EQ(test->priority_, THREAD_PROI_LOW);
277 EXPECT_EQ(test->name_, "test_thread_06");
278
279 EXPECT_GT(test->data_, 10);
280
281 times = 100;
282 EXPECT_GT(test->data_, 10);
283
284 sleep(1); // let the new thread has chance to run
285
286 // times > 10, TestRun03 return false, thread exit
287 EXPECT_EQ(pthread_equal(test->GetThread(), -1) != 0, (test->IsRunning() ? false : true));
288 }
289
290 /*
291 * @tc.name: testThread007
292 * @tc.desc: ThreadTest
293 */
294 HWTEST_F(UtilsThreadTest, testThread007, TestSize.Level0)
295 {
296 times = 0;
297 std::unique_ptr<TestThread> test = std::make_unique<TestThread>(0, true, TestRun03);
298 ThreadStatus status = test->Start("", THREAD_PROI_LOW, 0);
299
300 EXPECT_EQ(status == ThreadStatus::OK, true);
301 if (test->IsRunning()) {
302 status = test->Start("", THREAD_PROI_NORMAL, 1024);
303 EXPECT_EQ(status == ThreadStatus::INVALID_OPERATION, true);
304
305 test->NotifyExitSync();
306 EXPECT_EQ(pthread_equal(test->GetThread(), -1) != 0, (test->IsRunning() ? false : true));
307 }
308
309 sleep(1); // let the new thread has chance to run
310
311 EXPECT_EQ(pthread_equal(test->GetThread(), -1) != 0, (test->IsRunning() ? false : true));
312 }
313
314 /*
315 * @tc.name: testThread008
316 * @tc.desc: ThreadTest
317 */
318 HWTEST_F(UtilsThreadTest, testThread008, TestSize.Level0)
319 {
320 times = 0;
321 std::unique_ptr<TestThread> test = std::make_unique<TestThread>(0, true, TestRun03);
322
323 bool res = test->Thread::ReadyToWork();
324 EXPECT_EQ(res, true);
325
326 ThreadStatus status = test->Start("", THREAD_PROI_NORMAL, 1024);
327 EXPECT_EQ(status == ThreadStatus::OK, true);
328
329 sleep(1);
330 test->NotifyExitAsync();
331
332 sleep(1); // let the new thread has chance to run
333 EXPECT_EQ(pthread_equal(test->GetThread(), -1) != 0, (test->IsRunning() ? false : true));
334 }
335
336 class TestThread2 : public OHOS::Thread {
337 public:
TestThread2(const int data,ThreadRunFunc runFunc)338 TestThread2(const int data, ThreadRunFunc runFunc)
339 : data_(data), priority_(DEFAULT_PRIO), name_(DEFAULT_THREAD_NAME), runFunc_(runFunc)
340 {};
341
342 TestThread2() = delete;
~TestThread2()343 ~TestThread2() {}
344
345 int data_;
346 int priority_;
347 std::string name_;
348 protected:
349 bool Run() override;
350
351 private:
352 ThreadRunFunc runFunc_;
353 };
354
Run()355 bool TestThread2::Run()
356 {
357 priority_ = getpriority(PRIO_PROCESS, 0);
358 char threadName[MAX_THREAD_NAME_LEN + 1] = {0};
359 prctl(PR_GET_NAME, threadName, 0, 0);
360 name_ = threadName;
361
362 if (runFunc_ != nullptr) {
363 return (*runFunc_)(data_);
364 }
365
366 return false;
367 }
368
369 /*
370 * @tc.name: testThread009
371 * @tc.desc: ThreadTest
372 */
373 HWTEST_F(UtilsThreadTest, testThread009, TestSize.Level0)
374 {
375 times = 0;
376 std::unique_ptr<TestThread2> test = std::make_unique<TestThread2>(0, TestRun03);
377
378 bool res = test->ReadyToWork();
379 EXPECT_EQ(res, true);
380
381 ThreadStatus status = test->Start("", THREAD_PROI_NORMAL, 1024);
382 EXPECT_EQ(status == ThreadStatus::OK, true);
383
384 sleep(1);
385 test->NotifyExitAsync();
386
387 sleep(1); // let the new thread has chance to run
388 EXPECT_EQ(pthread_equal(test->GetThread(), -1) != 0, (test->IsRunning() ? false : true));
389 }
390
391 } // namespace
392 } // namespace OHOS