1/*
2 * Copyright (c) 2023-2023 Huawei Device Co., Ltd. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification,
5 * are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 *    conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 *    of conditions and the following disclaimer in the documentation and/or other materials
12 *    provided with the distribution.
13 *
14 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
15 *    to endorse or promote products derived from this software without specific prior written
16 *    permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include "xts_ipc.h"
32
33static int g_semTestStep = 0;
34
35LITE_TEST_SUIT(IPC, SemApi, IpcSemApiTestSuite);
36
37static BOOL IpcSemApiTestSuiteSetUp(void)
38{
39    return TRUE;
40}
41
42static BOOL IpcSemApiTestSuiteTearDown(void)
43{
44    return TRUE;
45}
46
47LITE_TEST_CASE(IpcSemApiTestSuite, testSemInit0100, Function | MediumTest | Level2)
48{
49    int ret;
50    sem_t sem;
51    int testValue[3] = {0, 1, 10}; /* 3, 1, 10 common data for test, no special meaning */
52
53    int index = (int)(sizeof(testValue) / sizeof(int));
54    for (int i = 0; i < index; i++) {
55
56        ret = sem_init((sem_t *)&sem, 0, testValue[0]);
57        ICUNIT_ASSERT_EQUAL(ret, 0, ret);
58
59        ret = sem_destroy(&sem);
60        ICUNIT_ASSERT_EQUAL(ret, 0, ret);
61    }
62    return 0;
63}
64
65LITE_TEST_CASE(IpcSemApiTestSuite, testSemPost0100, Function | MediumTest | Level2)
66{
67    int ret;
68    sem_t sem;
69
70    ret = sem_init((sem_t *)&sem, 0, 0);
71    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
72
73    ret = sem_post(&sem);
74    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
75
76    ret = sem_post(&sem);
77    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
78
79    ret = sem_post(&sem);
80    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
81
82    ret = sem_destroy(&sem);
83    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
84    return 0;
85}
86
87LITE_TEST_CASE(IpcSemApiTestSuite, testSemWait0100, Function | MediumTest | Level2)
88{
89    int ret;
90    sem_t sem;
91
92    ret = sem_init((sem_t *)&sem, 0, 3); /* 3, common data for test, no special meaning */
93    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
94
95    ret = sem_wait(&sem);
96    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
97
98    ret = sem_wait(&sem);
99    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
100
101    ret = sem_wait(&sem);
102    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
103
104    ret = sem_destroy(&sem);
105    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
106    return 0;
107}
108
109void *ThreadChat(void *arg)
110{
111    int ret;
112    sem_t *sem = (sem_t *)arg;
113
114    ICUNIT_ASSERT_EQUAL(g_semTestStep, 0, g_semTestStep);
115
116    g_semTestStep = 1; /* 1, common data for test, no special meaning */
117    ret = sem_wait(sem);
118    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
119
120    g_semTestStep = 2; /* 2, common data for test, no special meaning */
121    return NULL;
122}
123
124LITE_TEST_CASE(IpcSemApiTestSuite, testThreadChat0100, Function | MediumTest | Level3)
125{
126    pthread_t tid;
127    sem_t sem;
128    int ret;
129    struct timespec req;
130    g_semTestStep = 0;
131
132    ret = sem_init((sem_t *)&sem, 0, 0);
133    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
134
135    ret = pthread_create(&tid, NULL, ThreadChat, (void *)&sem);
136    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
137
138    req.tv_sec = 0;
139    req.tv_nsec = TEN_CONT * NANO_MS;
140    ret = nanosleep(&req, NULL);
141    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
142    ICUNIT_ASSERT_EQUAL(g_semTestStep, 1, g_semTestStep); /* 1, common data for test, no special meaning */
143
144    ret = sem_post(&sem);
145    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
146
147    ret = nanosleep(&req, NULL);
148    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
149    ICUNIT_ASSERT_EQUAL(g_semTestStep, 2, g_semTestStep); /* 2, common data for test, no special meaning */
150
151    ret = sem_post(&sem);
152    ICUNIT_ASSERT_EQUAL(g_semTestStep, 2, g_semTestStep); /* 2, common data for test, no special meaning */
153
154    ret = pthread_join(tid, NULL);
155    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
156
157    ret = sem_destroy(&sem);
158    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
159    return 0;
160}
161
162void *ThreadNThreadWait1(void *arg)
163{
164    int ret;
165    sem_t *sem = (sem_t *)arg;
166    struct timespec req;
167
168    req.tv_sec = 0;
169    req.tv_nsec = HUNDRED_CONT * NANO_MS;
170
171    ret = nanosleep(&req, NULL);
172    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
173    g_semTestStep = 1; /* 1, common data for test, no special meaning */
174    ret = sem_wait(sem);
175    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
176
177    g_semTestStep = 2; /* 2, common data for test, no special meaning */
178    return NULL;
179}
180
181void *ThreadNThreadWait2(void *arg)
182{
183    int ret;
184    sem_t *sem = (sem_t *)arg;
185    struct timespec req;
186
187    req.tv_sec = 0;
188    req.tv_nsec = 300 * NANO_MS; /* 300, common data for test, no special meaning */
189    ret = nanosleep(&req, NULL);
190    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
191    g_semTestStep = 3; /* 3, common data for test, no special meaning */
192
193    req.tv_nsec = 200 * NANO_MS; /* 200, common data for test, no special meaning */
194    ret = nanosleep(&req, NULL);
195    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
196    ret = sem_wait(sem);
197    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
198
199    g_semTestStep = 4; /* 4, common data for test, no special meaning */
200    return NULL;
201}
202
203LITE_TEST_CASE(IpcSemApiTestSuite, testThreadChat0400, Function | MediumTest | Level4)
204{
205    pthread_t tid1;
206    pthread_t tid2;
207    sem_t sem;
208    int ret;
209    struct timespec req;
210
211    req.tv_sec = 0;
212    req.tv_nsec = 200 * NANO_MS; /* 200, common data for test, no special meaning */
213    g_semTestStep = 0;
214
215    ret = sem_init((sem_t *)&sem, 0, 0);
216    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
217
218    ret = pthread_create(&tid1, NULL, ThreadNThreadWait1, (void *)&sem);
219    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
220
221    ret = pthread_create(&tid2, NULL, ThreadNThreadWait2, (void *)&sem);
222    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
223
224    ret = nanosleep(&req, NULL);
225    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
226    ICUNIT_ASSERT_EQUAL(g_semTestStep, 1, g_semTestStep); /* 1, common data for test, no special meaning */
227
228    ret = sem_post(&sem);
229    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
230
231    req.tv_nsec = 20 * NANO_MS; /* 20, common data for test, no special meaning */
232    ret = nanosleep(&req, NULL);
233    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
234    ICUNIT_ASSERT_EQUAL(g_semTestStep, 2, g_semTestStep); /* 2, common data for test, no special meaning */
235
236    req.tv_nsec = 200 * NANO_MS; /* 200, common data for test, no special meaning */
237    ret = nanosleep(&req, NULL);
238    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
239    ICUNIT_ASSERT_EQUAL(g_semTestStep, 3, g_semTestStep); /* 3, common data for test, no special meaning */
240
241    ret = sem_post(&sem);
242    req.tv_nsec = 20 * NANO_MS; /* 20, common data for test, no special meaning */
243    ret = nanosleep(&req, NULL);
244    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
245    ICUNIT_ASSERT_EQUAL(g_semTestStep, 3, g_semTestStep); /* 3, common data for test, no special meaning */
246
247    ret = pthread_join(tid1, NULL);
248    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
249
250    ret = pthread_join(tid2, NULL);
251    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
252
253    ICUNIT_ASSERT_EQUAL(g_semTestStep, 4, g_semTestStep); /* 4, common data for test, no special meaning */
254
255    ret = sem_destroy(&sem);
256    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
257    return 0;
258}
259
260LITE_TEST_CASE(IpcSemApiTestSuite, testSemInitAbnormal0200, Function | MediumTest | Level3)
261{
262    int ret;
263    sem_t sem;
264    unsigned int gtSemMax = (unsigned int)SEM_VALUE_MAX + 1; /* 1, common data for test, no special meaning */
265
266    ret = sem_init(&sem, 0, SEM_VALUE_MAX);
267    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
268
269    ret = sem_destroy(&sem);
270    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
271
272    ret = sem_init(&sem, 0, gtSemMax);
273    ICUNIT_ASSERT_EQUAL(ret, -1, ret); /* -1, common data for test, no special meaning */
274
275    ICUNIT_ASSERT_EQUAL(errno, EINVAL, errno);
276
277    ret = sem_init(&sem, 0, 1); /* 1, common data for test, no special meaning */
278    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
279
280    ret = sem_destroy(&sem);
281    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
282    return 0;
283}
284
285LITE_TEST_CASE(IpcSemApiTestSuite, testSemPostAbnormal, Function | MediumTest | Level3)
286{
287    int ret;
288    sem_t sem;
289
290    ret = sem_init(&sem, 0, SEM_VALUE_MAX);
291    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
292
293    ret = sem_post(&sem);
294    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
295
296    ret = sem_destroy(&sem);
297    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
298    return 0;
299}
300
301LITE_TEST_CASE(IpcSemApiTestSuite, testSemTimedWaitAbnormalA, Function | MediumTest | Level3)
302{
303    int ret;
304    struct timespec ts;
305    sem_t sem;
306
307    ret = sem_init(&sem, 0, 0);
308    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
309
310    ts.tv_sec = 0;
311    ts.tv_nsec = -2; /* -2, common data for test, no special meaning */
312    ret = sem_timedwait(&sem, &ts);
313    ICUNIT_ASSERT_EQUAL(ret, -1, ret); /* -1, common data for test, no special meaning */
314
315    ICUNIT_ASSERT_EQUAL(errno, EINVAL, errno);
316
317    ret = sem_destroy(&sem);
318    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
319    return 0;
320}
321
322LITE_TEST_CASE(IpcSemApiTestSuite, testSemTimedWaitAbnormalB, Function | MediumTest | Level3)
323{
324    int ret;
325    struct timespec ts;
326    sem_t sem;
327
328    ret = sem_init(&sem, 0, 0);
329    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
330
331    ts.tv_sec = time(NULL);
332    ts.tv_nsec = NANO_S;
333    ret = sem_timedwait(&sem, &ts);
334    ICUNIT_ASSERT_EQUAL(ret, -1, ret); /* -1, common data for test, no special meaning */
335
336    ICUNIT_ASSERT_EQUAL(errno, EINVAL, errno);
337
338    ret = sem_destroy(&sem);
339    ICUNIT_ASSERT_EQUAL(ret, 0, ret);
340    return 0;
341}
342
343RUN_TEST_SUITE(IpcSemApiTestSuite);
344
345void PosixSemFuncTest()
346{
347    RUN_ONE_TESTCASE(testSemInit0100);
348    RUN_ONE_TESTCASE(testSemPost0100);
349    RUN_ONE_TESTCASE(testSemWait0100);
350    RUN_ONE_TESTCASE(testThreadChat0100);
351    RUN_ONE_TESTCASE(testThreadChat0400);
352    RUN_ONE_TESTCASE(testSemInitAbnormal0200);
353    RUN_ONE_TESTCASE(testSemPostAbnormal);
354    RUN_ONE_TESTCASE(testSemTimedWaitAbnormalA);
355    RUN_ONE_TESTCASE(testSemTimedWaitAbnormalB);
356}