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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 EXPECT_EQ(semValue, 1);
261 EXPECT_EQ(reInt, 0) << "pthread_join failed, errno=" << reInt;
262 EXPECT_EQ(sem_destroy(&sem), 0) << "> sem_destroy errno = " << errno;
263 }
264
ThreadSemTimedWait(void * arg)265 void *ThreadSemTimedWait(void *arg)
266 {
267 struct timespec ts = {0};
268 sem_t *sem = (sem_t*)arg;
269 int semValue = 0;
270
271 EXPECT_EQ(sem_getvalue(sem, &semValue), 0) << "sem_getvalue errno = " << errno;
272 EXPECT_EQ(semValue, 0);
273
274 clock_gettime(CLOCK_REALTIME, &ts);
275 ts.tv_sec = ts.tv_sec + (ts.tv_nsec + KERNEL_100MS_BY_NS) / KERNEL_NS_PER_SECOND;
276 ts.tv_nsec = (ts.tv_nsec + KERNEL_100MS_BY_NS) % KERNEL_NS_PER_SECOND;
277 Msleep(50);
278 EXPECT_EQ(sem_timedwait(sem, &ts), 0) << "sem_timedwait errno = " << errno;
279 EXPECT_EQ(sem_getvalue(sem, &semValue), 0) << "sem_getvalue errno = " << errno;
280
281 Msleep(100);
282 EXPECT_EQ(semValue, 1);
283 return nullptr;
284 }
285
286 /**
287 * @tc.number SUB_KERNEL_IPC_SEM_CHAT_0300
288 * @tc.name Inter-thread communication, check sem_timedwait function
289 * @tc.desc [C- SOFTWARE -0200]
290 */
291 HWTEST_F(SemTest, testThreadSemTimedWait, Function | MediumTest | Level3)
292 {
293 pthread_t tid;
294 sem_t sem;
295 int reInt = 0;
296 int semValue = 0;
297
298 ASSERT_EQ(sem_init(&sem, 0, 0), 0) << "> sem_init errno = " << errno;
299
300 reInt = pthread_create(&tid, nullptr, ThreadSemTimedWait, (void*)&sem);
301 ASSERT_EQ(reInt, 0) << "> pthread_create errno, reInt = " << reInt;
302
303 Msleep(10);
304 EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno;
305 EXPECT_EQ(semValue, 0);
306 EXPECT_EQ(sem_post(&sem), 0) << "> sem_post errno = " << errno;
307 EXPECT_EQ(sem_post(&sem), 0) << "> sem_post errno = " << errno;
308
309 reInt = pthread_join(tid, nullptr);
310 EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "> sem_getvalue errno = " << errno;
311 EXPECT_EQ(semValue, 1);
312 EXPECT_EQ(reInt, 0) << "pthread_join failed, errno=" << reInt;
313 EXPECT_EQ(sem_destroy(&sem), 0) << "> sem_destroy errno = " << errno;
314 }
315
ThreadNThreadWait1(void * arg)316 void *ThreadNThreadWait1(void *arg)
317 {
318 sem_t *sem = (sem_t*)arg;
319 int semValue = 0;
320
321 Msleep(100);
322 EXPECT_EQ(sem_getvalue(sem, &semValue), 0) << "sem_getvalue errno = " << errno;
323 EXPECT_EQ(semValue, 0);
324 EXPECT_EQ(sem_wait(sem), 0) << "sem_wait errno = " << errno;
325 return nullptr;
326 }
327
ThreadNThreadWait2(void * arg)328 void *ThreadNThreadWait2(void *arg)
329 {
330 sem_t *sem = (sem_t*)arg;
331 int semValue = 0;
332 EXPECT_EQ(sem_getvalue(sem, &semValue), 0) << "sem_getvalue errno = " << errno;
333 EXPECT_EQ(semValue, 0);
334
335 Msleep(300);
336 EXPECT_EQ(sem_getvalue(sem, &semValue), 0) << "sem_getvalue errno = " << errno;
337 EXPECT_EQ(semValue, 0);
338
339 Msleep(200);
340 EXPECT_EQ(sem_getvalue(sem, &semValue), 0) << "sem_getvalue errno = " << errno;
341 EXPECT_EQ(semValue, 1);
342 EXPECT_EQ(sem_wait(sem), 0) << "sem_wait errno = " << errno;
343 return nullptr;
344 }
345
346 /**
347 * @tc.number SUB_KERNEL_IPC_SEM_CHAT_0400
348 * @tc.name N threads wait, main thread post
349 * @tc.desc [C- SOFTWARE -0200]
350 */
351 HWTEST_F(SemTest, testNThreadWait, Function | MediumTest | Level4)
352 {
353 pthread_t tid1;
354 pthread_t tid2;
355 sem_t sem;
356 int reInt = 0;
357 int semValue = 0;
358
359 ASSERT_EQ(sem_init(&sem, 0, 0), 0) << "> sem_init errno = " << errno;
360
361 reInt = pthread_create(&tid1, nullptr, ThreadNThreadWait1, (void*)&sem);
362 ASSERT_EQ(reInt, 0) << "> pthread_create errno, reInt = " << reInt;
363
364 reInt = pthread_create(&tid2, nullptr, ThreadNThreadWait2, (void*)&sem);
365 ASSERT_EQ(reInt, 0) << "> pthread_create errno, reInt = " << reInt;
366
367 Msleep(200);
368 EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "sem_getvalue errno = " << errno;
369 EXPECT_EQ(semValue, 0);
370 EXPECT_EQ(sem_post(&sem), 0) << "sem_post errno = " << errno;
371
372 Msleep(20);
373 EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "sem_getvalue errno = " << errno;
374 EXPECT_EQ(semValue, 0);
375
376 Msleep(200);
377 EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "sem_getvalue errno = " << errno;
378 EXPECT_EQ(semValue, 0);
379 EXPECT_EQ(sem_post(&sem), 0) << "sem_post errno = " << errno;
380
381 Msleep(20);
382 EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "sem_getvalue errno = " << errno;
383 EXPECT_EQ(semValue, 1);
384
385 reInt = pthread_join(tid1, nullptr);
386 EXPECT_EQ(reInt, 0) << "pthread_join failed, errno=" << reInt;
387 reInt = pthread_join(tid2, nullptr);
388 EXPECT_EQ(reInt, 0) << "pthread_join failed, errno=" << reInt;
389 EXPECT_EQ(sem_destroy(&sem), 0) << "> sem_destroy errno = " << errno;
390 }
391
ThreadNThreadPost1(void * arg)392 void *ThreadNThreadPost1(void *arg)
393 {
394 sem_t *sem = (sem_t*)arg;
395 int semValue = 0;
396
397 Msleep(200);
398 EXPECT_EQ(sem_post(sem), 0) << "sem_post errno = " << errno;
399 Msleep(20);
400 EXPECT_EQ(sem_getvalue(sem, &semValue), 0) << "sem_getvalue errno = " << errno;
401 EXPECT_EQ(semValue, 0);
402 return nullptr;
403 }
404
ThreadNThreadPost2(void * arg)405 void *ThreadNThreadPost2(void *arg)
406 {
407 sem_t *sem = (sem_t*)arg;
408 int semValue = 0;
409
410 Msleep(300);
411 EXPECT_EQ(sem_post(sem), 0) << "sem_post errno = " << errno;
412 Msleep(20);
413 EXPECT_EQ(sem_getvalue(sem, &semValue), 0) << "sem_getvalue errno = " << errno;
414 EXPECT_EQ(semValue, 1);
415 return nullptr;
416 }
417
418 /**
419 * @tc.number SUB_KERNEL_IPC_SEM_CHAT_0500
420 * @tc.name N threads post, main thread wait
421 * @tc.desc [C- SOFTWARE -0200]
422 */
423 HWTEST_F(SemTest, testNThreadPost, Function | MediumTest | Level4)
424 {
425 pthread_t tid1;
426 pthread_t tid2;
427 struct timespec ts = {0};
428 sem_t sem;
429 int reInt = 0;
430 int semValue = 0;
431
432 ASSERT_EQ(sem_init(&sem, 0, 0), 0) << "> sem_init errno = " << errno;
433
434 reInt = pthread_create(&tid1, nullptr, ThreadNThreadPost1, (void*)&sem);
435 ASSERT_EQ(reInt, 0) << "> pthread_create errno, reInt = " << reInt;
436
437 reInt = pthread_create(&tid2, nullptr, ThreadNThreadPost2, (void*)&sem);
438 ASSERT_EQ(reInt, 0) << "> pthread_create errno, reInt = " << reInt;
439
440 Msleep(100);
441 clock_gettime(CLOCK_REALTIME, &ts);
442 ts.tv_sec = ts.tv_sec + 1;
443 EXPECT_EQ(sem_timedwait(&sem, &ts), 0) << "> sem_timedwait errno = " << errno;
444
445 Msleep(400);
446 EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "sem_getvalue errno = " << errno;
447 EXPECT_EQ(semValue, 1);
448 EXPECT_EQ(sem_trywait(&sem), 0) << "> sem_trywait errno = " << errno;
449 EXPECT_EQ(sem_getvalue(&sem, &semValue), 0) << "sem_getvalue errno = " << errno;
450 EXPECT_EQ(semValue, 0);
451
452 reInt = pthread_join(tid1, nullptr);
453 EXPECT_EQ(reInt, 0) << "pthread_join failed, errno=" << reInt;
454 reInt = pthread_join(tid2, nullptr);
455 EXPECT_EQ(reInt, 0) << "pthread_join failed, errno=" << reInt;
456 EXPECT_EQ(sem_destroy(&sem), 0) << "> sem_destroy errno = " << errno;
457 }
458