1 #include <algorithm> 2 #include <chrono> 3 #include <cstdlib> 4 #include <fstream> 5 #include <gtest/gtest.h> 6 #include <memory> 7 #include <pthread.h> 8 #include <regex> 9 #include <thread> 10 #include <threads.h> 11 12 using namespace testing::ext; 13 14 #define TS_PER_T 1000000000 15 constexpr int USLEEP_TIME = 1000; 16 17 class ThreadRwlockTest : public testing::Test { SetUp()18 void SetUp() override {} TearDown()19 void TearDown() override {} 20 }; 21 22 class RwlockHandleControl { 23 public: RwlockHandleControl(std::function<int (pthread_rwlock_t *)> mLock_function,bool mFlag=false,pid_t mTid=0,std::function<int (pthread_rwlock_t *)> mTrylock_function=& pthread_rwlock_trywrlock)24 explicit RwlockHandleControl(std::function<int(pthread_rwlock_t*)> mLock_function, bool mFlag = false, 25 pid_t mTid = 0, std::function<int(pthread_rwlock_t*)> mTrylock_function = &pthread_rwlock_trywrlock) 26 { 27 wrLockTestFunc_ = mLock_function; 28 timeoutFlag_ = mFlag; 29 tid_ = mTid; 30 tryWrLockTestFunc_ = mTrylock_function; 31 }; 32 RwlockHandleControl(std::function<int (pthread_rwlock_t *,const timespec *)> mTimedLockFunction,clockid_t mClock,bool mFlag=true,pid_t mTid=0,std::function<int (pthread_rwlock_t *)> mTrylock_function=& pthread_rwlock_trywrlock)33 RwlockHandleControl(std::function<int(pthread_rwlock_t*, const timespec*)> mTimedLockFunction, clockid_t mClock, 34 bool mFlag = true, pid_t mTid = 0, 35 std::function<int(pthread_rwlock_t*)> mTrylock_function = &pthread_rwlock_trywrlock) 36 { 37 wrLockTestTimedFunc_ = mTimedLockFunction; 38 clock_ = mClock; 39 timeoutFlag_ = mFlag; 40 tid_ = mTid; 41 tryWrLockTestFunc_ = mTrylock_function; 42 }; 43 ~RwlockHandleControl()44 ~RwlockHandleControl() 45 { 46 tryWrLockTestFunc_ = nullptr; 47 wrLockTestFunc_ = nullptr; 48 wrLockTestTimedFunc_ = nullptr; 49 }; 50 PthreadRwlockWakeupHelper(RwlockHandleControl * arg)51 static void PthreadRwlockWakeupHelper(RwlockHandleControl* arg) 52 { 53 ASSERT_NE(nullptr, arg); 54 arg->tid_ = gettid(); 55 EXPECT_EQ(EBUSY, arg->tryWrLockTestFunc_(&arg->lock_)); 56 EXPECT_EQ(0, arg->wrLockTestFunc_(&arg->lock_)); 57 EXPECT_EQ(0, pthread_rwlock_unlock(&arg->lock_)); 58 }; 59 PthreadRwlockTimeoutHelper(RwlockHandleControl * arg)60 static void PthreadRwlockTimeoutHelper(RwlockHandleControl* arg) 61 { 62 ASSERT_NE(nullptr, arg); 63 arg->tid_ = gettid(); 64 EXPECT_EQ(EBUSY, arg->tryWrLockTestFunc_(&arg->lock_)); 65 timespec times {}; 66 EXPECT_EQ(0, clock_gettime(arg->clock_, ×)); 67 EXPECT_EQ(ETIMEDOUT, arg->wrLockTestTimedFunc_(&arg->lock_, ×)); 68 times.tv_nsec = -1; 69 EXPECT_EQ(EINVAL, arg->wrLockTestTimedFunc_(&arg->lock_, ×)); 70 times.tv_nsec = TS_PER_T; 71 EXPECT_EQ(EINVAL, arg->wrLockTestTimedFunc_(&arg->lock_, ×)); 72 EXPECT_EQ(0, clock_gettime(arg->clock_, ×)); 73 times.tv_sec += 1; 74 EXPECT_EQ(ETIMEDOUT, arg->wrLockTestTimedFunc_(&arg->lock_, ×)); 75 }; 76 WaitThreadSleep(pid_t & tid)77 static inline void WaitThreadSleep(pid_t& tid) 78 { 79 while (tid == 0) { 80 usleep(USLEEP_TIME); 81 } 82 std::string filename = "/proc/" + std::to_string(tid) + "/stat"; 83 std::regex regex { "\\s+S\\s+" }; 84 while (true) { 85 std::ifstream file(filename); 86 std::string content((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>()); 87 if (std::regex_search(content, regex)) { 88 break; 89 } 90 usleep(USLEEP_TIME); 91 } 92 } 93 TestPthreadRwlockWakeupWriter(RwlockHandleControl * arg)94 static void TestPthreadRwlockWakeupWriter(RwlockHandleControl* arg) 95 { 96 ASSERT_NE(nullptr, arg); 97 EXPECT_EQ(0, pthread_rwlock_init(&arg->lock_, nullptr)); 98 pthread_t thread; 99 if (!arg->timeoutFlag_) { 100 EXPECT_EQ(0, pthread_rwlock_rdlock(&arg->lock_)); 101 EXPECT_EQ(0, 102 pthread_create(&thread, nullptr, reinterpret_cast<void* (*)(void*)>(PthreadRwlockWakeupHelper), arg)); 103 WaitThreadSleep(arg->tid_); 104 EXPECT_EQ(0, pthread_rwlock_unlock(&arg->lock_)); 105 EXPECT_EQ(0, pthread_join(thread, nullptr)); 106 } else { 107 EXPECT_EQ(0, pthread_rwlock_wrlock(&arg->lock_)); 108 EXPECT_EQ(0, 109 pthread_create(&thread, nullptr, reinterpret_cast<void* (*)(void*)>(PthreadRwlockTimeoutHelper), arg)); 110 WaitThreadSleep(arg->tid_); 111 EXPECT_EQ(0, pthread_join(thread, nullptr)); 112 EXPECT_EQ(0, pthread_rwlock_unlock(&arg->lock_)); 113 } 114 EXPECT_EQ(0, pthread_rwlock_destroy(&arg->lock_)); 115 }; 116 117 private: 118 pthread_rwlock_t lock_; 119 bool timeoutFlag_; 120 clockid_t clock_; 121 pid_t tid_; 122 std::function<int(pthread_rwlock_t*)> tryWrLockTestFunc_; 123 std::function<int(pthread_rwlock_t*)> wrLockTestFunc_; 124 std::function<int(pthread_rwlock_t*, const timespec*)> wrLockTestTimedFunc_; 125 }; 126 127 /** 128 * @tc.name: pthread_rwlock_wrlock_001 129 * @tc.desc: Set up a sleep thread to test the normal use of this interface in the current scenario 130 * @tc.type: FUNC 131 * */ 132 HWTEST_F(ThreadRwlockTest, pthread_rwlock_wrlock_001, TestSize.Level1) 133 { 134 RwlockHandleControl* rhc = new RwlockHandleControl(&pthread_rwlock_wrlock); 135 RwlockHandleControl::TestPthreadRwlockWakeupWriter(rhc); 136 delete (rhc); 137 rhc = nullptr; 138 } 139 140 /** 141 * @tc.name: pthread_rwlock_timedwrlock_001 142 * @tc.desc: Set the waiting time based on the CLOCK_REALTIME clock for this interface to determine its normal operation 143 * in the sleep thread 144 * @tc.type: FUNC 145 * */ 146 HWTEST_F(ThreadRwlockTest, pthread_rwlock_timedwrlock_001, TestSize.Level1) 147 { 148 timespec times; 149 EXPECT_EQ(0, clock_gettime(CLOCK_REALTIME, ×)); 150 times.tv_sec += 1; 151 RwlockHandleControl* rhc = __anon3bc1845b0102(pthread_rwlock_t* rwlock) 152 new RwlockHandleControl([&](pthread_rwlock_t* rwlock) { return pthread_rwlock_timedwrlock(rwlock, ×); }); 153 RwlockHandleControl::TestPthreadRwlockWakeupWriter(rhc); 154 delete (rhc); 155 rhc = nullptr; 156 } 157 158 /** 159 * @tc.name: pthread_rwlock_timedwrlock_monotonic_np_001 160 * @tc.desc: Set the negative timeout time of the CLOCK_MONOTONIC clock as the function to determine whether the return 161 * is invalid, set the large timeout time of the CLOCK_MONOTONIC clock as the function to determine whether 162 * the return is invalid, and set the normal timeout time of the CLOCK_MONOTONIC clock as the function to 163 * determine whether the return is successful 164 * @tc.type: FUNC 165 * */ 166 HWTEST_F(ThreadRwlockTest, pthread_rwlock_timedwrlock_monotonic_np_001, TestSize.Level1) 167 { 168 RwlockHandleControl* rhc = new RwlockHandleControl(&pthread_rwlock_timedwrlock_monotonic_np, CLOCK_MONOTONIC); 169 RwlockHandleControl::TestPthreadRwlockWakeupWriter(rhc); 170 delete (rhc); 171 rhc = nullptr; 172 } 173 174 /** 175 * @tc.name: pthread_rwlock_timedwrlock_monotonic_np_002 176 * @tc.desc: Set the waiting time based on the CLOCK_MONOTONIC clock for this interface to determine its normal 177 * operation in the sleep thread 178 * @tc.type: FUNC 179 * */ 180 HWTEST_F(ThreadRwlockTest, pthread_rwlock_timedwrlock_monotonic_np_002, TestSize.Level1) 181 { 182 timespec times; 183 EXPECT_EQ(0, clock_gettime(CLOCK_MONOTONIC, ×)); 184 times.tv_sec += 1; 185 RwlockHandleControl* rhc = new RwlockHandleControl( __anon3bc1845b0202(pthread_rwlock_t* rwlock) 186 [&](pthread_rwlock_t* rwlock) { return pthread_rwlock_timedwrlock_monotonic_np(rwlock, ×); }); 187 RwlockHandleControl::TestPthreadRwlockWakeupWriter(rhc); 188 delete (rhc); 189 rhc = nullptr; 190 } 191 192 /** 193 * @tc.name: pthread_rwlock_clockwrlock_001 194 * @tc.desc: 1.Set the waiting time based on the CLOCK_MONOTONIC clock for this interface to determine its normal 195 * operation in the sleep thread. 196 * @tc.type: FUNC 197 * */ 198 HWTEST_F(ThreadRwlockTest, pthread_rwlock_clockwrlock_001, TestSize.Level1) 199 { 200 timespec times; 201 EXPECT_EQ(0, clock_gettime(CLOCK_MONOTONIC, ×)); 202 times.tv_sec += 1; 203 RwlockHandleControl* rhcMonotonic = new RwlockHandleControl( __anon3bc1845b0302(pthread_rwlock_t* rwlock) 204 [&](pthread_rwlock_t* rwlock) { return pthread_rwlock_clockwrlock(rwlock, CLOCK_MONOTONIC, ×); }); 205 delete (rhcMonotonic); 206 rhcMonotonic = nullptr; 207 } 208 209 /** 210 * @tc.name: pthread_rwlock_clockwrlock_002 211 * @tc.desc: Set the waiting time based on the CLOCK_REALTIME clock for this interface to determine its normal 212 * operation in the sleep thread. 213 * @tc.type: FUNC 214 * */ 215 HWTEST_F(ThreadRwlockTest, pthread_rwlock_clockwrlock_002, TestSize.Level1) 216 { 217 timespec times; 218 EXPECT_EQ(0, clock_gettime(CLOCK_REALTIME, ×)); 219 times.tv_sec += 1; 220 RwlockHandleControl* rhcRealtime = new RwlockHandleControl( __anon3bc1845b0402(pthread_rwlock_t* rwlock) 221 [&](pthread_rwlock_t* rwlock) { return pthread_rwlock_clockwrlock(rwlock, CLOCK_REALTIME, ×); }); 222 delete (rhcRealtime); 223 rhcRealtime = nullptr; 224 } 225 226 /** 227 * @tc.name: pthread_rwlock_clockwrlock_003 228 * @tc.desc: Testing the function with invalid locks returns invalid 229 * @tc.type: FUNC 230 * */ 231 HWTEST_F(ThreadRwlockTest, pthread_rwlock_clockwrlock_003, TestSize.Level1) 232 { 233 pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER; 234 timespec times; 235 EXPECT_EQ(EINVAL, pthread_rwlock_clockwrlock(&rwlock, CLOCK_THREAD_CPUTIME_ID, ×)); 236 } 237 238 /** 239 * @tc.name: pthread_rwlock_timedrdlock_001 240 * @tc.desc: Set the negative timeout time of the CLOCK_REALTIME clock as the function to determine whether the return 241 * is invalid, set the large timeout time of the CLOCK_REALTIME clock as the function to determine whether 242 * the return is invalid, and set the normal timeout time of the CLOCK_REALTIME clock as the function to 243 * determine whether the return is successful 244 * @tc.type: FUNC 245 * */ 246 HWTEST_F(ThreadRwlockTest, pthread_rwlock_timedrdlock_001, TestSize.Level1) 247 { 248 RwlockHandleControl* rhc = new RwlockHandleControl(&pthread_rwlock_timedrdlock, CLOCK_REALTIME); 249 RwlockHandleControl::TestPthreadRwlockWakeupWriter(rhc); 250 delete (rhc); 251 rhc = nullptr; 252 } 253 254 /** 255 * @tc.name: pthread_rwlock_timedrdlock_monotonic_np_001 256 * @tc.desc: Set the negative timeout time of the CLOCK_MONOTONIC clock as the function to determine whether the return 257 * is invalid, set the large timeout time of the CLOCK_MONOTONIC clock as the function to determine whether 258 * the return is invalid, and set the normal timeout time of the CLOCK_MONOTONIC clock as the function to 259 * determine whether the return is successful 260 * @tc.type: FUNC 261 * */ 262 HWTEST_F(ThreadRwlockTest, pthread_rwlock_timedrdlock_monotonic_np_001, TestSize.Level1) 263 { 264 RwlockHandleControl* rhc = new RwlockHandleControl(&pthread_rwlock_timedrdlock_monotonic_np, CLOCK_MONOTONIC); 265 RwlockHandleControl::TestPthreadRwlockWakeupWriter(rhc); 266 delete (rhc); 267 rhc = nullptr; 268 } 269 270 /** 271 * @tc.name: pthread_rwlock_timedrdlock_monotonic_np_002 272 * @tc.desc: Set the waiting time based on the CLOCK_MONOTONIC clock for this interface to determine its normal 273 * operation in the sleep thread 274 * @tc.type: FUNC 275 * */ 276 HWTEST_F(ThreadRwlockTest, pthread_rwlock_timedrdlock_monotonic_np_002, TestSize.Level1) 277 { 278 timespec times; 279 EXPECT_EQ(0, clock_gettime(CLOCK_MONOTONIC, ×)); 280 times.tv_sec += 1; 281 RwlockHandleControl* rhcMonotonic = new RwlockHandleControl( __anon3bc1845b0502(pthread_rwlock_t* rwlock) 282 [&](pthread_rwlock_t* rwlock) { return pthread_rwlock_timedrdlock_monotonic_np(rwlock, ×); }); 283 delete (rhcMonotonic); 284 rhcMonotonic = nullptr; 285 } 286 287 /** 288 * @tc.name: pthread_rwlock_clockrdlock_001 289 * @tc.desc: Set the negative timeout time of the CLOCK_MONOTONIC clock as the function to determine whether the return 290 * is invalid, set the large timeout time of the CLOCK_MONOTONIC clock as the function to determine whether 291 * the return is invalid, and set the normal timeout time of the CLOCK_MONOTONIC clock as the function to 292 * determine whether the return is successful 293 * @tc.type: FUNC 294 * */ 295 HWTEST_F(ThreadRwlockTest, pthread_rwlock_clockrdlock_001, TestSize.Level1) 296 { 297 RwlockHandleControl* rhc = new RwlockHandleControl( __anon3bc1845b0602(pthread_rwlock_t* __rwlock, const timespec* __timeout) 298 [&](pthread_rwlock_t* __rwlock, const timespec* __timeout) { 299 return pthread_rwlock_clockrdlock(__rwlock, CLOCK_MONOTONIC, __timeout); 300 }, 301 CLOCK_MONOTONIC); 302 RwlockHandleControl::TestPthreadRwlockWakeupWriter(rhc); 303 delete (rhc); 304 rhc = nullptr; 305 } 306 307 /** 308 * @tc.name: pthread_rwlock_clockrdlock_002 309 * @tc.desc: Set the negative timeout time of the CLOCK_REALTIME clock as the function to determine whether the return 310 * is invalid, set the large timeout time of the CLOCK_REALTIME clock as the function to determine whether the 311 * return is invalid, and set the normal timeout time of the CLOCK_REALTIME clock as the function to determine 312 * whether the return is successful 313 * @tc.type: FUNC 314 * */ 315 HWTEST_F(ThreadRwlockTest, pthread_rwlock_clockrdlock_002, TestSize.Level1) 316 { 317 RwlockHandleControl* rhc = new RwlockHandleControl( __anon3bc1845b0702(pthread_rwlock_t* __rwlock, const timespec* __timeout) 318 [&](pthread_rwlock_t* __rwlock, const timespec* __timeout) { 319 return pthread_rwlock_clockrdlock(__rwlock, CLOCK_REALTIME, __timeout); 320 }, 321 CLOCK_REALTIME); 322 RwlockHandleControl::TestPthreadRwlockWakeupWriter(rhc); 323 delete (rhc); 324 rhc = nullptr; 325 } 326 327 /** 328 * @tc.name: pthread_rwlock_clockrdlock_003 329 * @tc.desc: Testing the function with invalid locks returns invalid 330 * @tc.type: FUNC 331 * */ 332 HWTEST_F(ThreadRwlockTest, pthread_rwlock_clockrdlock_003, TestSize.Level1) 333 { 334 pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER; 335 timespec times; 336 EXPECT_EQ(EINVAL, pthread_rwlock_clockrdlock(&rwlock, CLOCK_THREAD_CPUTIME_ID, ×)); 337 } 338 339 /** 340 * @tc.name: pthread_rwlock_001 341 * @tc.desc: Single read rwlock: obtaining read rwlock and unlocking. 342 * @tc.type: FUNC 343 * */ 344 HWTEST_F(ThreadRwlockTest, pthread_rwlock_001, TestSize.Level1) 345 { 346 pthread_rwlock_t wrLock; 347 EXPECT_EQ(0, pthread_rwlock_init(&wrLock, nullptr)); 348 EXPECT_EQ(0, pthread_rwlock_rdlock(&wrLock)); 349 EXPECT_EQ(0, pthread_rwlock_unlock(&wrLock)); 350 EXPECT_EQ(0, pthread_rwlock_destroy(&wrLock)); 351 } 352 353 /** 354 * @tc.name: pthread_rwlock_002 355 * @tc.desc: Multiple read locks: Continuously acquire multiple read locks and unlock them. 356 * @tc.type: FUNC 357 * */ 358 HWTEST_F(ThreadRwlockTest, pthread_rwlock_002, TestSize.Level1) 359 { 360 pthread_rwlock_t wrLock; 361 EXPECT_EQ(0, pthread_rwlock_init(&wrLock, nullptr)); 362 EXPECT_EQ(0, pthread_rwlock_rdlock(&wrLock)); 363 EXPECT_EQ(0, pthread_rwlock_rdlock(&wrLock)); 364 EXPECT_EQ(0, pthread_rwlock_unlock(&wrLock)); 365 EXPECT_EQ(0, pthread_rwlock_unlock(&wrLock)); 366 EXPECT_EQ(0, pthread_rwlock_destroy(&wrLock)); 367 } 368 369 /** 370 * @tc.name: pthread_rwlock_003 371 * @tc.desc: Write rwlock: Obtain the write rwlock and unlock it. 372 * @tc.type: FUNC 373 * */ 374 HWTEST_F(ThreadRwlockTest, pthread_rwlock_003, TestSize.Level1) 375 { 376 pthread_rwlock_t wrLock; 377 EXPECT_EQ(0, pthread_rwlock_init(&wrLock, nullptr)); 378 EXPECT_EQ(0, pthread_rwlock_wrlock(&wrLock)); 379 EXPECT_EQ(0, pthread_rwlock_unlock(&wrLock)); 380 EXPECT_EQ(0, pthread_rwlock_destroy(&wrLock)); 381 } 382 383 /** 384 * @tc.name: pthread_rwlock_004 385 * @tc.desc: Attempt to write rwlock: Attempt to obtain the write rwlock. The first successful attempt, the second 386 * attempt, and the attempt to read the rwlock should all return EBUSY. 387 * @tc.type: FUNC 388 * */ 389 HWTEST_F(ThreadRwlockTest, pthread_rwlock_004, TestSize.Level1) 390 { 391 pthread_rwlock_t wrLock; 392 EXPECT_EQ(0, pthread_rwlock_init(&wrLock, nullptr)); 393 EXPECT_EQ(0, pthread_rwlock_trywrlock(&wrLock)); 394 EXPECT_EQ(EBUSY, pthread_rwlock_trywrlock(&wrLock)); 395 EXPECT_EQ(EBUSY, pthread_rwlock_tryrdlock(&wrLock)); 396 EXPECT_EQ(0, pthread_rwlock_unlock(&wrLock)); 397 EXPECT_EQ(0, pthread_rwlock_destroy(&wrLock)); 398 } 399 400 /** 401 * @tc.name: pthread_rwlock_005 402 * @tc.desc: Attempt to read rwlock: Attempt to obtain read rwlock, successful first and second attempts, attempt to 403 * write rwlock should return EBUSY, and then unlock twice. 404 * Obtain write rwlock: After unlocking, obtain the write rwlock again, which should be successful and 405 * immediately unlocked. 406 * @tc.type: FUNC 407 * */ 408 HWTEST_F(ThreadRwlockTest, pthread_rwlock_005, TestSize.Level1) 409 { 410 pthread_rwlock_t wrLock; 411 EXPECT_EQ(0, pthread_rwlock_init(&wrLock, nullptr)); 412 EXPECT_EQ(0, pthread_rwlock_tryrdlock(&wrLock)); 413 EXPECT_EQ(0, pthread_rwlock_tryrdlock(&wrLock)); 414 EXPECT_EQ(EBUSY, pthread_rwlock_trywrlock(&wrLock)); 415 EXPECT_EQ(0, pthread_rwlock_unlock(&wrLock)); 416 EXPECT_EQ(0, pthread_rwlock_unlock(&wrLock)); 417 EXPECT_EQ(0, pthread_rwlock_wrlock(&wrLock)); 418 EXPECT_EQ(0, pthread_rwlock_unlock(&wrLock)); 419 EXPECT_EQ(0, pthread_rwlock_destroy(&wrLock)); 420 } 421 422 /** 423 * @tc.name: pthread_rwlockattr_001 424 * @tc.desc: Determine whether the set shared attribute is equal to the obtained shared attribute 425 * @tc.type: FUNC 426 * */ 427 HWTEST_F(ThreadRwlockTest, pthread_rwlockattr_001, TestSize.Level1) 428 { 429 pthread_rwlockattr_t rwlockAttr; 430 int pthreadShared; 431 EXPECT_EQ(0, pthread_rwlockattr_init(&rwlockAttr)); 432 EXPECT_EQ(0, pthread_rwlockattr_setpshared(&rwlockAttr, PTHREAD_PROCESS_PRIVATE)); 433 EXPECT_EQ(0, pthread_rwlockattr_getpshared(&rwlockAttr, &pthreadShared)); 434 EXPECT_EQ(PTHREAD_PROCESS_PRIVATE, pthreadShared); 435 EXPECT_EQ(0, pthread_rwlockattr_setpshared(&rwlockAttr, PTHREAD_PROCESS_SHARED)); 436 EXPECT_EQ(0, pthread_rwlockattr_getpshared(&rwlockAttr, &pthreadShared)); 437 EXPECT_EQ(PTHREAD_PROCESS_SHARED, pthreadShared); 438 EXPECT_EQ(0, pthread_rwlockattr_destroy(&rwlockAttr)); 439 }