1/*
2 * Copyright (c) 2022 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#include <errno.h>
16#include <pthread.h>
17#include "pthread_util.h"
18
19/********************************************* Test case dividing line ***********************************************/
20
21pthread_rwlock_t g_rwlock1;
22
23static void *PthreadClockRdlockNoOutRealTimeW1(void *arg)
24{
25    TEST(pthread_rwlock_wrlock(&g_rwlock1) == 0);
26    Msleep(SLEEP_50_MS);
27    TEST(pthread_rwlock_unlock(&g_rwlock1) == 0);
28    return arg;
29}
30
31static void *PthreadClockRdlockNoOutRealTimeR2(void *arg)
32{
33    struct timespec ts = {0};
34    Msleep(SLEEP_20_MS);
35    GetDelayedTimeByClockid(&ts, DELAY_TIME_100_MS, CLOCK_REALTIME);
36    TEST(pthread_rwlock_clockrdlock(&g_rwlock1, CLOCK_REALTIME, &ts) == 0);
37    TEST(pthread_rwlock_unlock(&g_rwlock1) == 0);
38    return arg;
39}
40
41/**
42 * @tc.name     : pthread_rwlock_clockrdlock_0010
43 * @tc.desc     : test pthread_rwlock_clockrdlock with no timeout by CLOCK_REALTIME , write - read
44 * @tc.level    : Level 0
45 */
46static void pthread_rwlock_clockrdlock_0010(void)
47{
48    pthread_t tid[2];
49    TEST(pthread_rwlock_init(&g_rwlock1, NULL) == 0);
50
51    TEST(pthread_create(&tid[0], NULL, PthreadClockRdlockNoOutRealTimeW1, NULL) == 0);
52    TEST(pthread_create(&tid[1], NULL, PthreadClockRdlockNoOutRealTimeR2, NULL) == 0);
53
54    TEST(pthread_join(tid[0], NULL) == 0);
55    TEST(pthread_join(tid[1], NULL) == 0);
56    TEST(pthread_rwlock_destroy(&g_rwlock1) == 0);
57}
58
59/********************************************* Test case dividing line ***********************************************/
60
61pthread_rwlock_t g_rwlock2;
62
63static void *PthreadClockRdlockOutRealTimeW1(void *arg)
64{
65    TEST(pthread_rwlock_wrlock(&g_rwlock2) == 0);
66    Msleep(SLEEP_50_MS);
67    Msleep(SLEEP_100_MS);
68    TEST(pthread_rwlock_unlock(&g_rwlock2) == 0);
69    return arg;
70}
71
72static void *PthreadClockRdlockOutRealTimeR2(void *arg)
73{
74    struct timespec ts = {0};
75    struct timespec tsNow = {0};
76    Msleep(SLEEP_20_MS);
77    GetDelayedTimeByClockid(&ts, DELAY_TIME_100_MS, CLOCK_REALTIME);
78    TEST(pthread_rwlock_clockrdlock(&g_rwlock2, CLOCK_REALTIME, &ts) == ETIMEDOUT);
79    clock_gettime(CLOCK_REALTIME, &tsNow);
80    int timeDiff = GetTimeDiff(tsNow, ts); // calculate time different
81    TEST(timeDiff < 20);
82    return arg;
83}
84
85/**
86 * @tc.name     : pthread_rwlock_clockrdlock_0020
87 * @tc.desc     : test pthread_rwlock_clockrdlock with timeout by CLOCK_REALTIME, write - read
88 * @tc.level    : Level 0
89 */
90static void pthread_rwlock_clockrdlock_0020(void)
91{
92    pthread_t tid[2];
93    TEST(pthread_rwlock_init(&g_rwlock2, NULL) == 0);
94
95    TEST(pthread_create(&tid[0], NULL, PthreadClockRdlockOutRealTimeW1, NULL) == 0);
96    TEST(pthread_create(&tid[1], NULL, PthreadClockRdlockOutRealTimeR2, NULL) == 0);
97
98    TEST(pthread_join(tid[0], NULL) == 0);
99    TEST(pthread_join(tid[1], NULL) == 0);
100    TEST(pthread_rwlock_destroy(&g_rwlock2) == 0);
101}
102
103
104/********************************************* Test case dividing line ***********************************************/
105
106pthread_rwlock_t g_rwlock3;
107
108static void *PthreadClockRdlockNoOutMonoTimeW1(void *arg)
109{
110    TEST(pthread_rwlock_wrlock(&g_rwlock3) == 0);
111    Msleep(SLEEP_50_MS);
112    TEST(pthread_rwlock_unlock(&g_rwlock3) == 0);
113    return arg;
114}
115
116static void *PthreadClockRdlockNoOutMonoTimeR2(void *arg)
117{
118    struct timespec ts = {0};
119    Msleep(SLEEP_20_MS);
120    GetDelayedTimeByClockid(&ts, DELAY_TIME_100_MS, CLOCK_MONOTONIC);
121    TEST(pthread_rwlock_clockrdlock(&g_rwlock3, CLOCK_MONOTONIC, &ts) == 0);
122    TEST(pthread_rwlock_unlock(&g_rwlock3) == 0);
123    return arg;
124}
125
126/**
127 * @tc.name     : pthread_rwlock_clockrdlock_0030
128 * @tc.desc     : test pthread_rwlock_clockrdlock with no timeout by CLOCK_MONOTONIC , write - read
129 * @tc.level    : Level 0
130 */
131static void pthread_rwlock_clockrdlock_0030(void)
132{
133    pthread_t tid[2];
134    TEST(pthread_rwlock_init(&g_rwlock3, NULL) == 0);
135
136    TEST(pthread_create(&tid[0], NULL, PthreadClockRdlockNoOutMonoTimeW1, NULL) == 0);
137    TEST(pthread_create(&tid[1], NULL, PthreadClockRdlockNoOutMonoTimeR2, NULL) == 0);
138
139    TEST(pthread_join(tid[0], NULL) == 0);
140    TEST(pthread_join(tid[1], NULL) == 0);
141    TEST(pthread_rwlock_destroy(&g_rwlock3) == 0);
142}
143
144/********************************************* Test case dividing line ***********************************************/
145
146pthread_rwlock_t g_rwlock4;
147
148static void *PthreadClockRdlockOutMonoTimeW1(void *arg)
149{
150    TEST(pthread_rwlock_wrlock(&g_rwlock4) == 0);
151    Msleep(SLEEP_50_MS);
152    Msleep(SLEEP_100_MS);
153    TEST(pthread_rwlock_unlock(&g_rwlock4) == 0);
154    return arg;
155}
156
157static void *PthreadClockRdlockOutMonoTimeR2(void *arg)
158{
159    struct timespec ts = {0};
160    struct timespec tsNow = {0};
161    Msleep(SLEEP_20_MS);
162    GetDelayedTimeByClockid(&ts, DELAY_TIME_100_MS, CLOCK_MONOTONIC);
163    TEST(pthread_rwlock_clockrdlock(&g_rwlock4, CLOCK_MONOTONIC, &ts) == ETIMEDOUT);
164    clock_gettime(CLOCK_MONOTONIC, &tsNow);
165    int timeDiff = GetTimeDiff(tsNow, ts); // calculate time different
166    TEST(timeDiff < 20);
167    return arg;
168}
169
170/**
171 * @tc.name     : pthread_rwlock_clockrdlock_0040
172 * @tc.desc     : test pthread_rwlock_clockrdlock with timeout by CLOCK_MONOTONIC, write - read
173 * @tc.level    : Level 0
174 */
175static void pthread_rwlock_clockrdlock_0040(void)
176{
177    pthread_t tid[2];
178    TEST(pthread_rwlock_init(&g_rwlock4, NULL) == 0);
179
180    TEST(pthread_create(&tid[0], NULL, PthreadClockRdlockOutMonoTimeW1, NULL) == 0);
181    TEST(pthread_create(&tid[1], NULL, PthreadClockRdlockOutMonoTimeR2, NULL) == 0);
182
183    TEST(pthread_join(tid[0], NULL) == 0);
184    TEST(pthread_join(tid[1], NULL) == 0);
185    TEST(pthread_rwlock_destroy(&g_rwlock4) == 0);
186}
187
188/********************************************* Test case dividing line ***********************************************/
189
190pthread_rwlock_t g_rwlock5;
191
192static void *PthreadTimedRdlockMonoNPNoOutW1(void *arg)
193{
194    TEST(pthread_rwlock_wrlock(&g_rwlock5) == 0);
195    Msleep(SLEEP_50_MS);
196    TEST(pthread_rwlock_unlock(&g_rwlock5) == 0);
197    return arg;
198}
199
200static void *PthreadTimedRdlockMonoNPNoOutR2(void *arg)
201{
202    struct timespec ts = {0};
203    Msleep(SLEEP_20_MS);
204    GetDelayedTimeByClockid(&ts, DELAY_TIME_100_MS, CLOCK_MONOTONIC);
205    TEST(pthread_rwlock_timedrdlock_monotonic_np(&g_rwlock5, &ts) == 0);
206    TEST(pthread_rwlock_unlock(&g_rwlock5) == 0);
207    return arg;
208}
209
210/**
211 * @tc.name     : pthread_rwlock_timedrdlock_monotonic_np_0010
212 * @tc.desc     : test pthread_rwlock_timedrdlock_monotonic_np with no timeout by CLOCK_MONOTONIC, write - read
213 * @tc.level    : Level 0
214 */
215static void pthread_rwlock_timedrdlock_monotonic_np_0010(void)
216{
217    pthread_t tid[2];
218    TEST(pthread_rwlock_init(&g_rwlock5, NULL) == 0);
219
220    TEST(pthread_create(&tid[0], NULL, PthreadTimedRdlockMonoNPNoOutW1, NULL) == 0);
221    TEST(pthread_create(&tid[1], NULL, PthreadTimedRdlockMonoNPNoOutR2, NULL) == 0);
222
223    TEST(pthread_join(tid[0], NULL) == 0);
224    TEST(pthread_join(tid[1], NULL) == 0);
225    TEST(pthread_rwlock_destroy(&g_rwlock5) == 0);
226}
227
228/********************************************* Test case dividing line ***********************************************/
229
230pthread_rwlock_t g_rwlock6;
231
232static void *PthreadTimedRdlockMonoNPOutW1(void *arg)
233{
234    TEST(pthread_rwlock_wrlock(&g_rwlock6) == 0);
235    Msleep(SLEEP_50_MS);
236    Msleep(SLEEP_100_MS);
237    TEST(pthread_rwlock_unlock(&g_rwlock6) == 0);
238    return arg;
239}
240
241static void *PthreadTimedRdlockMonoNPOutR2(void *arg)
242{
243    struct timespec ts = {0};
244    struct timespec tsNow = {0};
245    Msleep(SLEEP_20_MS);
246    GetDelayedTimeByClockid(&ts, DELAY_TIME_100_MS, CLOCK_MONOTONIC);
247    TEST(pthread_rwlock_timedrdlock_monotonic_np(&g_rwlock6, &ts) == ETIMEDOUT);
248    clock_gettime(CLOCK_MONOTONIC, &tsNow);
249    int timeDiff = GetTimeDiff(tsNow, ts); // calculate time different
250    TEST(timeDiff < 20);
251    return arg;
252}
253
254/**
255 * @tc.name     : pthread_rwlock_timedrdlock_monotonic_np_0020
256 * @tc.desc     : test pthread_rwlock_timedrdlock_monotonic_np with timeout by CLOCK_MONOTONIC, write - read
257 * @tc.level    : Level 0
258 */
259static void pthread_rwlock_timedrdlock_monotonic_np_0020(void)
260{
261    pthread_t tid[2];
262    TEST(pthread_rwlock_init(&g_rwlock6, NULL) == 0);
263
264    TEST(pthread_create(&tid[0], NULL, PthreadTimedRdlockMonoNPOutW1, NULL) == 0);
265    TEST(pthread_create(&tid[1], NULL, PthreadTimedRdlockMonoNPOutR2, NULL) == 0);
266
267    TEST(pthread_join(tid[0], NULL) == 0);
268    TEST(pthread_join(tid[1], NULL) == 0);
269    TEST(pthread_rwlock_destroy(&g_rwlock6) == 0);
270}
271
272/**
273 * @tc.name     : pthread_rwlock_timedrdlock_monotonic_np_0030
274 * @tc.desc     : test pthread_rwlock_timedrdlock_monotonic_np with invalid rwlock
275 * @tc.level    : Level 2
276 */
277static void pthread_rwlock_timedrdlock_monotonic_np_0030(void)
278{
279    struct timespec ts = {0};
280    EXPECT_EQ(pthread_rwlock_timedrdlock_monotonic_np((pthread_rwlock_t *)NULL, &ts), EINVAL);
281}
282
283int main(void)
284{
285    pthread_rwlock_clockrdlock_0010();
286    pthread_rwlock_clockrdlock_0020();
287    pthread_rwlock_clockrdlock_0030();
288    pthread_rwlock_clockrdlock_0040();
289    pthread_rwlock_timedrdlock_monotonic_np_0010();
290    pthread_rwlock_timedrdlock_monotonic_np_0020();
291    pthread_rwlock_timedrdlock_monotonic_np_0030();
292
293	return t_status;
294}