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