1 #include <gtest/gtest.h> 2 #include <pthread.h> 3 #include <thread> 4 #include <threads.h> 5 6 constexpr size_t TEST_SIZE = 65536; 7 constexpr size_t ENAVAIL_TIME = -100; 8 constexpr size_t USED_TIME = 2; 9 10 using namespace testing::ext; 11 12 class ThreadMutexTest : public testing::Test { 13 protected: 14 pthread_mutex_t mutex_; 15 mtx_t mtx_; 16 timespec timeSpec_; 17 InitMutex(int mutexType,int protocol)18 void InitMutex(int mutexType, int protocol) 19 { 20 pthread_mutexattr_t mutexAttr; 21 EXPECT_EQ(0, pthread_mutexattr_init(&mutexAttr)); 22 EXPECT_EQ(0, pthread_mutexattr_settype(&mutexAttr, mutexType)); 23 EXPECT_EQ(0, pthread_mutexattr_setprotocol(&mutexAttr, protocol)); 24 EXPECT_EQ(0, pthread_mutex_init(&mutex_, &mutexAttr)); 25 EXPECT_EQ(0, pthread_mutexattr_destroy(&mutexAttr)); 26 } 27 SetUp()28 void SetUp() override 29 { 30 EXPECT_EQ(0, pthread_mutex_init(&mutex_, nullptr)); 31 } 32 TearDown()33 void TearDown() override 34 { 35 EXPECT_EQ(0, pthread_mutex_destroy(&mutex_)); 36 } 37 }; 38 39 /** 40 * @tc.name: mtx_init_001 41 * @tc.desc: Determine mtx_plain Is the initial session successful in plain mode. 42 * @tc.type: FUNC 43 * */ 44 HWTEST_F(ThreadMutexTest, mtx_init_001, TestSize.Level1) 45 { 46 EXPECT_EQ(thrd_success, mtx_init(&mtx_, mtx_plain)); 47 mtx_destroy(&mtx_); 48 } 49 50 /** 51 * @tc.name: mtx_init_002 52 * @tc.desc: Determine mtx_timed Is initialization successful in timed mode. 53 * @tc.type: FUNC 54 * */ 55 HWTEST_F(ThreadMutexTest, mtx_init_002, TestSize.Level1) 56 { 57 EXPECT_EQ(thrd_success, mtx_init(&mtx_, mtx_timed)); 58 mtx_destroy(&mtx_); 59 } 60 61 /** 62 * @tc.name: mtx_init_003 63 * @tc.desc: Determine mtx_plain | mtx_recursive initialization successful in recursive mode. 64 * @tc.type: FUNC 65 * */ 66 HWTEST_F(ThreadMutexTest, mtx_init_003, TestSize.Level1) 67 { 68 EXPECT_EQ(thrd_success, mtx_init(&mtx_, mtx_plain | mtx_recursive)); 69 mtx_destroy(&mtx_); 70 } 71 72 /** 73 * @tc.name: mtx_init_004 74 * @tc.desc: Determine mtx_timed | mtx_recursive initialization was successful in recursive mode. 75 * @tc.type: FUNC 76 * */ 77 HWTEST_F(ThreadMutexTest, mtx_init_004, TestSize.Level1) 78 { 79 EXPECT_EQ(thrd_success, mtx_init(&mtx_, mtx_timed | mtx_recursive)); 80 mtx_destroy(&mtx_); 81 } 82 83 /** 84 * @tc.name: mtx_trylock_001 85 * @tc.desc: Mtx_plain initialize the lock in recursive mode and lock it. Use this function to return thrd_success. 86 * @tc.type: FUNC 87 * */ 88 HWTEST_F(ThreadMutexTest, mtx_trylock_001, TestSize.Level1) 89 { 90 EXPECT_EQ(thrd_success, mtx_init(&mtx_, mtx_plain)); 91 EXPECT_EQ(thrd_success, mtx_trylock(&mtx_)); 92 EXPECT_EQ(thrd_busy, mtx_trylock(&mtx_)); 93 EXPECT_EQ(thrd_success, mtx_unlock(&mtx_)); 94 EXPECT_EQ(thrd_success, mtx_lock(&mtx_)); 95 EXPECT_EQ(thrd_busy, mtx_trylock(&mtx_)); 96 EXPECT_EQ(thrd_success, mtx_unlock(&mtx_)); 97 mtx_destroy(&mtx_); 98 } 99 100 /** 101 * @tc.name: mtx_trylock_002 102 * @tc.desc: Mtx_plain | mtx_recursive the lock in recursive mode and lock it. Use this function to return thrd_ Success 103 * @tc.type: FUNC 104 * */ 105 HWTEST_F(ThreadMutexTest, mtx_trylock_002, TestSize.Level1) 106 { 107 EXPECT_EQ(thrd_success, mtx_init(&mtx_, mtx_plain | mtx_recursive)); 108 EXPECT_EQ(thrd_success, mtx_lock(&mtx_)); 109 EXPECT_EQ(thrd_success, mtx_trylock(&mtx_)); 110 EXPECT_EQ(thrd_success, mtx_unlock(&mtx_)); 111 EXPECT_EQ(thrd_success, mtx_unlock(&mtx_)); 112 mtx_destroy(&mtx_); 113 } 114 115 /** 116 * @tc.name: mtx_timedlock_001 117 * @tc.desc: 1. Do not set an interval to determine whether the returned joinResult is successful. 118 * 2. Set an extremely short time to determine its timeout 119 * @tc.type: FUNC 120 * */ 121 HWTEST_F(ThreadMutexTest, mtx_timedlock_001, TestSize.Level1) 122 { 123 mtx_t mtxTime; 124 EXPECT_EQ(thrd_success, mtx_init(&mtxTime, mtx_timed)); 125 EXPECT_EQ(thrd_success, mtx_timedlock(&mtxTime, &timeSpec_)); 126 __anon99b22a9c0102null127 std::thread([&mtxTime] { 128 EXPECT_EQ(thrd_success, mtx_init(&mtxTime, mtx_timed)); 129 timespec timeSpec = {}; 130 EXPECT_EQ(thrd_success, mtx_timedlock(&mtxTime, &timeSpec)); 131 132 timeSpec = { .tv_nsec = 1000000 }; 133 EXPECT_EQ(thrd_timedout, mtx_timedlock(&mtxTime, &timeSpec)); 134 }).join(); 135 136 EXPECT_EQ(thrd_success, mtx_unlock(&mtxTime)); 137 mtx_destroy(&mtxTime); 138 } 139 140 /** 141 * @tc.name: mtx_unlock_001 142 * @tc.desc: Judge whether the unlocking is successful under normal operation and whether it can be locked again after 143 * unlocking 144 * @tc.type: FUNC 145 * */ 146 HWTEST_F(ThreadMutexTest, mtx_unlock_001, TestSize.Level1) 147 { 148 mtx_t mtxUnlock; 149 EXPECT_EQ(thrd_success, mtx_init(&mtxUnlock, mtx_plain)); 150 EXPECT_EQ(thrd_success, mtx_lock(&mtxUnlock)); __anon99b22a9c0202null151 std::thread([&mtxUnlock] { EXPECT_EQ(thrd_busy, mtx_trylock(&mtxUnlock)); }).join(); 152 EXPECT_EQ(thrd_success, mtx_unlock(&mtxUnlock)); 153 mtx_destroy(&mtxUnlock); 154 } 155 156 /** 157 * @tc.name: pthread_mutex_001 158 * @tc.desc: Successfully created and used a large number of different pthread keys 159 * @tc.type: FUNC 160 * */ 161 HWTEST_F(ThreadMutexTest, pthread_mutex_001, TestSize.Level1) 162 { 163 std::vector<pthread_mutex_t> mutexes(TEST_SIZE); 164 for (auto& mutex : mutexes) { 165 EXPECT_EQ(0, pthread_mutex_init(&mutex, nullptr)); 166 EXPECT_EQ(0, pthread_mutex_lock(&mutex)); 167 EXPECT_EQ(0, pthread_mutex_unlock(&mutex)); 168 EXPECT_EQ(0, pthread_mutex_destroy(&mutex)); 169 } 170 mutexes.clear(); 171 } 172 173 /** 174 * @tc.name: pthread_mutex_timedlock_001 175 * @tc.desc: 1. Set the minimum timeout waiting time to obtain the lock return timeout. 176 * 2. Set the einval timeout waiting time to obtain the lock return einval. 177 * 3. Set the normal timeout waiting time to obtain the return lock normal. 178 * @tc.type: FUNC 179 * */ 180 HWTEST_F(ThreadMutexTest, pthread_mutex_timedlock_001, TestSize.Level1) 181 { 182 pthread_mutex_lock(&mutex_); 183 clock_gettime(CLOCK_REALTIME, &timeSpec_); 184 EXPECT_EQ(ETIMEDOUT, pthread_mutex_timedlock(&mutex_, &timeSpec_)); 185 timeSpec_.tv_nsec = ENAVAIL_TIME; 186 EXPECT_EQ(EINVAL, pthread_mutex_timedlock(&mutex_, &timeSpec_)); 187 pthread_mutex_unlock(&mutex_); 188 clock_gettime(CLOCK_REALTIME, &timeSpec_); 189 timeSpec_.tv_sec += USED_TIME; 190 EXPECT_EQ(0, pthread_mutex_timedlock(&mutex_, &timeSpec_)); 191 pthread_mutex_unlock(&mutex_); 192 } 193 194 /** 195 * @tc.name: pthread_mutex_timedlock_002 196 * @tc.desc: Verify the correctness of the pthread_mutex_timedlock, especially whether the ETIMEOUT error can be 197 * returned correctly when the waiting time expires. 198 * @tc.type: FUNC 199 * */ 200 HWTEST_F(ThreadMutexTest, pthread_mutex_timedlock_002, TestSize.Level1) 201 { 202 InitMutex(PTHREAD_MUTEX_NORMAL, PTHREAD_PRIO_INHERIT); 203 clock_gettime(CLOCK_REALTIME, &timeSpec_); 204 timeSpec_.tv_sec += 1; 205 EXPECT_EQ(0, pthread_mutex_timedlock(&mutex_, &timeSpec_)); __anon99b22a9c0302(void* arg) 206 auto timeLockThread = [](void* arg) -> void* { 207 if (arg == nullptr) { 208 return nullptr; 209 } 210 auto mutexArg = static_cast<pthread_mutex_t*>(arg); 211 timespec ts; 212 clock_gettime(CLOCK_REALTIME, &ts); 213 ts.tv_sec += 1; 214 intptr_t joinResult = pthread_mutex_timedlock(mutexArg, &ts); 215 return reinterpret_cast<void*>(joinResult); 216 }; 217 pthread_t thread; 218 pthread_create(&thread, nullptr, timeLockThread, &mutex_); 219 void* joinResult; 220 pthread_join(thread, &joinResult); 221 EXPECT_EQ(ETIMEDOUT, reinterpret_cast<intptr_t>(joinResult)); 222 } 223 224 /** 225 * @tc.name: pthread_mutex_timedlock_monotonic_np_001 226 * @tc.desc: 1. Set the minimum timeout waiting time to obtain the lock return timeout. 227 * 2. Set the einval timeout waiting time to obtain the lock return einval. 228 * 3. Set the normal timeout waiting time to obtain the return lock normal. 229 * @tc.type: FUNC 230 * */ 231 HWTEST_F(ThreadMutexTest, pthread_mutex_timedlock_monotonic_np_001, TestSize.Level1) 232 { 233 pthread_mutex_lock(&mutex_); 234 clock_gettime(CLOCK_MONOTONIC, &timeSpec_); 235 EXPECT_EQ(ETIMEDOUT, pthread_mutex_timedlock_monotonic_np(&mutex_, &timeSpec_)); 236 timeSpec_.tv_nsec = ENAVAIL_TIME; 237 EXPECT_EQ(EINVAL, pthread_mutex_timedlock_monotonic_np(&mutex_, &timeSpec_)); 238 pthread_mutex_unlock(&mutex_); 239 clock_gettime(CLOCK_MONOTONIC, &timeSpec_); 240 timeSpec_.tv_sec += USED_TIME; 241 EXPECT_EQ(0, pthread_mutex_timedlock_monotonic_np(&mutex_, &timeSpec_)); 242 pthread_mutex_unlock(&mutex_); 243 } 244 245 /** 246 * @tc.name: pthread_mutex_timedlock_monotonic_np_002 247 * @tc.desc: Verify the correctness of the pthread_mutex_timedlock_monotonic_np, especially whether the ETIMEOUT error 248 * can be returned correctly when the waiting time expires. 249 * @tc.type: FUNC 250 * */ 251 HWTEST_F(ThreadMutexTest, pthread_mutex_timedlock_monotonic_np_002, TestSize.Level1) 252 { 253 InitMutex(PTHREAD_MUTEX_NORMAL, PTHREAD_PRIO_INHERIT); 254 clock_gettime(CLOCK_MONOTONIC, &timeSpec_); 255 timeSpec_.tv_sec += 1; 256 EXPECT_EQ(0, pthread_mutex_timedlock_monotonic_np(&mutex_, &timeSpec_)); __anon99b22a9c0402(void* arg) 257 auto timeLockThread = [](void* arg) -> void* { 258 if (arg == nullptr) { 259 return nullptr; 260 } 261 auto mutexArg = static_cast<pthread_mutex_t*>(arg); 262 timespec ts; 263 clock_gettime(CLOCK_MONOTONIC, &ts); 264 ts.tv_sec += 1; 265 intptr_t joinResult = pthread_mutex_timedlock_monotonic_np(mutexArg, &ts); 266 return reinterpret_cast<void*>(joinResult); 267 }; 268 pthread_t thread; 269 pthread_create(&thread, nullptr, timeLockThread, &mutex_); 270 void* joinResult; 271 pthread_join(thread, &joinResult); 272 EXPECT_EQ(ETIMEDOUT, reinterpret_cast<intptr_t>(joinResult)); 273 } 274 275 /** 276 * @tc.name: pthread_mutex_clocklock_001 277 * @tc.desc: Under the same clock 278 * 1. Set the minimum timeout waiting time to obtain the lock return timeout. 279 * 2. Set the einval timeout waiting time to obtain the lock return einval. 280 * 3. Set the normal timeout waiting time to obtain the return lock normal. 281 * @tc.type: FUNC 282 * */ 283 HWTEST_F(ThreadMutexTest, pthread_mutex_clocklock_001, TestSize.Level1) 284 { 285 pthread_mutex_lock(&mutex_); 286 clock_gettime(CLOCK_MONOTONIC, &timeSpec_); 287 EXPECT_EQ(ETIMEDOUT, pthread_mutex_clocklock(&mutex_, CLOCK_MONOTONIC, &timeSpec_)); 288 timeSpec_.tv_nsec = ENAVAIL_TIME; 289 EXPECT_EQ(EINVAL, pthread_mutex_clocklock(&mutex_, CLOCK_MONOTONIC, &timeSpec_)); 290 pthread_mutex_unlock(&mutex_); 291 clock_gettime(CLOCK_MONOTONIC, &timeSpec_); 292 timeSpec_.tv_sec += USED_TIME; 293 EXPECT_EQ(0, pthread_mutex_clocklock(&mutex_, CLOCK_MONOTONIC, &timeSpec_)); 294 pthread_mutex_unlock(&mutex_); 295 } 296 297 /** 298 * @tc.name: pthread_mutex_clocklock_002 299 * @tc.desc: Under the same clock 300 * 1. Set the minimum timeout waiting time to obtain the lock return timeout. 301 * 2. Set the einval timeout waiting time to obtain the lock return einval. 302 * 3. Set the normal timeout waiting time to obtain the return lock normal 303 * @tc.type: FUNC 304 * */ 305 HWTEST_F(ThreadMutexTest, pthread_mutex_clocklock_002, TestSize.Level1) 306 { 307 pthread_mutex_lock(&mutex_); 308 clock_gettime(CLOCK_REALTIME, &timeSpec_); 309 EXPECT_EQ(ETIMEDOUT, pthread_mutex_clocklock(&mutex_, CLOCK_REALTIME, &timeSpec_)); 310 timeSpec_.tv_nsec = ENAVAIL_TIME; 311 EXPECT_EQ(EINVAL, pthread_mutex_clocklock(&mutex_, CLOCK_REALTIME, &timeSpec_)); 312 pthread_mutex_unlock(&mutex_); 313 clock_gettime(CLOCK_REALTIME, &timeSpec_); 314 timeSpec_.tv_sec += USED_TIME; 315 EXPECT_EQ(0, pthread_mutex_clocklock(&mutex_, CLOCK_REALTIME, &timeSpec_)); 316 pthread_mutex_unlock(&mutex_); 317 } 318 319 /** 320 * @tc.name: pthread_mutex_clocklock_003 321 * @tc.desc: Verify the correctness of the pthread_mutex_clocklock, especially whether the ETIMEOUT error can be 322 * returned correctly when the waiting time expires. 323 * @tc.type: FUNC 324 * */ 325 HWTEST_F(ThreadMutexTest, pthread_mutex_clocklock_003, TestSize.Level1) 326 { 327 InitMutex(PTHREAD_MUTEX_NORMAL, PTHREAD_PRIO_INHERIT); 328 clock_gettime(CLOCK_MONOTONIC, &timeSpec_); 329 timeSpec_.tv_sec += 1; 330 EXPECT_EQ(0, pthread_mutex_clocklock(&mutex_, CLOCK_MONOTONIC, &timeSpec_)); __anon99b22a9c0502(void* arg) 331 auto timeLockThread = [](void* arg) -> void* { 332 if (arg == nullptr) { 333 return nullptr; 334 } 335 auto mutexArg = static_cast<pthread_mutex_t*>(arg); 336 timespec ts; 337 clock_gettime(CLOCK_MONOTONIC, &ts); 338 ts.tv_sec += 1; 339 intptr_t joinResult = pthread_mutex_clocklock(mutexArg, CLOCK_MONOTONIC, &ts); 340 return reinterpret_cast<void*>(joinResult); 341 }; 342 pthread_t thread; 343 pthread_create(&thread, nullptr, timeLockThread, &mutex_); 344 void* joinResult; 345 pthread_join(thread, &joinResult); 346 EXPECT_EQ(ETIMEDOUT, reinterpret_cast<intptr_t>(joinResult)); 347 } 348 349 /** 350 * @tc.name: pthread_mutex_clocklock_004 351 * @tc.desc: Verify the correctness of the pthread_mutex_clocklock, especially whether the ETIMEOUT error can be 352 * returned correctly when the waiting time expires. 353 * @tc.type: FUNC 354 * */ 355 HWTEST_F(ThreadMutexTest, pthread_mutex_clocklock_004, TestSize.Level1) 356 { 357 InitMutex(PTHREAD_MUTEX_NORMAL, PTHREAD_PRIO_INHERIT); 358 clock_gettime(CLOCK_REALTIME, &timeSpec_); 359 timeSpec_.tv_sec += 1; 360 EXPECT_EQ(0, pthread_mutex_clocklock(&mutex_, CLOCK_REALTIME, &timeSpec_)); __anon99b22a9c0602(void* arg) 361 auto timeLockThread = [](void* arg) -> void* { 362 if (arg == nullptr) { 363 return nullptr; 364 } 365 auto mutexArg = static_cast<pthread_mutex_t*>(arg); 366 timespec ts; 367 clock_gettime(CLOCK_REALTIME, &ts); 368 ts.tv_sec += 1; 369 intptr_t joinResult = pthread_mutex_clocklock(mutexArg, CLOCK_REALTIME, &ts); 370 return reinterpret_cast<void*>(joinResult); 371 }; 372 pthread_t thread; 373 pthread_create(&thread, nullptr, timeLockThread, &mutex_); 374 void* joinResult; 375 pthread_join(thread, &joinResult); 376 EXPECT_EQ(ETIMEDOUT, reinterpret_cast<intptr_t>(joinResult)); 377 } 378 379 /** 380 * @tc.name: pthread_mutex_clocklock_005 381 * @tc.desc: Setting the wait time of thread lock with unassigned ts returns invalid 382 * @tc.type: FUNC 383 * */ 384 HWTEST_F(ThreadMutexTest, pthread_mutex_clocklock_005, TestSize.Level1) 385 { 386 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 387 EXPECT_EQ(EINVAL, pthread_mutex_clocklock(&mutex, CLOCK_PROCESS_CPUTIME_ID, &timeSpec_)); 388 }