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
16#include <stdio.h>
17#include <string.h>
18#include <stdlib.h>
19#include <time.h>
20#include <unistd.h>
21#include <pthread.h>
22#include <sys/time.h>
23#include <gtest/gtest.h>
24#include "utils.h"
25#include "mt_utils.h"
26#include "log.h"
27#include "FutexTest.h"
28
29using namespace testing::ext;
30
31/********************************************* Test case dividing line ***********************************************/
32
33pthread_rwlock_t g_rwlock1;
34
35void *PthreadRWlockWW1(void *arg)
36{
37    EXPECT_EQ(pthread_rwlock_wrlock(&g_rwlock1), 0) << "> return errno";
38    Msleep(50);
39    CheckStep(2);
40    EXPECT_EQ(pthread_rwlock_unlock(&g_rwlock1), 0) << "> return errno";
41    return arg;
42}
43
44void *PthreadRWlockWW2(void *arg)
45{
46    Msleep(20);
47    EXPECT_EQ(pthread_rwlock_wrlock(&g_rwlock1), 0) << "> return errno";
48    CheckStep(3);
49    EXPECT_EQ(pthread_rwlock_unlock(&g_rwlock1), 0) << "> return errno";
50    return arg;
51}
52
53/**
54 * @tc.number     SUB_KERNEL_FUTEX_RWLOCK_ALL_0100
55 * @tc.name       test rdlock and wrlock, write - write
56 * @tc.desc       [C- SOFTWARE -0200]
57 */
58HWTEST_F(FutexTest, testPthreadRWlockWW, Function | MediumTest | Level3)
59{
60    pthread_t tid[2];
61    CheckStep(1);
62    EXPECT_EQ(pthread_rwlock_init(&g_rwlock1, nullptr), 0);
63
64    EXPECT_EQ(pthread_create(&tid[0], nullptr, PthreadRWlockWW1, nullptr), 0) << "> return errno";
65    EXPECT_EQ(pthread_create(&tid[1], nullptr, PthreadRWlockWW2, nullptr), 0) << "> return errno";
66
67    EXPECT_EQ(pthread_join(tid[0], nullptr), 0) << "> return errno";
68    EXPECT_EQ(pthread_join(tid[1], nullptr), 0) << "> return errno";
69    EXPECT_EQ(CheckStep(4), (uint64_t)0x1234);
70    EXPECT_EQ(pthread_rwlock_destroy(&g_rwlock1), 0);
71}
72
73/********************************************* Test case dividing line ***********************************************/
74
75pthread_rwlock_t g_rwlock2;
76
77void *PthreadRWlockWR1(void *arg)
78{
79    EXPECT_EQ(pthread_rwlock_wrlock(&g_rwlock2), 0) << "> return errno";
80    Msleep(50);
81    CheckStep(2);
82    EXPECT_EQ(pthread_rwlock_unlock(&g_rwlock2), 0) << "> return errno";
83    return arg;
84}
85
86void *PthreadRWlockWR2(void *arg)
87{
88    Msleep(20);
89    EXPECT_EQ(pthread_rwlock_rdlock(&g_rwlock2), 0) << "> return errno";
90    CheckStep(3);
91    EXPECT_EQ(pthread_rwlock_unlock(&g_rwlock2), 0) << "> return errno";
92    return arg;
93}
94
95/**
96 * @tc.number     SUB_KERNEL_FUTEX_RWLOCK_ALL_0200
97 * @tc.name       test rdlock and wrlock, write - read
98 * @tc.desc       [C- SOFTWARE -0200]
99 */
100HWTEST_F(FutexTest, testPthreadRWlockWR, Function | MediumTest | Level3)
101{
102    pthread_t tid[2];
103    CheckStep(1);
104    EXPECT_EQ(pthread_rwlock_init(&g_rwlock2, nullptr), 0);
105
106    EXPECT_EQ(pthread_create(&tid[0], nullptr, PthreadRWlockWR1, nullptr), 0) << "> return errno";
107    EXPECT_EQ(pthread_create(&tid[1], nullptr, PthreadRWlockWR2, nullptr), 0) << "> return errno";
108
109    EXPECT_EQ(pthread_join(tid[0], nullptr), 0) << "> return errno";
110    EXPECT_EQ(pthread_join(tid[1], nullptr), 0) << "> return errno";
111    EXPECT_EQ(CheckStep(4), (uint64_t)0x1234);
112    EXPECT_EQ(pthread_rwlock_destroy(&g_rwlock2), 0);
113}
114
115/********************************************* Test case dividing line ***********************************************/
116
117pthread_rwlock_t g_rwlock3;
118
119void *PthreadRWlockRR1(void *arg)
120{
121    EXPECT_EQ(pthread_rwlock_rdlock(&g_rwlock3), 0) << "> return errno";
122    Msleep(50);
123    CheckStep(3);
124    EXPECT_EQ(pthread_rwlock_unlock(&g_rwlock3), 0) << "> return errno";
125    return arg;
126}
127
128void *PthreadRWlockRR2(void *arg)
129{
130    Msleep(20);
131    EXPECT_EQ(pthread_rwlock_rdlock(&g_rwlock3), 0) << "> return errno";
132    CheckStep(2);
133    EXPECT_EQ(pthread_rwlock_unlock(&g_rwlock3), 0) << "> return errno";
134    return arg;
135}
136
137/**
138 * @tc.number     SUB_KERNEL_FUTEX_RWLOCK_ALL_0300
139 * @tc.name       test rdlock and wrlock, read - read
140 * @tc.desc       [C- SOFTWARE -0200]
141 */
142HWTEST_F(FutexTest, testPthreadRWlockRR, Function | MediumTest | Level3)
143{
144    pthread_t tid[2];
145    CheckStep(1);
146    EXPECT_EQ(pthread_rwlock_init(&g_rwlock3, nullptr), 0);
147
148    EXPECT_EQ(pthread_create(&tid[0], nullptr, PthreadRWlockRR1, nullptr), 0) << "> return errno";
149    EXPECT_EQ(pthread_create(&tid[1], nullptr, PthreadRWlockRR2, nullptr), 0) << "> return errno";
150
151    EXPECT_EQ(pthread_join(tid[0], nullptr), 0) << "> return errno";
152    EXPECT_EQ(pthread_join(tid[1], nullptr), 0) << "> return errno";
153    EXPECT_EQ(CheckStep(4), (uint64_t)0x1234);
154    EXPECT_EQ(pthread_rwlock_destroy(&g_rwlock3), 0);
155}
156
157/********************************************* Test case dividing line ***********************************************/
158
159pthread_rwlock_t g_rwlock4;
160
161void *PthreadRWlockRW1(void *arg)
162{
163    EXPECT_EQ(pthread_rwlock_rdlock(&g_rwlock4), 0) << "> return errno";
164    Msleep(50);
165    CheckStep(2);
166    EXPECT_EQ(pthread_rwlock_unlock(&g_rwlock4), 0) << "> return errno";
167    return arg;
168}
169
170void *PthreadRWlockRW2(void *arg)
171{
172    Msleep(20);
173    EXPECT_EQ(pthread_rwlock_wrlock(&g_rwlock4), 0) << "> return errno";
174    CheckStep(3);
175    EXPECT_EQ(pthread_rwlock_unlock(&g_rwlock4), 0) << "> return errno";
176    return arg;
177}
178
179/**
180 * @tc.number     SUB_KERNEL_FUTEX_RWLOCK_ALL_0400
181 * @tc.name       test rdlock and wrlock, read - write
182 * @tc.desc       [C- SOFTWARE -0200]
183 */
184HWTEST_F(FutexTest, testPthreadRWlockRW, Function | MediumTest | Level3)
185{
186    pthread_t tid[2];
187    CheckStep(1);
188    EXPECT_EQ(pthread_rwlock_init(&g_rwlock4, nullptr), 0);
189
190    EXPECT_EQ(pthread_create(&tid[0], nullptr, PthreadRWlockRW1, nullptr), 0) << "> return errno";
191    EXPECT_EQ(pthread_create(&tid[1], nullptr, PthreadRWlockRW2, nullptr), 0) << "> return errno";
192
193    EXPECT_EQ(pthread_join(tid[0], nullptr), 0) << "> return errno";
194    EXPECT_EQ(pthread_join(tid[1], nullptr), 0) << "> return errno";
195    EXPECT_EQ(CheckStep(4), (uint64_t)0x1234);
196    EXPECT_EQ(pthread_rwlock_destroy(&g_rwlock4), 0);
197}
198
199/********************************************* Test case dividing line ***********************************************/
200
201pthread_rwlock_t g_rwlock5;
202
203void *PthreadRWtrylockWR1(void *arg)
204{
205    EXPECT_EQ(pthread_rwlock_trywrlock(&g_rwlock5), 0) << "> return errno";
206    Msleep(50);
207    CheckStep(3);
208    EXPECT_EQ(pthread_rwlock_unlock(&g_rwlock5), 0) << "> return errno";
209    return arg;
210}
211
212void *PthreadRWtrylockWR2(void *arg)
213{
214    Msleep(20);
215    EXPECT_EQ(pthread_rwlock_tryrdlock(&g_rwlock5), EBUSY) << "> should return EBUSY";
216    CheckStep(2);
217    return arg;
218}
219
220/**
221 * @tc.number     SUB_KERNEL_FUTEX_RWLOCK_ALL_0500
222 * @tc.name       test tryrdlock and trywrlock, write - read
223 * @tc.desc       [C- SOFTWARE -0200]
224 */
225HWTEST_F(FutexTest, testPthreadRWtrylockWR, Function | MediumTest | Level3)
226{
227    pthread_t tid[2];
228    CheckStep(1);
229    EXPECT_EQ(pthread_rwlock_init(&g_rwlock5, nullptr), 0);
230
231    EXPECT_EQ(pthread_create(&tid[0], nullptr, PthreadRWtrylockWR1, nullptr), 0) << "> return errno";
232    EXPECT_EQ(pthread_create(&tid[1], nullptr, PthreadRWtrylockWR2, nullptr), 0) << "> return errno";
233
234    EXPECT_EQ(pthread_join(tid[0], nullptr), 0) << "> return errno";
235    EXPECT_EQ(pthread_join(tid[1], nullptr), 0) << "> return errno";
236    EXPECT_EQ(CheckStep(4), (uint64_t)0x1234);
237    EXPECT_EQ(pthread_rwlock_destroy(&g_rwlock5), 0);
238}
239
240/********************************************* Test case dividing line ***********************************************/
241
242pthread_rwlock_t g_rwlock6;
243
244void *PthreadRWtrylockRW1(void *arg)
245{
246    EXPECT_EQ(pthread_rwlock_tryrdlock(&g_rwlock6), 0) << "> return errno";
247    Msleep(50);
248    CheckStep(3);
249    EXPECT_EQ(pthread_rwlock_unlock(&g_rwlock6), 0) << "> return errno";
250    return arg;
251}
252
253void *PthreadRWtrylockRW2(void *arg)
254{
255    Msleep(20);
256    EXPECT_EQ(pthread_rwlock_trywrlock(&g_rwlock6), EBUSY) << "> should return EBUSY";
257    CheckStep(2);
258    return arg;
259}
260
261/**
262 * @tc.number     SUB_KERNEL_FUTEX_RWLOCK_ALL_0600
263 * @tc.name       test tryrdlock and trywrlock, read - write
264 * @tc.desc       [C- SOFTWARE -0200]
265 */
266HWTEST_F(FutexTest, testPthreadRWtrylockRW, Function | MediumTest | Level3)
267{
268    pthread_t tid[2];
269    CheckStep(1);
270    EXPECT_EQ(pthread_rwlock_init(&g_rwlock6, nullptr), 0);
271
272    EXPECT_EQ(pthread_create(&tid[0], nullptr, PthreadRWtrylockRW1, nullptr), 0) << "> return errno";
273    EXPECT_EQ(pthread_create(&tid[1], nullptr, PthreadRWtrylockRW2, nullptr), 0) << "> return errno";
274
275    EXPECT_EQ(pthread_join(tid[0], nullptr), 0) << "> return errno";
276    EXPECT_EQ(pthread_join(tid[1], nullptr), 0) << "> return errno";
277    EXPECT_EQ(CheckStep(4), (uint64_t)0x1234);
278    EXPECT_EQ(pthread_rwlock_destroy(&g_rwlock6), 0);
279}
280
281/********************************************* Test case dividing line ***********************************************/
282
283pthread_rwlock_t g_rwlock7;
284
285void *PthreadTimdNoOutRWlockWR1(void *arg)
286{
287    EXPECT_EQ(pthread_rwlock_wrlock(&g_rwlock7), 0) << "> return errno";
288    Msleep(50);
289    CheckStep(2);
290    EXPECT_EQ(pthread_rwlock_unlock(&g_rwlock7), 0) << "> return errno";
291    return arg;
292}
293
294void *PthreadTimdNoOutRWlockWR2(void *arg)
295{
296    struct timespec ts = {0};
297    Msleep(20);
298    GetDelayedTime(&ts, 100);
299    EXPECT_EQ(pthread_rwlock_timedrdlock(&g_rwlock7, &ts), 0) << "> return errno";
300    CheckStep(3);
301    EXPECT_EQ(pthread_rwlock_unlock(&g_rwlock7), 0) << "> return errno";
302    return arg;
303}
304
305/**
306 * @tc.number     SUB_KERNEL_FUTEX_RWLOCK_ALL_0700
307 * @tc.name       test pthread_rwlock_timedrdlock with no timeout , write - read
308 * @tc.desc       [C- SOFTWARE -0200]
309 */
310HWTEST_F(FutexTest, testPthreadTimdNoOutRWlockWR, Function | MediumTest | Level3)
311{
312    pthread_t tid[2];
313    CheckStep(1);
314    EXPECT_EQ(pthread_rwlock_init(&g_rwlock7, nullptr), 0);
315
316    EXPECT_EQ(pthread_create(&tid[0], nullptr, PthreadTimdNoOutRWlockWR1, nullptr), 0) << "> return errno";
317    EXPECT_EQ(pthread_create(&tid[1], nullptr, PthreadTimdNoOutRWlockWR2, nullptr), 0) << "> return errno";
318
319    EXPECT_EQ(pthread_join(tid[0], nullptr), 0) << "> return errno";
320    EXPECT_EQ(pthread_join(tid[1], nullptr), 0) << "> return errno";
321    EXPECT_EQ(CheckStep(4), (uint64_t)0x1234);
322    EXPECT_EQ(pthread_rwlock_destroy(&g_rwlock7), 0);
323}
324
325/********************************************* Test case dividing line ***********************************************/
326
327pthread_rwlock_t g_rwlock8;
328
329void *PthreadTimdOutRWlockWR1(void *arg)
330{
331    EXPECT_EQ(pthread_rwlock_wrlock(&g_rwlock8), 0) << "> return errno";
332    Msleep(50);
333    CheckStep(2);
334    Msleep(100);
335    CheckStep(4);
336    EXPECT_EQ(pthread_rwlock_unlock(&g_rwlock8), 0) << "> return errno";
337    return arg;
338}
339
340void *PthreadTimdOutRWlockWR2(void *arg)
341{
342    struct timespec ts = {0};
343    struct timespec tsNow = {0};
344    Msleep(20);
345    GetDelayedTime(&ts, 100);
346    EXPECT_EQ(pthread_rwlock_timedrdlock(&g_rwlock8, &ts), ETIMEDOUT) << "> return errno";
347    CheckStep(3);
348    clock_gettime(CLOCK_REALTIME, &tsNow);
349    int timeDiff = GetTimeDiff(tsNow, ts); // calculate time different
350    EXPECT_GE(timeDiff, 0);
351    EXPECT_LE(timeDiff, 20);
352    return arg;
353}
354
355/**
356 * @tc.number     SUB_KERNEL_FUTEX_RWLOCK_ALL_0800
357 * @tc.name       test pthread_rwlock_timedrdlock with timeout, write - read
358 * @tc.desc       [C- SOFTWARE -0200]
359 */
360HWTEST_F(FutexTest, testPthreadTimdOutRWlockWR, Function | MediumTest | Level3)
361{
362    pthread_t tid[2];
363    CheckStep(1);
364    EXPECT_EQ(pthread_rwlock_init(&g_rwlock8, nullptr), 0);
365
366    EXPECT_EQ(pthread_create(&tid[0], nullptr, PthreadTimdOutRWlockWR1, nullptr), 0) << "> return errno";
367    EXPECT_EQ(pthread_create(&tid[1], nullptr, PthreadTimdOutRWlockWR2, nullptr), 0) << "> return errno";
368
369    EXPECT_EQ(pthread_join(tid[0], nullptr), 0) << "> return errno";
370    EXPECT_EQ(pthread_join(tid[1], nullptr), 0) << "> return errno";
371    EXPECT_EQ(CheckStep(5), (uint64_t)0x12345);
372    EXPECT_EQ(pthread_rwlock_destroy(&g_rwlock8), 0);
373}
374
375/********************************************* Test case dividing line ***********************************************/
376
377pthread_rwlock_t g_rwlock9;
378
379void *PthreadTimdOutRWlockWW1(void *arg)
380{
381    EXPECT_EQ(pthread_rwlock_wrlock(&g_rwlock9), 0) << "> return errno";
382    Msleep(50);
383    CheckStep(2);
384    Msleep(100);
385    CheckStep(4);
386    EXPECT_EQ(pthread_rwlock_unlock(&g_rwlock9), 0) << "> return errno";
387    return arg;
388}
389
390void *PthreadTimdOutRWlockWW2(void *arg)
391{
392    struct timespec ts = {0};
393    struct timespec tsNow = {0};
394    Msleep(20);
395    GetDelayedTime(&ts, 100);
396    EXPECT_EQ(pthread_rwlock_timedwrlock(&g_rwlock9, &ts), ETIMEDOUT) << "> return errno";
397    CheckStep(3);
398    clock_gettime(CLOCK_REALTIME, &tsNow);
399    int timeDiff = GetTimeDiff(tsNow, ts); // calculate time different
400    EXPECT_GE(timeDiff, 0);
401    EXPECT_LE(timeDiff, 20);
402    return arg;
403}
404
405/**
406 * @tc.number     SUB_KERNEL_FUTEX_RWLOCK_ALL_0900
407 * @tc.name       test pthread_rwlock_timedwrlock with timeout, write - write
408 * @tc.desc       [C- SOFTWARE -0200]
409 */
410HWTEST_F(FutexTest, testPthreadTimdOutRWlockWW, Function | MediumTest | Level3)
411{
412    pthread_t tid[2];
413    CheckStep(1);
414    EXPECT_EQ(pthread_rwlock_init(&g_rwlock9, nullptr), 0);
415
416    EXPECT_EQ(pthread_create(&tid[0], nullptr, PthreadTimdOutRWlockWW1, nullptr), 0) << "> return errno";
417    EXPECT_EQ(pthread_create(&tid[1], nullptr, PthreadTimdOutRWlockWW2, nullptr), 0) << "> return errno";
418
419    EXPECT_EQ(pthread_join(tid[0], nullptr), 0) << "> return errno";
420    EXPECT_EQ(pthread_join(tid[1], nullptr), 0) << "> return errno";
421    EXPECT_EQ(CheckStep(5), (uint64_t)0x12345);
422    EXPECT_EQ(pthread_rwlock_destroy(&g_rwlock9), 0);
423}
424
425/********************************************* Test case dividing line ***********************************************/
426
427pthread_rwlock_t g_rwlockA;
428
429void *PthreadTimdNoOutRWlockWW1(void *arg)
430{
431    EXPECT_EQ(pthread_rwlock_wrlock(&g_rwlockA), 0) << "> return errno";
432    Msleep(50);
433    CheckStep(2);
434    EXPECT_EQ(pthread_rwlock_unlock(&g_rwlockA), 0) << "> return errno";
435    return arg;
436}
437
438void *PthreadTimdNoOutRWlockWW2(void *arg)
439{
440    struct timespec ts = {0};
441    Msleep(20);
442    GetDelayedTime(&ts, 100);
443    EXPECT_EQ(pthread_rwlock_timedwrlock(&g_rwlockA, &ts), 0) << "> return errno";
444    CheckStep(3);
445    EXPECT_EQ(pthread_rwlock_unlock(&g_rwlockA), 0) << "> return errno";
446    return arg;
447}
448
449/**
450 * @tc.number     SUB_KERNEL_FUTEX_RWLOCK_ALL_1000
451 * @tc.name       test pthread_rwlock_timedwrlock with no timeout, write - write
452 * @tc.desc       [C- SOFTWARE -0200]
453 */
454HWTEST_F(FutexTest, testPthreadTimdNoOutRWlockWW, Function | MediumTest | Level3)
455{
456    pthread_t tid[2];
457    CheckStep(1);
458    EXPECT_EQ(pthread_rwlock_init(&g_rwlockA, nullptr), 0);
459
460    EXPECT_EQ(pthread_create(&tid[0], nullptr, PthreadTimdNoOutRWlockWW1, nullptr), 0) << "> return errno";
461    EXPECT_EQ(pthread_create(&tid[1], nullptr, PthreadTimdNoOutRWlockWW2, nullptr), 0) << "> return errno";
462
463    EXPECT_EQ(pthread_join(tid[0], nullptr), 0) << "> return errno";
464    EXPECT_EQ(pthread_join(tid[1], nullptr), 0) << "> return errno";
465    EXPECT_EQ(CheckStep(4), (uint64_t)0x1234);
466    EXPECT_EQ(pthread_rwlock_destroy(&g_rwlockA), 0);
467}
468
469/********************************************* Test case dividing line ***********************************************/
470
471/**
472 * @tc.number     SUB_KERNEL_FUTEX_RWLOCKATTR_0100
473 * @tc.name       test pthread_rwlockattr_init api
474 * @tc.desc       [C- SOFTWARE -0200]
475 */
476HWTEST_F(FutexTest, testPthreadRwlockAttr, Function | MediumTest | Level1)
477{
478    pthread_rwlockattr_t attr;
479    EXPECT_EQ(pthread_rwlockattr_init(&attr), 0);
480    EXPECT_EQ(pthread_rwlockattr_destroy(&attr), 0);
481}
482