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 threa, may be different because of system memory align
146 EXPECT_EQ(test->data_, 0);
147 EXPECT_EQ(times, 0);
148 test->NotifyExitSync();
149 sleep(1);
150 EXPECT_EQ(pthread_equal(test->GetThread(), -1) != 0, (test->IsRunning() ? false : true));
151 }
152
153 /*
154 * @tc.name: testThread002
155 * @tc.desc: ThreadTest
156 */
157 HWTEST_F(UtilsThreadTest, testThread002, TestSize.Level0)
158 {
159 times = 0;
160 std::unique_ptr<TestThread> test = std::make_unique<TestThread>(0, true, TestRun01);
161 ThreadStatus status = test->Start("test_thread_02", THREAD_PROI_LOW, 1024);
162
163 EXPECT_EQ(status == ThreadStatus::OK, true);
164
165 sleep(1); // let the new thread has chance to run
166
167 // pthread_equal return non-zero if equal, RUN return false,may exit already
168 EXPECT_EQ(pthread_equal(test->GetThread(), -1) != 0, (test->IsRunning() ? false : true));
169
170 // ReadyToWork return true, RUN will be called!
171 EXPECT_EQ(test->priority_, THREAD_PROI_LOW);
172 EXPECT_EQ(test->name_, "test_thread_02");
173
174 EXPECT_EQ(test->data_, 1);
175 EXPECT_EQ(times, 0);
176 test->NotifyExitSync();
177 sleep(1);
178 EXPECT_EQ(pthread_equal(test->GetThread(), -1) != 0, (test->IsRunning() ? false : true));
179 }
180
181 /*
182 * @tc.name: testThread003
183 * @tc.desc: ThreadTest
184 */
185 HWTEST_F(UtilsThreadTest, testThread003, TestSize.Level0)
186 {
187 times = 0;
188 std::unique_ptr<TestThread> test = std::make_unique<TestThread>(0, false, TestRun02);
189 ThreadStatus status = test->Start("test_thread_03", THREAD_PROI_LOW, 1024);
190 EXPECT_EQ(status == ThreadStatus::OK, true);
191
192 pthread_t thread = test->GetThread();
193
194 // pthread_equal return non-zero if equal
195 EXPECT_EQ(pthread_equal(thread , -1) != 0, (test->IsRunning() ? false : true));
196
197 // ReadyToWork return false, RUN will not be called!
198 EXPECT_EQ(test->priority_, DEFAULT_PRIO);
199 EXPECT_EQ(test->name_, DEFAULT_THREAD_NAME);
200
201 EXPECT_EQ(test->data_, 0);
202 EXPECT_EQ(times, 0);
203 test->NotifyExitSync();
204 sleep(1);
205 EXPECT_EQ(pthread_equal(test->GetThread(), -1) != 0, (test->IsRunning() ? false : true));
206 }
207
208 /*
209 * @tc.name: testThread004
210 * @tc.desc: ThreadTest
211 */
212 HWTEST_F(UtilsThreadTest, testThread004, TestSize.Level0)
213 {
214 times = 0;
215 std::unique_ptr<TestThread> test = std::make_unique<TestThread>(0, true, TestRun02);
216 ThreadStatus status = test->Start("test_thread_04", THREAD_PROI_LOW, 1024);
217
218 EXPECT_EQ(status == ThreadStatus::OK, true);
219
220 sleep(1); // let the new thread has chance to run
221
222 // pthread_equal return non-zero if equal, RUN return false,may exit already
223 EXPECT_EQ(pthread_equal(test->GetThread(), -1) != 0, (test->IsRunning() ? false : true));
224
225 // ReadyToWork return true, RUN will be called!
226 EXPECT_EQ(test->priority_, THREAD_PROI_LOW);
227 EXPECT_EQ(test->name_, "test_thread_04");
228
229 EXPECT_GT(test->data_, 1);
230 EXPECT_EQ(times, 0);
231 test->NotifyExitSync();
232 sleep(1);
233 EXPECT_EQ(pthread_equal(test->GetThread(), -1) != 0, (test->IsRunning() ? false : true));
234 }
235
236 /*
237 * @tc.name: testThread005
238 * @tc.desc: ThreadTest
239 */
240 HWTEST_F(UtilsThreadTest, testThread005, TestSize.Level0)
241 {
242 times = 0;
243 std::unique_ptr<TestThread> test = std::make_unique<TestThread>(0, false, TestRun03);
244 ThreadStatus status = test->Start("test_thread_05", THREAD_PROI_LOW, 1024);
245 EXPECT_EQ(status == ThreadStatus::OK, true);
246
247 pthread_t thread = test->GetThread();
248
249 // pthread_equal return non-zero if equal
250 EXPECT_EQ(pthread_equal(thread , -1) != 0, (test->IsRunning() ? false : true));
251
252 // ReadyToWork return false, RUN will not be called!
253 EXPECT_EQ(test->priority_, DEFAULT_PRIO);
254 EXPECT_EQ(test->name_, DEFAULT_THREAD_NAME);
255
256 EXPECT_EQ(test->data_, 0);
257 EXPECT_EQ(times, 0);
258 test->NotifyExitSync();
259 sleep(1);
260 EXPECT_EQ(pthread_equal(test->GetThread(), -1) != 0, (test->IsRunning() ? false : true));
261 }
262
263 /*
264 * @tc.name: testThread006
265 * @tc.desc: ThreadTest
266 */
267 HWTEST_F(UtilsThreadTest, testThread006, TestSize.Level0)
268 {
269 times = 0;
270 std::unique_ptr<TestThread> test = std::make_unique<TestThread>(0, true, TestRun03);
271 ThreadStatus status = test->Start("test_thread_06", THREAD_PROI_LOW, 1024);
272
273 EXPECT_EQ(status == ThreadStatus::OK, true);
274
275 sleep(1); // let the new thread has chance to run
276
277 // pthread_equal return non-zero if equal, RUN return false,may exit already
278 EXPECT_EQ(pthread_equal(test->GetThread(), -1) != 0, (test->IsRunning() ? false : true));
279
280 // ReadyToWork return true, RUN will be called!
281 EXPECT_EQ(test->priority_, THREAD_PROI_LOW);
282 EXPECT_EQ(test->name_, "test_thread_06");
283
284 EXPECT_GT(test->data_, 10);
285 EXPECT_EQ(times, 0);
286
287 times = 100;
288 EXPECT_GT(test->data_, 10);
289
290 sleep(1); // let the new thread has chance to run
291
292 // times > 10, TestRun03 return false, thread exit
293 EXPECT_EQ(pthread_equal(test->GetThread(), -1) != 0, (test->IsRunning() ? false : true));
294 }
295
296 /*
297 * @tc.name: testThread007
298 * @tc.desc: ThreadTest
299 */
300 HWTEST_F(UtilsThreadTest, testThread007, TestSize.Level0)
301 {
302 times = 0;
303 std::unique_ptr<TestThread> test = std::make_unique<TestThread>(0, true, TestRun03);
304 ThreadStatus status = test->Start("", THREAD_PROI_LOW, 0);
305
306 EXPECT_EQ(status == ThreadStatus::OK, true);
307 if (test->IsRunning()) {
308 status = test->Start("", THREAD_PROI_NORMAL, 1024);
309 EXPECT_EQ(status == ThreadStatus::INVALID_OPERATION, true);
310
311 test->NotifyExitSync();
312 EXPECT_EQ(pthread_equal(test->GetThread(), -1) != 0, (test->IsRunning() ? false : true));
313 }
314
315 sleep(1); // let the new thread has chance to run
316
317 EXPECT_EQ(pthread_equal(test->GetThread(), -1) != 0, (test->IsRunning() ? false : true));
318 }
319
320 /*
321 * @tc.name: testThread008
322 * @tc.desc: ThreadTest
323 */
324 HWTEST_F(UtilsThreadTest, testThread008, TestSize.Level0)
325 {
326 times = 0;
327 std::unique_ptr<TestThread> test = std::make_unique<TestThread>(0, true, TestRun03);
328
329 bool res = test->Thread::ReadyToWork();
330 EXPECT_EQ(res, true);
331
332 ThreadStatus status = test->Start("", THREAD_PROI_NORMAL, 1024);
333 EXPECT_EQ(status == ThreadStatus::OK, true);
334
335 sleep(1);
336 test->NotifyExitAsync();
337
338 sleep(1); // let the new thread has chance to run
339 EXPECT_EQ(pthread_equal(test->GetThread(), -1) != 0, (test->IsRunning() ? false : true));
340 }
341
342 class TestThread2 : public OHOS::Thread {
343 public:
TestThread2(const int data,ThreadRunFunc runFunc)344 TestThread2(const int data, ThreadRunFunc runFunc)
345 : data_(data), priority_(DEFAULT_PRIO), name_(DEFAULT_THREAD_NAME), runFunc_(runFunc)
346 {};
347
348 TestThread2() = delete;
~TestThread2()349 ~TestThread2() {}
350
351 int data_;
352 int priority_;
353 std::string name_;
354 protected:
355 bool Run() override;
356
357 private:
358 ThreadRunFunc runFunc_;
359 };
360
Run()361 bool TestThread2::Run()
362 {
363 priority_ = getpriority(PRIO_PROCESS, 0);
364 char threadName[MAX_THREAD_NAME_LEN + 1] = {0};
365 prctl(PR_GET_NAME, threadName, 0, 0);
366 name_ = threadName;
367
368 if (runFunc_ != nullptr) {
369 return (*runFunc_)(data_);
370 }
371
372 return false;
373 }
374
375 /*
376 * @tc.name: testThread009
377 * @tc.desc: ThreadTest
378 */
379 HWTEST_F(UtilsThreadTest, testThread009, TestSize.Level0)
380 {
381 times = 0;
382 std::unique_ptr<TestThread2> test = std::make_unique<TestThread2>(0, TestRun03);
383
384 bool res = test->ReadyToWork();
385 EXPECT_EQ(res, true);
386
387 ThreadStatus status = test->Start("", THREAD_PROI_NORMAL, 1024);
388 EXPECT_EQ(status == ThreadStatus::OK, true);
389
390 sleep(1);
391 test->NotifyExitAsync();
392
393 sleep(1); // let the new thread has chance to run
394 EXPECT_EQ(pthread_equal(test->GetThread(), -1) != 0, (test->IsRunning() ? false : true));
395 }
396
397 } // namespace
398 } // namespace OHOS