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> 20using namespace testing::ext; 21using namespace std; 22 23namespace OHOS { 24namespace { 25static int times = 0; 26using ThreadRunFunc = bool (*)(int& data); 27 28class UtilsThreadTest : public testing::Test { 29public: 30 static void SetUpTestCase(void); 31 static void TearDownTestCase(void); 32 void SetUp(); 33 void TearDown(); 34}; 35 36void UtilsThreadTest::SetUpTestCase(void) 37{ 38 // input testsuit setup step 39} 40 41void UtilsThreadTest::TearDownTestCase(void) 42{ 43 // input testsuit teardown step 44} 45 46void UtilsThreadTest::SetUp(void) 47{ 48 // recover times 49 times = 0; 50} 51 52void UtilsThreadTest::TearDown(void) 53{ 54 // recover times 55 times = 0; 56} 57 58bool TestRun01(int& data) 59{ 60 ++data; 61 return false; 62} 63 64bool TestRun02(int& data) 65{ 66 ++data; 67 return true; 68} 69 70bool 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 81constexpr int DEFAULT_PRIO = 0; 82const std::string& DEFAULT_THREAD_NAME = "default"; 83 84class TestThread : public OHOS::Thread { 85public: 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; 91 ~TestThread() {} 92 93 bool ReadyToWork() override; 94 95 int data_; 96 int priority_; 97 std::string name_; 98protected: 99 bool Run() override; 100 101private: 102 bool readyToWork_; 103 ThreadRunFunc runFunc_; 104}; 105 106bool TestThread::ReadyToWork() 107{ 108 return readyToWork_; 109} 110 111bool 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 */ 129HWTEST_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 */ 157HWTEST_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 */ 185HWTEST_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 */ 212HWTEST_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 */ 240HWTEST_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 */ 267HWTEST_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 */ 300HWTEST_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 */ 324HWTEST_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 342class TestThread2 : public OHOS::Thread { 343public: 344 TestThread2(const int data, ThreadRunFunc runFunc) 345 : data_(data), priority_(DEFAULT_PRIO), name_(DEFAULT_THREAD_NAME), runFunc_(runFunc) 346 {}; 347 348 TestThread2() = delete; 349 ~TestThread2() {} 350 351 int data_; 352 int priority_; 353 std::string name_; 354protected: 355 bool Run() override; 356 357private: 358 ThreadRunFunc runFunc_; 359}; 360 361bool 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 */ 379HWTEST_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