Skip to content

Commit 5a158d6

Browse files
committed
Tests: Drivers: LowPowerTimeout: Update tests
Added unit tests for LowPowerTimeout API.
1 parent c6f655c commit 5a158d6

File tree

1 file changed

+204
-5
lines changed

1 file changed

+204
-5
lines changed

TESTS/mbed_drivers/lp_timeout/main.cpp

Lines changed: 204 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,205 @@
1515
*/
1616

1717
#if !DEVICE_LOWPOWERTIMER
18-
#error [NOT_SUPPORTED] Low power timer not supported for this target
18+
#error [NOT_SUPPORTED] Low power timer not supported for this target
1919
#endif
2020

2121
#include "utest/utest.h"
2222
#include "unity/unity.h"
2323
#include "greentea-client/test_env.h"
2424

2525
#include "mbed.h"
26+
#include "rtos.h"
2627

2728
using namespace utest::v1;
2829

30+
#define NUM_TIMEOUTS 64
31+
const float TEST_DELAY_S = 0.01;
32+
const uint32_t TEST_DELAY_MS = 1000.0F * TEST_DELAY_S;
33+
const us_timestamp_t TEST_DELAY_US = 1000000.0F * TEST_DELAY_S;
34+
35+
void sem_callback(Semaphore *sem)
36+
{
37+
sem->release();
38+
}
39+
40+
void cnt_callback(volatile uint32_t *cnt)
41+
{
42+
(*cnt)++;
43+
}
44+
45+
class TimeoutAttachUSTester: public LowPowerTimeout {
46+
public:
47+
void attach_callback(Callback<void()> func, us_timestamp_t delay_us)
48+
{
49+
attach_us(func, delay_us);
50+
}
51+
};
52+
53+
class TimeoutAttachTester: public LowPowerTimeout {
54+
public:
55+
void attach_callback(Callback<void()> func, us_timestamp_t delay_us)
56+
{
57+
attach(func, (float) delay_us / 1000000.0f);
58+
}
59+
};
60+
61+
/** Template for tests: callback called once
62+
*
63+
* Test callback called once
64+
* Given a LowPowerTimeout object with a callback attached with @a attach()
65+
* When given time elapses
66+
* Then the callback is called exactly one time
67+
*
68+
* Test callback called once
69+
* Given a LowPowerTimeout object with a callback attached with @a attach_us()
70+
* When given time elapses
71+
* Then the callback is called exactly one time
72+
*/
73+
template<typename T>
74+
void test_callback_fires_once(void)
75+
{
76+
Semaphore sem(0, 1);
77+
T timeout;
78+
79+
timeout.attach_callback(mbed::callback(sem_callback, &sem), TEST_DELAY_US);
80+
81+
int32_t sem_slots = sem.wait(0);
82+
TEST_ASSERT_EQUAL(0, sem_slots);
83+
84+
sem_slots = sem.wait(TEST_DELAY_MS + 1);
85+
TEST_ASSERT_EQUAL(1, sem_slots);
86+
87+
sem_slots = sem.wait(TEST_DELAY_MS + 1);
88+
TEST_ASSERT_EQUAL(0, sem_slots);
89+
90+
timeout.detach();
91+
}
92+
93+
/** Template for tests: callback not called when cancelled
94+
*
95+
* Test callback not called when cancelled
96+
* Given a LowPowerTimeout object with a callback attached with @a attach()
97+
* When the callback is detached before being called
98+
* Then the callback is never called
99+
*
100+
* Test callback not called when cancelled
101+
* Given a LowPowerTimeout object with a callback attached with @a attach_us()
102+
* When the callback is detached before being called
103+
* Then the callback is never called
104+
*/
105+
template<typename T>
106+
void test_cancel(void)
107+
{
108+
Semaphore sem(0, 1);
109+
T timeout;
110+
111+
timeout.attach_callback(mbed::callback(sem_callback, &sem), 2.0f * TEST_DELAY_US);
112+
113+
int32_t sem_slots = sem.wait(TEST_DELAY_MS);
114+
TEST_ASSERT_EQUAL(0, sem_slots);
115+
timeout.detach();
116+
117+
sem_slots = sem.wait(TEST_DELAY_MS + 1);
118+
TEST_ASSERT_EQUAL(0, sem_slots);
119+
}
120+
121+
/** Template for tests: callback override
122+
*
123+
* Test callback override
124+
* Given a LowPowerTimeout object with a callback attached with @a attach()
125+
* When another callback is attached before first one is called
126+
* and second callback's delay elapses
127+
* Then the second callback is called
128+
* and the first callback is never called
129+
*
130+
* Test callback override
131+
* Given a LowPowerTimeout object with a callback attached with @a attach_us()
132+
* When another callback is attached before first one is called
133+
* and second callback's delay elapses
134+
* Then the second callback is called
135+
* and the first callback is never called
136+
*/
137+
template<typename T>
138+
void test_override(void)
139+
{
140+
Semaphore sem1(0, 1);
141+
Semaphore sem2(0, 1);
142+
T timeout;
143+
144+
timeout.attach_callback(mbed::callback(sem_callback, &sem1), 2.0f * TEST_DELAY_US);
145+
146+
int32_t sem_slots = sem1.wait(TEST_DELAY_MS);
147+
TEST_ASSERT_EQUAL(0, sem_slots);
148+
timeout.attach_callback(mbed::callback(sem_callback, &sem2), 2.0f * TEST_DELAY_US);
149+
150+
sem_slots = sem2.wait(2 * TEST_DELAY_MS + 1);
151+
TEST_ASSERT_EQUAL(1, sem_slots);
152+
sem_slots = sem1.wait(0);
153+
TEST_ASSERT_EQUAL(0, sem_slots);
154+
155+
timeout.detach();
156+
}
157+
158+
/** Template for tests: multiple LowPowerTimeouts
159+
*
160+
* Test multiple LowPowerTimeouts
161+
* Given multiple separate LowPowerTimeout objects
162+
* When a callback is attached to all of these LowPowerTimeout objects with @a attach()
163+
* and delay for every LowPowerTimeout elapses
164+
* Then all callbacks are called
165+
*
166+
* Test multiple LowPowerTimeouts
167+
* Given multiple separate LowPowerTimeout objects
168+
* When a callback is attached to all of these LowPowerTimeout objects with @a attach_us()
169+
* and delay for every LowPowerTimeout elapses
170+
* Then all callbacks are called
171+
*/
172+
template<typename T>
173+
void test_multiple(void)
174+
{
175+
volatile uint32_t callback_count = 0;
176+
T timeouts[NUM_TIMEOUTS];
177+
for (size_t i = 0; i < NUM_TIMEOUTS; i++) {
178+
timeouts[i].attach_callback(mbed::callback(cnt_callback, &callback_count), TEST_DELAY_US);
179+
}
180+
Thread::wait(TEST_DELAY_MS + 1);
181+
TEST_ASSERT_EQUAL(NUM_TIMEOUTS, callback_count);
182+
}
183+
184+
/** Template for tests: zero delay
185+
*
186+
* Test zero delay
187+
* Given a LowPowerTimeout object
188+
* When a callback is attached with 0.0 s delay, with @a attach()
189+
* Then the callback is called instantly
190+
*
191+
* Test zero delay
192+
* Given a LowPowerTimeout object
193+
* When a callback is attached with 0.0 s delay, with @a attach_us()
194+
* Then the callback is called instantly
195+
*/
196+
template<typename T>
197+
void test_no_wait(void)
198+
{
199+
Semaphore sem(0, 1);
200+
T timeout;
201+
timeout.attach_callback(mbed::callback(sem_callback, &sem), 0ULL);
202+
203+
int32_t sem_slots = sem.wait(0);
204+
TEST_ASSERT_EQUAL(1, sem_slots);
205+
timeout.detach();
206+
}
207+
29208
volatile static bool complete;
30209
static LowPowerTimeout lpt;
31210

32211
/* Timeouts are quite arbitrary due to large number of boards with varying level of accuracy */
33212
#define LONG_TIMEOUT (100000)
34213
#define SHORT_TIMEOUT (600)
35214

36-
void cb_done() {
215+
void cb_done()
216+
{
37217
complete = true;
38218
}
39219

@@ -119,29 +299,48 @@ void lp_timeout_500us(void)
119299

120300
}
121301

122-
utest::v1::status_t greentea_failure_handler(const Case *const source, const failure_t reason) {
302+
utest::v1::status_t greentea_failure_handler(const Case * const source, const failure_t reason)
303+
{
123304
greentea_case_failure_abort_handler(source, reason);
124305
return STATUS_CONTINUE;
125306
}
126307

127308
Case cases[] = {
309+
Case("Test callback called once (with attach)", test_callback_fires_once<TimeoutAttachTester>),
310+
Case("Test callback called once (with attach_us)", test_callback_fires_once<TimeoutAttachUSTester>),
311+
312+
Case("Test callback not called when cancelled (with attach)", test_cancel<TimeoutAttachTester>),
313+
Case("Test callback not called when cancelled (with attach_us)", test_cancel<TimeoutAttachUSTester>),
314+
315+
Case("Test callback override (with attach)", test_override<TimeoutAttachTester>),
316+
Case("Test callback override (with attach_us)", test_override<TimeoutAttachUSTester>),
317+
318+
Case("Test multiple timeouts running in parallel (with attach)", test_multiple<TimeoutAttachTester>),
319+
Case("Test multiple timeouts running in parallel (with attach_us)", test_multiple<TimeoutAttachUSTester>),
320+
321+
Case("Test zero delay (with attach)", test_no_wait<TimeoutAttachTester>),
322+
Case("Test zero delay (with attach_us)", test_no_wait<TimeoutAttachUSTester>),
323+
128324
Case("500us LowPowerTimeout", lp_timeout_500us, greentea_failure_handler),
129325
Case("1ms LowPowerTimeout", lp_timeout_1ms, greentea_failure_handler),
130326
Case("1sec LowPowerTimeout", lp_timeout_1s, greentea_failure_handler),
131327
Case("5sec LowPowerTimeout", lp_timeout_5s, greentea_failure_handler),
328+
132329
#if DEVICE_SLEEP
133330
Case("1sec LowPowerTimeout from sleep", lp_timeout_1s_sleep, greentea_failure_handler),
134331
Case("1sec LowPowerTimeout from deepsleep", lp_timeout_1s_deepsleep, greentea_failure_handler),
135332
#endif /* DEVICE_SLEEP */
136333
};
137334

138-
utest::v1::status_t greentea_test_setup(const size_t number_of_cases) {
335+
utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
336+
{
139337
GREENTEA_SETUP(20, "default_auto");
140338
return greentea_test_setup_handler(number_of_cases);
141339
}
142340

143341
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
144342

145-
int main() {
343+
int main()
344+
{
146345
Harness::run(specification);
147346
}

0 commit comments

Comments
 (0)