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
21static void *PthreadClocklockOutRealTime(void *arg)
22{
23    pthread_mutex_t *mtx = (pthread_mutex_t*)arg;
24    struct timespec ts = {0};
25    struct timespec tsNow = {0};
26
27    Msleep(SLEEP_20_MS);
28    GetDelayedTimeByClockid(&ts, DELAY_TIME_100_MS, CLOCK_REALTIME);
29    TEST(pthread_mutex_clocklock(mtx, CLOCK_REALTIME, &ts) == ETIMEDOUT);
30
31    clock_gettime(CLOCK_REALTIME, &tsNow);
32    int timeDiff = GetTimeDiff(tsNow, ts); // calculate time different
33    TEST(timeDiff < 20);
34    return arg;
35}
36
37/**
38 * @tc.name     : pthread_mutex_clocklock_0010
39 * @tc.desc     : test pthread_mutex_clocklock whith timeout by CLOCK_REALTIME
40 * @tc.level    : Level 0
41 */
42static void pthread_mutex_clocklock_0010(void)
43{
44    pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
45    pthread_t tid;
46    TEST(pthread_create(&tid, NULL, PthreadClocklockOutRealTime, (void*)&mtx) == 0);
47
48    TEST(pthread_mutex_lock(&mtx) == 0);
49    Msleep(SLEEP_50_MS);
50    Msleep(SLEEP_100_MS);
51    TEST(pthread_mutex_unlock(&mtx) == 0);
52
53    TEST(pthread_join(tid, NULL) == 0);
54}
55
56/********************************************* Test case dividing line ***********************************************/
57
58static void *PthreadClocklockNoOutRealTime(void *arg)
59{
60    pthread_mutex_t *mtx = (pthread_mutex_t*)arg;
61    struct timespec ts = {0};
62
63    Msleep(SLEEP_20_MS);
64    GetDelayedTimeByClockid(&ts, DELAY_TIME_100_MS, CLOCK_REALTIME);
65    TEST(pthread_mutex_clocklock(mtx, CLOCK_REALTIME, &ts) == 0);
66    return arg;
67}
68
69/**
70 * @tc.name     : pthread_mutex_clocklock_0020
71 * @tc.desc     : test pthread_mutex_clocklock with no timeout by CLOCK_REALTIME
72 * @tc.level    : Level 0
73 */
74static void pthread_mutex_clocklock_0020(void)
75{
76    pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
77    pthread_t tid;
78    TEST(pthread_create(&tid, NULL, PthreadClocklockNoOutRealTime, (void*)&mtx) == 0);
79
80    TEST(pthread_mutex_lock(&mtx) == 0);
81    Msleep(SLEEP_50_MS);
82    TEST(pthread_mutex_unlock(&mtx) == 0);
83
84    TEST(pthread_join(tid, NULL) == 0);
85}
86
87/********************************************* Test case dividing line ***********************************************/
88
89static void *PthreadClocklockOutMonoTime(void *arg)
90{
91    pthread_mutex_t *mtx = (pthread_mutex_t*)arg;
92    struct timespec ts = {0};
93    struct timespec tsNow = {0};
94
95    Msleep(SLEEP_20_MS);
96    GetDelayedTimeByClockid(&ts, DELAY_TIME_100_MS, CLOCK_MONOTONIC);
97    TEST(pthread_mutex_clocklock(mtx, CLOCK_MONOTONIC, &ts) == ETIMEDOUT);
98
99    clock_gettime(CLOCK_MONOTONIC, &tsNow);
100    int timeDiff = GetTimeDiff(tsNow, ts); // calculate time different
101    TEST(timeDiff < 20);
102    return arg;
103}
104
105/**
106 * @tc.name     : pthread_mutex_clocklock_0030
107 * @tc.desc     : test pthread_mutex_clocklock whith timeout by CLOCK_MONOTONIC
108 * @tc.level    : Level 0
109 */
110static void pthread_mutex_clocklock_0030(void)
111{
112    pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
113    pthread_t tid;
114    TEST(pthread_create(&tid, NULL, PthreadClocklockOutMonoTime, (void*)&mtx) == 0);
115
116    TEST(pthread_mutex_lock(&mtx) == 0);
117    Msleep(SLEEP_50_MS);
118    Msleep(SLEEP_100_MS);
119    TEST(pthread_mutex_unlock(&mtx) == 0);
120
121    TEST(pthread_join(tid, NULL) == 0);
122}
123
124/********************************************* Test case dividing line ***********************************************/
125
126static void *PthreadClocklockNoOutMonoTime(void *arg)
127{
128    pthread_mutex_t *mtx = (pthread_mutex_t*)arg;
129    struct timespec ts = {0};
130
131    Msleep(SLEEP_20_MS);
132    GetDelayedTimeByClockid(&ts, DELAY_TIME_100_MS, CLOCK_MONOTONIC);
133    TEST(pthread_mutex_clocklock(mtx, CLOCK_MONOTONIC, &ts) == 0);
134    return arg;
135}
136
137/**
138 * @tc.name     : pthread_mutex_clocklock_0040
139 * @tc.desc     : test pthread_mutex_clocklock with no timeout by CLOCK_MONOTONIC
140 * @tc.level    : Level 0
141 */
142static void pthread_mutex_clocklock_0040(void)
143{
144    pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
145    pthread_t tid;
146    TEST(pthread_create(&tid, NULL, PthreadClocklockNoOutMonoTime, (void*)&mtx) == 0);
147
148    TEST(pthread_mutex_lock(&mtx) == 0);
149    Msleep(SLEEP_50_MS);
150    TEST(pthread_mutex_unlock(&mtx) == 0);
151
152    TEST(pthread_join(tid, NULL) == 0);
153}
154
155/********************************************* Test case dividing line ***********************************************/
156
157static void *PthreadClocklockOutRealTime2(void *arg)
158{
159    pthread_mutex_t *mtx = (pthread_mutex_t*)arg;
160    struct timespec ts = {0};
161    struct timespec tsNow = {0};
162
163    Msleep(SLEEP_20_MS);
164    GetDelayedTimeByClockid(&ts, DELAY_TIME_100_MS, CLOCK_REALTIME);
165    clock_gettime(CLOCK_REALTIME, &tsNow);
166    tsNow.tv_sec += 1;
167    clock_settime(CLOCK_REALTIME, &tsNow);
168    TEST(pthread_mutex_clocklock(mtx, CLOCK_REALTIME, &ts) == ETIMEDOUT);
169
170    clock_gettime(CLOCK_REALTIME, &tsNow);
171    tsNow.tv_sec -= 1;
172    clock_settime(CLOCK_REALTIME, &tsNow);
173
174    return arg;
175}
176
177/**
178 * @tc.name     : pthread_mutex_clocklock_0050
179 * @tc.desc     : test pthread_mutex_clocklock whith timeout by CLOCK_REALTIME
180 * @tc.level    : Level 2
181 */
182static void pthread_mutex_clocklock_0050(void)
183{
184    pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
185    pthread_t tid;
186    TEST(pthread_create(&tid, NULL, PthreadClocklockOutRealTime2, (void*)&mtx) == 0);
187
188    TEST(pthread_mutex_lock(&mtx) == 0);
189    Msleep(SLEEP_50_MS);
190    TEST(pthread_mutex_unlock(&mtx) == 0);
191
192    TEST(pthread_join(tid, NULL) == 0);
193}
194
195/********************************************* Test case dividing line ***********************************************/
196
197static void *PthreadClocklockNoOutMonoTime2(void *arg)
198{
199    pthread_mutex_t *mtx = (pthread_mutex_t*)arg;
200    struct timespec ts = {0};
201
202    Msleep(SLEEP_20_MS);
203    GetDelayedTimeByClockid(&ts, DELAY_TIME_100_MS, CLOCK_MONOTONIC);
204    TEST(pthread_mutex_clocklock(mtx, CLOCK_MONOTONIC, &ts) == 0);
205    return arg;
206}
207
208/**
209 * @tc.name     : pthread_mutex_clocklock_0060
210 * @tc.desc     : test pthread_mutex_clocklock whith timeout by CLOCK_REALTIME
211 * @tc.level    : Level 2
212 */
213static void pthread_mutex_clocklock_0060(void)
214{
215    struct timespec tsNow = {0};
216    pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
217    pthread_t tid;
218    TEST(pthread_create(&tid, NULL, PthreadClocklockNoOutMonoTime2, (void*)&mtx) == 0);
219
220    TEST(pthread_mutex_lock(&mtx) == 0);
221    Msleep(SLEEP_50_MS);
222    clock_gettime(CLOCK_MONOTONIC, &tsNow);
223    tsNow.tv_sec += 1;
224    clock_settime(CLOCK_REALTIME, &tsNow);
225    TEST(pthread_mutex_unlock(&mtx) == 0);
226
227    TEST(pthread_join(tid, NULL) == 0);
228
229    clock_gettime(CLOCK_REALTIME, &tsNow);
230    tsNow.tv_sec -= 1;
231    clock_settime(CLOCK_REALTIME, &tsNow);
232}
233
234/********************************************* Test case dividing line ***********************************************/
235
236static void *PthreadTimedlockMonotonicNPOut(void *arg)
237{
238    pthread_mutex_t *mtx = (pthread_mutex_t*)arg;
239    struct timespec ts = {0};
240    struct timespec tsNow = {0};
241
242    Msleep(SLEEP_20_MS);
243    GetDelayedTimeByClockid(&ts, DELAY_TIME_100_MS, CLOCK_MONOTONIC);
244    TEST(pthread_mutex_timedlock_monotonic_np(mtx, &ts) == ETIMEDOUT);
245
246    clock_gettime(CLOCK_MONOTONIC, &tsNow);
247    int timeDiff = GetTimeDiff(tsNow, ts); // calculate time different
248    TEST(timeDiff < 20);
249    return arg;
250}
251
252/**
253 * @tc.name     : pthread_mutex_timedlock_monotonic_np_0010
254 * @tc.desc     : test pthread_mutex_timedlock_monotonic_np whith timeout by CLOCK_MONOTONIC
255 * @tc.level    : Level 0
256 */
257static void pthread_mutex_timedlock_monotonic_np_0010(void)
258{
259    pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
260    pthread_t tid;
261    TEST(pthread_create(&tid, NULL, PthreadTimedlockMonotonicNPOut, (void*)&mtx) == 0);
262
263    TEST(pthread_mutex_lock(&mtx) == 0);
264    Msleep(SLEEP_50_MS);
265    Msleep(SLEEP_100_MS);
266    TEST(pthread_mutex_unlock(&mtx) == 0);
267
268    TEST(pthread_join(tid, NULL) == 0);
269}
270
271/********************************************* Test case dividing line ***********************************************/
272
273static void *PthreadTimedlockMonotonicNPNoOut(void *arg)
274{
275    pthread_mutex_t *mtx = (pthread_mutex_t*)arg;
276    struct timespec ts = {0};
277
278    Msleep(SLEEP_20_MS);
279    GetDelayedTimeByClockid(&ts, DELAY_TIME_100_MS, CLOCK_MONOTONIC);
280    TEST(pthread_mutex_timedlock_monotonic_np(mtx, &ts) == 0);
281    return arg;
282}
283
284/**
285 * @tc.name     : pthread_mutex_timedlock_monotonic_np_0020
286 * @tc.desc     : test pthread_mutex_timedlock_monotonic_np with no timeout by CLOCK_MONOTONIC
287 * @tc.level    : Level 0
288 */
289static void pthread_mutex_timedlock_monotonic_np_0020(void)
290{
291    pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
292    pthread_t tid;
293    TEST(pthread_create(&tid, NULL, PthreadTimedlockMonotonicNPNoOut, (void*)&mtx) == 0);
294
295    TEST(pthread_mutex_lock(&mtx) == 0);
296    Msleep(SLEEP_50_MS);
297    TEST(pthread_mutex_unlock(&mtx) == 0);
298
299    TEST(pthread_join(tid, NULL) == 0);
300}
301
302/********************************************* Test case dividing line ***********************************************/
303
304/**
305 * @tc.name     : pthread_mutex_timedlock_monotonic_np_0030
306 * @tc.desc     : test pthread_mutex_timedlock_monotonic_np_0030 with invalid args
307 * @tc.level    : Level 2
308 */
309static void pthread_mutex_timedlock_monotonic_np_0030(void)
310{
311    pthread_mutex_t *mtx = (pthread_mutex_t *)NULL;
312    struct timespec ts = {0};
313    EXPECT_EQ(pthread_mutex_timedlock_monotonic_np(mtx, &ts), EINVAL);
314}
315
316/********************************************* Test case dividing line ***********************************************/
317
318static void *PthreadLockTimeoutNPOut(void *arg)
319{
320    pthread_mutex_t *mtx = (pthread_mutex_t*)arg;
321    unsigned ms = DELAY_TIME_100_MS;
322    struct timespec ts = {0};
323    struct timespec tsNow = {0};
324
325    Msleep(SLEEP_20_MS);
326    GetDelayedTimeByClockid(&ts, ms, CLOCK_MONOTONIC);
327    TEST(pthread_mutex_lock_timeout_np(mtx, ms) == ETIMEDOUT);
328
329    clock_gettime(CLOCK_MONOTONIC, &tsNow);
330    int timeDiff = GetTimeDiff(tsNow, ts); // calculate time different
331    TEST(timeDiff < 20);
332    return arg;
333}
334
335/**
336 * @tc.name     : pthread_mutex_lock_timeout_np_0010
337 * @tc.desc     : test pthread_mutex_lock_timeout_np whith timeout by CLOCK_MONOTONIC
338 * @tc.level    : Level 0
339 */
340static void pthread_mutex_lock_timeout_np_0010(void)
341{
342    pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
343    pthread_t tid;
344    TEST(pthread_create(&tid, NULL, PthreadLockTimeoutNPOut, (void*)&mtx) == 0);
345
346    TEST(pthread_mutex_lock(&mtx) == 0);
347    Msleep(SLEEP_50_MS);
348    Msleep(SLEEP_100_MS);
349    TEST(pthread_mutex_unlock(&mtx) == 0);
350
351    TEST(pthread_join(tid, NULL) == 0);
352}
353
354/********************************************* Test case dividing line ***********************************************/
355
356static void *PthreadLockTimeoutNPNoOut(void *arg)
357{
358    pthread_mutex_t *mtx = (pthread_mutex_t*)arg;
359    unsigned ms = DELAY_TIME_100_MS;
360    struct timespec ts = {0};
361
362    Msleep(SLEEP_20_MS);
363    GetDelayedTimeByClockid(&ts, ms, CLOCK_MONOTONIC);
364    TEST(pthread_mutex_lock_timeout_np(mtx, ms) == 0);
365    return arg;
366}
367
368/**
369 * @tc.name     : pthread_mutex_lock_timeout_np_0020
370 * @tc.desc     : test pthread_mutex_lock_timeout_np with no timeout by CLOCK_MONOTONIC
371 * @tc.level    : Level 0
372 */
373static void pthread_mutex_lock_timeout_np_0020(void)
374{
375    pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
376    pthread_t tid;
377    TEST(pthread_create(&tid, NULL, PthreadLockTimeoutNPNoOut, (void*)&mtx) == 0);
378
379    TEST(pthread_mutex_lock(&mtx) == 0);
380    Msleep(SLEEP_50_MS);
381    TEST(pthread_mutex_unlock(&mtx) == 0);
382
383    TEST(pthread_join(tid, NULL) == 0);
384}
385
386int main(void)
387{
388    pthread_mutex_clocklock_0010();
389    pthread_mutex_clocklock_0020();
390    pthread_mutex_clocklock_0030();
391    pthread_mutex_clocklock_0040();
392    pthread_mutex_clocklock_0050();
393    pthread_mutex_clocklock_0060();
394    pthread_mutex_timedlock_monotonic_np_0010();
395    pthread_mutex_timedlock_monotonic_np_0020();
396    pthread_mutex_timedlock_monotonic_np_0030();
397    pthread_mutex_lock_timeout_np_0010();
398    pthread_mutex_lock_timeout_np_0020();
399
400    return t_status;
401}