Mayank Gupta / Mbed OS pelion-example-frdm

Dependencies:   FXAS21002 FXOS8700Q

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pal_rtos_test.c Source File

pal_rtos_test.c

00001 /*******************************************************************************
00002  * Copyright 2016, 2017 ARM Ltd.
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  *******************************************************************************/
00016 
00017 // Needed for PRIu64 on FreeRTOS
00018 #include <stdio.h>
00019 
00020 #include "pal.h"
00021 #include "unity.h"
00022 #include "unity_fixture.h"
00023 #include "pal_rtos_test_utils.h"
00024 #include "sotp.h"
00025 #include "pal_plat_rtos.h"
00026 #include "test_runners.h"
00027 
00028 #include <string.h>
00029 #include <stdlib.h>
00030 
00031 #define TRACE_GROUP "PAL"
00032 
00033 TEST_GROUP(pal_rtos);
00034 
00035 //Sometimes you may want to get local data in a module,
00036 //for example if you need to pass a reference.
00037 //However, you should usually avoid this.
00038 //extern int Counter;
00039 threadsArgument_t g_threadsArg = {0};
00040 
00041 // Note: this struct is accessed from the test code thread and timer callbacks
00042 // without any synchronization, so beware.
00043 volatile timerArgument_t g_timerArgs = {0};
00044 
00045 palMutexID_t mutex1 = NULLPTR;
00046 palMutexID_t mutex2 = NULLPTR;
00047 palSemaphoreID_t semaphore1 = NULLPTR;
00048 palRecursiveMutexParam_t* recursiveMutexData = NULL;
00049 #define PAL_RUNNING_TEST_TIME   5  //estimation on length of test in seconds
00050 #define PAL_TEST_HIGH_RES_TIMER 100
00051 #define PAL_TEST_HIGH_RES_TIMER2 10
00052 #define PAL_TEST_PERCENTAGE_TIMER_ERROR 10
00053 #define PAL_TEST_PERCENTAGE_HUNDRED  100
00054 #define PAL_TEST_TIME_SECOND 1000
00055 
00056 #define PAL_DELAY_RUN_LOOPS 10
00057 
00058 //Forward declarations
00059 void palRunThreads(void);
00060 
00061 
00062 TEST_SETUP(pal_rtos)
00063 {
00064     palStatus_t status = PAL_SUCCESS;
00065     status = pal_init();
00066     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00067 
00068 }
00069 
00070 TEST_TEAR_DOWN(pal_rtos)
00071 {
00072     if (NULL != recursiveMutexData)
00073     {
00074         if (recursiveMutexData->higherPriorityThread != NULLPTR)
00075         {
00076             pal_osThreadTerminate(&(recursiveMutexData->higherPriorityThread));
00077         }
00078         if (recursiveMutexData->lowerPriorityThread != NULLPTR)
00079         {
00080             pal_osThreadTerminate(&(recursiveMutexData->lowerPriorityThread));
00081         }
00082         if (recursiveMutexData->mtx != NULLPTR)
00083         {
00084             pal_osMutexDelete(&(recursiveMutexData->mtx));
00085         }
00086         if (recursiveMutexData->sem != NULLPTR)
00087         {
00088             pal_osSemaphoreDelete(&recursiveMutexData->sem);
00089         }
00090         free(recursiveMutexData);
00091         recursiveMutexData = NULL;
00092     }
00093     pal_destroy();
00094 }
00095 
00096 #define TEST_OUTPUT_32_1 "u32 1: 123456789"
00097 #define TEST_OUTPUT_32_2 "s32 2: -123456789"
00098 
00099 #define TEST_OUTPUT_INT_1 "int 1: 12345"
00100 
00101 #define TEST_OUTPUT_64_1 "u64 1: 123456789"
00102 #define TEST_OUTPUT_64_2 "u64 2: 18446744073709551615"
00103 #define TEST_OUTPUT_64_3 "s64 1: -123456789"
00104 #define TEST_OUTPUT_64_4 "s64 2: -9223372036854775801"
00105 
00106 /*! \brief Sanity check of the snprintf() from the libc/system
00107  * Fails if the snprintf() does not support 64b formatter (%lld or %llu)
00108  *
00109  * | # |    Step                               |   Expected  |
00110  * |---|---------------------------------------|-------------|
00111  * |  1| snprintf("%PRIu32)                    | success     |
00112  * |  2| snprintf("%PRId32)                    | success     |
00113  * |  3| snprintf("%d)                         | success     |
00114  * |  4| snprintf("%llu) (32b value)           | success     |
00115  * |  5| snprintf("%llu) (64b value)           | success     |
00116  * |  6| snprintf("%PRIu64) (32b value)        | success     |
00117  * |  7| snprintf("%PRIu64) (64b value)        | success     |
00118  * |  8| snprintf("%lld) (32b value)           | success     |
00119  * |  9| snprintf("%lld) (64b value)           | success     |
00120  * | 10| snprintf("%PRId64) (32b value)        | success     |
00121  * | 11| snprintf("%PRId64) (64b value)        | success     |
00122  */
00123 
00124 TEST(pal_rtos, BasicSnprintfTestInt)
00125 {
00126     char output[64];
00127 
00128     int result;
00129 
00130     uint32_t test32u;
00131     int32_t test32s;
00132 
00133     uint64_t test64u;
00134     int64_t test64s;
00135 
00136     // first test with 32b variables
00137     /*#1*/
00138     test32u = 123456789;
00139     result = snprintf(output, sizeof(output), "u32 1: %" PRIu32, test32u);
00140     TEST_ASSERT_EQUAL(strlen(TEST_OUTPUT_32_1), result);
00141     TEST_ASSERT_EQUAL_STRING(TEST_OUTPUT_32_1, output);
00142 
00143     /*#2*/
00144     test32s = 0 - 123456789;
00145     result = snprintf(output, sizeof(output), "s32 2: %" PRId32, test32s);
00146     TEST_ASSERT_EQUAL(strlen(TEST_OUTPUT_32_2), result);
00147     TEST_ASSERT_EQUAL_STRING(TEST_OUTPUT_32_2, output);
00148 
00149     /*#3*/
00150     // Note: this assumes just that int is at least 16 bits, which should be somewhat safe
00151     int testInt = 12345;
00152     result = snprintf(output, sizeof(output), "int 1: %d", testInt);
00153     TEST_ASSERT_EQUAL(strlen(TEST_OUTPUT_INT_1), result);
00154     TEST_ASSERT_EQUAL_STRING(TEST_OUTPUT_INT_1, output);
00155 
00156     /*#4*/
00157     // Then with 64b variables, hard coded, non standard %llu and %lld.
00158     // This part is a bit questionable, should it be ran or actually the code
00159     // which uses the %llu and expects it to have 64b fixed?!
00160     test64u = UINT64_C(123456789);
00161     result = snprintf(output, sizeof(output), "u64 1: %llu", (long long unsigned)test64u);
00162     TEST_ASSERT_EQUAL(strlen(TEST_OUTPUT_64_1), result);
00163     TEST_ASSERT_EQUAL_STRING(TEST_OUTPUT_64_1, output);
00164 
00165     /*#5*/
00166     test64u = UINT64_C(18446744073709551615);
00167     result = snprintf(output, sizeof(output), "u64 2: %llu", (long long unsigned)test64u);
00168     TEST_ASSERT_EQUAL(strlen(TEST_OUTPUT_64_2), result);
00169     TEST_ASSERT_EQUAL_STRING(TEST_OUTPUT_64_2, output);
00170 
00171     /*#6*/
00172     // the standard PRIu64 should work everywhere
00173     test64u = UINT64_C(123456789);
00174     result = snprintf(output, sizeof(output), "u64 1: %" PRIu64, test64u);
00175     TEST_ASSERT_EQUAL(strlen(TEST_OUTPUT_64_1), result);
00176     TEST_ASSERT_EQUAL_STRING(TEST_OUTPUT_64_1, output);
00177 
00178     /*#7*/
00179     test64u = UINT64_C(18446744073709551615);
00180     result = snprintf(output, sizeof(output), "u64 2: %" PRIu64, test64u);
00181     TEST_ASSERT_EQUAL(strlen(TEST_OUTPUT_64_2), result);
00182     TEST_ASSERT_EQUAL_STRING(TEST_OUTPUT_64_2, output);
00183 
00184     /*#8*/
00185     // Then with 64b signed variables, hard coded, non standard %lld
00186     // Again, this part is a bit questionable, should it be ran or actually the code
00187     // which uses the %lld and expects it to have 64b fixed?!
00188     test64s = INT64_C(-123456789);
00189     result = snprintf(output, sizeof(output), "s64 1: %lld", (long long)test64s);
00190     TEST_ASSERT_EQUAL(strlen(TEST_OUTPUT_64_3), result);
00191     TEST_ASSERT_EQUAL_STRING(TEST_OUTPUT_64_3, output);
00192 
00193     /*#9*/
00194     // a value of INT64_MIN might also be used, but setting that portably would need use of INT64_C()
00195     test64s = INT64_C(-9223372036854775801);
00196     result = snprintf(output, sizeof(output), "s64 2: %lld", (long long)test64s);
00197     TEST_ASSERT_EQUAL(strlen(TEST_OUTPUT_64_4), result);
00198     TEST_ASSERT_EQUAL_STRING(TEST_OUTPUT_64_4, output);
00199 
00200     /*#10*/
00201     // the standard PRId64 should work everywhere
00202     test64s = INT64_C(-123456789);
00203     result = snprintf(output, sizeof(output), "s64 1: %" PRId64, test64s);
00204     TEST_ASSERT_EQUAL(strlen(TEST_OUTPUT_64_3), result);
00205     TEST_ASSERT_EQUAL_STRING(TEST_OUTPUT_64_3, output);
00206 
00207     /*#11*/
00208     test64s = INT64_C(-9223372036854775801);
00209     result = snprintf(output, sizeof(output), "s64 2: %" PRId64, test64s);
00210     TEST_ASSERT_EQUAL(strlen(TEST_OUTPUT_64_4), result);
00211     TEST_ASSERT_EQUAL_STRING(TEST_OUTPUT_64_4, output);
00212 }
00213 
00214 #define TEST_OUTPUT_SIZE_1 "size_t 1: 123456789"
00215 #define TEST_OUTPUT_SIZE_2 "size_t 2: -123456789"
00216 
00217 /*! \brief Sanity check of the snprintf() from the libc/system
00218  * Fails if the snprintf() does not support size_t/ssize_t formatter (%zu or %zd)
00219  *
00220  * | # |    Step                               |   Expected  |
00221  * |---|---------------------------------------|-------------|
00222  * | 1 | snprintf("%zu) (size_t/32b value)     | success     |
00223  * | 2 | snprintf("%zd) (size_t/32b value)     | success     |
00224  */
00225 TEST(pal_rtos, BasicSnprintfTestSize)
00226 {
00227 // The %zu and %zd are not supported by newlib nano used in Mbed OS and FreeRTOS,
00228 // so these tests need to be left out.
00229 // Note: __GNUC__ is also defined by ARMCC in "--gnu" mode, so it can not be used directly.
00230 #if (!(defined(TARGET_LIKE_MBED) && defined(TOOLCHAIN_GCC)) && !(defined(__FREERTOS__) && !defined(__CC_ARM)))
00231     char output[64];
00232 
00233     int result;
00234 
00235     size_t testU;
00236 
00237     // Note: if the environment has 64b size_t, the code should have bigger
00238     // constant in use
00239 
00240     testU = 123456789;
00241 
00242     // Note: the newlib nano fails on these:
00243 
00244     /*#1*/
00245     result = snprintf(output, sizeof(output), "size_t 1: %zu", testU);
00246     TEST_ASSERT_EQUAL(strlen(TEST_OUTPUT_SIZE_1), result);
00247     TEST_ASSERT_EQUAL_STRING(TEST_OUTPUT_SIZE_1, output);
00248 
00249     // Note: the ssize_t is not that universally available or used as size_t so
00250     // this test is in comments.
00251     /*#2*/
00252 #if 0
00253     ssize_t testS;
00254     testS = 0 - 123456789;
00255 
00256     result = snprintf(output, sizeof(output), "size_t 2: %zd", testS);
00257     TEST_ASSERT_EQUAL(strlen(TEST_OUTPUT_SIZE_2), result);
00258     TEST_ASSERT_EQUAL_STRING(TEST_OUTPUT_SIZE_2, output);
00259 #endif
00260 #else
00261     TEST_IGNORE_MESSAGE("Ignored, zu and zd not supported");
00262 #endif
00263 }
00264 
00265 /*! \brief Sanity check of the kernel system tick API.
00266  * Fails if system tic value is zero (**note:** this can sometimes happen on wrap-around).
00267  *
00268  * | # |    Step                        |   Expected  |
00269  * |---|--------------------------------|-------------|
00270  * | 1 | Get current tick count using `pal_osKernelSysTick` and check that it is not 0.  | PAL_SUCCESS |
00271  */
00272 TEST(pal_rtos, pal_osKernelSysTick_Unity)
00273 {
00274     uint32_t tick1 = 0, tick2 = 0;
00275     /*#1*/
00276     tick1 = pal_osKernelSysTick();
00277     PAL_PRINTF("%" PRIu32 " %" PRIu32 "\n", tick1, tick2);
00278 
00279     TEST_ASSERT_TRUE(tick2 != tick1);
00280 }
00281 
00282 /*! \brief Sanity check of the kernel system tick API.
00283  * Fails if two calls return the same `sysTick` value.
00284  *
00285  * | # |    Step                        |   Expected  |
00286  * |---|--------------------------------|-------------|
00287  * | 1 | Get current tick count using `pal_osKernelSysTick`.       | PAL_SUCCESS |
00288  * | 2 | Get current tick count using `pal_osKernelSysTick`.       | PAL_SUCCESS |
00289  * | 3 | Check that the two tick count values are not the same. | PAL_SUCCESS |
00290  */
00291 TEST(pal_rtos, pal_osKernelSysTick64_Unity)
00292 {
00293     uint64_t tick1 = 0, tick2 = 0;
00294     /*#1*/
00295     tick1 = pal_osKernelSysTick();
00296     /*#2*/
00297     tick2 = pal_osKernelSysTick();
00298     /*#3*/
00299     TEST_ASSERT_TRUE(tick2 >= tick1);
00300 }
00301 
00302 /*! \brief Check the conversion from a non-zero `sysTick` value to microseconds.
00303  * Verify that the result is not 0.
00304  *
00305  * | # |    Step                        |   Expected  |
00306  * |---|--------------------------------|-------------|
00307  * | 1 | Convert a nubmer in `sysTicks` to microseconds using `pal_osKernelSysTickMicroSec` and check it is not 0. | PAL_SUCCESS |
00308  */
00309 TEST(pal_rtos, pal_osKernelSysTickMicroSec_Unity)
00310 {
00311     uint64_t tick = 0;
00312     uint64_t microSec = 2000 * 1000;
00313     /*#1*/
00314     tick = pal_osKernelSysTickMicroSec(microSec);
00315     TEST_ASSERT_TRUE(0 != tick);
00316 }
00317 
00318 /*! \brief Sanity check of non-zero values conversion between microseconds to ticks to milliseconds.
00319  * Verify that the result is correct when converting the input (microseconds) to the test output (milliseconds).
00320  *
00321  * | # |    Step                        |   Expected  |
00322  * |---|--------------------------------|-------------|
00323  * | 1 | Convert a nubmer in `sysTicks` to mircorseconds using `pal_osKernelSysTickMicroSec` and check it is not 0. | PAL_SUCCESS |
00324  * | 2 | Convert a nubmer in `sysTicks` to milliseconds using `pal_osKernelSysMilliSecTick` and check the returned value. | PAL_SUCCESS |
00325  */
00326 TEST(pal_rtos, pal_osKernelSysMilliSecTick_Unity)
00327 {
00328     uint64_t tick = 0;
00329     uint64_t microSec = 200 * 1000;
00330     uint64_t milliseconds = 0;
00331     /*#1*/
00332     tick = pal_osKernelSysTickMicroSec(microSec);
00333     TEST_ASSERT_TRUE(0 != tick);
00334     /*#2*/
00335     milliseconds = pal_osKernelSysMilliSecTick(tick);
00336 
00337     // Calculation in PAL might be done using integer values and therefore
00338     // the result can be off by 1 millisecond due to rounding
00339     TEST_ASSERT_INT_WITHIN(1, microSec/1000, milliseconds);
00340 }
00341 
00342 /*! \brief Verify that the tick frequency function returns a non-zero value.
00343  *
00344  * | # |    Step                        |   Expected  |
00345  * |---|--------------------------------|-------------|
00346  * | 1 | Get the kernel `sysTick` frequency and check that it is positive.     | PAL_SUCCESS |
00347  */
00348 TEST(pal_rtos, pal_osKernelSysTickFrequency_Unity)
00349 {
00350     uint64_t frequency = 0;
00351     /*#1*/
00352     frequency = pal_osKernelSysTickFrequency();
00353 
00354     TEST_ASSERT_TRUE(frequency > 0);
00355 }
00356 
00357 /*! \brief Sanity check for the Delay API, verifying that `sysTick` increments after delay.
00358  * The test reads two system tick values. Between the two calls, it calls the delay function and
00359  * verifies that the tick values are different.
00360  *
00361  * | # |    Step                        |   Expected  |
00362  * |---|--------------------------------|-------------|
00363  * | 1 | Get the kernel `sysTick` value.                           | PAL_SUCCESS |
00364  * | 2 | Sleep for a short period .                              | PAL_SUCCESS |
00365  * | 3 | Get the kernel `sysTick` value.                          | PAL_SUCCESS |
00366  * | 4 | Check that second tick value is greater than the first. | PAL_SUCCESS |
00367  */
00368 TEST(pal_rtos, pal_osDelay_Unity)
00369 {
00370     palStatus_t status = PAL_SUCCESS;
00371     uint32_t tick1 , tick2;
00372     /*#1*/
00373     tick1 = pal_osKernelSysTick();
00374     /*#2*/
00375     status = pal_osDelay(200);
00376     /*#3*/
00377     tick2 = pal_osKernelSysTick();
00378     /*#4*/
00379     TEST_ASSERT_TRUE(tick2 > tick1);
00380     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00381 }
00382 
00383 /*! \brief Test for basic timing scenarios based on calls for the ticks and delay
00384 * functionality while verifying that results meet the defined deltas.
00385 *
00386 * | # |    Step                        |   Expected  |
00387 * |---|--------------------------------|-------------|
00388 * | 1 | Get the kernel `sysTick` value.                                      | PAL_SUCCESS |
00389 * | 2 | Sleep for a very short period.                                     | PAL_SUCCESS |
00390 * | 3 | Get the kernel `sysTick` value.                                      | PAL_SUCCESS |
00391 * | 4 | Check that second tick value is greater than the first.            | PAL_SUCCESS |
00392 * | 5 | Get the kernel `sysTick` value.                                      | PAL_SUCCESS |
00393 * | 6 | Sleep for a longer period.                                         | PAL_SUCCESS |
00394 * | 7 | Get the kernel `sysTick` value.                                      | PAL_SUCCESS |
00395 * | 8 | Check that second tick value is greated than the first.           | PAL_SUCCESS |
00396 * | 9 | Calculate the difference between the ticks.                                | PAL_SUCCESS |
00397 * | 10 | Convert last sleep period to ticks.                              | PAL_SUCCESS |
00398 * | 11 | Check that the tick period is correct (same as sleep period +/-delta). | PAL_SUCCESS |
00399 */
00400 TEST(pal_rtos, BasicTimeScenario)
00401 {
00402     palStatus_t status = PAL_SUCCESS;
00403     uint64_t tick, tick1 , tick2 , tickDiff, tickDelta;
00404 
00405     /*#1*/
00406     tick1 = pal_osKernelSysTick();
00407     /*#2*/
00408     status = pal_osDelay(1);
00409     /*#3*/
00410     tick2 = pal_osKernelSysTick();
00411 
00412     /*#4*/
00413     TEST_ASSERT_TRUE(tick1 != tick2);
00414     TEST_ASSERT_TRUE(tick2 > tick1);  // To check that the tick counts are incremental - be aware of wrap-arounds
00415     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00416     /****************************************/
00417     /*#5*/
00418     tick1 = pal_osKernelSysTick();
00419     /*#6*/
00420     status = pal_osDelay(2000);
00421     /*#7*/
00422     tick2 = pal_osKernelSysTick();
00423 
00424     /*#8*/
00425     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00426     TEST_ASSERT_TRUE(tick1 != tick2);
00427     TEST_ASSERT_TRUE(tick2 > tick1);
00428 
00429     /*#9*/
00430     tickDiff = tick2 - tick1;
00431     /*#10*/
00432     tick = pal_osKernelSysTickMicroSec(2000 * 1000);
00433     // 10 milliseconds delta
00434     /*#11*/
00435     tickDelta = pal_osKernelSysTickMicroSec(10 * 1000);
00436     TEST_ASSERT_TRUE((tick - tickDelta < tickDiff) && (tickDiff < tick + tickDelta));
00437     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00438 }
00439 
00440 
00441 /*! \brief Test for basic long timing scenarios based on calls for the ticks and delay
00442 * functionality while verifying that results meet the defined deltas. In practice this
00443 * may be one of the first tests to run to get some baseline for timer accuracy measurements.
00444 *
00445 * | # |    Step                                                                 |   Expected  |
00446 * |---|-------------------------------------------------------------------------|-------------|
00447 * | 1 | Get the kernel `sysTick` value.                                         | PAL_SUCCESS |
00448 * | 2 | Get the kernel `millisecond` value.                                     | PAL_SUCCESS |
00449 * | 3 | start loop
00450 * | 4 | Get the kernel `sysTick` value.                                         | PAL_SUCCESS |
00451 * | 5 | Get the kernel `millisecond` value.                                     | PAL_SUCCESS |
00452 * | 6 | Delay for one second.                                                   | PAL_SUCCESS |
00453 * | 7 | Get the kernel `sysTick` value.                                         | PAL_SUCCESS |
00454 * | 8 | Get the kernel `millisecond` value.                                     | PAL_SUCCESS |
00455 * | 9 | Verify that `sysTick` diff for one second value is within error margin. | PAL_SUCCESS |
00456 * |10 | Verify that `ms` diff for one second value is within error margin.      | PAL_SUCCESS |
00457 * |11 | Continue loop
00458 * |12 | Get the kernel `sysTick` value.                                         | PAL_SUCCESS |
00459 * |13 | Get the kernel `millisecond` value.                                     | PAL_SUCCESS |
00460 * |14 | Verify that `sysTick` diff for loop duration is within error margin.    | PAL_SUCCESS |
00461 * |15 | Verify that `ms` diff for loop duration is within error margin.         | PAL_SUCCESS |
00462 */
00463 TEST(pal_rtos, BasicDelayTime)
00464 {
00465     palStatus_t status = PAL_SUCCESS;
00466 
00467     uint64_t tickTestStart;
00468     uint64_t tickTestEnd;
00469     uint64_t msTestStart;
00470     uint64_t msTestEnd;
00471 
00472     uint64_t tickInLoopStart;
00473     uint64_t tickInLoopEnd;
00474 
00475     uint64_t msInLoopStart;
00476     uint64_t msInLoopEnd;
00477 
00478     uint64_t tickDiff;
00479     uint64_t msDiff;
00480 
00481     const uint64_t ticksPerSecond = pal_osKernelSysTickFrequency();
00482 
00483     // Delay time can legally drift one 16th of a fraction (~6,25%) into one direction or another
00484     const uint64_t tickLoopDiffAllowed = ticksPerSecond / 32;
00485     const uint64_t msLoopDiffAllowed = 1000 / 32;
00486 
00487     const uint64_t tickTestDiffAllowed = (ticksPerSecond * PAL_DELAY_RUN_LOOPS) / 16;
00488     const uint64_t msTestDiffAllowed = (1000 * PAL_DELAY_RUN_LOOPS) / 16;
00489 
00490     /*#1*/
00491     tickTestStart = pal_osKernelSysTick();
00492 
00493     /*#2*/
00494     msTestStart = pal_osKernelSysMilliSecTick(tickTestStart);
00495 
00496     /*#3*/
00497 
00498     // Loop N times, one second per loop. Verify, that the timer values
00499     // are somewhere in the correct ballpark and the more complex timer
00500     // checks have hope to pass. Note: the times are evaluated in ticks
00501     // and also converted to milliseconds to help in debugging (and to
00502     // verify that the conversion actually works).
00503     for (int i=1; i <= PAL_DELAY_RUN_LOOPS; i++) {
00504 
00505         /*#4*/
00506         tickInLoopStart = pal_osKernelSysTick();
00507 
00508         /*#5*/
00509         msInLoopStart = pal_osKernelSysMilliSecTick(tickInLoopStart);
00510 
00511         /*#6*/
00512         status = pal_osDelay(1000);
00513 
00514         TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00515 
00516         /*#7*/
00517         tickInLoopEnd = pal_osKernelSysTick();
00518 
00519         /*#8*/
00520         msInLoopEnd = pal_osKernelSysMilliSecTick(tickInLoopEnd);
00521 
00522         tickDiff = tickInLoopEnd - tickInLoopStart;
00523         msDiff = msInLoopEnd - msInLoopStart;
00524 
00525         // XXX: This code is in comments to help in debugging the case when this
00526         // test fails on new platform
00527         /*
00528         tr_info("tickDiff       : %llu", tickDiff);
00529         tr_info("msDiff         : %llu", msDiff);
00530 
00531         tr_info("tickInLoopStart: %llu", tickInLoopStart);
00532         tr_info("tickInLoopEnd  : %llu", tickInLoopEnd);
00533 
00534         tr_info("msInLoopStart  : %llu", msInLoopStart);
00535         tr_info("msInLoopEnd    : %llu", msInLoopEnd);
00536         */
00537 
00538         /*#9*/
00539         TEST_ASSERT_UINT64_WITHIN(tickLoopDiffAllowed, ticksPerSecond, tickDiff);
00540 
00541         /*#10*/
00542         TEST_ASSERT_UINT64_WITHIN(msLoopDiffAllowed, 1000, msDiff);
00543 
00544         /*#11*/
00545     }
00546 
00547     /*#12*/
00548     tickTestEnd = pal_osKernelSysTick();
00549 
00550     /*#13*/
00551     msTestEnd = pal_osKernelSysMilliSecTick(tickTestEnd);
00552 
00553     tickDiff = tickTestEnd - tickTestStart;
00554     msDiff = msTestEnd - msTestStart;
00555 
00556     /*
00557     tr_info("tickTestStart  : %llu", tickTestStart);
00558     tr_info("msTestStart    : %llu", msTestStart);
00559     tr_info("tickTestEnd    : %llu", tickTestEnd);
00560     tr_info("msTestEnd      : %llu", msTestEnd);
00561     */
00562 
00563     /*#14*/
00564     TEST_ASSERT_UINT64_WITHIN(tickTestDiffAllowed, (ticksPerSecond*PAL_DELAY_RUN_LOOPS), tickDiff);
00565 
00566     /*#15*/
00567     TEST_ASSERT_UINT64_WITHIN(msTestDiffAllowed, (1000*PAL_DELAY_RUN_LOOPS), msDiff);
00568 }
00569 
00570 /*! \brief Test single-shot timer accuracy against system clock.
00571  *
00572 * | # |    Step                                                                                          |   Expected                     |
00573 * |---|--------------------------------------------------------------------------------------------------|--------------------------------|
00574 * | 1 | Create a one-shot timer, which calls `palTimerFunc1` when triggered, using `pal_osTimerCreate`.  | PAL_SUCCESS                    |
00575 * | 2 | Get the kernel `sysTick` value.                                                                  | PAL_SUCCESS                    |
00576 * | 3 | Start the timer using `pal_osTimerStart`.                                                        | PAL_SUCCESS                    |
00577 * | 4 | Sleep for a period.                                                                              | PAL_SUCCESS                    |
00578 * | 5 | Check that timer is in 10% limits.                                                               | PAL_SUCCESS                    |
00579 * | 6 | Delete the timer.                                                                                | PAL_SUCCESS                    |
00580 */
00581 TEST(pal_rtos, OneShotTimerAccuracyUnityTest)
00582 {
00583     palStatus_t status = PAL_SUCCESS;
00584     palTimerID_t timerID1 = NULLPTR;
00585 
00586     g_timerArgs.ticksInFunc1 = 0;
00587     g_timerArgs.ticksBeforeTimer = 0;
00588 
00589     /*#1*/
00590     status = pal_osTimerCreate(palTimerFunc1, NULL, palOsTimerOnce , &timerID1);
00591     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00592     /*#2*/
00593     g_timerArgs.ticksBeforeTimer = pal_osKernelSysTick();
00594     /*#3*/
00595     status = pal_osTimerStart(timerID1, PAL_TEST_TIME_SECOND);
00596     PAL_PRINTF("ticks before Timer: 0 - %" PRIu32 "\n", g_timerArgs.ticksBeforeTimer);
00597     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00598     /*#4*/
00599     status = pal_osDelay(1500);
00600     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00601     /*#5*/
00602     // check that timer is in 90..110% accuracy.
00603     TEST_ASSERT_UINT32_WITHIN((PAL_TEST_TIME_SECOND/PAL_TEST_PERCENTAGE_HUNDRED) * PAL_TEST_PERCENTAGE_TIMER_ERROR, PAL_TEST_TIME_SECOND, (pal_osKernelSysMilliSecTick(g_timerArgs.ticksInFunc1) - pal_osKernelSysMilliSecTick(g_timerArgs.ticksBeforeTimer)));
00604     /*#6*/
00605     status = pal_osTimerDelete(&timerID1);
00606     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00607     TEST_ASSERT_EQUAL(NULLPTR, timerID1);
00608 }
00609 
00610 /*! \brief Test periodic timer accuracy against system clock.
00611  *
00612 * | # |    Step                                                                                          |   Expected                     |
00613 * |---|--------------------------------------------------------------------------------------------------|--------------------------------|
00614 * | 1 | Create a periodic timer, which calls `palTimerFunc7` when triggered, using `pal_osTimerCreate`.  | PAL_SUCCESS                    |
00615 * | 2 | Get the kernel `sysTick` value.                                                                  | PAL_SUCCESS                    |
00616 * | 3 | Start the timer using `pal_osTimerStart`.                                                        | PAL_SUCCESS                    |
00617 * | 4 | Sleep for a period.                                                                              | PAL_SUCCESS                    |
00618 * | 5 | Check callback counter and that timer is in 10% limits.                                           | PAL_SUCCESS                    |
00619 * | 6 | Delete the timer .                                                                               | PAL_SUCCESS                    |
00620 */
00621 
00622 TEST(pal_rtos, PeriodicTimerAccuracyUnityTest)
00623 {
00624     palStatus_t status = PAL_SUCCESS;
00625     palTimerID_t timerID1 = NULLPTR;
00626 
00627     g_timerArgs.ticksInFunc1 = 0;
00628     g_timerArgs.ticksInFunc2 = 0;
00629     g_timerArgs.ticksBeforeTimer = 0;
00630 
00631     /*#1*/
00632     status = pal_osTimerCreate(palTimerFunc7, &timerID1, palOsTimerPeriodic , &timerID1);
00633     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00634     /*#2*/
00635     g_timerArgs.ticksBeforeTimer = pal_osKernelSysTick();
00636     /*#3*/
00637     status = pal_osTimerStart(timerID1, 100);
00638     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00639     /*#4*/
00640     status = pal_osDelay(1500);
00641     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00642     /*#5*/
00643     TEST_ASSERT_EQUAL_INT(10, g_timerArgs.ticksInFunc1);
00644     TEST_ASSERT_UINT32_WITHIN(((PAL_TEST_TIME_SECOND/PAL_TEST_PERCENTAGE_HUNDRED) * PAL_TEST_PERCENTAGE_TIMER_ERROR), PAL_TEST_TIME_SECOND, (pal_osKernelSysMilliSecTick(g_timerArgs.ticksInFunc2) - pal_osKernelSysMilliSecTick(g_timerArgs.ticksBeforeTimer)));
00645     /*#6*/
00646     status = pal_osTimerDelete(&timerID1);
00647     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00648     TEST_ASSERT_EQUAL(NULLPTR, timerID1);
00649 }
00650 
00651 /*! \brief Test that single-shot and periodic timer works when stopped from callback.
00652  *
00653 * | # |    Step                                                                                          |   Expected                     |
00654 * |---|--------------------------------------------------------------------------------------------------|--------------------------------|
00655 * | 1 | Create a one-shot timer, which calls `palTimerFunc6` when triggered, using `pal_osTimerCreate`.  | PAL_SUCCESS                    |
00656 * | 2 | Start the timer using `pal_osTimerStart`.                                                        | PAL_SUCCESS                    |
00657 * | 3 | Sleep for a period.                                                                              | PAL_SUCCESS                    |
00658 * | 4 | Check that timer is in fired only one time.                                                      | PAL_SUCCESS                    |
00659 * | 5 | Delete the timer.                                                                                | PAL_SUCCESS                    |
00660 */
00661 TEST(pal_rtos, OneShotTimerStopUnityTest)
00662 {
00663     palStatus_t status = PAL_SUCCESS;
00664     palTimerID_t timerID1 = NULLPTR;
00665 
00666     g_timerArgs.ticksBeforeTimer = 0;
00667     g_timerArgs.ticksInFunc1 = 0;
00668 
00669     /*#1*/
00670     status = pal_osTimerCreate(palTimerFunc6, &timerID1, palOsTimerOnce , &timerID1);
00671     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00672     /*#2*/
00673     status = pal_osTimerStart(timerID1, 500);
00674     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00675     /*#3*/
00676     status = pal_osDelay(1500);
00677     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00678     /*#4*/
00679     TEST_ASSERT_EQUAL_INT(1, g_timerArgs.ticksInFunc1);
00680     /*#5*/
00681     status = pal_osTimerDelete(&timerID1);
00682     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00683     TEST_ASSERT_EQUAL(NULLPTR, timerID1);
00684 
00685 }
00686 
00687 /*! \brief Test that single-shot and periodic timer works when stopped from callback.
00688  *
00689 * | # |    Step                                                                                          |   Expected                     |
00690 * |---|--------------------------------------------------------------------------------------------------|--------------------------------|
00691 * | 1 | Create a periodic timer, which calls `palTimerFunc6` when triggered, using `pal_osTimerCreate`.  | PAL_SUCCESS                    |
00692 * | 2 | Start the timer using `pal_osTimerStart`.                                                        | PAL_SUCCESS                    |
00693 * | 3 | Sleep for a period.                                                                              | PAL_SUCCESS                    |
00694 * | 4 | Check that timer is in fired only one time.                                                      | PAL_SUCCESS                    |
00695 * | 5 | Delete the timer.                                                                                | PAL_SUCCESS                    |
00696 */
00697 TEST(pal_rtos, PeriodicTimerStopUnityTest)
00698 {
00699     palStatus_t status = PAL_SUCCESS;
00700     palTimerID_t timerID1 = NULLPTR;
00701 
00702     g_timerArgs.ticksInFunc1 = 0;
00703 
00704     /*#1*/
00705     status = pal_osTimerCreate(palTimerFunc6, &timerID1, palOsTimerPeriodic , &timerID1);
00706     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00707     /*#2*/
00708     status = pal_osTimerStart(timerID1, 500);
00709     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00710     /*#3*/
00711     status = pal_osDelay(1500);
00712     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00713     /*#4*/
00714     TEST_ASSERT_EQUAL_INT(1, g_timerArgs.ticksInFunc1);
00715     /*#5*/
00716     status = pal_osTimerDelete(&timerID1);
00717     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00718     TEST_ASSERT_EQUAL(NULLPTR, timerID1);
00719 }
00720 /*! \brief Create two timers: periodic and one-shot. Starts both timers,
00721 * then causes a delay to allow output from the timer functions to be printed on the console.
00722 *
00723 * | # |    Step                                                                                          |   Expected                     |
00724 * |---|--------------------------------------------------------------------------------------------------|--------------------------------|
00725 * | 1 | Create a one-shot timer, which calls `palTimerFunc1` when triggered, using `pal_osTimerCreate`.  | PAL_SUCCESS                    |
00726 * | 2 | Create a periodic timer, which calls `palTimerFunc2` when triggered, using `pal_osTimerCreate`.  | PAL_SUCCESS                    |
00727 * | 3 | Get the kernel `sysTick` value.                                                                  | PAL_SUCCESS                    |
00728 * | 4 | Start the first timer using `pal_osTimerStart`.                                                  | PAL_SUCCESS                    |
00729 * | 5 | Get the kernel `sysTick` value.                                                                  | PAL_SUCCESS                    |
00730 * | 6 | Start the first timer using `pal_osTimerStart`.                                                  | PAL_SUCCESS                    |
00731 * | 7 | Sleep for a period.                                                                              | PAL_SUCCESS                    |
00732 * | 8 | Stop the second timer using `pal_osTimerStop`.                                                   | PAL_SUCCESS                    |
00733 * | 9 | Delete the first timer using `pal_osTimerDelete`.                                                | PAL_SUCCESS                    |
00734 * | 10 | Delete the second timer using `pal_osTimerDelete`.                                              | PAL_SUCCESS                    |
00735 */
00736 
00737 TEST(pal_rtos, TimerStartUnityTest)
00738 {
00739     uint32_t expectedTicks;
00740     uint32_t ticksInFuncError;
00741 
00742     palStatus_t status = PAL_SUCCESS;
00743     palTimerID_t timerID1 = NULLPTR;
00744     palTimerID_t timerID2 = NULLPTR;
00745 
00746     g_timerArgs.ticksBeforeTimer = 0;
00747     g_timerArgs.ticksInFunc1 = 0;
00748     g_timerArgs.ticksInFunc2 = 0;
00749 
00750     /*#1*/
00751     status = pal_osTimerCreate(palTimerFunc1, NULL, palOsTimerOnce , &timerID1);
00752     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00753     /*#2*/
00754     status = pal_osTimerCreate(palTimerFunc2, NULL, palOsTimerPeriodic , &timerID2);
00755     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00756     /*#3*/
00757     g_timerArgs.ticksBeforeTimer = pal_osKernelSysTick();
00758     /*#4*/
00759     status = pal_osTimerStart(timerID1, 1000);
00760     PAL_PRINTF("ticks before Timer: 0 - %" PRIu32 "\n", g_timerArgs.ticksBeforeTimer);
00761     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00762     /*#5*/
00763     g_timerArgs.ticksBeforeTimer = pal_osKernelSysTick();
00764     /*#6*/
00765     status = pal_osTimerStart(timerID2, 1000);
00766     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00767     /*#7*/
00768     status = pal_osDelay(1500);
00769     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00770     /*#8*/
00771     status = pal_osTimerStop(timerID2);
00772     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00773     /*#9*/
00774     status = pal_osTimerDelete(&timerID1);
00775     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00776     TEST_ASSERT_EQUAL(NULLPTR, timerID1);
00777     /*#10*/
00778     status = pal_osTimerDelete(&timerID2);
00779     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00780     TEST_ASSERT_EQUAL(NULLPTR, timerID2);
00781 }
00782 
00783 /*! \brief Test high-resolution timers
00784  *
00785 * | 1 | Create a periodic timer, which calls `palTimerFunc3` when triggered, using `pal_osTimerCreate`. | PAL_SUCCESS                    |
00786 * | 2 | Create a periodic timer, which calls `palTimerFunc4` when triggered, using `pal_osTimerCreate`. | PAL_ERR_NO_HIGH_RES_TIMER_LEFT |
00787 * | 3 | Start the first timer using `pal_osTimerStart` as high res timer.                               | PAL_SUCCESS                    |
00788 * | 4 | Start the second timer using `pal_osTimerStart` as high res timer.                              | PAL_ERR_NO_HIGH_RES_TIMER_LEFT |
00789 * | 5 | Sleep for a period.                                                                             | PAL_SUCCESS                    |
00790 * | 6 | Stop the second timer using `pal_osTimerStop`.                                                  | PAL_SUCCESS                    |
00791 * | 7 | Start the second timer using `pal_osTimerStart` as high res timer                               | PAL_SUCCESS                    |
00792 * | 8 | Sleep for a period.                                                                             | PAL_SUCCESS                    |
00793 * | 9 | Delete the first timer using `pal_osTimerDelete`.                                               | PAL_SUCCESS                    |
00794 * | 10 | Delete the second timer using `pal_osTimerDelete`.                                             | PAL_SUCCESS                    |
00795 */
00796 TEST(pal_rtos, HighResTimerUnityTest)
00797 {
00798     palStatus_t status = PAL_SUCCESS;
00799     palTimerID_t timerID1 = NULLPTR;
00800     palTimerID_t timerID2 = NULLPTR;
00801     uint32_t expectedTicks;
00802     uint32_t ticksInFuncError;
00803 
00804     g_timerArgs.ticksBeforeTimer = 0;
00805     g_timerArgs.ticksInFunc1 = 0;
00806     g_timerArgs.ticksInFunc2 = 0;
00807     
00808     /*#1*/
00809     status = pal_osTimerCreate(palTimerFunc3, NULL, palOsTimerPeriodic , &timerID1);
00810     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00811     
00812     /*#2*/
00813     status = pal_osTimerCreate(palTimerFunc4, NULL, palOsTimerPeriodic , &timerID2);
00814     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00815 
00816     /*#3*/
00817     status = pal_osTimerStart(timerID1, PAL_TEST_HIGH_RES_TIMER);
00818     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00819 
00820     /*#4*/
00821     status = pal_osTimerStart(timerID2, PAL_TEST_HIGH_RES_TIMER);
00822     if (PAL_SUCCESS == status) // behavior is slightly different for Linux due to high res timer limitation there (only one at a time supported there)
00823     {
00824         status = pal_osTimerStop(timerID2);
00825         TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00826     }
00827     else  
00828     {
00829         TEST_ASSERT_EQUAL_HEX(PAL_ERR_NO_HIGH_RES_TIMER_LEFT , status);
00830     }
00831     /*#5*/
00832     status = pal_osDelay(500);
00833     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00834 
00835     /*#6*/
00836     status = pal_osTimerStop(timerID1);
00837     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00838 
00839     /*#7*/
00840     status = pal_osTimerStart(timerID2, PAL_TEST_HIGH_RES_TIMER2);
00841     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00842 
00843     /*#8*/
00844     status = pal_osDelay(PAL_TIME_TO_WAIT_SHORT_MS);
00845     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00846 
00847     status = pal_osTimerStop(timerID2);
00848     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00849 
00850     // check there is at 90..110% of expected timer callbacks.
00851     expectedTicks = (uint32_t)((float)PAL_TIME_TO_WAIT_SHORT_MS / (float)PAL_TEST_HIGH_RES_TIMER2);
00852     ticksInFuncError = (uint32_t)(((float)PAL_TIME_TO_WAIT_SHORT_MS / (float)PAL_TEST_HIGH_RES_TIMER2) * (float)PAL_TEST_PERCENTAGE_TIMER_ERROR);
00853     TEST_ASSERT_UINT32_WITHIN(ticksInFuncError, expectedTicks, g_timerArgs.ticksInFunc1);
00854 
00855     /*#9*/
00856     status = pal_osTimerDelete(&timerID1);
00857     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00858     TEST_ASSERT_EQUAL(NULLPTR, timerID1);
00859     
00860     /*#10*/
00861     status = pal_osTimerDelete(&timerID2);
00862     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00863     TEST_ASSERT_EQUAL(NULLPTR, timerID2);
00864 }
00865 
00866 /*! /brief Test periodic timer with sleep inside the callback
00867  *
00868 * | 1 | Create a periodic timer, which calls `palTimerFunc5` when triggered, using `pal_osTimerCreate`. | PAL_SUCCESS                    |
00869 * | 2 | Sleep for a period.                                                                             | PAL_SUCCESS                    |
00870 * | 3 | Delete the first timer using `pal_osTimerDelete`.                                               | PAL_SUCCESS                    |
00871 * | 4 | Stop the timer using `pal_osTimerStop`.  and check the number of callbacks is correct           | PAL_SUCCESS                    |
00872 * | 5 | Delete the timer using `pal_osTimerDelete`.                                                     | PAL_SUCCESS                    |
00873 * | 6 | Start the timer with zero millisec.                                                             | PAL_ERR_RTOS_VALUE             |
00874 * | 7 | Delete the timer using `pal_osTimerDelete`.                                                     | PAL_SUCCESS                    |
00875 */
00876 TEST(pal_rtos, TimerSleepUnityTest)
00877 {
00878     palStatus_t status = PAL_SUCCESS;
00879     palTimerID_t timerID1 = NULLPTR;
00880     uint32_t expectedTicks;
00881     uint32_t ticksInFuncError;
00882     
00883     /*#1*/
00884     g_timerArgs.ticksBeforeTimer = 0;
00885     g_timerArgs.ticksInFunc1 = 0;
00886     g_timerArgs.ticksInFunc2 = 0;
00887 
00888     status = pal_osTimerCreate(palTimerFunc5, NULL, palOsTimerPeriodic , &timerID1);
00889     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00890 
00891     /*#2*/
00892     status = pal_osTimerStart(timerID1, PAL_TEST_HIGH_RES_TIMER);
00893     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00894     
00895     /*#3*/
00896     status = pal_osDelay(PAL_TIME_TO_WAIT_MS);
00897     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00898 
00899     /*#4*/
00900     status = pal_osTimerStop(timerID1);
00901     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00902 
00903     // The code expects currently timer to have +-10% accuracy, or actually a 90% of success
00904     // rate in getting CPU time. The previous +-5% did fail at random on Linux for perfectly
00905     // valid reasons, as the timer is ran in a thread and on a multi user, non-rtos OS the
00906     // CPU time is given at best effort basis. There is no need to ask for realtime thread
00907     // priority just to serve PAL tests, as nothing else in related codebase actually expects to have
00908     // semi hard realtime guarantees from a timer.
00909     expectedTicks = (uint32_t)((float)PAL_TIME_TO_WAIT_MS / (float)PAL_TEST_HIGH_RES_TIMER);
00910     ticksInFuncError = (uint32_t)(((float)PAL_TIME_TO_WAIT_MS / (float)PAL_TEST_HIGH_RES_TIMER) * (float)PAL_TEST_PERCENTAGE_TIMER_ERROR);
00911     TEST_ASSERT_UINT32_WITHIN(ticksInFuncError, expectedTicks, g_timerArgs.ticksInFunc1);
00912 
00913     /*#5*/
00914     status = pal_osTimerDelete(&timerID1);
00915     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00916     TEST_ASSERT_EQUAL(NULLPTR, timerID1);
00917 
00918 }
00919 
00920 /*! /brief Test timer API with non-valid parameters
00921  *
00922 * | 1 | Start the timer with zero millisec.                                                             | PAL_ERR_RTOS_VALUE             |
00923 * | 2 | Delete the timer using `pal_osTimerDelete`.                                                     | PAL_SUCCESS                    |
00924 */
00925 TEST(pal_rtos, TimerNegativeUnityTest)
00926 {
00927     palStatus_t status = PAL_SUCCESS;
00928     palTimerID_t timerID1 = NULLPTR;
00929 
00930     g_timerArgs.ticksBeforeTimer = 0;
00931     g_timerArgs.ticksInFunc1 = 0;
00932     g_timerArgs.ticksInFunc2 = 0;
00933 
00934     /*#1*/
00935     status = pal_osTimerCreate(palTimerFunc5, NULL, palOsTimerPeriodic , &timerID1);
00936     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00937     status = pal_osTimerStart(timerID1, 0);
00938     TEST_ASSERT_EQUAL_HEX(PAL_ERR_RTOS_VALUE , status);
00939 
00940     /*#2*/
00941     status = pal_osTimerDelete(&timerID1);
00942     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00943 }
00944 
00945 /*! \brief Creates mutexes and semaphores and uses them to communicate between
00946 * the different threads it creates (as defined in `pal_rtos_test_utils.c`).
00947 * In this test, we check that thread communication is working as expected between the threads and in the designed order.
00948 * In one case, we expect the thread to fail to lock a mutex – (thread1).
00949 * Threads are created with different priorities (PAL enforces this attribute).
00950 * For each case, the thread function prints the expected result. The test code verifies this result as well.
00951 *
00952 * | # |    Step                        |   Expected  |
00953 * |---|--------------------------------|-------------|
00954 * | 1 | Create a mutex using `pal_osMutexCreate`.                           | PAL_SUCCESS |
00955 * | 2 | Create a mutex using `pal_osMutexCreate`.                           | PAL_SUCCESS |
00956 * | 3 | Create a semaphore with count 1.                                  | PAL_SUCCESS |
00957 * | 4 | Run the PAL test threads using the `palRunThreads` test function.  | PAL_SUCCESS |
00958 * | 5 | Delete the semaphore using `pal_osSemaphoreDelete`.                     | PAL_SUCCESS |
00959 * | 6 | Delete the first mutex using `pal_osMutexDelete`.                       | PAL_SUCCESS |
00960 * | 7 | Delete the second mutex using `pal_osMutexDelete`.                       | PAL_SUCCESS |
00961 */
00962 TEST(pal_rtos, PrimitivesUnityTest1)
00963 {
00964     palStatus_t status = PAL_SUCCESS;
00965     /*#1*/
00966     status = pal_osMutexCreate(&mutex1);
00967     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00968     /*#2*/
00969     status = pal_osMutexCreate(&mutex2);
00970     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00971     /*#3*/
00972     status = pal_osSemaphoreCreate(1 ,&semaphore1);
00973     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00974     /*#4*/
00975     palRunThreads();
00976     /*#5*/
00977     status = pal_osSemaphoreDelete(&semaphore1);
00978     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00979     TEST_ASSERT_EQUAL(NULLPTR, semaphore1);
00980     /*#6*/
00981     status = pal_osMutexDelete(&mutex1);
00982     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00983     TEST_ASSERT_EQUAL(NULLPTR, mutex1);
00984     /*#7*/
00985     status = pal_osMutexDelete(&mutex2);
00986     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00987     TEST_ASSERT_EQUAL(NULLPTR, mutex2);
00988 
00989 }
00990 
00991 /*! \brief Verifies that several RTOS primitives APIs can handle invalid
00992 * arguments. The test calls each API with invalid arguments and verifies the result.
00993 * It also verifies that the semaphore wait API can accept NULL as the third parameter.
00994 *
00995 * | # |    Step                                                                      |   Expected               |
00996 * |---|------------------------------------------------------------------------------|--------------------------|
00997 * | 1 | Test thread creation with invalid arguments (`pal_osThreadCreateWithAlloc`). | PAL_ERR_INVALID_ARGUMENT |
00998 * | 2 | Test thread creation with invalid arguments (`pal_osThreadCreateWithAlloc`). | PAL_ERR_INVALID_ARGUMENT |
00999 * | 3 | Test thread creation with invalid arguments (`pal_osThreadCreateWithAlloc`). | PAL_ERR_INVALID_ARGUMENT |
01000 * | 4 | Test semaphore creation with invalid arguments (`pal_osSemaphoreCreate`).    | PAL_ERR_INVALID_ARGUMENT |
01001 * | 5 | Test semaphore creation with invalid arguments (`pal_osSemaphoreCreate`).    | PAL_ERR_INVALID_ARGUMENT |
01002 * | 6 | Test semaphore creation with invalid arguments (`pal_osSemaphoreCreate`).    | PAL_ERR_INVALID_ARGUMENT |
01003 * | 7 | Test semaphore creation with invalid arguments (`pal_osSemaphoreCreate`).    | PAL_ERR_INVALID_ARGUMENT |
01004 * | 8 | Test legacy thread create api (pal_osThreadCreate).                          | PAL_SUCCESS              |
01005 * | 9 | Call pal_osThreadTerminate with NULL invalid parameter.                      | PAL_ERR_INVALID_ARGUMENT |
01006 */
01007 TEST(pal_rtos, PrimitivesUnityTest2)
01008 {
01009 #ifdef DEBUG
01010     palStatus_t status = PAL_SUCCESS;
01011     palThreadID_t threadID = NULLPTR;
01012     int32_t tmp = 0;
01013     /*#1*/
01014     //Check thread parameter validation
01015     status = pal_osThreadCreateWithAlloc(palThreadFunc1, NULL, PAL_osPriorityError, 1024, NULL, &threadID);
01016     TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status);
01017     /*#2*/
01018     status = pal_osThreadCreateWithAlloc(palThreadFunc1, NULL, PAL_osPriorityIdle, 0, NULL, &threadID);
01019     TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status);
01020     /*#3*/
01021     status = pal_osThreadCreateWithAlloc(palThreadFunc1, NULL, PAL_osPriorityIdle, 1024, NULL, NULL);
01022     TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status);
01023 
01024     /*#4*/
01025     //Check semaphore parameter validation
01026     status = pal_osSemaphoreCreate(1 ,NULL);
01027     TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status);
01028     /*#5*/
01029     status = pal_osSemaphoreDelete(NULL);
01030     TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status);
01031     /*#6*/
01032     status = pal_osSemaphoreWait(NULLPTR, 1000, &tmp);
01033     TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status);
01034     /*#7*/
01035     status = pal_osSemaphoreRelease(NULLPTR);
01036     TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status);
01037     /*#9*/
01038     status = pal_osThreadTerminate(NULL);
01039     TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status);
01040 #else
01041     TEST_IGNORE_MESSAGE("Ignored, tested only with DEBUG build");
01042 #endif
01043 }
01044 
01045 /*! \brief Creates a semaphore with count=1 and a thread to
01046 * test that it waits forever (the test waits 5 seconds). Then deletes the semaphore
01047 * and terminates the thread.
01048 *
01049 * | # |    Step                        |   Expected  |
01050 * |---|--------------------------------|-------------|
01051 * | 1 | Create a semaphore with count = 1 using `pal_osSemaphoreCreate`.                          | PAL_SUCCESS |
01052 * | 2 | Wait for the semaphore using `pal_osSemaphoreWait` (should not block).                    | PAL_SUCCESS |
01053 * | 3 | Create a thread running `palThreadFuncWaitForEverTestusing` and `pal_osThreadCreateWithAlloc`. | PAL_SUCCESS |
01054 * | 4 | Get time using `pal_osKernelSysMilliSecTick` & pal_osKernelSysTick().                         | PAL_SUCCESS |
01055 * | 5 | Wait for the semaphore using `pal_osSemaphoreWait` (should block; released by thread). Allow 25% inaccuracy on timing. | PAL_SUCCESS |
01056 * | 6 | Delete the semaphore using `pal_osSemaphoreDelete`.                                           | PAL_SUCCESS |
01057 * | 7 | Terminate the thread using `pal_osThreadTerminate`.                                           | PAL_SUCCESS |
01058 */
01059 TEST(pal_rtos, SemaphoreWaitForever)
01060 {
01061     int32_t count = 0;
01062     uint64_t timeStartMs = PAL_MIN_SEC_FROM_EPOCH;
01063     uint64_t timeEndMs;
01064     palStatus_t status = PAL_SUCCESS;
01065     palThreadID_t threadID1 = PAL_INVALID_THREAD;
01066 
01067     /*#1*/
01068     status = pal_osSemaphoreCreate(1 ,&semaphore1);
01069     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
01070     /*#2*/
01071     status = pal_osSemaphoreWait(semaphore1, PAL_RTOS_WAIT_FOREVER, &count);
01072     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
01073     /*#3*/
01074     timeStartMs = pal_osKernelSysMilliSecTick(pal_osKernelSysTick());
01075     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); // More than current epoch time -> success    
01076     status = pal_osThreadCreateWithAlloc(palThreadFuncWaitForEverTest, (void *)&semaphore1, PAL_osPriorityAboveNormal, PAL_TEST_THREAD_STACK_SIZE, NULL, &threadID1);
01077     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
01078     /*#4*/
01079     status = pal_osSemaphoreWait(semaphore1, PAL_RTOS_WAIT_FOREVER, &count);
01080     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
01081     /*#5*/
01082     timeEndMs = pal_osKernelSysMilliSecTick(pal_osKernelSysTick());
01083     TEST_ASSERT_UINT64_WITHIN(PAL_TIME_TO_WAIT_MS/4, PAL_TIME_TO_WAIT_MS/2, (timeEndMs - timeStartMs));
01084     /*#6*/
01085     status = pal_osSemaphoreDelete(&semaphore1);
01086     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
01087     TEST_ASSERT_EQUAL(0, semaphore1);
01088     /*#7*/
01089     status = pal_osThreadTerminate(&threadID1);
01090     TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
01091 }
01092 
01093 /*! \brief Creates a semaphore and waits on it to verify the
01094 * available count for it. Also verifies that the semaphore release API works correctly.
01095 * In addition, it checks the semaphore parameter validation scenarios.
01096 *
01097 * | # |    Step                        |   Expected  |
01098 * |---|--------------------------------|-------------|
01099 * | 1 | Create a semaphore with count = 2 using `pal_osSemaphoreCreate`.                          | PAL_SUCCESS |
01100 * | 2 | Wait for the semaphore using `pal_osSemaphoreWait` (should not block), and check count.   | PAL_SUCCESS |
01101 * | 3 | Increase semaphore count by ten using `pal_osSemaphoreRelease` in a loop.             | PAL_SUCCESS |
01102 * | 4 | Delete semaphore using `pal_osSemaphoreDelete`.                                           | PAL_SUCCESS |
01103 * | 5 | Test semaphore creation with invalid arguments (`pal_osSemaphoreCreate`).                 | PAL_ERR_INVALID_ARGUMENT |
01104 * | 6 | Test semaphore deletion with invalid arguments (`pal_osSemaphoreDelete`).                 | PAL_ERR_INVALID_ARGUMENT |
01105 * | 7 | Test semaphore waiting with invalid arguments (`pal_osSemaphoreWait`).                    | PAL_ERR_INVALID_ARGUMENT |
01106 * | 8 | Test semaphore release with invalid arguments (`pal_osSemaphoreRelease`).                 | PAL_ERR_INVALID_ARGUMENT |
01107 */
01108 TEST(pal_rtos, SemaphoreBasicTest)
01109 {
01110 
01111     palStatus_t status = PAL_SUCCESS;
01112     int counter = 0;
01113     /*#1*/
01114     status = pal_osSemaphoreCreate(2 ,&semaphore1);
01115     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
01116     /*#2*/
01117     int32_t count = -1;
01118     status = pal_osSemaphoreWait(semaphore1, 1000, &count);
01119     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
01120     TEST_ASSERT_EQUAL(1, count);
01121 
01122     /*#3*/
01123     for(counter = 0; counter < 10; counter++)
01124     {
01125         status=pal_osSemaphoreRelease(semaphore1);
01126         TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
01127     }
01128     /*#4*/
01129     status=pal_osSemaphoreDelete(&semaphore1);
01130     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
01131     TEST_ASSERT_EQUAL(0, semaphore1);
01132 
01133     
01134 #ifdef DEBUG
01135     //Check semaphore parameter validation
01136     int32_t tmp;
01137     /*#5*/
01138     status = pal_osSemaphoreCreate(1 ,NULL);
01139     TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status);
01140     /*#6*/
01141     status = pal_osSemaphoreDelete(NULL);
01142     TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status);
01143     /*#7*/
01144     status = pal_osSemaphoreWait(NULLPTR, 1000, &tmp);
01145     TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status);
01146     /*#8*/
01147     status = pal_osSemaphoreRelease(NULLPTR);
01148     TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status);
01149 #endif
01150 }
01151 
01152 
01153 
01154 /*! \brief Performs a single atomic increment call
01155 * to an integer value and verifies that the result is as expected.
01156 *
01157 * | # |    Step                        |   Expected  |
01158 * |---|--------------------------------|-------------|
01159 * | 1 | Call atomic increment using `pal_osAtomicIncrement` and check that the value was incremented. | PAL_SUCCESS |
01160 * | 2 | Call atomic increment using `pal_osAtomicIncrement` and check that the value was incremented. | PAL_SUCCESS |
01161 * | 3 | Call atomic increment using `pal_osAtomicIncrement` with negative value and check that the value was decremented. | PAL_SUCCESS |
01162 * | 4 | Call atomic increment using `pal_osAtomicIncrement` with zero value and check that the value was same. | PAL_SUCCESS |
01163 * | 5 | Call atomic increment using `pal_osAtomicIncrement` with negative value and check that the value was decremented. | PAL_SUCCESS |
01164 * | 6 | Call atomic increment using `pal_osAtomicIncrement` with negative value and check that the value was decremented. | PAL_SUCCESS |
01165 */
01166 TEST(pal_rtos, AtomicIncrementUnityTest)
01167 {
01168     int32_t num1 = 0;
01169     int32_t increment = 10;
01170     int32_t tmp = 0;
01171     int32_t original = num1;
01172 
01173     /*#1*/
01174     tmp = pal_osAtomicIncrement(&num1, increment);
01175     TEST_ASSERT_EQUAL(original + increment, tmp);
01176     TEST_ASSERT_EQUAL(num1, tmp);
01177 
01178     /*#2*/
01179     increment = 40;
01180     tmp = pal_osAtomicIncrement(&num1, increment);
01181     TEST_ASSERT_EQUAL(50, tmp);
01182     TEST_ASSERT_EQUAL(num1, tmp);
01183 
01184     /*#3*/
01185     increment = -45;
01186     tmp = pal_osAtomicIncrement(&num1, increment);
01187     TEST_ASSERT_EQUAL(5, tmp);
01188     TEST_ASSERT_EQUAL(num1, tmp);
01189 
01190     /*#4*/
01191     // verify with zero too, as it is legal value
01192     increment = 0;
01193     tmp = pal_osAtomicIncrement(&num1, increment);
01194     TEST_ASSERT_EQUAL(5, tmp);
01195     TEST_ASSERT_EQUAL(num1, tmp);
01196 
01197     /*#5*/
01198     increment = -5;
01199     tmp = pal_osAtomicIncrement(&num1, increment);
01200     TEST_ASSERT_EQUAL(0, tmp);
01201     TEST_ASSERT_EQUAL(num1, tmp);
01202 
01203     /*#6*/
01204     increment = -15;
01205     tmp = pal_osAtomicIncrement(&num1, increment);
01206     TEST_ASSERT_EQUAL(-15, tmp);
01207     TEST_ASSERT_EQUAL(num1, tmp);
01208 }
01209 
01210 
01211 /*! \brief Verify that PAL can handle multiple calls for `pal_init()` and `pal_destroy()`.
01212 *
01213 * | # |    Step                                              |   Expected  |
01214 * |---|------------------------------------------------------|-------------|
01215 * | 1 | Call `pal_init`.                                     | PAL_SUCCESS |
01216 * | 2 | Call `pal_init`.                                     | PAL_SUCCESS |
01217 * | 3 | Call `pal_init`.                                     | PAL_SUCCESS |
01218 * | 4 | Call `pal_destroy` in a loop untill init count == 0. | PAL_SUCCESS |
01219 * | 5 | Call `pal_init`.                                     | PAL_SUCCESS |
01220 * | 6 | Call `pal_RTOSInitialize`.                           | PAL_SUCCESS |
01221 * | 7 | Call `pal_destroy`.                                  | PAL_SUCCESS |
01222 */
01223 TEST(pal_rtos, pal_init_test)
01224 {
01225 #if (PAL_INITIALIZED_BEFORE_TESTS == 0)
01226 
01227     palStatus_t status = PAL_SUCCESS;
01228     int32_t initCounter = 0;
01229     /*#1*/
01230     status = pal_init();
01231     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
01232     /*#2*/
01233     status = pal_init();
01234     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
01235     /*#3*/
01236     status = pal_init();
01237     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
01238 
01239     /*#4*/
01240     do
01241     {
01242         initCounter = pal_destroy();
01243         //TEST_ASSERT_EQUAL_HEX(0, initCounter);
01244 
01245     }while(initCounter != 0);
01246 
01247     /*#5*/
01248     status = pal_init();
01249     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
01250 
01251     status = pal_RTOSInitialize(NULLPTR);
01252     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
01253 
01254     /*#7*/
01255     initCounter = pal_destroy();
01256     TEST_ASSERT_EQUAL_HEX(0, initCounter);
01257 #else
01258     TEST_IGNORE_MESSAGE("Ignored, PAL_INITIALIZED_BEFORE_TESTS set");
01259 #endif
01260 }
01261 
01262 /*! \brief Check derivation of keys from the platform's Root of Trust using the KDF algorithm.
01263  *
01264  * 
01265  *
01266 * | # |    Step                        |   Expected  |
01267 * |---|--------------------------------|-------------|
01268 * | 1 | Start a loop to perform the following steps.                                               |  |
01269 * | 2 | Derive a device key for encryption using `pal_osGetDeviceKey`.                   | PAL_SUCCESS |
01270 * | 3 | Derive a device key for signing using `pal_osGetDeviceKey`.                      | PAL_SUCCESS |
01271 * | 4 | Call `pal_osGetDeviceKey` with invalid arguments.                              | PAL_FAILURE |
01272 * | 5 | Call `pal_osGetDeviceKey` with invalid arguments.                              | PAL_FAILURE |
01273 * | 6 | Check that the derived signing and encryption keys are different.                     | PAL_SUCCESS |
01274 * | 7 | Check that all integrations of each type of derivation return the same value.       | PAL_SUCCESS |
01275  */
01276 TEST(pal_rtos, GetDeviceKeyTest_CMAC)
01277 {
01278     palStatus_t status = PAL_SUCCESS;
01279     size_t keyLenBytes = 16;
01280     uint8_t timesToDerive = 4;
01281     unsigned char encKeyDerive[timesToDerive][keyLenBytes]; //16 bytes=128bit
01282     unsigned char signKeyDerive[timesToDerive][keyLenBytes]; //16 bytes=128bit
01283     /*#1*/
01284     for (int i=0; i < timesToDerive; i++)
01285     {
01286         /*#2*/
01287         status = pal_osGetDeviceKey(palOsStorageEncryptionKey128Bit, encKeyDerive[i], keyLenBytes);
01288         TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
01289         /*#3*/
01290         status = pal_osGetDeviceKey(palOsStorageSignatureKey128Bit ,  signKeyDerive[i], keyLenBytes);
01291         TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
01292         /*#4*/
01293         status = pal_osGetDeviceKey(palOsStorageSignatureKey128Bit ,  signKeyDerive[i], keyLenBytes-1);
01294         TEST_ASSERT_NOT_EQUAL(PAL_SUCCESS, status);
01295         /*#5*/
01296         status = pal_osGetDeviceKey(palOsStorageSignatureKey128Bit ,  NULL, keyLenBytes);
01297         TEST_ASSERT_NOT_EQUAL(PAL_SUCCESS, status);
01298         /*#6*/
01299         status = memcmp(encKeyDerive[i], signKeyDerive[i], keyLenBytes);
01300         TEST_ASSERT_NOT_EQUAL(status,0); //The keys MUST be different!
01301         /*#7*/
01302         if (i > 0) //Make sure key derivation is persistent every time
01303         {
01304             TEST_ASSERT_EQUAL_MEMORY(encKeyDerive[i-1], encKeyDerive[i], keyLenBytes);
01305             TEST_ASSERT_EQUAL_MEMORY(signKeyDerive[i-1], signKeyDerive[i], keyLenBytes);
01306 
01307         } //if
01308 
01309     } //for
01310 
01311 }
01312 
01313 /*! \brief Check derivation of keys from the platform's Root of Trust using the KDF algorithm.
01314  *
01315  * 
01316  *
01317 * | # |    Step                                                                        | Expected            |
01318 * |---|--------------------------------------------------------------------------------|---------------------|
01319 * | 1 | Start a loop to perform the following steps.                                   |                     |
01320 * | 2 | Derive a device key for encryption using `pal_osGetDeviceKey`.                 | PAL_SUCCESS         |
01321 * | 3 | Call `pal_osGetDeviceKey` with invalid arguments.                              | PAL_FAILURE         |
01322 * | 4 | Call `pal_osGetDeviceKey` with invalid arguments.                              | PAL_FAILURE         |
01323 * | 5 | Check that all integrations of each type of derivation return the same value.  | PAL_SUCCESS         |
01324 * | 6 | Call `pal_osGetDeviceKey` with invalid palDevKeyType_t.                        | PAL_ERR_INVALID_ARGUMENT |
01325  */
01326 TEST(pal_rtos, GetDeviceKeyTest_HMAC_SHA256)
01327 {
01328     palStatus_t status = PAL_SUCCESS;
01329     size_t keyLenBytes = 32;
01330     uint8_t timesToDerive = 4;
01331     unsigned char encKeyDerive[timesToDerive][keyLenBytes]; //32 bytes=256bit
01332     /*#1*/
01333     for (int i=0; i < timesToDerive; i++)
01334     {
01335         /*#2*/
01336         status = pal_osGetDeviceKey(palOsStorageHmacSha256 , encKeyDerive[i], keyLenBytes);
01337         TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
01338 #ifdef DEBUG
01339         /*#3*/
01340         status = pal_osGetDeviceKey(palOsStorageHmacSha256 ,  encKeyDerive[i], keyLenBytes-1);
01341         TEST_ASSERT_NOT_EQUAL(PAL_SUCCESS, status);
01342         /*#4*/
01343         status = pal_osGetDeviceKey(palOsStorageHmacSha256 ,  NULL, keyLenBytes);
01344         TEST_ASSERT_NOT_EQUAL(PAL_SUCCESS, status);
01345 #endif
01346         /*#5*/
01347         if (i > 0) //Make sure key derivation is persistent every time
01348         {
01349             TEST_ASSERT_EQUAL_MEMORY(encKeyDerive[i-1], encKeyDerive[i], keyLenBytes);
01350         } //if
01351 
01352     } //for
01353 
01354 #ifdef DEBUG
01355       /*#6*/
01356     status = pal_osGetDeviceKey((palDevKeyType_t)999, encKeyDerive[0], keyLenBytes);
01357     TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT , status);
01358 #endif
01359 }
01360 
01361 
01362 /*! \brief Check recursive mutex behavior.
01363 *
01364 * | # |    Step                        |   Expected  |
01365 * |---|--------------------------------|-------------|
01366 * | 1 | Create a mutex using `pal_osMutexCreate`.                                             | PAL_SUCCESS |
01367 * | 2 | Create a semaphore using `pal_osSemaphoreCreate`.                                     | PAL_SUCCESS |
01368 * | 3 | Create a thread running `RecursiveLockThread` using `pal_osThreadCreateWithAlloc`.       | PAL_SUCCESS |
01369 * | 4 | Create a thread running `RecursiveLockThread` using `pal_osThreadCreateWithAlloc`.       | PAL_SUCCESS |
01370 * | 5 | Release the semaphore using `pal_osSemaphoreRelease`.                                    | PAL_SUCCESS |
01371 * | 6 | Release the semaphore using `pal_osSemaphoreRelease`.                                    | PAL_SUCCESS |
01372 * | 7 | Sleep for a short interval.                                                          | PAL_SUCCESS |
01373 * | 8 | Wait for the semaphore using `pal_osSemaphoreWait`.                                      | PAL_SUCCESS |
01374 * | 9 | Wait for the semaphore using `pal_osSemaphoreWait`.                                      | PAL_SUCCESS |
01375 * | 10 | Terminate the first thread using `pal_osThreadTerminate`.                               | PAL_SUCCESS |
01376 * | 11 | Terminate the second thread using `pal_osThreadTerminate`.                              | PAL_SUCCESS |
01377 * | 12 | Delete the mutex using `pal_osMutexDelete`.                                           | PAL_SUCCESS |
01378 * | 13 | Delete the semaphore using `pal_osSemaphoreDelete`.                                   | PAL_SUCCESS |
01379 */
01380 TEST(pal_rtos, Recursive_Mutex_Test)
01381 {
01382     palStatus_t status;
01383     int32_t val = 0;
01384 
01385     recursiveMutexData = malloc(sizeof(palRecursiveMutexParam_t));
01386     TEST_ASSERT_NOT_NULL(recursiveMutexData);
01387     memset(recursiveMutexData, 0, sizeof(palRecursiveMutexParam_t));
01388     /*#1*/
01389     status = pal_osMutexCreate(&(recursiveMutexData->mtx));
01390     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
01391     /*#2*/
01392     status = pal_osSemaphoreCreate(0, &(recursiveMutexData->sem));
01393     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
01394     /*#3*/
01395     status = pal_osThreadCreateWithAlloc(RecursiveLockThread, (void*)recursiveMutexData, PAL_osPriorityHigh, PAL_TEST_THREAD_STACK_SIZE, NULL, &(recursiveMutexData->higherPriorityThread));
01396     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
01397     /*#4*/
01398      status = pal_osThreadCreateWithAlloc(RecursiveLockThread, (void*)recursiveMutexData, PAL_osPriorityAboveNormal, PAL_TEST_THREAD_STACK_SIZE, NULL, &(recursiveMutexData->lowerPriorityThread));
01399      TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
01400     /*#5*/
01401     status = pal_osSemaphoreRelease(recursiveMutexData->sem);
01402     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
01403     /*#6*/
01404     status = pal_osSemaphoreRelease(recursiveMutexData->sem);
01405     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
01406     /*#7*/
01407     pal_osDelay(1000);
01408     /*#8*/
01409     status = pal_osSemaphoreWait(recursiveMutexData->sem, PAL_RTOS_WAIT_FOREVER, &val);
01410     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
01411     /*#9*/
01412     status = pal_osSemaphoreWait(recursiveMutexData->sem, PAL_RTOS_WAIT_FOREVER, &val);
01413     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
01414     TEST_ASSERT_EQUAL(0, val);
01415     TEST_ASSERT_EQUAL_HEX(NULLPTR, recursiveMutexData->activeThread);
01416     /*#10*/
01417     status = pal_osThreadTerminate(&(recursiveMutexData->higherPriorityThread));
01418     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
01419     /*#11*/
01420     status = pal_osThreadTerminate(&(recursiveMutexData->lowerPriorityThread));
01421     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
01422     /*#12*/
01423     status = pal_osMutexDelete(&(recursiveMutexData->mtx));
01424     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
01425     /*#13*/
01426     status = pal_osSemaphoreDelete(&recursiveMutexData->sem);
01427     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
01428 
01429     TEST_ASSERT_EQUAL(400, recursiveMutexData->count);
01430 
01431     free(recursiveMutexData);
01432     recursiveMutexData = NULL;
01433 }
01434 
01435 
01436 
01437 
01438 /*! \brief This test verify the functionality of the RTC
01439  *
01440  * | # |    Step                        |   Expected  |
01441  * |---|--------------------------------|-------------|
01442  * | 1 | Get system RTC                           | PAL_SUCCESS |
01443  * | 2 | set new RTC                              | PAL_SUCCESS |
01444  * | 3 | delay for 2 seconds                      | PAL_SUCCESS |
01445  * | 4 | get RTC & compare to RTC from (2)        | PAL_SUCCESS |
01446  * | 5 | restore system time from (1)             | PAL_SUCCESS |
01447  */
01448 TEST(pal_rtos, pal_rtc)
01449 {
01450 #if (PAL_USE_HW_RTC)
01451     palStatus_t status = PAL_SUCCESS;
01452     uint64_t time1 = 0, sysTime = 0;
01453 
01454     /*#1*/
01455     status = pal_plat_osGetRtcTime(&sysTime);
01456     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
01457 
01458     /*#2*/
01459     status = pal_plat_osSetRtcTime(PAL_MIN_RTC_SET_TIME);
01460     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
01461 
01462     /*#3*/
01463     status = pal_osDelay(2000);
01464     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
01465 
01466     /*#4*/
01467     status = pal_plat_osGetRtcTime(&time1);
01468     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
01469     TEST_ASSERT_TRUE(time1 - PAL_MIN_RTC_SET_TIME >=  1 * PAL_ONE_SEC);
01470 
01471     /*#5*/
01472     pal_plat_osSetRtcTime(sysTime + time1 - PAL_MIN_RTC_SET_TIME  + 1); //add lost time from delay
01473 
01474 #else
01475     TEST_IGNORE_MESSAGE("Ignored, PAL_USE_HW_RTC not set");
01476 #endif
01477 }
01478