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#include <stdio.h>
16#include <string.h>
17#include <limits.h>
18#include <pthread.h>
19#include <gtest/gtest.h>
20#include "utils.h"
21#include "log.h"
22#include "KernelConstants.h"
23#include "PthreadTest.h"
24#include "mt_utils.h"
25
26using namespace testing::ext;
27
28void *ThreadPthreadCreateBasic(void *arg)
29{
30    char *s = (char*)arg;
31    EXPECT_STREQ(s, "1234567890 !@#$%^&*()_= ZXCVBNM [];'./>?:\" +-*/qwertyuiopasdfghjklzxcvbnm");
32    return arg;
33}
34
35/**
36 * @tc.number   SUB_KERNEL_PTHREAD_CREATE_0100
37 * @tc.name     pthread_create create a thread
38 * @tc.desc     [C- SOFTWARE -0200]
39 */
40HWTEST_F(PthreadTest, testPthreadCreateBasic, Function | MediumTest | Level2)
41{
42    pthread_t tid;
43    char str[] = "1234567890 !@#$%^&*()_= ZXCVBNM [];'./>?:\" +-*/qwertyuiopasdfghjklzxcvbnm";
44    ASSERT_EQ(pthread_create(&tid, nullptr, ThreadPthreadCreateBasic, (void*)str), 0) << "> return errno";
45
46    EXPECT_EQ(pthread_join(tid, nullptr), 0) << "> return errno";
47}
48
49void *ThreadPthreadJoinWait(void *arg)
50{
51    Msleep(20);
52    CheckStep(2);
53    return arg;
54}
55
56/**
57 * @tc.number   SUB_KERNEL_PTHREAD_JOIN_0100
58 * @tc.name     Test the waiting function of pthread_join
59 * @tc.desc     [C- SOFTWARE -0200]
60 */
61HWTEST_F(PthreadTest, testPthreadJoinWait, Function | MediumTest | Level2)
62{
63    pthread_t tid;
64    CheckStep(1);
65    ASSERT_EQ(pthread_create(&tid, nullptr, ThreadPthreadJoinWait, nullptr), 0) << "> return errno";
66    EXPECT_EQ(pthread_join(tid, nullptr), 0) << "> return errno";
67    EXPECT_EQ(CheckStep(3), (uint64_t)0x123) << "pthread_join no wait";
68}
69
70/**
71 * @tc.number   SUB_KERNEL_PTHREAD_JOIN_0200
72 * @tc.name     Test the function of pthread_join to get the return value
73 * @tc.desc     [C- SOFTWARE -0200]
74 */
75HWTEST_F(PthreadTest, testJoinReturn, Function | MediumTest | Level3)
76{
77    pthread_t tid;
78    int num = 4;
79    void *joinRe = nullptr;
80
81    ASSERT_EQ(pthread_create(&tid, nullptr, ThreadPublic, (void*)&num), 0) << "> return errno";
82    EXPECT_EQ(pthread_join(tid, &joinRe), 0) << "> return errno";
83
84    int *p = (int*)joinRe;
85    EXPECT_TRUE(&num == p);
86}
87
88/**
89 * @tc.number   SUB_KERNEL_PTHREAD_JOIN_0300
90 * @tc.name     Test the function about pthread_join, but child thread Exited
91 * @tc.desc     [C- SOFTWARE -0200]
92 */
93HWTEST_F(PthreadTest, testJoinExited, Function | MediumTest | Level3)
94{
95    pthread_t tid;
96    ASSERT_EQ(pthread_create(&tid, nullptr, ThreadPublic, nullptr), 0) << "> return errno";
97    Msleep(50);
98    EXPECT_EQ(pthread_join(tid, nullptr), 0) << "> return errno";
99}
100
101void *ThreadPthreadExitThread(void *arg)
102{
103    pthread_exit(arg);
104    return nullptr;
105}
106
107/**
108 * @tc.number   SUB_KERNEL_PTHREAD_EXIT_0100
109 * @tc.name     Test the return function of pthread_exit in the child thread
110 * @tc.desc     [C- SOFTWARE -0200]
111 */
112HWTEST_F(PthreadTest, testPthreadExitThread, Function | MediumTest | Level3)
113{
114    pthread_t tid;
115    int num = 4;
116    void *joinRe = nullptr;
117
118    ASSERT_EQ(pthread_create(&tid, nullptr, ThreadPthreadExitThread, (void*)&num), 0) << "> return errno";
119    EXPECT_EQ(pthread_join(tid, &joinRe), 0) << "> return errno";
120    int *p = (int*)joinRe;
121    EXPECT_TRUE(&num == p);
122}
123
124void FunPthreadExit(void *arg)
125{
126    pthread_exit(arg);
127}
128
129void *ThreadPthreadExitFunction(void *arg)
130{
131    FunPthreadExit(arg);
132    return nullptr;
133}
134
135/**
136 * @tc.number   SUB_KERNEL_PTHREAD_EXIT_0200
137 * @tc.name     Test the return function of pthread_exit in the child thread function
138 * @tc.desc     [C- SOFTWARE -0200]
139 */
140HWTEST_F(PthreadTest, testPthreadExitFunction, Function | MediumTest | Level3)
141{
142    pthread_t tid;
143    int num = 4;
144    void *joinRe = nullptr;
145
146    ASSERT_EQ(pthread_create(&tid, nullptr, ThreadPthreadExitFunction, (void*)&num), 0) << "> return errno";
147    EXPECT_EQ(pthread_join(tid, &joinRe), 0) << "> return errno";
148    int *p = (int*)joinRe;
149    EXPECT_TRUE(&num == p);
150}
151
152/**
153 * @tc.number   SUB_KERNEL_PTHREAD_DETACH_0100
154 * @tc.name     Use pthread_detach to detach child threads
155 * @tc.desc     [C- SOFTWARE -0200]
156 */
157HWTEST_F(PthreadTest, testPthreadDetach, Function | MediumTest | Level3)
158{
159    pthread_t tid;
160    ASSERT_EQ(pthread_create(&tid, nullptr, ThreadPublic, nullptr), 0) << "> return errno";
161    EXPECT_EQ(pthread_detach(tid), 0) << "> return errno";
162    EXPECT_EQ(pthread_join(tid, nullptr), EINVAL) << "> return errno";
163}
164
165void *ThreadPthreadEqual(void *arg)
166{
167    pthread_t *tid = (pthread_t*)arg;
168    EXPECT_NE(pthread_equal(*tid, pthread_self()), 0) << "pthread_equal should be equal";
169    Msleep(10);
170    return arg;
171}
172
173/**
174 * @tc.number   SUB_KERNEL_PTHREAD_EQUAL_0100
175 * @tc.name     Use pthread_equal checks process equality
176 * @tc.desc     [C- SOFTWARE -0200]
177 */
178HWTEST_F(PthreadTest, testPthreadEqual, Function | MediumTest | Level3)
179{
180    pthread_t tid;
181    ASSERT_EQ(pthread_create(&tid, nullptr, ThreadPthreadEqual, (void*)&tid), 0) << "> return errno";
182    EXPECT_EQ(pthread_equal(tid, pthread_self()), 0) << "pthread_equal should be no equal";
183    EXPECT_EQ(pthread_join(tid, nullptr), 0) << "> return errno";
184}
185
186/**
187 * @tc.number   SUB_KERNEL_PTHREAD_KEY_CREATE_0100
188 * @tc.name     Check the parameter PTHREAD_KEYS_MAX of pthread_key_create
189 * @tc.desc     [C- SOFTWARE -0200]
190 */
191HWTEST_F(PthreadTest, testPthreadKeysMax, Function | MediumTest | Level3)
192{
193    int creatCnt = -1;
194    pid_t pid = fork();
195    ASSERT_TRUE(pid >= 0) << "> parent: fork errno = " << errno;
196    if (pid == 0) {
197        int re;
198        int exitCode = 0;
199        pthread_key_t keys[PTHREAD_KEYS_MAX];
200        for (int i = 0; i < PTHREAD_KEYS_MAX; i++) {
201            re = pthread_key_create(&keys[i], nullptr);
202            if (re == EAGAIN) {
203                LOG("pthread_key_create %d errno = %d", i, re);
204                creatCnt = i;
205                break;
206            } else if (re != 0) {
207                LOG("pthread_key_create %d errno = %d", i, re);
208                exitCode = 1;
209                creatCnt = i;
210                break;
211            }
212        }
213
214        if (creatCnt == -1) {
215            creatCnt = PTHREAD_KEYS_MAX;
216        }
217
218        for (int i = 0; i < creatCnt; i++) {
219            re = pthread_key_delete(keys[i]);
220            if (re != 0) {
221                LOG("pthread_key_delete %d errno = %d", i, re);
222                exitCode = 1;
223                break;
224            }
225        }
226        exit(exitCode);
227    }
228    WaitProcExitedOK(pid);
229}
230
231/**
232 * @tc.number   SUB_KERNEL_PTHREAD_GETSPECIFIC_0100
233 * @tc.name     Use pthread_getspecific to get the value corresponding to the parameter key
234 * @tc.desc     [C- SOFTWARE -0200]
235 */
236HWTEST_F(PthreadTest, testPthreadGetspecific, Function | MediumTest | Level3)
237{
238    pthread_key_t keys;
239    int testInt = 100;
240    void *testVoidP = (void*)&testInt;
241    EXPECT_EQ(pthread_key_create(&keys, nullptr), 0) << "> return errno";
242
243    void *reVoidP = pthread_getspecific(keys);
244    EXPECT_EQ(reVoidP, nullptr);
245
246    EXPECT_EQ(pthread_setspecific(keys, testVoidP), 0) << "> return errno";
247
248    reVoidP = pthread_getspecific(keys);
249    EXPECT_EQ(reVoidP, testVoidP);
250
251    EXPECT_EQ(pthread_key_delete(keys), 0) << "> return errno";
252
253    reVoidP = pthread_getspecific(keys);
254    EXPECT_EQ(reVoidP, nullptr);
255}
256
257pthread_key_t g_keys;
258pthread_once_t g_once = PTHREAD_ONCE_INIT;
259int g_intPthreadSpecificAll = 0;
260
261// Destructor function, excute after ThreadPthreadSpecificAll
262void DestructorPthreadSpecificAll(void *param)
263{
264    int *p = (int*)param;
265    *p += 1;
266}
267
268void OnceFunc()
269{
270    // DestructorPthreadSpecificAll() execute twice
271    EXPECT_EQ(pthread_key_create(&g_keys, DestructorPthreadSpecificAll), 0) << "> return errno";
272    EXPECT_EQ(pthread_getspecific(g_keys), nullptr);
273    // execute once
274    g_intPthreadSpecificAll++;
275    EXPECT_EQ(g_intPthreadSpecificAll, 1);
276}
277
278void *ThreadPthreadSpecificAll(void *arg)
279{
280    // OnceFunc() execute once
281    int reInt = pthread_once(&g_once, OnceFunc);
282    EXPECT_TRUE((reInt == 0) || (reInt == 2));
283
284    if (pthread_getspecific(g_keys) == nullptr) {
285        // execute twice
286        g_intPthreadSpecificAll++;
287        EXPECT_EQ(pthread_setspecific(g_keys, (void*)&g_intPthreadSpecificAll), 0) << "> return errno";
288    }
289    // only 2 or 4
290    EXPECT_GE(g_intPthreadSpecificAll, 2);
291    EXPECT_NE(g_intPthreadSpecificAll, 3);
292    EXPECT_LE(g_intPthreadSpecificAll, 4);
293    return arg;
294}
295
296void DestructorPthreadSpecificAllDelete(void *param)
297{
298    int *p = (int*)param;
299    *p += 1;
300}
301
302void *ThreadPthreadSpecificAllDelete(void *arg)
303{
304    pthread_key_t keys;
305    EXPECT_EQ(pthread_key_create(&keys, DestructorPthreadSpecificAllDelete), 0) << "> return errno";
306    EXPECT_EQ(pthread_getspecific(keys), nullptr);
307    EXPECT_EQ(pthread_setspecific(keys, arg), 0) << "> return errno";
308    EXPECT_EQ(pthread_getspecific(keys), arg);
309    EXPECT_EQ(pthread_key_delete(keys), 0) << "> return errno";
310    return arg;
311}
312
313/**
314 * @tc.number   SUB_KERNEL_PTHREAD_SPECIFIC_ALL_0200
315 * @tc.name     Delete the key before the child thread exits
316 * @tc.desc     [C- SOFTWARE -0200]
317 */
318HWTEST_F(PthreadTest, testPthreadSpecificAllDelete, Function | MediumTest | Level3)
319{
320    int data = 1;
321    pthread_t tid;
322    ASSERT_EQ(pthread_create(&tid, nullptr, ThreadPthreadSpecificAllDelete, (void*)&data), 0) << "> return errno";
323    Msleep(100);
324    pthread_join(tid, nullptr);
325    EXPECT_EQ(data, 1);
326}
327
328void TestPushHandler1(void *arg)
329{
330    CheckStep(3);
331}
332
333void TestPushHandler2(void *arg)
334{
335    CheckStep(2);
336}
337
338void *ThreadTestPush(void *arg)
339{
340    pthread_cleanup_push(TestPushHandler1, nullptr);
341    pthread_cleanup_push(TestPushHandler2, nullptr);
342    pthread_cleanup_pop(1);
343    pthread_cleanup_pop(1);
344    return arg;
345}
346
347/**
348 * @tc.number   SUB_KERNEL_PTHREAD_CLEANUP_ALL_0100
349 * @tc.name     pthread_cleanup_push and pthread_cleanup_pop basic test
350 * @tc.desc     [C- SOFTWARE -0200]
351 */
352HWTEST_F(PthreadTest, testPthreadCleanupPushPopBasic, Function | MediumTest | Level3)
353{
354    pthread_t tid;
355    CheckStep(1);
356    ASSERT_EQ(pthread_create(&tid, nullptr, ThreadTestPush, nullptr), 0) << "> return errno";
357    Msleep(100);
358    pthread_join(tid, nullptr);
359    EXPECT_EQ(CheckStep(4), (uint64_t)0x1234);
360}
361
362void TestPushParamHandler(void *arg)
363{
364    int *testInt = (int*)arg;
365    EXPECT_EQ(*testInt, 1);
366    CheckStep(2);
367}
368
369void *ThreadTestPushParam(void *arg)
370{
371    int testInt = 1;
372    pthread_cleanup_push(TestPushParamHandler, (void*)&testInt);
373    pthread_cleanup_pop(1);
374    return arg;
375}
376
377/**
378 * @tc.number   SUB_KERNEL_PTHREAD_CLEANUP_ALL_0200
379 * @tc.name     pthread_cleanup_push and pthread_cleanup_pop test with param
380 * @tc.desc     [C- SOFTWARE -0200]
381 */
382HWTEST_F(PthreadTest, testPthreadCleanupPushPopParam, Function | MediumTest | Level3)
383{
384    pthread_t tid;
385    CheckStep(1);
386    ASSERT_EQ(pthread_create(&tid, nullptr, ThreadTestPushParam, nullptr), 0) << "> return errno";
387    Msleep(100);
388    pthread_join(tid, nullptr);
389    EXPECT_EQ(CheckStep(3), (uint64_t)0x123);
390}
391
392void TestPopHandler1(void *arg)
393{
394    CheckStep(2);
395}
396
397void TestPopHandler2(void *arg)
398{
399    // unreachable
400    LOG("step = %lx", CheckStep(10));
401}
402
403static void *ThreadTestop(void *arg)
404{
405    pthread_cleanup_push(TestPopHandler1, nullptr);
406    pthread_cleanup_push(TestPopHandler2, nullptr);
407    pthread_cleanup_pop(0);
408    pthread_cleanup_pop(1);
409    return arg;
410}
411
412/**
413 * @tc.number   SUB_KERNEL_PTHREAD_CLEANUP_ALL_0300
414 * @tc.name     pthread_cleanup_pop use different parameters
415 * @tc.desc     [C- SOFTWARE -0200]
416 */
417HWTEST_F(PthreadTest, testPop, Function | MediumTest | Level3)
418{
419    pthread_t tid;
420    CheckStep(1);
421    ASSERT_EQ(pthread_create(&tid, nullptr, ThreadTestop, nullptr), 0) << "> return errno";
422    Msleep(100);
423    pthread_join(tid, nullptr);
424    EXPECT_EQ(CheckStep(3), (uint64_t)0x123);
425}
426
427/**
428 * @tc.number   SUB_KERNEL_PTHREAD_BARRIER_INIT_0100
429 * @tc.name     basic test of pthread_barrier_init
430 * @tc.desc     [C- SOFTWARE -0200]
431 */
432HWTEST_F(PthreadTest, testBarrierInit, Function | MediumTest | Level2)
433{
434    pthread_barrier_t barrier;
435    EXPECT_EQ(pthread_barrier_init(&barrier, nullptr, 0), EINVAL) << "> return errno";
436}
437
438/**
439 * @tc.number   SUB_KERNEL_PTHREAD_BARRIERATTR_INIT_0100
440 * @tc.name     basic test with pthread_barrierattr_init
441 * @tc.desc     [C- SOFTWARE -0200]
442 */
443HWTEST_F(PthreadTest, testBarrierattrInit, Function | MediumTest | Level3)
444{
445    pthread_barrierattr_t barrierAttr;
446    pthread_barrier_t barrier;
447    EXPECT_EQ(pthread_barrierattr_init(&barrierAttr), 0);
448    EXPECT_EQ(pthread_barrierattr_destroy(&barrierAttr), 0);
449    EXPECT_EQ(pthread_barrier_init(&barrier, &barrierAttr, 1), 0) << "> return errno";
450    EXPECT_EQ(pthread_barrier_destroy(&barrier), 0) << "> return errno";
451}
452
453static pthread_barrier_t g_barrier;
454void *ThreadTestBarrierWait1(void *arg)
455{
456    int *intP = (int*)arg;
457    int reInt = pthread_barrier_wait(&g_barrier);
458    if (reInt == PTHREAD_BARRIER_SERIAL_THREAD) {
459        CheckStep(2);
460    } else if (reInt == 0) {
461        Msleep(30);
462        *intP += 1;
463    } else {
464        ADD_FAILURE();
465    }
466    return arg;
467}
468
469void *ThreadTestBarrierWait2(void *arg)
470{
471    int *intP = (int*)arg;
472    int reInt = pthread_barrier_wait(&g_barrier);
473    if (reInt == PTHREAD_BARRIER_SERIAL_THREAD) {
474        CheckStep(2);
475    } else if (reInt == 0) {
476        Msleep(20);
477        *intP += 1;
478    } else {
479        ADD_FAILURE();
480    }
481    return arg;
482}
483
484/**
485 * @tc.number   SUB_KERNEL_PTHREAD_BARRIER_ALL_0100
486 * @tc.name     test pthread_barrier_wait return value
487 * @tc.desc     [C- SOFTWARE -0200]
488 */
489HWTEST_F(PthreadTest, testBarrierWait, Function | MediumTest | Level3)
490{
491    pthread_t tid;
492    pthread_t tid1;
493    CheckStep(1);
494    int intParam = 0;
495
496    EXPECT_EQ(pthread_barrier_init(&g_barrier, nullptr, 3), 0) << "> return errno";
497    ASSERT_EQ(pthread_create(&tid, nullptr, ThreadTestBarrierWait1, (void*)&intParam), 0) << "> return errno";
498    ASSERT_EQ(pthread_create(&tid1, nullptr, ThreadTestBarrierWait2, (void*)&intParam), 0) << "> return errno";
499    int reInt = pthread_barrier_wait(&g_barrier);
500    if (reInt == PTHREAD_BARRIER_SERIAL_THREAD) {
501        CheckStep(2);
502    } else if (reInt == 0) {
503        Msleep(10);
504        intParam++;
505    } else {
506        ADD_FAILURE();
507    }
508    Msleep(50);
509    pthread_join(tid, nullptr);
510    pthread_join(tid1, nullptr);
511    EXPECT_EQ(pthread_barrier_destroy(&g_barrier), 0) << "> return errno";
512    EXPECT_EQ(CheckStep(3), (uint64_t)0x123);
513    EXPECT_EQ(intParam, 2);
514}
515
516void *ThreadTestBarrierAlwaysWait(void *arg)
517{
518    pthread_barrier_t *barrier = (pthread_barrier_t*)arg;
519    int reInt = pthread_barrier_wait(barrier);
520    if ((reInt != PTHREAD_BARRIER_SERIAL_THREAD) && (reInt != 0)) {
521        ADD_FAILURE();
522    }
523    CheckStep(3);
524    return arg;
525}
526
527/**
528 * @tc.number   SUB_KERNEL_PTHREAD_BARRIER_ALL_0200
529 * @tc.name     Comprehensive test with barrier properties, always waiting
530 * @tc.desc     [C- SOFTWARE -0200]
531 */
532HWTEST_F(PthreadTest, testBarrierAlwaysWait, Function | MediumTest | Level3)
533{
534    pthread_t tid;
535    pthread_t tid1;
536    pthread_barrier_t barrier;
537    CheckStep(1);
538
539    EXPECT_EQ(pthread_barrier_init(&barrier, nullptr, 3), 0) << "> return errno";
540    ASSERT_EQ(pthread_create(&tid, nullptr, ThreadTestBarrierAlwaysWait, (pthread_barrier_t*)&barrier), 0)
541        << "> return errno";
542    ASSERT_EQ(pthread_create(&tid1, nullptr, ThreadTestBarrierAlwaysWait, (pthread_barrier_t*)&barrier), 0)
543        << "> return errno";
544
545    Msleep(100);
546    EXPECT_EQ(CheckStep(2), (uint64_t)0x12);  // childs threads always waiting
547    int reInt = pthread_barrier_wait(&barrier);
548    if ((reInt != PTHREAD_BARRIER_SERIAL_THREAD) && (reInt != 0)) {
549        ADD_FAILURE();
550    }
551    pthread_join(tid, nullptr);
552    pthread_join(tid1, nullptr);
553    EXPECT_EQ(pthread_barrier_destroy(&barrier), 0) << "> return errno";
554}
555
556/**
557 * @tc.number   SUB_KERNEL_PTHREAD_SETCANCELSTATE_0100
558 * @tc.name     basic test about pthread_setcancelstate
559 * @tc.desc     [C- SOFTWARE -0200]
560 */
561HWTEST_F(PthreadTest, testPthreadSetcancelstate, Function | MediumTest | Level3)
562{
563    int oldState = 0;
564    EXPECT_EQ(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldState), 0) << "> return errno";
565    EXPECT_EQ(oldState, PTHREAD_CANCEL_ENABLE);
566    EXPECT_EQ(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldState), 0) << "> return errno";
567    EXPECT_EQ(oldState, PTHREAD_CANCEL_DISABLE);
568    EXPECT_EQ(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, nullptr), 0) << "> return errno";
569    EXPECT_EQ(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, nullptr), 0) << "> return errno";
570}
571
572/**
573 * @tc.number   SUB_KERNEL_PTHREAD_SETCANCELTYPE_0100
574 * @tc.name     basic test about pthread_setcanceltype
575 * @tc.desc     [C- SOFTWARE -0200]
576 */
577HWTEST_F(PthreadTest, testPthreadSetcanceltype, Function | MediumTest | Level3)
578{
579    int oldState = 0;
580    EXPECT_EQ(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldState), 0) << "> return errno";
581    EXPECT_EQ(oldState, PTHREAD_CANCEL_DEFERRED);
582    EXPECT_EQ(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldState), 0) << "> return errno";
583    EXPECT_EQ(oldState, PTHREAD_CANCEL_ASYNCHRONOUS);
584    EXPECT_EQ(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, nullptr), 0) << "> return errno";
585    EXPECT_EQ(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, nullptr), 0) << "> return errno";
586}
587
588void *ThreadPthreadNoCancelPoint(void *arg)
589{
590    CheckStep(2);
591    KeepRun(50);
592    CheckStep(3);
593    return arg;
594}
595
596/**
597 * @tc.number   SUB_KERNEL_PTHREAD_CANCEL_0100
598 * @tc.name     test pthread_cancel with no cancel point
599 * @tc.desc     [C- SOFTWARE -0200]
600 */
601HWTEST_F(PthreadTest, testPthreadNoCancelPoint, Function | MediumTest | Level3)
602{
603    pthread_t tid;
604    CheckStep(1);
605    ASSERT_EQ(pthread_create(&tid, nullptr, ThreadPthreadNoCancelPoint, nullptr), 0) << "> return errno";
606    Msleep(10);
607    EXPECT_EQ(pthread_cancel(tid), 0);
608    Msleep(100);
609    EXPECT_EQ(pthread_join(tid, NULL), 0);
610}
611
612void *ThreadPthreadCancelPoint(void *arg)
613{
614    CheckStep(2);
615    KeepRun(50);
616    pthread_testcancel();
617
618    // unreachable
619    CheckStep(3);
620    return arg;
621}
622
623/**
624 * @tc.number   SUB_KERNEL_PTHREAD_CANCEL_0200
625 * @tc.name     test pthread_cancel with cancel point
626 * @tc.desc     [C- SOFTWARE -0200]
627 */
628HWTEST_F(PthreadTest, testPthreadCancelPoint, Function | MediumTest | Level3)
629{
630    pthread_t tid;
631    CheckStep(1);
632    ASSERT_EQ(pthread_create(&tid, nullptr, ThreadPthreadCancelPoint, nullptr), 0) << "> return errno";
633    Msleep(20);
634    EXPECT_EQ(pthread_cancel(tid), 0);
635    Msleep(100);
636    EXPECT_EQ(pthread_join(tid, NULL), 0);
637    EXPECT_EQ(CheckStep(3), (uint64_t)0x123);
638}
639
640void *ThreadPthreadCancelDisable(void *arg)
641{
642    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, nullptr);
643    CheckStep(2);
644    Msleep(50);
645    pthread_testcancel();
646    CheckStep(3);
647    return arg;
648}
649
650/**
651 * @tc.number   SUB_KERNEL_PTHREAD_CANCEL_ALL_0100
652 * @tc.name     test pthread_cancel with PTHREAD_CANCEL_DISABLE
653 * @tc.desc     [C- SOFTWARE -0200]
654 */
655HWTEST_F(PthreadTest, testPthreadCancelDisable, Function | MediumTest | Level3)
656{
657    pthread_t tid;
658    CheckStep(1);
659    ASSERT_EQ(pthread_create(&tid, nullptr, ThreadPthreadCancelDisable, nullptr), 0) << "> return errno";
660    Msleep(10);
661    EXPECT_EQ(pthread_cancel(tid), 0);
662    Msleep(100);
663    EXPECT_EQ(pthread_join(tid, NULL), 0);
664    EXPECT_EQ(CheckStep(4), (uint64_t)0x1234);
665}
666
667void *ThreadPthreadCancelAsynchronous(void *arg)
668{
669    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, nullptr);
670    CheckStep(2);
671    KeepRun(50);
672
673    // unreachable
674    CheckStep(3);
675    return arg;
676}
677
678/**
679 * @tc.number   SUB_KERNEL_PTHREAD_CANCEL_ALL_0200
680 * @tc.name     test pthread_cancel with PTHREAD_CANCEL_ASYNCHRONOUS
681 * @tc.desc     [C- SOFTWARE -0200]
682 */
683HWTEST_F(PthreadTest, testPthreadCancelAsynchronous, Function | MediumTest | Level3)
684{
685    pthread_t tid;
686    CheckStep(1);
687
688    ASSERT_EQ(pthread_create(&tid, nullptr, ThreadPthreadCancelAsynchronous, nullptr), 0) << "> return errno";
689    Msleep(10);
690    EXPECT_EQ(pthread_cancel(tid), 0);
691    Msleep(100);
692    EXPECT_EQ(pthread_join(tid, NULL), 0);
693    EXPECT_EQ(CheckStep(3), (uint64_t)0x123);
694}
695
696void *ThreadPthreadCancelDeferred(void *arg)
697{
698    pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, nullptr);
699    CheckStep(2);
700    KeepRun(50);
701    CheckStep(3);
702    Msleep(100);
703    return arg;
704}
705
706/**
707 * @tc.number   SUB_KERNEL_PTHREAD_CANCEL_ALL_0300
708 * @tc.name     test pthread_cancel with PTHREAD_CANCEL_DEFERRED
709 * @tc.desc     [C- SOFTWARE -0200]
710 */
711HWTEST_F(PthreadTest, testPthreadCancelDeferred, Function | MediumTest | Level3)
712{
713    pthread_t tid;
714    CheckStep(1);
715
716    ASSERT_EQ(pthread_create(&tid, nullptr, ThreadPthreadCancelDeferred, nullptr), 0) << "> return errno";
717    Msleep(10);
718    EXPECT_EQ(pthread_cancel(tid), 0);
719    Msleep(100);
720    EXPECT_EQ(pthread_join(tid, NULL), 0);
721    EXPECT_EQ(CheckStep(4), (uint64_t)0x1234);
722}
723
724void *ThreadPthreadCancelEnable(void *arg)
725{
726    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, nullptr);
727    CheckStep(2);
728    Msleep(50);
729    pthread_testcancel();
730    // unreachable
731    CheckStep(3);
732    return arg;
733}
734
735/**
736 * @tc.number   SUB_KERNEL_PTHREAD_CANCEL_ALL_0400
737 * @tc.name     test pthread_cancel with PTHREAD_CANCEL_ENABLE
738 * @tc.desc     [C- SOFTWARE -0200]
739 */
740HWTEST_F(PthreadTest, testPthreadCancelEnable, Function | MediumTest | Level3)
741{
742    pthread_t tid;
743    CheckStep(1);
744    ASSERT_EQ(pthread_create(&tid, nullptr, ThreadPthreadCancelEnable, nullptr), 0) << "> return errno";
745    Msleep(10);
746    EXPECT_EQ(pthread_cancel(tid), 0);
747    Msleep(100);
748    EXPECT_EQ(pthread_join(tid, NULL), 0);
749    EXPECT_EQ(CheckStep(3), (uint64_t)0x123);
750}
751
752void PreparePthreadAtfork(void)
753{
754    CheckStep(2);
755}
756
757void ParentPthreadAtfork(void)
758{
759    Msleep(20);
760    CheckStep(5);
761}
762
763void ChildPthreadAtfork(void)
764{
765    CheckStep(3);
766}
767
768/**
769 * @tc.number   SUB_KERNEL_PTHREAD_ATFORK_0100
770 * @tc.name     Basic test about pthread_atfork whit one thread
771 * @tc.desc     [C- SOFTWARE -0200]
772 */
773HWTEST_F(PthreadTest, testPthreadAtfork, Function | MediumTest | Level3)
774{
775    pid_t pid = fork();
776    ASSERT_TRUE(pid >= 0) << "> fork errno = " << errno;
777    if (pid == 0) {
778        CheckStep(1);
779        if (pthread_atfork(PreparePthreadAtfork, ParentPthreadAtfork, ChildPthreadAtfork) != 0) {
780            exit(1);
781        }
782
783        pid_t pid = fork();
784        if (pid < 0){
785            exit(1);
786        } else if (pid == 0) {
787            if (CheckStep(4) != 0x1234) {
788                exit(1);
789            }
790            exit(0);
791        }
792        if (CheckStep(6) != 0x123456) {
793            exit(1);
794        }
795
796        // check child-child exit
797        int exitCode;
798        int procStat = CheckProcStatus(pid, &exitCode, 0);
799        if (procStat != 1) {
800            exit(1);
801        }
802        if (exitCode != 0) {
803            LOG("> target process should exited 0");
804            exit(1);
805        }
806        exit(0);
807    }
808    WaitProcExitedOK(pid);
809}
810
811void PrepareNPthreadAtfork(void)
812{
813    CheckStep(2);
814}
815
816void ParentNPthreadAtfork(void)
817{
818    Msleep(20);
819    CheckStep(5);
820}
821
822void ChildNPthreadAtfork(void)
823{
824    CheckStep(3);
825}
826
827void *ThreadNPthreadAtfork(void *arg)
828{
829    CheckStep(1);
830    if (pthread_atfork(PrepareNPthreadAtfork, ParentNPthreadAtfork, ChildNPthreadAtfork) != 0) {
831        exit(1);
832    }
833    pid_t pid = fork();
834    if (pid < 0) {
835        LOG("> fork errno = %d", errno);
836        exit(1);
837    } else if (pid == 0) {
838        if (CheckStep(4) != 0x1234) {
839            exit(1);
840        }
841        exit(0);
842    }
843
844    if (CheckStep(6) != 0x123456) {
845        exit(1);
846    }
847    // check child-child exit
848    int exitCode;
849    int procStat = CheckProcStatus(pid, &exitCode, 0);
850    if (procStat != 1) {
851        exit(1);
852    }
853    if (exitCode != 0) {
854        LOG("> target process should exited 0");
855        exit(1);
856    }
857    exit(0);
858    return arg;
859}
860
861/**
862 * @tc.number   SUB_KERNEL_PTHREAD_ATFORK_0200
863 * @tc.name     Basic test about pthread_atfork whit two thread
864 * @tc.desc     [C- SOFTWARE -0200]
865 */
866HWTEST_F(PthreadTest, testNPthreadAtfork, Function | MediumTest | Level3)
867{
868    pid_t pid = fork();
869    ASSERT_TRUE(pid >= 0) << "> fork errno = " << errno;
870    if (pid == 0) {
871        pthread_t tid;
872        if (pthread_create(&tid, nullptr, ThreadNPthreadAtfork, nullptr) != 0) {
873            exit(1);
874        }
875        if (pthread_join(tid, nullptr) != 0) {
876            exit(1);
877        }
878        exit(0);
879    }
880    WaitProcExitedOK(pid);
881}
882
883void FunOnce(void)
884{
885    CheckStep(2);
886}
887
888void *ThreadOnce(void *arg)
889{
890    pthread_once_t *once = (pthread_once_t*)arg;
891    EXPECT_EQ(pthread_once(once, FunOnce), 0);
892    return arg;
893}
894
895/**
896 * @tc.number     SUB_KERNEL_PTHREAD_ONCE_0100
897 * @tc.name       pthread_once basic test
898 * @tc.desc       [C- SOFTWARE -0200]
899 */
900HWTEST_F(PthreadTest, testPthreadOnce, Function | MediumTest | Level3)
901{
902    pthread_once_t once = PTHREAD_ONCE_INIT;
903    pthread_t tid[2];
904    CheckStep(1);
905    ASSERT_EQ(pthread_create(&tid[0], nullptr, ThreadOnce, (void*)&once), 0) << "> return errno";
906    ASSERT_EQ(pthread_create(&tid[1], nullptr, ThreadOnce, (void*)&once), 0) << "> return errno";
907    EXPECT_EQ(pthread_join(tid[0], nullptr), 0) << "> return errno";
908    EXPECT_EQ(pthread_join(tid[1], nullptr), 0) << "> return errno";
909    EXPECT_EQ(CheckStep(3), (uint64_t)0x123);
910}
911