• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
__anon9e7d3fbe0102null127     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));
__anon9e7d3fbe0202null151     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_));
__anon9e7d3fbe0302(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_));
__anon9e7d3fbe0402(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_));
__anon9e7d3fbe0502(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_));
__anon9e7d3fbe0602(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 }