Skip to content

Commit 3211cb5

Browse files
committed
Tests: Drivers: Timeout: Update tests
Added unit tests for Timeout API.
1 parent c60194f commit 3211cb5

File tree

1 file changed

+225
-33
lines changed

1 file changed

+225
-33
lines changed

TESTS/mbed_drivers/timeout/main.cpp

Lines changed: 225 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,236 @@
1-
/*
2-
* Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
3-
* SPDX-License-Identifier: Apache-2.0
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2017 ARM Limited
43
*
5-
* Licensed under the Apache License, Version 2.0 (the "License"); you may
6-
* not use this file except in compliance with the License.
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
76
* You may obtain a copy of the License at
87
*
9-
* http://www.apache.org/licenses/LICENSE-2.0
8+
* http://www.apache.org/licenses/LICENSE-2.0
109
*
1110
* Unless required by applicable law or agreed to in writing, software
12-
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13-
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1413
* See the License for the specific language governing permissions and
1514
* limitations under the License.
1615
*/
16+
#include "mbed.h"
17+
#include "greentea-client/test_env.h"
18+
#include "unity.h"
19+
#include "utest.h"
20+
#include "rtos.h"
1721

22+
using namespace utest::v1;
1823

19-
/*
20-
* Tests is to measure the accuracy of Timeout over a period of time
24+
#define NUM_TIMEOUTS 64
25+
const float TEST_DELAY_S = 0.01;
26+
const uint32_t TEST_DELAY_MS = 1000.0F * TEST_DELAY_S;
27+
const us_timestamp_t TEST_DELAY_US = 1000000.0F * TEST_DELAY_S;
28+
29+
void sem_callback(Semaphore *sem)
30+
{
31+
sem->release();
32+
}
33+
34+
void cnt_callback(volatile uint32_t *cnt)
35+
{
36+
(*cnt)++;
37+
}
38+
39+
class TimeoutAttachUSTester: public Timeout {
40+
public:
41+
void attach_callback(Callback<void()> func, us_timestamp_t delay_us)
42+
{
43+
attach_us(func, delay_us);
44+
}
45+
};
46+
47+
class TimeoutAttachTester: public Timeout {
48+
public:
49+
void attach_callback(Callback<void()> func, us_timestamp_t delay_us)
50+
{
51+
attach(func, (float) delay_us / 1000000.0f);
52+
}
53+
};
54+
55+
/** Template for tests: callback called once
2156
*
57+
* Test callback called once
58+
* Given a Timeout object with a callback attached with @a attach()
59+
* When given time elapses
60+
* Then the callback is called exactly one time
2261
*
23-
* 1) DUT would start to update callback_trigger_count every milli sec
24-
* 2) Host would query what is current count base_time, Device responds by the callback_trigger_count
25-
* 3) Host after waiting for measurement stretch. It will query for device time again final_time.
26-
* 4) Host computes the drift considering base_time, final_time, transport delay and measurement stretch
27-
* 5) Finally host send the results back to device pass/fail based on tolerance.
28-
* 6) More details on tests can be found in timing_drift_auto.py
62+
* Test callback called once
63+
* Given a Timeout object with a callback attached with @a attach_us()
64+
* When given time elapses
65+
* Then the callback is called exactly one time
66+
*/
67+
template<typename T>
68+
void test_callback_fires_once(void)
69+
{
70+
Semaphore sem(0, 1);
71+
T timeout;
72+
73+
timeout.attach_callback(mbed::callback(sem_callback, &sem), TEST_DELAY_US);
74+
75+
int32_t sem_slots = sem.wait(0);
76+
TEST_ASSERT_EQUAL(0, sem_slots);
77+
78+
sem_slots = sem.wait(TEST_DELAY_MS + 1);
79+
TEST_ASSERT_EQUAL(1, sem_slots);
80+
81+
sem_slots = sem.wait(TEST_DELAY_MS + 1);
82+
TEST_ASSERT_EQUAL(0, sem_slots);
83+
84+
timeout.detach();
85+
}
86+
87+
/** Template for tests: callback not called when cancelled
2988
*
89+
* Test callback not called when cancelled
90+
* Given a Timeout object with a callback attached with @a attach()
91+
* When the callback is detached before being called
92+
* Then the callback is never called
93+
*
94+
* Test callback not called when cancelled
95+
* Given a Timeout object with a callback attached with @a attach_us()
96+
* When the callback is detached before being called
97+
* Then the callback is never called
3098
*/
99+
template<typename T>
100+
void test_cancel(void)
101+
{
102+
Semaphore sem(0, 1);
103+
T timeout;
31104

32-
#include "mbed.h"
33-
#include "greentea-client/test_env.h"
34-
#include "utest/utest.h"
35-
#include "unity/unity.h"
105+
timeout.attach_callback(mbed::callback(sem_callback, &sem), 2.0f * TEST_DELAY_US);
36106

37-
using namespace utest::v1;
107+
int32_t sem_slots = sem.wait(TEST_DELAY_MS);
108+
TEST_ASSERT_EQUAL(0, sem_slots);
109+
timeout.detach();
38110

39-
#define PERIOD_US 10000
111+
sem_slots = sem.wait(TEST_DELAY_MS + 1);
112+
TEST_ASSERT_EQUAL(0, sem_slots);
113+
}
40114

41-
volatile int ticker_count = 0;
115+
/** Template for tests: callback override
116+
*
117+
* Test callback override
118+
* Given a Timeout object with a callback attached with @a attach()
119+
* When another callback is attached before first one is called
120+
* and second callback's delay elapses
121+
* Then the second callback is called
122+
* and the first callback is never called
123+
*
124+
* Test callback override
125+
* Given a Timeout object with a callback attached with @a attach_us()
126+
* When another callback is attached before first one is called
127+
* and second callback's delay elapses
128+
* Then the second callback is called
129+
* and the first callback is never called
130+
*/
131+
template<typename T>
132+
void test_override(void)
133+
{
134+
Semaphore sem1(0, 1);
135+
Semaphore sem2(0, 1);
136+
T timeout;
137+
138+
timeout.attach_callback(mbed::callback(sem_callback, &sem1), 2.0f * TEST_DELAY_US);
139+
140+
int32_t sem_slots = sem1.wait(TEST_DELAY_MS);
141+
TEST_ASSERT_EQUAL(0, sem_slots);
142+
timeout.attach_callback(mbed::callback(sem_callback, &sem2), 2.0f * TEST_DELAY_US);
143+
144+
sem_slots = sem2.wait(2 * TEST_DELAY_MS + 1);
145+
TEST_ASSERT_EQUAL(1, sem_slots);
146+
sem_slots = sem1.wait(0);
147+
TEST_ASSERT_EQUAL(0, sem_slots);
148+
149+
timeout.detach();
150+
}
151+
152+
/** Template for tests: multiple Timeouts
153+
*
154+
* Test multiple Timeouts
155+
* Given multiple separate Timeout objects
156+
* When a callback is attached to all of these Timeout objects with @a attach()
157+
* and delay for every Timeout elapses
158+
* Then all callbacks are called
159+
*
160+
* Test multiple Timeouts
161+
* Given multiple separate Timeout objects
162+
* When a callback is attached to all of these Timeout objects with @a attach_us()
163+
* and delay for every Timeout elapses
164+
* Then all callbacks are called
165+
*/
166+
template<typename T>
167+
void test_multiple(void)
168+
{
169+
volatile uint32_t callback_count = 0;
170+
T timeouts[NUM_TIMEOUTS];
171+
for (size_t i = 0; i < NUM_TIMEOUTS; i++) {
172+
timeouts[i].attach_callback(mbed::callback(cnt_callback, &callback_count), TEST_DELAY_US);
173+
}
174+
Thread::wait(TEST_DELAY_MS + 1);
175+
TEST_ASSERT_EQUAL(NUM_TIMEOUTS, callback_count);
176+
}
177+
178+
/** Template for tests: zero delay
179+
*
180+
* Test zero delay
181+
* Given a Timeout object
182+
* When a callback is attached with 0.0 s delay, with @a attach()
183+
* Then the callback is called instantly
184+
*
185+
* Test zero delay
186+
* Given a Timeout object
187+
* When a callback is attached with 0.0 s delay, with @a attach_us()
188+
* Then the callback is called instantly
189+
*/
190+
template<typename T>
191+
void test_no_wait(void)
192+
{
193+
Semaphore sem(0, 1);
194+
T timeout;
195+
timeout.attach_callback(mbed::callback(sem_callback, &sem), 0ULL);
196+
197+
int32_t sem_slots = sem.wait(0);
198+
TEST_ASSERT_EQUAL(1, sem_slots);
199+
timeout.detach();
200+
}
201+
202+
#define PERIOD_US 10000
42203
volatile uint32_t callback_trigger_count = 0;
43204
static const int test_timeout = 240;
44205
Timeout timeout;
45206

46-
void set_incremeant_count() {
47-
timeout.attach_us(set_incremeant_count, PERIOD_US);
207+
void set_increment_count()
208+
{
209+
timeout.attach_us(set_increment_count, PERIOD_US);
48210
++callback_trigger_count;
49211
}
50212

51-
void test_case_timeout() {
213+
/*
214+
* Tests is to measure the accuracy of Timeout over a period of time
215+
*
216+
*
217+
* 1) DUT would start to update callback_trigger_count every milli sec
218+
* 2) Host would query what is current count base_time, Device responds by the callback_trigger_count
219+
* 3) Host after waiting for measurement stretch. It will query for device time again final_time.
220+
* 4) Host computes the drift considering base_time, final_time, transport delay and measurement stretch
221+
* 5) Finally host send the results back to device pass/fail based on tolerance.
222+
* 6) More details on tests can be found in timing_drift_auto.py
223+
*
224+
*/
225+
void test_case_timeout()
226+
{
52227

53228
char _key[11] = { };
54229
char _value[128] = { };
55230
int expected_key = 1;
56-
uint8_t results_size = 0;
57231

58232
greentea_send_kv("timing_drift_check_start", 0);
59-
timeout.attach_us(set_incremeant_count, PERIOD_US);
233+
timeout.attach_us(set_increment_count, PERIOD_US);
60234

61235
// wait for 1st signal from host
62236
do {
@@ -73,19 +247,37 @@ void test_case_timeout() {
73247
//get the results from host
74248
greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
75249

76-
TEST_ASSERT_EQUAL_STRING_MESSAGE("pass", _key,"Host side script reported a fail...");
250+
TEST_ASSERT_EQUAL_STRING_MESSAGE("pass", _key, "Host side script reported a fail...");
77251
}
78252

79-
// Test casess
80-
Case cases[] = { Case("Timers: toggle on/off", test_case_timeout), };
253+
Case cases[] = {
254+
Case("Test callback called once (with attach)", test_callback_fires_once<TimeoutAttachTester>),
255+
Case("Test callback called once (with attach_us)", test_callback_fires_once<TimeoutAttachUSTester>),
256+
257+
Case("Test callback not called when cancelled (with attach)", test_cancel<TimeoutAttachTester>),
258+
Case("Test callback not called when cancelled (with attach_us)", test_cancel<TimeoutAttachUSTester>),
259+
260+
Case("Test callback override (with attach)", test_override<TimeoutAttachTester>),
261+
Case("Test callback override (with attach_us)", test_override<TimeoutAttachUSTester>),
262+
263+
Case("Test multiple timeouts running in parallel (with attach)", test_multiple<TimeoutAttachTester>),
264+
Case("Test multiple timeouts running in parallel (with attach_us)", test_multiple<TimeoutAttachUSTester>),
265+
266+
Case("Test zero delay (with attach)", test_no_wait<TimeoutAttachTester>),
267+
Case("Test zero delay (with attach_us)", test_no_wait<TimeoutAttachUSTester>),
268+
269+
Case("Timers: toggle on/off", test_case_timeout)
270+
};
81271

82-
utest::v1::status_t greentea_test_setup(const size_t number_of_cases) {
272+
utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
273+
{
83274
GREENTEA_SETUP(test_timeout, "timing_drift_auto");
84275
return greentea_test_setup_handler(number_of_cases);
85276
}
86277

87278
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
88279

89-
int main() {
280+
int main()
281+
{
90282
Harness::run(specification);
91283
}

0 commit comments

Comments
 (0)