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