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