Marco Zecchini
/
Example_RTOS
Rtos API example
Embed:
(wiki syntax)
Show/hide line numbers
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
Generated on Sun Jul 17 2022 08:25:27 by 1.7.2