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 #include "rtos.h"
00021 
00022 #if defined(MBED_RTOS_SINGLE_THREAD)
00023   #error [NOT_SUPPORTED] test not supported
00024 #endif
00025 
00026 using namespace utest::v1;
00027 
00028 #define THREAD_STACK_SIZE 512
00029 #define TEST_UINT_MSG 0xDEADBEEF
00030 #define TEST_UINT_MSG2 0xE1EE7
00031 #define TEST_TIMEOUT 50
00032 
00033 template <uint32_t ms>
00034 void thread_put_uint_msg(Queue<uint32_t, 1> *q)
00035 {
00036     Thread::wait(ms);
00037     osStatus stat = q->put((uint32_t*) TEST_UINT_MSG);
00038     TEST_ASSERT_EQUAL(osOK, stat);
00039 }
00040 
00041 template <uint32_t ms, uint32_t val>
00042 void thread_get_uint_msg(Queue<uint32_t, 1> *q)
00043 {
00044     Thread::wait(ms);
00045     osEvent evt = q->get();
00046     TEST_ASSERT_EQUAL(osEventMessage, evt.status);
00047     TEST_ASSERT_EQUAL(val, evt.value.v);
00048 }
00049 
00050 /** Test pass uint msg
00051 
00052     Given a queue for uint32_t messages with one slot
00053     When a uin32_t value is inserted into the queue
00054         and a message is extracted from the queue
00055     Then the extracted message is the same as previously inserted message
00056  */
00057 void test_pass_uint()
00058 {
00059     Queue<uint32_t, 1> q;
00060     osStatus stat = q.put((uint32_t*)TEST_UINT_MSG);
00061     TEST_ASSERT_EQUAL(osOK, stat);
00062 
00063     osEvent evt = q.get();
00064     TEST_ASSERT_EQUAL(osEventMessage, evt.status);
00065     TEST_ASSERT_EQUAL(TEST_UINT_MSG, evt.value.v);
00066 }
00067 
00068 /** Test pass uint msg twice
00069 
00070     Given a queue for uint32_t messages with one slot
00071     When a uin32_t value is inserted into the queue
00072         and a message is extracted from the queue
00073         and the procedure is repeated with different message
00074     Then the extracted message is the same as previously inserted message for both iterations
00075 
00076  */
00077 void test_pass_uint_twice()
00078 {
00079     Queue<uint32_t, 1> q;
00080     osStatus stat = q.put((uint32_t*)TEST_UINT_MSG);
00081     TEST_ASSERT_EQUAL(osOK, stat);
00082 
00083     osEvent evt = q.get();
00084     TEST_ASSERT_EQUAL(osEventMessage, evt.status);
00085     TEST_ASSERT_EQUAL(TEST_UINT_MSG, evt.value.v);
00086 
00087     stat = q.put((uint32_t*)TEST_UINT_MSG2);
00088     TEST_ASSERT_EQUAL(osOK, stat);
00089 
00090     evt = q.get();
00091     TEST_ASSERT_EQUAL(osEventMessage, evt.status);
00092     TEST_ASSERT_EQUAL(TEST_UINT_MSG2, evt.value.v);
00093 }
00094 
00095 /** Test pass ptr msg
00096 
00097     Given a queue for pointers to uint32_t messages with one slot
00098     When a pointer to an uint32_t is inserted into the queue
00099         and a message is extracted from the queue
00100     Then the extracted message is the same as previously inserted message
00101  */
00102 void test_pass_ptr()
00103 {
00104     Queue<uint32_t, 1> q;
00105     uint32_t msg = TEST_UINT_MSG;
00106 
00107     osStatus stat = q.put(&msg);
00108     TEST_ASSERT_EQUAL(osOK, stat);
00109 
00110     osEvent evt = q.get();
00111     TEST_ASSERT_EQUAL(osEventMessage, evt.status);
00112     TEST_ASSERT_EQUAL(&msg, evt.value.p);
00113 }
00114 
00115 /** Test get from empty queue
00116 
00117     Given an empty queue for uint32_t values
00118     When @a get is called on the queue with timeout of 0
00119     Then queue returns status of osOK, but no data
00120  */
00121 void test_get_empty_no_timeout()
00122 {
00123     Queue<uint32_t, 1> q;
00124 
00125     osEvent evt = q.get(0);
00126     TEST_ASSERT_EQUAL(osOK, evt.status);
00127 }
00128 
00129 /** Test get from empty queue with timeout
00130 
00131     Given an empty queue for uint32_t values
00132     When @a get is called on the queue with timeout of 50ms
00133     Then queue returns status of osEventTimeout after about 50ms wait
00134  */
00135 void test_get_empty_timeout()
00136 {
00137     Queue<uint32_t, 1> q;
00138     Timer timer;
00139     timer.start();
00140 
00141     osEvent evt = q.get(50);
00142     TEST_ASSERT_EQUAL(osEventTimeout, evt.status);
00143     TEST_ASSERT_UINT32_WITHIN(5000, 50000, timer.read_us());
00144 }
00145 
00146 /** Test get empty wait forever
00147 
00148     Given a two threads A & B and a queue for uint32_t values
00149     When thread A calls @a get on an empty queue with osWaitForever
00150     Then the thread A waits for a message to appear in the queue
00151     When thread B puts a message in the queue
00152     Then thread A wakes up and receives it
00153  */
00154 void test_get_empty_wait_forever()
00155 {
00156     Thread t(osPriorityNormal, THREAD_STACK_SIZE);
00157     Queue<uint32_t, 1> q;
00158 
00159     t.start(callback(thread_put_uint_msg<TEST_TIMEOUT>, &q));
00160 
00161     Timer timer;
00162     timer.start();
00163 
00164     osEvent evt = q.get();
00165     TEST_ASSERT_EQUAL(osEventMessage, evt.status);
00166     TEST_ASSERT_EQUAL(TEST_UINT_MSG, evt.value.v);
00167     TEST_ASSERT_UINT32_WITHIN(TEST_TIMEOUT * 100, TEST_TIMEOUT * 1000, timer.read_us());
00168 }
00169 
00170 /** Test put full no timeout
00171  *
00172  * Given a queue with one slot for uint32_t data
00173  * When a thread tries to insert two messages
00174  * Then first operation succeeds and second fails with @a osErrorResource
00175  */
00176 void test_put_full_no_timeout()
00177 {
00178     Queue<uint32_t, 1> q;
00179 
00180     osStatus stat = q.put((uint32_t*) TEST_UINT_MSG);
00181     TEST_ASSERT_EQUAL(osOK, stat);
00182 
00183     stat = q.put((uint32_t*) TEST_UINT_MSG);
00184     TEST_ASSERT_EQUAL(osErrorResource, stat);
00185 }
00186 
00187 /** Test put full timeout
00188  *
00189  * Given a queue with one slot for uint32_t data
00190  * When a thread tries to insert two messages with @ TEST_TIMEOUT timeout
00191  * Then first operation succeeds and second fails with @a osErrorTimeout
00192  */
00193 void test_put_full_timeout()
00194 {
00195     Queue<uint32_t, 1> q;
00196 
00197     osStatus stat = q.put((uint32_t*) TEST_UINT_MSG, TEST_TIMEOUT);
00198     TEST_ASSERT_EQUAL(osOK, stat);
00199 
00200     Timer timer;
00201     timer.start();
00202 
00203     stat = q.put((uint32_t*) TEST_UINT_MSG, TEST_TIMEOUT);
00204     TEST_ASSERT_EQUAL(osErrorTimeout, stat);
00205     TEST_ASSERT_UINT32_WITHIN(TEST_TIMEOUT * 100, TEST_TIMEOUT * 1000, timer.read_us());
00206 }
00207 
00208 /** Test put full wait forever
00209  *
00210  * Given two threads A & B and a queue with one slot for uint32_t data
00211  * When thread A puts a message to the queue and tries to put second one with @a osWaitForever timeout
00212  * Then thread waits for a slot to become empty in the queue
00213  * When thread B takes one message out of the queue
00214  * Then thread A successfully inserts message into the queue
00215  */
00216 void test_put_full_waitforever()
00217 {
00218     Thread t(osPriorityNormal, THREAD_STACK_SIZE);
00219     Queue<uint32_t, 1> q;
00220 
00221     t.start(callback(thread_get_uint_msg<TEST_TIMEOUT, TEST_UINT_MSG>, &q));
00222 
00223     osStatus stat = q.put((uint32_t*) TEST_UINT_MSG);
00224     TEST_ASSERT_EQUAL(osOK, stat);
00225 
00226     Timer timer;
00227     timer.start();
00228     stat = q.put((uint32_t*) TEST_UINT_MSG, osWaitForever);
00229     TEST_ASSERT_EQUAL(osOK, stat);
00230     TEST_ASSERT_UINT32_WITHIN(TEST_TIMEOUT * 100, TEST_TIMEOUT * 1000, timer.read_us());
00231 
00232     t.join();
00233 }
00234 
00235 /** Test message ordering
00236 
00237     Given a queue of uint32_t data
00238     When two messages are inserted with equal priority
00239     Then messages should be returned in the exact order they were inserted
00240  */
00241 void test_msg_order()
00242 {
00243     Queue<uint32_t, 2> q;
00244 
00245     osStatus stat = q.put((uint32_t*) TEST_UINT_MSG, TEST_TIMEOUT);
00246     TEST_ASSERT_EQUAL(osOK, stat);
00247 
00248     stat = q.put((uint32_t*) TEST_UINT_MSG2, TEST_TIMEOUT);
00249     TEST_ASSERT_EQUAL(osOK, stat);
00250 
00251     osEvent evt = q.get();
00252     TEST_ASSERT_EQUAL(osEventMessage, evt.status);
00253     TEST_ASSERT_EQUAL(TEST_UINT_MSG, evt.value.v);
00254 
00255     evt = q.get();
00256     TEST_ASSERT_EQUAL(osEventMessage, evt.status);
00257     TEST_ASSERT_EQUAL(TEST_UINT_MSG2, evt.value.v);
00258 }
00259 
00260 /** Test message priority
00261 
00262     Given a queue of uint32_t data
00263     When two messages are inserted with ascending priority
00264     Then messages should be returned in descending priority order
00265  */
00266 void test_msg_prio()
00267 {
00268     Queue<uint32_t, 2> q;
00269 
00270     osStatus stat = q.put((uint32_t*) TEST_UINT_MSG, TEST_TIMEOUT, 0);
00271     TEST_ASSERT_EQUAL(osOK, stat);
00272 
00273     stat = q.put((uint32_t*) TEST_UINT_MSG2, TEST_TIMEOUT, 1);
00274     TEST_ASSERT_EQUAL(osOK, stat);
00275 
00276     osEvent evt = q.get();
00277     TEST_ASSERT_EQUAL(osEventMessage, evt.status);
00278     TEST_ASSERT_EQUAL(TEST_UINT_MSG2, evt.value.v);
00279 
00280     evt = q.get();
00281     TEST_ASSERT_EQUAL(osEventMessage, evt.status);
00282     TEST_ASSERT_EQUAL(TEST_UINT_MSG, evt.value.v);
00283 }
00284 
00285 /** Test queue empty
00286 
00287     Given a queue of uint32_t data
00288     before data is inserted the queue should be empty
00289     after data is inserted the queue shouldn't be empty
00290  */
00291 void test_queue_empty()
00292 {
00293     Queue<uint32_t, 1> q;
00294 
00295     TEST_ASSERT_EQUAL(true, q.empty());
00296 
00297     q.put((uint32_t*) TEST_UINT_MSG, TEST_TIMEOUT, 1);
00298 
00299     TEST_ASSERT_EQUAL(false, q.empty());
00300 }
00301 
00302 /** Test queue empty
00303 
00304     Given a queue of uint32_t data with size of 1
00305     before data is inserted the queue shouldn't be full
00306     after data is inserted the queue should be full
00307  */
00308 void test_queue_full()
00309 {
00310     Queue<uint32_t, 1> q;
00311 
00312     TEST_ASSERT_EQUAL(false, q.full());
00313 
00314     q.put((uint32_t*) TEST_UINT_MSG, TEST_TIMEOUT, 1);
00315 
00316     TEST_ASSERT_EQUAL(true, q.full());
00317 }
00318 
00319 utest::v1::status_t test_setup(const size_t number_of_cases)
00320 {
00321     GREENTEA_SETUP(5, "default_auto");
00322     return verbose_test_setup_handler(number_of_cases);
00323 }
00324 
00325 Case cases[] = {
00326     Case("Test pass uint msg", test_pass_uint),
00327     Case("Test pass uint msg twice", test_pass_uint_twice),
00328     Case("Test pass ptr msg", test_pass_ptr),
00329     Case("Test get from empty queue no timeout", test_get_empty_no_timeout),
00330     Case("Test get from empty queue timeout", test_get_empty_timeout),
00331     Case("Test get empty wait forever", test_get_empty_wait_forever),
00332     Case("Test put full no timeout", test_put_full_no_timeout),
00333     Case("Test put full timeout", test_put_full_timeout),
00334     Case("Test put full wait forever", test_put_full_waitforever),
00335     Case("Test message ordering", test_msg_order),
00336     Case("Test message priority", test_msg_prio),
00337     Case("Test queue empty", test_queue_empty),
00338     Case("Test queue full", test_queue_full)
00339 };
00340 
00341 Specification specification(test_setup, cases);
00342 
00343 int main()
00344 {
00345     return !Harness::run(specification);
00346 }