3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
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:
12 * The above copyright notice and this permission notice shall be included in all
13 * copies or substantial portions of the Software.
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.
22 * https://www.FreeRTOS.org
23 * https://github.com/FreeRTOS
26 /*! @file binary_semaphore_utest.c */
28 #include "../queue_utest_common.h"
29 #include "mock_fake_port.h"
33 #include "FreeRTOSConfig.h"
36 /* =============================== CONSTANTS =============================== */
38 /* ============================ GLOBAL VARIABLES =========================== */
40 /* Used to share a semaphore handle between a test case and callback */
41 static SemaphoreHandle_t xSemaphoreHandleStatic;
43 /* ========================== CALLBACK FUNCTIONS =========================== */
45 /* ============================= Unity Fixtures ============================= */
62 int suiteTearDown( int numFailures )
64 return commonSuiteTearDown( numFailures );
67 /* ========================== Helper functions =========================== */
69 /* ============================= Test Cases ============================== */
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
77 void test_macro_xSemaphoreTake_xSemaphoreCreateBinary_fail( void )
79 SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
81 /* validate returned semaphore handle */
82 TEST_ASSERT_NOT_EQUAL( NULL, xSemaphore );
84 TEST_ASSERT_EQUAL( QUEUE_T_SIZE, getLastMallocSize() );
86 /* Verify that an immediate xSemaphoreTake operation fails */
87 TEST_ASSERT_EQUAL( pdFALSE, xSemaphoreTake( xSemaphore, 0 ) );
89 vSemaphoreDelete( xSemaphore );
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
98 void test_macro_xSemaphoreGive_xSemaphoreCreateBinary_success( void )
100 SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
102 /* validate returned semaphore handle */
103 TEST_ASSERT_NOT_EQUAL( NULL, xSemaphore );
105 TEST_ASSERT_EQUAL( QUEUE_T_SIZE, getLastMallocSize() );
107 /* Verify that an immediate xSemaphoreGive operation succeeds */
108 TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreGive( xSemaphore ) );
110 vSemaphoreDelete( xSemaphore );
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
120 void test_macro_xSemaphoreTake_vSemaphoreCreateBinary_success( void )
122 SemaphoreHandle_t xSemaphore = NULL;
124 vSemaphoreCreateBinary( xSemaphore );
126 /* validate returned semaphore handle */
127 TEST_ASSERT_NOT_EQUAL( NULL, xSemaphore );
128 TEST_ASSERT_EQUAL( QUEUE_T_SIZE, getLastMallocSize() );
130 /* Verify that an immediate xSemaphoreTake operation succeeds */
131 TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreTake( xSemaphore, 0 ) );
133 vSemaphoreDelete( xSemaphore );
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
143 void test_macro_xSemaphoreGive_vSemaphoreCreateBinary_fail( void )
145 SemaphoreHandle_t xSemaphore = NULL;
147 vSemaphoreCreateBinary( xSemaphore );
149 /* validate returned semaphore handle */
150 TEST_ASSERT_NOT_EQUAL( NULL, xSemaphore );
151 TEST_ASSERT_EQUAL( QUEUE_T_SIZE, getLastMallocSize() );
153 /* Verify that an immediate xSemaphoreGive operation fails */
154 TEST_ASSERT_EQUAL( pdFALSE, xSemaphoreGive( xSemaphore ) );
156 vSemaphoreDelete( xSemaphore );
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
166 void test_macro_xSemaphoreGive_xSemaphoreTake_success( void )
168 SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
170 /* validate returned semaphore handle */
171 TEST_ASSERT_NOT_EQUAL( NULL, xSemaphore );
173 TEST_ASSERT_EQUAL( QUEUE_T_SIZE, getLastMallocSize() );
175 /* Verify that an immediate xSemaphoreGive operation succeeds */
176 TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreGive( xSemaphore ) );
178 /* Verify that a subsequent xSemaphoreTake operation succeeds */
179 TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreTake( xSemaphore, 0 ) );
181 vSemaphoreDelete( xSemaphore );
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
191 void test_macro_xSemaphoreGive_multiple_fail( void )
193 SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
195 /* validate returned semaphore handle */
196 TEST_ASSERT_NOT_EQUAL( NULL, xSemaphore );
198 TEST_ASSERT_EQUAL( QUEUE_T_SIZE, getLastMallocSize() );
200 /* Verify that an immediate xSemaphoreGive operation succeeds */
201 TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreGive( xSemaphore ) );
203 /* Verify that the second xSemaphoreGive operation fails */
204 TEST_ASSERT_EQUAL( pdFALSE, xSemaphoreGive( xSemaphore ) );
206 vSemaphoreDelete( xSemaphore );
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
216 void test_macro_xSemaphoreTake_multiple_fail( void )
218 SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
220 /* validate returned semaphore handle */
221 TEST_ASSERT_NOT_EQUAL( NULL, xSemaphore );
223 TEST_ASSERT_EQUAL( QUEUE_T_SIZE, getLastMallocSize() );
225 /* Verify that an immediate xSemaphoreGive operation succeeds */
226 TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreGive( xSemaphore ) );
228 /* Verify that a subsequent xSemaphoreTake operation succeeds */
229 TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreTake( xSemaphore, 0 ) );
231 /* Verify that a second xSemaphoreTake operation fails */
232 TEST_ASSERT_EQUAL( pdFALSE, xSemaphoreTake( xSemaphore, 0 ) );
234 vSemaphoreDelete( xSemaphore );
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
244 void test_macro_uxSemaphoreGetCount( void )
246 SemaphoreHandle_t xSemaphore = NULL;
248 vSemaphoreCreateBinary( xSemaphore );
250 TEST_ASSERT_EQUAL( B_SEMPHR_AVAILABLE, uxSemaphoreGetCount( xSemaphore ) );
252 ( void ) xSemaphoreTake( xSemaphore, 0 );
254 TEST_ASSERT_EQUAL( B_SEMPHR_TAKEN, uxSemaphoreGetCount( xSemaphore ) );
256 vSemaphoreDelete( xSemaphore );
260 * @brief Test xSemaphoreTakeFromISR with a Binary Semaphore
261 * @coverage xQueueReceiveFromISR
263 void test_macro_xSemaphoreTakeFromISR_success( void )
265 SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
267 vFakePortAssertIfInterruptPriorityInvalid_Expect();
269 /* Give the Binary Semaphore */
270 ( void ) xSemaphoreGive( xSemaphore );
272 TEST_ASSERT_EQUAL( B_SEMPHR_AVAILABLE, uxSemaphoreGetCount( xSemaphore ) );
274 TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreTakeFromISR( xSemaphore, NULL ) );
276 TEST_ASSERT_EQUAL( B_SEMPHR_TAKEN, uxSemaphoreGetCount( xSemaphore ) );
278 vSemaphoreDelete( xSemaphore );
282 * @brief xSemaphoreGiveFromISR with an empty queue
283 * @coverage xQueueGiveFromISR
285 void test_macro_xSemaphoreGiveFromISR_success( void )
287 SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
289 vFakePortAssertIfInterruptPriorityInvalid_Expect();
291 TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreGiveFromISR( xSemaphore, NULL ) );
293 TEST_ASSERT_EQUAL( B_SEMPHR_AVAILABLE, uxSemaphoreGetCount( xSemaphore ) );
295 vSemaphoreDelete( xSemaphore );
299 * @brief xSemaphoreGiveFromISR with a full queue
300 * @coverage xQueueGiveFromISR
302 void test_macro_xSemaphoreGiveFromISR_fail( void )
304 SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
306 vFakePortAssertIfInterruptPriorityInvalid_Expect();
307 TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreGiveFromISR( xSemaphore, NULL ) );
309 vFakePortAssertIfInterruptPriorityInvalid_Expect();
310 TEST_ASSERT_EQUAL( errQUEUE_FULL, xSemaphoreGiveFromISR( xSemaphore, NULL ) );
312 TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreTake( xSemaphore, 0 ) );
314 vSemaphoreDelete( xSemaphore );
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
323 void test_macro_xSemaphoreGiveFromISR_high_priority_pending_null_ptr( void )
325 SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
327 vFakePortAssertIfInterruptPriorityInvalid_Expect();
329 /* Insert an item into the event list */
330 td_task_setFakeTaskPriority( DEFAULT_PRIORITY + 1 );
331 td_task_addFakeTaskWaitingToReceiveFromQueue( xSemaphore );
333 /* Give the Binary Semaphore */
334 TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreGiveFromISR( xSemaphore, NULL ) );
336 TEST_ASSERT_EQUAL( pdTRUE, td_task_getYieldPending() );
338 TEST_ASSERT_EQUAL( B_SEMPHR_AVAILABLE, uxSemaphoreGetCount( xSemaphore ) );
340 vSemaphoreDelete( xSemaphore );
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
349 void test_macro_xSemaphoreGiveFromISR_high_priority_pending( void )
351 SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
353 vFakePortAssertIfInterruptPriorityInvalid_Expect();
355 /* Insert an item into the event list */
356 td_task_setFakeTaskPriority( DEFAULT_PRIORITY + 1 );
357 td_task_addFakeTaskWaitingToReceiveFromQueue( xSemaphore );
359 BaseType_t xHigherPriorityTaskWoken = pdFALSE;
361 /* Give the semaphore */
362 TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken ) );
364 TEST_ASSERT_EQUAL( pdTRUE, xHigherPriorityTaskWoken );
366 TEST_ASSERT_EQUAL( pdTRUE, td_task_getYieldPending() );
368 TEST_ASSERT_EQUAL( B_SEMPHR_AVAILABLE, uxSemaphoreGetCount( xSemaphore ) );
370 vSemaphoreDelete( xSemaphore );
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
379 void test_macro_xSemaphoreGiveFromISR_low_priority_pending( void )
381 SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
383 vFakePortAssertIfInterruptPriorityInvalid_Expect();
385 /* Insert an item into the event list */
386 td_task_setFakeTaskPriority( DEFAULT_PRIORITY - 1 );
387 td_task_addFakeTaskWaitingToReceiveFromQueue( xSemaphore );
389 BaseType_t xHigherPriorityTaskWoken = pdFALSE;
391 /* Give the semaphore */
392 TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken ) );
394 TEST_ASSERT_EQUAL( pdFALSE, xHigherPriorityTaskWoken );
396 TEST_ASSERT_EQUAL( pdFALSE, td_task_getYieldPending() );
398 TEST_ASSERT_EQUAL( B_SEMPHR_AVAILABLE, uxSemaphoreGetCount( xSemaphore ) );
400 vSemaphoreDelete( xSemaphore );
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
408 void test_macro_xSemaphoreGiveFromISR_no_pending( void )
410 SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
412 vFakePortAssertIfInterruptPriorityInvalid_Expect();
414 BaseType_t xHigherPriorityTaskWoken = pdFALSE;
416 /* Give the semaphore */
417 TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken ) );
419 TEST_ASSERT_EQUAL( pdFALSE, xHigherPriorityTaskWoken );
421 TEST_ASSERT_EQUAL( pdFALSE, td_task_getYieldPending() );
423 TEST_ASSERT_EQUAL( B_SEMPHR_AVAILABLE, uxSemaphoreGetCount( xSemaphore ) );
425 vSemaphoreDelete( xSemaphore );
429 * @brief Test xSemaphoreGiveFromISR on a semaphore that is locked
430 * @coverage xQueueGiveFromISR
432 void test_xSemaphoreGiveFromISR_locked( void )
434 SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
436 /* Set private lock counters */
437 vSetQueueRxLock( xSemaphore, queueLOCKED_UNMODIFIED );
438 vSetQueueTxLock( xSemaphore, queueLOCKED_UNMODIFIED );
440 vFakePortAssertIfInterruptPriorityInvalid_Expect();
442 TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreGiveFromISR( xSemaphore, NULL ) );
444 /* Verify that the cRxLock counter has not changed */
445 TEST_ASSERT_EQUAL( queueLOCKED_UNMODIFIED, cGetQueueRxLock( xSemaphore ) );
447 /* Verify that the cTxLock counter has been incremented */
448 TEST_ASSERT_EQUAL( queueLOCKED_UNMODIFIED + 1, cGetQueueTxLock( xSemaphore ) );
450 TEST_ASSERT_EQUAL( B_SEMPHR_AVAILABLE, uxSemaphoreGetCount( xSemaphore ) );
452 vSemaphoreDelete( xSemaphore );
456 * @brief Test xSemaphoreGiveFromISR on a semaphore that is locked and cRxLock overflows.
457 * @coverage xQueueGiveFromISR
459 void test_xSemaphoreGiveFromISR_locked_overflow( void )
461 SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
463 /* Set private lock counters */
464 vSetQueueRxLock( xSemaphore, INT8_MAX );
465 vSetQueueTxLock( xSemaphore, INT8_MAX );
467 vFakePortAssertIfInterruptPriorityInvalid_Expect();
469 /* Expect an assertion since the cTxLock value has overflowed */
470 fakeAssertExpectFail();
472 TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreGiveFromISR( xSemaphore, NULL ) );
474 /* Verify that the cRxLock counter has not changed */
475 TEST_ASSERT_EQUAL( INT8_MAX, cGetQueueRxLock( xSemaphore ) );
477 /* Verify that the cTxLock counter has been incremented */
478 TEST_ASSERT_EQUAL( INT8_MIN, cGetQueueTxLock( xSemaphore ) );
480 TEST_ASSERT_EQUAL( true, fakeAssertGetFlagAndClear() );
482 TEST_ASSERT_EQUAL( B_SEMPHR_AVAILABLE, uxSemaphoreGetCount( xSemaphore ) );
484 vSemaphoreDelete( xSemaphore );
488 * @brief Test xSemaphoreTake with an occupied semaphore with higher priority tasks waiting
489 * @coverage xQueueSemaphoreTake
491 void test_xSemaphoreTake_tasks_waiting_higher_priority( void )
493 /* Create a new binary semaphore */
494 SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
496 ( void ) xSemaphoreGive( xSemaphore );
498 /* Insert an item into the event list */
499 td_task_setFakeTaskPriority( DEFAULT_PRIORITY + 1 );
500 td_task_addFakeTaskWaitingToSendToQueue( xSemaphore );
502 /* take the semaphore */
503 TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreTake( xSemaphore, 0 ) );
505 TEST_ASSERT_EQUAL( 1, td_task_getYieldCount() );
507 TEST_ASSERT_EQUAL( 1, td_task_getCount_vPortYieldWithinAPI() );
509 TEST_ASSERT_EQUAL( B_SEMPHR_TAKEN, uxSemaphoreGetCount( xSemaphore ) );
511 vSemaphoreDelete( xSemaphore );
515 * @brief Test xSemaphoreTake with an occupied semaphore with an equal priority task waiting
516 * @coverage xQueueSemaphoreTake
518 void test_xSemaphoreTake_tasks_waiting_equal_priority( void )
520 /* Create a new binary semaphore */
521 SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
523 ( void ) xSemaphoreGive( xSemaphore );
525 /* Insert an item into the event list */
526 td_task_setFakeTaskPriority( DEFAULT_PRIORITY );
527 td_task_addFakeTaskWaitingToSendToQueue( xSemaphore );
529 /* take the semaphore */
530 TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreTake( xSemaphore, 0 ) );
532 TEST_ASSERT_EQUAL( 0, td_task_getYieldCount() );
534 TEST_ASSERT_EQUAL( 0, td_task_getCount_vPortYieldWithinAPI() );
536 TEST_ASSERT_EQUAL( B_SEMPHR_TAKEN, uxSemaphoreGetCount( xSemaphore ) );
538 vSemaphoreDelete( xSemaphore );
542 * @brief Test xSemaphoreTake with an occupied semaphore with lower priority tasks waiting.
543 * @coverage xQueueSemaphoreTake
545 void test_xSemaphoreTake_tasks_waiting_lower_priority( void )
547 /* Create a new binary semaphore */
548 SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
550 ( void ) xSemaphoreGive( xSemaphore );
552 /* Insert an item into the event list */
553 td_task_setFakeTaskPriority( DEFAULT_PRIORITY - 1 );
554 td_task_addFakeTaskWaitingToSendToQueue( xSemaphore );
556 /* take the semaphore */
557 TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreTake( xSemaphore, 0 ) );
559 TEST_ASSERT_EQUAL( 0, td_task_getYieldCount() );
561 TEST_ASSERT_EQUAL( 0, td_task_getCount_vPortYieldWithinAPI() );
563 TEST_ASSERT_EQUAL( B_SEMPHR_TAKEN, uxSemaphoreGetCount( xSemaphore ) );
565 vSemaphoreDelete( xSemaphore );
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
574 void test_xSemaphoreTake_blocking_suspended_assert( void )
576 SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
578 fakeAssertExpectFail();
580 vTaskSuspendAll_Stub( td_task_vTaskSuspendAllStubNoCheck );
582 td_task_setSchedulerState( taskSCHEDULER_SUSPENDED );
584 TEST_ASSERT_EQUAL( pdFALSE, xSemaphoreTake( xSemaphore, TICKS_TO_WAIT ) );
586 TEST_ASSERT_EQUAL( TICKS_TO_WAIT, td_task_getYieldCount() );
588 TEST_ASSERT_EQUAL( TICKS_TO_WAIT, td_task_getCount_vPortYieldWithinAPI() );
590 TEST_ASSERT_EQUAL( pdTRUE, fakeAssertGetFlagAndClear() );
592 td_task_setSchedulerState( taskSCHEDULER_RUNNING );
594 vSemaphoreDelete( xSemaphore );
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
603 void test_xSemaphoreTake_nonblocking_suspended_noassert( void )
605 SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
607 td_task_setSchedulerState( taskSCHEDULER_SUSPENDED );
609 TEST_ASSERT_EQUAL( pdFALSE, xSemaphoreTake( xSemaphore, 0 ) );
611 td_task_setSchedulerState( taskSCHEDULER_RUNNING );
613 vSemaphoreDelete( xSemaphore );
617 * @brief Callback which calls xSemaphoreGive on xSemaphoreHandleStatic
619 static BaseType_t blocking_success_xTaskCheckForTimeOut_cb( TimeOut_t * const pxTimeOut,
620 TickType_t * const pxTicksToWait,
621 int cmock_num_calls )
623 BaseType_t xReturnValue = td_task_xTaskCheckForTimeOutStub( pxTimeOut, pxTicksToWait, cmock_num_calls );
625 if( cmock_num_calls == NUM_CALLS_TO_INTERCEPT )
627 ( void ) xSemaphoreGiveFromISR( xSemaphoreHandleStatic, NULL );
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
638 void test_xSemaphoreTake_blocking_success( void )
640 SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
642 /* Export for blocking_success_xTaskCheckForTimeOut_cb callback */
643 xSemaphoreHandleStatic = xSemaphore;
645 vFakePortAssertIfInterruptPriorityInvalid_Ignore();
647 xTaskCheckForTimeOut_Stub( &blocking_success_xTaskCheckForTimeOut_cb );
649 TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreTake( xSemaphore, TICKS_TO_WAIT ) );
651 TEST_ASSERT_EQUAL( NUM_CALLS_TO_INTERCEPT, td_task_getYieldCount() );
653 TEST_ASSERT_EQUAL( NUM_CALLS_TO_INTERCEPT, td_task_getCount_vPortYieldWithinAPI() );
655 TEST_ASSERT_EQUAL( B_SEMPHR_TAKEN, uxSemaphoreGetCount( xSemaphore ) );
656 vSemaphoreDelete( xSemaphore );
660 * @brief Callback which calls xSemaphoreGive on xSemaphoreHandleStatic when
661 * cmock_num_calls == TICKS_TO_WAIT
663 static BaseType_t blocking_last_chance_xTaskCheckForTimeOut_cb( TimeOut_t * const pxTimeOut,
664 TickType_t * const pxTicksToWait,
665 int cmock_num_calls )
667 BaseType_t xReturnValue = td_task_xTaskCheckForTimeOutStub( pxTimeOut, pxTicksToWait, cmock_num_calls );
669 if( cmock_num_calls == TICKS_TO_WAIT )
671 ( void ) xSemaphoreGiveFromISR( xSemaphoreHandleStatic, NULL );
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
683 void test_xSemaphoreTake_blocking_success_last_chance( void )
685 SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
687 /* Export for blocking_success_xTaskCheckForTimeOut_cb callback */
688 xSemaphoreHandleStatic = xSemaphore;
690 vFakePortAssertIfInterruptPriorityInvalid_Expect();
692 xTaskCheckForTimeOut_Stub( &blocking_last_chance_xTaskCheckForTimeOut_cb );
694 TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreTake( xSemaphore, TICKS_TO_WAIT ) );
696 TEST_ASSERT_EQUAL( TICKS_TO_WAIT, td_task_getYieldCount() );
698 TEST_ASSERT_EQUAL( TICKS_TO_WAIT, td_task_getCount_vPortYieldWithinAPI() );
700 TEST_ASSERT_EQUAL( B_SEMPHR_TAKEN, uxSemaphoreGetCount( xSemaphore ) );
701 vSemaphoreDelete( xSemaphore );
705 * @brief Test xSemaphoreTake in blocking mode with a taken binary semaphore
706 * @coverage xQueueSemaphoreTake
708 void test_xSemaphoreTake_blocking_timeout( void )
710 SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
712 TEST_ASSERT_EQUAL( pdFALSE, xSemaphoreTake( xSemaphore, TICKS_TO_WAIT ) );
714 TEST_ASSERT_EQUAL( TICKS_TO_WAIT, td_task_getYieldCount() );
716 TEST_ASSERT_EQUAL( TICKS_TO_WAIT, td_task_getCount_vPortYieldWithinAPI() );
718 vSemaphoreDelete( xSemaphore );
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
727 void test_xSemaphoreTake_blocking_locked( void )
729 /* Create a new binary semaphore */
730 SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
732 /* Set private lock counters */
733 vSetQueueRxLock( xSemaphore, queueLOCKED_UNMODIFIED );
734 vSetQueueTxLock( xSemaphore, queueLOCKED_UNMODIFIED );
736 /* Run xSemaphoreTake in blocking mode with the semaphore locked */
737 TEST_ASSERT_EQUAL( pdFALSE, xSemaphoreTake( xSemaphore, TICKS_TO_WAIT ) );
739 TEST_ASSERT_EQUAL( TICKS_TO_WAIT, td_task_getYieldCount() );
741 TEST_ASSERT_EQUAL( TICKS_TO_WAIT, td_task_getCount_vPortYieldWithinAPI() );
743 /* Verify that the semaphore is now unlocked */
744 TEST_ASSERT_EQUAL( queueUNLOCKED, cGetQueueRxLock( xSemaphore ) );
745 TEST_ASSERT_EQUAL( queueUNLOCKED, cGetQueueTxLock( xSemaphore ) );
747 vSemaphoreDelete( xSemaphore );
751 * @brief Callback for test_xSemaphoreTake_blocking_success_locked_no_pending
752 * which adds an item to it's test queue.
754 static BaseType_t xSemaphoreTake_xTaskCheckForTimeOutCB( TimeOut_t * const pxTimeOut,
755 TickType_t * const pxTicksToWait,
756 int cmock_num_calls )
758 BaseType_t xReturnValue = td_task_xTaskCheckForTimeOutStub( pxTimeOut, pxTicksToWait, cmock_num_calls );
760 if( cmock_num_calls == NUM_CALLS_TO_INTERCEPT )
762 TEST_ASSERT_TRUE( xSemaphoreGiveFromISR( xSemaphoreHandleStatic, NULL ) );
763 TEST_ASSERT_EQUAL( 1, uxQueueMessagesWaiting( xSemaphoreHandleStatic ) );
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
775 void test_xSemaphoreTake_blocking_success_locked_no_pending( void )
777 SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
779 vFakePortAssertIfInterruptPriorityInvalid_Ignore();
781 /* Export for callbacks */
782 xSemaphoreHandleStatic = xSemaphore;
784 xTaskCheckForTimeOut_Stub( &xSemaphoreTake_xTaskCheckForTimeOutCB );
785 xTaskResumeAll_Stub( &td_task_xTaskResumeAllStub );
787 TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreTake( xSemaphore, TICKS_TO_WAIT ) );
789 TEST_ASSERT_EQUAL( 0, uxSemaphoreGetCount( xSemaphore ) );
791 TEST_ASSERT_EQUAL( NUM_CALLS_TO_INTERCEPT, td_task_getYieldCount() );
793 TEST_ASSERT_EQUAL( NUM_CALLS_TO_INTERCEPT, td_task_getCount_vPortYieldWithinAPI() );
795 vQueueDelete( xSemaphore );
800 * @brief Callback for xTaskResumeAll used by tests for blocking calls to
803 static BaseType_t xSemaphoreTake_xTaskResumeAllCallback( int cmock_num_calls )
805 BaseType_t xReturnValue = td_task_xTaskResumeAllStub( cmock_num_calls );
807 /* If td_task_xTaskResumeAllStub returns pdTRUE, a higher priority task is pending
808 * Receive from an ISR to block */
809 if( pdTRUE == xReturnValue )
811 if( cmock_num_calls == NUM_CALLS_TO_INTERCEPT )
813 TEST_ASSERT_EQUAL( 1, uxSemaphoreGetCount( xSemaphoreHandleStatic ) );
814 TEST_ASSERT_TRUE( xSemaphoreTakeFromISR( xSemaphoreHandleStatic, NULL ) );
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
827 void test_xSemaphoreTake_blocking_timeout_locked_high_prio_pending( void )
829 SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
831 vFakePortAssertIfInterruptPriorityInvalid_Ignore();
833 /* Export for callbacks */
834 xSemaphoreHandleStatic = xSemaphore;
836 xTaskCheckForTimeOut_Stub( &xSemaphoreTake_xTaskCheckForTimeOutCB );
837 xTaskResumeAll_Stub( &xSemaphoreTake_xTaskResumeAllCallback );
839 td_task_setFakeTaskPriority( DEFAULT_PRIORITY + 1 );
841 td_task_addFakeTaskWaitingToReceiveFromQueue( xSemaphore );
843 TEST_ASSERT_EQUAL( pdFALSE, xSemaphoreTake( xSemaphore, TICKS_TO_WAIT ) );
845 TEST_ASSERT_EQUAL( 0, uxSemaphoreGetCount( xSemaphore ) );
847 TEST_ASSERT_EQUAL( TICKS_TO_WAIT, td_task_getYieldCount() );
849 TEST_ASSERT_EQUAL( NUM_CALLS_TO_INTERCEPT + 1, td_task_getCount_YieldFromTaskResumeAll() );
851 TEST_ASSERT_EQUAL( NUM_CALLS_TO_INTERCEPT - 1, td_task_getCount_vPortYieldWithinAPI() );
853 TEST_ASSERT_EQUAL( 1, td_task_getCount_vTaskMissedYield() );
855 vQueueDelete( xSemaphore );
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
864 void test_xSemaphoreTake_blocking_success_locked_low_prio_pending( void )
866 SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
868 vFakePortAssertIfInterruptPriorityInvalid_Ignore();
870 /* Export for callbacks */
871 xSemaphoreHandleStatic = xSemaphore;
873 xTaskCheckForTimeOut_Stub( &xSemaphoreTake_xTaskCheckForTimeOutCB );
874 xTaskResumeAll_Stub( &xSemaphoreTake_xTaskResumeAllCallback );
876 td_task_setFakeTaskPriority( DEFAULT_PRIORITY - 1 );
878 td_task_addFakeTaskWaitingToReceiveFromQueue( xSemaphore );
880 TEST_ASSERT_EQUAL( pdTRUE, xSemaphoreTake( xSemaphore, TICKS_TO_WAIT ) );
882 TEST_ASSERT_EQUAL( 0, uxSemaphoreGetCount( xSemaphore ) );
884 TEST_ASSERT_EQUAL( NUM_CALLS_TO_INTERCEPT, td_task_getYieldCount() );
886 TEST_ASSERT_EQUAL( NUM_CALLS_TO_INTERCEPT, td_task_getCount_vPortYieldWithinAPI() );
888 vQueueDelete( xSemaphore );