From cfcc2cbf7aa4e6aeb6dca83d57cf2dae610d4d65 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Thu, 31 Jan 2019 14:45:31 +0100 Subject: Add RTEMS Test Framework Update #3199. --- cpukit/Makefile.am | 12 + cpukit/headers.am | 1 + cpukit/include/t.h | 2377 +++++++++++++++++++++++++++++++++ cpukit/libtest/t-test-checks-eno.c | 145 ++ cpukit/libtest/t-test-checks-psx.c | 17 + cpukit/libtest/t-test-checks.c | 328 +++++ cpukit/libtest/t-test-hash-sha256.c | 100 ++ cpukit/libtest/t-test-malloc.c | 112 ++ cpukit/libtest/t-test-rtems-fds.c | 83 ++ cpukit/libtest/t-test-rtems-heap.c | 112 ++ cpukit/libtest/t-test-rtems-measure.c | 837 ++++++++++++ cpukit/libtest/t-test-rtems-objs.c | 447 +++++++ cpukit/libtest/t-test-rtems.c | 51 + cpukit/libtest/t-test-time.c | 233 ++++ cpukit/libtest/t-test.c | 888 ++++++++++++ 15 files changed, 5743 insertions(+) create mode 100644 cpukit/include/t.h create mode 100644 cpukit/libtest/t-test-checks-eno.c create mode 100644 cpukit/libtest/t-test-checks-psx.c create mode 100644 cpukit/libtest/t-test-checks.c create mode 100644 cpukit/libtest/t-test-hash-sha256.c create mode 100644 cpukit/libtest/t-test-malloc.c create mode 100644 cpukit/libtest/t-test-rtems-fds.c create mode 100644 cpukit/libtest/t-test-rtems-heap.c create mode 100644 cpukit/libtest/t-test-rtems-measure.c create mode 100644 cpukit/libtest/t-test-rtems-objs.c create mode 100644 cpukit/libtest/t-test-rtems.c create mode 100644 cpukit/libtest/t-test-time.c create mode 100644 cpukit/libtest/t-test.c diff --git a/cpukit/Makefile.am b/cpukit/Makefile.am index 9e77facccb..b4315819ac 100644 --- a/cpukit/Makefile.am +++ b/cpukit/Makefile.am @@ -1837,6 +1837,18 @@ librtemstest_a_SOURCES += libtest/testbusy.c librtemstest_a_SOURCES += libtest/testextension.c librtemstest_a_SOURCES += libtest/testparallel.c librtemstest_a_SOURCES += libtest/testwrappers.c +librtemstest_a_SOURCES += libtest/t-test.c +librtemstest_a_SOURCES += libtest/t-test-checks.c +librtemstest_a_SOURCES += libtest/t-test-checks-eno.c +librtemstest_a_SOURCES += libtest/t-test-checks-psx.c +librtemstest_a_SOURCES += libtest/t-test-hash-sha256.c +librtemstest_a_SOURCES += libtest/t-test-malloc.c +librtemstest_a_SOURCES += libtest/t-test-rtems.c +librtemstest_a_SOURCES += libtest/t-test-rtems-fds.c +librtemstest_a_SOURCES += libtest/t-test-rtems-heap.c +librtemstest_a_SOURCES += libtest/t-test-rtems-measure.c +librtemstest_a_SOURCES += libtest/t-test-rtems-objs.c +librtemstest_a_SOURCES += libtest/t-test-time.c project_lib_LIBRARIES += libftpd.a diff --git a/cpukit/headers.am b/cpukit/headers.am index 92d4022edd..69cdb525ef 100644 --- a/cpukit/headers.am +++ b/cpukit/headers.am @@ -17,6 +17,7 @@ include_HEADERS += include/poll.h include_HEADERS += include/rtems.h include_HEADERS += include/sha256.h include_HEADERS += include/sha512.h +include_HEADERS += include/t.h include_HEADERS += include/xz.h include_HEADERS += include/zconf.h include_HEADERS += include/zlib.h diff --git a/cpukit/include/t.h b/cpukit/include/t.h new file mode 100644 index 0000000000..10d9096be2 --- /dev/null +++ b/cpukit/include/t.h @@ -0,0 +1,2377 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (C) 2018, 2019 embedded brains GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef THE_T_TEST_FRAMEWORK_H +#define THE_T_TEST_FRAMEWORK_H + +#include +#include +#include +#include +#include + +#ifdef __rtems__ +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup RTEMSTestFramework RTEMS Test Framework + * + * @brief The RTEMS Test Framework helps you to write tests. + * + * @{ + */ + +typedef enum { + T_QUIET, + T_NORMAL, + T_VERBOSE +} T_verbosity; + +typedef struct T_fixture { + void (*setup)(void *); + void (*stop)(void *); + void (*teardown)(void *); + void *initial_context; +} T_fixture; + +#define T_ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) + +/* + * The __FILE__ includes the full file path from the command line. Enable the + * build system to give a sorter file name via a command line define. + */ +#ifndef T_FILE_NAME +#define T_FILE_NAME __FILE__ +#endif + +/** @} */ + +/** + * @defgroup RTEMSTestFrameworkImpl RTEMS Test Framework Implementation + * + * @ingroup RTEMSTestFramework + * + * @brief Implementation details. + * + * @{ + */ + +typedef struct T_case_context { + const char *name; + void (*body)(void); + const T_fixture *fixture; + const struct T_case_context *next; +} T_case_context; + +void T_case_register(T_case_context *); + +#define T_CHECK_STOP 1U + +#define T_CHECK_QUIET 2U + +#define T_CHECK_STEP_FLAG 4U + +#define T_CHECK_STEP_TO_FLAGS(step) ((unsigned int)(step) << 8) + +#define T_CHECK_STEP_FROM_FLAGS(flags) ((flags) >> 8) + +#define T_CHECK_STEP(step) (T_CHECK_STEP_TO_FLAGS(step) | T_CHECK_STEP_FLAG) + +typedef struct { + const char *file; + int line; + unsigned int flags; +} T_check_context; + +typedef struct { + T_check_context base; + const char *msg; +} T_check_context_msg; + +void T_check_true(bool, const T_check_context *, const char *, ...); + +#define T_flags_true(a, flags, ...) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_true(a, &T_check_instance, __VA_ARGS__); \ +} + +#define T_flags_eq(a, e, flags, ...) \ + T_flags_true((a) == (e), flags, __VA_ARGS__) + +#define T_flags_ne(a, e, flags, ...) \ + T_flags_true((a) != (e), flags, __VA_ARGS__) + +void T_check_eq_ptr(const void *, const T_check_context_msg *, const void *); + +#define T_flags_eq_ptr(a, e, flags, sa, se) \ +{ \ + static const T_check_context_msg T_check_instance = { \ + { T_FILE_NAME, __LINE__, flags }, sa " == " se }; \ + T_check_eq_ptr(a, &T_check_instance, e); \ +} + +void T_check_ne_ptr(const void *, const T_check_context_msg *, const void *); + +#define T_flags_ne_ptr(a, e, flags, sa, se) \ +{ \ + static const T_check_context_msg T_check_instance = { \ + { T_FILE_NAME, __LINE__, flags }, sa " != " se }; \ + T_check_ne_ptr(a, &T_check_instance, e); \ +} + +void T_check_null(const void *, const T_check_context_msg *); + +#define T_flags_null(a, flags, sa) \ +{ \ + static const T_check_context_msg T_check_instance = { \ + { T_FILE_NAME, __LINE__, flags }, sa }; \ + T_check_null(a, &T_check_instance); \ +} + +void T_check_not_null(const void *, const T_check_context_msg *); + +#define T_flags_not_null(a, flags, sa) \ +{ \ + static const T_check_context_msg T_check_instance = { \ + { T_FILE_NAME, __LINE__, flags }, sa }; \ + T_check_not_null(a, &T_check_instance); \ +} + +void T_check_eq_mem(const void *, const T_check_context_msg *, const void *, + size_t); + +#define T_flags_eq_mem(a, e, n, flags, sa, se, sn) \ +{ \ + static const T_check_context_msg T_check_instance = { \ + { T_FILE_NAME, __LINE__, flags }, \ + "memcmp(" sa ", " se ", " sn ") == 0" }; \ + T_check_eq_mem(a, &T_check_instance, e, n); \ +} + +void T_check_ne_mem(const void *, const T_check_context_msg *, const void *, + size_t); + +#define T_flags_ne_mem(a, e, n, flags, sa, se, sn) \ +{ \ + static const T_check_context_msg T_check_instance = { \ + { T_FILE_NAME, __LINE__, flags }, \ + "memcmp(" sa ", " se ", " sn ") != 0" }; \ + T_check_ne_mem(a, &T_check_instance, e, n); \ +} + +void T_check_eq_str(const char *, const T_check_context *, const char *); + +#define T_flags_eq_str(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_eq_str(a, &T_check_instance, e); \ +} + +void T_check_ne_str(const char *, const T_check_context *, const char *); + +#define T_flags_ne_str(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_ne_str(a, &T_check_instance, e); \ +} + +void T_check_eq_nstr(const char *, const T_check_context *, const char *, + size_t); + +#define T_flags_eq_nstr(a, e, n, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_eq_nstr(a, &T_check_instance, e, n); \ +} + +void T_check_ne_nstr(const char *, const T_check_context *, const char *, + size_t); + +#define T_flags_ne_nstr(a, e, n, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_ne_nstr(a, &T_check_instance, e, n); \ +} + +void T_check_eq_char(char, const T_check_context *, char); + +#define T_flags_eq_char(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_eq_char(a, &T_check_instance, e); \ +} + +void T_check_ne_char(char, const T_check_context *, char); + +#define T_flags_ne_char(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_ne_char(a, &T_check_instance, e); \ +} + +void T_check_eq_int(int, const T_check_context *, int); + +#define T_flags_eq_int(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_eq_int(a, &T_check_instance, e); \ +} + +void T_check_ne_int(int, const T_check_context *, int); + +#define T_flags_ne_int(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_ne_int(a, &T_check_instance, e); \ +} + +void T_check_ge_int(int, const T_check_context *, int); + +#define T_flags_ge_int(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_ge_int(a, &T_check_instance, e); \ +} + +void T_check_gt_int(int, const T_check_context *, int); + +#define T_flags_gt_int(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_gt_int(a, &T_check_instance, e); \ +} + +void T_check_le_int(int, const T_check_context *, int); + +#define T_flags_le_int(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_le_int(a, &T_check_instance, e); \ +} + +void T_check_lt_int(int, const T_check_context *, int); + +#define T_flags_lt_int(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_lt_int(a, &T_check_instance, e); \ +} + +void T_check_eq_uint(unsigned int, const T_check_context *, unsigned int); + +#define T_flags_eq_uint(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_eq_uint(a, &T_check_instance, e); \ +} + +void T_check_ne_uint(unsigned int, const T_check_context *, unsigned int); + +#define T_flags_ne_uint(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_ne_uint(a, &T_check_instance, e); \ +} + +void T_check_ge_uint(unsigned int, const T_check_context *, unsigned int); + +#define T_flags_ge_uint(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_ge_uint(a, &T_check_instance, e); \ +} + +void T_check_gt_uint(unsigned int, const T_check_context *, unsigned int); + +#define T_flags_gt_uint(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_gt_uint(a, &T_check_instance, e); \ +} + +void T_check_le_uint(unsigned int, const T_check_context *, unsigned int); + +#define T_flags_le_uint(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_le_uint(a, &T_check_instance, e); \ +} + +void T_check_lt_uint(unsigned int, const T_check_context *, unsigned int); + +#define T_flags_lt_uint(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_lt_uint(a, &T_check_instance, e); \ +} + +void T_check_eq_long(long, const T_check_context *, long); + +#define T_flags_eq_long(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_eq_long(a, &T_check_instance, e); \ +} + +void T_check_ne_long(long, const T_check_context *, long); + +#define T_flags_ne_long(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_ne_long(a, &T_check_instance, e); \ +} + +void T_check_ge_long(long, const T_check_context *, long); + +#define T_flags_ge_long(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_ge_long(a, &T_check_instance, e); \ +} + +void T_check_gt_long(long, const T_check_context *, long); + +#define T_flags_gt_long(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_gt_long(a, &T_check_instance, e); \ +} + +void T_check_le_long(long, const T_check_context *, long); + +#define T_flags_le_long(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_le_long(a, &T_check_instance, e); \ +} + +void T_check_lt_long(long, const T_check_context *, long); + +#define T_flags_lt_long(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_lt_long(a, &T_check_instance, e); \ +} + +void T_check_eq_ulong(unsigned long, const T_check_context *, unsigned long); + +#define T_flags_eq_ulong(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_eq_ulong(a, &T_check_instance, e); \ +} + +void T_check_ne_ulong(unsigned long, const T_check_context *, unsigned long); + +#define T_flags_ne_ulong(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_ne_ulong(a, &T_check_instance, e); \ +} + +void T_check_ge_ulong(unsigned long, const T_check_context *, unsigned long); + +#define T_flags_ge_ulong(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_ge_ulong(a, &T_check_instance, e); \ +} + +void T_check_gt_ulong(unsigned long, const T_check_context *, unsigned long); + +#define T_flags_gt_ulong(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_gt_ulong(a, &T_check_instance, e); \ +} + +void T_check_le_ulong(unsigned long, const T_check_context *, unsigned long); + +#define T_flags_le_ulong(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_le_ulong(a, &T_check_instance, e); \ +} + +void T_check_lt_ulong(unsigned long, const T_check_context *, unsigned long); + +#define T_flags_lt_ulong(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_lt_ulong(a, &T_check_instance, e); \ +} + +void T_check_eq_ll(long long, const T_check_context *, long long); + +#define T_flags_eq_ll(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_eq_ll(a, &T_check_instance, e); \ +} + +void T_check_ne_ll(long long, const T_check_context *, long long); + +#define T_flags_ne_ll(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_ne_ll(a, &T_check_instance, e); \ +} + +void T_check_ge_ll(long long, const T_check_context *, long long); + +#define T_flags_ge_ll(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_ge_ll(a, &T_check_instance, e); \ +} + +void T_check_gt_ll(long long, const T_check_context *, long long); + +#define T_flags_gt_ll(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_gt_ll(a, &T_check_instance, e); \ +} + +void T_check_le_ll(long long, const T_check_context *, long long); + +#define T_flags_le_ll(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_le_ll(a, &T_check_instance, e); \ +} + +void T_check_lt_ll(long long, const T_check_context *, long long); + +#define T_flags_lt_ll(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_lt_ll(a, &T_check_instance, e); \ +} + +void T_check_eq_ull(unsigned long long, const T_check_context *, + unsigned long long); + +#define T_flags_eq_ull(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_eq_ull(a, &T_check_instance, e); \ +} + +void T_check_ne_ull(unsigned long long, const T_check_context *, + unsigned long long); + +#define T_flags_ne_ull(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_ne_ull(a, &T_check_instance, e); \ +} + +void T_check_ge_ull(unsigned long long, const T_check_context *, + unsigned long long); + +#define T_flags_ge_ull(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_ge_ull(a, &T_check_instance, e); \ +} + +void T_check_gt_ull(unsigned long long, const T_check_context *, + unsigned long long); + +#define T_flags_gt_ull(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_gt_ull(a, &T_check_instance, e); \ +} + +void T_check_le_ull(unsigned long long, const T_check_context *, + unsigned long long); + +#define T_flags_le_ull(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_le_ull(a, &T_check_instance, e); \ +} + +void T_check_lt_ull(unsigned long long, const T_check_context *, + unsigned long long); + +#define T_flags_lt_ull(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_lt_ull(a, &T_check_instance, e); \ +} + +void T_check_eno(int, const T_check_context *, int); + +#define T_flags_eno(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_eno(a, &T_check_instance, e); \ +} + +void T_check_eno_success(int, const T_check_context *); + +#define T_flags_eno_success(a, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_eno_success(a, &T_check_instance); \ +} + +void T_check_psx_error(int, const T_check_context *, int); + +#define T_flags_psx_error(a, eno, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_psx_error(a, &T_check_instance, eno); \ +} + +void T_check_psx_success(int, const T_check_context *); + +#define T_flags_psx_success(a, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_psx_success(a, &T_check_instance); \ +} + +/** @} */ + +int T_printf(char const *, ...); + +int T_vprintf(char const *, va_list); + +int T_snprintf(char *, size_t, const char *, ...); + +void T_log(T_verbosity, char const *, ...); + +const char *T_case_name(void); + +T_verbosity T_set_verbosity(T_verbosity); + +/** + * @defgroup RTEMSTestFrameworkChecksBool Boolean Checks + * + * @ingroup RTEMSTestFramework + * + * @brief Checks for boolean expressions. + * + * @{ + */ + +#define T_true(a, ...) T_flags_true(a, 0, __VA_ARGS__) +#define T_assert_true(a, ...) T_flags_true(a, T_CHECK_STOP, __VA_ARGS__) +#define T_quiet_true(a, ...) T_flags_true(a, T_CHECK_QUIET, __VA_ARGS__) +#define T_step_true(s, a, ...) T_flags_true(a, T_CHECK_STEP(s), __VA_ARGS__) +#define T_step_assert_true(s, a, ...) \ + T_flags_true(a, T_CHECK_STEP(s) | T_CHECK_STOP, __VA_ARGS__) + +#define T_false(a, ...) T_flags_true(!(a), 0, __VA_ARGS__) +#define T_assert_false(a, ...) T_flags_true(!(a), T_CHECK_STOP, __VA_ARGS__) +#define T_quiet_false(a, ...) T_flags_true(!(a), T_CHECK_QUIET, __VA_ARGS__) +#define T_step_false(s, a, ...) T_flags_true(!(a), T_CHECK_STEP(s), __VA_ARGS__) +#define T_step_assert_false(s, a, ...) \ + T_flags_true(!(a), T_CHECK_STEP(s) | T_CHECK_STOP, __VA_ARGS__) + +/** @} */ + +/** + * @defgroup RTEMSTestFrameworkChecksGeneric Generic Checks + * + * @ingroup RTEMSTestFramework + * + * @brief Checks for data types with an equality or inequality operator. + * + * @{ + */ + +#define T_eq(a, e, ...) T_flags_eq(a, e, 0, __VA_ARGS__) +#define T_assert_eq(a, e, ...) T_flags_eq(a, e, T_CHECK_STOP, __VA_ARGS__) +#define T_quiet_eq(a, e, ...) T_flags_eq(a, e, T_CHECK_QUIET, __VA_ARGS__) +#define T_step_eq(s, a, e, ...) T_flags_eq(a, e, T_CHECK_STEP(s), __VA_ARGS__) +#define T_step_assert_eq(s, a, e, ...) \ + T_flags_eq(a, e, T_CHECK_STEP(s) | T_CHECK_STOP, __VA_ARGS__) + +#define T_ne(a, e, ...) T_flags_ne(a, e, 0, __VA_ARGS__) +#define T_assert_ne(a, e, ...) T_flags_ne(a, e, T_CHECK_STOP, __VA_ARGS__) +#define T_quiet_ne(a, e, ...) T_flags_ne(a, e, T_CHECK_QUIET, __VA_ARGS__) +#define T_step_ne(s, a, e, ...) T_flags_ne(a, e, T_CHECK_STEP(s), __VA_ARGS__) +#define T_step_assert_ne(s, a, e, ...) \ + T_flags_ne(a, e, T_CHECK_STEP(s) | T_CHECK_STOP, __VA_ARGS__) + +/** @} */ + +/** + * @defgroup RTEMSTestFrameworkChecksPointer Pointer Checks + * + * @ingroup RTEMSTestFramework + * + * @brief Checks for pointers. + * + * @{ + */ + +#define T_eq_ptr(a, e) T_flags_eq_ptr(a, e, 0, #a, #e) +#define T_assert_eq_ptr(a, e) T_flags_eq_ptr(a, e, T_CHECK_STOP, #a, #e) +#define T_quiet_eq_ptr(a, e) T_flags_eq_ptr(a, e, T_CHECK_QUIET, #a, #e) +#define T_step_eq_ptr(s, a, e) T_flags_eq_ptr(a, e, T_CHECK_STEP(s), #a, #e) +#define T_step_assert_eq_ptr(s, a, e) \ + T_flags_eq_ptr(a, e, T_CHECK_STEP(s) | T_CHECK_STOP, #a, #e) + +#define T_ne_ptr(a, e) T_flags_ne_ptr(a, e, 0, #a, #e) +#define T_assert_ne_ptr(a, e) T_flags_ne_ptr(a, e, T_CHECK_STOP, #a, #e) +#define T_quiet_ne_ptr(a, e) T_flags_ne_ptr(a, e, T_CHECK_QUIET, #a, #e) +#define T_step_ne_ptr(s, a, e) T_flags_ne_ptr(a, e, T_CHECK_STEP(s), #a, #e) +#define T_step_assert_ne_ptr(s, a, e) \ + T_flags_ne_ptr(a, e, T_CHECK_STEP(s) | T_CHECK_STOP, #a, #e) + +#define T_null(a) T_flags_null(a, 0, #a) +#define T_assert_null(a) T_flags_null(a, T_CHECK_STOP, #a) +#define T_quiet_null(a) T_flags_null(a, T_CHECK_QUIET, #a) +#define T_step_null(s, a) T_flags_null(a, T_CHECK_STEP(s), #a) +#define T_step_assert_null(s, a) \ + T_flags_null(a, T_CHECK_STEP(s) | T_CHECK_STOP, #a) + +#define T_not_null(a) T_flags_not_null(a, 0, #a) +#define T_assert_not_null(a) T_flags_not_null(a, T_CHECK_STOP, #a) +#define T_quiet_not_null(a) T_flags_not_null(a, T_CHECK_QUIET, #a) +#define T_step_not_null(s, a) T_flags_not_null(a, T_CHECK_STEP(s), #a) +#define T_step_assert_not_null(s, a) \ + T_flags_not_null(a, T_CHECK_STEP(s) | T_CHECK_STOP, #a) + +/** @} */ + +/** + * @defgroup RTEMSTestFrameworkChecksMemStr Memory Area Checks + * + * @ingroup RTEMSTestFramework + * + * @brief Checks for memory areas. + * + * @{ + */ + +#define T_eq_mem(a, e, n) T_flags_eq_mem(a, e, n, 0, #a, #e, #n) +#define T_assert_eq_mem(a, e, n) \ + T_flags_eq_mem(a, e, n, T_CHECK_STOP, #a, #e, #n) +#define T_quiet_eq_mem(a, e, n) \ + T_flags_eq_mem(a, e, n, T_CHECK_QUIET, #a, #e, #n) +#define T_step_eq_mem(s, a, e, n) \ + T_flags_eq_mem(a, e, n, T_CHECK_STEP(s), #a, #e, #n) +#define T_step_assert_eq_mem(s, a, e, n) \ + T_flags_eq_mem(a, e, n, T_CHECK_STEP(s) | T_CHECK_STOP, #a, #e, #n) + +#define T_ne_mem(a, e, n) T_flags_ne_mem(a, e, n, 0, #a, #e, #n) +#define T_assert_ne_mem(a, e, n) \ + T_flags_ne_mem(a, e, n, T_CHECK_STOP, #a, #e, #n) +#define T_quiet_ne_mem(a, e, n) \ + T_flags_ne_mem(a, e, n, T_CHECK_QUIET, #a, #e, #n) +#define T_step_ne_mem(s, a, e, n) \ + T_flags_ne_mem(a, e, n, T_CHECK_STEP(s), #a, #e, #n) +#define T_step_assert_ne_mem(s, a, e, n) \ + T_flags_ne_mem(a, e, n, T_CHECK_STEP(s) | T_CHECK_STOP, #a, #e, #n) + +/** @} */ + +/** + * @defgroup RTEMSTestFrameworkChecksStr String Checks + * + * @ingroup RTEMSTestFramework + * + * @brief Checks for strings. + * + * @{ + */ + + +#define T_eq_str(a, e) T_flags_eq_str(a, e, 0) +#define T_assert_eq_str(a, e) T_flags_eq_str(a, e, T_CHECK_STOP) +#define T_quiet_eq_str(a, e) T_flags_eq_str(a, e, T_CHECK_QUIET) +#define T_step_eq_str(s, a, e) T_flags_eq_str(a, e, T_CHECK_STEP(s)) +#define T_step_assert_eq_str(s, a, e) \ + T_flags_eq_str(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ne_str(a, e) T_flags_ne_str(a, e, 0) +#define T_assert_ne_str(a, e) T_flags_ne_str(a, e, T_CHECK_STOP) +#define T_quiet_ne_str(a, e) T_flags_ne_str(a, e, T_CHECK_QUIET) +#define T_step_ne_str(s, a, e) T_flags_ne_str(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ne_str(s, a, e) \ + T_flags_ne_str(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_eq_nstr(a, e, n) T_flags_eq_nstr(a, e, n, 0) +#define T_assert_eq_nstr(a, e, n) T_flags_eq_nstr(a, e, n, T_CHECK_STOP) +#define T_quiet_eq_nstr(a, e, n) T_flags_eq_nstr(a, e, n, T_CHECK_QUIET) +#define T_step_eq_nstr(s, a, e, n) T_flags_eq_nstr(a, e, n, T_CHECK_STEP(s)) +#define T_step_assert_eq_nstr(s, a, e, n) \ + T_flags_eq_nstr(a, e, n, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ne_nstr(a, e, n) T_flags_ne_nstr(a, e, n, 0) +#define T_assert_ne_nstr(a, e, n) T_flags_ne_nstr(a, e, n, T_CHECK_STOP) +#define T_quiet_ne_nstr(a, e, n) T_flags_ne_nstr(a, e, n, T_CHECK_QUIET) +#define T_step_ne_nstr(s, a, e, n) T_flags_ne_nstr(a, e, n, T_CHECK_STEP(s)) +#define T_step_assert_ne_nstr(s, a, e, n) \ + T_flags_ne_nstr(a, e, n, T_CHECK_STEP(s) | T_CHECK_STOP) + +/** @} */ + +/** + * @defgroup RTEMSTestFrameworkChecksChar Character Checks + * + * @ingroup RTEMSTestFramework + * + * @brief Checks for characters (char). + * + * @{ + */ + +#define T_eq_char(a, e) T_flags_eq_char(a, e, 0) +#define T_assert_eq_char(a, e) T_flags_eq_char(a, e, T_CHECK_STOP) +#define T_quiet_eq_char(a, e) T_flags_eq_char(a, e, T_CHECK_QUIET) +#define T_step_eq_char(s, a, e) T_flags_eq_char(a, e, T_CHECK_STEP(s)) +#define T_step_assert_eq_char(s, a, e) \ + T_flags_eq_char(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ne_char(a, e) T_flags_ne_char(a, e, 0) +#define T_assert_ne_char(a, e) T_flags_ne_char(a, e, T_CHECK_STOP) +#define T_quiet_ne_char(a, e) T_flags_ne_char(a, e, T_CHECK_QUIET) +#define T_step_ne_char(s, a, e) T_flags_ne_char(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ne_char(s, a, e) \ + T_flags_ne_char(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +/** @} */ + +/** + * @defgroup RTEMSTestFrameworkChecksSChar Signed Character Checks + * + * @ingroup RTEMSTestFramework + * + * @brief Checks for signed characters (signed char). + * + * @{ + */ + +#define T_eq_schar(a, e) T_flags_eq_int(a, e, 0) +#define T_assert_eq_schar(a, e) T_flags_eq_int(a, e, T_CHECK_STOP) +#define T_quiet_eq_schar(a, e) T_flags_eq_int(a, e, T_CHECK_QUIET) +#define T_step_eq_schar(s, a, e) T_flags_eq_int(a, e, T_CHECK_STEP(s)) +#define T_step_assert_eq_schar(s, a, e) \ + T_flags_eq_int(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ne_schar(a, e) T_flags_ne_int(a, e, 0) +#define T_assert_ne_schar(a, e) T_flags_ne_int(a, e, T_CHECK_STOP) +#define T_quiet_ne_schar(a, e) T_flags_ne_int(a, e, T_CHECK_QUIET) +#define T_step_ne_schar(s, a, e) T_flags_ne_int(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ne_schar(s, a, e) \ + T_flags_ne_int(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ge_schar(a, e) T_flags_ge_int(a, e, 0) +#define T_assert_ge_schar(a, e) T_flags_ge_int(a, e, T_CHECK_STOP) +#define T_quiet_ge_schar(a, e) T_flags_ge_int(a, e, T_CHECK_QUIET) +#define T_step_ge_schar(s, a, e) T_flags_ge_int(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ge_schar(s, a, e) \ + T_flags_ge_int(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_gt_schar(a, e) T_flags_gt_int(a, e, 0) +#define T_assert_gt_schar(a, e) T_flags_gt_int(a, e, T_CHECK_STOP) +#define T_quiet_gt_schar(a, e) T_flags_gt_int(a, e, T_CHECK_QUIET) +#define T_step_gt_schar(s, a, e) T_flags_gt_int(a, e, T_CHECK_STEP(s)) +#define T_step_assert_gt_schar(s, a, e) \ + T_flags_gt_int(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_le_schar(a, e) T_flags_le_int(a, e, 0) +#define T_assert_le_schar(a, e) T_flags_le_int(a, e, T_CHECK_STOP) +#define T_quiet_le_schar(a, e) T_flags_le_int(a, e, T_CHECK_QUIET) +#define T_step_le_schar(s, a, e) T_flags_le_int(a, e, T_CHECK_STEP(s)) +#define T_step_assert_le_schar(s, a, e) \ + T_flags_le_int(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_lt_schar(a, e) T_flags_lt_int(a, e, 0) +#define T_assert_lt_schar(a, e) T_flags_lt_int(a, e, T_CHECK_STOP) +#define T_quiet_lt_schar(a, e) T_flags_lt_int(a, e, T_CHECK_QUIET) +#define T_step_lt_schar(s, a, e) T_flags_lt_int(a, e, T_CHECK_STEP(s)) +#define T_step_assert_lt_schar(s, a, e) \ + T_flags_lt_int(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +/** @} */ + +/** + * @defgroup RTEMSTestFrameworkChecksUChar Unsigned Character Checks + * + * @ingroup RTEMSTestFramework + * + * @brief Checks for unsigned characters (unsigned char). + * + * @{ + */ + +#define T_eq_uchar(a, e) T_flags_eq_uint(a, e, 0) +#define T_assert_eq_uchar(a, e) T_flags_eq_uint(a, e, T_CHECK_STOP) +#define T_quiet_eq_uchar(a, e) T_flags_eq_uint(a, e, T_CHECK_QUIET) +#define T_step_eq_uchar(s, a, e) T_flags_eq_uint(a, e, T_CHECK_STEP(s)) +#define T_step_assert_eq_uchar(s, a, e) \ + T_flags_eq_uint(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ne_uchar(a, e) T_flags_ne_uint(a, e, 0) +#define T_assert_ne_uchar(a, e) T_flags_ne_uint(a, e, T_CHECK_STOP) +#define T_quiet_ne_uchar(a, e) T_flags_ne_uint(a, e, T_CHECK_QUIET) +#define T_step_ne_uchar(s, a, e) T_flags_ne_uint(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ne_uchar(s, a, e) \ + T_flags_ne_uint(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ge_uchar(a, e) T_flags_ge_uint(a, e, 0) +#define T_assert_ge_uchar(a, e) T_flags_ge_uint(a, e, T_CHECK_STOP) +#define T_quiet_ge_uchar(a, e) T_flags_ge_uint(a, e, T_CHECK_QUIET) +#define T_step_ge_uchar(s, a, e) T_flags_ge_uint(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ge_uchar(s, a, e) \ + T_flags_ge_uint(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_gt_uchar(a, e) T_flags_gt_uint(a, e, 0) +#define T_assert_gt_uchar(a, e) T_flags_gt_uint(a, e, T_CHECK_STOP) +#define T_quiet_gt_uchar(a, e) T_flags_gt_uint(a, e, T_CHECK_QUIET) +#define T_step_gt_uchar(s, a, e) T_flags_gt_uint(a, e, T_CHECK_STEP(s)) +#define T_step_assert_gt_uchar(s, a, e) \ + T_flags_gt_uint(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_le_uchar(a, e) T_flags_le_uint(a, e, 0) +#define T_assert_le_uchar(a, e) T_flags_le_uint(a, e, T_CHECK_STOP) +#define T_quiet_le_uchar(a, e) T_flags_le_uint(a, e, T_CHECK_QUIET) +#define T_step_le_uchar(s, a, e) T_flags_le_uint(a, e, T_CHECK_STEP(s)) +#define T_step_assert_le_uchar(s, a, e) \ + T_flags_le_uint(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_lt_uchar(a, e) T_flags_lt_uint(a, e, 0) +#define T_assert_lt_uchar(a, e) T_flags_lt_uint(a, e, T_CHECK_STOP) +#define T_quiet_lt_uchar(a, e) T_flags_lt_uint(a, e, T_CHECK_QUIET) +#define T_step_lt_uchar(s, a, e) T_flags_lt_uint(a, e, T_CHECK_STEP(s)) +#define T_step_assert_lt_uchar(s, a, e) \ + T_flags_lt_uint(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +/** @} */ + +/** + * @defgroup RTEMSTestFrameworkChecksShort Signed Short Integer Checks + * + * @ingroup RTEMSTestFramework + * + * @brief Checks for signed short integers (short). + * + * @{ + */ + +#define T_eq_short(a, e) T_flags_eq_int(a, e, 0) +#define T_assert_eq_short(a, e) T_flags_eq_int(a, e, T_CHECK_STOP) +#define T_quiet_eq_short(a, e) T_flags_eq_int(a, e, T_CHECK_QUIET) +#define T_step_eq_short(s, a, e) T_flags_eq_int(a, e, T_CHECK_STEP(s)) +#define T_step_assert_eq_short(s, a, e) \ + T_flags_eq_int(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ne_short(a, e) T_flags_ne_int(a, e, 0) +#define T_assert_ne_short(a, e) T_flags_ne_int(a, e, T_CHECK_STOP) +#define T_quiet_ne_short(a, e) T_flags_ne_int(a, e, T_CHECK_QUIET) +#define T_step_ne_short(s, a, e) T_flags_ne_int(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ne_short(s, a, e) \ + T_flags_ne_int(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ge_short(a, e) T_flags_ge_int(a, e, 0) +#define T_assert_ge_short(a, e) T_flags_ge_int(a, e, T_CHECK_STOP) +#define T_quiet_ge_short(a, e) T_flags_ge_int(a, e, T_CHECK_QUIET) +#define T_step_ge_short(s, a, e) T_flags_ge_int(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ge_short(s, a, e) \ + T_flags_ge_int(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_gt_short(a, e) T_flags_gt_int(a, e, 0) +#define T_assert_gt_short(a, e) T_flags_gt_int(a, e, T_CHECK_STOP) +#define T_quiet_gt_short(a, e) T_flags_gt_int(a, e, T_CHECK_QUIET) +#define T_step_gt_short(s, a, e) T_flags_gt_int(a, e, T_CHECK_STEP(s)) +#define T_step_assert_gt_short(s, a, e) \ + T_flags_gt_int(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_le_short(a, e) T_flags_le_int(a, e, 0) +#define T_assert_le_short(a, e) T_flags_le_int(a, e, T_CHECK_STOP) +#define T_quiet_le_short(a, e) T_flags_le_int(a, e, T_CHECK_QUIET) +#define T_step_le_short(s, a, e) T_flags_le_int(a, e, T_CHECK_STEP(s)) +#define T_step_assert_le_short(s, a, e) \ + T_flags_le_int(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_lt_short(a, e) T_flags_lt_int(a, e, 0) +#define T_assert_lt_short(a, e) T_flags_lt_int(a, e, T_CHECK_STOP) +#define T_quiet_lt_short(a, e) T_flags_lt_int(a, e, T_CHECK_QUIET) +#define T_step_lt_short(s, a, e) T_flags_lt_int(a, e, T_CHECK_STEP(s)) +#define T_step_assert_lt_short(s, a, e) \ + T_flags_lt_int(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +/** @} */ + +/** + * @defgroup RTEMSTestFrameworkChecksUShort Unsigned Short Integer Checks + * + * @ingroup RTEMSTestFramework + * + * @brief Checks for unsigned short integers (unsigned short). + * + * @{ + */ + +#define T_eq_ushort(a, e) T_flags_eq_uint(a, e, 0) +#define T_assert_eq_ushort(a, e) T_flags_eq_uint(a, e, T_CHECK_STOP) +#define T_quiet_eq_ushort(a, e) T_flags_eq_uint(a, e, T_CHECK_QUIET) +#define T_step_eq_ushort(s, a, e) T_flags_eq_uint(a, e, T_CHECK_STEP(s)) +#define T_step_assert_eq_ushort(s, a, e) \ + T_flags_eq_uint(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ne_ushort(a, e) T_flags_ne_uint(a, e, 0) +#define T_assert_ne_ushort(a, e) T_flags_ne_uint(a, e, T_CHECK_STOP) +#define T_quiet_ne_ushort(a, e) T_flags_ne_uint(a, e, T_CHECK_QUIET) +#define T_step_ne_ushort(s, a, e) T_flags_ne_uint(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ne_ushort(s, a, e) \ + T_flags_ne_uint(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ge_ushort(a, e) T_flags_ge_uint(a, e, 0) +#define T_assert_ge_ushort(a, e) T_flags_ge_uint(a, e, T_CHECK_STOP) +#define T_quiet_ge_ushort(a, e) T_flags_ge_uint(a, e, T_CHECK_QUIET) +#define T_step_ge_ushort(s, a, e) T_flags_ge_uint(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ge_ushort(s, a, e) \ + T_flags_ge_uint(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_gt_ushort(a, e) T_flags_gt_uint(a, e, 0) +#define T_assert_gt_ushort(a, e) T_flags_gt_uint(a, e, T_CHECK_STOP) +#define T_quiet_gt_ushort(a, e) T_flags_gt_uint(a, e, T_CHECK_QUIET) +#define T_step_gt_ushort(s, a, e) T_flags_gt_uint(a, e, T_CHECK_STEP(s)) +#define T_step_assert_gt_ushort(s, a, e) \ + T_flags_gt_uint(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_le_ushort(a, e) T_flags_le_uint(a, e, 0) +#define T_assert_le_ushort(a, e) T_flags_le_uint(a, e, T_CHECK_STOP) +#define T_quiet_le_ushort(a, e) T_flags_le_uint(a, e, T_CHECK_QUIET) +#define T_step_le_ushort(s, a, e) T_flags_le_uint(a, e, T_CHECK_STEP(s)) +#define T_step_assert_le_ushort(s, a, e) \ + T_flags_le_uint(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_lt_ushort(a, e) T_flags_lt_uint(a, e, 0) +#define T_assert_lt_ushort(a, e) T_flags_lt_uint(a, e, T_CHECK_STOP) +#define T_quiet_lt_ushort(a, e) T_flags_lt_uint(a, e, T_CHECK_QUIET) +#define T_step_lt_ushort(s, a, e) T_flags_lt_uint(a, e, T_CHECK_STEP(s)) +#define T_step_assert_lt_ushort(s, a, e) \ + T_flags_lt_uint(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +/** @} */ + +/** + * @defgroup RTEMSTestFrameworkChecksInt Signed Integer Checks + * + * @ingroup RTEMSTestFramework + * + * @brief Checks for signed integers (int). + * + * @{ + */ + +#define T_eq_int(a, e) T_flags_eq_int(a, e, 0) +#define T_assert_eq_int(a, e) T_flags_eq_int(a, e, T_CHECK_STOP) +#define T_quiet_eq_int(a, e) T_flags_eq_int(a, e, T_CHECK_QUIET) +#define T_step_eq_int(s, a, e) T_flags_eq_int(a, e, T_CHECK_STEP(s)) +#define T_step_assert_eq_int(s, a, e) \ + T_flags_eq_int(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ne_int(a, e) T_flags_ne_int(a, e, 0) +#define T_assert_ne_int(a, e) T_flags_ne_int(a, e, T_CHECK_STOP) +#define T_quiet_ne_int(a, e) T_flags_ne_int(a, e, T_CHECK_QUIET) +#define T_step_ne_int(s, a, e) T_flags_ne_int(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ne_int(s, a, e) \ + T_flags_ne_int(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ge_int(a, e) T_flags_ge_int(a, e, 0) +#define T_assert_ge_int(a, e) T_flags_ge_int(a, e, T_CHECK_STOP) +#define T_quiet_ge_int(a, e) T_flags_ge_int(a, e, T_CHECK_QUIET) +#define T_step_ge_int(s, a, e) T_flags_ge_int(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ge_int(s, a, e) \ + T_flags_ge_int(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_gt_int(a, e) T_flags_gt_int(a, e, 0) +#define T_assert_gt_int(a, e) T_flags_gt_int(a, e, T_CHECK_STOP) +#define T_quiet_gt_int(a, e) T_flags_gt_int(a, e, T_CHECK_QUIET) +#define T_step_gt_int(s, a, e) T_flags_gt_int(a, e, T_CHECK_STEP(s)) +#define T_step_assert_gt_int(s, a, e) \ + T_flags_gt_int(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_le_int(a, e) T_flags_le_int(a, e, 0) +#define T_assert_le_int(a, e) T_flags_le_int(a, e, T_CHECK_STOP) +#define T_quiet_le_int(a, e) T_flags_le_int(a, e, T_CHECK_QUIET) +#define T_step_le_int(s, a, e) T_flags_le_int(a, e, T_CHECK_STEP(s)) +#define T_step_assert_le_int(s, a, e) \ + T_flags_le_int(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_lt_int(a, e) T_flags_lt_int(a, e, 0) +#define T_assert_lt_int(a, e) T_flags_lt_int(a, e, T_CHECK_STOP) +#define T_quiet_lt_int(a, e) T_flags_lt_int(a, e, T_CHECK_QUIET) +#define T_step_lt_int(s, a, e) T_flags_lt_int(a, e, T_CHECK_STEP(s)) +#define T_step_assert_lt_int(s, a, e) \ + T_flags_lt_int(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +/** @} */ + +/** + * @defgroup RTEMSTestFrameworkChecksUInt Unsigned Integer Checks + * + * @ingroup RTEMSTestFramework + * + * @brief Checks for unsigned integers (unsigned int). + * + * @{ + */ + +#define T_eq_uint(a, e) T_flags_eq_uint(a, e, 0) +#define T_assert_eq_uint(a, e) T_flags_eq_uint(a, e, T_CHECK_STOP) +#define T_quiet_eq_uint(a, e) T_flags_eq_uint(a, e, T_CHECK_QUIET) +#define T_step_eq_uint(s, a, e) T_flags_eq_uint(a, e, T_CHECK_STEP(s)) +#define T_step_assert_eq_uint(s, a, e) \ + T_flags_eq_uint(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ne_uint(a, e) T_flags_ne_uint(a, e, 0) +#define T_assert_ne_uint(a, e) T_flags_ne_uint(a, e, T_CHECK_STOP) +#define T_quiet_ne_uint(a, e) T_flags_ne_uint(a, e, T_CHECK_QUIET) +#define T_step_ne_uint(s, a, e) T_flags_ne_uint(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ne_uint(s, a, e) \ + T_flags_ne_uint(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ge_uint(a, e) T_flags_ge_uint(a, e, 0) +#define T_assert_ge_uint(a, e) T_flags_ge_uint(a, e, T_CHECK_STOP) +#define T_quiet_ge_uint(a, e) T_flags_ge_uint(a, e, T_CHECK_QUIET) +#define T_step_ge_uint(s, a, e) T_flags_ge_uint(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ge_uint(s, a, e) \ + T_flags_ge_uint(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_gt_uint(a, e) T_flags_gt_uint(a, e, 0) +#define T_assert_gt_uint(a, e) T_flags_gt_uint(a, e, T_CHECK_STOP) +#define T_quiet_gt_uint(a, e) T_flags_gt_uint(a, e, T_CHECK_QUIET) +#define T_step_gt_uint(s, a, e) T_flags_gt_uint(a, e, T_CHECK_STEP(s)) +#define T_step_assert_gt_uint(s, a, e) \ + T_flags_gt_uint(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_le_uint(a, e) T_flags_le_uint(a, e, 0) +#define T_assert_le_uint(a, e) T_flags_le_uint(a, e, T_CHECK_STOP) +#define T_quiet_le_uint(a, e) T_flags_le_uint(a, e, T_CHECK_QUIET) +#define T_step_le_uint(s, a, e) T_flags_le_uint(a, e, T_CHECK_STEP(s)) +#define T_step_assert_le_uint(s, a, e) \ + T_flags_le_uint(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_lt_uint(a, e) T_flags_lt_uint(a, e, 0) +#define T_assert_lt_uint(a, e) T_flags_lt_uint(a, e, T_CHECK_STOP) +#define T_quiet_lt_uint(a, e) T_flags_lt_uint(a, e, T_CHECK_QUIET) +#define T_step_lt_uint(s, a, e) T_flags_lt_uint(a, e, T_CHECK_STEP(s)) +#define T_step_assert_lt_uint(s, a, e) \ + T_flags_lt_uint(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +/** @} */ + +/** + * @defgroup RTEMSTestFrameworkChecksLong Signed Long Integer Checks + * + * @ingroup RTEMSTestFramework + * + * @brief Checks for signed long integers (long). + * + * @{ + */ + +#define T_eq_long(a, e) T_flags_eq_long(a, e, 0) +#define T_assert_eq_long(a, e) T_flags_eq_long(a, e, T_CHECK_STOP) +#define T_quiet_eq_long(a, e) T_flags_eq_long(a, e, T_CHECK_QUIET) +#define T_step_eq_long(s, a, e) T_flags_eq_long(a, e, T_CHECK_STEP(s)) +#define T_step_assert_eq_long(s, a, e) \ + T_flags_eq_long(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ne_long(a, e) T_flags_ne_long(a, e, 0) +#define T_assert_ne_long(a, e) T_flags_ne_long(a, e, T_CHECK_STOP) +#define T_quiet_ne_long(a, e) T_flags_ne_long(a, e, T_CHECK_QUIET) +#define T_step_ne_long(s, a, e) T_flags_ne_long(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ne_long(s, a, e) \ + T_flags_ne_long(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ge_long(a, e) T_flags_ge_long(a, e, 0) +#define T_assert_ge_long(a, e) T_flags_ge_long(a, e, T_CHECK_STOP) +#define T_quiet_ge_long(a, e) T_flags_ge_long(a, e, T_CHECK_QUIET) +#define T_step_ge_long(s, a, e) T_flags_ge_long(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ge_long(s, a, e) \ + T_flags_ge_long(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_gt_long(a, e) T_flags_gt_long(a, e, 0) +#define T_assert_gt_long(a, e) T_flags_gt_long(a, e, T_CHECK_STOP) +#define T_quiet_gt_long(a, e) T_flags_gt_long(a, e, T_CHECK_QUIET) +#define T_step_gt_long(s, a, e) T_flags_gt_long(a, e, T_CHECK_STEP(s)) +#define T_step_assert_gt_long(s, a, e) \ + T_flags_gt_long(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_le_long(a, e) T_flags_le_long(a, e, 0) +#define T_assert_le_long(a, e) T_flags_le_long(a, e, T_CHECK_STOP) +#define T_quiet_le_long(a, e) T_flags_le_long(a, e, T_CHECK_QUIET) +#define T_step_le_long(s, a, e) T_flags_le_long(a, e, T_CHECK_STEP(s)) +#define T_step_assert_le_long(s, a, e) \ + T_flags_le_long(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_lt_long(a, e) T_flags_lt_long(a, e, 0) +#define T_assert_lt_long(a, e) T_flags_lt_long(a, e, T_CHECK_STOP) +#define T_quiet_lt_long(a, e) T_flags_lt_long(a, e, T_CHECK_QUIET) +#define T_step_lt_long(s, a, e) T_flags_lt_long(a, e, T_CHECK_STEP(s)) +#define T_step_assert_lt_long(s, a, e) \ + T_flags_lt_long(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +/** @} */ + +/** + * @defgroup RTEMSTestFrameworkChecksULong Unsigned Long Integer Checks + * + * @ingroup RTEMSTestFramework + * + * @brief Checks for unsigned long integers (unsigned long). + * + * @{ + */ + +#define T_eq_ulong(a, e) T_flags_eq_ulong(a, e, 0) +#define T_assert_eq_ulong(a, e) T_flags_eq_ulong(a, e, T_CHECK_STOP) +#define T_quiet_eq_ulong(a, e) T_flags_eq_ulong(a, e, T_CHECK_QUIET) +#define T_step_eq_ulong(s, a, e) T_flags_eq_ulong(a, e, T_CHECK_STEP(s)) +#define T_step_assert_eq_ulong(s, a, e) \ + T_flags_eq_ulong(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ne_ulong(a, e) T_flags_ne_ulong(a, e, 0) +#define T_assert_ne_ulong(a, e) T_flags_ne_ulong(a, e, T_CHECK_STOP) +#define T_quiet_ne_ulong(a, e) T_flags_ne_ulong(a, e, T_CHECK_QUIET) +#define T_step_ne_ulong(s, a, e) T_flags_ne_ulong(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ne_ulong(s, a, e) \ + T_flags_ne_ulong(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ge_ulong(a, e) T_flags_ge_ulong(a, e, 0) +#define T_assert_ge_ulong(a, e) T_flags_ge_ulong(a, e, T_CHECK_STOP) +#define T_quiet_ge_ulong(a, e) T_flags_ge_ulong(a, e, T_CHECK_QUIET) +#define T_step_ge_ulong(s, a, e) T_flags_ge_ulong(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ge_ulong(s, a, e) \ + T_flags_ge_ulong(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_gt_ulong(a, e) T_flags_gt_ulong(a, e, 0) +#define T_assert_gt_ulong(a, e) T_flags_gt_ulong(a, e, T_CHECK_STOP) +#define T_quiet_gt_ulong(a, e) T_flags_gt_ulong(a, e, T_CHECK_QUIET) +#define T_step_gt_ulong(s, a, e) T_flags_gt_ulong(a, e, T_CHECK_STEP(s)) +#define T_step_assert_gt_ulong(s, a, e) \ + T_flags_gt_ulong(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_le_ulong(a, e) T_flags_le_ulong(a, e, 0) +#define T_assert_le_ulong(a, e) T_flags_le_ulong(a, e, T_CHECK_STOP) +#define T_quiet_le_ulong(a, e) T_flags_le_ulong(a, e, T_CHECK_QUIET) +#define T_step_le_ulong(s, a, e) T_flags_le_ulong(a, e, T_CHECK_STEP(s)) +#define T_step_assert_le_ulong(s, a, e) \ + T_flags_le_ulong(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_lt_ulong(a, e) T_flags_lt_ulong(a, e, 0) +#define T_assert_lt_ulong(a, e) T_flags_lt_ulong(a, e, T_CHECK_STOP) +#define T_quiet_lt_ulong(a, e) T_flags_lt_ulong(a, e, T_CHECK_QUIET) +#define T_step_lt_ulong(s, a, e) T_flags_lt_ulong(a, e, T_CHECK_STEP(s)) +#define T_step_assert_lt_ulong(s, a, e) \ + T_flags_lt_ulong(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +/** @} */ + +/** + * @defgroup RTEMSTestFrameworkChecksLong Signed Long Long Integer Checks + * + * @ingroup RTEMSTestFramework + * + * @brief Checks for signed long long integers (long long). + * + * @{ + */ + +#define T_eq_ll(a, e) T_flags_eq_ll(a, e, 0) +#define T_assert_eq_ll(a, e) T_flags_eq_ll(a, e, T_CHECK_STOP) +#define T_quiet_eq_ll(a, e) T_flags_eq_ll(a, e, T_CHECK_QUIET) +#define T_step_eq_ll(s, a, e) T_flags_eq_ll(a, e, T_CHECK_STEP(s)) +#define T_step_assert_eq_ll(s, a, e) \ + T_flags_eq_ll(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ne_ll(a, e) T_flags_ne_ll(a, e, 0) +#define T_assert_ne_ll(a, e) T_flags_ne_ll(a, e, T_CHECK_STOP) +#define T_quiet_ne_ll(a, e) T_flags_ne_ll(a, e, T_CHECK_QUIET) +#define T_step_ne_ll(s, a, e) T_flags_ne_ll(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ne_ll(s, a, e) \ + T_flags_ne_ll(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ge_ll(a, e) T_flags_ge_ll(a, e, 0) +#define T_assert_ge_ll(a, e) T_flags_ge_ll(a, e, T_CHECK_STOP) +#define T_quiet_ge_ll(a, e) T_flags_ge_ll(a, e, T_CHECK_QUIET) +#define T_step_ge_ll(s, a, e) T_flags_ge_ll(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ge_ll(s, a, e) \ + T_flags_ge_ll(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_gt_ll(a, e) T_flags_gt_ll(a, e, 0) +#define T_assert_gt_ll(a, e) T_flags_gt_ll(a, e, T_CHECK_STOP) +#define T_quiet_gt_ll(a, e) T_flags_gt_ll(a, e, T_CHECK_QUIET) +#define T_step_gt_ll(s, a, e) T_flags_gt_ll(a, e, T_CHECK_STEP(s)) +#define T_step_assert_gt_ll(s, a, e) \ + T_flags_gt_ll(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_le_ll(a, e) T_flags_le_ll(a, e, 0) +#define T_assert_le_ll(a, e) T_flags_le_ll(a, e, T_CHECK_STOP) +#define T_quiet_le_ll(a, e) T_flags_le_ll(a, e, T_CHECK_QUIET) +#define T_step_le_ll(s, a, e) T_flags_le_ll(a, e, T_CHECK_STEP(s)) +#define T_step_assert_le_ll(s, a, e) \ + T_flags_le_ll(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_lt_ll(a, e) T_flags_lt_ll(a, e, 0) +#define T_assert_lt_ll(a, e) T_flags_lt_ll(a, e, T_CHECK_STOP) +#define T_quiet_lt_ll(a, e) T_flags_lt_ll(a, e, T_CHECK_QUIET) +#define T_step_lt_ll(s, a, e) T_flags_lt_ll(a, e, T_CHECK_STEP(s)) +#define T_step_assert_lt_ll(s, a, e) \ + T_flags_lt_ll(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +/** @} */ + +/** + * @defgroup RTEMSTestFrameworkChecksULongLong Unsigned Long Long Integer Checks + * + * @ingroup RTEMSTestFramework + * + * @brief Checks for unsigned long long integers (unsigned long long). + * + * @{ + */ + +#define T_eq_ull(a, e) T_flags_eq_ull(a, e, 0) +#define T_assert_eq_ull(a, e) T_flags_eq_ull(a, e, T_CHECK_STOP) +#define T_quiet_eq_ull(a, e) T_flags_eq_ull(a, e, T_CHECK_QUIET) +#define T_step_eq_ull(s, a, e) T_flags_eq_ull(a, e, T_CHECK_STEP(s)) +#define T_step_assert_eq_ull(s, a, e) \ + T_flags_eq_ull(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ne_ull(a, e) T_flags_ne_ull(a, e, 0) +#define T_assert_ne_ull(a, e) T_flags_ne_ull(a, e, T_CHECK_STOP) +#define T_quiet_ne_ull(a, e) T_flags_ne_ull(a, e, T_CHECK_QUIET) +#define T_step_ne_ull(s, a, e) T_flags_ne_ull(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ne_ull(s, a, e) \ + T_flags_ne_ull(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ge_ull(a, e) T_flags_ge_ull(a, e, 0) +#define T_assert_ge_ull(a, e) T_flags_ge_ull(a, e, T_CHECK_STOP) +#define T_quiet_ge_ull(a, e) T_flags_ge_ull(a, e, T_CHECK_QUIET) +#define T_step_ge_ull(s, a, e) T_flags_ge_ull(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ge_ull(s, a, e) \ + T_flags_ge_ull(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_gt_ull(a, e) T_flags_gt_ull(a, e, 0) +#define T_assert_gt_ull(a, e) T_flags_gt_ull(a, e, T_CHECK_STOP) +#define T_quiet_gt_ull(a, e) T_flags_gt_ull(a, e, T_CHECK_QUIET) +#define T_step_gt_ull(s, a, e) T_flags_gt_ull(a, e, T_CHECK_STEP(s)) +#define T_step_assert_gt_ull(s, a, e) \ + T_flags_gt_ull(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_le_ull(a, e) T_flags_le_ull(a, e, 0) +#define T_assert_le_ull(a, e) T_flags_le_ull(a, e, T_CHECK_STOP) +#define T_quiet_le_ull(a, e) T_flags_le_ull(a, e, T_CHECK_QUIET) +#define T_step_le_ull(s, a, e) T_flags_le_ull(a, e, T_CHECK_STEP(s)) +#define T_step_assert_le_ull(s, a, e) \ + T_flags_le_ull(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_lt_ull(a, e) T_flags_lt_ull(a, e, 0) +#define T_assert_lt_ull(a, e) T_flags_lt_ull(a, e, T_CHECK_STOP) +#define T_quiet_lt_ull(a, e) T_flags_lt_ull(a, e, T_CHECK_QUIET) +#define T_step_lt_ull(s, a, e) T_flags_lt_ull(a, e, T_CHECK_STEP(s)) +#define T_step_assert_lt_ull(s, a, e) \ + T_flags_lt_ull(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +/** @} */ + +/** + * @defgroup RTEMSTestFrameworkChecksInt8 Signed 8-Bit Integer Checks + * + * @ingroup RTEMSTestFramework + * + * @brief Checks for signed 8-bit integers (int8_t). + * + * @{ + */ + +#define T_eq_i8(a, e) T_flags_eq_int(a, e, 0) +#define T_assert_eq_i8(a, e) T_flags_eq_int(a, e, T_CHECK_STOP) +#define T_quiet_eq_i8(a, e) T_flags_eq_int(a, e, T_CHECK_QUIET) +#define T_step_eq_i8(s, a, e) T_flags_eq_int(a, e, T_CHECK_STEP(s)) +#define T_step_assert_eq_i8(s, a, e) \ + T_flags_eq_int(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ne_i8(a, e) T_flags_ne_int(a, e, 0) +#define T_assert_ne_i8(a, e) T_flags_ne_int(a, e, T_CHECK_STOP) +#define T_quiet_ne_i8(a, e) T_flags_ne_int(a, e, T_CHECK_QUIET) +#define T_step_ne_i8(s, a, e) T_flags_ne_int(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ne_i8(s, a, e) \ + T_flags_ne_int(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ge_i8(a, e) T_flags_ge_int(a, e, 0) +#define T_assert_ge_i8(a, e) T_flags_ge_int(a, e, T_CHECK_STOP) +#define T_quiet_ge_i8(a, e) T_flags_ge_int(a, e, T_CHECK_QUIET) +#define T_step_ge_i8(s, a, e) T_flags_ge_int(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ge_i8(s, a, e) \ + T_flags_ge_int(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_gt_i8(a, e) T_flags_gt_int(a, e, 0) +#define T_assert_gt_i8(a, e) T_flags_gt_int(a, e, T_CHECK_STOP) +#define T_quiet_gt_i8(a, e) T_flags_gt_int(a, e, T_CHECK_QUIET) +#define T_step_gt_i8(s, a, e) T_flags_gt_int(a, e, T_CHECK_STEP(s)) +#define T_step_assert_gt_i8(s, a, e) \ + T_flags_gt_int(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_le_i8(a, e) T_flags_le_int(a, e, 0) +#define T_assert_le_i8(a, e) T_flags_le_int(a, e, T_CHECK_STOP) +#define T_quiet_le_i8(a, e) T_flags_le_int(a, e, T_CHECK_QUIET) +#define T_step_le_i8(s, a, e) T_flags_le_int(a, e, T_CHECK_STEP(s)) +#define T_step_assert_le_i8(s, a, e) \ + T_flags_le_int(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_lt_i8(a, e) T_flags_lt_int(a, e, 0) +#define T_assert_lt_i8(a, e) T_flags_lt_int(a, e, T_CHECK_STOP) +#define T_quiet_lt_i8(a, e) T_flags_lt_int(a, e, T_CHECK_QUIET) +#define T_step_lt_i8(s, a, e) T_flags_lt_int(a, e, T_CHECK_STEP(s)) +#define T_step_assert_lt_i8(s, a, e) \ + T_flags_lt_int(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +/** @} */ + +/** + * @defgroup RTEMSTestFrameworkChecksUInt8 Unsigned 8-Bit Integer Checks + * + * @ingroup RTEMSTestFramework + * + * @brief Checks for unsigned 8-bit integers (uint8_t). + * + * @{ + */ + +#define T_eq_u8(a, e) T_flags_eq_uint(a, e, 0) +#define T_assert_eq_u8(a, e) T_flags_eq_uint(a, e, T_CHECK_STOP) +#define T_quiet_eq_u8(a, e) T_flags_eq_uint(a, e, T_CHECK_QUIET) +#define T_step_eq_u8(s, a, e) T_flags_eq_uint(a, e, T_CHECK_STEP(s)) +#define T_step_assert_eq_u8(s, a, e) \ + T_flags_eq_uint(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ne_u8(a, e) T_flags_ne_uint(a, e, 0) +#define T_assert_ne_u8(a, e) T_flags_ne_uint(a, e, T_CHECK_STOP) +#define T_quiet_ne_u8(a, e) T_flags_ne_uint(a, e, T_CHECK_QUIET) +#define T_step_ne_u8(s, a, e) T_flags_ne_uint(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ne_u8(s, a, e) \ + T_flags_ne_uint(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ge_u8(a, e) T_flags_ge_uint(a, e, 0) +#define T_assert_ge_u8(a, e) T_flags_ge_uint(a, e, T_CHECK_STOP) +#define T_quiet_ge_u8(a, e) T_flags_ge_uint(a, e, T_CHECK_QUIET) +#define T_step_ge_u8(s, a, e) T_flags_ge_uint(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ge_u8(s, a, e) \ + T_flags_ge_uint(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_gt_u8(a, e) T_flags_gt_uint(a, e, 0) +#define T_assert_gt_u8(a, e) T_flags_gt_uint(a, e, T_CHECK_STOP) +#define T_quiet_gt_u8(a, e) T_flags_gt_uint(a, e, T_CHECK_QUIET) +#define T_step_gt_u8(s, a, e) T_flags_gt_uint(a, e, T_CHECK_STEP(s)) +#define T_step_assert_gt_u8(s, a, e) \ + T_flags_gt_uint(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_le_u8(a, e) T_flags_le_uint(a, e, 0) +#define T_assert_le_u8(a, e) T_flags_le_uint(a, e, T_CHECK_STOP) +#define T_quiet_le_u8(a, e) T_flags_le_uint(a, e, T_CHECK_QUIET) +#define T_step_le_u8(s, a, e) T_flags_le_uint(a, e, T_CHECK_STEP(s)) +#define T_step_assert_le_u8(s, a, e) \ + T_flags_le_uint(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_lt_u8(a, e) T_flags_lt_uint(a, e, 0) +#define T_assert_lt_u8(a, e) T_flags_lt_uint(a, e, T_CHECK_STOP) +#define T_quiet_lt_u8(a, e) T_flags_lt_uint(a, e, T_CHECK_QUIET) +#define T_step_lt_u8(s, a, e) T_flags_lt_uint(a, e, T_CHECK_STEP(s)) +#define T_step_assert_lt_u8(s, a, e) \ + T_flags_lt_uint(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +/** @} */ + +/** + * @defgroup RTEMSTestFrameworkChecksInt16 Signed 16-Bit Integer Checks + * + * @ingroup RTEMSTestFramework + * + * @brief Checks for signed 16-bit integers (int16_t). + * + * @{ + */ + +#define T_eq_i16(a, e) T_flags_eq_int(a, e, 0) +#define T_assert_eq_i16(a, e) T_flags_eq_int(a, e, T_CHECK_STOP) +#define T_quiet_eq_i16(a, e) T_flags_eq_int(a, e, T_CHECK_QUIET) +#define T_step_eq_i16(s, a, e) T_flags_eq_int(a, e, T_CHECK_STEP(s)) +#define T_step_assert_eq_i16(s, a, e) \ + T_flags_eq_int(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ne_i16(a, e) T_flags_ne_int(a, e, 0) +#define T_assert_ne_i16(a, e) T_flags_ne_int(a, e, T_CHECK_STOP) +#define T_quiet_ne_i16(a, e) T_flags_ne_int(a, e, T_CHECK_QUIET) +#define T_step_ne_i16(s, a, e) T_flags_ne_int(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ne_i16(s, a, e) \ + T_flags_ne_int(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ge_i16(a, e) T_flags_ge_int(a, e, 0) +#define T_assert_ge_i16(a, e) T_flags_ge_int(a, e, T_CHECK_STOP) +#define T_quiet_ge_i16(a, e) T_flags_ge_int(a, e, T_CHECK_QUIET) +#define T_step_ge_i16(s, a, e) T_flags_ge_int(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ge_i16(s, a, e) \ + T_flags_ge_int(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_gt_i16(a, e) T_flags_gt_int(a, e, 0) +#define T_assert_gt_i16(a, e) T_flags_gt_int(a, e, T_CHECK_STOP) +#define T_quiet_gt_i16(a, e) T_flags_gt_int(a, e, T_CHECK_QUIET) +#define T_step_gt_i16(s, a, e) T_flags_gt_int(a, e, T_CHECK_STEP(s)) +#define T_step_assert_gt_i16(s, a, e) \ + T_flags_gt_int(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_le_i16(a, e) T_flags_le_int(a, e, 0) +#define T_assert_le_i16(a, e) T_flags_le_int(a, e, T_CHECK_STOP) +#define T_quiet_le_i16(a, e) T_flags_le_int(a, e, T_CHECK_QUIET) +#define T_step_le_i16(s, a, e) T_flags_le_int(a, e, T_CHECK_STEP(s)) +#define T_step_assert_le_i16(s, a, e) \ + T_flags_le_int(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_lt_i16(a, e) T_flags_lt_int(a, e, 0) +#define T_assert_lt_i16(a, e) T_flags_lt_int(a, e, T_CHECK_STOP) +#define T_quiet_lt_i16(a, e) T_flags_lt_int(a, e, T_CHECK_QUIET) +#define T_step_lt_i16(s, a, e) T_flags_lt_int(a, e, T_CHECK_STEP(s)) +#define T_step_assert_lt_i16(s, a, e) \ + T_flags_lt_int(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +/** @} */ + +/** + * @defgroup RTEMSTestFrameworkChecksUInt16 Unsigned 16-Bit Integer Checks + * + * @ingroup RTEMSTestFramework + * + * @brief Checks for unsigned 16-bit integers (uint16_t). + * + * @{ + */ + +#define T_eq_u16(a, e) T_flags_eq_uint(a, e, 0) +#define T_assert_eq_u16(a, e) T_flags_eq_uint(a, e, T_CHECK_STOP) +#define T_quiet_eq_u16(a, e) T_flags_eq_uint(a, e, T_CHECK_QUIET) +#define T_step_eq_u16(s, a, e) T_flags_eq_uint(a, e, T_CHECK_STEP(s)) +#define T_step_assert_eq_u16(s, a, e) \ + T_flags_eq_uint(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ne_u16(a, e) T_flags_ne_uint(a, e, 0) +#define T_assert_ne_u16(a, e) T_flags_ne_uint(a, e, T_CHECK_STOP) +#define T_quiet_ne_u16(a, e) T_flags_ne_uint(a, e, T_CHECK_QUIET) +#define T_step_ne_u16(s, a, e) T_flags_ne_uint(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ne_u16(s, a, e) \ + T_flags_ne_uint(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ge_u16(a, e) T_flags_ge_uint(a, e, 0) +#define T_assert_ge_u16(a, e) T_flags_ge_uint(a, e, T_CHECK_STOP) +#define T_quiet_ge_u16(a, e) T_flags_ge_uint(a, e, T_CHECK_QUIET) +#define T_step_ge_u16(s, a, e) T_flags_ge_uint(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ge_u16(s, a, e) \ + T_flags_ge_uint(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_gt_u16(a, e) T_flags_gt_uint(a, e, 0) +#define T_assert_gt_u16(a, e) T_flags_gt_uint(a, e, T_CHECK_STOP) +#define T_quiet_gt_u16(a, e) T_flags_gt_uint(a, e, T_CHECK_QUIET) +#define T_step_gt_u16(s, a, e) T_flags_gt_uint(a, e, T_CHECK_STEP(s)) +#define T_step_assert_gt_u16(s, a, e) \ + T_flags_gt_uint(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_le_u16(a, e) T_flags_le_uint(a, e, 0) +#define T_assert_le_u16(a, e) T_flags_le_uint(a, e, T_CHECK_STOP) +#define T_quiet_le_u16(a, e) T_flags_le_uint(a, e, T_CHECK_QUIET) +#define T_step_le_u16(s, a, e) T_flags_le_uint(a, e, T_CHECK_STEP(s)) +#define T_step_assert_le_u16(s, a, e) \ + T_flags_le_uint(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_lt_u16(a, e) T_flags_lt_uint(a, e, 0) +#define T_assert_lt_u16(a, e) T_flags_lt_uint(a, e, T_CHECK_STOP) +#define T_quiet_lt_u16(a, e) T_flags_lt_uint(a, e, T_CHECK_QUIET) +#define T_step_lt_u16(s, a, e) T_flags_lt_uint(a, e, T_CHECK_STEP(s)) +#define T_step_assert_lt_u16(s, a, e) \ + T_flags_lt_uint(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +/** @} */ + +/** + * @defgroup RTEMSTestFrameworkChecksInt32 Signed 32-Bit Integer Checks + * + * @ingroup RTEMSTestFramework + * + * @brief Checks for signed 32-bit integers (int32_t). + * + * @{ + */ + +#define T_eq_i32(a, e) T_flags_eq_long(a, e, 0) +#define T_assert_eq_i32(a, e) T_flags_eq_long(a, e, T_CHECK_STOP) +#define T_quiet_eq_i32(a, e) T_flags_eq_long(a, e, T_CHECK_QUIET) +#define T_step_eq_i32(s, a, e) T_flags_eq_long(a, e, T_CHECK_STEP(s)) +#define T_step_assert_eq_i32(s, a, e) \ + T_flags_eq_long(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ne_i32(a, e) T_flags_ne_long(a, e, 0) +#define T_assert_ne_i32(a, e) T_flags_ne_long(a, e, T_CHECK_STOP) +#define T_quiet_ne_i32(a, e) T_flags_ne_long(a, e, T_CHECK_QUIET) +#define T_step_ne_i32(s, a, e) T_flags_ne_long(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ne_i32(s, a, e) \ + T_flags_ne_long(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ge_i32(a, e) T_flags_ge_long(a, e, 0) +#define T_assert_ge_i32(a, e) T_flags_ge_long(a, e, T_CHECK_STOP) +#define T_quiet_ge_i32(a, e) T_flags_ge_long(a, e, T_CHECK_QUIET) +#define T_step_ge_i32(s, a, e) T_flags_ge_long(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ge_i32(s, a, e) \ + T_flags_ge_long(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_gt_i32(a, e) T_flags_gt_long(a, e, 0) +#define T_assert_gt_i32(a, e) T_flags_gt_long(a, e, T_CHECK_STOP) +#define T_quiet_gt_i32(a, e) T_flags_gt_long(a, e, T_CHECK_QUIET) +#define T_step_gt_i32(s, a, e) T_flags_gt_long(a, e, T_CHECK_STEP(s)) +#define T_step_assert_gt_i32(s, a, e) \ + T_flags_gt_long(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_le_i32(a, e) T_flags_le_long(a, e, 0) +#define T_assert_le_i32(a, e) T_flags_le_long(a, e, T_CHECK_STOP) +#define T_quiet_le_i32(a, e) T_flags_le_long(a, e, T_CHECK_QUIET) +#define T_step_le_i32(s, a, e) T_flags_le_long(a, e, T_CHECK_STEP(s)) +#define T_step_assert_le_i32(s, a, e) \ + T_flags_le_long(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_lt_i32(a, e) T_flags_lt_long(a, e, 0) +#define T_assert_lt_i32(a, e) T_flags_lt_long(a, e, T_CHECK_STOP) +#define T_quiet_lt_i32(a, e) T_flags_lt_long(a, e, T_CHECK_QUIET) +#define T_step_lt_i32(s, a, e) T_flags_lt_long(a, e, T_CHECK_STEP(s)) +#define T_step_assert_lt_i32(s, a, e) \ + T_flags_lt_long(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +/** @} */ + +/** + * @defgroup RTEMSTestFrameworkChecksUInt32 Unsigned 32-Bit Integer Checks + * + * @ingroup RTEMSTestFramework + * + * @brief Checks for unsigned 32-bit integers (uint32_t). + * + * @{ + */ + +#define T_eq_u32(a, e) T_flags_eq_ulong(a, e, 0) +#define T_assert_eq_u32(a, e) T_flags_eq_ulong(a, e, T_CHECK_STOP) +#define T_quiet_eq_u32(a, e) T_flags_eq_ulong(a, e, T_CHECK_QUIET) +#define T_step_eq_u32(s, a, e) T_flags_eq_ulong(a, e, T_CHECK_STEP(s)) +#define T_step_assert_eq_u32(s, a, e) \ + T_flags_eq_ulong(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ne_u32(a, e) T_flags_ne_ulong(a, e, 0) +#define T_assert_ne_u32(a, e) T_flags_ne_ulong(a, e, T_CHECK_STOP) +#define T_quiet_ne_u32(a, e) T_flags_ne_ulong(a, e, T_CHECK_QUIET) +#define T_step_ne_u32(s, a, e) T_flags_ne_ulong(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ne_u32(s, a, e) \ + T_flags_ne_ulong(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ge_u32(a, e) T_flags_ge_ulong(a, e, 0) +#define T_assert_ge_u32(a, e) T_flags_ge_ulong(a, e, T_CHECK_STOP) +#define T_quiet_ge_u32(a, e) T_flags_ge_ulong(a, e, T_CHECK_QUIET) +#define T_step_ge_u32(s, a, e) T_flags_ge_ulong(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ge_u32(s, a, e) \ + T_flags_ge_ulong(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_gt_u32(a, e) T_flags_gt_ulong(a, e, 0) +#define T_assert_gt_u32(a, e) T_flags_gt_ulong(a, e, T_CHECK_STOP) +#define T_quiet_gt_u32(a, e) T_flags_gt_ulong(a, e, T_CHECK_QUIET) +#define T_step_gt_u32(s, a, e) T_flags_gt_ulong(a, e, T_CHECK_STEP(s)) +#define T_step_assert_gt_u32(s, a, e) \ + T_flags_gt_ulong(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_le_u32(a, e) T_flags_le_ulong(a, e, 0) +#define T_assert_le_u32(a, e) T_flags_le_ulong(a, e, T_CHECK_STOP) +#define T_quiet_le_u32(a, e) T_flags_le_ulong(a, e, T_CHECK_QUIET) +#define T_step_le_u32(s, a, e) T_flags_le_ulong(a, e, T_CHECK_STEP(s)) +#define T_step_assert_le_u32(s, a, e) \ + T_flags_le_ulong(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_lt_u32(a, e) T_flags_lt_ulong(a, e, 0) +#define T_assert_lt_u32(a, e) T_flags_lt_ulong(a, e, T_CHECK_STOP) +#define T_quiet_lt_u32(a, e) T_flags_lt_ulong(a, e, T_CHECK_QUIET) +#define T_step_lt_u32(s, a, e) T_flags_lt_ulong(a, e, T_CHECK_STEP(s)) +#define T_step_assert_lt_u32(s, a, e) \ + T_flags_lt_ulong(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +/** @} */ + +/** + * @defgroup RTEMSTestFrameworkChecksInt64 Signed 64-Bit Integer Checks + * + * @ingroup RTEMSTestFramework + * + * @brief Checks for signed 64-bit integers (int64_t). + * + * @{ + */ + +#define T_eq_i64(a, e) T_flags_eq_ll(a, e, 0) +#define T_assert_eq_i64(a, e) T_flags_eq_ll(a, e, T_CHECK_STOP) +#define T_quiet_eq_i64(a, e) T_flags_eq_ll(a, e, T_CHECK_QUIET) +#define T_step_eq_i64(s, a, e) T_flags_eq_ll(a, e, T_CHECK_STEP(s)) +#define T_step_assert_eq_i64(s, a, e) \ + T_flags_eq_ll(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ne_i64(a, e) T_flags_ne_ll(a, e, 0) +#define T_assert_ne_i64(a, e) T_flags_ne_ll(a, e, T_CHECK_STOP) +#define T_quiet_ne_i64(a, e) T_flags_ne_ll(a, e, T_CHECK_QUIET) +#define T_step_ne_i64(s, a, e) T_flags_ne_ll(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ne_i64(s, a, e) \ + T_flags_ne_ll(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ge_i64(a, e) T_flags_ge_ll(a, e, 0) +#define T_assert_ge_i64(a, e) T_flags_ge_ll(a, e, T_CHECK_STOP) +#define T_quiet_ge_i64(a, e) T_flags_ge_ll(a, e, T_CHECK_QUIET) +#define T_step_ge_i64(s, a, e) T_flags_ge_ll(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ge_i64(s, a, e) \ + T_flags_ge_ll(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_gt_i64(a, e) T_flags_gt_ll(a, e, 0) +#define T_assert_gt_i64(a, e) T_flags_gt_ll(a, e, T_CHECK_STOP) +#define T_quiet_gt_i64(a, e) T_flags_gt_ll(a, e, T_CHECK_QUIET) +#define T_step_gt_i64(s, a, e) T_flags_gt_ll(a, e, T_CHECK_STEP(s)) +#define T_step_assert_gt_i64(s, a, e) \ + T_flags_gt_ll(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_le_i64(a, e) T_flags_le_ll(a, e, 0) +#define T_assert_le_i64(a, e) T_flags_le_ll(a, e, T_CHECK_STOP) +#define T_quiet_le_i64(a, e) T_flags_le_ll(a, e, T_CHECK_QUIET) +#define T_step_le_i64(s, a, e) T_flags_le_ll(a, e, T_CHECK_STEP(s)) +#define T_step_assert_le_i64(s, a, e) \ + T_flags_le_ll(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_lt_i64(a, e) T_flags_lt_ll(a, e, 0) +#define T_assert_lt_i64(a, e) T_flags_lt_ll(a, e, T_CHECK_STOP) +#define T_quiet_lt_i64(a, e) T_flags_lt_ll(a, e, T_CHECK_QUIET) +#define T_step_lt_i64(s, a, e) T_flags_lt_ll(a, e, T_CHECK_STEP(s)) +#define T_step_assert_lt_i64(s, a, e) \ + T_flags_lt_ll(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +/** @} */ + +/** + * @defgroup RTEMSTestFrameworkChecksUInt64 Unsigned 64-Bit Integer Checks + * + * @ingroup RTEMSTestFramework + * + * @brief Checks for unsigned 64-bit integers (uint64_t). + * + * @{ + */ + +#define T_eq_u64(a, e) T_flags_eq_ull(a, e, 0) +#define T_assert_eq_u64(a, e) T_flags_eq_ull(a, e, T_CHECK_STOP) +#define T_quiet_eq_u64(a, e) T_flags_eq_ull(a, e, T_CHECK_QUIET) +#define T_step_eq_u64(s, a, e) T_flags_eq_ull(a, e, T_CHECK_STEP(s)) +#define T_step_assert_eq_u64(s, a, e) \ + T_flags_eq_ull(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ne_u64(a, e) T_flags_ne_ull(a, e, 0) +#define T_assert_ne_u64(a, e) T_flags_ne_ull(a, e, T_CHECK_STOP) +#define T_quiet_ne_u64(a, e) T_flags_ne_ull(a, e, T_CHECK_QUIET) +#define T_step_ne_u64(s, a, e) T_flags_ne_ull(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ne_u64(s, a, e) \ + T_flags_ne_ull(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ge_u64(a, e) T_flags_ge_ull(a, e, 0) +#define T_assert_ge_u64(a, e) T_flags_ge_ull(a, e, T_CHECK_STOP) +#define T_quiet_ge_u64(a, e) T_flags_ge_ull(a, e, T_CHECK_QUIET) +#define T_step_ge_u64(s, a, e) T_flags_ge_ull(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ge_u64(s, a, e) \ + T_flags_ge_ull(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_gt_u64(a, e) T_flags_gt_ull(a, e, 0) +#define T_assert_gt_u64(a, e) T_flags_gt_ull(a, e, T_CHECK_STOP) +#define T_quiet_gt_u64(a, e) T_flags_gt_ull(a, e, T_CHECK_QUIET) +#define T_step_gt_u64(s, a, e) T_flags_gt_ull(a, e, T_CHECK_STEP(s)) +#define T_step_assert_gt_u64(s, a, e) \ + T_flags_gt_ull(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_le_u64(a, e) T_flags_le_ull(a, e, 0) +#define T_assert_le_u64(a, e) T_flags_le_ull(a, e, T_CHECK_STOP) +#define T_quiet_le_u64(a, e) T_flags_le_ull(a, e, T_CHECK_QUIET) +#define T_step_le_u64(s, a, e) T_flags_le_ull(a, e, T_CHECK_STEP(s)) +#define T_step_assert_le_u64(s, a, e) \ + T_flags_le_ull(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_lt_u64(a, e) T_flags_lt_ull(a, e, 0) +#define T_assert_lt_u64(a, e) T_flags_lt_ull(a, e, T_CHECK_STOP) +#define T_quiet_lt_u64(a, e) T_flags_lt_ull(a, e, T_CHECK_QUIET) +#define T_step_lt_u64(s, a, e) T_flags_lt_ull(a, e, T_CHECK_STEP(s)) +#define T_step_assert_lt_u64(s, a, e) \ + T_flags_lt_ull(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +/** @} */ + +/** + * @defgroup RTEMSTestFrameworkChecksIntptr Signed Pointer Value Checks + * + * @ingroup RTEMSTestFramework + * + * @brief Checks for signed pointer values (intptr_t). + * + * @{ + */ + +#define T_eq_iptr(a, e) T_flags_eq_long(a, e, 0) +#define T_assert_eq_iptr(a, e) T_flags_eq_long(a, e, T_CHECK_STOP) +#define T_quiet_eq_iptr(a, e) T_flags_eq_long(a, e, T_CHECK_QUIET) +#define T_step_eq_iptr(s, a, e) T_flags_eq_long(a, e, T_CHECK_STEP(s)) +#define T_step_assert_eq_iptr(s, a, e) \ + T_flags_eq_long(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ne_iptr(a, e) T_flags_ne_long(a, e, 0) +#define T_assert_ne_iptr(a, e) T_flags_ne_long(a, e, T_CHECK_STOP) +#define T_quiet_ne_iptr(a, e) T_flags_ne_long(a, e, T_CHECK_QUIET) +#define T_step_ne_iptr(s, a, e) T_flags_ne_long(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ne_iptr(s, a, e) \ + T_flags_ne_long(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ge_iptr(a, e) T_flags_ge_long(a, e, 0) +#define T_assert_ge_iptr(a, e) T_flags_ge_long(a, e, T_CHECK_STOP) +#define T_quiet_ge_iptr(a, e) T_flags_ge_long(a, e, T_CHECK_QUIET) +#define T_step_ge_iptr(s, a, e) T_flags_ge_long(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ge_iptr(s, a, e) \ + T_flags_ge_long(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_gt_iptr(a, e) T_flags_gt_long(a, e, 0) +#define T_assert_gt_iptr(a, e) T_flags_gt_long(a, e, T_CHECK_STOP) +#define T_quiet_gt_iptr(a, e) T_flags_gt_long(a, e, T_CHECK_QUIET) +#define T_step_gt_iptr(s, a, e) T_flags_gt_long(a, e, T_CHECK_STEP(s)) +#define T_step_assert_gt_iptr(s, a, e) \ + T_flags_gt_long(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_le_iptr(a, e) T_flags_le_long(a, e, 0) +#define T_assert_le_iptr(a, e) T_flags_le_long(a, e, T_CHECK_STOP) +#define T_quiet_le_iptr(a, e) T_flags_le_long(a, e, T_CHECK_QUIET) +#define T_step_le_iptr(s, a, e) T_flags_le_long(a, e, T_CHECK_STEP(s)) +#define T_step_assert_le_iptr(s, a, e) \ + T_flags_le_long(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_lt_iptr(a, e) T_flags_lt_long(a, e, 0) +#define T_assert_lt_iptr(a, e) T_flags_lt_long(a, e, T_CHECK_STOP) +#define T_quiet_lt_iptr(a, e) T_flags_lt_long(a, e, T_CHECK_QUIET) +#define T_step_lt_iptr(s, a, e) T_flags_lt_long(a, e, T_CHECK_STEP(s)) +#define T_step_assert_lt_iptr(s, a, e) \ + T_flags_lt_long(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +/** @} */ + +/** + * @defgroup RTEMSTestFrameworkChecksUIntptr Unsigned Pointer Value Checks + * + * @ingroup RTEMSTestFramework + * + * @brief Checks for unsigned pointer values (uintptr_t). + * + * @{ + */ + +#define T_eq_uptr(a, e) T_flags_eq_ulong(a, e, 0) +#define T_assert_eq_uptr(a, e) T_flags_eq_ulong(a, e, T_CHECK_STOP) +#define T_quiet_eq_uptr(a, e) T_flags_eq_ulong(a, e, T_CHECK_QUIET) +#define T_step_eq_uptr(s, a, e) T_flags_eq_ulong(a, e, T_CHECK_STEP(s)) +#define T_step_assert_eq_uptr(s, a, e) \ + T_flags_eq_ulong(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ne_uptr(a, e) T_flags_ne_ulong(a, e, 0) +#define T_assert_ne_uptr(a, e) T_flags_ne_ulong(a, e, T_CHECK_STOP) +#define T_quiet_ne_uptr(a, e) T_flags_ne_ulong(a, e, T_CHECK_QUIET) +#define T_step_ne_uptr(s, a, e) T_flags_ne_ulong(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ne_uptr(s, a, e) \ + T_flags_ne_ulong(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ge_uptr(a, e) T_flags_ge_ulong(a, e, 0) +#define T_assert_ge_uptr(a, e) T_flags_ge_ulong(a, e, T_CHECK_STOP) +#define T_quiet_ge_uptr(a, e) T_flags_ge_ulong(a, e, T_CHECK_QUIET) +#define T_step_ge_uptr(s, a, e) T_flags_ge_ulong(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ge_uptr(s, a, e) \ + T_flags_ge_ulong(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_gt_uptr(a, e) T_flags_gt_ulong(a, e, 0) +#define T_assert_gt_uptr(a, e) T_flags_gt_ulong(a, e, T_CHECK_STOP) +#define T_quiet_gt_uptr(a, e) T_flags_gt_ulong(a, e, T_CHECK_QUIET) +#define T_step_gt_uptr(s, a, e) T_flags_gt_ulong(a, e, T_CHECK_STEP(s)) +#define T_step_assert_gt_uptr(s, a, e) \ + T_flags_gt_ulong(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_le_uptr(a, e) T_flags_le_ulong(a, e, 0) +#define T_assert_le_uptr(a, e) T_flags_le_ulong(a, e, T_CHECK_STOP) +#define T_quiet_le_uptr(a, e) T_flags_le_ulong(a, e, T_CHECK_QUIET) +#define T_step_le_uptr(s, a, e) T_flags_le_ulong(a, e, T_CHECK_STEP(s)) +#define T_step_assert_le_uptr(s, a, e) \ + T_flags_le_ulong(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_lt_uptr(a, e) T_flags_lt_ulong(a, e, 0) +#define T_assert_lt_uptr(a, e) T_flags_lt_ulong(a, e, T_CHECK_STOP) +#define T_quiet_lt_uptr(a, e) T_flags_lt_ulong(a, e, T_CHECK_QUIET) +#define T_step_lt_uptr(s, a, e) T_flags_lt_ulong(a, e, T_CHECK_STEP(s)) +#define T_step_assert_lt_uptr(s, a, e) \ + T_flags_lt_ulong(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +/** @} */ + +/** + * @defgroup RTEMSTestFrameworkChecksSSZ Signed Size Checks + * + * @ingroup RTEMSTestFramework + * + * @brief Checks for signed sizes (ssize_t). + * + * @{ + */ + +#define T_eq_ssz(a, e) T_flags_eq_long(a, e, 0) +#define T_assert_eq_ssz(a, e) T_flags_eq_long(a, e, T_CHECK_STOP) +#define T_quiet_eq_ssz(a, e) T_flags_eq_long(a, e, T_CHECK_QUIET) +#define T_step_eq_ssz(s, a, e) T_flags_eq_long(a, e, T_CHECK_STEP(s)) +#define T_step_assert_eq_ssz(s, a, e) \ + T_flags_eq_long(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ne_ssz(a, e) T_flags_ne_long(a, e, 0) +#define T_assert_ne_ssz(a, e) T_flags_ne_long(a, e, T_CHECK_STOP) +#define T_quiet_ne_ssz(a, e) T_flags_ne_long(a, e, T_CHECK_QUIET) +#define T_step_ne_ssz(s, a, e) T_flags_ne_long(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ne_ssz(s, a, e) \ + T_flags_ne_long(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ge_ssz(a, e) T_flags_ge_long(a, e, 0) +#define T_assert_ge_ssz(a, e) T_flags_ge_long(a, e, T_CHECK_STOP) +#define T_quiet_ge_ssz(a, e) T_flags_ge_long(a, e, T_CHECK_QUIET) +#define T_step_ge_ssz(s, a, e) T_flags_ge_long(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ge_ssz(s, a, e) \ + T_flags_ge_long(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_gt_ssz(a, e) T_flags_gt_long(a, e, 0) +#define T_assert_gt_ssz(a, e) T_flags_gt_long(a, e, T_CHECK_STOP) +#define T_quiet_gt_ssz(a, e) T_flags_gt_long(a, e, T_CHECK_QUIET) +#define T_step_gt_ssz(s, a, e) T_flags_gt_long(a, e, T_CHECK_STEP(s)) +#define T_step_assert_gt_ssz(s, a, e) \ + T_flags_gt_long(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_le_ssz(a, e) T_flags_le_long(a, e, 0) +#define T_assert_le_ssz(a, e) T_flags_le_long(a, e, T_CHECK_STOP) +#define T_quiet_le_ssz(a, e) T_flags_le_long(a, e, T_CHECK_QUIET) +#define T_step_le_ssz(s, a, e) T_flags_le_long(a, e, T_CHECK_STEP(s)) +#define T_step_assert_le_ssz(s, a, e) \ + T_flags_le_long(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_lt_ssz(a, e) T_flags_lt_long(a, e, 0) +#define T_assert_lt_ssz(a, e) T_flags_lt_long(a, e, T_CHECK_STOP) +#define T_quiet_lt_ssz(a, e) T_flags_lt_long(a, e, T_CHECK_QUIET) +#define T_step_lt_ssz(s, a, e) T_flags_lt_long(a, e, T_CHECK_STEP(s)) +#define T_step_assert_lt_ssz(s, a, e) \ + T_flags_lt_long(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +/** @} */ + +/** + * @defgroup RTEMSTestFrameworkChecksSZ Size Checks + * + * @ingroup RTEMSTestFramework + * + * @brief Checks for sizes (size_t). + * + * @{ + */ + +#define T_eq_sz(a, e) T_flags_eq_ulong(a, e, 0) +#define T_assert_eq_sz(a, e) T_flags_eq_ulong(a, e, T_CHECK_STOP) +#define T_quiet_eq_sz(a, e) T_flags_eq_ulong(a, e, T_CHECK_QUIET) +#define T_step_eq_sz(s, a, e) T_flags_eq_ulong(a, e, T_CHECK_STEP(s)) +#define T_step_assert_eq_sz(s, a, e) \ + T_flags_eq_ulong(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ne_sz(a, e) T_flags_ne_ulong(a, e, 0) +#define T_assert_ne_sz(a, e) T_flags_ne_ulong(a, e, T_CHECK_STOP) +#define T_quiet_ne_sz(a, e) T_flags_ne_ulong(a, e, T_CHECK_QUIET) +#define T_step_ne_sz(s, a, e) T_flags_ne_ulong(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ne_sz(s, a, e) \ + T_flags_ne_ulong(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_ge_sz(a, e) T_flags_ge_ulong(a, e, 0) +#define T_assert_ge_sz(a, e) T_flags_ge_ulong(a, e, T_CHECK_STOP) +#define T_quiet_ge_sz(a, e) T_flags_ge_ulong(a, e, T_CHECK_QUIET) +#define T_step_ge_sz(s, a, e) T_flags_ge_ulong(a, e, T_CHECK_STEP(s)) +#define T_step_assert_ge_sz(s, a, e) \ + T_flags_ge_ulong(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_gt_sz(a, e) T_flags_gt_ulong(a, e, 0) +#define T_assert_gt_sz(a, e) T_flags_gt_ulong(a, e, T_CHECK_STOP) +#define T_quiet_gt_sz(a, e) T_flags_gt_ulong(a, e, T_CHECK_QUIET) +#define T_step_gt_sz(s, a, e) T_flags_gt_ulong(a, e, T_CHECK_STEP(s)) +#define T_step_assert_gt_sz(s, a, e) \ + T_flags_gt_ulong(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_le_sz(a, e) T_flags_le_ulong(a, e, 0) +#define T_assert_le_sz(a, e) T_flags_le_ulong(a, e, T_CHECK_STOP) +#define T_quiet_le_sz(a, e) T_flags_le_ulong(a, e, T_CHECK_QUIET) +#define T_step_le_sz(s, a, e) T_flags_le_ulong(a, e, T_CHECK_STEP(s)) +#define T_step_assert_le_sz(s, a, e) \ + T_flags_le_ulong(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_lt_sz(a, e) T_flags_lt_ulong(a, e, 0) +#define T_assert_lt_sz(a, e) T_flags_lt_ulong(a, e, T_CHECK_STOP) +#define T_quiet_lt_sz(a, e) T_flags_lt_ulong(a, e, T_CHECK_QUIET) +#define T_step_lt_sz(s, a, e) T_flags_lt_ulong(a, e, T_CHECK_STEP(s)) +#define T_step_assert_lt_sz(s, a, e) \ + T_flags_lt_ulong(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +/** @} */ + +/** + * @defgroup RTEMSTestFrameworkChecksPSX POSIX Status and Error Number Checks + * + * @ingroup RTEMSTestFramework + * + * @brief Checks for POSIX status and error numbers. + * + * @{ + */ + +const char *T_strerror(int); + +#define T_eno(a, e) T_flags_eno(a, e, 0) +#define T_assert_eno(a, e) T_flags_eno(a, e, T_CHECK_STOP) +#define T_quiet_eno(a, e) T_flags_eno(a, e, T_CHECK_QUIET) +#define T_step_eno(s, a, e) T_flags_eno(a, e, T_CHECK_STEP(s)) +#define T_step_assert_eno(s, a, e) \ + T_flags_eno(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_eno_success(a) T_flags_eno_success(a, 0) +#define T_assert_eno_success(a) T_flags_eno_success(a, T_CHECK_STOP) +#define T_quiet_eno_success(a) T_flags_eno_success(a, T_CHECK_QUIET) +#define T_step_eno_success(s, a) T_flags_eno_success(a, T_CHECK_STEP(s)) +#define T_step_assert_eno_success(s, a) \ + T_flags_eno_success(a, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_psx_error(a, eno) T_flags_psx_error(a, eno, 0) +#define T_assert_psx_error(a, eno) T_flags_psx_error(a, eno, T_CHECK_STOP) +#define T_quiet_psx_error(a, eno) T_flags_psx_error(a, eno, T_CHECK_QUIET) +#define T_step_psx_error(s, a, eno) T_flags_psx_error(a, eno, T_CHECK_STEP(s)) +#define T_step_assert_psx_error(s, a, eno) \ + T_flags_psx_error(a, eno, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_psx_success(a) T_flags_psx_success(a, 0) +#define T_assert_psx_success(a) T_flags_psx_success(a, T_CHECK_STOP) +#define T_quiet_psx_success(a) T_flags_psx_success(a, T_CHECK_QUIET) +#define T_step_psx_success(s, a) T_flags_psx_success(a, T_CHECK_STEP(s)) +#define T_step_assert_psx_success(s, a) \ + T_flags_psx_success(a, T_CHECK_STEP(s) | T_CHECK_STOP) + +/** @} */ + +#ifdef __rtems__ +void T_check_rsc(uint32_t, const T_check_context *, uint32_t); + +#define T_flags_rsc(a, e, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_rsc(a, &T_check_instance, e); \ +} + +void T_check_rsc_success(uint32_t, const T_check_context *); + +#define T_flags_rsc_success(a, flags) \ +{ \ + static const T_check_context T_check_instance = { \ + T_FILE_NAME, __LINE__, flags }; \ + T_check_rsc_success(a, &T_check_instance); \ +} + +/** + * @defgroup RTEMSTestFrameworkChecksRSC RTEMS Status Code Checks + * + * @ingroup RTEMSTestFramework + * + * @brief Checks for RTEMS status codes (rtems_status_code). + * + * @{ + */ + +#define T_rsc(a, e) T_flags_rsc(a, e, 0) +#define T_assert_rsc(a, e) T_flags_rsc(a, e, T_CHECK_STOP) +#define T_quiet_rsc(a, e) T_flags_rsc(a, e, T_CHECK_QUIET) +#define T_step_rsc(s, a, e) T_flags_rsc(a, e, T_CHECK_STEP(s)) +#define T_step_assert_rsc(s, a, e) \ + T_flags_rsc(a, e, T_CHECK_STEP(s) | T_CHECK_STOP) + +#define T_rsc_success(a) T_flags_rsc_success(a, 0) +#define T_assert_rsc_success(a) T_flags_rsc_success(a, T_CHECK_STOP) +#define T_quiet_rsc_success(a) T_flags_rsc_success(a, T_CHECK_QUIET) +#define T_step_rsc_success(s, a) T_flags_rsc_success(a, T_CHECK_STEP(s)) +#define T_step_assert_rsc_success(s, a) \ + T_flags_rsc_success(a, T_CHECK_STEP(s) | T_CHECK_STOP) + +/** @} */ +#endif /* __rtems__ */ + +void T_plan(unsigned int); + +#define T_step(s, ...) T_flags_true(true, T_CHECK_STEP(s), __VA_ARGS__) +#define T_step_assert(s, ...) \ + T_flags_true(true, T_CHECK_STEP(s) | T_CHECK_STOP, __VA_ARGS__) + +/** + * @defgroup RTEMSTestFrameworkTime Time Services + * + * @ingroup RTEMSTestFramework + * + * @brief Time service functions. + * + * @{ + */ + +#ifdef __rtems__ +typedef CPU_Counter_ticks T_ticks; +#else +typedef unsigned long T_ticks; +#endif + +typedef uint64_t T_time; + +/* More than enough for sizeof("18446744073.709552765") */ +typedef char T_time_string[24]; + +const char *T_time_to_string_ns(T_time, T_time_string); + +const char *T_time_to_string_us(T_time, T_time_string); + +const char *T_time_to_string_ms(T_time, T_time_string); + +const char *T_time_to_string_s(T_time, T_time_string); + +const char *T_ticks_to_string_ns(T_ticks, T_time_string); + +const char *T_ticks_to_string_us(T_ticks, T_time_string); + +const char *T_ticks_to_string_ms(T_ticks, T_time_string); + +const char *T_ticks_to_string_s(T_ticks, T_time_string); + +T_time T_ticks_to_time(T_ticks); + +T_ticks T_time_to_ticks(T_time); + +T_time T_seconds_and_nanoseconds_to_time(uint32_t, uint32_t); + +void T_time_to_seconds_and_nanoseconds(T_time, uint32_t *, uint32_t *); + +#ifdef __rtems__ +int64_t _Timecounter_Sbinuptime(void); + +static inline T_time +T_now(void) +{ + return (T_time)_Timecounter_Sbinuptime(); +} + +static inline T_ticks +T_tick(void) +{ + return _CPU_Counter_read(); +} +#else +T_time T_now(void); + +T_ticks T_tick(void); +#endif + +T_time T_now_dummy(void); + +T_time T_now_via_tick(void); + +T_time T_case_begin_time(void); + +/** @} */ + +void *T_malloc(size_t); + +void *T_calloc(size_t, size_t); + +void *T_zalloc(size_t, void (*)(void *)); + +void T_free(void *); + +void T_register(void); + +typedef enum { + T_EVENT_RUN_INITIALIZE, + T_EVENT_CASE_EARLY, + T_EVENT_CASE_BEGIN, + T_EVENT_CASE_END, + T_EVENT_CASE_LATE, + T_EVENT_RUN_FINALIZE +} T_event; + +typedef void (*T_action)(T_event, const char *); + +typedef void (*T_putchar)(int, void *); + +typedef struct { + const char *name; + T_putchar putchar; + void *putchar_arg; + T_verbosity verbosity; + T_time (*now)(void); + size_t action_count; + const T_action *actions; +} T_config; + +void T_putchar_default(int, void *); + +int T_main(const T_config *); + +bool T_is_runner(void); + +void T_run_initialize(const T_config *); + +void T_run_all(void); + +void T_run_by_name(const char *); + +void T_case_begin(const char *, const T_fixture *); + +void T_case_end(void); + +bool T_run_finalize(void); + +void T_set_putchar(T_putchar, void *, T_putchar *, void **); + +void *T_fixture_context(void); + +void T_set_fixture_context(void *); + +#ifdef __rtems__ +#define T_TEST_CASE_FIXTURE(name, fixture) \ +void T_case_body_##name(void); \ +T_case_context T_case_instance_##name = { \ + #name, \ + T_case_body_##name, \ + fixture, \ + NULL \ +}; \ +static T_case_context * const T_case_item_##name \ +__attribute((__section__(".rtemsroset._T.content.0." #name))) \ +__attribute((__used__)) = &T_case_instance_##name; \ +void T_case_body_##name(void) +#else /* __rtems__ */ +#define T_TEST_CASE_FIXTURE(name, fixture) \ +void T_case_body_##name(void); \ +T_case_context T_case_instance_##name = { \ + #name, \ + T_case_body_##name, \ + fixture, \ + NULL \ +}; \ +__attribute((__constructor__)) static void \ +T_case_register_##name(void) \ +{ \ + T_case_register(&T_case_instance_##name); \ +} \ +void T_case_body_##name(void) +#endif /* __rtems__ */ + +#define T_TEST_CASE(name) T_TEST_CASE_FIXTURE(name, NULL) + +void T_report_hash_sha256(T_event, const char *); + +void T_check_heap(T_event, const char *); + +#ifdef __rtems__ +void T_check_file_descriptors(T_event, const char *); + +void T_check_rtems_barriers(T_event, const char *); + +void T_check_rtems_extensions(T_event, const char *); + +void T_check_rtems_message_queues(T_event, const char *); + +void T_check_rtems_partitions(T_event, const char *); + +void T_check_rtems_periods(T_event, const char *); + +void T_check_rtems_regions(T_event, const char *); + +void T_check_rtems_semaphores(T_event, const char *); + +void T_check_rtems_tasks(T_event, const char *); + +void T_check_rtems_timers(T_event, const char *); + +void T_check_posix_keys(T_event, const char *); + +void T_check_posix_message_queues(T_event, const char *); + +void T_check_posix_semaphores(T_event, const char *); + +void T_check_posix_shms(T_event, const char *); + +void T_check_posix_threads(T_event, const char *); + +void T_check_posix_timers(T_event, const char *); +#endif /* __rtems__ */ + +/** + * @defgroup RTEMSTestFrameworkDestructors Destructors + * + * @ingroup RTEMSTestFramework + * + * @brief Support to run destructors at the end of a test case. + * + * @{ + */ + +typedef struct T_destructor { + struct { + struct T_destructor *le_next; + struct T_destructor **le_prev; + } node; + void (*destroy)(struct T_destructor *); +} T_destructor; + +void T_add_destructor(T_destructor *, void (*)(T_destructor *)); + +void T_remove_destructor(T_destructor *); + +/** @} */ + +/** + * @defgroup RTEMSTestFrameworkMeasureRuntime Runtime Measurements + * + * @ingroup RTEMSTestFramework + * + * @brief Support to measure the runtime of code fragments. + * + * @{ + */ + +typedef struct T_measure_runtime_context T_measure_runtime_context; + +typedef struct { + size_t sample_count; +} T_measure_runtime_config; + +typedef struct { + const char *name; + int flags; + void (*setup)(void *); + void (*body)(void *); + bool (*teardown)(void *, T_ticks *, uint32_t, uint32_t, unsigned int); + void *arg; +} T_measure_runtime_request; + +#define T_MEASURE_RUNTIME_ALLOW_CLOCK_ISR 0x1 + +#define T_MEASURE_RUNTIME_REPORT_SAMPLES 0x2 + +#define T_MEASURE_RUNTIME_DISABLE_VALID_CACHE 0x10 + +#define T_MEASURE_RUNTIME_DISABLE_HOT_CACHE 0x20 + +#define T_MEASURE_RUNTIME_DISABLE_DIRTY_CACHE 0x40 + +#define T_MEASURE_RUNTIME_DISABLE_MINOR_LOAD 0x80 + +#define T_MEASURE_RUNTIME_DISABLE_MAX_LOAD 0x100 + +T_measure_runtime_context *T_measure_runtime_create( + const T_measure_runtime_config *); + +void T_measure_runtime(T_measure_runtime_context *, + const T_measure_runtime_request *); + +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* THE_T_TEST_FRAMEWORK_H */ diff --git a/cpukit/libtest/t-test-checks-eno.c b/cpukit/libtest/t-test-checks-eno.c new file mode 100644 index 0000000000..c33b196206 --- /dev/null +++ b/cpukit/libtest/t-test-checks-eno.c @@ -0,0 +1,145 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (C) 2018 embedded brains GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include + +#define T_STRERROR_CASE(eno) case eno: return #eno + +const char *T_strerror(int eno) +{ + switch (eno) { + case 0: + return "0"; + T_STRERROR_CASE(E2BIG); + T_STRERROR_CASE(EACCES); + T_STRERROR_CASE(EADDRINUSE); + T_STRERROR_CASE(EADDRNOTAVAIL); + T_STRERROR_CASE(EAFNOSUPPORT); + T_STRERROR_CASE(EAGAIN); + T_STRERROR_CASE(EALREADY); + T_STRERROR_CASE(EBADF); + T_STRERROR_CASE(EBADMSG); + T_STRERROR_CASE(EBUSY); + T_STRERROR_CASE(ECANCELED); + T_STRERROR_CASE(ECHILD); + T_STRERROR_CASE(ECONNABORTED); + T_STRERROR_CASE(ECONNREFUSED); + T_STRERROR_CASE(ECONNRESET); + T_STRERROR_CASE(EDEADLK); + T_STRERROR_CASE(EDESTADDRREQ); + T_STRERROR_CASE(EDOM); + T_STRERROR_CASE(EDQUOT); + T_STRERROR_CASE(EEXIST); + T_STRERROR_CASE(EFAULT); + T_STRERROR_CASE(EFBIG); + T_STRERROR_CASE(EHOSTDOWN); + T_STRERROR_CASE(EHOSTUNREACH); + T_STRERROR_CASE(EIDRM); + T_STRERROR_CASE(EILSEQ); + T_STRERROR_CASE(EINPROGRESS); + T_STRERROR_CASE(EINTR); + T_STRERROR_CASE(EINVAL); + T_STRERROR_CASE(EIO); + T_STRERROR_CASE(EISCONN); + T_STRERROR_CASE(EISDIR); + T_STRERROR_CASE(ELOOP); + T_STRERROR_CASE(EMFILE); + T_STRERROR_CASE(EMLINK); + T_STRERROR_CASE(EMSGSIZE); + T_STRERROR_CASE(EMULTIHOP); + T_STRERROR_CASE(ENAMETOOLONG); + T_STRERROR_CASE(ENETDOWN); + T_STRERROR_CASE(ENETRESET); + T_STRERROR_CASE(ENETUNREACH); + T_STRERROR_CASE(ENFILE); + T_STRERROR_CASE(ENOBUFS); +#ifdef ENODATA + T_STRERROR_CASE(ENODATA); +#endif + T_STRERROR_CASE(ENODEV); + T_STRERROR_CASE(ENOENT); + T_STRERROR_CASE(ENOEXEC); + T_STRERROR_CASE(ENOLCK); + T_STRERROR_CASE(ENOLINK); + T_STRERROR_CASE(ENOMEM); + T_STRERROR_CASE(ENOMSG); + T_STRERROR_CASE(ENOPROTOOPT); + T_STRERROR_CASE(ENOSPC); +#ifdef ENOSR + T_STRERROR_CASE(ENOSR); +#endif +#ifdef ENOSTR + T_STRERROR_CASE(ENOSTR); +#endif + T_STRERROR_CASE(ENOSYS); + T_STRERROR_CASE(ENOTCONN); + T_STRERROR_CASE(ENOTDIR); + T_STRERROR_CASE(ENOTEMPTY); + T_STRERROR_CASE(ENOTRECOVERABLE); + T_STRERROR_CASE(ENOTSOCK); +#if ENOTSUP != EOPNOTSUPP + T_STRERROR_CASE(ENOTSUP); +#endif + T_STRERROR_CASE(ENOTTY); + T_STRERROR_CASE(ENXIO); + T_STRERROR_CASE(EOPNOTSUPP); + T_STRERROR_CASE(EOVERFLOW); + T_STRERROR_CASE(EOWNERDEAD); + T_STRERROR_CASE(EPERM); + T_STRERROR_CASE(EPFNOSUPPORT); + T_STRERROR_CASE(EPIPE); + T_STRERROR_CASE(EPROTO); + T_STRERROR_CASE(EPROTONOSUPPORT); + T_STRERROR_CASE(EPROTOTYPE); + T_STRERROR_CASE(ERANGE); + T_STRERROR_CASE(EROFS); + T_STRERROR_CASE(ESPIPE); + T_STRERROR_CASE(ESRCH); + T_STRERROR_CASE(ESTALE); +#ifdef ETIME + T_STRERROR_CASE(ETIME); +#endif + T_STRERROR_CASE(ETIMEDOUT); + T_STRERROR_CASE(ETOOMANYREFS); + T_STRERROR_CASE(ETXTBSY); + T_STRERROR_CASE(EXDEV); + default: + return "?"; + } +} + +void T_check_eno(int a, const T_check_context *t, int e) +{ + T_check_true(a == e, t, "%s == %s", T_strerror(a), T_strerror(e)); +} + +void T_check_eno_success(int a, const T_check_context *t) +{ + T_check_eno(a, t, 0); +} diff --git a/cpukit/libtest/t-test-checks-psx.c b/cpukit/libtest/t-test-checks-psx.c new file mode 100644 index 0000000000..58e9fb64f5 --- /dev/null +++ b/cpukit/libtest/t-test-checks-psx.c @@ -0,0 +1,17 @@ +#include + +#include + +void T_check_psx_error(int a, const T_check_context *t, int eeno) +{ + int aeno; + + aeno = errno; + T_check_true(a == -1 && aeno == eeno, t, "%i == -1, %s == %s", a, + T_strerror(aeno), T_strerror(eeno)); +} + +void T_check_psx_success(int a, const T_check_context *t) +{ + T_check_true(a == 0, t, "%i == 0, %s", a, T_strerror(errno)); +} diff --git a/cpukit/libtest/t-test-checks.c b/cpukit/libtest/t-test-checks.c new file mode 100644 index 0000000000..b9e1f7b5f5 --- /dev/null +++ b/cpukit/libtest/t-test-checks.c @@ -0,0 +1,328 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (C) 2018 embedded brains GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include + +void +T_check_eq_ptr(const void *a, const T_check_context_msg *t, const void *e) +{ + T_check_true(a == e, &t->base, "%s", t->msg); +} + +void +T_check_ne_ptr(const void *a, const T_check_context_msg *t, const void *e) +{ + T_check_true(a != e, &t->base, "%s", t->msg); +} + +void +T_check_null(const void *a, const T_check_context_msg *t) +{ + T_check_true(a == NULL, &t->base, "%s == NULL", t->msg); +} + +void +T_check_not_null(const void *a, const T_check_context_msg *t) +{ + T_check_true(a != NULL, &t->base, "%s != NULL", t->msg); +} + +void +T_check_eq_mem(const void *a, const T_check_context_msg *t, const void *e, + size_t n) +{ + T_check_true(memcmp(a, e, n) == 0, &t->base, "%s", t->msg); +} + +void +T_check_ne_mem(const void *a, const T_check_context_msg *t, const void *e, + size_t n) +{ + T_check_true(memcmp(a, e, n) != 0, &t->base, "%s", t->msg); +} + +void +T_check_eq_str(const char *a, const T_check_context *t, const char *e) +{ + T_check_true(strcmp(a, e) == 0, t, "\"%s\" == \"%s\"", a, e); +} + +void +T_check_ne_str(const char *a, const T_check_context *t, const char *e) +{ + T_check_true(strcmp(a, e) != 0, t, "\"%s\" != \"%s\"", a, e); +} + +void +T_check_eq_nstr(const char *a, const T_check_context *t, const char *e, size_t n) +{ + T_check_true(strncmp(a, e, n) == 0, t, "\"%.*s\" == \"%.*s\"", (int)n, a, + (int)n, e); +} + +void +T_check_ne_nstr(const char *a, const T_check_context *t, const char *e, size_t n) +{ + T_check_true(strncmp(a, e, n) != 0, t, "\"%.*s\" != \"%.*s\"", (int)n, a, + (int)n, e); +} + +void +T_check_eq_char(char a, const T_check_context *t, char e) +{ + T_check_true(a == e, t, "'%c' == '%c'", a, e); +} + +void +T_check_ne_char(char a, const T_check_context *t, char e) +{ + T_check_true(a != e, t, "'%c' != '%c'", a, e); +} + +void +T_check_eq_int(int a, const T_check_context *t, int e) +{ + T_check_true(a == e, t, "%i == %i", a, e); +} + +void +T_check_ne_int(int a, const T_check_context *t, int e) +{ + T_check_true(a != e, t, "%i != %i", a, e); +} + +void +T_check_ge_int(int a, const T_check_context *t, int e) +{ + T_check_true(a >= e, t, "%i >= %i", a, e); +} + +void +T_check_gt_int(int a, const T_check_context *t, int e) +{ + T_check_true(a > e, t, "%i > %i", a, e); +} + +void +T_check_le_int(int a, const T_check_context *t, int e) +{ + T_check_true(a <= e, t, "%i <= %i", a, e); +} + +void +T_check_lt_int(int a, const T_check_context *t, int e) +{ + T_check_true(a < e, t, "%i < %i", a, e); +} + +void +T_check_eq_uint(unsigned int a, const T_check_context *t, unsigned int e) +{ + T_check_true(a == e, t, "%u == %u", a, e); +} + +void +T_check_ne_uint(unsigned int a, const T_check_context *t, unsigned int e) +{ + T_check_true(a != e, t, "%u != %u", a, e); +} + +void +T_check_ge_uint(unsigned int a, const T_check_context *t, unsigned int e) +{ + T_check_true(a >= e, t, "%u >= %u", a, e); +} + +void +T_check_gt_uint(unsigned int a, const T_check_context *t, unsigned int e) +{ + T_check_true(a > e, t, "%u > %u", a, e); +} + +void +T_check_le_uint(unsigned int a, const T_check_context *t, unsigned int e) +{ + T_check_true(a <= e, t, "%u <= %u", a, e); +} + +void +T_check_lt_uint(unsigned int a, const T_check_context *t, unsigned int e) +{ + T_check_true(a < e, t, "%u < %u", a, e); +} + +void +T_check_eq_long(long a, const T_check_context *t, long e) +{ + T_check_true(a == e, t, "%li == %li", a, e); +} + +void +T_check_ne_long(long a, const T_check_context *t, long e) +{ + T_check_true(a != e, t, "%li != %li", a, e); +} + +void +T_check_ge_long(long a, const T_check_context *t, long e) +{ + T_check_true(a >= e, t, "%li >= %li", a, e); +} + +void +T_check_gt_long(long a, const T_check_context *t, long e) +{ + T_check_true(a > e, t, "%li > %li", a, e); +} + +void +T_check_le_long(long a, const T_check_context *t, long e) +{ + T_check_true(a <= e, t, "%li <= %li", a, e); +} + +void +T_check_lt_long(long a, const T_check_context *t, long e) +{ + T_check_true(a < e, t, "%li < %li", a, e); +} + +void +T_check_eq_ulong(unsigned long a, const T_check_context *t, unsigned long e) +{ + T_check_true(a == e, t, "%lu == %lu", a, e); +} + +void +T_check_ne_ulong(unsigned long a, const T_check_context *t, unsigned long e) +{ + T_check_true(a != e, t, "%lu != %lu", a, e); +} + +void +T_check_ge_ulong(unsigned long a, const T_check_context *t, unsigned long e) +{ + T_check_true(a >= e, t, "%lu >= %lu", a, e); +} + +void +T_check_gt_ulong(unsigned long a, const T_check_context *t, unsigned long e) +{ + T_check_true(a > e, t, "%lu > %lu", a, e); +} + +void +T_check_le_ulong(unsigned long a, const T_check_context *t, unsigned long e) +{ + T_check_true(a <= e, t, "%lu <= %lu", a, e); +} + +void +T_check_lt_ulong(unsigned long a, const T_check_context *t, unsigned long e) +{ + T_check_true(a < e, t, "%lu < %lu", a, e); +} + +void +T_check_eq_ll(long long a, const T_check_context *t, long long e) +{ + T_check_true(a == e, t, "%lli == %lli", a, e); +} + +void +T_check_ne_ll(long long a, const T_check_context *t, long long e) +{ + T_check_true(a != e, t, "%lli != %lli", a, e); +} + +void +T_check_ge_ll(long long a, const T_check_context *t, long long e) +{ + T_check_true(a >= e, t, "%lli >= %lli", a, e); +} + +void +T_check_gt_ll(long long a, const T_check_context *t, long long e) +{ + T_check_true(a > e, t, "%lli > %lli", a, e); +} + +void +T_check_le_ll(long long a, const T_check_context *t, long long e) +{ + T_check_true(a <= e, t, "%lli <= %lli", a, e); +} + +void +T_check_lt_ll(long long a, const T_check_context *t, long long e) +{ + T_check_true(a < e, t, "%lli < %lli", a, e); +} + +void +T_check_eq_ull(unsigned long long a, const T_check_context *t, + unsigned long long e) +{ + T_check_true(a == e, t, "%llu == %llu", a, e); +} + +void +T_check_ne_ull(unsigned long long a, const T_check_context *t, + unsigned long long e) +{ + T_check_true(a != e, t, "%llu != %llu", a, e); +} + +void +T_check_ge_ull(unsigned long long a, const T_check_context *t, + unsigned long long e) +{ + T_check_true(a >= e, t, "%llu >= %llu", a, e); +} + +void +T_check_gt_ull(unsigned long long a, const T_check_context *t, + unsigned long long e) +{ + T_check_true(a > e, t, "%llu > %llu", a, e); +} + +void +T_check_le_ull(unsigned long long a, const T_check_context *t, + unsigned long long e) +{ + T_check_true(a <= e, t, "%llu <= %llu", a, e); +} + +void +T_check_lt_ull(unsigned long long a, const T_check_context *t, + unsigned long long e) +{ + T_check_true(a < e, t, "%llu < %llu", a, e); +} diff --git a/cpukit/libtest/t-test-hash-sha256.c b/cpukit/libtest/t-test-hash-sha256.c new file mode 100644 index 0000000000..c272da27ac --- /dev/null +++ b/cpukit/libtest/t-test-hash-sha256.c @@ -0,0 +1,100 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (C) 2019 embedded brains GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#if defined(__rtems__) +#include +#else +#include +#endif + +typedef struct { + SHA256_CTX sha256; + T_putchar putchar; + void *putchar_arg; +} T_report_hash_sha256_context; + +static T_report_hash_sha256_context T_report_hash_sha256_instance; + +static void +T_report_hash_sha256_putchar(int c, void *arg) +{ + T_report_hash_sha256_context *ctx; + char cc; + + ctx = arg; + cc = (char)c; + SHA256_Update(&ctx->sha256, &cc, sizeof(cc)); + (*ctx->putchar)(c, ctx->putchar_arg); +} + +static void +T_report_hash_sha256_initialize(void) +{ + T_report_hash_sha256_context *ctx; + + ctx = &T_report_hash_sha256_instance; + SHA256_Init(&ctx->sha256); + T_set_putchar(T_report_hash_sha256_putchar, ctx, &ctx->putchar, + &ctx->putchar_arg); +} + +static void +T_report_hash_sha256_finalize(void) +{ + T_report_hash_sha256_context *ctx; + unsigned char hash[32]; + size_t i; + + ctx = &T_report_hash_sha256_instance; + SHA256_Final(hash, &ctx->sha256); + T_printf("Y:ReportHash:SHA256:"); + + for (i = 0; i < 32; ++i) { + T_printf("%02x", hash[i]); + } + + T_printf("\n"); +} + +void +T_report_hash_sha256(T_event event, const char *name) +{ + (void)name; + + switch (event) { + case T_EVENT_RUN_INITIALIZE: + T_report_hash_sha256_initialize(); + break; + case T_EVENT_RUN_FINALIZE: + T_report_hash_sha256_finalize(); + break; + default: + break; + }; +} diff --git a/cpukit/libtest/t-test-malloc.c b/cpukit/libtest/t-test-malloc.c new file mode 100644 index 0000000000..83f32bebf5 --- /dev/null +++ b/cpukit/libtest/t-test-malloc.c @@ -0,0 +1,112 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (C) 2018 embedded brains GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include + +#ifdef __BIGGEST_ALIGNMENT__ +#define T_BIGGEST_ALIGNMENT __BIGGEST_ALIGNMENT__ +#else +#define T_BIGGEST_ALIGNMENT sizeof(long long) +#endif + +typedef struct __attribute__((__aligned__(T_BIGGEST_ALIGNMENT))) { + T_destructor base; + void (*destroy)(void *); +} T_malloc_destructor; + +static void +T_malloc_destroy(T_destructor *base) +{ + T_malloc_destructor *dtor; + + dtor = (T_malloc_destructor *)(uintptr_t)base; + + if (dtor->destroy != NULL) { + (*dtor->destroy)(dtor + 1); + } + + free(dtor); +} + +static void * +T_do_malloc(size_t size, void (*destroy)(void *)) +{ + T_malloc_destructor *dtor; + size_t new_size; + + new_size = sizeof(*dtor) + size; + if (new_size <= size) { + return NULL; + } + + dtor = malloc(new_size); + if (dtor != NULL) { + dtor->destroy = destroy; + T_add_destructor(&dtor->base, T_malloc_destroy); + ++dtor; + } + + return dtor; +} + +void * +T_malloc(size_t size) +{ + return T_do_malloc(size, NULL); +} + +void * +T_calloc(size_t nelem, size_t elsize) +{ + return T_zalloc(nelem * elsize, NULL); +} + +void * +T_zalloc(size_t size, void (*destroy)(void *)) +{ + void *p; + + p = T_do_malloc(size, destroy); + if (p != NULL) { + p = memset(p, 0, size); + } + + return p; +} + +void +T_free(void *ptr) +{ + T_malloc_destructor *dtor; + + dtor = ptr; + --dtor; + T_remove_destructor(&dtor->base); + free(dtor); +} diff --git a/cpukit/libtest/t-test-rtems-fds.c b/cpukit/libtest/t-test-rtems-fds.c new file mode 100644 index 0000000000..79720a01c4 --- /dev/null +++ b/cpukit/libtest/t-test-rtems-fds.c @@ -0,0 +1,83 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (C) 2018 embedded brains GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include + +static int T_open_fds; + +static int +T_count_open_fds(void) +{ + int free_count; + rtems_libio_t *iop; + + free_count = 0; + rtems_libio_lock(); + + iop = rtems_libio_iop_free_head; + while (iop != NULL) { + ++free_count; + iop = iop->data1; + } + + rtems_libio_unlock(); + return (int)rtems_libio_number_iops - free_count; +} + +static void +T_check_open_fds(void) +{ + int open_fds; + int delta; + + open_fds = T_count_open_fds(); + delta = open_fds - T_open_fds; + + if (delta != 0) { + T_open_fds = open_fds; + T_check_true(NULL, false, "file descriptor leak (%+i)", delta); + } +} + +void +T_check_file_descriptors(T_event event, const char *name) +{ + (void)name; + + switch (event) { + case T_EVENT_RUN_INITIALIZE: + T_open_fds = T_count_open_fds(); + break; + case T_EVENT_CASE_END: + T_check_open_fds(); + break; + default: + break; + }; +} diff --git a/cpukit/libtest/t-test-rtems-heap.c b/cpukit/libtest/t-test-rtems-heap.c new file mode 100644 index 0000000000..8858f5b952 --- /dev/null +++ b/cpukit/libtest/t-test-rtems-heap.c @@ -0,0 +1,112 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (C) 2018 embedded brains GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +#include +#include + +typedef struct { + Heap_Information_block heap_info; + Heap_Information_block workspace_info; +} T_resource_heap_context; + +static T_resource_heap_context T_resource_heap_instance; + +static void +T_get_heap_info(Heap_Control *heap, Heap_Information_block *info) +{ + _Heap_Get_information(heap, info); + memset(&info->Stats, 0, sizeof(info->Stats)); +} + +static void +T_heap_run_initialize(void) +{ + T_resource_heap_context *ctx; + + ctx = &T_resource_heap_instance; + T_get_heap_info(&_Workspace_Area, &ctx->workspace_info); + + if (!rtems_configuration_get_unified_work_area()) { + T_get_heap_info(RTEMS_Malloc_Heap, &ctx->heap_info); + } +} + +static void +T_heap_case_end(void) +{ + T_resource_heap_context *ctx; + Heap_Information_block info; + bool ok; + + ctx = &T_resource_heap_instance; + + T_get_heap_info(&_Workspace_Area, &info); + ok = memcmp(&info, &ctx->workspace_info, sizeof(info)) == 0; + + if (!ok) { + const char *where; + + if (rtems_configuration_get_unified_work_area()) { + where = "workspace or heap"; + } else { + where = "workspace"; + } + + T_check_true(ok, NULL, "memory leak in %s", where); + memcpy(&ctx->workspace_info, &info, sizeof(info)); + } + + if (!rtems_configuration_get_unified_work_area()) { + T_get_heap_info(RTEMS_Malloc_Heap, &info); + ok = memcmp(&info, &ctx->heap_info, sizeof(info)) == 0; + + if (!ok) { + T_check_true(ok, NULL, "memory leak in heap"); + memcpy(&ctx->heap_info, &info, sizeof(info)); + } + } +} + +void +T_check_heap(T_event event, const char *name) +{ + (void)name; + + switch (event) { + case T_EVENT_RUN_INITIALIZE: + T_heap_run_initialize(); + break; + case T_EVENT_CASE_END: + T_heap_case_end(); + break; + default: + break; + }; +} diff --git a/cpukit/libtest/t-test-rtems-measure.c b/cpukit/libtest/t-test-rtems-measure.c new file mode 100644 index 0000000000..207aef7afa --- /dev/null +++ b/cpukit/libtest/t-test-rtems-measure.c @@ -0,0 +1,837 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (C) 2018 embedded brains GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +#include +#include +#include + +#include + +#define WAKEUP_EVENT RTEMS_EVENT_0 + +typedef struct { + struct T_measure_runtime_context *master; + rtems_id id; + volatile unsigned int *chunk; +} load_context; + +struct T_measure_runtime_context { + T_destructor destructor; + size_t sample_count; + T_ticks *samples; + size_t cache_line_size; + size_t chunk_size; + volatile unsigned int *chunk; + rtems_id runner; + uint32_t load_count; + load_context *load_contexts; +}; + +static unsigned int +dirty_data_cache(volatile unsigned int *chunk, size_t chunk_size, + size_t cache_line_size, unsigned int token) +{ + size_t m; + size_t k; + size_t i; + + m = chunk_size / sizeof(chunk[0]); + k = cache_line_size / sizeof(chunk[0]); + + for (i = 0; i < m; i += k) { + chunk[i] = i + token; + } + + return i + token; +} + +static void +wait_for_worker(void) +{ + rtems_event_set events; + + (void)rtems_event_receive(WAKEUP_EVENT, RTEMS_EVENT_ALL | RTEMS_WAIT, + RTEMS_NO_TIMEOUT, &events); +} + +static void +wakeup_master(const T_measure_runtime_context *ctx) +{ + (void)rtems_event_send(ctx->runner, WAKEUP_EVENT); +} + +static void +suspend_worker(const load_context *lctx) +{ + (void)rtems_task_suspend(lctx->id); +} + +static void +restart_worker(const load_context *lctx) +{ + (void)rtems_task_restart(lctx->id, (rtems_task_argument)lctx); + wait_for_worker(); +} + +static void +load_worker(rtems_task_argument arg) +{ + const load_context *lctx; + T_measure_runtime_context *ctx; + unsigned int token; + volatile unsigned int *chunk; + size_t chunk_size; + size_t cache_line_size; + + lctx = (const load_context *)arg; + ctx = lctx->master; + chunk = lctx->chunk; + chunk_size = ctx->chunk_size; + cache_line_size = ctx->cache_line_size; + token = (unsigned int)rtems_get_current_processor(); + + token = dirty_data_cache(chunk, chunk_size, cache_line_size, token); + wakeup_master(ctx); + + while (true) { + token = dirty_data_cache(chunk, chunk_size, cache_line_size, + token); + } +} + +static void +destroy_worker(const T_measure_runtime_context *ctx) +{ + uint32_t load; + + for (load = 0; load < ctx->load_count; ++load) { + const load_context *lctx; + + lctx = &ctx->load_contexts[load]; + + if (lctx->chunk != ctx->chunk) { + free(RTEMS_DEVOLATILE(unsigned int *, lctx->chunk)); + } + + + if (lctx->id != 0) { + rtems_task_delete(lctx->id); + } + } +} + +static void +destroy(T_destructor *dtor) +{ + T_measure_runtime_context *ctx; + + ctx = (T_measure_runtime_context *)dtor; + destroy_worker(ctx); + free(ctx); +} + +static void * +add_offset(const volatile void *p, uintptr_t o) +{ + return (void *)((uintptr_t)p + o); +} + +static void * +align_up(const volatile void *p, uintptr_t a) +{ + return (void *)(((uintptr_t)p + a - 1) & ~(a - 1)); +} + +T_measure_runtime_context * +T_measure_runtime_create(const T_measure_runtime_config *config) +{ + T_measure_runtime_context *ctx; + size_t sample_size; + size_t cache_line_size; + size_t chunk_size; + size_t load_size; + uint32_t load_count; + bool success; + uint32_t i; +#ifdef RTEMS_SMP + cpu_set_t cpu; +#endif + + sample_size = config->sample_count * sizeof(ctx->samples[0]); + + cache_line_size = rtems_cache_get_data_line_size(); + + if (cache_line_size == 0) { + cache_line_size = 8; + } + + chunk_size = rtems_cache_get_data_cache_size(0); + + if (chunk_size == 0) { + chunk_size = cache_line_size; + } + + chunk_size *= 2; + + load_count = rtems_get_processor_count(); + load_size = load_count * sizeof(ctx->load_contexts[0]); + + ctx = malloc(sizeof(*ctx) + sample_size + load_size + chunk_size + + 2 * cache_line_size); + + if (ctx == NULL) { + return NULL; + } + + ctx->sample_count = config->sample_count; + ctx->samples = add_offset(ctx, sizeof(*ctx)); + ctx->cache_line_size = cache_line_size; + ctx->chunk_size = chunk_size; + ctx->chunk = add_offset(ctx->samples, sample_size); + ctx->runner = rtems_task_self(); + ctx->load_count = load_count; + ctx->load_contexts = add_offset(ctx->chunk, chunk_size); + ctx->samples = align_up(ctx->samples, cache_line_size); + ctx->chunk = align_up(ctx->chunk, cache_line_size); + + memset(ctx->load_contexts, 0, load_size); + success = true; + + for (i = 0; i < load_count; ++i) { + rtems_status_code sc; + rtems_id id; + load_context *lctx; +#ifdef RTEMS_SMP + rtems_task_priority priority; + rtems_id scheduler; + + sc = rtems_scheduler_ident_by_processor(i, &scheduler); + if (sc != RTEMS_SUCCESSFUL) { + continue; + } +#endif + + sc = rtems_task_create(rtems_build_name('L', 'O', 'A', 'D'), + RTEMS_MAXIMUM_PRIORITY - 1, RTEMS_MINIMUM_STACK_SIZE, + RTEMS_DEFAULT_MODES, RTEMS_DEFAULT_ATTRIBUTES, &id); + if (sc != RTEMS_SUCCESSFUL) { + success = false; + break; + } + + lctx = &ctx->load_contexts[i]; + + lctx->master = ctx; + lctx->id = id; + + lctx->chunk = malloc(chunk_size); + if (lctx->chunk == NULL) { + lctx->chunk = ctx->chunk; + } + +#ifdef RTEMS_SMP + (void)rtems_scheduler_get_maximum_priority(scheduler, &priority); + (void)rtems_task_set_scheduler(id, scheduler, priority - 1); + + CPU_ZERO(&cpu); + CPU_SET((int)i, &cpu); + (void)rtems_task_set_affinity(id, sizeof(cpu), &cpu); +#endif + + (void)rtems_task_start(id, load_worker, + (rtems_task_argument)lctx); + + wait_for_worker(); + suspend_worker(lctx); + } + + if (success) { +#ifdef RTEMS_SMP + CPU_ZERO(&cpu); + CPU_SET(0, &cpu); + (void)rtems_task_set_affinity(RTEMS_SELF, sizeof(cpu), &cpu); +#endif + } else { + destroy(&ctx->destructor); + return NULL; + } + + T_add_destructor(&ctx->destructor, destroy); + return ctx; +} + +static int +cmp(const void *ap, const void *bp) +{ + T_ticks a; + T_ticks b; + + a = *(const T_ticks *)ap; + b = *(const T_ticks *)bp; + + if (a < b) { + return -1; + } else if (a > b) { + return 1; + } else { + return 0; + } +} + +static void +measure_variant_begin(const char *name, const char *variant) +{ + T_printf("M:B:%s\n", name); + T_printf("M:V:%s\n", variant); +} + +static T_time +accumulate(const T_ticks *samples, size_t sample_count) +{ + T_time a; + size_t i; + + a = 0; + + for (i = 0; i < sample_count; ++i) { + a += T_ticks_to_time(samples[i]); + } + + return a; +} + +static T_ticks +median_absolute_deviation(T_ticks *samples, size_t sample_count) +{ + T_ticks median; + size_t i; + + median = samples[sample_count / 2]; + + for (i = 0; i < sample_count / 2; ++i) { + samples[i] = median - samples[i]; + } + + for (; i < sample_count; ++i) { + samples[i] = samples[i] - median; + } + + qsort(samples, sample_count, sizeof(samples[0]), cmp); + return samples[sample_count / 2]; +} + +static void +report_sorted_samples(const T_measure_runtime_context *ctx) +{ + size_t sample_count; + const T_ticks *samples; + T_time_string ts; + T_ticks last; + T_ticks v; + size_t count; + size_t i; + + sample_count = ctx->sample_count; + samples = ctx->samples; + last = 0; + --last; + count = 0; + + for (i = 0; i < sample_count; ++i) { + v = samples[i]; + ++count; + + if (v != last) { + uint32_t sa; + uint32_t sb; + uint32_t nsa; + uint32_t nsb; + T_time t; + + T_time_to_seconds_and_nanoseconds(T_ticks_to_time(last), + &sa, &nsa); + t = T_ticks_to_time(v); + T_time_to_seconds_and_nanoseconds(t, &sb, &nsb); + + if (sa != sb || nsa != nsb) { + T_printf("M:S:%zu:%s\n", count, + T_time_to_string_ns(t, ts)); + count = 0; + } + + last = v; + } + } + + if (count > 0) { + T_printf("M:S:%zu:%s\n", count, + T_ticks_to_string_ns(last, ts)); + } +} + +static void +measure_variant_end(const T_measure_runtime_context *ctx, + const T_measure_runtime_request *req, T_time begin) +{ + size_t sample_count; + T_ticks *samples; + T_time_string ts; + T_time d; + T_ticks v; + T_time a; + + sample_count = ctx->sample_count; + samples = ctx->samples; + d = T_now() - begin; + a = accumulate(samples, sample_count); + qsort(samples, sample_count, sizeof(samples[0]), cmp); + T_printf("M:N:%zu\n", sample_count); + + if ((req->flags & T_MEASURE_RUNTIME_REPORT_SAMPLES) != 0) { + report_sorted_samples(ctx); + } + + v = samples[0]; + T_printf("M:MI:%s\n", T_ticks_to_string_ns(v, ts)); + v = samples[(1 * sample_count) / 100]; + T_printf("M:P1:%s\n", T_ticks_to_string_ns(v, ts)); + v = samples[(1 * sample_count) / 4]; + T_printf("M:Q1:%s\n", T_ticks_to_string_ns(v, ts)); + v = samples[sample_count / 2]; + T_printf("M:Q2:%s\n", T_ticks_to_string_ns(v, ts)); + v = samples[(3 * sample_count) / 4]; + T_printf("M:Q3:%s\n", T_ticks_to_string_ns(v, ts)); + v = samples[(99 * sample_count) / 100]; + T_printf("M:P99:%s\n", T_ticks_to_string_ns(v, ts)); + v = samples[sample_count - 1]; + T_printf("M:MX:%s\n", T_ticks_to_string_ns(v, ts)); + v = median_absolute_deviation(samples, sample_count); + T_printf("M:MAD:%s\n", T_ticks_to_string_ns(v, ts)); + T_printf("M:D:%s\n", T_time_to_string_ns(a, ts)); + T_printf("M:E:%s:D:%s\n", req->name, T_time_to_string_ns(d, ts)); +} + +static void +fill_data_cache(volatile unsigned int *chunk, size_t chunk_size, + size_t cache_line_size) +{ + size_t m; + size_t k; + size_t i; + + m = chunk_size / sizeof(chunk[0]); + k = cache_line_size / sizeof(chunk[0]); + + for (i = 0; i < m; i += k) { + chunk[i]; + } +} + +static void +dirty_call(void (*body)(void *), void *arg) +{ + void *space; + + /* Ensure that we use an untouched stack area */ + space = alloca(1024); + RTEMS_OBFUSCATE_VARIABLE(space); + + (*body)(arg); +} + +static void +setup(const T_measure_runtime_request *req, void *arg) +{ + if (req->setup != NULL) { + (*req->setup)(arg); + } +} + +static bool +teardown(const T_measure_runtime_request *req, void *arg, T_ticks *delta, + uint32_t tic, uint32_t toc, unsigned int retry, + unsigned int maximum_retries) +{ + if (req->teardown == NULL) { + return tic == toc || retry >= maximum_retries; + } + + return (*req->teardown)(arg, delta, tic, toc, retry); +} + +static unsigned int +get_maximum_retries(const T_measure_runtime_request *req) +{ + return (req->flags & T_MEASURE_RUNTIME_ALLOW_CLOCK_ISR) != 0 ? 1 : 0; +} + +static void +measure_valid_cache(T_measure_runtime_context *ctx, + const T_measure_runtime_request *req) +{ + size_t sample_count; + T_ticks *samples; + void (*body)(void *); + void *arg; + size_t i; + T_time begin; + + measure_variant_begin(req->name, "ValidCache"); + begin = T_now(); + sample_count = ctx->sample_count; + samples = ctx->samples; + body = req->body; + arg = req->arg; + + for (i = 0; i < sample_count; ++i) { + unsigned int maximum_retries; + unsigned int retry; + + maximum_retries = get_maximum_retries(req); + retry = 0; + + while (true) { + rtems_interval tic; + rtems_interval toc; + T_ticks t0; + T_ticks t1; + + setup(req, arg); + fill_data_cache(ctx->chunk, ctx->chunk_size, + ctx->cache_line_size); + + tic = rtems_clock_get_ticks_since_boot(); + t0 = T_tick(); + (*body)(arg); + t1 = T_tick(); + toc = rtems_clock_get_ticks_since_boot(); + samples[i] = t1 - t0; + + if (teardown(req, arg, &samples[i], tic, toc, retry, + maximum_retries)) { + break; + } + + ++retry; + } + } + + measure_variant_end(ctx, req, begin); +} + +static void +measure_hot_cache(T_measure_runtime_context *ctx, + const T_measure_runtime_request *req) +{ + size_t sample_count; + T_ticks *samples; + void (*body)(void *); + void *arg; + size_t i; + T_time begin; + + measure_variant_begin(req->name, "HotCache"); + begin = T_now(); + sample_count = ctx->sample_count; + samples = ctx->samples; + body = req->body; + arg = req->arg; + + for (i = 0; i < sample_count; ++i) { + unsigned int maximum_retries; + unsigned int retry; + + maximum_retries = get_maximum_retries(req); + retry = 0; + + while (true) { + rtems_interval tic; + rtems_interval toc; + T_ticks t0; + T_ticks t1; + + setup(req, arg); + + tic = rtems_clock_get_ticks_since_boot(); + t0 = T_tick(); + (*body)(arg); + t1 = T_tick(); + toc = rtems_clock_get_ticks_since_boot(); + samples[i] = t1 - t0; + + (void)teardown(req, arg, &samples[i], tic, toc, retry, + 0); + setup(req, arg); + + tic = rtems_clock_get_ticks_since_boot(); + t0 = T_tick(); + (*body)(arg); + t1 = T_tick(); + toc = rtems_clock_get_ticks_since_boot(); + samples[i] = t1 - t0; + + if (teardown(req, arg, &samples[i], tic, toc, retry, + maximum_retries)) { + break; + } + + ++retry; + } + } + + measure_variant_end(ctx, req, begin); +} + +static void +measure_dirty_cache(T_measure_runtime_context *ctx, + const T_measure_runtime_request *req) +{ + size_t sample_count; + T_ticks *samples; + void (*body)(void *); + void *arg; + size_t i; + T_time begin; + size_t token; + + measure_variant_begin(req->name, "DirtyCache"); + begin = T_now(); + sample_count = ctx->sample_count; + samples = ctx->samples; + body = req->body; + arg = req->arg; + token = 0; + + for (i = 0; i < sample_count; ++i) { + unsigned int maximum_retries; + unsigned int retry; + + maximum_retries = get_maximum_retries(req); + retry = 0; + + while (true) { + rtems_interval tic; + rtems_interval toc; + T_ticks t0; + T_ticks t1; + + setup(req, arg); + token = dirty_data_cache(ctx->chunk, ctx->chunk_size, + ctx->cache_line_size, token); + rtems_cache_invalidate_entire_instruction(); + + tic = rtems_clock_get_ticks_since_boot(); + t0 = T_tick(); + dirty_call(body, arg); + t1 = T_tick(); + toc = rtems_clock_get_ticks_since_boot(); + samples[i] = t1 - t0; + + if (teardown(req, arg, &samples[i], tic, toc, retry, + maximum_retries)) { + break; + } + + ++retry; + } + } + + measure_variant_end(ctx, req, begin); +} + +#ifdef __sparc__ +/* + * Use recursive function calls to wake sure that we cause window overflow + * traps in the body. Try to make it hard for the compiler to optimize the + * recursive function away. + */ +static T_ticks +recursive_load_call(void (*body)(void *), void *arg, int n) +{ + T_ticks delta; + + RTEMS_OBFUSCATE_VARIABLE(n); + + if (n > 0) { + delta = recursive_load_call(body, arg, n - 1); + } else { + T_ticks t0; + T_ticks t1; + + t0 = T_tick(); + dirty_call(body, arg); + t1 = T_tick(); + + delta = t1 - t0; + } + + RTEMS_OBFUSCATE_VARIABLE(delta); + return delta; +} +#else +static T_ticks +load_call(void (*body)(void *), void *arg) +{ + T_ticks t0; + T_ticks t1; + + t0 = T_tick(); + dirty_call(body, arg); + t1 = T_tick(); + + return t1 - t0; +} +#endif + +static void +measure_load_variant(T_measure_runtime_context *ctx, + const T_measure_runtime_request *req, + const load_context *lctx, uint32_t load) +{ + size_t sample_count; + T_ticks *samples; + void (*body)(void *); + void *arg; + size_t i; + T_time begin; + size_t token; + + measure_variant_begin(req->name, "Load"); + T_printf("M:L:%" PRIu32 "\n", load + 1); + begin = T_now(); + sample_count = ctx->sample_count; + samples = ctx->samples; + body = req->body; + arg = req->arg; + token = 0; + + restart_worker(lctx); + + for (i = 0; i < sample_count; ++i) { + unsigned int maximum_retries; + unsigned int retry; + + maximum_retries = get_maximum_retries(req); + retry = 0; + + while (true) { + rtems_interval tic; + rtems_interval toc; + T_ticks delta; + + setup(req, arg); + token = dirty_data_cache(ctx->chunk, ctx->chunk_size, + ctx->cache_line_size, token); + rtems_cache_invalidate_entire_instruction(); + + tic = rtems_clock_get_ticks_since_boot(); +#ifdef __sparc__ + delta = recursive_load_call(body, arg, + SPARC_NUMBER_OF_REGISTER_WINDOWS - 3); +#else + delta = load_call(body, arg); +#endif + toc = rtems_clock_get_ticks_since_boot(); + samples[i] = delta; + + if (teardown(req, arg, &samples[i], tic, toc, retry, + maximum_retries)) { + break; + } + + ++retry; + } + } + + measure_variant_end(ctx, req, begin); +} + +static void +measure_load(T_measure_runtime_context *ctx, + const T_measure_runtime_request *req) +{ + const load_context *lctx; + uint32_t load; + +#ifdef RTEMS_SMP + for (load = 0; load < ctx->load_count - 1; ++load) { + lctx = &ctx->load_contexts[load]; + + if (lctx->id != 0) { + if ((req->flags & + T_MEASURE_RUNTIME_DISABLE_MINOR_LOAD) == 0) { + measure_load_variant(ctx, req, lctx, load); + } else { + restart_worker(lctx); + } + } + } +#endif + + if ((req->flags & T_MEASURE_RUNTIME_DISABLE_MAX_LOAD) == 0) { + load = ctx->load_count - 1; + lctx = &ctx->load_contexts[load]; + + if (lctx->id != 0) { + measure_load_variant(ctx, req, lctx, load); + } + } + + for (load = 0; load < ctx->load_count; ++load) { + lctx = &ctx->load_contexts[load]; + + if (lctx->id != 0) { + suspend_worker(lctx); + } + } +} + +void +T_measure_runtime(T_measure_runtime_context *ctx, + const T_measure_runtime_request *req) +{ + /* + * Do ValidCache variant before HotCache to get a good overall cache + * state for the HotCache variant. + */ + if ((req->flags & T_MEASURE_RUNTIME_DISABLE_VALID_CACHE) == 0) { + measure_valid_cache(ctx, req); + } + + if ((req->flags & T_MEASURE_RUNTIME_DISABLE_HOT_CACHE) == 0) { + measure_hot_cache(ctx, req); + } + + if ((req->flags & T_MEASURE_RUNTIME_DISABLE_DIRTY_CACHE) == 0) { + measure_dirty_cache(ctx, req); + } + + measure_load(ctx, req); +} diff --git a/cpukit/libtest/t-test-rtems-objs.c b/cpukit/libtest/t-test-rtems-objs.c new file mode 100644 index 0000000000..dd4f2d59d2 --- /dev/null +++ b/cpukit/libtest/t-test-rtems-objs.c @@ -0,0 +1,447 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (C) 2018 embedded brains GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#undef __STRICT_ANSI__ + +#include + +#include + +#include +#include +#include + +static Objects_Maximum +T_objects_count(Objects_APIs api, uint16_t cls) +{ + const Objects_Information *information; + Objects_Maximum count; + + information = _Objects_Get_information(api, cls); + + _RTEMS_Lock_allocator(); + + if (information != NULL) { + count = _Objects_Active_count(information); + } else { + count = 0; + } + + _RTEMS_Unlock_allocator(); + + return count; +} + +static void +T_objects_check(Objects_APIs api, uint16_t cls, + Objects_Maximum *expected, const char *name) +{ + Objects_Maximum count; + int32_t delta; + + count = T_objects_count(api, cls); + delta = (int32_t)count - (int32_t)*expected; + + if (delta != 0) { + *expected = count; + T_check_true(NULL, false, "%s leak (%" PRIi32 ")", name, delta); + } +} + +static Objects_Maximum T_barrier_count; + +static void +T_rtems_barriers_run_initialize(void) +{ + T_barrier_count = T_objects_count(OBJECTS_CLASSIC_API, + OBJECTS_RTEMS_BARRIERS); +} + +static void +T_rtems_barriers_case_end(void) +{ + T_objects_check(OBJECTS_CLASSIC_API, OBJECTS_RTEMS_BARRIERS, + &T_barrier_count, "RTEMS barrier"); +} + +void +T_check_rtems_barriers(T_event event, const char *name) +{ + (void)name; + + switch (event) { + case T_EVENT_RUN_INITIALIZE: + T_rtems_barriers_run_initialize(); + break; + case T_EVENT_CASE_END: + T_rtems_barriers_case_end(); + break; + default: + break; + }; +} + +static Objects_Maximum T_extension_count; + +static void +T_rtems_extensions_run_initialize(void) +{ + T_extension_count = T_objects_count(OBJECTS_CLASSIC_API, + OBJECTS_RTEMS_EXTENSIONS); +} + +static void +T_rtems_extensions_case_end(void) +{ + T_objects_check(OBJECTS_CLASSIC_API, OBJECTS_RTEMS_EXTENSIONS, + &T_extension_count, "RTEMS extension"); +} + +void +T_check_rtems_extensions(T_event event, const char *name) +{ + (void)name; + + switch (event) { + case T_EVENT_RUN_INITIALIZE: + T_rtems_extensions_run_initialize(); + break; + case T_EVENT_CASE_END: + T_rtems_extensions_case_end(); + break; + default: + break; + }; +} + +static Objects_Maximum T_mq_count; + +static void +T_rtems_message_queues_run_initialize(void) +{ + T_mq_count = T_objects_count(OBJECTS_CLASSIC_API, + OBJECTS_RTEMS_MESSAGE_QUEUES); +} + +static void +T_rtems_message_queues_case_end(void) +{ + T_objects_check(OBJECTS_CLASSIC_API, OBJECTS_RTEMS_MESSAGE_QUEUES, + &T_mq_count, "RTEMS message queue"); +} + +void +T_check_rtems_message_queues(T_event event, const char *name) +{ + (void)name; + + switch (event) { + case T_EVENT_RUN_INITIALIZE: + T_rtems_message_queues_run_initialize(); + break; + case T_EVENT_CASE_END: + T_rtems_message_queues_case_end(); + break; + default: + break; + }; +} + +static Objects_Maximum T_part_count; + +static void +T_rtems_partitions_run_initialize(void) +{ + T_part_count = T_objects_count(OBJECTS_CLASSIC_API, + OBJECTS_RTEMS_PARTITIONS); +} + +static void +T_rtems_partitions_case_end(void) +{ + T_objects_check(OBJECTS_CLASSIC_API, OBJECTS_RTEMS_PARTITIONS, + &T_part_count, "RTEMS partition"); +} + +void +T_check_rtems_partitions(T_event event, const char *name) +{ + (void)name; + + switch (event) { + case T_EVENT_RUN_INITIALIZE: + T_rtems_partitions_run_initialize(); + break; + case T_EVENT_CASE_END: + T_rtems_partitions_case_end(); + break; + default: + break; + }; +} + +static Objects_Maximum T_period_count; + +static void +T_rtems_periods_run_initialize(void) +{ + T_period_count = T_objects_count(OBJECTS_CLASSIC_API, + OBJECTS_RTEMS_PERIODS); +} + +static void +T_rtems_periods_case_end(void) +{ + T_objects_check(OBJECTS_CLASSIC_API, OBJECTS_RTEMS_PERIODS, + &T_period_count, "RTEMS period"); +} + +void +T_check_rtems_periods(T_event event, const char *name) +{ + (void)name; + + switch (event) { + case T_EVENT_RUN_INITIALIZE: + T_rtems_periods_run_initialize(); + break; + case T_EVENT_CASE_END: + T_rtems_periods_case_end(); + break; + default: + break; + }; +} + +static Objects_Maximum T_region_count; + +static void +T_rtems_regions_run_initialize(void) +{ + T_region_count = T_objects_count(OBJECTS_CLASSIC_API, + OBJECTS_RTEMS_REGIONS); +} + +static void +T_rtems_regions_case_end(void) +{ + T_objects_check(OBJECTS_CLASSIC_API, OBJECTS_RTEMS_REGIONS, + &T_region_count, "RTEMS region"); +} + +void +T_check_rtems_regions(T_event event, const char *name) +{ + (void)name; + + switch (event) { + case T_EVENT_RUN_INITIALIZE: + T_rtems_regions_run_initialize(); + break; + case T_EVENT_CASE_END: + T_rtems_regions_case_end(); + break; + default: + break; + }; +} + +static Objects_Maximum T_sema_count; + +static void +T_rtems_semaphores_run_initialize(void) +{ + T_sema_count = T_objects_count(OBJECTS_CLASSIC_API, + OBJECTS_RTEMS_SEMAPHORES); +} + +static void +T_rtems_semaphores_case_end(void) +{ + T_objects_check(OBJECTS_CLASSIC_API, OBJECTS_RTEMS_SEMAPHORES, + &T_sema_count, "RTEMS semaphore"); +} + +void +T_check_rtems_semaphores(T_event event, const char *name) +{ + (void)name; + + switch (event) { + case T_EVENT_RUN_INITIALIZE: + T_rtems_semaphores_run_initialize(); + break; + case T_EVENT_CASE_END: + T_rtems_semaphores_case_end(); + break; + default: + break; + }; +} + +static Objects_Maximum T_task_count; + +static void +T_rtems_tasks_run_initialize(void) +{ + T_task_count = T_objects_count(OBJECTS_CLASSIC_API, + OBJECTS_RTEMS_TASKS); +} + +static void +T_rtems_tasks_case_end(void) +{ + _RTEMS_Lock_allocator(); + _Thread_Kill_zombies(); + _RTEMS_Unlock_allocator(); + + T_objects_check(OBJECTS_CLASSIC_API, OBJECTS_RTEMS_TASKS, + &T_task_count, "RTEMS task"); +} + +void +T_check_rtems_tasks(T_event event, const char *name) +{ + (void)name; + + switch (event) { + case T_EVENT_RUN_INITIALIZE: + T_rtems_tasks_run_initialize(); + break; + case T_EVENT_CASE_END: + T_rtems_tasks_case_end(); + break; + default: + break; + }; +} + +static Objects_Maximum T_timer_count; + +static void +T_rtems_timers_run_initialize(void) +{ + T_timer_count = T_objects_count(OBJECTS_CLASSIC_API, + OBJECTS_RTEMS_TIMERS); +} + +static void +T_rtems_timers_case_end(void) +{ + T_objects_check(OBJECTS_CLASSIC_API, OBJECTS_RTEMS_TIMERS, + &T_timer_count, "RTEMS timer"); +} + +void +T_check_rtems_timers(T_event event, const char *name) +{ + (void)name; + + switch (event) { + case T_EVENT_RUN_INITIALIZE: + T_rtems_timers_run_initialize(); + break; + case T_EVENT_CASE_END: + T_rtems_timers_case_end(); + break; + default: + break; + }; +} + +static Objects_Maximum T_posix_key_count; + +static ssize_t T_posix_key_value_count; + +static POSIX_Keys_Control * +T_get_next_posix_key(Objects_Id *id) +{ + return (POSIX_Keys_Control *) + _Objects_Get_next(*id, &_POSIX_Keys_Information, id); +} + +static ssize_t +T_get_active_posix_key_value_pairs(void) +{ + ssize_t count; + Objects_Id id; + POSIX_Keys_Control *the_key; + + count = 0; + id = OBJECTS_ID_INITIAL_INDEX; + + while ((the_key = T_get_next_posix_key(&id)) != NULL ) { + count += (ssize_t) + _Chain_Node_count_unprotected(&the_key->Key_value_pairs); + _Objects_Allocator_unlock(); + } + + return count; +} + +static void +T_posix_keys_run_initialize(void) +{ + T_posix_key_count = T_objects_count(OBJECTS_POSIX_API, + OBJECTS_POSIX_KEYS); + T_posix_key_value_count = T_get_active_posix_key_value_pairs(); +} + +static void +T_posix_keys_case_end(void) +{ + ssize_t count; + ssize_t delta; + + T_objects_check(OBJECTS_POSIX_API, OBJECTS_POSIX_KEYS, + &T_posix_key_count, "POSIX key"); + + count = T_get_active_posix_key_value_pairs(); + delta = count - T_posix_key_value_count; + + if (delta != 0) { + T_posix_key_value_count = count; + T_check_true(NULL, false, "POSIX key value pair leak (%zi)", delta); + } +} + +void +T_check_posix_keys(T_event event, const char *name) +{ + (void)name; + + switch (event) { + case T_EVENT_RUN_INITIALIZE: + T_posix_keys_run_initialize(); + break; + case T_EVENT_CASE_END: + T_posix_keys_case_end(); + break; + default: + break; + }; +} diff --git a/cpukit/libtest/t-test-rtems.c b/cpukit/libtest/t-test-rtems.c new file mode 100644 index 0000000000..7f53005862 --- /dev/null +++ b/cpukit/libtest/t-test-rtems.c @@ -0,0 +1,51 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (C) 2018 embedded brains GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +#include + +void +T_putchar_default(int c, void *arg) +{ + (void)arg; + rtems_putc((char)c); +} + +void +T_check_rsc(uint32_t a, const T_check_context *t, uint32_t e) +{ + T_check_true(a == e, t, "%s == %s", rtems_status_text(a), + rtems_status_text(e)); +} + +void +T_check_rsc_success(uint32_t a, const T_check_context *t) +{ + T_check_rsc(a, t, RTEMS_SUCCESSFUL); +} diff --git a/cpukit/libtest/t-test-time.c b/cpukit/libtest/t-test-time.c new file mode 100644 index 0000000000..02d729f580 --- /dev/null +++ b/cpukit/libtest/t-test-time.c @@ -0,0 +1,233 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (C) 2018 embedded brains GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#undef __STRICT_ANSI__ + +#include + +#include +#include +#include +#include + +#ifdef __rtems__ +#include +#include +#endif + +#ifdef __rtems__ +static T_time +round_sbt(T_time time) +{ + /* + * One 1ns consists of 4.30 fractions of 1/2**32. Round up close to + * the middle. This turns the conversion mapping of struct timespec to + * sbintime_t and back into the identity function. + */ + return time + 2; +} +#endif + +const char * +T_time_to_string_ns(T_time time, T_time_string string) +{ + uint32_t s; + uint32_t f; + +#ifdef __rtems__ + time = round_sbt(time); + s = (uint32_t)(time >> 32); + f = (uint32_t)(((uint64_t)1000000000 * (uint32_t)time) >> 32); +#else + s = (uint32_t)(time / 1000000000); + f = (uint32_t)(time % 1000000000); +#endif + + (void)T_snprintf(string, sizeof(T_time_string), + "%" PRIu32 ".%09" PRIu32, s, f); + return string; +} + +const char * +T_time_to_string_us(T_time time, T_time_string string) +{ + uint32_t s; + uint32_t f; + +#ifdef __rtems__ + time = round_sbt(time); + s = (uint32_t)(time >> 32); + f = (uint32_t)(((uint64_t)1000000 * (uint32_t)time) >> 32); +#else + time /= 1000; + s = (uint32_t)(time / 1000000); + f = (uint32_t)(time % 1000000); +#endif + + (void)T_snprintf(string, sizeof(T_time_string), + "%" PRIu32 ".%06" PRIu32, s, f); + return string; +} + +const char * +T_time_to_string_ms(T_time time, T_time_string string) +{ + uint32_t s; + uint32_t f; + +#ifdef __rtems__ + time = round_sbt(time); + s = (uint32_t)(time >> 32); + f = (uint32_t)(((uint64_t)1000 * (uint32_t)time) >> 32); +#else + time /= 1000000; + s = (uint32_t)(time / 1000); + f = (uint32_t)(time % 1000); +#endif + + (void)T_snprintf(string, sizeof(T_time_string), + "%" PRIu32 ".%03" PRIu32, s, f); + return string; +} + +const char * +T_time_to_string_s(T_time time, T_time_string string) +{ + uint32_t s; + +#ifdef __rtems__ + time = round_sbt(time); + s = (uint32_t)(time >> 32); +#else + s = (uint32_t)(time / 1000000000); +#endif + + (void)T_snprintf(string, sizeof(T_time_string), "%" PRIu32, s); + return string; +} + +const char * +T_ticks_to_string_ns(T_ticks ticks, T_time_string string) +{ + return T_time_to_string_ns(T_ticks_to_time(ticks), string); +} + +const char * +T_ticks_to_string_us(T_ticks ticks, T_time_string string) +{ + return T_time_to_string_us(T_ticks_to_time(ticks), string); +} + +const char * +T_ticks_to_string_ms(T_ticks ticks, T_time_string string) +{ + return T_time_to_string_ms(T_ticks_to_time(ticks), string); +} + +const char * +T_ticks_to_string_s(T_ticks ticks, T_time_string string) +{ + return T_time_to_string_s(T_ticks_to_time(ticks), string); +} + +uint64_t +T_ticks_to_time(T_ticks ticks) +{ +#ifdef __rtems__ + return (uint64_t)rtems_counter_ticks_to_sbintime(ticks); +#else + return ticks; +#endif +} + +T_ticks +T_time_to_ticks(T_time time) +{ +#ifdef __rtems__ + return rtems_counter_sbintime_to_ticks((sbintime_t)time); +#else + return time; +#endif +} + +T_time +T_seconds_and_nanoseconds_to_time(uint32_t s, uint32_t ns) +{ +#ifdef __rtems__ + struct timespec ts; + + ts.tv_sec = s; + ts.tv_nsec = (long)ns; + return (T_time)tstosbt(ts); +#else + return (T_time)s * (T_time)1000000000 + (T_time)ns; +#endif +} + +void +T_time_to_seconds_and_nanoseconds(T_time time, uint32_t *s, uint32_t *ns) +{ +#ifdef __rtems__ + time = round_sbt(time); + *s = (uint32_t)(time >> 32); + *ns = (uint32_t)(((uint64_t)1000000000 * (uint32_t)time) >> 32); +#else + *s = (uint32_t)(time / 1000000000); + *ns = (uint32_t)(time % 1000000000); +#endif +} + +#ifndef __rtems__ +T_time +T_now(void) +{ + struct timespec tp; + + (void)clock_gettime(CLOCK_MONOTONIC, &tp); + return (T_time)tp.tv_sec * (T_time)1000000000 + (T_time)tp.tv_nsec; +} + +T_ticks +T_tick(void) +{ + return T_now(); +} +#endif + +static atomic_uint dummy_time; + +T_time +T_now_dummy(void) +{ + return atomic_fetch_add_explicit(&dummy_time, 1, memory_order_relaxed); +} + +T_time +T_now_via_tick(void) +{ + return T_ticks_to_time(T_tick()); +} diff --git a/cpukit/libtest/t-test.c b/cpukit/libtest/t-test.c new file mode 100644 index 0000000000..cf3bcd6a99 --- /dev/null +++ b/cpukit/libtest/t-test.c @@ -0,0 +1,888 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (C) 2018, 2019 embedded brains GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define _GNU_SOURCE + +#include + +#include +#include +#include +#include +#include +#include + +#ifdef __rtems__ +#include +#include +#include +#include +#include +#include +#else +#include "t-test-printf.h" +#endif /* __rtems__ */ + +#define T_LINE_SIZE 120 + +#define T_SCOPE_SIZE 5 + +typedef struct { + pthread_spinlock_t lock; + void (*putchar)(int, void *); + void *putchar_arg; + T_verbosity verbosity; + const T_case_context *registered_cases; + const T_case_context *current_case; + void *fixture_context; + LIST_HEAD(, T_destructor) destructors; + T_time case_begin_time; + atomic_uint planned_steps; + atomic_uint steps; + atomic_uint failures; + jmp_buf case_begin_context; + unsigned int overall_cases; + unsigned int overall_steps; + unsigned int overall_failures; + T_time run_begin_time; +#ifdef __rtems__ + Thread_Control *runner_thread; + const Per_CPU_Control *runner_cpu; +#else + bool runner_valid; + pthread_t runner_thread; +#endif + const T_config *config; +} T_context; + +static T_context T_instance; + +static int +T_do_vprintf(T_context *ctx, char const *fmt, va_list ap) +{ + return _IO_Vprintf(ctx->putchar, ctx->putchar_arg, fmt, ap); +} + +int +T_vprintf(char const *fmt, va_list ap) +{ + return T_do_vprintf(&T_instance, fmt, ap); +} + +typedef struct { + char *s; + size_t n; +} T_putchar_string_context; + +static void +T_putchar_string(int c, void *arg) +{ + T_putchar_string_context *ctx; + char *s; + size_t n; + + ctx = arg; + s = ctx->s; + n = ctx->n; + + if (n == 1) { + c = '\0'; + } + + if (n > 1) { + *s = (char)c; + ++s; + --n; + } + + ctx->s = s; + ctx->n = n; +} + +int +T_snprintf(char *s, size_t n, char const *fmt, ...) +{ + va_list ap; + int len; + T_putchar_string_context ctx = { + .s = s, + .n = n + }; + + va_start(ap, fmt); + len = _IO_Vprintf(T_putchar_string, &ctx, fmt, ap); + va_end(ap); + + if (ctx.n > 0) { + *ctx.s = '\0'; + } + + return len; +} + +static int +T_cpu(void) +{ +#if defined(__rtems__) + return (int)_SMP_Get_current_processor(); +#elif defined(__linux__) + return sched_getcpu(); +#else + return 0; +#endif +} + +#if defined(__rtems__) +static const char * +T_object_name_to_string(Objects_Name name, char *buf) +{ + uint32_t on; + size_t i; + int s; + + on = name.name_u32; + i = 0; + + for (s = 24; s >= 0; s -= 8) { + unsigned char c; + + c = (unsigned char)(on >> s); + + if (c >= '!' && c <= '~') { + buf[i] = (char)c; + ++i; + } + } + + buf[i] = '\0'; + return buf; +} + +static const char * +T_thread_name(const Thread_Control *th, char *buf) +{ + if (th != NULL) { + const char *name; + + name = th->Join_queue.Queue.name; + + if (name != NULL && name[0] != '\0') { + return name; + } else { + return T_object_name_to_string(th->Object.name, buf); + } + } else { + buf[0] = '?'; + buf[1] = '\0'; + return buf; + } +} +#endif + +static const char * +T_scope(char *buf) +{ + const char *r; + +#if defined(__rtems__) + ISR_Level level; + const Per_CPU_Control *cpu_self; + + _ISR_Local_disable(level); + cpu_self = _Per_CPU_Get(); + + if (cpu_self->isr_nest_level == 0) { + Thread_Control *executing; + + executing = _Per_CPU_Get_executing(cpu_self); + _ISR_Local_enable(level); + r = T_thread_name(executing, buf); + } else { + _ISR_Local_enable(level); + buf[0] = 'I'; + buf[1] = 'S'; + buf[2] = 'R'; + buf[3] = '\0'; + r = buf; + } +#elif defined(__linux__) + static __thread char name[128]; + + (void)buf; + + if (name[0] == '\0') { + pthread_getname_np(pthread_self(), name, sizeof(name)); + } + + r = &name[0]; +#else + buf[0] = '?'; + buf[1] = '\0'; + r = buf; +#endif + + return r; +} + +static void +T_set_runner(T_context *ctx) +{ +#ifdef __rtems__ + ISR_Level level; + const Per_CPU_Control *cpu_self; + + _ISR_Local_disable(level); + cpu_self = _Per_CPU_Get(); + ctx->runner_cpu = cpu_self; + + if (cpu_self->isr_nest_level == 0) { + ctx->runner_thread = _Per_CPU_Get_executing(cpu_self); + } else { + ctx->runner_thread = NULL; + } + + _ISR_Local_enable(level); +#else + ctx->runner_valid = true; + ctx->runner_thread = pthread_self(); +#endif +} + +int +T_printf(char const *fmt, ...) +{ + va_list ap; + int len; + + va_start(ap, fmt); + len = T_vprintf(fmt, ap); + va_end(ap); + + return len; +} + +void +T_log(T_verbosity verbosity, char const *fmt, ...) +{ + T_context *ctx; + + ctx = &T_instance; + + if (ctx->verbosity >= verbosity) { + va_list ap; + + T_printf("L:"); + va_start(ap, fmt); + T_vprintf(fmt, ap); + va_end(ap); + T_printf("\n"); + } +} + +static unsigned int +T_fetch_add_step(T_context *ctx) +{ + return atomic_fetch_add_explicit(&ctx->steps, 1, memory_order_relaxed); +} + +static unsigned int +T_add_failure(T_context *ctx) +{ + return atomic_fetch_add_explicit(&ctx->failures, 1, + memory_order_relaxed); +} + +static void +T_stop(T_context *ctx) +{ + const T_case_context *tc; + + tc = ctx->current_case; + + if (tc != NULL) { + const T_fixture *fixture; + + fixture = tc->fixture; + + if (fixture != NULL && fixture->stop != NULL) { + (*fixture->stop)(ctx->fixture_context); + } + } + + longjmp(ctx->case_begin_context, 1); +} + +void T_plan(unsigned int planned_steps) +{ + T_context *ctx; + unsigned int expected; + bool success; + + ctx = &T_instance; + expected = UINT_MAX; + success = atomic_compare_exchange_strong_explicit(&ctx->planned_steps, + &expected, planned_steps, memory_order_relaxed, + memory_order_relaxed); + T_check_true(success, NULL, "planned steps (%u) already set", expected); +} + +void +T_case_register(T_case_context *tc) +{ + T_context *ctx; + + ctx = &T_instance; + tc->next = ctx->registered_cases; + ctx->registered_cases = tc; +} + +T_verbosity +T_set_verbosity(T_verbosity verbosity) +{ + T_context *ctx; + T_verbosity previous; + + ctx = &T_instance; + previous = ctx->verbosity; + ctx->verbosity = verbosity; + + return previous; +} + +void * +T_fixture_context(void) +{ + return T_instance.fixture_context; +} + +void +T_set_fixture_context(void *context) +{ + T_instance.fixture_context = context; +} + +const char * +T_case_name(void) +{ + const T_case_context *tc; + + tc = T_instance.current_case; + + if (tc != NULL) { + return tc->name; + } else { + return "?"; + } +} + +void +T_check_true(bool ok, const T_check_context *t, const char *fmt, ...) +{ + T_context *ctx; + va_list ap; + char scope[T_SCOPE_SIZE]; + + ctx = &T_instance; + + if (t != NULL) { + unsigned int step; + + if ((t->flags & T_CHECK_QUIET) == 0) { + step = T_fetch_add_step(ctx); + } else { + step = UINT_MAX; + } + + if ((t->flags & T_CHECK_STEP_FLAG) != 0 && + step != T_CHECK_STEP_FROM_FLAGS(t->flags)) { + T_add_failure(ctx); + T_printf("F:%u:%i:%s:%s:%i:planned step (%u)\n", step, + T_cpu(), T_scope(scope), t->file, t->line, + T_CHECK_STEP_FROM_FLAGS(t->flags)); + } else if (!ok) { + T_add_failure(ctx); + + if (ctx->verbosity >= T_NORMAL) { + if ((t->flags & T_CHECK_QUIET) == 0) { + T_printf("F:%u:%i:%s:%s:%i:", + step, T_cpu(), T_scope(scope), + t->file, t->line); + } else { + T_printf("F:*:%i:%s:%s:%i:", T_cpu(), + T_scope(scope), t->file, t->line); + } + + va_start(ap, fmt); + T_vprintf(fmt, ap); + va_end(ap); + + T_printf("\n"); + } + + if ((t->flags & T_CHECK_STOP) != 0) { + T_stop(ctx); + } + } else if ((t->flags & T_CHECK_QUIET) == 0 && + ctx->verbosity >= T_VERBOSE) { + T_printf("P:%u:%i:%s:%s:%i\n", step, T_cpu(), + T_scope(scope), t->file, t->line); + } + } else if (!ok) { + T_add_failure(ctx); + + T_printf("F:*:%i:%s:*:*:", T_cpu(), T_scope(scope)); + + va_start(ap, fmt); + T_vprintf(fmt, ap); + va_end(ap); + + T_printf("\n"); + } +} + +static void +T_do_log(T_context *ctx, T_verbosity verbosity, char const *fmt, ...) +{ + if (ctx->verbosity >= verbosity) { + va_list ap; + + va_start(ap, fmt); + T_vprintf(fmt, ap); + va_end(ap); + } +} + +static void +T_system(T_context *ctx) +{ +#if defined(__rtems__) + T_do_log(ctx, T_QUIET, "S:Platform:RTEMS\n"); + T_do_log(ctx, T_QUIET, "S:Compiler:" __VERSION__ "\n"); + T_do_log(ctx, T_QUIET, "S:Version:%s\n", rtems_version()); + T_do_log(ctx, T_QUIET, "S:BSP:%s\n", rtems_board_support_package()); +#if RTEMS_DEBUG + T_do_log(ctx, T_QUIET, "S:RTEMS_DEBUG:1\n"); +#else + T_do_log(ctx, T_QUIET, "S:RTEMS_DEBUG:0\n"); +#endif +#if RTEMS_MULTIPROCESSING + T_do_log(ctx, T_QUIET, "S:RTEMS_MULTIPROCESSING:1\n"); +#else + T_do_log(ctx, T_QUIET, "S:RTEMS_MULTIPROCESSING:0\n"); +#endif +#if RTEMS_POSIX_API + T_do_log(ctx, T_QUIET, "S:RTEMS_POSIX_API:1\n"); +#else + T_do_log(ctx, T_QUIET, "S:RTEMS_POSIX_API:0\n"); +#endif +#if RTEMS_PROFILING + T_do_log(ctx, T_QUIET, "S:RTEMS_PROFILING:1\n"); +#else + T_do_log(ctx, T_QUIET, "S:RTEMS_PROFILING:0\n"); +#endif +#if RTEMS_SMP + T_do_log(ctx, T_QUIET, "S:RTEMS_SMP:1\n"); +#else + T_do_log(ctx, T_QUIET, "S:RTEMS_SMP:0\n"); +#endif +#elif defined(__linux__) + T_do_log(ctx, T_QUIET, "S:Platform:Linux\n"); + T_do_log(ctx, T_QUIET, "S:Compiler:" __VERSION__ "\n"); +#else + T_do_log(ctx, T_QUIET, "S:Platform:POSIX\n"); +#ifdef __VERSION__ + T_do_log(ctx, T_QUIET, "S:Compiler:" __VERSION__ "\n"); +#endif +#endif +} + +void +T_add_destructor(T_destructor *dtor, void (*destroy)(T_destructor *)) +{ + T_context *ctx; + + dtor->destroy = destroy; + ctx = &T_instance; + pthread_spin_lock(&ctx->lock); + LIST_INSERT_HEAD(&ctx->destructors, dtor, node); + pthread_spin_unlock(&ctx->lock); +} + +void +T_remove_destructor(T_destructor *dtor) +{ + T_context *ctx; + + ctx = &T_instance; + pthread_spin_lock(&ctx->lock); + LIST_REMOVE(dtor, node); + pthread_spin_unlock(&ctx->lock); +} + +static void +T_call_destructors(const T_context *ctx) +{ + T_destructor *dtor; + +#ifdef __linux__ + while (!LIST_EMPTY(&ctx->destructors)) { + dtor = LIST_FIRST(&ctx->destructors); + LIST_REMOVE(dtor, node); + (*dtor->destroy)(dtor); + } +#else + T_destructor *tmp; + + LIST_FOREACH_SAFE(dtor, &ctx->destructors, node, tmp) { + (*dtor->destroy)(dtor); + } +#endif +} + +static void +T_call_actions_forward(const T_config *config, T_event event, const char *name) +{ + const T_action *actions; + size_t n; + size_t i; + + actions = config->actions; + n = config->action_count; + + for (i = 0; i < n; ++i) { + (*actions[i])(event, name); + } +} + +static void +T_call_actions_backward(const T_config *config, T_event event, + const char *name) +{ + const T_action *actions; + size_t n; + size_t i; + + actions = config->actions; + n = config->action_count; + + for (i = 0; i < n; ++i) { + (*actions[n - i - 1])(event, name); + } +} + +static T_context * +T_do_run_initialize(const T_config *config) +{ + T_context *ctx; + + ctx = &T_instance; + + pthread_spin_init(&ctx->lock, PTHREAD_PROCESS_PRIVATE); + + ctx->config = config; + ctx->putchar = config->putchar; + ctx->putchar_arg = config->putchar_arg; + ctx->verbosity = config->verbosity; + atomic_store_explicit(&ctx->steps, 0, memory_order_relaxed); + atomic_store_explicit(&ctx->failures, 0, memory_order_relaxed); + ctx->overall_cases = 0; + ctx->overall_steps = 0; + ctx->overall_failures = 0; + + T_set_runner(ctx); + T_call_actions_forward(config, T_EVENT_RUN_INITIALIZE, config->name); + T_do_log(ctx, T_QUIET, "A:%s\n", config->name); + T_system(ctx); + ctx->run_begin_time = (*config->now)(); + + return ctx; +} + +static void +T_do_case_begin(T_context *ctx, const T_case_context *tc) +{ + const T_config *config; + const T_fixture *fixture; + + config = ctx->config; + fixture = tc->fixture; + ctx->verbosity = config->verbosity; + ctx->current_case = tc; + LIST_INIT(&ctx->destructors); + atomic_store_explicit(&ctx->planned_steps, UINT_MAX, + memory_order_relaxed); + atomic_store_explicit(&ctx->steps, 0, memory_order_relaxed); + atomic_store_explicit(&ctx->failures, 0, memory_order_relaxed); + + T_call_actions_forward(config, T_EVENT_CASE_EARLY, tc->name); + T_do_log(ctx, T_NORMAL, "B:%s\n", tc->name); + ctx->case_begin_time = (*config->now)(); + T_call_actions_forward(config, T_EVENT_CASE_BEGIN, tc->name); + + if (fixture != NULL) { + ctx->fixture_context = fixture->initial_context; + + if (fixture->setup != NULL) { + (*fixture->setup)(ctx->fixture_context); + } + } +} + +static void +T_do_case_end(T_context *ctx, const T_case_context *tc) +{ + const T_config *config; + const T_fixture *fixture; + unsigned int planned_steps; + unsigned int steps; + unsigned int failures; + T_time delta; + T_time_string ts; + + config = ctx->config; + fixture = tc->fixture; + + if (fixture != NULL && fixture->teardown != NULL) { + (*fixture->teardown)(ctx->fixture_context); + } + + T_call_destructors(ctx); + T_call_actions_backward(config, T_EVENT_CASE_END, tc->name); + + planned_steps = atomic_fetch_add_explicit(&ctx->planned_steps, + 0, memory_order_relaxed); + steps = atomic_fetch_add_explicit(&ctx->steps, 0, + memory_order_relaxed); + failures = atomic_fetch_add_explicit(&ctx->failures, 0, + memory_order_relaxed); + + if (planned_steps != UINT_MAX && planned_steps != steps && + failures == 0) { + ++failures; + + if (ctx->verbosity >= T_NORMAL) { + char scope[T_SCOPE_SIZE]; + + T_printf("F:*:%i:%s:*:*:actual steps (%u), " + "planned steps (%u)\n", T_cpu(), + T_scope(scope), steps, planned_steps); + } + } + + delta = (*config->now)() - ctx->case_begin_time; + T_do_log(ctx, T_QUIET, "E:%s:N:%u:F:%u:D:%s\n", + tc->name, steps, failures, T_time_to_string_us(delta, ts)); + + ++ctx->overall_cases; + ctx->overall_steps += steps; + ctx->overall_failures += failures; + + T_call_actions_backward(config, T_EVENT_CASE_LATE, tc->name); +} + +static void +T_run_case(T_context *ctx, const T_case_context *tc) +{ + T_do_case_begin(ctx, tc); + + if (setjmp(ctx->case_begin_context) == 0) { + (*tc->body)(); + } + + T_do_case_end(ctx, tc); +} + +static void +T_do_run_all(T_context *ctx) +{ + const T_case_context *tc; + + tc = ctx->registered_cases; + + while (tc != NULL) { + T_run_case(ctx, tc); + tc = tc->next; + } +} + +static bool +T_do_run_finalize(T_context *ctx) +{ + const T_config *config; + T_time delta; + T_time_string ts; + + config = ctx->config; + delta = (*config->now)() - ctx->run_begin_time; + T_do_log(ctx, T_QUIET, "Z:%s:C:%u:N:%u:F:%u:D:%s\n", config->name, + ctx->overall_cases, ctx->overall_steps, ctx->overall_failures, + T_time_to_string_us(delta, ts)); + T_call_actions_backward(config, T_EVENT_RUN_FINALIZE, config->name); +#ifdef __rtems__ + ctx->runner_thread = NULL; + ctx->runner_cpu = NULL; +#else + ctx->runner_valid = false; +#endif + pthread_spin_destroy(&ctx->lock); + + return ctx->overall_failures == 0; +} + +int +T_main(const T_config *config) +{ + T_context *ctx; + + ctx = T_do_run_initialize(config); + T_do_run_all(ctx); + + return T_do_run_finalize(ctx) ? 0 : 1; +} + +bool T_is_runner(void) +{ + T_context *ctx; + bool is_runner; +#ifdef __rtems__ + ISR_Level level; + const Per_CPU_Control *cpu_self; +#endif + + ctx = &T_instance; +#ifdef __rtems__ + _ISR_Local_disable(level); + cpu_self = _Per_CPU_Get(); + + if (ctx->runner_thread != NULL) { + is_runner = cpu_self->isr_nest_level == 0 && + _Per_CPU_Get_executing(cpu_self) == ctx->runner_thread; + } else { + is_runner = cpu_self == ctx->runner_cpu; + } + + _ISR_Local_enable(level); +#else + is_runner = ctx->runner_valid && + pthread_equal(pthread_self(), ctx->runner_thread) != 0; +#endif + + return is_runner; +} + +#ifdef __rtems__ +RTEMS_LINKER_ROSET(_T, T_case_context *); +#endif /* __rtems__ */ + +void T_register(void) +{ +#ifdef __rtems__ + T_case_context * const *tc; + + RTEMS_LINKER_SET_FOREACH(_T, tc) { + T_case_register(*tc); + } +#endif /* __rtems__ */ +} + +void +T_run_initialize(const T_config *config) +{ + (void)T_do_run_initialize(config); +} + +void +T_run_all(void) +{ + T_do_run_all(&T_instance); +} + +void +T_run_by_name(const char *name) +{ + T_context *ctx; + const T_case_context *tc; + + ctx = &T_instance; + tc = ctx->registered_cases; + + while (tc != NULL) { + if (strcmp(tc->name, name) == 0) { + T_run_case(ctx, tc); + break; + } + + tc = tc->next; + } +} + +static T_case_context default_case; + +void +T_case_begin(const char *name, const T_fixture *fixture) +{ + T_case_context *tc; + + tc = &default_case; + tc->name = name; + tc->fixture = fixture; + T_do_case_begin(&T_instance, tc); +} + +void +T_case_end(void) +{ + T_case_context *tc; + + tc = &default_case; + T_do_case_end(&T_instance, tc); +} + +bool +T_run_finalize(void) +{ + return T_do_run_finalize(&T_instance); +} + +T_time +T_case_begin_time(void) +{ + return T_instance.case_begin_time; +} + +void +T_set_putchar(T_putchar new_putchar, void *new_arg, T_putchar *old_putchar, + void **old_arg) +{ + T_context *ctx; + + ctx = &T_instance; + *old_putchar = ctx->putchar; + *old_arg = ctx->putchar_arg; + ctx->putchar = new_putchar; + ctx->putchar_arg = new_arg; +} -- cgit v1.2.3