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
21 using namespace testing::ext;
22 using namespace OHOS;
23 using namespace std;
24
25 static int times = 0;
26 using ThreadRunFunc = bool (*)(int& data);
27
28 class UtilsThreadTest : public testing::Test
29 {
30 public :
31 static void SetUpTestCase(void);
32 static void TearDownTestCase(void);
33 void SetUp();
34 void TearDown();
35 };
36
SetUpTestCase(void)37 void UtilsThreadTest::SetUpTestCase(void)
38 {
39 // input testsuit setup step
40 }
41
TearDownTestCase(void)42 void UtilsThreadTest::TearDownTestCase(void)
43 {
44 // input testsuit teardown step
45 }
46
SetUp(void)47 void UtilsThreadTest::SetUp(void)
48 {
49 // recover times
50 times = 0;
51 }
52
TearDown(void)53 void UtilsThreadTest::TearDown(void)
54 {
55 // recover times
56 times = 0;
57 }
58
59 // get priority of thread
GetThreadPriority(const pthread_t & thread)60 int GetThreadPriority(const pthread_t& thread)
61 {
62 sched_param param;
63 int priority;
64 int policy;
65 int ret;
66
67 // scheduling parameters of target thread
68 ret = pthread_getschedparam (thread, &policy, ¶m);
69 if (ret != 0){
70 printf("pthread_getschedparam failed! thread:%lu, ret:%d\n", thread, ret);
71 return -1;
72 }
73
74 // sched_priority contains the priority of the thread
75 priority = param.sched_priority;
76 return priority;
77 }
78
79
TestRun01(int & data)80 bool TestRun01(int& data)
81 {
82 ++data;
83 return false;
84 }
85
TestRun02(int & data)86 bool TestRun02(int& data)
87 {
88 ++data;
89 return true;
90 }
91
TestRun03(int & data)92 bool TestRun03(int& data)
93 {
94 static const int TRY_TIMES = 10;
95 if (times <= TRY_TIMES) {
96 ++data;
97 return true;
98 }
99
100 return false;
101 }
102
103 constexpr int DEFAULT_PRIO = 0;
104 const std::string& DEFAULT_THREAD_NAME = "default";
105
106 class TestThread : public OHOS::Thread{
107 public:
TestThread(const int data,const bool readyToWork,ThreadRunFunc runFunc)108 TestThread(const int data, const bool readyToWork, ThreadRunFunc runFunc)
109 : data_(data), priority_(DEFAULT_PRIO), name_(DEFAULT_THREAD_NAME), readyToWork_(readyToWork), runFunc_(runFunc)
110 {};
111
112 TestThread() = delete;
~TestThread()113 ~TestThread(){};
114
115 bool ReadyToWork() override;
116
117 int data_;
118 int priority_;
119 std::string name_;
120 protected:
121 bool Run() override;
122
123 private:
124 bool readyToWork_;
125 ThreadRunFunc runFunc_;
126 };
127
ReadyToWork()128 bool TestThread::ReadyToWork()
129 {
130 return readyToWork_;
131 }
132
Run()133 bool TestThread::Run()
134 {
135 priority_ = getpriority(PRIO_PROCESS, 0);
136 char threadName[MAX_THREAD_NAME_LEN] = {0};
137 prctl(PR_GET_NAME, threadName, 0, 0);
138 name_ = threadName;
139
140 if (runFunc_ != nullptr) {
141 return (*runFunc_)(data_);
142 }
143
144 return false;
145 }
146
147 /*
148 * @tc.name: testThread001
149 * @tc.desc: ThreadTest
150 */
151 HWTEST_F(UtilsThreadTest, testThread001, TestSize.Level1)
152 {
153 times = 0;
154 std::unique_ptr<TestThread> test = std::make_unique<TestThread>(0, false, TestRun01);
155 ThreadStatus status = test->Start("test_thread_01", THREAD_PROI_LOW, 1024);
156 EXPECT_EQ(status == ThreadStatus::OK, true);
157
158 pthread_t thread = test->GetThread();
159
160 // pthread_equal return non-zero if equal
161 EXPECT_EQ(pthread_equal(thread ,-1) != 0, (test->IsRunning() ? false : true));
162
163 // ReadyToWork return false, RUN will not be called!
164 EXPECT_EQ(test->priority_, DEFAULT_PRIO);
165 EXPECT_EQ(test->name_, DEFAULT_THREAD_NAME);
166
167 // get stacksize of threa, may be different because of system memory align
168
169 EXPECT_EQ(test->data_, 0);
170 EXPECT_EQ(times, 0);
171 test->NotifyExitSync();
172 sleep(1);
173 EXPECT_EQ(pthread_equal(test->GetThread() ,-1) != 0, (test->IsRunning() ? false : true));
174 }
175
176 /*
177 * @tc.name: testThread002
178 * @tc.desc: ThreadTest
179 */
180 HWTEST_F(UtilsThreadTest, testThread002, TestSize.Level1)
181 {
182 times = 0;
183 std::unique_ptr<TestThread> test = std::make_unique<TestThread>(0, true, TestRun01);
184 ThreadStatus status = test->Start("test_thread_02", THREAD_PROI_LOW, 1024);
185
186 EXPECT_EQ(status == ThreadStatus::OK, true);
187
188 sleep(1); // let the new thread has chance to run
189
190 // pthread_equal return non-zero if equal, RUN return false,may exit already
191 EXPECT_EQ(pthread_equal(test->GetThread() ,-1) != 0, (test->IsRunning() ? false : true));
192
193 // ReadyToWork return true, RUN will be called!
194 EXPECT_EQ(test->priority_, THREAD_PROI_LOW);
195 EXPECT_EQ(test->name_, "test_thread_02");
196
197 EXPECT_EQ(test->data_, 1);
198 EXPECT_EQ(times, 0);
199 test->NotifyExitSync();
200 sleep(1);
201 EXPECT_EQ(pthread_equal(test->GetThread() ,-1) != 0, (test->IsRunning() ? false : true));
202 }
203
204 /*
205 * @tc.name: testThread003
206 * @tc.desc: ThreadTest
207 */
208 HWTEST_F(UtilsThreadTest, testThread003, TestSize.Level1)
209 {
210 times = 0;
211 std::unique_ptr<TestThread> test = std::make_unique<TestThread>(0, false, TestRun02);
212 ThreadStatus status = test->Start("test_thread_03", THREAD_PROI_LOW, 1024);
213 EXPECT_EQ(status == ThreadStatus::OK, true);
214
215 pthread_t thread = test->GetThread();
216
217 // pthread_equal return non-zero if equal
218 EXPECT_EQ(pthread_equal(thread ,-1) != 0, (test->IsRunning() ? false : true));
219
220 // ReadyToWork return false, RUN will not be called!
221 EXPECT_EQ(test->priority_, DEFAULT_PRIO);
222 EXPECT_EQ(test->name_, DEFAULT_THREAD_NAME);
223
224 EXPECT_EQ(test->data_, 0);
225 EXPECT_EQ(times, 0);
226 test->NotifyExitSync();
227 sleep(1);
228 EXPECT_EQ(pthread_equal(test->GetThread() ,-1) != 0, (test->IsRunning() ? false : true));
229 }
230
231 /*
232 * @tc.name: testThread004
233 * @tc.desc: ThreadTest
234 */
235 HWTEST_F(UtilsThreadTest, testThread004, TestSize.Level1)
236 {
237 times = 0;
238 std::unique_ptr<TestThread> test = std::make_unique<TestThread>(0, true, TestRun02);
239 ThreadStatus status = test->Start("test_thread_04", THREAD_PROI_LOW, 1024);
240
241 EXPECT_EQ(status == ThreadStatus::OK, true);
242
243 sleep(1); // let the new thread has chance to run
244
245 // pthread_equal return non-zero if equal, RUN return false,may exit already
246 EXPECT_EQ(pthread_equal(test->GetThread() ,-1) != 0, (test->IsRunning() ? false : true));
247
248 // ReadyToWork return true, RUN will be called!
249 EXPECT_EQ(test->priority_, THREAD_PROI_LOW);
250 EXPECT_EQ(test->name_, "test_thread_04");
251
252 EXPECT_GT(test->data_, 1);
253 EXPECT_EQ(times, 0);
254 test->NotifyExitSync();
255 sleep(1);
256 EXPECT_EQ(pthread_equal(test->GetThread() ,-1) != 0, (test->IsRunning() ? false : true));
257 }
258
259 /*
260 * @tc.name: testThread005
261 * @tc.desc: ThreadTest
262 */
263 HWTEST_F(UtilsThreadTest, testThread005, TestSize.Level1)
264 {
265 times = 0;
266 std::unique_ptr<TestThread> test = std::make_unique<TestThread>(0, false, TestRun03);
267 ThreadStatus status = test->Start("test_thread_05", THREAD_PROI_LOW, 1024);
268 EXPECT_EQ(status == ThreadStatus::OK, true);
269
270 pthread_t thread = test->GetThread();
271
272 // pthread_equal return non-zero if equal
273 EXPECT_EQ(pthread_equal(thread ,-1) != 0, (test->IsRunning() ? false : true));
274
275 // ReadyToWork return false, RUN will not be called!
276 EXPECT_EQ(test->priority_, DEFAULT_PRIO);
277 EXPECT_EQ(test->name_, DEFAULT_THREAD_NAME);
278
279 EXPECT_EQ(test->data_, 0);
280 EXPECT_EQ(times, 0);
281 test->NotifyExitSync();
282 sleep(1);
283 EXPECT_EQ(pthread_equal(test->GetThread() ,-1) != 0, (test->IsRunning() ? false : true));
284 }
285
286 /*
287 * @tc.name: testThread006
288 * @tc.desc: ThreadTest
289 */
290 HWTEST_F(UtilsThreadTest, testThread006, TestSize.Level1)
291 {
292 times = 0;
293 std::unique_ptr<TestThread> test = std::make_unique<TestThread>(0, true, TestRun03);
294 ThreadStatus status = test->Start("test_thread_06", THREAD_PROI_LOW, 1024);
295
296 EXPECT_EQ(status == ThreadStatus::OK, true);
297
298 sleep(1); // let the new thread has chance to run
299
300 // pthread_equal return non-zero if equal, RUN return false,may exit already
301 EXPECT_EQ(pthread_equal(test->GetThread() ,-1) != 0, (test->IsRunning() ? false : true));
302
303 // ReadyToWork return true, RUN will be called!
304 EXPECT_EQ(test->priority_, THREAD_PROI_LOW);
305 EXPECT_EQ(test->name_, "test_thread_06");
306
307 EXPECT_GT(test->data_, 10);
308 EXPECT_EQ(times, 0);
309
310 times = 100;
311 EXPECT_GT(test->data_, 10);
312
313 sleep(1); // let the new thread has chance to run
314
315 // times > 10, TestRun03 return false, thread exit
316 EXPECT_EQ(pthread_equal(test->GetThread() ,-1) != 0, (test->IsRunning() ? false : true));
317 }
318
319