Rtos API example

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2017 ARM Limited
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 #include "mbed.h"
00017 #include "greentea-client/test_env.h"
00018 #include "unity.h"
00019 #include "utest.h"
00020 
00021 using namespace utest::v1;
00022 
00023 /* Enum used to select block allocation method. */
00024 typedef enum
00025 {
00026     ALLOC, CALLOC
00027 } AllocType;
00028 
00029 /* Structure for complex block type. */
00030 typedef struct
00031 {
00032     int a;
00033     char b;
00034     int c;
00035 } COMPLEX_TYPE;
00036 
00037 /* Function to check if complex type object is cleared.*/
00038 bool comp_is_cleared(COMPLEX_TYPE *object)
00039 {
00040     if (object->a == 0 && object->b == 0 && object->c == 0) {
00041         return true;
00042     }
00043 
00044     return false;
00045 }
00046 
00047 /* Function to check if complex type object holds specified values.*/
00048 bool comp_is_equal(COMPLEX_TYPE *object, int a, char b, int c)
00049 {
00050     if (object->a == a && object->b == b && object->c == c) {
00051         return true;
00052     }
00053 
00054     return false;
00055 }
00056 
00057 /* Function to set complex type object fields.*/
00058 void comp_set(COMPLEX_TYPE *object, int a, char b, int c)
00059 {
00060     object->a = a;
00061     object->b = b;
00062     object->c = c;
00063 }
00064 
00065 /* Template for functional tests for alloc(), calloc() functions
00066  * of MemoryPool object.
00067  *
00068  * Given MemoryPool object of the specified type and queue size has
00069  * been successfully created.
00070  * When max number of blocks is allocated from the pool.
00071  * Then all allocations are successful.
00072  *
00073  * */
00074 template<typename T, const uint32_t numOfEntries>
00075 void test_mem_pool_alloc_success(AllocType atype)
00076 {
00077     MemoryPool<T, numOfEntries> mem_pool;
00078     T * p_blocks[numOfEntries];
00079     uint32_t i;
00080 
00081     /* Test alloc()/calloc() methods - try to allocate max number of
00082        blocks. All allocations should be successful. */
00083     for (i = 0; i < numOfEntries; i++) {
00084         /* Allocate memory block. */
00085         if (atype == ALLOC) {
00086             p_blocks[i] = mem_pool.alloc();
00087         } else {
00088             p_blocks[i] = mem_pool.calloc();
00089         }
00090 
00091         /* Show that memory pool block has been allocated. */
00092         TEST_ASSERT_NOT_NULL(p_blocks[i]);
00093 
00094         /* Check if Calloc clears the block. */
00095         if (atype == CALLOC) {
00096             TEST_ASSERT_EQUAL(0, *p_blocks[i]);
00097         }
00098 
00099         /* Init fields. */
00100         *p_blocks[i] = (i + 5);
00101     }
00102 
00103     /* Check if blocks holds valid values. */
00104     for (i = 0; i < numOfEntries; i++) {
00105         TEST_ASSERT_EQUAL((i + 5), *p_blocks[i]);
00106     }
00107 }
00108 
00109 /* Template for functional tests for alloc(), calloc() functions
00110  * of MemoryPool object.
00111  *
00112  * Complex memory pool block type is used.
00113  *
00114  * Given MemoryPool object of the specified type and queue size has
00115  * been successfully created.
00116  * When max number of blocks is allocated from the pool.
00117  * Then all allocations are successful.
00118  *
00119  * */
00120 template<typename T, const uint32_t numOfEntries>
00121 void test_mem_pool_alloc_success_complex(AllocType atype)
00122 {
00123     MemoryPool<T, numOfEntries> mem_pool;
00124     T * p_blocks[numOfEntries];
00125     uint32_t i;
00126 
00127     /* Test alloc()/calloc() methods - try to allocate max number of
00128        blocks. All allocations should be successful. */
00129     for (i = 0; i < numOfEntries; i++) {
00130         /* Allocate memory block. */
00131         if (atype == ALLOC) {
00132             p_blocks[i] = mem_pool.alloc();
00133         } else {
00134             p_blocks[i] = mem_pool.calloc();
00135         }
00136 
00137         /* Show that memory pool block has been allocated. */
00138         TEST_ASSERT_NOT_NULL(p_blocks[i]);
00139 
00140         /* Check if Calloc clears the block. */
00141         if (atype == CALLOC) {
00142             TEST_ASSERT_EQUAL(true, comp_is_cleared(p_blocks[i]));
00143         }
00144 
00145         /* Init fields. */
00146         comp_set(p_blocks[i], i + 1, i + 2, i + 3);
00147     }
00148 
00149     /* Check if blocks holds valid values. */
00150     for (i = 0; i < numOfEntries; i++) {
00151         TEST_ASSERT_EQUAL(true, comp_is_equal(p_blocks[i], i + 1, i + 2, i + 3));
00152     }
00153 }
00154 
00155 /* Template for functional tests for alloc(), calloc() functions
00156  * of MemoryPool object.
00157  *
00158  * Given MemoryPool has already max number of blocks allocated from the pool.
00159  * When next block is allocated.
00160  * Then allocation fails.
00161  *
00162  * */
00163 template<typename T, const uint32_t numOfEntries>
00164 void test_mem_pool_alloc_fail(AllocType atype)
00165 {
00166     MemoryPool<T, numOfEntries> mem_pool;
00167     T * p_blocks[numOfEntries];
00168     T * p_extra_block;
00169     uint32_t i;
00170 
00171     /* Allocate all available blocks. */
00172     for (i = 0; i < numOfEntries; i++) {
00173         if (atype == ALLOC) {
00174             p_blocks[i] = mem_pool.alloc();
00175         } else {
00176             p_blocks[i] = mem_pool.calloc();
00177         }
00178 
00179         /* Show that memory pool block has been allocated. */
00180         TEST_ASSERT_NOT_NULL(p_blocks[i]);
00181     }
00182 
00183     /* There are no more blocks available. Try to allocate another block. */
00184     if (atype == ALLOC) {
00185         p_extra_block = mem_pool.alloc();
00186     } else {
00187         p_extra_block = mem_pool.calloc();
00188     }
00189 
00190     /* Show that memory pool block has NOT been allocated. */
00191     TEST_ASSERT_NULL(p_extra_block);
00192 }
00193 
00194 /* Template for functional tests for free() function
00195  * of MemoryPool object.
00196  *
00197  * Given MemoryPool has all blocks allocated.
00198  * When free operation is executed on the each allocated block.
00199  * Then each deallocation is successfully performed.
00200  *
00201  * */
00202 template<typename T, const uint32_t numOfEntries>
00203 void test_mem_pool_free_success(AllocType atype)
00204 {
00205     MemoryPool<T, numOfEntries> mem_pool;
00206     T * p_blocks[numOfEntries];
00207     uint32_t i;
00208     osStatus status;
00209 
00210     /* Allocate all available blocks. */
00211     for (i = 0; i < numOfEntries; i++) {
00212         if (atype == ALLOC) {
00213             p_blocks[i] = mem_pool.alloc();
00214         } else {
00215             p_blocks[i] = mem_pool.calloc();
00216         }
00217 
00218         /* Show that memory pool block has been allocated. */
00219         TEST_ASSERT_NOT_NULL(p_blocks[i]);
00220     }
00221 
00222     /* Free all memory blocks. */
00223     for (i = 0; i < numOfEntries; i++) {
00224         status = mem_pool.free(p_blocks[i]);
00225 
00226         /* Check operation status. */
00227         TEST_ASSERT_EQUAL(osOK, status);
00228     }
00229 }
00230 
00231 /* Template for functional tests for alloc(), calloc() functions
00232  * of MemoryPool object.
00233  *
00234  * Basic memory pool block type is used.
00235  *
00236  * Given MemoryPool had all blocks allocated and one block has
00237  * been freed (last).
00238  * When next block is allocated.
00239  * Then allocation is successful.
00240  *
00241  * */
00242 template<typename T, const uint32_t numOfEntries>
00243 void test_mem_pool_free_realloc_last(AllocType atype)
00244 {
00245     MemoryPool<T, numOfEntries> mem_pool;
00246     T * p_blocks[numOfEntries];
00247     uint32_t i;
00248     osStatus status;
00249 
00250     /* Allocate all available blocks. */
00251     for (i = 0; i < numOfEntries; i++) {
00252         if (atype == ALLOC) {
00253             p_blocks[i] = mem_pool.alloc();
00254         } else {
00255             p_blocks[i] = mem_pool.calloc();
00256         }
00257 
00258         /* Init block. */
00259         *p_blocks[i] = 0xAB;
00260 
00261         /* Show that memory pool block has been allocated. */
00262         TEST_ASSERT_NOT_NULL(p_blocks[i]);
00263     }
00264 
00265     /* Free the last block. */
00266     status = mem_pool.free(p_blocks[numOfEntries - 1]);
00267 
00268     /* Check status. */
00269     TEST_ASSERT_EQUAL(osOK, status);
00270 
00271     /* Try to allocate another block (one block is now available). */
00272     if (atype == ALLOC) {
00273         p_blocks[numOfEntries - 1] = mem_pool.alloc();
00274     } else {
00275         p_blocks[numOfEntries - 1] = mem_pool.calloc();
00276     }
00277 
00278     /* Show that memory pool block has been now allocated. */
00279     TEST_ASSERT_NOT_NULL(p_blocks[numOfEntries - 1]);
00280 
00281     /* Check if Calloc clears the block. */
00282     if (atype == CALLOC) {
00283         TEST_ASSERT_EQUAL(0, *p_blocks[numOfEntries - 1]);
00284     }
00285 }
00286 
00287 /* Template for functional tests for alloc(), calloc() functions
00288  * of MemoryPool object.
00289  *
00290  * Complex memory pool block type is used.
00291  *
00292  * Given MemoryPool had all blocks allocated and one block has
00293  * been freed (last).
00294  * When next block is allocated.
00295  * Then allocation is successful.
00296  *
00297  * */
00298 template<typename T, const uint32_t numOfEntries>
00299 void test_mem_pool_free_realloc_last_complex(AllocType atype)
00300 {
00301     MemoryPool<T, numOfEntries> mem_pool;
00302     T * p_blocks[numOfEntries];
00303     uint32_t i;
00304     osStatus status;
00305 
00306     /* Allocate all available blocks. */
00307     for (i = 0; i < numOfEntries; i++) {
00308         if (atype == ALLOC) {
00309             p_blocks[i] = mem_pool.alloc();
00310         } else {
00311             p_blocks[i] = mem_pool.calloc();
00312         }
00313 
00314         /* Init block. */
00315         comp_set(p_blocks[i], i + 1, i + 2, i + 3);
00316 
00317         /* Show that memory pool block has been allocated. */
00318         TEST_ASSERT_NOT_NULL(p_blocks[i]);
00319     }
00320 
00321     /* Free the last block. */
00322     status = mem_pool.free(p_blocks[numOfEntries - 1]);
00323 
00324     /* Check status. */
00325     TEST_ASSERT_EQUAL(osOK, status);
00326 
00327     /* Try to allocate another block (one block is now available). */
00328     if (atype == ALLOC) {
00329         p_blocks[numOfEntries - 1] = mem_pool.alloc();
00330     } else {
00331         p_blocks[numOfEntries - 1] = mem_pool.calloc();
00332     }
00333 
00334     /* Show that memory pool block has been now allocated. */
00335     TEST_ASSERT_NOT_NULL(p_blocks[numOfEntries - 1]);
00336 
00337     /* Check if Calloc clears the block. */
00338     if (atype == CALLOC) {
00339         TEST_ASSERT_EQUAL(true, comp_is_cleared(p_blocks[numOfEntries - 1]));
00340     }
00341 }
00342 
00343 /* Template for functional tests for alloc(), calloc() functions
00344  * of MemoryPool object.
00345  *
00346  * Basic memory pool block type is used.
00347  *
00348  * Given MemoryPool had all blocks allocated and one block has
00349  * been freed (first).
00350  * When next block is allocated.
00351  * Then allocation is successful.
00352  *
00353  * */
00354 template<typename T, const uint32_t numOfEntries>
00355 void test_mem_pool_free_realloc_first(AllocType atype)
00356 {
00357     MemoryPool<T, numOfEntries> mem_pool;
00358     T * p_blocks[numOfEntries];
00359     uint32_t i;
00360     osStatus status;
00361 
00362     /* Allocate all available blocks. */
00363     for (i = 0; i < numOfEntries; i++) {
00364         if (atype == ALLOC) {
00365             p_blocks[i] = mem_pool.alloc();
00366         } else {
00367             p_blocks[i] = mem_pool.calloc();
00368         }
00369 
00370         /* Init block. */
00371         *p_blocks[i] = 0xAB;
00372 
00373         /* Show that memory pool block has been allocated. */
00374         TEST_ASSERT_NOT_NULL(p_blocks[i]);
00375     }
00376 
00377     /* Free the last block. */
00378     status = mem_pool.free(p_blocks[0]);
00379 
00380     /* Check status. */
00381     TEST_ASSERT_EQUAL(osOK, status);
00382 
00383     /* Try to allocate another block (one block is now available). */
00384     if (atype == ALLOC) {
00385         p_blocks[0] = mem_pool.alloc();
00386     } else {
00387         p_blocks[0] = mem_pool.calloc();
00388     }
00389 
00390     /* Show that memory pool block has been now allocated. */
00391     TEST_ASSERT_NOT_NULL(p_blocks[0]);
00392 
00393     /* Check if Calloc clears the block. */
00394     if (atype == CALLOC) {
00395         TEST_ASSERT_EQUAL(0, *p_blocks[0]);
00396     }
00397 }
00398 
00399 /* Template for functional tests for alloc(), calloc() functions
00400  * of MemoryPool object.
00401  *
00402  * Complex memory pool block type is used.
00403  *
00404  * Given MemoryPool had all blocks allocated and one block has
00405  * been freed (first).
00406  * When next block is allocated.
00407  * Then allocation is successful.
00408  *
00409  * */
00410 template<typename T, const uint32_t numOfEntries>
00411 void test_mem_pool_free_realloc_first_complex(AllocType atype)
00412 {
00413     MemoryPool<T, numOfEntries> mem_pool;
00414     T * p_blocks[numOfEntries];
00415     uint32_t i;
00416     osStatus status;
00417 
00418     /* Allocate all available blocks. */
00419     for (i = 0; i < numOfEntries; i++) {
00420         if (atype == ALLOC) {
00421             p_blocks[i] = mem_pool.alloc();
00422         } else {
00423             p_blocks[i] = mem_pool.calloc();
00424         }
00425 
00426         /* Init block. */
00427         comp_set(p_blocks[i], i + 1, i + 2, i + 3);
00428 
00429         /* Show that memory pool block has been allocated. */
00430         TEST_ASSERT_NOT_NULL(p_blocks[i]);
00431     }
00432 
00433     /* Free the last block. */
00434     status = mem_pool.free(p_blocks[0]);
00435 
00436     /* Check status. */
00437     TEST_ASSERT_EQUAL(osOK, status);
00438 
00439     /* Try to allocate another block (one block is now available). */
00440     if (atype == ALLOC) {
00441         p_blocks[0] = mem_pool.alloc();
00442     } else {
00443         p_blocks[0] = mem_pool.calloc();
00444     }
00445 
00446     /* Show that memory pool block has been now allocated. */
00447     TEST_ASSERT_NOT_NULL(p_blocks[0]);
00448 
00449     /* Check if Calloc clears the block. */
00450     if (atype == CALLOC) {
00451         TEST_ASSERT_EQUAL(true, comp_is_cleared(p_blocks[0]));
00452     }
00453 }
00454 
00455 /* Robustness checks for free() function.
00456  *
00457  * Given block from the MemoryPool has been successfully deallocated.
00458  * When free operation is executed on this block again.
00459  * Then operation fails with osErrorResource status.
00460  *
00461  * */
00462 void test_mem_pool_free_on_freed_block()
00463 {
00464     MemoryPool<int, 1> mem_pool;
00465     int * p_block;
00466     osStatus status;
00467 
00468     /* Allocate memory block. */
00469     p_block = mem_pool.alloc();
00470 
00471     /* Show that memory pool block has been allocated. */
00472     TEST_ASSERT_NOT_NULL(p_block);
00473 
00474     /* Free memory block. */
00475     status = mem_pool.free(p_block);
00476 
00477     /* Check operation status. */
00478     TEST_ASSERT_EQUAL(osOK, status);
00479 
00480     /* Free memory block again. */
00481     status = mem_pool.free(p_block);
00482 
00483     /* Check operation status. */
00484     TEST_ASSERT_EQUAL(osErrorResource, status);
00485 }
00486 
00487 /* Robustness checks for free() function.
00488  * Function under test is called with invalid parameters.
00489  *
00490  * Given MemoryPool object has been successfully created.
00491  * When free operation is performed on NULL address.
00492  * Then deallocation fails with osErrorParameter error.
00493  *
00494  */
00495 void free_block_invalid_parameter_null()
00496 {
00497     MemoryPool<int, 1> mem_pool;
00498     osStatus status;
00499 
00500     /* Try to free block passing invalid parameter (NULL). */
00501     status = mem_pool.free(NULL);
00502 
00503     /* Check operation status. */
00504     TEST_ASSERT_EQUAL(osErrorParameter, status);
00505 }
00506 
00507 /* Robustness checks for free() function.
00508  * Function under test is called with invalid parameters.
00509  *
00510  * Given MemoryPool object has been successfully created.
00511  * When free operation is performed on invalid address.
00512  * Then deallocation fails with osErrorParameter error.
00513  *
00514  */
00515 void free_block_invalid_parameter()
00516 {
00517     MemoryPool<int, 1> mem_pool;
00518     osStatus status;
00519 
00520     /* Try to free block passing invalid parameter (variable address). */
00521     status = mem_pool.free(reinterpret_cast<int*>(&status));
00522 
00523     /* Check operation status. */
00524     TEST_ASSERT_EQUAL(osErrorParameter, status);
00525 }
00526 
00527 /* Use wrapper functions to reduce memory usage. */
00528 
00529 template<typename T, const uint32_t numOfEntries>
00530 void test_mem_pool_alloc_success_wrapper()
00531 {
00532     test_mem_pool_alloc_success<T, numOfEntries>(ALLOC);
00533     test_mem_pool_alloc_success<T, numOfEntries>(CALLOC);
00534 }
00535 
00536 template<typename T, const uint32_t numOfEntries>
00537 void test_mem_pool_alloc_success_complex_wrapper()
00538 {
00539     test_mem_pool_alloc_success_complex<T, numOfEntries>(ALLOC);
00540     test_mem_pool_alloc_success_complex<T, numOfEntries>(CALLOC);
00541 }
00542 
00543 template<typename T, const uint32_t numOfEntries>
00544 void test_mem_pool_free_success_wrapper()
00545 {
00546     test_mem_pool_free_success<T, numOfEntries>(ALLOC);
00547     test_mem_pool_free_success<T, numOfEntries>(CALLOC);
00548 }
00549 
00550 template<typename T, const uint32_t numOfEntries>
00551 void test_mem_pool_free_realloc_last_wrapper()
00552 {
00553     test_mem_pool_free_realloc_last<T, numOfEntries>(ALLOC);
00554     test_mem_pool_free_realloc_last<T, numOfEntries>(CALLOC);
00555 
00556 }
00557 
00558 template<typename T, const uint32_t numOfEntries>
00559 void test_mem_pool_free_realloc_first_wrapper()
00560 {
00561     test_mem_pool_free_realloc_first<T, numOfEntries>(ALLOC);
00562     test_mem_pool_free_realloc_first<T, numOfEntries>(CALLOC);
00563 }
00564 
00565 template<typename T, const uint32_t numOfEntries>
00566 void test_mem_pool_free_realloc_first_complex_wrapper()
00567 {
00568     test_mem_pool_free_realloc_first_complex<T, numOfEntries>(ALLOC);
00569     test_mem_pool_free_realloc_first_complex<T, numOfEntries>(CALLOC);
00570 }
00571 
00572 template<typename T, const uint32_t numOfEntries>
00573 void test_mem_pool_free_realloc_last_complex_wrapper()
00574 {
00575     test_mem_pool_free_realloc_last_complex<T, numOfEntries>(ALLOC);
00576     test_mem_pool_free_realloc_last_complex<T, numOfEntries>(CALLOC);
00577 }
00578 
00579 template<typename T, const uint32_t numOfEntries>
00580 void test_mem_pool_alloc_fail_wrapper()
00581 {
00582     test_mem_pool_alloc_fail<T, numOfEntries>(ALLOC);
00583     test_mem_pool_alloc_fail<T, numOfEntries>(CALLOC);
00584 }
00585 
00586 Case cases[] = {
00587     Case("Test: alloc()/calloc() - success, 4 bytes b_type, q_size equal to 1.", test_mem_pool_alloc_success_wrapper<int, 1>),
00588     Case("Test: alloc()/calloc() - success, 4 bytes b_type, q_size equal to 3.", test_mem_pool_alloc_success_wrapper<int, 3>),
00589     Case("Test: alloc()/calloc() - success, 1 bytes b_type, q_size equal to 1.", test_mem_pool_alloc_success_wrapper<char, 1>),
00590     Case("Test: alloc()/calloc() - success, 1 bytes b_type, q_size equal to 3.", test_mem_pool_alloc_success_wrapper<char, 3>),
00591     Case("Test: alloc()/calloc() - success, complex b_type, q_size equal to 1.", test_mem_pool_alloc_success_complex_wrapper<COMPLEX_TYPE, 1>),
00592     Case("Test: alloc()/calloc() - success, complex b_type, q_size equal to 3.", test_mem_pool_alloc_success_complex_wrapper<COMPLEX_TYPE, 3>),
00593 
00594     Case("Test: free() - success, 4 bytes b_type, q_size equal to 1.", test_mem_pool_free_success_wrapper<int, 1>),
00595     Case("Test: free() - success, 4 bytes b_type, q_size equal to 3.", test_mem_pool_free_success_wrapper<int, 3>),
00596     Case("Test: free() - success, complex b_type, q_size equal to 1.", test_mem_pool_free_success_wrapper<COMPLEX_TYPE, 1>),
00597     Case("Test: free() - success, complex b_type, q_size equal to 3.", test_mem_pool_free_success_wrapper<COMPLEX_TYPE, 3>),
00598 
00599     Case("Test: re-allocation of the last block, basic type.", test_mem_pool_free_realloc_last_wrapper<int, 3>),
00600     Case("Test: re-allocation of the first block, basic type.", test_mem_pool_free_realloc_first_wrapper<int, 3>),
00601     Case("Test: re-allocation of the first block, complex type.", test_mem_pool_free_realloc_first_complex_wrapper<COMPLEX_TYPE, 3>),
00602     Case("Test: re-allocation of the last block, complex type.", test_mem_pool_free_realloc_last_complex_wrapper<COMPLEX_TYPE, 3>),
00603 
00604     Case("Test: fail (out of free blocks).", test_mem_pool_alloc_fail_wrapper<int, 3>),
00605 
00606     Case("Test: free() - robust (free block twice).", test_mem_pool_free_on_freed_block),
00607     Case("Test: free() - robust (free called with invalid param - NULL).", free_block_invalid_parameter_null),
00608     Case("Test: free() - robust (free called with invalid param).", free_block_invalid_parameter)
00609 };
00610 
00611 utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
00612 {
00613     GREENTEA_SETUP(20, "default_auto");
00614     return greentea_test_setup_handler(number_of_cases);
00615 }
00616 
00617 Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
00618 
00619 int main()
00620 {
00621     Harness::run(specification);
00622 }
00623