Skip to content

Commit 3806c87

Browse files
authored
Merge pull request #2559 from pan-/utest_globals_optimizations
[utest]: Allow the linker to remove any part of utest if not used
2 parents c1ee7fb + aab1070 commit 3806c87

File tree

7 files changed

+122
-52
lines changed

7 files changed

+122
-52
lines changed

TESTS/storage_abstraction/basicAPI/basicAPI.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ control_t test_initialize(const size_t call_count)
135135
TEST_ASSERT(rc >= ARM_DRIVER_OK);
136136
if (rc == ARM_DRIVER_OK) {
137137
TEST_ASSERT_EQUAL(1, capabilities.asynchronous_ops);
138-
return (call_count < REPEAT_INSTANCES) ? (CaseTimeout(200) + CaseRepeatAll) : CaseNext;
138+
return (call_count < REPEAT_INSTANCES) ? (CaseTimeout(200) + CaseRepeatAll) : (control_t) CaseNext;
139139
}
140140

141141
TEST_ASSERT(rc == 1);

features/frameworks/utest/source/utest_default_handlers.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ const handlers_t utest::v1::verbose_continue_handlers = {
3434
verbose_case_failure_handler
3535
};
3636

37+
const handlers_t& utest::v1::default_handlers = greentea_abort_handlers;
3738

3839
// --- SPECIAL HANDLERS ---
3940
static void test_failure_handler(const failure_t failure) {

features/frameworks/utest/source/utest_harness.cpp

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ namespace
3636

3737
const Case *case_current = NULL;
3838
size_t case_index = 0;
39-
control_t case_control = control_t(REPEAT_SETUP_TEARDOWN);
39+
base_control_t case_control = { REPEAT_SETUP_TEARDOWN, TIMEOUT_UNDECLR };
4040
size_t case_repeat_count = 1;
4141

4242
void *case_timeout_handle = NULL;
@@ -47,8 +47,13 @@ namespace
4747
size_t case_failed = 0;
4848
size_t case_failed_before = 0;
4949

50-
handlers_t defaults = default_handlers;
51-
handlers_t handlers = defaults;
50+
struct DefaultHandlers : public handlers_t {
51+
DefaultHandlers() : handlers_t(default_handlers) { }
52+
DefaultHandlers(const handlers_t& other) : handlers_t(other) { }
53+
};
54+
55+
SingletonPtr<DefaultHandlers> defaults;
56+
SingletonPtr<DefaultHandlers> handlers;
5257

5358
location_t location = LOCATION_UNKNOWN;
5459

@@ -110,10 +115,10 @@ bool Harness::run(const Specification& specification)
110115
return false;
111116
test_cases = specification.cases;
112117
test_length = specification.length;
113-
defaults = specification.defaults;
114-
handlers.test_setup = defaults.get_handler(specification.setup_handler);
115-
handlers.test_teardown = defaults.get_handler(specification.teardown_handler);
116-
handlers.test_failure = defaults.get_handler(specification.failure_handler);
118+
*defaults.get() = specification.defaults;
119+
handlers->test_setup = defaults->get_handler(specification.setup_handler);
120+
handlers->test_teardown = defaults->get_handler(specification.teardown_handler);
121+
handlers->test_failure = defaults->get_handler(specification.failure_handler);
117122

118123
test_index_of_case = 0;
119124
test_passed = 0;
@@ -127,16 +132,16 @@ bool Harness::run(const Specification& specification)
127132
int setup_status = 0;
128133
failure_t failure(REASON_NONE, location);
129134

130-
if (handlers.test_setup) {
131-
setup_status = handlers.test_setup(test_length);
135+
if (handlers->test_setup) {
136+
setup_status = handlers->test_setup(test_length);
132137
if (setup_status == STATUS_CONTINUE) setup_status = 0;
133138
else if (setup_status < STATUS_CONTINUE) failure.reason = REASON_TEST_SETUP;
134139
else if (setup_status > signed(test_length)) failure.reason = REASON_CASE_INDEX;
135140
}
136141

137142
if (failure.reason != REASON_NONE) {
138-
if (handlers.test_failure) handlers.test_failure(failure);
139-
if (handlers.test_teardown) handlers.test_teardown(0, 0, failure);
143+
if (handlers->test_failure) handlers->test_failure(failure);
144+
if (handlers->test_teardown) handlers->test_teardown(0, 0, failure);
140145
test_cases = NULL;
141146
exit(1);
142147
return true;
@@ -150,8 +155,8 @@ bool Harness::run(const Specification& specification)
150155
scheduler.post(run_next_case, 0);
151156
if (scheduler.run() != 0) {
152157
failure.reason = REASON_SCHEDULER;
153-
if (handlers.test_failure) handlers.test_failure(failure);
154-
if (handlers.test_teardown) handlers.test_teardown(0, 0, failure);
158+
if (handlers->test_failure) handlers->test_failure(failure);
159+
if (handlers->test_teardown) handlers->test_teardown(0, 0, failure);
155160
test_cases = NULL;
156161
exit(1);
157162
return true;
@@ -167,8 +172,8 @@ void Harness::raise_failure(const failure_reason_t reason)
167172
if (test_cases == NULL) return;
168173

169174
utest::v1::status_t fail_status = STATUS_ABORT;
170-
if (handlers.test_failure) handlers.test_failure(failure_t(reason, location));
171-
if (handlers.case_failure) fail_status = handlers.case_failure(case_current, failure_t(reason, location));
175+
if (handlers->test_failure) handlers->test_failure(failure_t(reason, location));
176+
if (handlers->case_failure) fail_status = handlers->case_failure(case_current, failure_t(reason, location));
172177

173178
{
174179
UTEST_ENTER_CRITICAL_SECTION;
@@ -184,25 +189,25 @@ void Harness::raise_failure(const failure_reason_t reason)
184189
}
185190

186191
if (fail_status == STATUS_ABORT || reason & REASON_CASE_SETUP) {
187-
if (handlers.case_teardown && location != LOCATION_CASE_TEARDOWN) {
192+
if (handlers->case_teardown && location != LOCATION_CASE_TEARDOWN) {
188193
location_t fail_loc(location);
189194
location = LOCATION_CASE_TEARDOWN;
190195

191-
utest::v1::status_t teardown_status = handlers.case_teardown(case_current, case_passed, case_failed, failure_t(reason, fail_loc));
196+
utest::v1::status_t teardown_status = handlers->case_teardown(case_current, case_passed, case_failed, failure_t(reason, fail_loc));
192197
if (teardown_status < STATUS_CONTINUE) raise_failure(REASON_CASE_TEARDOWN);
193198
else if (teardown_status > signed(test_length)) raise_failure(REASON_CASE_INDEX);
194199
else if (teardown_status >= 0) case_index = teardown_status - 1;
195200

196201
// Restore case failure location once we have dealt with case teardown
197202
location = fail_loc;
198-
handlers.case_teardown = NULL;
203+
handlers->case_teardown = NULL;
199204
}
200205
}
201206
if (fail_status == STATUS_ABORT) {
202207
test_failed++;
203208
failure_t fail(reason, location);
204209
location = LOCATION_TEST_TEARDOWN;
205-
if (handlers.test_teardown) handlers.test_teardown(test_passed, test_failed, fail);
210+
if (handlers->test_teardown) handlers->test_teardown(test_passed, test_failed, fail);
206211
exit(test_failed);
207212
die();
208213
}
@@ -218,8 +223,8 @@ void Harness::schedule_next_case()
218223
if (case_control.repeat & REPEAT_SETUP_TEARDOWN || !(case_control.repeat & (REPEAT_ON_TIMEOUT | REPEAT_ON_VALIDATE))) {
219224
location = LOCATION_CASE_TEARDOWN;
220225

221-
if (handlers.case_teardown) {
222-
utest::v1::status_t status = handlers.case_teardown(case_current, case_passed, case_failed,
226+
if (handlers->case_teardown) {
227+
utest::v1::status_t status = handlers->case_teardown(case_current, case_passed, case_failed,
223228
case_failed ? failure_t(REASON_CASES, LOCATION_UNKNOWN) : failure_t(REASON_NONE));
224229
if (status < STATUS_CONTINUE) raise_failure(REASON_CASE_TEARDOWN);
225230
else if (status > signed(test_length)) raise_failure(REASON_CASE_INDEX);
@@ -298,9 +303,9 @@ void Harness::run_next_case()
298303
UTEST_LOG_FUNCTION();
299304
if(case_current < (test_cases + test_length))
300305
{
301-
handlers.case_setup = defaults.get_handler(case_current->setup_handler);
302-
handlers.case_teardown = defaults.get_handler(case_current->teardown_handler);
303-
handlers.case_failure = defaults.get_handler(case_current->failure_handler);
306+
handlers->case_setup = defaults->get_handler(case_current->setup_handler);
307+
handlers->case_teardown = defaults->get_handler(case_current->teardown_handler);
308+
handlers->case_failure = defaults->get_handler(case_current->failure_handler);
304309

305310
if (case_current->is_empty()) {
306311
location = LOCATION_UNKNOWN;
@@ -321,7 +326,7 @@ void Harness::run_next_case()
321326

322327
if (setup_repeat & REPEAT_SETUP_TEARDOWN) {
323328
location = LOCATION_CASE_SETUP;
324-
if (handlers.case_setup && (handlers.case_setup(case_current, test_index_of_case) != STATUS_CONTINUE)) {
329+
if (handlers->case_setup && (handlers->case_setup(case_current, test_index_of_case) != STATUS_CONTINUE)) {
325330
raise_failure(REASON_CASE_SETUP);
326331
schedule_next_case();
327332
return;
@@ -361,9 +366,9 @@ void Harness::run_next_case()
361366
UTEST_LEAVE_CRITICAL_SECTION;
362367
}
363368
}
364-
else if (handlers.test_teardown) {
369+
else if (handlers->test_teardown) {
365370
location = LOCATION_TEST_TEARDOWN;
366-
handlers.test_teardown(test_passed, test_failed, test_failed ? failure_t(REASON_CASES, LOCATION_UNKNOWN) : failure_t(REASON_NONE));
371+
handlers->test_teardown(test_passed, test_failed, test_failed ? failure_t(REASON_CASES, LOCATION_UNKNOWN) : failure_t(REASON_NONE));
367372
test_cases = NULL;
368373
exit(test_failed);
369374
} else {

features/frameworks/utest/source/utest_shim.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ static volatile utest_v1_harness_callback_t minimal_callback;
6666
static volatile utest_v1_harness_callback_t ticker_callback;
6767

6868
// Timeout object used to control the scheduling of test case callbacks
69-
Timeout utest_timeout_object;
69+
SingletonPtr<Timeout> utest_timeout_object;
7070

7171
static void ticker_handler()
7272
{
@@ -77,7 +77,9 @@ static void ticker_handler()
7777
static int32_t utest_us_ticker_init()
7878
{
7979
UTEST_LOG_FUNCTION();
80-
// Ticker scheduler does not require any initialisation so return immediately
80+
// initialize the Timeout object to makes sure it is not initialized in
81+
// interrupt context.
82+
utest_timeout_object.get();
8183
return 0;
8284
}
8385
static void *utest_us_ticker_post(const utest_v1_harness_callback_t callback, timestamp_t delay_ms)
@@ -88,7 +90,7 @@ static void *utest_us_ticker_post(const utest_v1_harness_callback_t callback, ti
8890
if (delay_ms) {
8991
ticker_callback = callback;
9092
// fire the interrupt in 1000us * delay_ms
91-
utest_timeout_object.attach_us(ticker_handler, delay_us);
93+
utest_timeout_object->attach_us(ticker_handler, delay_us);
9294

9395
}
9496
else {
@@ -102,7 +104,7 @@ static int32_t utest_us_ticker_cancel(void *handle)
102104
{
103105
UTEST_LOG_FUNCTION();
104106
(void) handle;
105-
utest_timeout_object.detach();
107+
utest_timeout_object->detach();
106108
return 0;
107109
}
108110
static int32_t utest_us_ticker_run()

features/frameworks/utest/source/utest_types.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,3 +114,22 @@ const char* utest::v1::stringify(utest::v1::status_t status)
114114
}
115115
return "Unknown Status";
116116
}
117+
118+
119+
const utest::v1::base_control_t utest::v1::CaseNext = { REPEAT_NONE, TIMEOUT_NONE };
120+
121+
const utest::v1::base_control_t utest::v1::CaseNoRepeat = { REPEAT_NONE, TIMEOUT_UNDECLR };
122+
123+
const utest::v1::base_control_t utest::v1::CaseRepeatAll = { REPEAT_ALL, TIMEOUT_UNDECLR };
124+
125+
const utest::v1::base_control_t utest::v1::CaseRepeatHandler = { REPEAT_HANDLER, TIMEOUT_UNDECLR };
126+
127+
const utest::v1::base_control_t utest::v1::CaseNoTimeout = { REPEAT_UNDECLR, TIMEOUT_NONE };
128+
129+
const utest::v1::base_control_t utest::v1::CaseAwait = { REPEAT_UNDECLR, TIMEOUT_FOREVER };
130+
131+
// equal to CaeReapeatAll
132+
const utest::v1::base_control_t utest::v1::CaseRepeat = { REPEAT_ALL, TIMEOUT_UNDECLR };
133+
134+
// equal to CaseRepeatHandler
135+
const utest::v1::base_control_t utest::v1::CaseRepeatHandlerOnly = { REPEAT_HANDLER, TIMEOUT_UNDECLR };

features/frameworks/utest/utest/utest_default_handlers.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ namespace v1 {
185185
extern const handlers_t selftest_handlers;
186186

187187
/// The greentea aborting handlers are the default
188-
const handlers_t default_handlers = greentea_abort_handlers;
188+
extern const handlers_t& default_handlers;
189189

190190
} // namespace v1
191191
} // namespace utest

features/frameworks/utest/utest/utest_types.h

Lines changed: 62 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,23 @@ namespace v1 {
120120
/// Stringifies a status.
121121
const char* stringify(utest::v1::status_t status);
122122

123+
/** POD version of the class control_t.
124+
* It is used to instantiate const control_t objects as PODs
125+
* and prevent them to be included in the final binary.
126+
* @note: control_pod_t can be converted to control_t by copy construction.
127+
*/
128+
struct base_control_t {
129+
repeat_t repeat;
130+
uint32_t timeout;
131+
132+
repeat_t inline get_repeat() const {
133+
return repeat;
134+
}
135+
uint32_t inline get_timeout() const {
136+
return timeout;
137+
}
138+
};
139+
123140
/** Control class for specifying test case attributes
124141
*
125142
* This class encapsulated control information about test cases which, when returned from
@@ -148,24 +165,26 @@ namespace v1 {
148165
*
149166
* In the future, more control information may be added transparently and backwards compatible.
150167
*/
151-
struct control_t
168+
struct control_t : private base_control_t
152169
{
153-
control_t() : repeat(REPEAT_UNDECLR), timeout(TIMEOUT_UNDECLR) {}
170+
control_t() : base_control_t(make_base_control_t(REPEAT_UNDECLR, TIMEOUT_UNDECLR)) {}
154171

155172
control_t(repeat_t repeat, uint32_t timeout_ms) :
156-
repeat(repeat), timeout(timeout_ms) {}
173+
base_control_t(make_base_control_t(repeat, timeout_ms)) {}
157174

158175
control_t(repeat_t repeat) :
159-
repeat(repeat), timeout(TIMEOUT_UNDECLR) {}
176+
base_control_t(make_base_control_t(repeat, TIMEOUT_UNDECLR)) {}
160177

161178
control_t(uint32_t timeout_ms) :
162-
repeat(REPEAT_UNDECLR), timeout(timeout_ms) {}
179+
base_control_t(make_base_control_t(REPEAT_UNDECLR, timeout_ms)) {}
163180

164-
control_t
165-
inline operator+(const control_t& rhs) const {
181+
control_t(const base_control_t& other) :
182+
base_control_t(other) {}
183+
184+
friend control_t operator+(const control_t& lhs, const control_t& rhs) {
166185
control_t result(
167-
repeat_t(this->repeat | rhs.repeat),
168-
(rhs.timeout == TIMEOUT_NONE) ? rhs.timeout : this->timeout);
186+
repeat_t(lhs.repeat | rhs.repeat),
187+
(rhs.timeout == TIMEOUT_NONE) ? rhs.timeout : lhs.timeout);
169188

170189
if (result.timeout != TIMEOUT_NONE && result.timeout > rhs.timeout) {
171190
result.timeout = rhs.timeout;
@@ -196,25 +215,46 @@ namespace v1 {
196215
}
197216

198217
private:
199-
repeat_t repeat;
200-
uint32_t timeout;
218+
static base_control_t make_base_control_t(repeat_t repeat, uint32_t timeout) {
219+
base_control_t result = {
220+
repeat,
221+
timeout
222+
};
223+
return result;
224+
}
225+
201226
friend class Harness;
202227
};
203228

229+
/// @see operator+ in control_t
230+
inline control_t operator+(const base_control_t& lhs, const base_control_t& rhs) {
231+
return control_t(lhs) + control_t(rhs);
232+
}
233+
234+
/// @see operator+ in control_t
235+
inline control_t operator+(const base_control_t& lhs, const control_t& rhs) {
236+
return control_t(lhs) + rhs;
237+
}
238+
239+
/// @see operator+ in control_t
240+
inline control_t operator+(const control_t& lhs, const base_control_t& rhs) {
241+
return lhs + control_t(rhs);
242+
}
243+
204244
/// does not repeat this test case and immediately moves on to the next one without timeout
205-
const control_t CaseNext(REPEAT_NONE, TIMEOUT_NONE);
245+
extern const base_control_t CaseNext;
206246

207247
/// does not repeat this test case, moves on to the next one
208-
const control_t CaseNoRepeat(REPEAT_NONE);
248+
extern const base_control_t CaseNoRepeat;
209249
/// repeats the test case handler with calling teardown and setup handlers
210-
const control_t CaseRepeatAll(REPEAT_ALL);
250+
extern const base_control_t CaseRepeatAll;
211251
/// repeats only the test case handler without calling teardown and setup handlers
212-
const control_t CaseRepeatHandler(REPEAT_HANDLER);
252+
extern const base_control_t CaseRepeatHandler;
213253

214254
/// No timeout, immediately moves on to the next case, but allows repeats
215-
const control_t CaseNoTimeout(TIMEOUT_NONE);
255+
extern const base_control_t CaseNoTimeout;
216256
/// Awaits until the callback is validated and never times out. Use with caution!
217-
const control_t CaseAwait(TIMEOUT_FOREVER);
257+
extern const base_control_t CaseAwait;
218258
/// Alias class for asynchronous timeout control in milliseconds
219259
inline control_t CaseTimeout(uint32_t ms) { return ms; }
220260

@@ -341,8 +381,11 @@ namespace v1 {
341381

342382

343383
// deprecations
344-
__deprecated_message("Use CaseRepeatAll instead.") const control_t CaseRepeat = CaseRepeatAll;
345-
__deprecated_message("Use CaseRepeatHandler instead.") const control_t CaseRepeatHandlerOnly = CaseRepeatHandler;
384+
__deprecated_message("Use CaseRepeatAll instead.")
385+
extern const base_control_t CaseRepeat;
386+
387+
__deprecated_message("Use CaseRepeatHandler instead.")
388+
extern const base_control_t CaseRepeatHandlerOnly;
346389

347390
__deprecated_message("Use REASON_NONE instead.") const failure_reason_t FAILURE_NONE = REASON_NONE;
348391
__deprecated_message("Use REASON_UNKNOWN instead.") const failure_reason_t FAILURE_UNKNOWN = REASON_UNKNOWN;

0 commit comments

Comments
 (0)