]> begriffs open source - cmsis-freertos/blob - Test/CMock/queue/sets/binary_semaphore_utest.c
Update README.md - branch main is now the base branch
[cmsis-freertos] / Test / CMock / queue / sets / binary_semaphore_utest.c
1 /*
2  * FreeRTOS V202111.00
3  * Copyright (C) 2020 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of
6  * this software and associated documentation files (the "Software"), to deal in
7  * the Software without restriction, including without limitation the rights to
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9  * the Software, and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in all
13  * copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * https://www.FreeRTOS.org
23  * https://github.com/FreeRTOS
24  *
25  */
26 /*! @file binary_semaphore_utest.c */
27
28 #include "../queue_utest_common.h"
29 #include "mock_fake_port.h"
30
31 /* Queue includes */
32 #include "FreeRTOS.h"
33 #include "FreeRTOSConfig.h"
34 #include "semphr.h"
35
36 /* ===============================  CONSTANTS =============================== */
37
38 /* ============================  GLOBAL VARIABLES =========================== */
39
40 /* Used to share a semaphore handle between a test case and callback */
41 static SemaphoreHandle_t xSemaphoreHandleStatic;
42
43 /* ==========================  CALLBACK FUNCTIONS =========================== */
44
45 /* ============================= Unity Fixtures ============================= */
46
47 void setUp( void )
48 {
49     commonSetUp();
50 }
51
52 void tearDown( void )
53 {
54     commonTearDown();
55 }
56
57 void suiteSetUp()
58 {
59     commonSuiteSetUp();
60 }
61
62 int suiteTearDown( int numFailures )
63 {
64     return commonSuiteTearDown( numFailures );
65 }
66
67 /* ==========================  Helper functions =========================== */
68
69 /* =============================  Test Cases ============================== */
70
71 /**
72  * @brief Test xSemaphoreTake with a Binary Semaphore
73  * @details Create a binary semaphore using xSemaphoreCreateBinary
74  * and verify that an immediate call to xSemaphoreTake fails.
75  * @coverage xQueueSemaphoreTake
76  */
77 void test_macro_xSemaphoreTake_xSemaphoreCreateBinary_fail( void )
78 {
79     SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
80
81     /* validate returned semaphore handle */
82     TEST_ASSERT_NOT_EQUAL( NULL, xSemaphore );
83
84     TEST_ASSERT_EQUAL( QUEUE_T_SIZE, getLastMallocSize() );
85
86     /* Verify that an immediate xSemaphoreTake operation fails */
87     TEST_ASSERT_EQUAL( pdFALSE, xSemaphoreTake( xSemaphore, 0 ) );
88
89     vSemaphoreDelete( xSemaphore );
90 }
91
92 /**
93  * @brief Test xSemaphoreGive with xSemaphoreCreateBinary
94  * @details Create a binary semaphore using xSemaphoreCreateBinary
95  * and verify that an immediate call to xSemaphoreGive succeeds.
96  * @coverage xQueueGenericSend
97  */
98 void test_macro_xSemaphoreGive_xSemaphoreCreateBinary_success( void )
99 {
100     SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
101
102     /* validate returned semaphore handle */
103     TEST_ASSERT_NOT_EQUAL( NULL, xSemaphore );
104
105     TEST_ASSERT_EQUAL( QUEUE_T_SIZE, getLastMallocSize() );
106
107     /* Verify that an immediate xSemaphoreGive operation succeeds */
108     TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreGive( xSemaphore ) );
109
110     vSemaphoreDelete( xSemaphore );
111 }
112
113 /**
114  * @deprecated
115  * @brief Test xSemaphoreTake with vSemaphoreCreateBinary
116  * @details Create a semaphore using vSemaphoreCreateBinary and verify that a
117  *          subsequent call to xSemaphoreTake succeeds.
118  * @coverage xQueueSemaphoreTake
119  */
120 void test_macro_xSemaphoreTake_vSemaphoreCreateBinary_success( void )
121 {
122     SemaphoreHandle_t xSemaphore = NULL;
123
124     vSemaphoreCreateBinary( xSemaphore );
125
126     /* validate returned semaphore handle */
127     TEST_ASSERT_NOT_EQUAL( NULL, xSemaphore );
128     TEST_ASSERT_EQUAL( QUEUE_T_SIZE, getLastMallocSize() );
129
130     /* Verify that an immediate xSemaphoreTake operation succeeds */
131     TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreTake( xSemaphore, 0 ) );
132
133     vSemaphoreDelete( xSemaphore );
134 }
135
136 /**
137  * @deprecated
138  * @brief Test xSemaphoreGive with vSemaphoreCreateBinary
139  * @details Create a semaphore using vSemaphoreCreateBinary and verify that a
140  *          subsequent call to xSemaphoreGive fails.
141  * @coverage xQueueGenericSend
142  */
143 void test_macro_xSemaphoreGive_vSemaphoreCreateBinary_fail( void )
144 {
145     SemaphoreHandle_t xSemaphore = NULL;
146
147     vSemaphoreCreateBinary( xSemaphore );
148
149     /* validate returned semaphore handle */
150     TEST_ASSERT_NOT_EQUAL( NULL, xSemaphore );
151     TEST_ASSERT_EQUAL( QUEUE_T_SIZE, getLastMallocSize() );
152
153     /* Verify that an immediate xSemaphoreGive operation fails */
154     TEST_ASSERT_EQUAL( pdFALSE, xSemaphoreGive( xSemaphore ) );
155
156     vSemaphoreDelete( xSemaphore );
157 }
158
159 /**
160  * @brief Test xSemaphoreGive and xSemaphoreTake with xSemaphoreCreateBinary
161  * @details Create a binary semaphore using xSemaphoreCreateBinary
162  * and verify that an immediate call to xSemaphoreGive succeeds and a subsequent
163  * call to xSemaphoreTake succeeds.
164  * @coverage xQueueGenericSend xQueueSemaphoreTake
165  */
166 void test_macro_xSemaphoreGive_xSemaphoreTake_success( void )
167 {
168     SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
169
170     /* validate returned semaphore handle */
171     TEST_ASSERT_NOT_EQUAL( NULL, xSemaphore );
172
173     TEST_ASSERT_EQUAL( QUEUE_T_SIZE, getLastMallocSize() );
174
175     /* Verify that an immediate xSemaphoreGive operation succeeds */
176     TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreGive( xSemaphore ) );
177
178     /* Verify that a subsequent xSemaphoreTake operation succeeds */
179     TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreTake( xSemaphore, 0 ) );
180
181     vSemaphoreDelete( xSemaphore );
182 }
183
184 /**
185  * @brief Test xSemaphoreGive multiple times on a Binary Semaphore
186  * @details Create a binary semaphore using xSemaphoreCreateBinary
187  * and verify that an immediate call to xSemaphoreGive succeeds and a subsequent
188  * call to xSemaphoreGive fails.
189  * @coverage xQueueGenericSend
190  */
191 void test_macro_xSemaphoreGive_multiple_fail( void )
192 {
193     SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
194
195     /* validate returned semaphore handle */
196     TEST_ASSERT_NOT_EQUAL( NULL, xSemaphore );
197
198     TEST_ASSERT_EQUAL( QUEUE_T_SIZE, getLastMallocSize() );
199
200     /* Verify that an immediate xSemaphoreGive operation succeeds */
201     TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreGive( xSemaphore ) );
202
203     /* Verify that the second xSemaphoreGive operation fails */
204     TEST_ASSERT_EQUAL( pdFALSE, xSemaphoreGive( xSemaphore ) );
205
206     vSemaphoreDelete( xSemaphore );
207 }
208
209 /**
210  * @brief Test xSemaphoreTake multiple times on a Binary Semaphore
211  * @details Create a binary semaphore using xSemaphoreCreateBinary,
212  * verify that an immediate call to xSemaphoreGive succeeds, a subsequent
213  * call to xSemaphoreTake succeds, but a second call to xSemaphoreTake fails.
214  * @coverage xQueueSemaphoreTake
215  */
216 void test_macro_xSemaphoreTake_multiple_fail( void )
217 {
218     SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
219
220     /* validate returned semaphore handle */
221     TEST_ASSERT_NOT_EQUAL( NULL, xSemaphore );
222
223     TEST_ASSERT_EQUAL( QUEUE_T_SIZE, getLastMallocSize() );
224
225     /* Verify that an immediate xSemaphoreGive operation succeeds */
226     TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreGive( xSemaphore ) );
227
228     /* Verify that a subsequent xSemaphoreTake operation succeeds */
229     TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreTake( xSemaphore, 0 ) );
230
231     /* Verify that a second xSemaphoreTake operation fails */
232     TEST_ASSERT_EQUAL( pdFALSE, xSemaphoreTake( xSemaphore, 0 ) );
233
234     vSemaphoreDelete( xSemaphore );
235 }
236
237 /**
238  * @brief Test uxSemaphoreGetCount with a Binary Semaphore
239  * @details Create a binary semaphore using vSemaphoreCreateBinary.
240  *  validate the return value of uxSemaphoreGetCount(),
241  *  call xSemaphoreTake() and validate the return value of uxSemaphoreGetCount()
242  * @coverage uxQueueMessagesWaiting
243  */
244 void test_macro_uxSemaphoreGetCount( void )
245 {
246     SemaphoreHandle_t xSemaphore = NULL;
247
248     vSemaphoreCreateBinary( xSemaphore );
249
250     TEST_ASSERT_EQUAL( B_SEMPHR_AVAILABLE, uxSemaphoreGetCount( xSemaphore ) );
251
252     ( void ) xSemaphoreTake( xSemaphore, 0 );
253
254     TEST_ASSERT_EQUAL( B_SEMPHR_TAKEN, uxSemaphoreGetCount( xSemaphore ) );
255
256     vSemaphoreDelete( xSemaphore );
257 }
258
259 /**
260  * @brief Test xSemaphoreTakeFromISR with a Binary Semaphore
261  * @coverage xQueueReceiveFromISR
262  **/
263 void test_macro_xSemaphoreTakeFromISR_success( void )
264 {
265     SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
266
267     vFakePortAssertIfInterruptPriorityInvalid_Expect();
268
269     /* Give the Binary Semaphore */
270     ( void ) xSemaphoreGive( xSemaphore );
271
272     TEST_ASSERT_EQUAL( B_SEMPHR_AVAILABLE, uxSemaphoreGetCount( xSemaphore ) );
273
274     TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreTakeFromISR( xSemaphore, NULL ) );
275
276     TEST_ASSERT_EQUAL( B_SEMPHR_TAKEN, uxSemaphoreGetCount( xSemaphore ) );
277
278     vSemaphoreDelete( xSemaphore );
279 }
280
281 /**
282  * @brief xSemaphoreGiveFromISR with an empty queue
283  * @coverage xQueueGiveFromISR
284  */
285 void test_macro_xSemaphoreGiveFromISR_success( void )
286 {
287     SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
288
289     vFakePortAssertIfInterruptPriorityInvalid_Expect();
290
291     TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreGiveFromISR( xSemaphore, NULL ) );
292
293     TEST_ASSERT_EQUAL( B_SEMPHR_AVAILABLE, uxSemaphoreGetCount( xSemaphore ) );
294
295     vSemaphoreDelete( xSemaphore );
296 }
297
298 /*!
299  * @brief xSemaphoreGiveFromISR with a full queue
300  * @coverage xQueueGiveFromISR
301  */
302 void test_macro_xSemaphoreGiveFromISR_fail( void )
303 {
304     SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
305
306     vFakePortAssertIfInterruptPriorityInvalid_Expect();
307     TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreGiveFromISR( xSemaphore, NULL ) );
308
309     vFakePortAssertIfInterruptPriorityInvalid_Expect();
310     TEST_ASSERT_EQUAL( errQUEUE_FULL, xSemaphoreGiveFromISR( xSemaphore, NULL ) );
311
312     TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreTake( xSemaphore, 0 ) );
313
314     vSemaphoreDelete( xSemaphore );
315 }
316
317 /**
318  * @brief Test xSemaphoreGiveFromISR with a higher priority task waiting and a null pointer for pxHigherPriorityTaskWoken
319  * @details Test xSemaphoreGiveFromISR with a higher priority task waiting and
320  *  verifies that a null pxHigherPriorityTaskWoken is handled correctly.
321  * @coverage xQueueGiveFromISR
322  */
323 void test_macro_xSemaphoreGiveFromISR_high_priority_pending_null_ptr( void )
324 {
325     SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
326
327     vFakePortAssertIfInterruptPriorityInvalid_Expect();
328
329     /* Insert an item into the event list */
330     td_task_setFakeTaskPriority( DEFAULT_PRIORITY + 1 );
331     td_task_addFakeTaskWaitingToReceiveFromQueue( xSemaphore );
332
333     /* Give the Binary Semaphore */
334     TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreGiveFromISR( xSemaphore, NULL ) );
335
336     TEST_ASSERT_EQUAL( pdTRUE, td_task_getYieldPending() );
337
338     TEST_ASSERT_EQUAL( B_SEMPHR_AVAILABLE, uxSemaphoreGetCount( xSemaphore ) );
339
340     vSemaphoreDelete( xSemaphore );
341 }
342
343 /**
344  * @brief Test xSemaphoreGiveFromISR with a higher priority task waiting
345  * @details Test xSemaphoreGiveFromISR with a higher priority task waiting and
346  *  verify that xHigherPriorityTaskWoken is set accordingly.
347  * @coverage xQueueGiveFromISR
348  */
349 void test_macro_xSemaphoreGiveFromISR_high_priority_pending( void )
350 {
351     SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
352
353     vFakePortAssertIfInterruptPriorityInvalid_Expect();
354
355     /* Insert an item into the event list */
356     td_task_setFakeTaskPriority( DEFAULT_PRIORITY + 1 );
357     td_task_addFakeTaskWaitingToReceiveFromQueue( xSemaphore );
358
359     BaseType_t xHigherPriorityTaskWoken = pdFALSE;
360
361     /* Give the semaphore */
362     TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken ) );
363
364     TEST_ASSERT_EQUAL( pdTRUE, xHigherPriorityTaskWoken );
365
366     TEST_ASSERT_EQUAL( pdTRUE, td_task_getYieldPending() );
367
368     TEST_ASSERT_EQUAL( B_SEMPHR_AVAILABLE, uxSemaphoreGetCount( xSemaphore ) );
369
370     vSemaphoreDelete( xSemaphore );
371 }
372
373 /**
374  * @brief Test xSemaphoreGiveFromISR with a lower priority task waiting
375  * @details Test xSemaphoreGiveFromISR with a lower priority task waiting and
376  *  verify that xHigherPriorityTaskWoken is not modified.
377  * @coverage xQueueGiveFromISR
378  */
379 void test_macro_xSemaphoreGiveFromISR_low_priority_pending( void )
380 {
381     SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
382
383     vFakePortAssertIfInterruptPriorityInvalid_Expect();
384
385     /* Insert an item into the event list */
386     td_task_setFakeTaskPriority( DEFAULT_PRIORITY - 1 );
387     td_task_addFakeTaskWaitingToReceiveFromQueue( xSemaphore );
388
389     BaseType_t xHigherPriorityTaskWoken = pdFALSE;
390
391     /* Give the semaphore */
392     TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken ) );
393
394     TEST_ASSERT_EQUAL( pdFALSE, xHigherPriorityTaskWoken );
395
396     TEST_ASSERT_EQUAL( pdFALSE, td_task_getYieldPending() );
397
398     TEST_ASSERT_EQUAL( B_SEMPHR_AVAILABLE, uxSemaphoreGetCount( xSemaphore ) );
399
400     vSemaphoreDelete( xSemaphore );
401 }
402
403 /**
404  * @brief Test xSemaphoreGiveFromISR with no tasks waiting
405  * @details Test xSemaphoreGiveFromISR with no tasks waiting and verify that xHigherPriorityTaskWoken is not modified.
406  * @coverage xQueueGiveFromISR
407  */
408 void test_macro_xSemaphoreGiveFromISR_no_pending( void )
409 {
410     SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
411
412     vFakePortAssertIfInterruptPriorityInvalid_Expect();
413
414     BaseType_t xHigherPriorityTaskWoken = pdFALSE;
415
416     /* Give the semaphore */
417     TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken ) );
418
419     TEST_ASSERT_EQUAL( pdFALSE, xHigherPriorityTaskWoken );
420
421     TEST_ASSERT_EQUAL( pdFALSE, td_task_getYieldPending() );
422
423     TEST_ASSERT_EQUAL( B_SEMPHR_AVAILABLE, uxSemaphoreGetCount( xSemaphore ) );
424
425     vSemaphoreDelete( xSemaphore );
426 }
427
428 /**
429  * @brief Test xSemaphoreGiveFromISR on a semaphore that is locked
430  * @coverage xQueueGiveFromISR
431  */
432 void test_xSemaphoreGiveFromISR_locked( void )
433 {
434     SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
435
436     /* Set private lock counters */
437     vSetQueueRxLock( xSemaphore, queueLOCKED_UNMODIFIED );
438     vSetQueueTxLock( xSemaphore, queueLOCKED_UNMODIFIED );
439
440     vFakePortAssertIfInterruptPriorityInvalid_Expect();
441
442     TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreGiveFromISR( xSemaphore, NULL ) );
443
444     /* Verify that the cRxLock counter has not changed */
445     TEST_ASSERT_EQUAL( queueLOCKED_UNMODIFIED, cGetQueueRxLock( xSemaphore ) );
446
447     /* Verify that the cTxLock counter has been incremented */
448     TEST_ASSERT_EQUAL( queueLOCKED_UNMODIFIED + 1, cGetQueueTxLock( xSemaphore ) );
449
450     TEST_ASSERT_EQUAL( B_SEMPHR_AVAILABLE, uxSemaphoreGetCount( xSemaphore ) );
451
452     vSemaphoreDelete( xSemaphore );
453 }
454
455 /**
456  * @brief Test xSemaphoreGiveFromISR on a semaphore that is locked and cRxLock overflows.
457  * @coverage xQueueGiveFromISR
458  */
459 void test_xSemaphoreGiveFromISR_locked_overflow( void )
460 {
461     SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
462
463     /* Set private lock counters */
464     vSetQueueRxLock( xSemaphore, INT8_MAX );
465     vSetQueueTxLock( xSemaphore, INT8_MAX );
466
467     vFakePortAssertIfInterruptPriorityInvalid_Expect();
468
469     /* Expect an assertion since the cTxLock value has overflowed */
470     fakeAssertExpectFail();
471
472     TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreGiveFromISR( xSemaphore, NULL ) );
473
474     /* Verify that the cRxLock counter has not changed */
475     TEST_ASSERT_EQUAL( INT8_MAX, cGetQueueRxLock( xSemaphore ) );
476
477     /* Verify that the cTxLock counter has been incremented */
478     TEST_ASSERT_EQUAL( INT8_MIN, cGetQueueTxLock( xSemaphore ) );
479
480     TEST_ASSERT_EQUAL( true, fakeAssertGetFlagAndClear() );
481
482     TEST_ASSERT_EQUAL( B_SEMPHR_AVAILABLE, uxSemaphoreGetCount( xSemaphore ) );
483
484     vSemaphoreDelete( xSemaphore );
485 }
486
487 /**
488  * @brief Test xSemaphoreTake with an occupied semaphore with higher priority tasks waiting
489  * @coverage xQueueSemaphoreTake
490  */
491 void test_xSemaphoreTake_tasks_waiting_higher_priority( void )
492 {
493     /* Create a new binary semaphore */
494     SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
495
496     ( void ) xSemaphoreGive( xSemaphore );
497
498     /* Insert an item into the event list */
499     td_task_setFakeTaskPriority( DEFAULT_PRIORITY + 1 );
500     td_task_addFakeTaskWaitingToSendToQueue( xSemaphore );
501
502     /* take the semaphore */
503     TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreTake( xSemaphore, 0 ) );
504
505     TEST_ASSERT_EQUAL( 1, td_task_getYieldCount() );
506
507     TEST_ASSERT_EQUAL( 1, td_task_getCount_vPortYieldWithinAPI() );
508
509     TEST_ASSERT_EQUAL( B_SEMPHR_TAKEN, uxSemaphoreGetCount( xSemaphore ) );
510
511     vSemaphoreDelete( xSemaphore );
512 }
513
514 /**
515  * @brief Test xSemaphoreTake with an occupied semaphore with an equal priority task waiting
516  * @coverage xQueueSemaphoreTake
517  */
518 void test_xSemaphoreTake_tasks_waiting_equal_priority( void )
519 {
520     /* Create a new binary semaphore */
521     SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
522
523     ( void ) xSemaphoreGive( xSemaphore );
524
525     /* Insert an item into the event list */
526     td_task_setFakeTaskPriority( DEFAULT_PRIORITY );
527     td_task_addFakeTaskWaitingToSendToQueue( xSemaphore );
528
529     /* take the semaphore */
530     TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreTake( xSemaphore, 0 ) );
531
532     TEST_ASSERT_EQUAL( 0, td_task_getYieldCount() );
533
534     TEST_ASSERT_EQUAL( 0, td_task_getCount_vPortYieldWithinAPI() );
535
536     TEST_ASSERT_EQUAL( B_SEMPHR_TAKEN, uxSemaphoreGetCount( xSemaphore ) );
537
538     vSemaphoreDelete( xSemaphore );
539 }
540
541 /**
542  * @brief Test xSemaphoreTake with an occupied semaphore with lower priority tasks waiting.
543  * @coverage xQueueSemaphoreTake
544  */
545 void test_xSemaphoreTake_tasks_waiting_lower_priority( void )
546 {
547     /* Create a new binary semaphore */
548     SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
549
550     ( void ) xSemaphoreGive( xSemaphore );
551
552     /* Insert an item into the event list */
553     td_task_setFakeTaskPriority( DEFAULT_PRIORITY - 1 );
554     td_task_addFakeTaskWaitingToSendToQueue( xSemaphore );
555
556     /* take the semaphore */
557     TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreTake( xSemaphore, 0 ) );
558
559     TEST_ASSERT_EQUAL( 0, td_task_getYieldCount() );
560
561     TEST_ASSERT_EQUAL( 0, td_task_getCount_vPortYieldWithinAPI() );
562
563     TEST_ASSERT_EQUAL( B_SEMPHR_TAKEN, uxSemaphoreGetCount( xSemaphore ) );
564
565     vSemaphoreDelete( xSemaphore );
566 }
567
568 /**
569  *  @brief Test xSemaphoreTake with taskSCHEDULER_SUSPENDED and timeout=10
570  *  @details This should cause xSemaphoreTake to configASSERT because it would
571  *  block forever when the semaphore is empty.
572  *  @coverage xQueueSemaphoreTake
573  */
574 void test_xSemaphoreTake_blocking_suspended_assert( void )
575 {
576     SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
577
578     fakeAssertExpectFail();
579
580     vTaskSuspendAll_Stub( td_task_vTaskSuspendAllStubNoCheck );
581
582     td_task_setSchedulerState( taskSCHEDULER_SUSPENDED );
583
584     TEST_ASSERT_EQUAL( pdFALSE, xSemaphoreTake( xSemaphore, TICKS_TO_WAIT ) );
585
586     TEST_ASSERT_EQUAL( TICKS_TO_WAIT, td_task_getYieldCount() );
587
588     TEST_ASSERT_EQUAL( TICKS_TO_WAIT, td_task_getCount_vPortYieldWithinAPI() );
589
590     TEST_ASSERT_EQUAL( pdTRUE, fakeAssertGetFlagAndClear() );
591
592     td_task_setSchedulerState( taskSCHEDULER_RUNNING );
593
594     vSemaphoreDelete( xSemaphore );
595 }
596
597 /**
598  *  @brief Test xSemaphoreTake with taskSCHEDULER_SUSPENDED and timeout=0
599  *  @details This should not cause xSemaphoreTake to configASSERT because
600  *  xSemaphoreTake is non-blocking when timeout=0.
601  *  @coverage xQueueSemaphoreTake
602  */
603 void test_xSemaphoreTake_nonblocking_suspended_noassert( void )
604 {
605     SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
606
607     td_task_setSchedulerState( taskSCHEDULER_SUSPENDED );
608
609     TEST_ASSERT_EQUAL( pdFALSE, xSemaphoreTake( xSemaphore, 0 ) );
610
611     td_task_setSchedulerState( taskSCHEDULER_RUNNING );
612
613     vSemaphoreDelete( xSemaphore );
614 }
615
616 /**
617  *  @brief Callback which calls xSemaphoreGive on xSemaphoreHandleStatic
618  */
619 static BaseType_t blocking_success_xTaskCheckForTimeOut_cb( TimeOut_t * const pxTimeOut,
620                                                             TickType_t * const pxTicksToWait,
621                                                             int cmock_num_calls )
622 {
623     BaseType_t xReturnValue = td_task_xTaskCheckForTimeOutStub( pxTimeOut, pxTicksToWait, cmock_num_calls );
624
625     if( cmock_num_calls == NUM_CALLS_TO_INTERCEPT )
626     {
627         ( void ) xSemaphoreGiveFromISR( xSemaphoreHandleStatic, NULL );
628     }
629
630     return xReturnValue;
631 }
632
633 /**
634  * @brief Test xSemaphoreTake in blocking mode with a taken Binary Semaphore
635  * which becomes available while a call to xSemaphoreTake is blocking.
636  * @coverage xQueueSemaphoreTake
637  */
638 void test_xSemaphoreTake_blocking_success( void )
639 {
640     SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
641
642     /* Export for blocking_success_xTaskCheckForTimeOut_cb callback */
643     xSemaphoreHandleStatic = xSemaphore;
644
645     vFakePortAssertIfInterruptPriorityInvalid_Ignore();
646
647     xTaskCheckForTimeOut_Stub( &blocking_success_xTaskCheckForTimeOut_cb );
648
649     TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreTake( xSemaphore, TICKS_TO_WAIT ) );
650
651     TEST_ASSERT_EQUAL( NUM_CALLS_TO_INTERCEPT, td_task_getYieldCount() );
652
653     TEST_ASSERT_EQUAL( NUM_CALLS_TO_INTERCEPT, td_task_getCount_vPortYieldWithinAPI() );
654
655     TEST_ASSERT_EQUAL( B_SEMPHR_TAKEN, uxSemaphoreGetCount( xSemaphore ) );
656     vSemaphoreDelete( xSemaphore );
657 }
658
659 /**
660  *  @brief Callback which calls xSemaphoreGive on xSemaphoreHandleStatic when
661  *  cmock_num_calls == TICKS_TO_WAIT
662  */
663 static BaseType_t blocking_last_chance_xTaskCheckForTimeOut_cb( TimeOut_t * const pxTimeOut,
664                                                                 TickType_t * const pxTicksToWait,
665                                                                 int cmock_num_calls )
666 {
667     BaseType_t xReturnValue = td_task_xTaskCheckForTimeOutStub( pxTimeOut, pxTicksToWait, cmock_num_calls );
668
669     if( cmock_num_calls == TICKS_TO_WAIT )
670     {
671         ( void ) xSemaphoreGiveFromISR( xSemaphoreHandleStatic, NULL );
672         return pdTRUE;
673     }
674
675     return xReturnValue;
676 }
677
678 /**
679  * @brief Test xSemaphoreTake in blocking mode with a Binary Semaphore that is initially taken,
680  * but becomes available at the end of the blocking time period.
681  * @coverage xQueueSemaphoreTake
682  */
683 void test_xSemaphoreTake_blocking_success_last_chance( void )
684 {
685     SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
686
687     /* Export for blocking_success_xTaskCheckForTimeOut_cb callback */
688     xSemaphoreHandleStatic = xSemaphore;
689
690     vFakePortAssertIfInterruptPriorityInvalid_Expect();
691
692     xTaskCheckForTimeOut_Stub( &blocking_last_chance_xTaskCheckForTimeOut_cb );
693
694     TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreTake( xSemaphore, TICKS_TO_WAIT ) );
695
696     TEST_ASSERT_EQUAL( TICKS_TO_WAIT, td_task_getYieldCount() );
697
698     TEST_ASSERT_EQUAL( TICKS_TO_WAIT, td_task_getCount_vPortYieldWithinAPI() );
699
700     TEST_ASSERT_EQUAL( B_SEMPHR_TAKEN, uxSemaphoreGetCount( xSemaphore ) );
701     vSemaphoreDelete( xSemaphore );
702 }
703
704 /**
705  * @brief Test xSemaphoreTake in blocking mode with a taken binary semaphore
706  * @coverage xQueueSemaphoreTake
707  */
708 void test_xSemaphoreTake_blocking_timeout( void )
709 {
710     SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
711
712     TEST_ASSERT_EQUAL( pdFALSE, xSemaphoreTake( xSemaphore, TICKS_TO_WAIT ) );
713
714     TEST_ASSERT_EQUAL( TICKS_TO_WAIT, td_task_getYieldCount() );
715
716     TEST_ASSERT_EQUAL( TICKS_TO_WAIT, td_task_getCount_vPortYieldWithinAPI() );
717
718     vSemaphoreDelete( xSemaphore );
719 }
720
721 /**
722  * @brief Test xSemaphoreTake in blocking mode with a taken locked semaphore
723  * @details This test case verifies a situation that should never occur
724  * ( xSemaphoreTake called on a locked semaphore ).
725  * @coverage xQueueSemaphoreTake
726  */
727 void test_xSemaphoreTake_blocking_locked( void )
728 {
729     /* Create a new binary semaphore */
730     SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
731
732     /* Set private lock counters */
733     vSetQueueRxLock( xSemaphore, queueLOCKED_UNMODIFIED );
734     vSetQueueTxLock( xSemaphore, queueLOCKED_UNMODIFIED );
735
736     /* Run xSemaphoreTake in blocking mode with the semaphore locked */
737     TEST_ASSERT_EQUAL( pdFALSE, xSemaphoreTake( xSemaphore, TICKS_TO_WAIT ) );
738
739     TEST_ASSERT_EQUAL( TICKS_TO_WAIT, td_task_getYieldCount() );
740
741     TEST_ASSERT_EQUAL( TICKS_TO_WAIT, td_task_getCount_vPortYieldWithinAPI() );
742
743     /* Verify that the semaphore is now unlocked */
744     TEST_ASSERT_EQUAL( queueUNLOCKED, cGetQueueRxLock( xSemaphore ) );
745     TEST_ASSERT_EQUAL( queueUNLOCKED, cGetQueueTxLock( xSemaphore ) );
746
747     vSemaphoreDelete( xSemaphore );
748 }
749
750 /**
751  *  @brief Callback for test_xSemaphoreTake_blocking_success_locked_no_pending
752  *  which adds an item to it's test queue.
753  */
754 static BaseType_t xSemaphoreTake_xTaskCheckForTimeOutCB( TimeOut_t * const pxTimeOut,
755                                                          TickType_t * const pxTicksToWait,
756                                                          int cmock_num_calls )
757 {
758     BaseType_t xReturnValue = td_task_xTaskCheckForTimeOutStub( pxTimeOut, pxTicksToWait, cmock_num_calls );
759
760     if( cmock_num_calls == NUM_CALLS_TO_INTERCEPT )
761     {
762         TEST_ASSERT_TRUE( xSemaphoreGiveFromISR( xSemaphoreHandleStatic, NULL ) );
763         TEST_ASSERT_EQUAL( 1, uxQueueMessagesWaiting( xSemaphoreHandleStatic ) );
764     }
765
766     return xReturnValue;
767 }
768
769 /**
770  *  @brief Test a blocking call to xSemaphoreTake with a locked binary semaphore.
771  *  @details Test a blocking call to xSemaphoreTake with a locked binary semaphore with no
772  *  tasks in the binary semaphore WaitingToReceiveFrom event list.
773  *  @coverage xQueueSemaphoreTake prvUnlockQueue
774  */
775 void test_xSemaphoreTake_blocking_success_locked_no_pending( void )
776 {
777     SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
778
779     vFakePortAssertIfInterruptPriorityInvalid_Ignore();
780
781     /* Export for callbacks */
782     xSemaphoreHandleStatic = xSemaphore;
783
784     xTaskCheckForTimeOut_Stub( &xSemaphoreTake_xTaskCheckForTimeOutCB );
785     xTaskResumeAll_Stub( &td_task_xTaskResumeAllStub );
786
787     TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreTake( xSemaphore, TICKS_TO_WAIT ) );
788
789     TEST_ASSERT_EQUAL( 0, uxSemaphoreGetCount( xSemaphore ) );
790
791     TEST_ASSERT_EQUAL( NUM_CALLS_TO_INTERCEPT, td_task_getYieldCount() );
792
793     TEST_ASSERT_EQUAL( NUM_CALLS_TO_INTERCEPT, td_task_getCount_vPortYieldWithinAPI() );
794
795     vQueueDelete( xSemaphore );
796 }
797
798
799 /**
800  * @brief Callback for xTaskResumeAll used by tests for blocking calls to
801  * xSemaphoreTake
802  */
803 static BaseType_t xSemaphoreTake_xTaskResumeAllCallback( int cmock_num_calls )
804 {
805     BaseType_t xReturnValue = td_task_xTaskResumeAllStub( cmock_num_calls );
806
807     /* If td_task_xTaskResumeAllStub returns pdTRUE, a higher priority task is pending
808      * Receive from an ISR to block */
809     if( pdTRUE == xReturnValue )
810     {
811         if( cmock_num_calls == NUM_CALLS_TO_INTERCEPT )
812         {
813             TEST_ASSERT_EQUAL( 1, uxSemaphoreGetCount( xSemaphoreHandleStatic ) );
814             TEST_ASSERT_TRUE( xSemaphoreTakeFromISR( xSemaphoreHandleStatic, NULL ) );
815         }
816     }
817
818     return xReturnValue;
819 }
820
821 /**
822  *  @brief Test a blocking call to xSemaphoreTake with a locked binary semaphore.
823  *  @details Test a blocking call to xSemaphoreTake with a locked binary semaphore with a
824  *  higher priority task in the binary semaphore WaitingToReceiveFrom event list.
825  *  @coverage xQueueSemaphoreTake prvUnlockQueue
826  */
827 void test_xSemaphoreTake_blocking_timeout_locked_high_prio_pending( void )
828 {
829     SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
830
831     vFakePortAssertIfInterruptPriorityInvalid_Ignore();
832
833     /* Export for callbacks */
834     xSemaphoreHandleStatic = xSemaphore;
835
836     xTaskCheckForTimeOut_Stub( &xSemaphoreTake_xTaskCheckForTimeOutCB );
837     xTaskResumeAll_Stub( &xSemaphoreTake_xTaskResumeAllCallback );
838
839     td_task_setFakeTaskPriority( DEFAULT_PRIORITY + 1 );
840
841     td_task_addFakeTaskWaitingToReceiveFromQueue( xSemaphore );
842
843     TEST_ASSERT_EQUAL( pdFALSE, xSemaphoreTake( xSemaphore, TICKS_TO_WAIT ) );
844
845     TEST_ASSERT_EQUAL( 0, uxSemaphoreGetCount( xSemaphore ) );
846
847     TEST_ASSERT_EQUAL( TICKS_TO_WAIT, td_task_getYieldCount() );
848
849     TEST_ASSERT_EQUAL( NUM_CALLS_TO_INTERCEPT + 1, td_task_getCount_YieldFromTaskResumeAll() );
850
851     TEST_ASSERT_EQUAL( NUM_CALLS_TO_INTERCEPT - 1, td_task_getCount_vPortYieldWithinAPI() );
852
853     TEST_ASSERT_EQUAL( 1, td_task_getCount_vTaskMissedYield() );
854
855     vQueueDelete( xSemaphore );
856 }
857
858 /**
859  *  @brief Test a blocking call to xSemaphoreTake with a locked binary semaphore.
860  *  @details Test a blocking call to xSemaphoreTake with a locked binary semaphore with a
861  *  lower priority task in the semaphore WaitingToReceiveFrom event list.
862  *  @coverage xQueueSemaphoreTake prvUnlockQueue
863  */
864 void test_xSemaphoreTake_blocking_success_locked_low_prio_pending( void )
865 {
866     SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
867
868     vFakePortAssertIfInterruptPriorityInvalid_Ignore();
869
870     /* Export for callbacks */
871     xSemaphoreHandleStatic = xSemaphore;
872
873     xTaskCheckForTimeOut_Stub( &xSemaphoreTake_xTaskCheckForTimeOutCB );
874     xTaskResumeAll_Stub( &xSemaphoreTake_xTaskResumeAllCallback );
875
876     td_task_setFakeTaskPriority( DEFAULT_PRIORITY - 1 );
877
878     td_task_addFakeTaskWaitingToReceiveFromQueue( xSemaphore );
879
880     TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreTake( xSemaphore, TICKS_TO_WAIT ) );
881
882     TEST_ASSERT_EQUAL( 0, uxSemaphoreGetCount( xSemaphore ) );
883
884     TEST_ASSERT_EQUAL( NUM_CALLS_TO_INTERCEPT, td_task_getYieldCount() );
885
886     TEST_ASSERT_EQUAL( NUM_CALLS_TO_INTERCEPT, td_task_getCount_vPortYieldWithinAPI() );
887
888     vQueueDelete( xSemaphore );
889 }