Mistake on this page?
Report an issue in GitHub or email us
utest_types.h
1 /****************************************************************************
2  * Copyright (c) 2015, ARM Limited, All Rights Reserved
3  * SPDX-License-Identifier: Apache-2.0
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License"); you may
6  * not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * 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.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  ****************************************************************************
17  */
18 
19 #ifndef UTEST_TYPES_H
20 #define UTEST_TYPES_H
21 
22 #include <stdint.h>
23 #include <stdbool.h>
24 #include <stdio.h>
25 #include "utest/utest_shim.h"
26 #include "SingletonPtr.h"
27 
28 namespace utest {
29 /** \addtogroup frameworks */
30 /** @{*/
31 namespace v1 {
32 
33  /// repeat_t
34  enum repeat_t {
35  REPEAT_UNDECLR = 0,
36  REPEAT_NONE = 1, ///< continue with the next test case
37 
38  REPEAT_ON_TIMEOUT = 2,
39  REPEAT_ON_VALIDATE = 4,
40  REPEAT_CASE_ONLY = 8,
41  REPEAT_SETUP_TEARDOWN = 16,
42 
43  REPEAT_MASK = REPEAT_ON_TIMEOUT | REPEAT_ON_VALIDATE | REPEAT_CASE_ONLY | REPEAT_SETUP_TEARDOWN,
44 
45  REPEAT_ALL_ON_TIMEOUT = REPEAT_SETUP_TEARDOWN | REPEAT_ON_TIMEOUT, ///< repeat the handler with setup and teardown on timeout
46  REPEAT_HANDLER_ON_TIMEOUT = REPEAT_CASE_ONLY | REPEAT_ON_TIMEOUT, ///< repeat only the handler on timeout
47  REPEAT_ALL = REPEAT_SETUP_TEARDOWN | REPEAT_ON_VALIDATE, ///< repeat the handler with setup and teardown
48  REPEAT_HANDLER = REPEAT_CASE_ONLY | REPEAT_ON_VALIDATE ///< repeat only the handler
49  };
50 
51  /// status_t
52  enum status_t {
53  STATUS_CONTINUE = -1, ///< continues testing
54  STATUS_IGNORE = -2, ///< ignores failure and continues testing
55  STATUS_ABORT = -3 ///< stops testing
56  };
57 
58  /// failure_reason_t
60  REASON_NONE = 0, ///< No failure occurred
61 
62  REASON_UNKNOWN = (1 << 0), ///< An unknown failure occurred
63  REASON_CASES = (1 << 1), ///< A failure occurred in at least one test case
64  REASON_EMPTY_CASE = (1 << 2), ///< The test case contains only empty handlers
65  REASON_TIMEOUT = (1 << 3), ///< An expected asynchronous call timed out
66  REASON_ASSERTION = (1 << 4), ///< An assertion failed
67 
68  REASON_TEST_SETUP = (1 << 5), ///< Test setup failed
69  REASON_TEST_TEARDOWN = (1 << 6), ///< Test teardown failed
70  REASON_CASE_SETUP = (1 << 7), ///< Case setup failed
71  REASON_CASE_HANDLER = (1 << 8), ///< Case handler failed
72  REASON_CASE_TEARDOWN = (1 << 9), ///< Case teardown failed
73 
74  REASON_CASE_INDEX = (1 << 10), ///< Case index out-of-range
75  REASON_SCHEDULER = (1 << 11), ///< Asynchronous callback scheduling failed
76 
77  REASON_IGNORE = 0x8000 ///< The failure may be ignored
78  };
79 
80  /// location_t
81  enum location_t {
82  LOCATION_NONE = 0, ///< No location information
83  LOCATION_TEST_SETUP, ///< A failure occurred in the test setup
84  LOCATION_TEST_TEARDOWN, ///< A failure occurred in the test teardown
85  LOCATION_CASE_SETUP, ///< A failure occurred in the case setup
86  LOCATION_CASE_HANDLER, ///< A failure occurred in the case handler
87  LOCATION_CASE_TEARDOWN, ///< A failure occurred in the case teardown
88  LOCATION_UNKNOWN ///< A failure occurred in an unknown location
89  };
90 
91  /// Contains the reason and location of the failure.
92  struct failure_t {
93  failure_t() : reason(REASON_NONE), location(LOCATION_NONE) {}
94  failure_t(failure_reason_t reason) : reason(reason), location(LOCATION_NONE) {}
95  failure_t(location_t location) : reason(REASON_NONE), location(location) {}
96  failure_t(failure_reason_t reason, location_t location) : reason(reason), location(location) {}
97 
98  /// Copy constructor
99  failure_t(const failure_t &obj){
100  reason = obj.reason;
101  location = obj.location;
102  }
103 
104  /// @returns a copy of the failure with the reason ignored.
105  failure_t ignored() const {
106  return failure_t(failure_reason_t(reason | REASON_IGNORE), location);
107  }
108 
109  failure_reason_t reason;
110  location_t location;
111  };
112 
113 
114  enum {
115  TIMEOUT_NONE = uint32_t(-1), ///< Do not use a timeout
116  TIMEOUT_UNDECLR = uint32_t(-2), ///< Timeout not explicitly specified, defaults to NONE
117  TIMEOUT_FOREVER = uint32_t(-3) ///< Never time out
118  };
119 
120  /// Stringifies a failure reason for understandable error messages.
121  const char* stringify(failure_reason_t reason);
122  /// Stringifies a failure for understandable error messages.
123  const char* stringify(failure_t failure);
124  /// Stringifies a location.
125  const char* stringify(location_t location);
126  /// Stringifies a status.
127  const char* stringify(utest::v1::status_t status);
128 
129  /** POD version of the class control_t.
130  * It is used to instantiate const control_t objects as PODs
131  * and prevent them to be included in the final binary.
132  * @note: control_pod_t can be converted to control_t by copy construction.
133  */
134  struct base_control_t {
135  repeat_t repeat;
136  uint32_t timeout;
137 
138  repeat_t inline get_repeat() const {
139  return repeat;
140  }
141  uint32_t inline get_timeout() const {
142  return timeout;
143  }
144  };
145 
146  /** Control class for specifying test case attributes
147  *
148  * This class encapsulated control information about test cases which, when returned from
149  * a test case influences the behavior of the test harness.
150  * Instead of using this class directly it is recommended to use the aliases for clearer
151  * semantics:
152  * @code
153  * control_t test_case(const size_t call_count) {
154  * // repeat 5 times for a total of 6 calls
155  * return (call_count < 6) ? CaseRepeatHandler : CaseNext;
156  * }
157  * @endcode
158  *
159  * This class overloads the `+` operator to implement something similiar to saturated arbitration:
160  * - The lower timeout value "wins".
161  * - A more involved repeat "wins" (ie. `ALL` > 'HANDLER' > 'NONE').
162  * - Next Case always wins.
163  *
164  * You may then add timeouts and repeats together:
165  * @code
166  * control_t test_case(const size_t call_count) {
167  * // repeat 5 times for a total of 6 calls, each with a 500ms asynchronous timeout
168  * return CaseTimeout(500) + ((call_count < 6) ? CaseRepeatAll : CaseNoRepeat);
169  * }
170  * @endcode
171  *
172  * In the future, more control information may be added transparently and backwards compatible.
173  */
174  struct control_t : private base_control_t
175  {
176  control_t() : base_control_t(make_base_control_t(REPEAT_UNDECLR, TIMEOUT_UNDECLR)) {}
177 
178  control_t(repeat_t repeat, uint32_t timeout_ms) :
179  base_control_t(make_base_control_t(repeat, timeout_ms)) {}
180 
181  control_t(repeat_t repeat) :
182  base_control_t(make_base_control_t(repeat, TIMEOUT_UNDECLR)) {}
183 
184  control_t(uint32_t timeout_ms) :
185  base_control_t(make_base_control_t(REPEAT_UNDECLR, timeout_ms)) {}
186 
187  control_t(const base_control_t& other) :
188  base_control_t(other) {}
189 
190  friend control_t operator+(const control_t& lhs, const control_t& rhs) {
191  control_t result(
192  repeat_t(lhs.repeat | rhs.repeat),
193  (rhs.timeout == TIMEOUT_NONE) ? rhs.timeout : lhs.timeout);
194 
195  if (result.timeout != TIMEOUT_NONE && result.timeout > rhs.timeout) {
196  result.timeout = rhs.timeout;
197  }
198 
199  if (result.repeat & REPEAT_NONE) {
200  result.repeat = REPEAT_NONE;
201  }
202  else {
203  if (result.repeat & REPEAT_SETUP_TEARDOWN) {
204  result.repeat = repeat_t(result.repeat & ~REPEAT_CASE_ONLY);
205  }
206  if (result.timeout == TIMEOUT_NONE && result.repeat & REPEAT_ON_TIMEOUT) {
207  result.repeat = repeat_t(result.repeat & ~REPEAT_ON_TIMEOUT);
208  }
209  }
210 
211  return result;
212  }
213 
214  repeat_t
215  inline get_repeat() const {
216  return repeat;
217  }
218  uint32_t
219  inline get_timeout() const {
220  return timeout;
221  }
222 
223  private:
224  static base_control_t make_base_control_t(repeat_t repeat, uint32_t timeout) {
225  base_control_t result = {
226  repeat,
227  timeout
228  };
229  return result;
230  }
231 
232  friend class Harness;
233  };
234 
235  /// @see operator+ in control_t
236  inline control_t operator+(const base_control_t& lhs, const base_control_t& rhs) {
237  return control_t(lhs) + control_t(rhs);
238  }
239 
240  /// @see operator+ in control_t
241  inline control_t operator+(const base_control_t& lhs, const control_t& rhs) {
242  return control_t(lhs) + rhs;
243  }
244 
245  /// @see operator+ in control_t
246  inline control_t operator+(const control_t& lhs, const base_control_t& rhs) {
247  return lhs + control_t(rhs);
248  }
249 
250  /// does not repeat this test case and immediately moves on to the next one without timeout
251  extern const base_control_t CaseNext;
252 
253  /// does not repeat this test case, moves on to the next one
254  extern const base_control_t CaseNoRepeat;
255  /// repeats the test case handler with calling teardown and setup handlers
256  extern const base_control_t CaseRepeatAll;
257  /// repeats only the test case handler without calling teardown and setup handlers
258  extern const base_control_t CaseRepeatHandler;
259 
260  /// No timeout, immediately moves on to the next case, but allows repeats
261  extern const base_control_t CaseNoTimeout;
262  /// Awaits until the callback is validated and never times out. Use with caution!
263  extern const base_control_t CaseAwait;
264  /// Alias class for asynchronous timeout control in milliseconds
265  inline control_t CaseTimeout(uint32_t ms) { return ms; }
266 
267  /// Alias class for asynchronous timeout control in milliseconds and
268  /// repeats the test case handler with calling teardown and setup handlers
270  /// Alias class for asynchronous timeout control in milliseconds and
271  /// repeats only the test case handler without calling teardown and setup handlers
273 
274  class Case; // forward declaration
275 
276  /** Test setup handler.
277  *
278  * This handler is called before execution of any test case and
279  * allows you to initialize your common test environment.
280  *
281  * @param number_of_cases the total number of test cases in the test specification
282  *
283  * @returns
284  * You can return `STATUS_ABORT` if you initialization failed and the test teardown handler will
285  * then be called with the `REASON_SETUP`.
286  */
287  typedef utest::v1::status_t (*test_setup_handler_t)(const size_t number_of_cases);
288 
289  /** Test teardown handler.
290  *
291  * This handler is called after execution of all test case or if test execution is aborted.
292  * You can use this handler to de-initialize your test environment and output test statistics.
293  * The failure argument contains the immediate reason why this handler is called.
294  * If the test completed normally without failures, this will contain `REASON_NONE`.
295  *
296  * After execution of this handler, the test harness will stop execution.
297  *
298  * @param passed the number of cases without failures
299  * @param failed the number of cases with at least one failure
300  * @param failure the reason why this handler was called
301  */
302  typedef void (*test_teardown_handler_t)(const size_t passed, const size_t failed, const failure_t failure);
303 
304  /** Test failure handler.
305  *
306  * This handler is called anytime a failure occurs during the execution of a test speficication.
307  * The handler only allows logging of failures and cannot influence test execution.
308  *
309  * @param failure the reason why this handler was called
310  */
311  typedef void (*test_failure_handler_t)(const failure_t reason);
312 
313  /** Test case setup handler.
314  *
315  * This handler is called before execution of each test case and
316  * allows you to modify your environment before each test case.
317  *
318  * @param source the test case to be setup
319  * @param index_of_case the current index of the test case within the specification
320  *
321  * @returns
322  * You can return `STATUS_ABORT` to indicate that your setup failed, which will call the case
323  * failure handler with `REASON_SETUP` and then the case teardown handler with `REASON_SETUP`.
324  * This gives the teardown handler a chance to clean up a failed setup.
325  */
326  typedef utest::v1::status_t (*case_setup_handler_t)(const Case *const source, const size_t index_of_case);
327 
328  /** Primitive test case handler
329  *
330  * This handler is called only if the case setup succeeded and is followed by the test case teardown handler.
331  *
332  * @note This handler is executed only once.
333  */
334  typedef void (*case_handler_t)(void);
335 
336  /** Complex test case handler
337  *
338  * This handler is called only if the case setup succeeded and then may be repeated or
339  * awaiting a asynchronous callback, depending on the return modifiers.
340  *
341  * @returns
342  * A combination of control modifiers.
343  */
345 
346  /** Test case handler (repeatable)
347  *
348  * This handler is called only if the case setup succeeded and then may be repeated or
349  * awaiting a asynchronous callback, depending on the return modifiers.
350  *
351  * @param call_count starting at `1`, contains the number of times this handler has been called
352  *
353  * @returns
354  * A combination of control modifiers.
355  */
356  typedef control_t (*case_call_count_handler_t)(const size_t call_count);
357 
358  /** Test case teardown handler.
359  *
360  * This handler is called after execution of each test case or all repeated test cases and
361  * allows you to reset your environment after each test case.
362  *
363  * @param source the test case to be torn down
364  * @param passed the number of cases without failures (can be >1 for repeated test cases)
365  * @param failed the number failures (can be larger than the number of (repeated) test cases)
366  * @param failure the reason why this handler was called
367  *
368  * @returns
369  * You can return `STATUS_ABORT` to indicate that your teardown failed, which will call the case
370  * failure handler with `REASON_TEARDOWN`.
371  */
372  typedef utest::v1::status_t (*case_teardown_handler_t)(const Case *const source, const size_t passed, const size_t failed, const failure_t reason);
373 
374  /** Test case failure handler.
375  *
376  * This handler is called whenever a failure occurred during the setup, execution or teardown.
377  *
378  * @param source the test case in which the failure occurred
379  * @param reason the reason why this handler was called
380  *
381  * @returns
382  * You can return `STATUS_ABORT` to indicate that this failure is non-recoverable, which will call the case
383  * teardown handler with reason. If a failure occurs during teardown, the teardown will not be called again.
384  * You may return `STATUS_IGNORE` which will cause the harness to ignore and not count the failure.
385  */
386  typedef utest::v1::status_t (*case_failure_handler_t)(const Case *const source, const failure_t reason);
387 
388 
389  // deprecations
390  __deprecated_message("Use CaseRepeatAll instead.")
391  extern const base_control_t CaseRepeat;
392 
393  __deprecated_message("Use CaseRepeatHandler instead.")
394  extern const base_control_t CaseRepeatHandlerOnly;
395 
396  __deprecated_message("Use REASON_NONE instead.") const failure_reason_t FAILURE_NONE = REASON_NONE;
397  __deprecated_message("Use REASON_UNKNOWN instead.") const failure_reason_t FAILURE_UNKNOWN = REASON_UNKNOWN;
398  __deprecated_message("Use REASON_CASES instead.") const failure_reason_t FAILURE_CASES = REASON_CASES;
399  __deprecated_message("Use REASON_EMPTY_CASE instead.") const failure_reason_t FAILURE_EMPTY_CASE = REASON_EMPTY_CASE;
400  __deprecated_message("Use REASON_TIMEOUT instead.") const failure_reason_t FAILURE_TIMEOUT = REASON_TIMEOUT;
401  __deprecated_message("Use REASON_ASSERTION instead.") const failure_reason_t FAILURE_ASSERTION = REASON_ASSERTION;
402  __deprecated_message("Use REASON_CASE_SETUP instead.") const failure_reason_t FAILURE_SETUP = REASON_CASE_SETUP;
403  __deprecated_message("Use REASON_CASE_TEARDOWN instead.") const failure_reason_t FAILURE_TEARDOWN = REASON_CASE_TEARDOWN;
404  __deprecated_message("Use REASON_IGNORE instead.") const failure_reason_t FAILURE_IGNORE = REASON_IGNORE;
405 
406 
407 } // namespace v1
408 } // namespace utest
409 
410 #endif // UTEST_TYPES_H
411 
412 /** @}*/
Test case wrapper class.
Definition: utest_case.h:108
An assertion failed.
Definition: utest_types.h:66
stops testing
Definition: utest_types.h:55
A failure occurred in the case setup.
Definition: utest_types.h:85
Control class for specifying test case attributes.
Definition: utest_types.h:174
const base_control_t CaseAwait
Awaits until the callback is validated and never times out. Use with caution!
repeat_t
repeat_t
Definition: utest_types.h:34
const char * stringify(utest::v1::status_t status)
Stringifies a status.
Case index out-of-range.
Definition: utest_types.h:74
repeat only the handler on timeout
Definition: utest_types.h:46
const base_control_t CaseNext
does not repeat this test case and immediately moves on to the next one without timeout ...
A failure occurred in the test setup.
Definition: utest_types.h:83
const base_control_t CaseNoRepeat
does not repeat this test case, moves on to the next one
An unknown failure occurred.
Definition: utest_types.h:62
A failure occurred in an unknown location.
Definition: utest_types.h:88
Case setup failed.
Definition: utest_types.h:70
A failure occurred in at least one test case.
Definition: utest_types.h:63
POD version of the class control_t.
Definition: utest_types.h:134
utest::v1::status_t(* case_setup_handler_t)(const Case *const source, const size_t index_of_case)
Test case setup handler.
Definition: utest_types.h:326
const base_control_t CaseNoTimeout
No timeout, immediately moves on to the next case, but allows repeats.
Do not use a timeout.
Definition: utest_types.h:115
Test Harness.
Definition: utest_harness.h:46
const base_control_t CaseRepeatAll
repeats the test case handler with calling teardown and setup handlers
No failure occurred.
Definition: utest_types.h:60
Case handler failed.
Definition: utest_types.h:71
repeat the handler with setup and teardown
Definition: utest_types.h:47
Timeout not explicitly specified, defaults to NONE.
Definition: utest_types.h:116
utest::v1::status_t(* case_teardown_handler_t)(const Case *const source, const size_t passed, const size_t failed, const failure_t reason)
Test case teardown handler.
Definition: utest_types.h:372
A failure occurred in the test teardown.
Definition: utest_types.h:84
control_t CaseTimeout(uint32_t ms)
Alias class for asynchronous timeout control in milliseconds.
Definition: utest_types.h:265
Contains the reason and location of the failure.
Definition: utest_types.h:92
utest::v1::status_t(* test_setup_handler_t)(const size_t number_of_cases)
Test setup handler.
Definition: utest_types.h:287
continue with the next test case
Definition: utest_types.h:36
Test teardown failed.
Definition: utest_types.h:69
void(* test_teardown_handler_t)(const size_t passed, const size_t failed, const failure_t failure)
Test teardown handler.
Definition: utest_types.h:302
A failure occurred in the case handler.
Definition: utest_types.h:86
control_t CaseRepeatAllOnTimeout(uint32_t ms)
Alias class for asynchronous timeout control in milliseconds and repeats the test case handler with c...
Definition: utest_types.h:269
control_t operator+(const control_t &lhs, const base_control_t &rhs)
Definition: utest_types.h:246
A failure occurred in the case teardown.
Definition: utest_types.h:87
void(* test_failure_handler_t)(const failure_t reason)
Test failure handler.
Definition: utest_types.h:311
failure_reason_t
failure_reason_t
Definition: utest_types.h:59
failure_t ignored() const
Definition: utest_types.h:105
repeat only the handler
Definition: utest_types.h:48
ignores failure and continues testing
Definition: utest_types.h:54
Test setup failed.
Definition: utest_types.h:68
The test case contains only empty handlers.
Definition: utest_types.h:64
void(* case_handler_t)(void)
Primitive test case handler.
Definition: utest_types.h:334
An expected asynchronous call timed out.
Definition: utest_types.h:65
Case teardown failed.
Definition: utest_types.h:72
failure_t(const failure_t &obj)
Copy constructor.
Definition: utest_types.h:99
utest::v1::status_t(* case_failure_handler_t)(const Case *const source, const failure_t reason)
Test case failure handler.
Definition: utest_types.h:386
continues testing
Definition: utest_types.h:53
control_t(* case_call_count_handler_t)(const size_t call_count)
Test case handler (repeatable)
Definition: utest_types.h:356
const base_control_t CaseRepeatHandler
repeats only the test case handler without calling teardown and setup handlers
No location information.
Definition: utest_types.h:82
control_t CaseRepeatHandlerOnTimeout(uint32_t ms)
Alias class for asynchronous timeout control in milliseconds and repeats only the test case handler w...
Definition: utest_types.h:272
control_t(* case_control_handler_t)(void)
Complex test case handler.
Definition: utest_types.h:344
location_t
location_t
Definition: utest_types.h:81
Asynchronous callback scheduling failed.
Definition: utest_types.h:75
repeat the handler with setup and teardown on timeout
Definition: utest_types.h:45
status_t
status_t
Definition: utest_types.h:52
The failure may be ignored.
Definition: utest_types.h:77
Important Information for this Arm website

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.