1 /*
2  * Copyright (c) 2006-2019, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2021-08-12     luckyzjq     the first version
9  */
10 
11 #include <rtthread.h>
12 #include <stdlib.h>
13 #include "utest.h"
14 
15 static struct rt_semaphore static_semaphore;
16 #ifdef RT_USING_HEAP
17 static rt_sem_t dynamic_semaphore;
18 #endif /* RT_USING_HEAP */
19 
test_static_semaphore_init(void)20 static void test_static_semaphore_init(void)
21 {
22     rt_err_t result;
23     int rand_num = rand() % 0x10000;
24 
25     for (int i = 0; i < rand_num; i++)
26     {
27         result = rt_sem_init(&static_semaphore, "static_sem", i, RT_IPC_FLAG_PRIO);
28         if (RT_EOK != result)
29         {
30             uassert_true(RT_FALSE);
31             break;
32         }
33         rt_sem_detach(&static_semaphore);
34 
35         result = rt_sem_init(&static_semaphore, "static_sem", i, RT_IPC_FLAG_FIFO);
36         if (RT_EOK != result)
37         {
38             uassert_true(RT_FALSE);
39             break;
40         }
41         rt_sem_detach(&static_semaphore);
42     }
43 
44     uassert_true(RT_TRUE);
45 }
46 
test_static_semaphore_detach(void)47 static void test_static_semaphore_detach(void)
48 {
49     rt_err_t result;
50     int rand_num = rand() % 0x10000;
51 
52     for (int i = 0; i < rand_num; i++)
53     {
54         result = rt_sem_init(&static_semaphore, "static_sem", i, RT_IPC_FLAG_PRIO);
55         if (RT_EOK != result)
56         {
57             break;
58         }
59 
60         result = rt_sem_detach(&static_semaphore);
61         if (RT_EOK != result)
62         {
63             uassert_true(RT_FALSE);
64             break;
65         }
66 
67         result = rt_sem_init(&static_semaphore, "static_sem", i, RT_IPC_FLAG_FIFO);
68         if (RT_EOK != result)
69         {
70             break;
71         }
72         result = rt_sem_detach(&static_semaphore);
73         if (RT_EOK != result)
74         {
75             uassert_true(RT_FALSE);
76             break;
77         }
78     }
79 
80     uassert_true(RT_TRUE);
81 }
82 
test_static_semaphore_take(void)83 static void test_static_semaphore_take(void)
84 {
85     rt_err_t result;
86     result = rt_sem_init(&static_semaphore, "static_sem", 1, RT_IPC_FLAG_PRIO);
87     if (RT_EOK == result)
88     {
89         /* first take */
90         result = rt_sem_take(&static_semaphore, RT_WAITING_FOREVER);
91         if (RT_EOK != result)
92             uassert_true(RT_FALSE);
93         /* second take */
94         result = rt_sem_take(&static_semaphore, 100);
95         if (-RT_ETIMEOUT != result)
96             uassert_true(RT_FALSE);
97     }
98     else
99     {
100         return;
101     }
102 
103     rt_sem_detach(&static_semaphore);
104     uassert_true(RT_TRUE);
105 
106     return;
107 }
108 
test_static_semaphore_trytake(void)109 static void test_static_semaphore_trytake(void)
110 {
111     rt_err_t result;
112     result = rt_sem_init(&static_semaphore, "static_sem", 1, RT_IPC_FLAG_PRIO);
113     if (RT_EOK == result)
114     {
115         /* first take */
116         result = rt_sem_trytake(&static_semaphore);
117         if (RT_EOK != result)
118             uassert_true(RT_FALSE);
119         /* second take */
120         result = rt_sem_trytake(&static_semaphore);
121         if (-RT_ETIMEOUT != result)
122             uassert_true(RT_FALSE);
123     }
124     else
125     {
126         return;
127     }
128 
129     rt_sem_detach(&static_semaphore);
130     uassert_true(RT_TRUE);
131 
132     return;
133 }
134 
test_static_semaphore_release(void)135 static void test_static_semaphore_release(void)
136 {
137     rt_err_t result;
138     result = rt_sem_init(&static_semaphore, "static_sem", 0, RT_IPC_FLAG_PRIO);
139     if (RT_EOK == result)
140     {
141         /* first take */
142         result = rt_sem_take(&static_semaphore, 100);
143         if (-RT_ETIMEOUT != result)
144             uassert_true(RT_FALSE);
145 
146         /* release */
147         result = rt_sem_release(&static_semaphore);
148         if (RT_EOK != result)
149             uassert_true(RT_FALSE);
150 
151         /* second take */
152         result = rt_sem_take(&static_semaphore, RT_WAITING_FOREVER);
153         if (RT_EOK != result)
154             uassert_true(RT_FALSE);
155     }
156     else
157     {
158         return;
159     }
160 
161     rt_sem_detach(&static_semaphore);
162     uassert_true(RT_TRUE);
163 
164     return;
165 }
166 
test_static_semaphore_control(void)167 static void test_static_semaphore_control(void)
168 {
169     rt_err_t result;
170     int value = 0;
171 
172     value = rand() % 100;
173     result = rt_sem_init(&static_semaphore, "static_sem", 1, RT_IPC_FLAG_PRIO);
174     if (RT_EOK == result)
175     {
176         result = rt_sem_control(&static_semaphore, RT_IPC_CMD_RESET, &value);
177         if (RT_EOK != result)
178         {
179             uassert_true(RT_FALSE);
180         }
181     }
182     else
183     {
184         return;
185     }
186 
187     for (int i = 0; i < value; i++)
188     {
189         result = rt_sem_take(&static_semaphore, 10);
190         if (RT_EOK != result)
191         {
192             uassert_true(RT_FALSE);
193         }
194     }
195 
196     rt_sem_detach(&static_semaphore);
197     uassert_true(RT_TRUE);
198 }
199 
static_release_isr_hardware_callback(void * param)200 static void static_release_isr_hardware_callback(void *param)
201 {
202     rt_err_t result;
203 
204     result = rt_sem_release(&static_semaphore);
205     if (RT_EOK != result)
206     {
207         uassert_true(RT_FALSE);
208     }
209 }
210 
static_release_isr_software_callback(void * param)211 static void static_release_isr_software_callback(void *param)
212 {
213     rt_err_t result;
214 
215     result = rt_sem_release(&static_semaphore);
216     if (RT_EOK != result)
217     {
218         uassert_true(RT_FALSE);
219     }
220 }
221 
test_static_semaphore_release_isr(void)222 static void test_static_semaphore_release_isr(void)
223 {
224     rt_err_t result;
225     rt_timer_t hardware_timer;
226     rt_timer_t software_timer;
227 
228     /* create timer */
229     hardware_timer = rt_timer_create("release_isr",
230                                      static_release_isr_hardware_callback,
231                                      RT_NULL,
232                                      100,
233                                      RT_TIMER_FLAG_HARD_TIMER | RT_TIMER_FLAG_ONE_SHOT);
234     software_timer = rt_timer_create("release_isr",
235                                      static_release_isr_software_callback,
236                                      RT_NULL,
237                                      100,
238                                      RT_TIMER_FLAG_SOFT_TIMER | RT_TIMER_FLAG_ONE_SHOT);
239     /* start tiemr */
240     if (hardware_timer)
241         rt_timer_start(hardware_timer);
242     if (software_timer)
243         rt_timer_start(software_timer);
244 
245     result = rt_sem_init(&static_semaphore, "static_sem", 0, RT_IPC_FLAG_PRIO);
246     if (RT_EOK == result)
247     {
248         for (int i = 0; i < 2; i++)
249         {
250             result = rt_sem_take(&static_semaphore, 1000);
251             if (RT_EOK != result)
252             {
253                 uassert_true(RT_FALSE);
254             }
255         }
256     }
257     else
258     {
259         return;
260     }
261 
262     rt_sem_detach(&static_semaphore);
263     rt_timer_delete(hardware_timer);
264     rt_timer_delete(software_timer);
265 
266     uassert_true(RT_TRUE);
267 }
268 
269 #ifdef RT_USING_HEAP
test_dynamic_semaphore_create(void)270 static void test_dynamic_semaphore_create(void)
271 {
272     int rand_num = rand() % 0x10000;
273 
274     for (int i = 0; i < rand_num; i++)
275     {
276         dynamic_semaphore = rt_sem_create("static_sem", i, RT_IPC_FLAG_PRIO);
277         if (RT_NULL == dynamic_semaphore)
278         {
279             uassert_true(RT_FALSE);
280             break;
281         }
282         rt_sem_delete(dynamic_semaphore);
283 
284         dynamic_semaphore = rt_sem_create("static_sem", i, RT_IPC_FLAG_FIFO);
285         if (RT_NULL == dynamic_semaphore)
286         {
287             uassert_true(RT_FALSE);
288             break;
289         }
290         rt_sem_delete(dynamic_semaphore);
291     }
292 
293     uassert_true(RT_TRUE);
294 }
295 
test_dynamic_semaphore_delete(void)296 static void test_dynamic_semaphore_delete(void)
297 {
298     rt_err_t result;
299     int rand_num = rand() % 0x10000;
300 
301     for (int i = 0; i < rand_num; i++)
302     {
303         dynamic_semaphore = rt_sem_create("static_sem", i, RT_IPC_FLAG_PRIO);
304         if (RT_NULL == dynamic_semaphore)
305         {
306             break;
307         }
308 
309         result = rt_sem_delete(dynamic_semaphore);
310         if (RT_EOK != result)
311         {
312             uassert_true(RT_FALSE);
313             break;
314         }
315 
316         dynamic_semaphore = rt_sem_create("static_sem", i, RT_IPC_FLAG_FIFO);
317         if (RT_NULL == dynamic_semaphore)
318         {
319             break;
320         }
321         result = rt_sem_delete(dynamic_semaphore);
322         if (RT_EOK != result)
323         {
324             uassert_true(RT_FALSE);
325             break;
326         }
327     }
328 
329     uassert_true(RT_TRUE);
330 }
331 
test_dynamic_semaphore_take(void)332 static void test_dynamic_semaphore_take(void)
333 {
334     rt_err_t result;
335     dynamic_semaphore = rt_sem_create("static_sem", 1, RT_IPC_FLAG_PRIO);
336     if (RT_NULL != dynamic_semaphore)
337     {
338         /* first take */
339         result = rt_sem_take(dynamic_semaphore, RT_WAITING_FOREVER);
340         if (RT_EOK != result)
341             uassert_true(RT_FALSE);
342         /* second take */
343         result = rt_sem_take(dynamic_semaphore, 100);
344         if (-RT_ETIMEOUT != result)
345             uassert_true(RT_FALSE);
346     }
347     else
348     {
349         return;
350     }
351 
352     rt_sem_delete(dynamic_semaphore);
353     uassert_true(RT_TRUE);
354 
355     return;
356 }
357 
test_dynamic_semaphore_trytake(void)358 static void test_dynamic_semaphore_trytake(void)
359 {
360     rt_err_t result;
361     dynamic_semaphore = rt_sem_create("static_sem", 1, RT_IPC_FLAG_PRIO);
362     if (RT_NULL != dynamic_semaphore)
363     {
364         /* first take */
365         result = rt_sem_trytake(dynamic_semaphore);
366         if (RT_EOK != result)
367             uassert_true(RT_FALSE);
368         /* second take */
369         result = rt_sem_trytake(dynamic_semaphore);
370         if (-RT_ETIMEOUT != result)
371             uassert_true(RT_FALSE);
372     }
373     else
374     {
375         return;
376     }
377 
378     rt_sem_delete(dynamic_semaphore);
379     uassert_true(RT_TRUE);
380 
381     return;
382 }
383 
test_dynamic_semaphore_release(void)384 static void test_dynamic_semaphore_release(void)
385 {
386     rt_err_t result;
387     dynamic_semaphore = rt_sem_create("static_sem", 0, RT_IPC_FLAG_PRIO);
388     if (RT_NULL != dynamic_semaphore)
389     {
390         /* first take */
391         result = rt_sem_take(dynamic_semaphore, 100);
392         if (-RT_ETIMEOUT != result)
393             uassert_true(RT_FALSE);
394 
395         /* release */
396         result = rt_sem_release(dynamic_semaphore);
397         if (RT_EOK != result)
398             uassert_true(RT_FALSE);
399 
400         /* second take */
401         result = rt_sem_take(dynamic_semaphore, RT_WAITING_FOREVER);
402         if (RT_EOK != result)
403             uassert_true(RT_FALSE);
404     }
405     else
406     {
407         return;
408     }
409 
410     rt_sem_delete(dynamic_semaphore);
411     uassert_true(RT_TRUE);
412 
413     return;
414 }
415 
test_dynamic_semaphore_control(void)416 static void test_dynamic_semaphore_control(void)
417 {
418     rt_err_t result;
419     int value = 0;
420 
421     value = rand() % 100;
422     dynamic_semaphore = rt_sem_create("static_sem", 1, RT_IPC_FLAG_PRIO);
423     if (RT_NULL != dynamic_semaphore)
424     {
425         result = rt_sem_control(dynamic_semaphore, RT_IPC_CMD_RESET, &value);
426         if (RT_EOK != result)
427         {
428             uassert_true(RT_FALSE);
429         }
430     }
431     else
432     {
433         return;
434     }
435 
436     for (int i = 0; i < value; i++)
437     {
438         result = rt_sem_take(dynamic_semaphore, 10);
439         if (RT_EOK != result)
440         {
441             uassert_true(RT_FALSE);
442         }
443     }
444 
445     rt_sem_delete(dynamic_semaphore);
446     uassert_true(RT_TRUE);
447 }
448 
dynamic_release_isr_hardware_callback(void * param)449 static void dynamic_release_isr_hardware_callback(void *param)
450 {
451     rt_err_t result;
452 
453     result = rt_sem_release(dynamic_semaphore);
454     if (RT_EOK != result)
455     {
456         uassert_true(RT_FALSE);
457     }
458 }
459 
dynamic_release_isr_software_callback(void * param)460 static void dynamic_release_isr_software_callback(void *param)
461 {
462     rt_err_t result;
463 
464     result = rt_sem_release(dynamic_semaphore);
465     if (RT_EOK != result)
466     {
467         uassert_true(RT_FALSE);
468     }
469 }
470 
test_dynamic_semaphore_release_isr(void)471 static void test_dynamic_semaphore_release_isr(void)
472 {
473     rt_err_t result;
474     rt_timer_t hardware_timer;
475     rt_timer_t software_timer;
476 
477     /* create timer */
478     hardware_timer = rt_timer_create("release_isr",
479                                      dynamic_release_isr_hardware_callback,
480                                      RT_NULL,
481                                      100,
482                                      RT_TIMER_FLAG_HARD_TIMER | RT_TIMER_FLAG_ONE_SHOT);
483     software_timer = rt_timer_create("release_isr",
484                                      dynamic_release_isr_software_callback,
485                                      RT_NULL,
486                                      100,
487                                      RT_TIMER_FLAG_SOFT_TIMER | RT_TIMER_FLAG_ONE_SHOT);
488     /* start tiemr */
489     if (hardware_timer)
490         rt_timer_start(hardware_timer);
491     if (software_timer)
492         rt_timer_start(software_timer);
493 
494     dynamic_semaphore = rt_sem_create("static_sem", 0, RT_IPC_FLAG_PRIO);
495     if (RT_NULL != dynamic_semaphore)
496     {
497         for (int i = 0; i < 2; i++)
498         {
499             result = rt_sem_take(dynamic_semaphore, 1000);
500             if (RT_EOK != result)
501             {
502                 uassert_true(RT_FALSE);
503             }
504         }
505     }
506     else
507     {
508         return;
509     }
510 
511     rt_sem_delete(dynamic_semaphore);
512     rt_timer_delete(hardware_timer);
513     rt_timer_delete(software_timer);
514 
515     uassert_true(RT_TRUE);
516 }
517 
518 #endif /* RT_USING_HEAP */
519 
utest_tc_init(void)520 static rt_err_t utest_tc_init(void)
521 {
522 #ifdef RT_USING_HEAP
523     dynamic_semaphore = RT_NULL;
524 #endif /* RT_USING_HEAP */
525 
526     return RT_EOK;
527 }
528 
utest_tc_cleanup(void)529 static rt_err_t utest_tc_cleanup(void)
530 {
531 #ifdef RT_USING_HEAP
532     dynamic_semaphore = RT_NULL;
533 #endif /* RT_USING_HEAP */
534 
535     return RT_EOK;
536 }
537 
testcase(void)538 static void testcase(void)
539 {
540     UTEST_UNIT_RUN(test_static_semaphore_init);
541     UTEST_UNIT_RUN(test_static_semaphore_take);
542     UTEST_UNIT_RUN(test_static_semaphore_release);
543     UTEST_UNIT_RUN(test_static_semaphore_detach);
544     UTEST_UNIT_RUN(test_static_semaphore_trytake);
545     UTEST_UNIT_RUN(test_static_semaphore_control);
546     UTEST_UNIT_RUN(test_static_semaphore_release_isr);
547 
548 #ifdef RT_USING_HEAP
549     UTEST_UNIT_RUN(test_dynamic_semaphore_create);
550     UTEST_UNIT_RUN(test_dynamic_semaphore_take);
551     UTEST_UNIT_RUN(test_dynamic_semaphore_release);
552     UTEST_UNIT_RUN(test_dynamic_semaphore_delete);
553     UTEST_UNIT_RUN(test_dynamic_semaphore_trytake);
554     UTEST_UNIT_RUN(test_dynamic_semaphore_control);
555     UTEST_UNIT_RUN(test_dynamic_semaphore_release_isr);
556 #endif /* RT_USING_HEAP */
557 }
558 UTEST_TC_EXPORT(testcase, "testcases.kernel.semaphore_tc", utest_tc_init, utest_tc_cleanup, 1000);
559