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 
24 using namespace testing::ext;
25 
26 static const unsigned int KERNEL_NS_PER_SECOND = 1000000000;
27 static const unsigned int KERNEL_100MS_BY_NS = 100000000;
28 
29 class SemTest : public::testing::Test {
30 };
31 
32 /**
33  * @tc.number   SUB_KERNEL_IPC_SEM_INIT_0100
34  * @tc.name     Use sem_init initialize the semaphore with 0
35  * @tc.desc     [C- SOFTWARE -0200]
36  */
HWTEST_F(SemTest, testSemInitA, Function | MediumTest | Level2)37 HWTEST_F(SemTest, testSemInitA, Function | MediumTest | Level2)
38 {
39     sem_t sem;
40     int semValue = 0;
41     int testValue = 0;
42 
43     EXPECT_NE(sem_init(&sem, 0, testValue), -1) << "> sem_init errno = " << errno;
44     EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno;
45     EXPECT_TRUE(semValue == testValue);
46     EXPECT_EQ(sem_destroy(&sem), 0) << "> sem_destroy errno = " << errno;
47 }
48 
49 /**
50  * @tc.number   SUB_KERNEL_IPC_SEM_INIT_0110
51  * @tc.name     Use sem_init initialize the semaphore with 1
52  * @tc.desc     [C- SOFTWARE -0200]
53  */
HWTEST_F(SemTest, testSemInitB, Function | MediumTest | Level2)54 HWTEST_F(SemTest, testSemInitB, Function | MediumTest | Level2)
55 {
56     sem_t sem;
57     int semValue = 0;
58     int testValue = 1;
59 
60     EXPECT_NE(sem_init(&sem, 0, testValue), -1) << "> sem_init errno = " << errno;
61     EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno;
62     EXPECT_EQ(semValue, testValue);
63     EXPECT_EQ(sem_destroy(&sem), 0) << "> sem_destroy errno = " << errno;
64 }
65 
66 /**
67  * @tc.number   SUB_KERNEL_IPC_SEM_INIT_0120
68  * @tc.name     Use sem_init initialize the semaphore with 100
69  * @tc.desc     [C- SOFTWARE -0200]
70  */
HWTEST_F(SemTest, testSemInitC, Function | MediumTest | Level2)71 HWTEST_F(SemTest, testSemInitC, Function | MediumTest | Level2)
72 {
73     sem_t sem;
74     int semValue = 0;
75     int testValue = 10;
76 
77     EXPECT_NE(sem_init(&sem, 0, testValue), -1) << "> sem_init errno = " << errno;
78     EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno;
79     EXPECT_EQ(semValue, testValue);
80     EXPECT_EQ(sem_destroy(&sem), 0) << "> sem_destroy errno = " << errno;
81 }
82 
83 /**
84  * @tc.number   SUB_KERNEL_IPC_SEM_POST_0100
85  * @tc.name     sem_post increases the semaphore count
86  * @tc.desc     [C- SOFTWARE -0200]
87  */
HWTEST_F(SemTest, testSemPost, Function | MediumTest | Level2)88 HWTEST_F(SemTest, testSemPost, Function | MediumTest | Level2)
89 {
90     sem_t sem;
91     int semValue = 0;
92 
93     ASSERT_NE(sem_init(&sem, 0, 0), -1) << "> sem_init errno = " << errno;
94     EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno;
95     EXPECT_EQ(semValue, 0);
96 
97     EXPECT_EQ(sem_post(&sem), 0) << "> sem_post errno = " << errno;
98     EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno;
99     EXPECT_EQ(semValue, 1);
100 
101     EXPECT_EQ(sem_post(&sem), 0) << "> sem_post errno = " << errno;
102     EXPECT_EQ(sem_post(&sem), 0) << "> sem_post errno = " << errno;
103     EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno;
104     EXPECT_EQ(semValue, 3);
105 
106     EXPECT_EQ(sem_destroy(&sem), 0) << "> sem_destroy errno = " << errno;
107 }
108 
109 /**
110  * @tc.number   SUB_KERNEL_IPC_SEM_WAIT_0100
111  * @tc.name     sem_wait get semaphore
112  * @tc.desc     [C- SOFTWARE -0200]
113  */
HWTEST_F(SemTest, testSemWait, Function | MediumTest | Level2)114 HWTEST_F(SemTest, testSemWait, Function | MediumTest | Level2)
115 {
116     sem_t sem;
117     int semValue = 0;
118 
119     ASSERT_NE(sem_init(&sem, 0, 3), -1) << "> sem_init errno = " << errno;
120     EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno;
121     EXPECT_EQ(semValue, 3);
122 
123     EXPECT_EQ(sem_wait(&sem), 0) << "> sem_wait errno = " << errno;
124     EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno;
125     EXPECT_EQ(semValue, 2);
126 
127     EXPECT_EQ(sem_wait(&sem), 0) << "> sem_wait errno = " << errno;
128     EXPECT_EQ(sem_wait(&sem), 0) << "> sem_wait errno = " << errno;
129     EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno;
130     EXPECT_EQ(semValue, 0);
131 
132     EXPECT_EQ(sem_destroy(&sem), 0) << "> sem_destroy errno = " << errno;
133 }
134 
135 /**
136  * @tc.number   SUB_KERNEL_IPC_SEM_TRYWAIT_0100
137  * @tc.name     sem_trywait get semaphore
138  * @tc.desc     [C- SOFTWARE -0200]
139  */
HWTEST_F(SemTest, testSemTryWait, Function | MediumTest | Level2)140 HWTEST_F(SemTest, testSemTryWait, Function | MediumTest | Level2)
141 {
142     sem_t sem;
143     int semValue = 0;
144 
145     ASSERT_NE(sem_init(&sem, 0, 3), -1) << "> sem_init errno = " << errno;
146     EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno;
147     EXPECT_EQ(semValue, 3);
148 
149     EXPECT_EQ(sem_trywait(&sem), 0) << "> sem_trywait errno = " << errno;
150     EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno;
151     EXPECT_EQ(semValue, 2);
152 
153     EXPECT_EQ(sem_trywait(&sem), 0) << "> sem_trywait errno = " << errno;
154     EXPECT_EQ(sem_trywait(&sem), 0) << "> sem_trywait errno = " << errno;
155     EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno;
156     EXPECT_EQ(semValue, 0);
157     EXPECT_EQ(sem_destroy(&sem), 0) << "> sem_destroy errno = " << errno;
158 }
159 
160 /**
161  * @tc.number   SUB_KERNEL_IPC_SEM_DESTROY_0100
162  * @tc.name     check sem_destroy function
163  * @tc.desc     [C- SOFTWARE -0200]
164  */
HWTEST_F(SemTest, testSemdestroy, Function | MediumTest | Level3)165 HWTEST_F(SemTest, testSemdestroy, Function | MediumTest | Level3)
166 {
167     sem_t sem;
168     ASSERT_EQ(sem_init(&sem, 0, 0), 0) << "> sem_init errno = " << errno;
169     EXPECT_EQ(sem_destroy(&sem), 0) << "> sem_destroy errno = " << errno;
170 }
171 
ThreadChat(void *arg)172 void *ThreadChat(void *arg)
173 {
174     sem_t *sem = (sem_t*)arg;
175     int semValue = 0;
176 
177     EXPECT_EQ(sem_getvalue(sem, &semValue), 0) << "sem_getvalue errno = " << errno;
178     EXPECT_EQ(semValue, 0);
179     EXPECT_EQ(sem_wait(sem), 0) << "sem_wait errno = " << errno;
180     return nullptr;
181 }
182 
183 /**
184  * @tc.number   SUB_KERNEL_IPC_SEM_CHAT_0100
185  * @tc.name     Inter-thread communication, check sem_wait function
186  * @tc.desc     [C- SOFTWARE -0200]
187  */
HWTEST_F(SemTest, testThreadChat, Function | MediumTest | Level3)188 HWTEST_F(SemTest, testThreadChat, Function | MediumTest | Level3)
189 {
190     pthread_t tid;
191     sem_t sem;
192     int reInt = 0;
193     int semValue = 0;
194 
195     ASSERT_EQ(sem_init(&sem, 0, 0), 0) << "> sem_init errno = " << errno;
196 
197     reInt = pthread_create(&tid, nullptr, ThreadChat, (void*)&sem);
198     ASSERT_EQ(reInt, 0) << "> pthread_create errno, reInt = " << reInt;
199 
200     Msleep(20);
201     EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno;
202     EXPECT_EQ(semValue, 0);
203 
204     EXPECT_EQ(sem_post(&sem), 0) << "sem_post errno = " << errno;
205     EXPECT_EQ(sem_post(&sem), 0) << "sem_post errno = " << errno;
206 
207     Msleep(20);
208     EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno;
209     EXPECT_EQ(semValue, 1);
210 
211     reInt = pthread_join(tid, nullptr);
212     EXPECT_EQ(reInt, 0) << "pthread_join failed, errno=" << reInt;
213     EXPECT_EQ(sem_destroy(&sem), 0) << "> sem_destroy errno = " << errno;
214 }
215 
ThreadSemTryWait(void *arg)216 void *ThreadSemTryWait(void *arg)
217 {
218     sem_t *sem = (sem_t*)arg;
219     int semValue = 0;
220     int loop = 10;
221 
222     EXPECT_EQ(sem_getvalue(sem, &semValue), 0) << "sem_getvalue errno = " << errno;
223     EXPECT_EQ(semValue, 0);
224     for (int i = 0; i < loop; i++) {
225         if (sem_trywait(sem) == 0) {
226             break;
227 
228         }
229         Msleep(10);
230     }
231     return nullptr;
232 }
233 
234 /**
235  * @tc.number   SUB_KERNEL_IPC_SEM_CHAT_0200
236  * @tc.name     basic function test : Inter-thread communication, check sem_trywait function
237  * @tc.desc     [C- SOFTWARE -0200]
238  */
HWTEST_F(SemTest, testThreadSemTryWait, Function | MediumTest | Level3)239 HWTEST_F(SemTest, testThreadSemTryWait, Function | MediumTest | Level3)
240 {
241     sem_t sem;
242     int reInt = 0;
243     int semValue = 0;
244 
245     ASSERT_EQ(sem_init(&sem, 0, 0), 0) << "> sem_init errno = " << errno;
246 
247     pthread_t tid;
248     reInt = pthread_create(&tid, nullptr, ThreadSemTryWait, (void*)&sem);
249     ASSERT_EQ(reInt, 0) << "> pthread_create errno, reInt = " << reInt;
250 
251     Msleep(20);
252     EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno;
253     EXPECT_EQ(semValue, 0);
254 
255     EXPECT_EQ(sem_post(&sem), 0) << "sem_post errno = " << errno;
256     EXPECT_EQ(sem_post(&sem), 0) << "sem_post errno = " << errno;
257 
258     reInt = pthread_join(tid, nullptr);
259     EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno;
260 
261     if (semValue == 1 || semValue == 2) {
262         EXPECT_TRUE(true);
263         LOG("semValue = %d", semValue);
264     } else {
265         EXPECT_TRUE(false);
266         LOG("semValue errno, semValue = %d", semValue);
267     }
268 
269     EXPECT_EQ(reInt, 0) << "pthread_join failed, errno=" << reInt;
270     EXPECT_EQ(sem_destroy(&sem), 0) << "> sem_destroy errno = " << errno;
271 }
272 
ThreadSemTimedWait(void *arg)273 void *ThreadSemTimedWait(void *arg)
274 {
275     struct timespec ts = {0};
276     sem_t *sem = (sem_t*)arg;
277     int semValue = 0;
278 
279     EXPECT_EQ(sem_getvalue(sem, &semValue), 0) << "sem_getvalue errno = " << errno;
280     EXPECT_EQ(semValue, 0);
281 
282     clock_gettime(CLOCK_REALTIME, &ts);
283     ts.tv_sec = ts.tv_sec + (ts.tv_nsec + KERNEL_100MS_BY_NS) / KERNEL_NS_PER_SECOND;
284     ts.tv_nsec = (ts.tv_nsec + KERNEL_100MS_BY_NS) % KERNEL_NS_PER_SECOND;
285     Msleep(50);
286     EXPECT_EQ(sem_timedwait(sem, &ts), 0) << "sem_timedwait errno = " << errno;
287     EXPECT_EQ(sem_getvalue(sem, &semValue), 0) << "sem_getvalue errno = " << errno;
288 
289     Msleep(100);
290     EXPECT_EQ(semValue, 1);
291     return nullptr;
292 }
293 
294 /**
295  * @tc.number   SUB_KERNEL_IPC_SEM_CHAT_0300
296  * @tc.name     Inter-thread communication, check sem_timedwait function
297  * @tc.desc     [C- SOFTWARE -0200]
298  */
HWTEST_F(SemTest, testThreadSemTimedWait, Function | MediumTest | Level3)299 HWTEST_F(SemTest, testThreadSemTimedWait, Function | MediumTest | Level3)
300 {
301     pthread_t tid;
302     sem_t sem;
303     int reInt = 0;
304     int semValue = 0;
305 
306     ASSERT_EQ(sem_init(&sem, 0, 0), 0) << "> sem_init errno = " << errno;
307 
308     reInt = pthread_create(&tid, nullptr, ThreadSemTimedWait, (void*)&sem);
309     ASSERT_EQ(reInt, 0) << "> pthread_create errno, reInt = " << reInt;
310 
311     Msleep(10);
312     EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno;
313     EXPECT_EQ(semValue, 0);
314     EXPECT_EQ(sem_post(&sem), 0) << "> sem_post errno = " << errno;
315     EXPECT_EQ(sem_post(&sem), 0) << "> sem_post errno = " << errno;
316 
317     reInt = pthread_join(tid, nullptr);
318     EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno;
319     EXPECT_EQ(semValue, 1);
320     EXPECT_EQ(reInt, 0) << "pthread_join failed, errno=" << reInt;
321     EXPECT_EQ(sem_destroy(&sem), 0) << "> sem_destroy errno = " << errno;
322 }
323 
ThreadNThreadWait1(void *arg)324 void *ThreadNThreadWait1(void *arg)
325 {
326     sem_t *sem = (sem_t*)arg;
327     int semValue = 0;
328 
329     Msleep(100);
330     EXPECT_EQ(sem_getvalue(sem, &semValue), 0) << "sem_getvalue errno = " << errno;
331     EXPECT_EQ(semValue, 0);
332     EXPECT_EQ(sem_wait(sem), 0) << "sem_wait errno = " << errno;
333     return nullptr;
334 }
335 
ThreadNThreadWait2(void *arg)336 void *ThreadNThreadWait2(void *arg)
337 {
338     sem_t *sem = (sem_t*)arg;
339     int semValue = 0;
340     EXPECT_EQ(sem_getvalue(sem, &semValue), 0) << "sem_getvalue errno = " << errno;
341     EXPECT_EQ(semValue, 0);
342 
343     Msleep(300);
344     EXPECT_EQ(sem_getvalue(sem, &semValue), 0) << "sem_getvalue errno = " << errno;
345     EXPECT_EQ(semValue, 0);
346 
347     Msleep(200);
348     EXPECT_EQ(sem_getvalue(sem, &semValue), 0) << "sem_getvalue errno = " << errno;
349     EXPECT_EQ(semValue, 1);
350     EXPECT_EQ(sem_wait(sem), 0) << "sem_wait errno = " << errno;
351     return nullptr;
352 }
353 
354 /**
355  * @tc.number   SUB_KERNEL_IPC_SEM_CHAT_0400
356  * @tc.name     N threads wait, main thread post
357  * @tc.desc     [C- SOFTWARE -0200]
358  */
HWTEST_F(SemTest, testNThreadWait, Function | MediumTest | Level4)359 HWTEST_F(SemTest, testNThreadWait, Function | MediumTest | Level4)
360 {
361     pthread_t tid1;
362     pthread_t tid2;
363     sem_t sem;
364     int reInt = 0;
365     int semValue = 0;
366 
367     ASSERT_EQ(sem_init(&sem, 0, 0), 0) << "> sem_init errno = " << errno;
368 
369     reInt = pthread_create(&tid1, nullptr, ThreadNThreadWait1, (void*)&sem);
370     ASSERT_EQ(reInt, 0) << "> pthread_create errno, reInt = " << reInt;
371 
372     reInt = pthread_create(&tid2, nullptr, ThreadNThreadWait2, (void*)&sem);
373     ASSERT_EQ(reInt, 0) << "> pthread_create errno, reInt = " << reInt;
374 
375     Msleep(200);
376     EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "sem_getvalue errno = " << errno;
377     EXPECT_EQ(semValue, 0);
378     EXPECT_EQ(sem_post(&sem), 0) << "sem_post errno = " << errno;
379 
380     Msleep(20);
381     EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "sem_getvalue errno = " << errno;
382     EXPECT_EQ(semValue, 0);
383 
384     Msleep(200);
385     EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "sem_getvalue errno = " << errno;
386     EXPECT_EQ(semValue, 0);
387     EXPECT_EQ(sem_post(&sem), 0) << "sem_post errno = " << errno;
388 
389     Msleep(20);
390     EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "sem_getvalue errno = " << errno;
391     EXPECT_EQ(semValue, 1);
392 
393     reInt = pthread_join(tid1, nullptr);
394     EXPECT_EQ(reInt, 0) << "pthread_join failed, errno=" << reInt;
395     reInt = pthread_join(tid2, nullptr);
396     EXPECT_EQ(reInt, 0) << "pthread_join failed, errno=" << reInt;
397     EXPECT_EQ(sem_destroy(&sem), 0) << "> sem_destroy errno = " << errno;
398 }
399 
ThreadNThreadPost1(void *arg)400 void *ThreadNThreadPost1(void *arg)
401 {
402     sem_t *sem = (sem_t*)arg;
403     int semValue = 0;
404 
405     Msleep(200);
406     EXPECT_EQ(sem_post(sem), 0) << "sem_post errno = " << errno;
407     Msleep(20);
408     EXPECT_EQ(sem_getvalue(sem, &semValue), 0) << "sem_getvalue errno = " << errno;
409     EXPECT_EQ(semValue, 0);
410     return nullptr;
411 }
412 
ThreadNThreadPost2(void *arg)413 void *ThreadNThreadPost2(void *arg)
414 {
415     sem_t *sem = (sem_t*)arg;
416     int semValue = 0;
417 
418     Msleep(300);
419     EXPECT_EQ(sem_post(sem), 0) << "sem_post errno = " << errno;
420     Msleep(20);
421     EXPECT_EQ(sem_getvalue(sem, &semValue), 0) << "sem_getvalue errno = " << errno;
422     EXPECT_EQ(semValue, 1);
423     return nullptr;
424 }
425 
426 /**
427  * @tc.number   SUB_KERNEL_IPC_SEM_CHAT_0500
428  * @tc.name     N threads post, main thread wait
429  * @tc.desc     [C- SOFTWARE -0200]
430  */
HWTEST_F(SemTest, testNThreadPost, Function | MediumTest | Level4)431 HWTEST_F(SemTest, testNThreadPost, Function | MediumTest | Level4)
432 {
433     pthread_t tid1;
434     pthread_t tid2;
435     struct timespec ts = {0};
436     sem_t sem;
437     int reInt = 0;
438     int semValue = 0;
439 
440     ASSERT_EQ(sem_init(&sem, 0, 0), 0) << "> sem_init errno = " << errno;
441 
442     reInt = pthread_create(&tid1, nullptr, ThreadNThreadPost1, (void*)&sem);
443     ASSERT_EQ(reInt, 0) << "> pthread_create errno, reInt = " << reInt;
444 
445     reInt = pthread_create(&tid2, nullptr, ThreadNThreadPost2, (void*)&sem);
446     ASSERT_EQ(reInt, 0) << "> pthread_create errno, reInt = " << reInt;
447 
448     Msleep(100);
449     clock_gettime(CLOCK_REALTIME, &ts);
450     ts.tv_sec = ts.tv_sec + 1;
451     EXPECT_EQ(sem_timedwait(&sem, &ts), 0) << "> sem_timedwait errno = " << errno;
452 
453     Msleep(400);
454     EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "sem_getvalue errno = " << errno;
455     EXPECT_EQ(semValue, 1);
456     EXPECT_EQ(sem_trywait(&sem), 0) << "> sem_trywait errno = " << errno;
457     EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "sem_getvalue errno = " << errno;
458     EXPECT_EQ(semValue, 0);
459 
460     reInt = pthread_join(tid1, nullptr);
461     EXPECT_EQ(reInt, 0) << "pthread_join failed, errno=" << reInt;
462     reInt = pthread_join(tid2, nullptr);
463     EXPECT_EQ(reInt, 0) << "pthread_join failed, errno=" << reInt;
464     EXPECT_EQ(sem_destroy(&sem), 0) << "> sem_destroy errno = " << errno;
465 }
466