Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 #include "rtos.h" 00021 00022 #if defined(MBED_RTOS_SINGLE_THREAD) 00023 #error [NOT_SUPPORTED] test not supported 00024 #endif 00025 00026 #if !DEVICE_USTICKER 00027 #error [NOT_SUPPORTED] test not supported 00028 #endif 00029 00030 using namespace utest::v1; 00031 00032 #define THREAD_STACK_SIZE 320 /* larger stack cause out of heap memory on some 16kB RAM boards in multi thread test*/ 00033 #define QUEUE_SIZE 16 00034 #define THREAD_1_ID 1 00035 #define THREAD_2_ID 2 00036 #define THREAD_3_ID 3 00037 #define QUEUE_PUT_DELAY_1 5 00038 #define QUEUE_PUT_DELAY_2 50 00039 #define QUEUE_PUT_DELAY_3 100 00040 #define DATA_BASE 100 00041 00042 00043 typedef struct { 00044 uint16_t data; 00045 uint8_t thread_id; 00046 } mail_t; 00047 00048 00049 template<uint8_t thread_id, uint32_t wait_ms, uint32_t send_count> 00050 void send_thread(Mail<mail_t, QUEUE_SIZE> *m) 00051 { 00052 uint32_t data = thread_id * DATA_BASE; 00053 00054 for (uint32_t i = 0; i < send_count; i++) { 00055 mail_t *mail = m->alloc(); 00056 mail->thread_id = thread_id; 00057 mail->data = data++; 00058 m->put(mail); 00059 Thread::wait(wait_ms); 00060 } 00061 } 00062 00063 template<uint8_t thread_id, uint32_t queue_size, uint32_t wait_ms> 00064 void receive_thread(Mail<mail_t, queue_size> *m) 00065 { 00066 int result_counter = 0; 00067 uint32_t data = thread_id * DATA_BASE; 00068 00069 Thread::wait(wait_ms); 00070 for (uint32_t i = 0; i < queue_size; i++) { 00071 osEvent evt = m->get(); 00072 if (evt.status == osEventMail) { 00073 mail_t *mail = (mail_t*)evt.value.p; 00074 const uint8_t id = mail->thread_id; 00075 00076 // verify thread id 00077 TEST_ASSERT_TRUE(id == thread_id); 00078 // verify sent data 00079 TEST_ASSERT_TRUE(mail->data == data++); 00080 00081 m->free(mail); 00082 result_counter++; 00083 } 00084 } 00085 TEST_ASSERT_EQUAL(queue_size, result_counter); 00086 } 00087 00088 /** Test single thread Mail usage and order 00089 00090 Given mailbox and one additional thread 00091 When messages are put in to the Mail box by this thread 00092 Then messages are received in main thread in the same order as was sent and the data sent is valid 00093 */ 00094 void test_single_thread_order(void) 00095 { 00096 uint16_t data = DATA_BASE; 00097 int result_counter = 0; 00098 Mail<mail_t, QUEUE_SIZE> mail_box; 00099 00100 // mail send thread creation 00101 Thread thread(osPriorityNormal, THREAD_STACK_SIZE); 00102 thread.start(callback(send_thread<THREAD_1_ID, QUEUE_PUT_DELAY_1, QUEUE_SIZE>, &mail_box)); 00103 00104 // wait for some mail to be collected 00105 Thread::wait(10); 00106 00107 for (uint32_t i = 0; i < QUEUE_SIZE; i++) { 00108 // mail receive (main thread) 00109 osEvent evt = mail_box.get(); 00110 if (evt.status == osEventMail) { 00111 mail_t *mail = (mail_t*)evt.value.p; 00112 const uint8_t id = mail->thread_id; 00113 00114 // verify thread id 00115 TEST_ASSERT_TRUE(id == THREAD_1_ID); 00116 // verify sent data 00117 TEST_ASSERT_TRUE(mail->data == data++); 00118 mail_box.free(mail); 00119 00120 result_counter++; 00121 } 00122 } 00123 TEST_ASSERT_EQUAL(QUEUE_SIZE, result_counter); 00124 } 00125 00126 /** Test multi thread Mail usage and order 00127 00128 Given mailbox and three additional threads 00129 When messages are put in to the Mail box by these threads 00130 Then messages are received in main thread in the same per thread order as was sent and the data sent is valid 00131 */ 00132 void test_multi_thread_order(void) 00133 { 00134 uint16_t data[4] = { 0, DATA_BASE, DATA_BASE * 2, DATA_BASE * 3 }; 00135 int result_counter = 0; 00136 Mail<mail_t, QUEUE_SIZE> mail_box; 00137 00138 // mail send threads creation 00139 Thread thread1(osPriorityNormal, THREAD_STACK_SIZE); 00140 Thread thread2(osPriorityNormal, THREAD_STACK_SIZE); 00141 Thread thread3(osPriorityNormal, THREAD_STACK_SIZE); 00142 thread1.start(callback(send_thread<THREAD_1_ID, QUEUE_PUT_DELAY_1, 7>, &mail_box)); 00143 thread2.start(callback(send_thread<THREAD_2_ID, QUEUE_PUT_DELAY_2, 5>, &mail_box)); 00144 thread3.start(callback(send_thread<THREAD_3_ID, QUEUE_PUT_DELAY_3, 4>, &mail_box)); 00145 00146 // wait for some mail to be collected 00147 Thread::wait(10); 00148 00149 for (uint32_t i = 0; i < QUEUE_SIZE; i++) { 00150 // mail receive (main thread) 00151 osEvent evt = mail_box.get(); 00152 if (evt.status == osEventMail) { 00153 mail_t *mail = (mail_t*)evt.value.p; 00154 const uint8_t id = mail->thread_id; 00155 00156 // verify thread id 00157 TEST_ASSERT_TRUE((id == THREAD_1_ID) || (id == THREAD_2_ID) || (id == THREAD_3_ID)); 00158 // verify sent data 00159 TEST_ASSERT_TRUE(mail->data == data[id]++); 00160 mail_box.free(mail); 00161 00162 result_counter++; 00163 } 00164 } 00165 TEST_ASSERT_EQUAL(QUEUE_SIZE, result_counter); 00166 } 00167 00168 /** Test multi thread multi Mail usage and order 00169 00170 Given 3 mailbox and three additional threads 00171 When messages are put in to the mail boxes by main thread 00172 Then messages are received by threads in the same per mail box order as was sent and the data sent is valid 00173 */ 00174 void test_multi_thread_multi_mail_order(void) 00175 { 00176 Mail<mail_t, 4> mail_box[4]; /* mail_box[0] not used */ 00177 uint16_t data[4] = { 0, DATA_BASE, DATA_BASE * 2, DATA_BASE * 3 }; 00178 mail_t *mail; 00179 uint8_t id; 00180 00181 // mail receive threads creation 00182 Thread thread1(osPriorityNormal, THREAD_STACK_SIZE); 00183 Thread thread2(osPriorityNormal, THREAD_STACK_SIZE); 00184 Thread thread3(osPriorityNormal, THREAD_STACK_SIZE); 00185 thread1.start(callback(receive_thread<THREAD_1_ID, 4, 0>, mail_box + 1)); 00186 thread2.start(callback(receive_thread<THREAD_2_ID, 4, 10>, mail_box + 2)); 00187 thread3.start(callback(receive_thread<THREAD_3_ID, 4, 100>, mail_box + 3)); 00188 00189 for (uint32_t i = 0; i < 4; i++) { 00190 id = THREAD_1_ID; 00191 mail = mail_box[id].alloc(); 00192 mail->thread_id = id; 00193 mail->data = data[id]++; 00194 mail_box[id].put(mail); 00195 00196 id = THREAD_2_ID; 00197 mail = mail_box[id].alloc(); 00198 mail->thread_id = id; 00199 mail->data = data[id]++; 00200 mail_box[id].put(mail); 00201 00202 id = THREAD_3_ID; 00203 mail = mail_box[id].alloc(); 00204 mail->thread_id = id; 00205 mail->data = data[id]++; 00206 mail_box[id].put(mail); 00207 00208 Thread::wait(i * 10); 00209 } 00210 00211 thread1.join(); 00212 thread2.join(); 00213 thread3.join(); 00214 } 00215 00216 /** Test message memory deallocation with block out of the scope 00217 00218 Given an empty mailbox 00219 When try to free out of the scope memory block 00220 Then it return appropriate error code 00221 */ 00222 void test_free_wrong() 00223 { 00224 osStatus status; 00225 Mail<uint32_t, 4> mail_box; 00226 uint32_t *mail, data; 00227 00228 mail = &data; 00229 status = mail_box.free(mail); 00230 TEST_ASSERT_EQUAL(osErrorParameter, status); 00231 00232 mail = mail_box.alloc(); 00233 TEST_ASSERT_NOT_EQUAL(NULL, mail); 00234 00235 mail = &data; 00236 status = mail_box.free(mail); 00237 TEST_ASSERT_EQUAL(osErrorParameter, status); 00238 } 00239 00240 /** Test message memory deallocation with null block 00241 00242 Given an empty mailbox 00243 When try to free null ptr 00244 Then it return appropriate error code 00245 */ 00246 void test_free_null() 00247 { 00248 osStatus status; 00249 Mail<uint32_t, 4> mail_box; 00250 uint32_t *mail; 00251 00252 mail = NULL; 00253 status = mail_box.free(mail); 00254 TEST_ASSERT_EQUAL(osErrorParameter, status); 00255 00256 mail = mail_box.alloc(); 00257 TEST_ASSERT_NOT_EQUAL(NULL, mail); 00258 00259 mail = NULL; 00260 status = mail_box.free(mail); 00261 TEST_ASSERT_EQUAL(osErrorParameter, status); 00262 } 00263 00264 /** Test same message memory deallocation twice 00265 00266 Given an empty mailbox 00267 Then allocate message memory 00268 When try to free it second time 00269 Then it return appropriate error code 00270 */ 00271 void test_free_twice() 00272 { 00273 osStatus status; 00274 Mail<uint32_t, 4> mail_box; 00275 00276 uint32_t *mail = mail_box.alloc(); 00277 TEST_ASSERT_NOT_EQUAL(NULL, mail); 00278 00279 status = mail_box.free(mail); 00280 TEST_ASSERT_EQUAL(osOK, status); 00281 00282 status = mail_box.free(mail); 00283 TEST_ASSERT_EQUAL(osErrorResource, status); 00284 } 00285 00286 /** Test get from empty mailbox with timeout set 00287 00288 Given an empty mailbox 00289 When @a get is called on the mailbox with timeout of 50 00290 Then mailbox returns status of osOK, but no data after specified amount of time 00291 */ 00292 void test_get_empty_timeout() 00293 { 00294 Mail<uint32_t, 4> mail_box; 00295 Timer timer; 00296 00297 timer.start(); 00298 osEvent evt = mail_box.get(50); 00299 TEST_ASSERT_UINT32_WITHIN(5000, 50000, timer.read_us()); 00300 TEST_ASSERT_EQUAL(osEventTimeout, evt.status); 00301 } 00302 00303 /** Test get from empty mailbox with 0 timeout 00304 00305 Given an empty mailbox 00306 When @a get is called on the mailbox with timeout of 0 00307 Then mailbox returns status of osOK, but no data 00308 */ 00309 void test_get_empty_no_timeout() 00310 { 00311 Mail<uint32_t, 4> mail_box; 00312 00313 osEvent evt = mail_box.get(0); 00314 TEST_ASSERT_EQUAL(osOK, evt.status); 00315 } 00316 00317 /** Test mail order 00318 00319 Given an mailbox for uint32_t values 00320 Then allocate two mails and put them in to mailbox 00321 When call @a get it returns previously put mails 00322 Then mails should be in the same order as put 00323 */ 00324 void test_order(void) 00325 { 00326 osStatus status; 00327 osEvent evt; 00328 Mail<int32_t, 4> mail_box; 00329 const int32_t TEST_VAL1 = 123; 00330 const int32_t TEST_VAL2 = 456; 00331 00332 int32_t *mail1 = mail_box.alloc(); 00333 TEST_ASSERT_NOT_EQUAL(NULL, mail1); 00334 00335 *mail1 = TEST_VAL1; 00336 status = mail_box.put(mail1); 00337 TEST_ASSERT_EQUAL(osOK, status); 00338 00339 int32_t *mail2 = mail_box.alloc(); 00340 TEST_ASSERT_NOT_EQUAL(NULL, mail2); 00341 00342 *mail2 = TEST_VAL2; 00343 status = mail_box.put(mail2); 00344 TEST_ASSERT_EQUAL(osOK, status); 00345 00346 00347 evt = mail_box.get(); 00348 TEST_ASSERT_EQUAL(evt.status, osEventMail); 00349 00350 mail1 = (int32_t*)evt.value.p; 00351 TEST_ASSERT_EQUAL(TEST_VAL1, *mail1); 00352 00353 evt = mail_box.get(); 00354 TEST_ASSERT_EQUAL(evt.status, osEventMail); 00355 00356 mail2 = (int32_t*)evt.value.p; 00357 TEST_ASSERT_EQUAL(TEST_VAL2, *mail2); 00358 00359 00360 status = mail_box.free(mail1); 00361 TEST_ASSERT_EQUAL(osOK, status); 00362 00363 status = mail_box.free(mail2); 00364 TEST_ASSERT_EQUAL(osOK, status); 00365 } 00366 00367 /** Test Mail box max size limit 00368 00369 Given an Mail box with max size of 4 elements 00370 When call @a alloc four times it returns memory blocks 00371 Then the memory blocks should be valid 00372 When call @a alloc one more time it returns memory blocks 00373 Then the memory blocks should be not valid (NULL - no memory available) 00374 */ 00375 void test_max_size() 00376 { 00377 osStatus status; 00378 Mail<uint32_t, 4> mail_box; 00379 const uint32_t TEST_VAL = 123; 00380 00381 // 1 OK 00382 uint32_t *mail1 = mail_box.alloc(); 00383 TEST_ASSERT_NOT_EQUAL(NULL, mail1); 00384 00385 // 2 OK 00386 uint32_t *mail2 = mail_box.alloc(); 00387 TEST_ASSERT_NOT_EQUAL(NULL, mail2); 00388 00389 // 3 OK 00390 uint32_t *mail3 = mail_box.alloc(); 00391 TEST_ASSERT_NOT_EQUAL(NULL, mail3); 00392 00393 // 4 OK 00394 uint32_t *mail4 = mail_box.alloc(); 00395 TEST_ASSERT_NOT_EQUAL(NULL, mail4); 00396 00397 // 5 KO 00398 uint32_t *mail5 = mail_box.alloc(); 00399 TEST_ASSERT_EQUAL(NULL, mail5); 00400 00401 00402 status = mail_box.free(mail1); 00403 TEST_ASSERT_EQUAL(osOK, status); 00404 00405 status = mail_box.free(mail2); 00406 TEST_ASSERT_EQUAL(osOK, status); 00407 00408 status = mail_box.free(mail3); 00409 TEST_ASSERT_EQUAL(osOK, status); 00410 00411 status = mail_box.free(mail4); 00412 TEST_ASSERT_EQUAL(osOK, status); 00413 } 00414 00415 /** Test mailbox of T type data 00416 00417 Given an mailbox with T memory block type 00418 When allocate/put/get/free memory block 00419 Then all operations should succeed 00420 */ 00421 template<typename T> 00422 void test_data_type(void) 00423 { 00424 osStatus status; 00425 Mail<T, 4> mail_box; 00426 const T TEST_VAL = 123; 00427 00428 T *mail = mail_box.alloc(); 00429 TEST_ASSERT_NOT_EQUAL(NULL, mail); 00430 00431 *mail = TEST_VAL; 00432 status = mail_box.put(mail); 00433 TEST_ASSERT_EQUAL(osOK, status); 00434 00435 osEvent evt = mail_box.get(); 00436 TEST_ASSERT_EQUAL(evt.status, osEventMail); 00437 00438 mail = (T*)evt.value.p; 00439 TEST_ASSERT_EQUAL(TEST_VAL, *mail); 00440 00441 00442 status = mail_box.free(mail); 00443 TEST_ASSERT_EQUAL(osOK, status); 00444 } 00445 00446 /** Test calloc - memory block allocation with resetting 00447 00448 Given an empty Mail box 00449 When call @a calloc it returns allocated memory block 00450 Then the memory block should be valid and filled with zeros 00451 */ 00452 void test_calloc() 00453 { 00454 Mail<uint32_t, 1> mail_box; 00455 00456 uint32_t *mail = mail_box.calloc(); 00457 TEST_ASSERT_NOT_EQUAL(NULL, mail); 00458 TEST_ASSERT_EQUAL(0, *mail); 00459 } 00460 00461 /** Test mail empty 00462 00463 Given a mail of uint32_t data 00464 before data is inserted the mail should be empty 00465 after data is inserted the mail shouldn't be empty 00466 */ 00467 void test_mail_empty() 00468 { 00469 Mail<mail_t, 1> m; 00470 00471 mail_t *mail = m.alloc(); 00472 00473 TEST_ASSERT_EQUAL(true, m.empty()); 00474 00475 m.put(mail); 00476 00477 TEST_ASSERT_EQUAL(false, m.empty()); 00478 } 00479 00480 /** Test mail empty 00481 00482 Given a mail of uint32_t data with size of 1 00483 before data is inserted the mail shouldn't be full 00484 after data is inserted the mail should be full 00485 */ 00486 void test_mail_full() 00487 { 00488 Mail<mail_t, 1> m; 00489 00490 mail_t *mail = m.alloc(); 00491 00492 TEST_ASSERT_EQUAL(false, m.full()); 00493 00494 m.put(mail); 00495 00496 TEST_ASSERT_EQUAL(true, m.full()); 00497 } 00498 00499 utest::v1::status_t test_setup(const size_t number_of_cases) 00500 { 00501 GREENTEA_SETUP(10, "default_auto"); 00502 return verbose_test_setup_handler(number_of_cases); 00503 } 00504 00505 Case cases[] = { 00506 Case("Test calloc", test_calloc), 00507 Case("Test message type uint8", test_data_type<uint8_t>), 00508 Case("Test message type uint16", test_data_type<uint16_t>), 00509 Case("Test message type uint32", test_data_type<uint32_t>), 00510 Case("Test mailbox max size", test_max_size), 00511 Case("Test message send order", test_order), 00512 Case("Test get with timeout on empty mailbox", test_get_empty_timeout), 00513 Case("Test get without timeout on empty mailbox", test_get_empty_no_timeout), 00514 Case("Test message free twice", test_free_twice), 00515 Case("Test null message free", test_free_null), 00516 Case("Test invalid message free", test_free_wrong), 00517 Case("Test message send/receive single thread and order", test_single_thread_order), 00518 Case("Test message send/receive multi-thread and per thread order", test_multi_thread_order), 00519 Case("Test message send/receive multi-thread, multi-Mail and per thread order", test_multi_thread_multi_mail_order), 00520 Case("Test mail empty", test_mail_empty), 00521 Case("Test mail full", test_mail_full) 00522 }; 00523 00524 Specification specification(test_setup, cases); 00525 00526 int main() 00527 { 00528 return !Harness::run(specification); 00529 }
Generated on Tue Jul 12 2022 12:45:24 by
1.7.2