Skip to content

Commit 5c0f39f

Browse files
committed
Split callback test into multiple tests based on types
As the templated tests grew, the resulting binary exceeded a flash size of 64K. This caused the test to incorrectly fail on small devices. Moved and split into the following: TESTS/mbed_functional/callback TESTS/mbed_functional/callback_small TESTS/mbed_functional/callback_big TESTS/mbed_functional/functionpointer
1 parent c71e67f commit 5c0f39f

File tree

4 files changed

+927
-33
lines changed

4 files changed

+927
-33
lines changed
Lines changed: 351 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,351 @@
1+
#include "mbed.h"
2+
#include "greentea-client/test_env.h"
3+
#include "unity.h"
4+
#include "utest.h"
5+
6+
using namespace utest::v1;
7+
8+
9+
// static functions
10+
template <typename T>
11+
T static_func0() { return 0; }
12+
template <typename T>
13+
T static_func1(T a0) { return 0 | a0; }
14+
template <typename T>
15+
T static_func2(T a0, T a1) { return 0 | a0 | a1; }
16+
template <typename T>
17+
T static_func3(T a0, T a1, T a2) { return 0 | a0 | a1 | a2; }
18+
template <typename T>
19+
T static_func4(T a0, T a1, T a2, T a3) { return 0 | a0 | a1 | a2 | a3; }
20+
template <typename T>
21+
T static_func5(T a0, T a1, T a2, T a3, T a4) { return 0 | a0 | a1 | a2 | a3 | a4; }
22+
23+
// class functions
24+
template <typename T>
25+
struct Thing {
26+
T t;
27+
Thing() : t(0x80) {}
28+
29+
T member_func0() { return t; }
30+
T member_func1(T a0) { return t | a0; }
31+
T member_func2(T a0, T a1) { return t | a0 | a1; }
32+
T member_func3(T a0, T a1, T a2) { return t | a0 | a1 | a2; }
33+
T member_func4(T a0, T a1, T a2, T a3) { return t | a0 | a1 | a2 | a3; }
34+
T member_func5(T a0, T a1, T a2, T a3, T a4) { return t | a0 | a1 | a2 | a3 | a4; }
35+
36+
T const_member_func0() const { return t; }
37+
T const_member_func1(T a0) const { return t | a0; }
38+
T const_member_func2(T a0, T a1) const { return t | a0 | a1; }
39+
T const_member_func3(T a0, T a1, T a2) const { return t | a0 | a1 | a2; }
40+
T const_member_func4(T a0, T a1, T a2, T a3) const { return t | a0 | a1 | a2 | a3; }
41+
T const_member_func5(T a0, T a1, T a2, T a3, T a4) const { return t | a0 | a1 | a2 | a3 | a4; }
42+
43+
T volatile_member_func0() volatile { return t; }
44+
T volatile_member_func1(T a0) volatile { return t | a0; }
45+
T volatile_member_func2(T a0, T a1) volatile { return t | a0 | a1; }
46+
T volatile_member_func3(T a0, T a1, T a2) volatile { return t | a0 | a1 | a2; }
47+
T volatile_member_func4(T a0, T a1, T a2, T a3) volatile { return t | a0 | a1 | a2 | a3; }
48+
T volatile_member_func5(T a0, T a1, T a2, T a3, T a4) volatile { return t | a0 | a1 | a2 | a3 | a4; }
49+
50+
T const_volatile_member_func0() const volatile { return t; }
51+
T const_volatile_member_func1(T a0) const volatile { return t | a0; }
52+
T const_volatile_member_func2(T a0, T a1) const volatile { return t | a0 | a1; }
53+
T const_volatile_member_func3(T a0, T a1, T a2) const volatile { return t | a0 | a1 | a2; }
54+
T const_volatile_member_func4(T a0, T a1, T a2, T a3) const volatile { return t | a0 | a1 | a2 | a3; }
55+
T const_volatile_member_func5(T a0, T a1, T a2, T a3, T a4) const volatile { return t | a0 | a1 | a2 | a3 | a4; }
56+
};
57+
58+
// bound functions
59+
template <typename T>
60+
T bound_func0(Thing<T> *t) { return t->t; }
61+
template <typename T>
62+
T bound_func1(Thing<T> *t, T a0) { return t->t | a0; }
63+
template <typename T>
64+
T bound_func2(Thing<T> *t, T a0, T a1) { return t->t | a0 | a1; }
65+
template <typename T>
66+
T bound_func3(Thing<T> *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; }
67+
template <typename T>
68+
T bound_func4(Thing<T> *t, T a0, T a1, T a2, T a3) { return t->t | a0 | a1 | a2 | a3; }
69+
template <typename T>
70+
T bound_func5(Thing<T> *t, T a0, T a1, T a2, T a3, T a4) { return t->t | a0 | a1 | a2 | a3 | a4; }
71+
72+
// const bound functions
73+
template <typename T>
74+
T const_func0(const Thing<T> *t) { return t->t; }
75+
template <typename T>
76+
T const_func1(const Thing<T> *t, T a0) { return t->t | a0; }
77+
template <typename T>
78+
T const_func2(const Thing<T> *t, T a0, T a1) { return t->t | a0 | a1; }
79+
template <typename T>
80+
T const_func3(const Thing<T> *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; }
81+
template <typename T>
82+
T const_func4(const Thing<T> *t, T a0, T a1, T a2, T a3) { return t->t | a0 | a1 | a2 | a3; }
83+
template <typename T>
84+
T const_func5(const Thing<T> *t, T a0, T a1, T a2, T a3, T a4) { return t->t | a0 | a1 | a2 | a3 | a4; }
85+
86+
// volatile bound functions
87+
template <typename T>
88+
T volatile_func0(volatile Thing<T> *t) { return t->t; }
89+
template <typename T>
90+
T volatile_func1(volatile Thing<T> *t, T a0) { return t->t | a0; }
91+
template <typename T>
92+
T volatile_func2(volatile Thing<T> *t, T a0, T a1) { return t->t | a0 | a1; }
93+
template <typename T>
94+
T volatile_func3(volatile Thing<T> *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; }
95+
template <typename T>
96+
T volatile_func4(volatile Thing<T> *t, T a0, T a1, T a2, T a3) { return t->t | a0 | a1 | a2 | a3; }
97+
template <typename T>
98+
T volatile_func5(volatile Thing<T> *t, T a0, T a1, T a2, T a3, T a4) { return t->t | a0 | a1 | a2 | a3 | a4; }
99+
100+
// const volatile bound functions
101+
template <typename T>
102+
T const_volatile_func0(const volatile Thing<T> *t) { return t->t; }
103+
template <typename T>
104+
T const_volatile_func1(const volatile Thing<T> *t, T a0) { return t->t | a0; }
105+
template <typename T>
106+
T const_volatile_func2(const volatile Thing<T> *t, T a0, T a1) { return t->t | a0 | a1; }
107+
template <typename T>
108+
T const_volatile_func3(const volatile Thing<T> *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; }
109+
template <typename T>
110+
T const_volatile_func4(const volatile Thing<T> *t, T a0, T a1, T a2, T a3) { return t->t | a0 | a1 | a2 | a3; }
111+
template <typename T>
112+
T const_volatile_func5(const volatile Thing<T> *t, T a0, T a1, T a2, T a3, T a4) { return t->t | a0 | a1 | a2 | a3 | a4; }
113+
114+
115+
// function call and result verification
116+
template <typename T>
117+
struct Verifier {
118+
static void verify0(Callback<T()> func) {
119+
T result = func();
120+
TEST_ASSERT_EQUAL(result, 0x00);
121+
}
122+
123+
template <typename O, typename M>
124+
static void verify0(O *obj, M method) {
125+
Callback<T()> func(obj, method);
126+
T result = func();
127+
TEST_ASSERT_EQUAL(result, 0x80);
128+
}
129+
130+
static void verify1(Callback<T(T)> func) {
131+
T result = func((1 << 0));
132+
TEST_ASSERT_EQUAL(result, 0x00 | (1 << 0));
133+
}
134+
135+
template <typename O, typename M>
136+
static void verify1(O *obj, M method) {
137+
Callback<T(T)> func(obj, method);
138+
T result = func((1 << 0));
139+
TEST_ASSERT_EQUAL(result, 0x80 | (1 << 0));
140+
}
141+
142+
static void verify2(Callback<T(T, T)> func) {
143+
T result = func((1 << 0), (1 << 1));
144+
TEST_ASSERT_EQUAL(result, 0x00 | (1 << 0) | (1 << 1));
145+
}
146+
147+
template <typename O, typename M>
148+
static void verify2(O *obj, M method) {
149+
Callback<T(T, T)> func(obj, method);
150+
T result = func((1 << 0), (1 << 1));
151+
TEST_ASSERT_EQUAL(result, 0x80 | (1 << 0) | (1 << 1));
152+
}
153+
154+
static void verify3(Callback<T(T, T, T)> func) {
155+
T result = func((1 << 0), (1 << 1), (1 << 2));
156+
TEST_ASSERT_EQUAL(result, 0x00 | (1 << 0) | (1 << 1) | (1 << 2));
157+
}
158+
159+
template <typename O, typename M>
160+
static void verify3(O *obj, M method) {
161+
Callback<T(T, T, T)> func(obj, method);
162+
T result = func((1 << 0), (1 << 1), (1 << 2));
163+
TEST_ASSERT_EQUAL(result, 0x80 | (1 << 0) | (1 << 1) | (1 << 2));
164+
}
165+
166+
static void verify4(Callback<T(T, T, T, T)> func) {
167+
T result = func((1 << 0), (1 << 1), (1 << 2), (1 << 3));
168+
TEST_ASSERT_EQUAL(result, 0x00 | (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3));
169+
}
170+
171+
template <typename O, typename M>
172+
static void verify4(O *obj, M method) {
173+
Callback<T(T, T, T, T)> func(obj, method);
174+
T result = func((1 << 0), (1 << 1), (1 << 2), (1 << 3));
175+
TEST_ASSERT_EQUAL(result, 0x80 | (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3));
176+
}
177+
178+
static void verify5(Callback<T(T, T, T, T, T)> func) {
179+
T result = func((1 << 0), (1 << 1), (1 << 2), (1 << 3), (1 << 4));
180+
TEST_ASSERT_EQUAL(result, 0x00 | (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4));
181+
}
182+
183+
template <typename O, typename M>
184+
static void verify5(O *obj, M method) {
185+
Callback<T(T, T, T, T, T)> func(obj, method);
186+
T result = func((1 << 0), (1 << 1), (1 << 2), (1 << 3), (1 << 4));
187+
TEST_ASSERT_EQUAL(result, 0x80 | (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4));
188+
}
189+
};
190+
191+
192+
// test dispatch
193+
template <typename T>
194+
void test_dispatch0() {
195+
Thing<T> thing;
196+
Verifier<T>::verify0(static_func0<T>);
197+
Verifier<T>::verify0(&thing, &Thing<T>::member_func0);
198+
Verifier<T>::verify0((const Thing<T>*)&thing, &Thing<T>::const_member_func0);
199+
Verifier<T>::verify0((volatile Thing<T>*)&thing, &Thing<T>::volatile_member_func0);
200+
Verifier<T>::verify0((const volatile Thing<T>*)&thing, &Thing<T>::const_volatile_member_func0);
201+
Verifier<T>::verify0(&thing, &bound_func0<T>);
202+
Verifier<T>::verify0((const Thing<T>*)&thing, &const_func0<T>);
203+
Verifier<T>::verify0((volatile Thing<T>*)&thing, &volatile_func0<T>);
204+
Verifier<T>::verify0((const volatile Thing<T>*)&thing, &const_volatile_func0<T>);
205+
Verifier<T>::verify0(callback(static_func0<T>));
206+
207+
Callback<T()> cb(static_func0);
208+
Verifier<T>::verify0(cb);
209+
cb = static_func0;
210+
Verifier<T>::verify0(cb);
211+
cb.attach(&thing, &bound_func0<T>);
212+
Verifier<T>::verify0(&cb, &Callback<T()>::call);
213+
Verifier<T>::verify0((void*)&cb, &Callback<T()>::thunk);
214+
}
215+
216+
template <typename T>
217+
void test_dispatch1() {
218+
Thing<T> thing;
219+
Verifier<T>::verify1(static_func1<T>);
220+
Verifier<T>::verify1(&thing, &Thing<T>::member_func1);
221+
Verifier<T>::verify1((const Thing<T>*)&thing, &Thing<T>::const_member_func1);
222+
Verifier<T>::verify1((volatile Thing<T>*)&thing, &Thing<T>::volatile_member_func1);
223+
Verifier<T>::verify1((const volatile Thing<T>*)&thing, &Thing<T>::const_volatile_member_func1);
224+
Verifier<T>::verify1(&thing, &bound_func1<T>);
225+
Verifier<T>::verify1((const Thing<T>*)&thing, &const_func1<T>);
226+
Verifier<T>::verify1((volatile Thing<T>*)&thing, &volatile_func1<T>);
227+
Verifier<T>::verify1((const volatile Thing<T>*)&thing, &const_volatile_func1<T>);
228+
Verifier<T>::verify1(callback(static_func1<T>));
229+
230+
Callback<T(T)> cb(static_func1);
231+
Verifier<T>::verify1(cb);
232+
cb = static_func1;
233+
Verifier<T>::verify1(cb);
234+
cb.attach(&thing, &bound_func1<T>);
235+
Verifier<T>::verify1(&cb, &Callback<T(T)>::call);
236+
Verifier<T>::verify1((void*)&cb, &Callback<T(T)>::thunk);
237+
}
238+
239+
template <typename T>
240+
void test_dispatch2() {
241+
Thing<T> thing;
242+
Verifier<T>::verify2(static_func2<T>);
243+
Verifier<T>::verify2(&thing, &Thing<T>::member_func2);
244+
Verifier<T>::verify2((const Thing<T>*)&thing, &Thing<T>::const_member_func2);
245+
Verifier<T>::verify2((volatile Thing<T>*)&thing, &Thing<T>::volatile_member_func2);
246+
Verifier<T>::verify2((const volatile Thing<T>*)&thing, &Thing<T>::const_volatile_member_func2);
247+
Verifier<T>::verify2(&thing, &bound_func2<T>);
248+
Verifier<T>::verify2((const Thing<T>*)&thing, &const_func2<T>);
249+
Verifier<T>::verify2((volatile Thing<T>*)&thing, &volatile_func2<T>);
250+
Verifier<T>::verify2((const volatile Thing<T>*)&thing, &const_volatile_func2<T>);
251+
Verifier<T>::verify2(callback(static_func2<T>));
252+
253+
Callback<T(T, T)> cb(static_func2);
254+
Verifier<T>::verify2(cb);
255+
cb = static_func2;
256+
Verifier<T>::verify2(cb);
257+
cb.attach(&thing, &bound_func2<T>);
258+
Verifier<T>::verify2(&cb, &Callback<T(T, T)>::call);
259+
Verifier<T>::verify2((void*)&cb, &Callback<T(T, T)>::thunk);
260+
}
261+
262+
template <typename T>
263+
void test_dispatch3() {
264+
Thing<T> thing;
265+
Verifier<T>::verify3(static_func3<T>);
266+
Verifier<T>::verify3(&thing, &Thing<T>::member_func3);
267+
Verifier<T>::verify3((const Thing<T>*)&thing, &Thing<T>::const_member_func3);
268+
Verifier<T>::verify3((volatile Thing<T>*)&thing, &Thing<T>::volatile_member_func3);
269+
Verifier<T>::verify3((const volatile Thing<T>*)&thing, &Thing<T>::const_volatile_member_func3);
270+
Verifier<T>::verify3(&thing, &bound_func3<T>);
271+
Verifier<T>::verify3((const Thing<T>*)&thing, &const_func3<T>);
272+
Verifier<T>::verify3((volatile Thing<T>*)&thing, &volatile_func3<T>);
273+
Verifier<T>::verify3((const volatile Thing<T>*)&thing, &const_volatile_func3<T>);
274+
Verifier<T>::verify3(callback(static_func3<T>));
275+
276+
Callback<T(T, T, T)> cb(static_func3);
277+
Verifier<T>::verify3(cb);
278+
cb = static_func3;
279+
Verifier<T>::verify3(cb);
280+
cb.attach(&thing, &bound_func3<T>);
281+
Verifier<T>::verify3(&cb, &Callback<T(T, T, T)>::call);
282+
Verifier<T>::verify3((void*)&cb, &Callback<T(T, T, T)>::thunk);
283+
}
284+
285+
template <typename T>
286+
void test_dispatch4() {
287+
Thing<T> thing;
288+
Verifier<T>::verify4(static_func4<T>);
289+
Verifier<T>::verify4(&thing, &Thing<T>::member_func4);
290+
Verifier<T>::verify4((const Thing<T>*)&thing, &Thing<T>::const_member_func4);
291+
Verifier<T>::verify4((volatile Thing<T>*)&thing, &Thing<T>::volatile_member_func4);
292+
Verifier<T>::verify4((const volatile Thing<T>*)&thing, &Thing<T>::const_volatile_member_func4);
293+
Verifier<T>::verify4(&thing, &bound_func4<T>);
294+
Verifier<T>::verify4((const Thing<T>*)&thing, &const_func4<T>);
295+
Verifier<T>::verify4((volatile Thing<T>*)&thing, &volatile_func4<T>);
296+
Verifier<T>::verify4((const volatile Thing<T>*)&thing, &const_volatile_func4<T>);
297+
Verifier<T>::verify4(callback(static_func4<T>));
298+
299+
Callback<T(T, T, T, T)> cb(static_func4);
300+
Verifier<T>::verify4(cb);
301+
cb = static_func4;
302+
Verifier<T>::verify4(cb);
303+
cb.attach(&thing, &bound_func4<T>);
304+
Verifier<T>::verify4(&cb, &Callback<T(T, T, T, T)>::call);
305+
Verifier<T>::verify4((void*)&cb, &Callback<T(T, T, T, T)>::thunk);
306+
}
307+
308+
template <typename T>
309+
void test_dispatch5() {
310+
Thing<T> thing;
311+
Verifier<T>::verify5(static_func5<T>);
312+
Verifier<T>::verify5(&thing, &Thing<T>::member_func5);
313+
Verifier<T>::verify5((const Thing<T>*)&thing, &Thing<T>::const_member_func5);
314+
Verifier<T>::verify5((volatile Thing<T>*)&thing, &Thing<T>::volatile_member_func5);
315+
Verifier<T>::verify5((const volatile Thing<T>*)&thing, &Thing<T>::const_volatile_member_func5);
316+
Verifier<T>::verify5(&thing, &bound_func5<T>);
317+
Verifier<T>::verify5((const Thing<T>*)&thing, &const_func5<T>);
318+
Verifier<T>::verify5((volatile Thing<T>*)&thing, &volatile_func5<T>);
319+
Verifier<T>::verify5((const volatile Thing<T>*)&thing, &const_volatile_func5<T>);
320+
Verifier<T>::verify5(callback(static_func5<T>));
321+
322+
Callback<T(T, T, T, T, T)> cb(static_func5);
323+
Verifier<T>::verify5(cb);
324+
cb = static_func5;
325+
Verifier<T>::verify5(cb);
326+
cb.attach(&thing, &bound_func5<T>);
327+
Verifier<T>::verify5(&cb, &Callback<T(T, T, T, T, T)>::call);
328+
Verifier<T>::verify5((void*)&cb, &Callback<T(T, T, T, T, T)>::thunk);
329+
}
330+
331+
332+
// Test setup
333+
utest::v1::status_t test_setup(const size_t number_of_cases) {
334+
GREENTEA_SETUP(10, "default_auto");
335+
return verbose_test_setup_handler(number_of_cases);
336+
}
337+
338+
Case cases[] = {
339+
Case("Testing callbacks with 0 ints", test_dispatch0<int>),
340+
Case("Testing callbacks with 1 ints", test_dispatch1<int>),
341+
Case("Testing callbacks with 2 ints", test_dispatch2<int>),
342+
Case("Testing callbacks with 3 ints", test_dispatch3<int>),
343+
Case("Testing callbacks with 4 ints", test_dispatch4<int>),
344+
Case("Testing callbacks with 5 ints", test_dispatch5<int>),
345+
};
346+
347+
Specification specification(test_setup, cases);
348+
349+
int main() {
350+
return !Harness::run(specification);
351+
}

0 commit comments

Comments
 (0)