• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_, &times));
67         EXPECT_EQ(ETIMEDOUT, arg->wrLockTestTimedFunc_(&arg->lock_, &times));
68         times.tv_nsec = -1;
69         EXPECT_EQ(EINVAL, arg->wrLockTestTimedFunc_(&arg->lock_, &times));
70         times.tv_nsec = TS_PER_T;
71         EXPECT_EQ(EINVAL, arg->wrLockTestTimedFunc_(&arg->lock_, &times));
72         EXPECT_EQ(0, clock_gettime(arg->clock_, &times));
73         times.tv_sec += 1;
74         EXPECT_EQ(ETIMEDOUT, arg->wrLockTestTimedFunc_(&arg->lock_, &times));
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, &times));
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, &times); });
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, &times));
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, &times); });
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, &times));
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, &times); });
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, &times));
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, &times); });
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, &times));
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, &times));
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, &times); });
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, &times));
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 }