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 <semaphore.h>
19#include <pthread.h>
20#include <gtest/gtest.h>
21#include "utils.h"
22#include "log.h"
23#include "KernelConstants.h"
24#include "PthreadTest.h"
25
26using namespace testing::ext;
27
28/**
29 * @tc.number   SUB_KERNEL_PTHREAD_ATTR_SETDETACHSTATE_0100
30 * @tc.name     basic test about pthread_attr_setdetachstate
31 * @tc.desc     [C- SOFTWARE -0200]
32 */
33HWTEST_F(PthreadTest, testPthreadAttrSetdetachstate, Function | MediumTest | Level3)
34{
35    pthread_t tid;
36    pthread_attr_t attr;
37    int param;
38
39    // PTHREAD_CREATE_DETACHED
40    EXPECT_EQ(pthread_attr_init(&attr), 0);
41    EXPECT_EQ(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED), 0) << "> return errno";
42    EXPECT_EQ(pthread_attr_getdetachstate(&attr, &param), 0);
43    EXPECT_EQ(param, PTHREAD_CREATE_DETACHED);
44
45    ASSERT_EQ(pthread_create(&tid, &attr, ThreadPublic, nullptr), 0) << "> return errno";
46    EXPECT_EQ(pthread_attr_destroy(&attr), 0);
47    EXPECT_EQ(pthread_join(tid, nullptr), EINVAL) << "> return errno";
48
49    // PTHREAD_CREATE_JOINABLE
50    EXPECT_EQ(pthread_attr_init(&attr), 0);
51    EXPECT_EQ(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE), 0) << "> return errno";
52    EXPECT_EQ(pthread_attr_getdetachstate(&attr, &param), 0);
53    EXPECT_EQ(param, PTHREAD_CREATE_JOINABLE);
54
55    ASSERT_EQ(pthread_create(&tid, &attr, ThreadPublic, nullptr), 0) << "> return errno";
56    EXPECT_EQ(pthread_attr_destroy(&attr), 0);
57    EXPECT_EQ(pthread_join(tid, nullptr), 0) << "> return errno";
58}
59
60void *ThreadPthreadAttrSetscope(void *arg)
61{
62    pthread_attr_t attr;
63    int getScope;
64    int setScope = PTHREAD_SCOPE_PROCESS;
65
66    EXPECT_EQ(pthread_getattr_np(pthread_self(), &attr), 0) << "> return errno";
67    EXPECT_EQ(pthread_attr_getscope(&attr, &getScope), 0) << "> return errno";
68    LOG("getScope = %d", getScope);
69    EXPECT_EQ(getScope, setScope);
70    return arg;
71}
72
73/**
74 * @tc.number   SUB_KERNEL_PTHREAD_ATTR_SCOPE_ALL_0100
75 * @tc.name     Comprehensivetest test about competitive scope
76 * @tc.desc     [C- SOFTWARE -0200]
77 */
78HWTEST_F(PthreadTest, testPthreadAttrSetscope, Function | MediumTest | Level3)
79{
80    pthread_t tid;
81    pthread_attr_t attr;
82    int getScope;
83    const int setScope = PTHREAD_SCOPE_PROCESS;
84    EXPECT_EQ(pthread_attr_init(&attr), 0);
85    EXPECT_EQ(pthread_attr_getscope(&attr, &getScope), 0) << "> return errno";
86    LOG("getScope = %d", getScope);
87
88    EXPECT_EQ(pthread_attr_setscope(&attr, setScope), 0) << "> return errno";
89    EXPECT_EQ(pthread_attr_getscope(&attr, &getScope), 0) << "> return errno";
90    LOG("getScope = %d", getScope);
91    EXPECT_EQ(getScope, setScope);
92
93    ASSERT_EQ(pthread_create(&tid, &attr, ThreadPthreadAttrSetscope, nullptr), 0) << "> return errno";
94
95    Msleep(20);
96    pthread_join(tid, nullptr);
97    EXPECT_EQ(pthread_attr_destroy(&attr), 0);
98}
99
100void *ThreadPthreadAttrSetguardsize(void *arg)
101{
102    pthread_attr_t attr;
103    size_t getGuardSize;
104    const size_t setGuardSize = DEF_PROCESS_GUARD_SIZE * 2;
105
106    EXPECT_EQ(pthread_getattr_np(pthread_self(), &attr), 0) << "> return errno";
107    EXPECT_EQ(pthread_attr_getguardsize(&attr, &getGuardSize), 0) << "> return errno";
108    LOG("getGuardSize = %ld", getGuardSize);
109    EXPECT_EQ(getGuardSize, setGuardSize);
110    return arg;
111}
112
113/**
114 * @tc.number   SUB_KERNEL_PTHREAD_ATTR_SETGUARDSIZE_0100
115 * @tc.name     basic test about pthread_attr_setguardsize
116 * @tc.desc     [C- SOFTWARE -0200]
117 */
118HWTEST_F(PthreadTest, testPthreadAttrSetguardsize, Function | MediumTest | Level3)
119{
120    pthread_t tid;
121    pthread_attr_t attr;
122    size_t getGuardSize;
123    const size_t setGuardSize = DEF_PROCESS_GUARD_SIZE * 2;
124    EXPECT_EQ(pthread_attr_init(&attr), 0);
125    EXPECT_EQ(pthread_attr_getguardsize(&attr, &getGuardSize), 0) << "> return errno";
126    LOG("getGuardSize = %ld", getGuardSize);
127
128    EXPECT_EQ(pthread_attr_setguardsize(&attr, setGuardSize), 0) << "> return errno";
129    EXPECT_EQ(pthread_attr_getguardsize(&attr, &getGuardSize), 0) << "> return errno";
130    LOG("getGuardSize = %ld", getGuardSize);
131    EXPECT_EQ(getGuardSize, setGuardSize);
132
133    ASSERT_EQ(pthread_create(&tid, &attr, ThreadPthreadAttrSetguardsize, nullptr), 0) << "> return errno";
134
135    Msleep(20);
136    pthread_join(tid, nullptr);
137    EXPECT_EQ(pthread_attr_destroy(&attr), 0);
138}
139
140void *ThreadPthreadAttrSetstacksize(void *arg)
141{
142    pthread_attr_t attr;
143    size_t stackSize;
144    size_t guardSize;
145
146    EXPECT_EQ(pthread_getattr_np(pthread_self(), &attr), 0) << "> return errno";
147    EXPECT_EQ(pthread_attr_getstacksize(&attr, &stackSize), 0) << "> return errno";
148    EXPECT_EQ(pthread_attr_getguardsize(&attr, &guardSize), 0) << "> return errno";
149    LOG("stackSize = %ld", stackSize);
150    LOG("guardSize = %ld", guardSize);
151    // must >= setsize
152    EXPECT_GE(stackSize, PTHREAD_STACK_MIN);
153    return arg;
154}
155
156/**
157 * @tc.number   SUB_KERNEL_PTHREAD_ATTR_SETSTACKSIZE_0100
158 * @tc.name     basic test about pthread_attr_setstacksize
159 * @tc.desc     [C- SOFTWARE -0200]
160 */
161HWTEST_F(PthreadTest, testPthreadAttrSetstacksize, Function | MediumTest | Level3)
162{
163    pthread_t tid;
164    pthread_attr_t attr;
165    size_t stackSize;
166
167    EXPECT_EQ(pthread_attr_init(&attr), 0);
168    EXPECT_EQ(pthread_attr_getstacksize(&attr, &stackSize), 0) << "> return errno";
169    stackSize = PTHREAD_STACK_MIN;
170    LOG("PTHREAD_STACK_MIN = %d", PTHREAD_STACK_MIN);
171    EXPECT_EQ(pthread_attr_setstacksize(&attr, stackSize), 0) << "> return errno";
172    EXPECT_EQ(pthread_attr_getstacksize(&attr, &stackSize), 0) << "> return errno";
173    LOG("stackSize = %d", stackSize);
174    EXPECT_EQ(stackSize, PTHREAD_STACK_MIN);
175
176    ASSERT_EQ(pthread_create(&tid, &attr, ThreadPthreadAttrSetstacksize, nullptr), 0) << "> return errno";
177
178    Msleep(20);
179    pthread_join(tid, nullptr);
180    EXPECT_EQ(pthread_attr_destroy(&attr), 0);
181}
182
183/**
184 * @tc.number   SUB_KERNEL_PTHREAD_ATTR_SETSTACKSIZE_0200
185 * @tc.name     test pthread_attr_setstacksize EINVAL
186 * @tc.desc     [C- SOFTWARE -0200]
187 */
188HWTEST_F(PthreadTest, testPthreadAttrSetstacksizeEINVAL, Function | MediumTest | Level3)
189{
190    pthread_attr_t attr;
191    size_t stackSize;
192
193    EXPECT_EQ(pthread_attr_init(&attr), 0);
194    EXPECT_EQ(pthread_attr_getstacksize(&attr, &stackSize), 0) << "> return errno";
195    stackSize = PTHREAD_STACK_MIN - 1;
196    LOG("PTHREAD_STACK_MIN = %d", PTHREAD_STACK_MIN);
197    EXPECT_EQ(pthread_attr_setstacksize(&attr, stackSize), EINVAL) << "> return errno";
198    EXPECT_EQ(pthread_attr_destroy(&attr), 0);
199}
200
201void *ThreadPthreadAttrSetstack(void *arg)
202{
203    pthread_attr_t attr;
204    void *stackAddr1 = nullptr;
205    size_t stackSize = 0;
206
207    EXPECT_EQ(pthread_getattr_np(pthread_self(), &attr), 0) << "> return errno";
208    EXPECT_EQ(pthread_attr_getstack(&attr, &stackAddr1, &stackSize), 0) << "> return errno";
209    EXPECT_GE(stackSize, PTHREAD_STACK_MIN);
210    return arg;
211}
212
213/**
214 * @tc.number   SUB_KERNEL_PTHREAD_ATTR_SETSTACK_0100
215 * @tc.name     basic test about pthread_attr_setstack
216 * @tc.desc     [C- SOFTWARE -0200]
217 */
218HWTEST_F(PthreadTest, testPthreadAttrSetstack, Function | MediumTest | Level3)
219{
220    pthread_t tid;
221    pthread_attr_t attr;
222    void *stackAddr = nullptr;
223    size_t stackSize;
224
225    EXPECT_EQ(pthread_attr_init(&attr), 0);
226
227    stackAddr = malloc(PTHREAD_STACK_MIN);
228    ASSERT_NE(stackAddr, nullptr);
229    LOG("stackAddr = %p", stackAddr);
230
231    stackSize = PTHREAD_STACK_MIN;
232    posix_memalign(&stackAddr, getpagesize(), stackSize);
233    LOG("getpagesize() = %d", getpagesize());
234    LOG("stackAddr = %p", stackAddr);
235
236    EXPECT_EQ(pthread_attr_setstack(&attr, stackAddr, stackSize), 0) << "> return errno";
237    LOG("stackAddr = %p", stackAddr);
238    EXPECT_EQ(pthread_attr_getstack(&attr, &stackAddr, &stackSize), 0) << "> return errno";
239    LOG("stackAddr = %p", stackAddr);
240    EXPECT_EQ(stackSize, PTHREAD_STACK_MIN);
241
242    EXPECT_EQ(pthread_create(&tid, &attr, ThreadPthreadAttrSetstack, stackAddr), 0) << "> return errno";
243    Msleep(100);
244    pthread_join(tid, nullptr);
245    EXPECT_EQ(pthread_attr_destroy(&attr), 0);
246}
247
248/**
249 * @tc.number   SUB_KERNEL_PTHREAD_ATTR_GETSTACK_0100
250 * @tc.name     test pthread_attr_setstack about return EINVAL
251 * @tc.desc     [C- SOFTWARE -0200]
252 */
253HWTEST_F(PthreadTest, testPthreadAttrGetstackEINVAL, Function | MediumTest | Level3)
254{
255    pthread_attr_t attr;
256    void *stackAddr = nullptr;
257    size_t stackSize;
258    EXPECT_EQ(pthread_attr_init(&attr), 0);
259    EXPECT_EQ(pthread_attr_getstack(&attr, &stackAddr, &stackSize), EINVAL) << "> return errno != EINVAL";
260    EXPECT_EQ(pthread_attr_destroy(&attr), 0);
261}
262
263void *ThreadPthreadGetattrNp(void *arg)
264{
265    pthread_attr_t attr;
266    size_t stackSize;
267    size_t guardSize;
268    int param;
269
270    EXPECT_EQ(pthread_getattr_np(pthread_self(), &attr), 0) << "> return errno";
271
272    EXPECT_EQ(pthread_attr_getstacksize(&attr, &stackSize), 0) << "> return errno";
273    // must >= DEF_PROCESS_STACK_SIZE
274    EXPECT_GE(stackSize, DEF_PROCESS_STACK_SIZE);
275
276    EXPECT_EQ(pthread_attr_getguardsize(&attr, &guardSize), 0) << "> return errno";
277    EXPECT_EQ(guardSize, DEF_PROCESS_GUARD_SIZE);
278
279    EXPECT_EQ(pthread_attr_getdetachstate(&attr, &param), 0);
280    EXPECT_EQ(param, DEF_PROCESS_DETACHSTATE);
281
282    EXPECT_EQ(pthread_attr_destroy(&attr), 0);
283
284    LOG("stackSize = %ld", stackSize);
285    LOG("guardSize; = %ld", guardSize);
286    return arg;
287}
288
289/**
290 * @tc.number   SUB_KERNEL_PTHREAD_GETATTR_NP_0100
291 * @tc.name     basic about about pthread_getattr_np
292 * @tc.desc     [C- SOFTWARE -0200]
293 */
294HWTEST_F(PthreadTest, testPthreadGetattrNp, Function | MediumTest | Level3)
295{
296    pthread_t tid;
297    EXPECT_EQ(pthread_create(&tid, nullptr, ThreadPthreadGetattrNp, nullptr), 0) << "> return errno";
298    Msleep(100);
299    pthread_join(tid, nullptr);
300}
301