[PATCH 2/3] Add the T Test Framework

Sebastian Huber sebastian.huber at embedded-brains.de
Thu Mar 14 10:24:15 UTC 2019


Update #3199.
---
 cpukit/Makefile.am                    |   11 +
 cpukit/headers.am                     |    1 +
 cpukit/include/t.h                    | 2128 +++++++++++++++++++++++++++++++++
 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-malloc.c        |   96 ++
 cpukit/libtest/t-test-rtems-fds.c     |   72 ++
 cpukit/libtest/t-test-rtems-heap.c    |   95 ++
 cpukit/libtest/t-test-rtems-measure.c |  837 +++++++++++++
 cpukit/libtest/t-test-rtems-objs.c    |  277 +++++
 cpukit/libtest/t-test-rtems.c         |  104 ++
 cpukit/libtest/t-test-time.c          |  233 ++++
 cpukit/libtest/t-test.c               |  791 ++++++++++++
 14 files changed, 5135 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-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 0081bb77cd..33c6c293ec 100644
--- a/cpukit/Makefile.am
+++ b/cpukit/Makefile.am
@@ -1837,6 +1837,17 @@ 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-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..3b78de0145
--- /dev/null
+++ b/cpukit/include/t.h
@@ -0,0 +1,2128 @@
+/*
+ * 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 <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#ifdef __rtems__
+#include <rtems/score/cpu.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup TheTTestFramework The T Test Framework
+ *
+ * @brief The T 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 TheTTestFrameworkImpl The T Test Framework Implementation
+ *
+ * @ingroup TheTTestFramework
+ *
+ * @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_TEST_STOP 1U
+
+#define T_TEST_QUIET 2U
+
+#define T_TEST_STEP_FLAG 4U
+
+#define T_TEST_STEP_TO_FLAGS(step) ((unsigned int)(step) << 8)
+
+#define T_TEST_STEP_FROM_FLAGS(flags) ((flags) >> 8)
+
+#define T_TEST_STEP(step) (T_TEST_STEP_TO_FLAGS(step) | T_TEST_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(const T_check_context *, bool, const char *, ...);
+
+#define T_flags_true(a, flags, ...)					\
+{									\
+	static const T_check_context T_check_instance = {		\
+	    T_FILE_NAME, __LINE__, flags };				\
+	T_check_true(&T_check_instance, a, __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 T_check_context_msg *, const void *, 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(&T_check_instance, a, e);			\
+}
+
+void T_check_ne_ptr(const T_check_context_msg *, const void *, 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(&T_check_instance, a, e);			\
+}
+
+void T_check_null(const T_check_context_msg *, const void *);
+
+#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(&T_check_instance, a);				\
+}
+
+void T_check_not_null(const T_check_context_msg *, const void *);
+
+#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(&T_check_instance, a);				\
+}
+
+void T_check_eq_mem(const T_check_context_msg *, const void *, 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(&T_check_instance, a, e, n);			\
+}
+
+void T_check_ne_mem(const T_check_context_msg *, const void *, 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(&T_check_instance, a, e, n);			\
+}
+
+void T_check_eq_str(const T_check_context *, const char *, 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(&T_check_instance, a, e);			\
+}
+
+void T_check_ne_str(const T_check_context *, const char *, 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(&T_check_instance, a, e);			\
+}
+
+void T_check_eq_nstr(const T_check_context *, const char *, 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(&T_check_instance, a, e, n);			\
+}
+
+void T_check_ne_nstr(const T_check_context *, const char *, 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(&T_check_instance, a, e, n);			\
+}
+
+void T_check_eq_char(const T_check_context *, char, 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(&T_check_instance, a, e);			\
+}
+
+void T_check_ne_char(const T_check_context *, char, 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(&T_check_instance, a, e);			\
+}
+
+void T_check_eq_int(const T_check_context *, int, 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(&T_check_instance, a, e);			\
+}
+
+void T_check_ne_int(const T_check_context *, int, 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(&T_check_instance, a, e);			\
+}
+
+void T_check_ge_int(const T_check_context *, int, 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(&T_check_instance, a, e);			\
+}
+
+void T_check_gt_int(const T_check_context *, int, 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(&T_check_instance, a, e);			\
+}
+
+void T_check_le_int(const T_check_context *, int, 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(&T_check_instance, a, e);			\
+}
+
+void T_check_lt_int(const T_check_context *, int, 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(&T_check_instance, a, e);			\
+}
+
+void T_check_eq_uint(const T_check_context *, unsigned int, 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(&T_check_instance, a, e);			\
+}
+
+void T_check_ne_uint(const T_check_context *, unsigned int, 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(&T_check_instance, a, e);			\
+}
+
+void T_check_ge_uint(const T_check_context *, unsigned int, 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(&T_check_instance, a, e);			\
+}
+
+void T_check_gt_uint(const T_check_context *, unsigned int, 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(&T_check_instance, a, e);			\
+}
+
+void T_check_le_uint(const T_check_context *, unsigned int, 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(&T_check_instance, a, e);			\
+}
+
+void T_check_lt_uint(const T_check_context *, unsigned int, 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(&T_check_instance, a, e);			\
+}
+
+void T_check_eq_long(const T_check_context *, long, 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(&T_check_instance, a, e);			\
+}
+
+void T_check_ne_long(const T_check_context *, long, 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(&T_check_instance, a, e);			\
+}
+
+void T_check_ge_long(const T_check_context *, long, 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(&T_check_instance, a, e);			\
+}
+
+void T_check_gt_long(const T_check_context *, long, 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(&T_check_instance, a, e);			\
+}
+
+void T_check_le_long(const T_check_context *, long, 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(&T_check_instance, a, e);			\
+}
+
+void T_check_lt_long(const T_check_context *, long, 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(&T_check_instance, a, e);			\
+}
+
+void T_check_eq_ulong(const T_check_context *, unsigned long, 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(&T_check_instance, a, e);			\
+}
+
+void T_check_ne_ulong(const T_check_context *, unsigned long, 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(&T_check_instance, a, e);			\
+}
+
+void T_check_ge_ulong(const T_check_context *, unsigned long, 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(&T_check_instance, a, e);			\
+}
+
+void T_check_gt_ulong(const T_check_context *, unsigned long, 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(&T_check_instance, a, e);			\
+}
+
+void T_check_le_ulong(const T_check_context *, unsigned long, 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(&T_check_instance, a, e);			\
+}
+
+void T_check_lt_ulong(const T_check_context *, unsigned long, 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(&T_check_instance, a, e);			\
+}
+
+void T_check_eq_ll(const T_check_context *, long long, 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(&T_check_instance, a, e);				\
+}
+
+void T_check_ne_ll(const T_check_context *, long long, 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(&T_check_instance, a, e);				\
+}
+
+void T_check_ge_ll(const T_check_context *, long long, 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(&T_check_instance, a, e);				\
+}
+
+void T_check_gt_ll(const T_check_context *, long long, 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(&T_check_instance, a, e);				\
+}
+
+void T_check_le_ll(const T_check_context *, long long, 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(&T_check_instance, a, e);				\
+}
+
+void T_check_lt_ll(const T_check_context *, long long, 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(&T_check_instance, a, e);				\
+}
+
+void T_check_eq_ull(const T_check_context *, unsigned long long,
+    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(&T_check_instance, a, e);			\
+}
+
+void T_check_ne_ull(const T_check_context *, unsigned long long,
+    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(&T_check_instance, a, e);			\
+}
+
+void T_check_ge_ull(const T_check_context *, unsigned long long,
+    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(&T_check_instance, a, e);			\
+}
+
+void T_check_gt_ull(const T_check_context *, unsigned long long,
+    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(&T_check_instance, a, e);			\
+}
+
+void T_check_le_ull(const T_check_context *, unsigned long long,
+    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(&T_check_instance, a, e);			\
+}
+
+void T_check_lt_ull(const T_check_context *, unsigned long long,
+    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(&T_check_instance, a, e);			\
+}
+
+void T_check_eno(const T_check_context *, int, int);
+
+#define T_flags_eno(a, e, flags)					\
+{									\
+	static const T_check_context T_check_instance = {		\
+	    T_FILE_NAME, __LINE__, flags };				\
+	T_check_eno(&T_check_instance, a, e);				\
+}
+
+void T_check_eno_success(const T_check_context *, int);
+
+#define T_flags_eno_success(a, flags)					\
+{									\
+	static const T_check_context T_check_instance = {		\
+	    T_FILE_NAME, __LINE__, flags };				\
+	T_check_eno_success(&T_check_instance, a);			\
+}
+
+void T_check_psx_error(const T_check_context *, int, 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(&T_check_instance, a, eno);			\
+}
+
+void T_check_psx_success(const T_check_context *, int);
+
+#define T_flags_psx_success(a, flags)					\
+{									\
+	static const T_check_context T_check_instance = {		\
+	    T_FILE_NAME, __LINE__, flags };				\
+	T_check_psx_success(&T_check_instance, a);			\
+}
+
+/** @} */
+
+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 TheTTestFrameworkChecksBool Boolean Checks
+ *
+ * @ingroup TheTTestFramework
+ *
+ * @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_TEST_STOP, __VA_ARGS__)
+#define T_quiet_true(a, ...) T_flags_true(a, T_TEST_QUIET, __VA_ARGS__)
+#define T_step_true(s, a, ...) T_flags_true(a, T_TEST_STEP(s), __VA_ARGS__)
+
+#define T_false(a, ...) T_flags_true(!(a), 0, __VA_ARGS__)
+#define T_assert_false(a, ...) T_flags_true(!(a), T_TEST_STOP, __VA_ARGS__)
+#define T_quiet_false(a, ...) T_flags_true(!(a), T_TEST_QUIET, __VA_ARGS__)
+#define T_step_false(s, a, ...) T_flags_true(!(a), T_TEST_STEP(s), __VA_ARGS__)
+
+/** @} */
+
+/**
+ * @defgroup TheTTestFrameworkChecksGeneric Generic Checks
+ *
+ * @ingroup TheTTestFramework
+ *
+ * @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_TEST_STOP, __VA_ARGS__)
+#define T_quiet_eq(a, e, ...) T_flags_eq(a, e, T_TEST_QUIET, __VA_ARGS__)
+#define T_step_eq(s, a, e, ...) T_flags_eq(a, e, T_TEST_STEP(s), __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_TEST_STOP, __VA_ARGS__)
+#define T_quiet_ne(a, e, ...) T_flags_ne(a, e, T_TEST_QUIET, __VA_ARGS__)
+#define T_step_ne(s, a, e, ...) T_flags_ne(a, e, T_TEST_STEP(s), __VA_ARGS__)
+
+/** @} */
+
+/**
+ * @defgroup TheTTestFrameworkChecksPointer Pointer Checks
+ *
+ * @ingroup TheTTestFramework
+ *
+ * @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_TEST_STOP, #a, #e)
+#define T_quiet_eq_ptr(a, e) T_flags_eq_ptr(a, e, T_TEST_QUIET, #a, #e)
+#define T_step_eq_ptr(s, a, e) T_flags_eq_ptr(a, e, T_TEST_STEP(s), #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_TEST_STOP, #a, #e)
+#define T_quiet_ne_ptr(a, e) T_flags_ne_ptr(a, e, T_TEST_QUIET, #a, #e)
+#define T_step_ne_ptr(s, a, e) T_flags_ne_ptr(a, e, T_TEST_STEP(s), #a, #e)
+
+#define T_null(a) T_flags_null(a, 0, #a)
+#define T_assert_null(a) T_flags_null(a, T_TEST_STOP, #a)
+#define T_quiet_null(a) T_flags_null(a, T_TEST_QUIET, #a)
+#define T_step_null(s, a) T_flags_null(a, T_TEST_STEP(s), #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_TEST_STOP, #a)
+#define T_quiet_not_null(a) T_flags_not_null(a, T_TEST_QUIET, #a)
+#define T_step_not_null(s, a) T_flags_not_null(a, T_TEST_STEP(s), #a)
+
+/** @} */
+
+/**
+ * @defgroup TheTTestFrameworkChecksMemStr Memory Area Checks
+ *
+ * @ingroup TheTTestFramework
+ *
+ * @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_TEST_STOP, #a, #e, #n)
+#define T_quiet_eq_mem(a, e, n) \
+    T_flags_eq_mem(a, e, n, T_TEST_QUIET, #a, #e, #n)
+#define T_step_eq_mem(s, a, e, n) \
+    T_flags_eq_mem(a, e, n, T_TEST_STEP(s), #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_TEST_STOP, #a, #e, #n)
+#define T_quiet_ne_mem(a, e, n) \
+    T_flags_ne_mem(a, e, n, T_TEST_QUIET, #a, #e, #n)
+#define T_step_ne_mem(s, a, e, n) \
+    T_flags_ne_mem(a, e, n, T_TEST_STEP(s), #a, #e, #n)
+
+/** @} */
+
+/**
+ * @defgroup TheTTestFrameworkChecksStr String Checks
+ *
+ * @ingroup TheTTestFramework
+ *
+ * @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_TEST_STOP)
+#define T_quiet_eq_str(a, e) T_flags_eq_str(a, e, T_TEST_QUIET)
+#define T_step_eq_str(s, a, e) T_flags_eq_str(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ne_str(a, e) T_flags_ne_str(a, e, T_TEST_QUIET)
+#define T_step_ne_str(s, a, e) T_flags_ne_str(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_eq_nstr(a, e, n) T_flags_eq_nstr(a, e, n, T_TEST_QUIET)
+#define T_step_eq_nstr(s, a, e, n) T_flags_eq_nstr(a, e, n, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ne_nstr(a, e, n) T_flags_ne_nstr(a, e, n, T_TEST_QUIET)
+#define T_step_ne_nstr(s, a, e, n) T_flags_ne_nstr(a, e, n, T_TEST_STEP(s))
+
+/** @} */
+
+/**
+ * @defgroup TheTTestFrameworkChecksChar Character Checks
+ *
+ * @ingroup TheTTestFramework
+ *
+ * @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_TEST_STOP)
+#define T_quiet_eq_char(a, e) T_flags_eq_char(a, e, T_TEST_QUIET)
+#define T_step_eq_char(s, a, e) T_flags_eq_char(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ne_char(a, e) T_flags_ne_char(a, e, T_TEST_QUIET)
+#define T_step_ne_char(s, a, e) T_flags_ne_char(a, e, T_TEST_STEP(s))
+
+/** @} */
+
+/**
+ * @defgroup TheTTestFrameworkChecksSChar Signed Character Checks
+ *
+ * @ingroup TheTTestFramework
+ *
+ * @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_TEST_STOP)
+#define T_quiet_eq_schar(a, e) T_flags_eq_int(a, e, T_TEST_QUIET)
+#define T_step_eq_schar(s, a, e) T_flags_eq_int(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ne_schar(a, e) T_flags_ne_int(a, e, T_TEST_QUIET)
+#define T_step_ne_schar(s, a, e) T_flags_ne_int(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ge_schar(a, e) T_flags_ge_int(a, e, T_TEST_QUIET)
+#define T_step_ge_schar(s, a, e) T_flags_ge_int(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_gt_schar(a, e) T_flags_gt_int(a, e, T_TEST_QUIET)
+#define T_step_gt_schar(s, a, e) T_flags_gt_int(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_le_schar(a, e) T_flags_le_int(a, e, T_TEST_QUIET)
+#define T_step_le_schar(s, a, e) T_flags_le_int(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_lt_schar(a, e) T_flags_lt_int(a, e, T_TEST_QUIET)
+#define T_step_lt_schar(s, a, e) T_flags_lt_int(a, e, T_TEST_STEP(s))
+
+/** @} */
+
+/**
+ * @defgroup TheTTestFrameworkChecksUChar Unsigned Character Checks
+ *
+ * @ingroup TheTTestFramework
+ *
+ * @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_TEST_STOP)
+#define T_quiet_eq_uchar(a, e) T_flags_eq_uint(a, e, T_TEST_QUIET)
+#define T_step_eq_uchar(s, a, e) T_flags_eq_uint(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ne_uchar(a, e) T_flags_ne_uint(a, e, T_TEST_QUIET)
+#define T_step_ne_uchar(s, a, e) T_flags_ne_uint(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ge_uchar(a, e) T_flags_ge_uint(a, e, T_TEST_QUIET)
+#define T_step_ge_uchar(s, a, e) T_flags_ge_uint(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_gt_uchar(a, e) T_flags_gt_uint(a, e, T_TEST_QUIET)
+#define T_step_gt_uchar(s, a, e) T_flags_gt_uint(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_le_uchar(a, e) T_flags_le_uint(a, e, T_TEST_QUIET)
+#define T_step_le_uchar(s, a, e) T_flags_le_uint(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_lt_uchar(a, e) T_flags_lt_uint(a, e, T_TEST_QUIET)
+#define T_step_lt_uchar(s, a, e) T_flags_lt_uint(a, e, T_TEST_STEP(s))
+
+/** @} */
+
+/**
+ * @defgroup TheTTestFrameworkChecksShort Signed Short Integer Checks
+ *
+ * @ingroup TheTTestFramework
+ *
+ * @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_TEST_STOP)
+#define T_quiet_eq_short(a, e) T_flags_eq_int(a, e, T_TEST_QUIET)
+#define T_step_eq_short(s, a, e) T_flags_eq_int(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ne_short(a, e) T_flags_ne_int(a, e, T_TEST_QUIET)
+#define T_step_ne_short(s, a, e) T_flags_ne_int(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ge_short(a, e) T_flags_ge_int(a, e, T_TEST_QUIET)
+#define T_step_ge_short(s, a, e) T_flags_ge_int(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_gt_short(a, e) T_flags_gt_int(a, e, T_TEST_QUIET)
+#define T_step_gt_short(s, a, e) T_flags_gt_int(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_le_short(a, e) T_flags_le_int(a, e, T_TEST_QUIET)
+#define T_step_le_short(s, a, e) T_flags_le_int(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_lt_short(a, e) T_flags_lt_int(a, e, T_TEST_QUIET)
+#define T_step_lt_short(s, a, e) T_flags_lt_int(a, e, T_TEST_STEP(s))
+
+/** @} */
+
+/**
+ * @defgroup TheTTestFrameworkChecksUShort Unsigned Short Integer Checks
+ *
+ * @ingroup TheTTestFramework
+ *
+ * @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_TEST_STOP)
+#define T_quiet_eq_ushort(a, e) T_flags_eq_uint(a, e, T_TEST_QUIET)
+#define T_step_eq_ushort(s, a, e) T_flags_eq_uint(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ne_ushort(a, e) T_flags_ne_uint(a, e, T_TEST_QUIET)
+#define T_step_ne_ushort(s, a, e) T_flags_ne_uint(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ge_ushort(a, e) T_flags_ge_uint(a, e, T_TEST_QUIET)
+#define T_step_ge_ushort(s, a, e) T_flags_ge_uint(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_gt_ushort(a, e) T_flags_gt_uint(a, e, T_TEST_QUIET)
+#define T_step_gt_ushort(s, a, e) T_flags_gt_uint(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_le_ushort(a, e) T_flags_le_uint(a, e, T_TEST_QUIET)
+#define T_step_le_ushort(s, a, e) T_flags_le_uint(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_lt_ushort(a, e) T_flags_lt_uint(a, e, T_TEST_QUIET)
+#define T_step_lt_ushort(s, a, e) T_flags_lt_uint(a, e, T_TEST_STEP(s))
+
+/** @} */
+
+/**
+ * @defgroup TheTTestFrameworkChecksInt Signed Integer Checks
+ *
+ * @ingroup TheTTestFramework
+ *
+ * @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_TEST_STOP)
+#define T_quiet_eq_int(a, e) T_flags_eq_int(a, e, T_TEST_QUIET)
+#define T_step_eq_int(s, a, e) T_flags_eq_int(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ne_int(a, e) T_flags_ne_int(a, e, T_TEST_QUIET)
+#define T_step_ne_int(s, a, e) T_flags_ne_int(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ge_int(a, e) T_flags_ge_int(a, e, T_TEST_QUIET)
+#define T_step_ge_int(s, a, e) T_flags_ge_int(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_gt_int(a, e) T_flags_gt_int(a, e, T_TEST_QUIET)
+#define T_step_gt_int(s, a, e) T_flags_gt_int(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_le_int(a, e) T_flags_le_int(a, e, T_TEST_QUIET)
+#define T_step_le_int(s, a, e) T_flags_le_int(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_lt_int(a, e) T_flags_lt_int(a, e, T_TEST_QUIET)
+#define T_step_lt_int(s, a, e) T_flags_lt_int(a, e, T_TEST_STEP(s))
+
+/** @} */
+
+/**
+ * @defgroup TheTTestFrameworkChecksUInt Unsigned Integer Checks
+ *
+ * @ingroup TheTTestFramework
+ *
+ * @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_TEST_STOP)
+#define T_quiet_eq_uint(a, e) T_flags_eq_uint(a, e, T_TEST_QUIET)
+#define T_step_eq_uint(s, a, e) T_flags_eq_uint(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ne_uint(a, e) T_flags_ne_uint(a, e, T_TEST_QUIET)
+#define T_step_ne_uint(s, a, e) T_flags_ne_uint(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ge_uint(a, e) T_flags_ge_uint(a, e, T_TEST_QUIET)
+#define T_step_ge_uint(s, a, e) T_flags_ge_uint(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_gt_uint(a, e) T_flags_gt_uint(a, e, T_TEST_QUIET)
+#define T_step_gt_uint(s, a, e) T_flags_gt_uint(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_le_uint(a, e) T_flags_le_uint(a, e, T_TEST_QUIET)
+#define T_step_le_uint(s, a, e) T_flags_le_uint(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_lt_uint(a, e) T_flags_lt_uint(a, e, T_TEST_QUIET)
+#define T_step_lt_uint(s, a, e) T_flags_lt_uint(a, e, T_TEST_STEP(s))
+
+/** @} */
+
+/**
+ * @defgroup TheTTestFrameworkChecksLong Signed Long Integer Checks
+ *
+ * @ingroup TheTTestFramework
+ *
+ * @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_TEST_STOP)
+#define T_quiet_eq_long(a, e) T_flags_eq_long(a, e, T_TEST_QUIET)
+#define T_step_eq_long(s, a, e) T_flags_eq_long(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ne_long(a, e) T_flags_ne_long(a, e, T_TEST_QUIET)
+#define T_step_ne_long(s, a, e) T_flags_ne_long(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ge_long(a, e) T_flags_ge_long(a, e, T_TEST_QUIET)
+#define T_step_ge_long(s, a, e) T_flags_ge_long(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_gt_long(a, e) T_flags_gt_long(a, e, T_TEST_QUIET)
+#define T_step_gt_long(s, a, e) T_flags_gt_long(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_le_long(a, e) T_flags_le_long(a, e, T_TEST_QUIET)
+#define T_step_le_long(s, a, e) T_flags_le_long(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_lt_long(a, e) T_flags_lt_long(a, e, T_TEST_QUIET)
+#define T_step_lt_long(s, a, e) T_flags_lt_long(a, e, T_TEST_STEP(s))
+
+/** @} */
+
+/**
+ * @defgroup TheTTestFrameworkChecksULong Unsigned Long Integer Checks
+ *
+ * @ingroup TheTTestFramework
+ *
+ * @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_TEST_STOP)
+#define T_quiet_eq_ulong(a, e) T_flags_eq_ulong(a, e, T_TEST_QUIET)
+#define T_step_eq_ulong(s, a, e) T_flags_eq_ulong(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ne_ulong(a, e) T_flags_ne_ulong(a, e, T_TEST_QUIET)
+#define T_step_ne_ulong(s, a, e) T_flags_ne_ulong(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ge_ulong(a, e) T_flags_ge_ulong(a, e, T_TEST_QUIET)
+#define T_step_ge_ulong(s, a, e) T_flags_ge_ulong(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_gt_ulong(a, e) T_flags_gt_ulong(a, e, T_TEST_QUIET)
+#define T_step_gt_ulong(s, a, e) T_flags_gt_ulong(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_le_ulong(a, e) T_flags_le_ulong(a, e, T_TEST_QUIET)
+#define T_step_le_ulong(s, a, e) T_flags_le_ulong(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_lt_ulong(a, e) T_flags_lt_ulong(a, e, T_TEST_QUIET)
+#define T_step_lt_ulong(s, a, e) T_flags_lt_ulong(a, e, T_TEST_STEP(s))
+
+/** @} */
+
+/**
+ * @defgroup TheTTestFrameworkChecksLong Signed Long Long Integer Checks
+ *
+ * @ingroup TheTTestFramework
+ *
+ * @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_TEST_STOP)
+#define T_quiet_eq_ll(a, e) T_flags_eq_ll(a, e, T_TEST_QUIET)
+#define T_step_eq_ll(s, a, e) T_flags_eq_ll(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ne_ll(a, e) T_flags_ne_ll(a, e, T_TEST_QUIET)
+#define T_step_ne_ll(s, a, e) T_flags_ne_ll(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ge_ll(a, e) T_flags_ge_ll(a, e, T_TEST_QUIET)
+#define T_step_ge_ll(s, a, e) T_flags_ge_ll(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_gt_ll(a, e) T_flags_gt_ll(a, e, T_TEST_QUIET)
+#define T_step_gt_ll(s, a, e) T_flags_gt_ll(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_le_ll(a, e) T_flags_le_ll(a, e, T_TEST_QUIET)
+#define T_step_le_ll(s, a, e) T_flags_le_ll(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_lt_ll(a, e) T_flags_lt_ll(a, e, T_TEST_QUIET)
+#define T_step_lt_ll(s, a, e) T_flags_lt_ll(a, e, T_TEST_STEP(s))
+
+/** @} */
+
+/**
+ * @defgroup TheTTestFrameworkChecksULongLong Unsigned Long Long Integer Checks
+ *
+ * @ingroup TheTTestFramework
+ *
+ * @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_TEST_STOP)
+#define T_quiet_eq_ull(a, e) T_flags_eq_ull(a, e, T_TEST_QUIET)
+#define T_step_eq_ull(s, a, e) T_flags_eq_ull(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ne_ull(a, e) T_flags_ne_ull(a, e, T_TEST_QUIET)
+#define T_step_ne_ull(s, a, e) T_flags_ne_ull(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ge_ull(a, e) T_flags_ge_ull(a, e, T_TEST_QUIET)
+#define T_step_ge_ull(s, a, e) T_flags_ge_ull(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_gt_ull(a, e) T_flags_gt_ull(a, e, T_TEST_QUIET)
+#define T_step_gt_ull(s, a, e) T_flags_gt_ull(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_le_ull(a, e) T_flags_le_ull(a, e, T_TEST_QUIET)
+#define T_step_le_ull(s, a, e) T_flags_le_ull(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_lt_ull(a, e) T_flags_lt_ull(a, e, T_TEST_QUIET)
+#define T_step_lt_ull(s, a, e) T_flags_lt_ull(a, e, T_TEST_STEP(s))
+
+/** @} */
+
+/**
+ * @defgroup TheTTestFrameworkChecksInt8 Signed 8-Bit Integer Checks
+ *
+ * @ingroup TheTTestFramework
+ *
+ * @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_TEST_STOP)
+#define T_quiet_eq_i8(a, e) T_flags_eq_int(a, e, T_TEST_QUIET)
+#define T_step_eq_i8(s, a, e) T_flags_eq_int(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ne_i8(a, e) T_flags_ne_int(a, e, T_TEST_QUIET)
+#define T_step_ne_i8(s, a, e) T_flags_ne_int(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ge_i8(a, e) T_flags_ge_int(a, e, T_TEST_QUIET)
+#define T_step_ge_i8(s, a, e) T_flags_ge_int(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_gt_i8(a, e) T_flags_gt_int(a, e, T_TEST_QUIET)
+#define T_step_gt_i8(s, a, e) T_flags_gt_int(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_le_i8(a, e) T_flags_le_int(a, e, T_TEST_QUIET)
+#define T_step_le_i8(s, a, e) T_flags_le_int(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_lt_i8(a, e) T_flags_lt_int(a, e, T_TEST_QUIET)
+#define T_step_lt_i8(s, a, e) T_flags_lt_int(a, e, T_TEST_STEP(s))
+
+/** @} */
+
+/**
+ * @defgroup TheTTestFrameworkChecksUInt8 Unsigned 8-Bit Integer Checks
+ *
+ * @ingroup TheTTestFramework
+ *
+ * @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_TEST_STOP)
+#define T_quiet_eq_u8(a, e) T_flags_eq_uint(a, e, T_TEST_QUIET)
+#define T_step_eq_u8(s, a, e) T_flags_eq_uint(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ne_u8(a, e) T_flags_ne_uint(a, e, T_TEST_QUIET)
+#define T_step_ne_u8(s, a, e) T_flags_ne_uint(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ge_u8(a, e) T_flags_ge_uint(a, e, T_TEST_QUIET)
+#define T_step_ge_u8(s, a, e) T_flags_ge_uint(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_gt_u8(a, e) T_flags_gt_uint(a, e, T_TEST_QUIET)
+#define T_step_gt_u8(s, a, e) T_flags_gt_uint(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_le_u8(a, e) T_flags_le_uint(a, e, T_TEST_QUIET)
+#define T_step_le_u8(s, a, e) T_flags_le_uint(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_lt_u8(a, e) T_flags_lt_uint(a, e, T_TEST_QUIET)
+#define T_step_lt_u8(s, a, e) T_flags_lt_uint(a, e, T_TEST_STEP(s))
+
+/** @} */
+
+/**
+ * @defgroup TheTTestFrameworkChecksInt16 Signed 16-Bit Integer Checks
+ *
+ * @ingroup TheTTestFramework
+ *
+ * @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_TEST_STOP)
+#define T_quiet_eq_i16(a, e) T_flags_eq_int(a, e, T_TEST_QUIET)
+#define T_step_eq_i16(s, a, e) T_flags_eq_int(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ne_i16(a, e) T_flags_ne_int(a, e, T_TEST_QUIET)
+#define T_step_ne_i16(s, a, e) T_flags_ne_int(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ge_i16(a, e) T_flags_ge_int(a, e, T_TEST_QUIET)
+#define T_step_ge_i16(s, a, e) T_flags_ge_int(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_gt_i16(a, e) T_flags_gt_int(a, e, T_TEST_QUIET)
+#define T_step_gt_i16(s, a, e) T_flags_gt_int(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_le_i16(a, e) T_flags_le_int(a, e, T_TEST_QUIET)
+#define T_step_le_i16(s, a, e) T_flags_le_int(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_lt_i16(a, e) T_flags_lt_int(a, e, T_TEST_QUIET)
+#define T_step_lt_i16(s, a, e) T_flags_lt_int(a, e, T_TEST_STEP(s))
+
+/** @} */
+
+/**
+ * @defgroup TheTTestFrameworkChecksUInt16 Unsigned 16-Bit Integer Checks
+ *
+ * @ingroup TheTTestFramework
+ *
+ * @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_TEST_STOP)
+#define T_quiet_eq_u16(a, e) T_flags_eq_uint(a, e, T_TEST_QUIET)
+#define T_step_eq_u16(s, a, e) T_flags_eq_uint(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ne_u16(a, e) T_flags_ne_uint(a, e, T_TEST_QUIET)
+#define T_step_ne_u16(s, a, e) T_flags_ne_uint(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ge_u16(a, e) T_flags_ge_uint(a, e, T_TEST_QUIET)
+#define T_step_ge_u16(s, a, e) T_flags_ge_uint(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_gt_u16(a, e) T_flags_gt_uint(a, e, T_TEST_QUIET)
+#define T_step_gt_u16(s, a, e) T_flags_gt_uint(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_le_u16(a, e) T_flags_le_uint(a, e, T_TEST_QUIET)
+#define T_step_le_u16(s, a, e) T_flags_le_uint(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_lt_u16(a, e) T_flags_lt_uint(a, e, T_TEST_QUIET)
+#define T_step_lt_u16(s, a, e) T_flags_lt_uint(a, e, T_TEST_STEP(s))
+
+/** @} */
+
+/**
+ * @defgroup TheTTestFrameworkChecksInt32 Signed 32-Bit Integer Checks
+ *
+ * @ingroup TheTTestFramework
+ *
+ * @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_TEST_STOP)
+#define T_quiet_eq_i32(a, e) T_flags_eq_long(a, e, T_TEST_QUIET)
+#define T_step_eq_i32(s, a, e) T_flags_eq_long(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ne_i32(a, e) T_flags_ne_long(a, e, T_TEST_QUIET)
+#define T_step_ne_i32(s, a, e) T_flags_ne_long(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ge_i32(a, e) T_flags_ge_long(a, e, T_TEST_QUIET)
+#define T_step_ge_i32(s, a, e) T_flags_ge_long(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_gt_i32(a, e) T_flags_gt_long(a, e, T_TEST_QUIET)
+#define T_step_gt_i32(s, a, e) T_flags_gt_long(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_le_i32(a, e) T_flags_le_long(a, e, T_TEST_QUIET)
+#define T_step_le_i32(s, a, e) T_flags_le_long(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_lt_i32(a, e) T_flags_lt_long(a, e, T_TEST_QUIET)
+#define T_step_lt_i32(s, a, e) T_flags_lt_long(a, e, T_TEST_STEP(s))
+
+/** @} */
+
+/**
+ * @defgroup TheTTestFrameworkChecksUInt32 Unsigned 32-Bit Integer Checks
+ *
+ * @ingroup TheTTestFramework
+ *
+ * @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_TEST_STOP)
+#define T_quiet_eq_u32(a, e) T_flags_eq_ulong(a, e, T_TEST_QUIET)
+#define T_step_eq_u32(s, a, e) T_flags_eq_ulong(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ne_u32(a, e) T_flags_ne_ulong(a, e, T_TEST_QUIET)
+#define T_step_ne_u32(s, a, e) T_flags_ne_ulong(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ge_u32(a, e) T_flags_ge_ulong(a, e, T_TEST_QUIET)
+#define T_step_ge_u32(s, a, e) T_flags_ge_ulong(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_gt_u32(a, e) T_flags_gt_ulong(a, e, T_TEST_QUIET)
+#define T_step_gt_u32(s, a, e) T_flags_gt_ulong(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_le_u32(a, e) T_flags_le_ulong(a, e, T_TEST_QUIET)
+#define T_step_le_u32(s, a, e) T_flags_le_ulong(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_lt_u32(a, e) T_flags_lt_ulong(a, e, T_TEST_QUIET)
+#define T_step_lt_u32(s, a, e) T_flags_lt_ulong(a, e, T_TEST_STEP(s))
+
+/** @} */
+
+/**
+ * @defgroup TheTTestFrameworkChecksInt64 Signed 64-Bit Integer Checks
+ *
+ * @ingroup TheTTestFramework
+ *
+ * @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_TEST_STOP)
+#define T_quiet_eq_i64(a, e) T_flags_eq_ll(a, e, T_TEST_QUIET)
+#define T_step_eq_i64(s, a, e) T_flags_eq_ll(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ne_i64(a, e) T_flags_ne_ll(a, e, T_TEST_QUIET)
+#define T_step_ne_i64(s, a, e) T_flags_ne_ll(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ge_i64(a, e) T_flags_ge_ll(a, e, T_TEST_QUIET)
+#define T_step_ge_i64(s, a, e) T_flags_ge_ll(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_gt_i64(a, e) T_flags_gt_ll(a, e, T_TEST_QUIET)
+#define T_step_gt_i64(s, a, e) T_flags_gt_ll(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_le_i64(a, e) T_flags_le_ll(a, e, T_TEST_QUIET)
+#define T_step_le_i64(s, a, e) T_flags_le_ll(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_lt_i64(a, e) T_flags_lt_ll(a, e, T_TEST_QUIET)
+#define T_step_lt_i64(s, a, e) T_flags_lt_ll(a, e, T_TEST_STEP(s))
+
+/** @} */
+
+/**
+ * @defgroup TheTTestFrameworkChecksUInt64 Unsigned 64-Bit Integer Checks
+ *
+ * @ingroup TheTTestFramework
+ *
+ * @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_TEST_STOP)
+#define T_quiet_eq_u64(a, e) T_flags_eq_ull(a, e, T_TEST_QUIET)
+#define T_step_eq_u64(s, a, e) T_flags_eq_ull(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ne_u64(a, e) T_flags_ne_ull(a, e, T_TEST_QUIET)
+#define T_step_ne_u64(s, a, e) T_flags_ne_ull(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ge_u64(a, e) T_flags_ge_ull(a, e, T_TEST_QUIET)
+#define T_step_ge_u64(s, a, e) T_flags_ge_ull(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_gt_u64(a, e) T_flags_gt_ull(a, e, T_TEST_QUIET)
+#define T_step_gt_u64(s, a, e) T_flags_gt_ull(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_le_u64(a, e) T_flags_le_ull(a, e, T_TEST_QUIET)
+#define T_step_le_u64(s, a, e) T_flags_le_ull(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_lt_u64(a, e) T_flags_lt_ull(a, e, T_TEST_QUIET)
+#define T_step_lt_u64(s, a, e) T_flags_lt_ull(a, e, T_TEST_STEP(s))
+
+/** @} */
+
+/**
+ * @defgroup TheTTestFrameworkChecksIntptr Signed Pointer Value Checks
+ *
+ * @ingroup TheTTestFramework
+ *
+ * @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_TEST_STOP)
+#define T_quiet_eq_iptr(a, e) T_flags_eq_long(a, e, T_TEST_QUIET)
+#define T_step_eq_iptr(s, a, e) T_flags_eq_long(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ne_iptr(a, e) T_flags_ne_long(a, e, T_TEST_QUIET)
+#define T_step_ne_iptr(s, a, e) T_flags_ne_long(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ge_iptr(a, e) T_flags_ge_long(a, e, T_TEST_QUIET)
+#define T_step_ge_iptr(s, a, e) T_flags_ge_long(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_gt_iptr(a, e) T_flags_gt_long(a, e, T_TEST_QUIET)
+#define T_step_gt_iptr(s, a, e) T_flags_gt_long(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_le_iptr(a, e) T_flags_le_long(a, e, T_TEST_QUIET)
+#define T_step_le_iptr(s, a, e) T_flags_le_long(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_lt_iptr(a, e) T_flags_lt_long(a, e, T_TEST_QUIET)
+#define T_step_lt_iptr(s, a, e) T_flags_lt_long(a, e, T_TEST_STEP(s))
+
+/** @} */
+
+/**
+ * @defgroup TheTTestFrameworkChecksUIntptr Unsigned Pointer Value Checks
+ *
+ * @ingroup TheTTestFramework
+ *
+ * @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_TEST_STOP)
+#define T_quiet_eq_uptr(a, e) T_flags_eq_ulong(a, e, T_TEST_QUIET)
+#define T_step_eq_uptr(s, a, e) T_flags_eq_ulong(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ne_uptr(a, e) T_flags_ne_ulong(a, e, T_TEST_QUIET)
+#define T_step_ne_uptr(s, a, e) T_flags_ne_ulong(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ge_uptr(a, e) T_flags_ge_ulong(a, e, T_TEST_QUIET)
+#define T_step_ge_uptr(s, a, e) T_flags_ge_ulong(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_gt_uptr(a, e) T_flags_gt_ulong(a, e, T_TEST_QUIET)
+#define T_step_gt_uptr(s, a, e) T_flags_gt_ulong(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_le_uptr(a, e) T_flags_le_ulong(a, e, T_TEST_QUIET)
+#define T_step_le_uptr(s, a, e) T_flags_le_ulong(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_lt_uptr(a, e) T_flags_lt_ulong(a, e, T_TEST_QUIET)
+#define T_step_lt_uptr(s, a, e) T_flags_lt_ulong(a, e, T_TEST_STEP(s))
+
+/** @} */
+
+/**
+ * @defgroup TheTTestFrameworkChecksSSZ Signed Size Checks
+ *
+ * @ingroup TheTTestFramework
+ *
+ * @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_TEST_STOP)
+#define T_quiet_eq_ssz(a, e) T_flags_eq_long(a, e, T_TEST_QUIET)
+#define T_step_eq_ssz(s, a, e) T_flags_eq_long(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ne_ssz(a, e) T_flags_ne_long(a, e, T_TEST_QUIET)
+#define T_step_ne_ssz(s, a, e) T_flags_ne_long(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ge_ssz(a, e) T_flags_ge_long(a, e, T_TEST_QUIET)
+#define T_step_ge_ssz(s, a, e) T_flags_ge_long(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_gt_ssz(a, e) T_flags_gt_long(a, e, T_TEST_QUIET)
+#define T_step_gt_ssz(s, a, e) T_flags_gt_long(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_le_ssz(a, e) T_flags_le_long(a, e, T_TEST_QUIET)
+#define T_step_le_ssz(s, a, e) T_flags_le_long(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_lt_ssz(a, e) T_flags_lt_long(a, e, T_TEST_QUIET)
+#define T_step_lt_ssz(s, a, e) T_flags_lt_long(a, e, T_TEST_STEP(s))
+
+/** @} */
+
+/**
+ * @defgroup TheTTestFrameworkChecksSZ Size Checks
+ *
+ * @ingroup TheTTestFramework
+ *
+ * @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_TEST_STOP)
+#define T_quiet_eq_sz(a, e) T_flags_eq_ulong(a, e, T_TEST_QUIET)
+#define T_step_eq_sz(s, a, e) T_flags_eq_ulong(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ne_sz(a, e) T_flags_ne_ulong(a, e, T_TEST_QUIET)
+#define T_step_ne_sz(s, a, e) T_flags_ne_ulong(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_ge_sz(a, e) T_flags_ge_ulong(a, e, T_TEST_QUIET)
+#define T_step_ge_sz(s, a, e) T_flags_ge_ulong(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_gt_sz(a, e) T_flags_gt_ulong(a, e, T_TEST_QUIET)
+#define T_step_gt_sz(s, a, e) T_flags_gt_ulong(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_le_sz(a, e) T_flags_le_ulong(a, e, T_TEST_QUIET)
+#define T_step_le_sz(s, a, e) T_flags_le_ulong(a, e, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_lt_sz(a, e) T_flags_lt_ulong(a, e, T_TEST_QUIET)
+#define T_step_lt_sz(s, a, e) T_flags_lt_ulong(a, e, T_TEST_STEP(s))
+
+/** @} */
+
+/**
+ * @defgroup TheTTestFrameworkChecksPSX POSIX Status and Error Number Checks
+ *
+ * @ingroup TheTTestFramework
+ *
+ * @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_TEST_STOP)
+#define T_quiet_eno(a, e) T_flags_eno(a, e, T_TEST_QUIET)
+#define T_step_eno(s, a, e) T_flags_eno(a, e, T_TEST_STEP(s))
+
+#define T_eno_success(a) T_flags_eno_success(a, 0)
+#define T_assert_eno_success(a) T_flags_eno_success(a, T_TEST_STOP)
+#define T_quiet_eno_success(a) T_flags_eno_success(a, T_TEST_QUIET)
+#define T_step_eno_success(s, a) T_flags_eno_success(a, T_TEST_STEP(s))
+
+#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_TEST_STOP)
+#define T_quiet_psx_error(a, eno) T_flags_psx_error(a, eno, T_TEST_QUIET)
+#define T_step_psx_error(s, a, eno) T_flags_psx_error(a, eno, T_TEST_STEP(s))
+
+#define T_psx_success(a) T_flags_psx_success(a, 0)
+#define T_assert_psx_success(a) T_flags_psx_success(a, T_TEST_STOP)
+#define T_quiet_psx_success(a) T_flags_psx_success(a, T_TEST_QUIET)
+#define T_step_psx_success(s, a) T_flags_psx_success(a, T_TEST_STEP(s))
+
+/** @} */
+
+#ifdef __rtems__
+void T_check_rsc(const T_check_context *, uint32_t, 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(&T_check_instance, a, e);				\
+}
+
+void T_check_rsc_success(const T_check_context *, uint32_t);
+
+#define T_flags_rsc_success(a, flags)					\
+{									\
+	static const T_check_context T_check_instance = {		\
+	    T_FILE_NAME, __LINE__, flags };				\
+	T_check_rsc_success(&T_check_instance, a);			\
+}
+
+/**
+ * @defgroup TheTTestFrameworkChecksRSC RTEMS Status Code Checks
+ *
+ * @ingroup TheTTestFramework
+ *
+ * @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_TEST_STOP)
+#define T_quiet_rsc(a, e) T_flags_rsc(a, e, T_TEST_QUIET)
+#define T_step_rsc(s, a, e) T_flags_rsc(a, e, T_TEST_STEP(s))
+
+#define T_rsc_success(a) T_flags_rsc_success(a, 0)
+#define T_assert_rsc_success(a) T_flags_rsc_success(a, T_TEST_STOP)
+#define T_quiet_rsc_success(a) T_flags_rsc_success(a, T_TEST_QUIET)
+#define T_step_rsc_success(s, a) T_flags_rsc_success(a, T_TEST_STEP(s))
+
+/** @} */
+#endif /* __rtems__ */
+
+void T_plan(unsigned int);
+
+#define T_step(s, ...) T_flags_true(true, T_TEST_STEP(s), __VA_ARGS__)
+
+/**
+ * @defgroup TheTTestFrameworkTime Time Services
+ *
+ * @ingroup TheTTestFramework
+ *
+ * @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 T_free(void *);
+
+void T_register(void);
+
+typedef void (*T_resource_handler)(void);
+
+typedef enum {
+	T_RESOURCE_INITIALIZE,
+	T_RESOURCE_CHECK,
+	T_RESOURCE_DESTROY,
+	T_RESOURCE_HANDLER_COUNT
+} T_resource_action;
+
+typedef struct {
+	T_resource_handler handlers[T_RESOURCE_HANDLER_COUNT];
+} T_resource_checker;
+
+typedef struct {
+	const char *name;
+	T_verbosity verbosity;
+	T_time (*now)(void);
+	void (*case_begin)(const char *);
+	void (*case_end)(const char *);
+	size_t resource_checker_count;
+	const T_resource_checker *resource_checkers;
+} T_config;
+
+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_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_resource_heap_initialize(void);
+void T_resource_heap_check(void);
+#define T_RESOURCE_HEAP \
+    { { T_resource_heap_initialize, T_resource_heap_check, NULL } }
+
+#ifdef __rtems__
+void T_resource_rtems_barriers_initialize(void);
+void T_resource_rtems_barriers_check(void);
+#define T_RESOURCE_RTEMS_BARRIERS \
+    { { T_resource_rtems_barriers_initialize, \
+    T_resource_rtems_barriers_check, NULL } }
+
+void T_resource_rtems_extensions_initialize(void);
+void T_resource_rtems_extensions_check(void);
+#define T_RESOURCE_RTEMS_EXTENSIONS \
+    { { T_resource_rtems_extensions_initialize, \
+    T_resource_rtems_extensions_check, NULL } }
+
+void T_resource_rtems_mqs_initialize(void);
+void T_resource_rtems_mqs_check(void);
+#define T_RESOURCE_RTEMS_MESSAGE_QUEUES \
+    { { T_resource_rtems_mqs_initialize, \
+    T_resource_rtems_mqs_check, NULL } }
+
+void T_resource_rtems_parts_initialize(void);
+void T_resource_rtems_parts_check(void);
+#define T_RESOURCE_RTEMS_PARTITIONS \
+    { { T_resource_rtems_parts_initialize, \
+    T_resource_rtems_parts_check, NULL } }
+
+void T_resource_rtems_periods_initialize(void);
+void T_resource_rtems_periods_check(void);
+#define T_RESOURCE_RTEMS_PERIODS \
+    { { T_resource_rtems_periods_initialize, \
+    T_resource_rtems_periods_check, NULL } }
+
+void T_resource_rtems_regions_initialize(void);
+void T_resource_rtems_regions_check(void);
+#define T_RESOURCE_RTEMS_REGIONS \
+    { { T_resource_rtems_regions_initialize, \
+    T_resource_rtems_regions_check, NULL } }
+
+void T_resource_rtems_semas_initialize(void);
+void T_resource_rtems_semas_check(void);
+#define T_RESOURCE_RTEMS_SEMAPHORES \
+    { { T_resource_rtems_semas_initialize, \
+    T_resource_rtems_semas_check, NULL } }
+
+void T_resource_rtems_tasks_initialize(void);
+void T_resource_rtems_tasks_check(void);
+#define T_RESOURCE_RTEMS_TASKS \
+    { { T_resource_rtems_tasks_initialize, \
+    T_resource_rtems_tasks_check, NULL } }
+
+void T_resource_rtems_timers_initialize(void);
+void T_resource_rtems_timers_check(void);
+#define T_RESOURCE_RTEMS_TIMERS \
+    { { T_resource_rtems_timers_initialize, \
+    T_resource_rtems_timers_check, NULL } }
+
+void T_resource_posix_keys_initialize(void);
+void T_resource_posix_keys_check(void);
+#define T_RESOURCE_POSIX_KEYS \
+    { { T_resource_posix_keys_initialize, \
+    T_resource_posix_keys_check, NULL } }
+
+void T_resource_posix_mqs_initialize(void);
+void T_resource_posix_mqs_check(void);
+#define T_RESOURCE_POSIX_MESSAGE_QUEUES \
+    { { T_resource_posix_mqs_initialize, \
+    T_resource_posix_mqs_check, NULL } }
+
+void T_resource_posix_semas_initialize(void);
+void T_resource_posix_semas_check(void);
+#define T_RESOURCE_POSIX_NAMED_SEMAPHORES \
+    { { T_resource_posix_semas_initialize, \
+    T_resource_posix_semas_check, NULL } }
+
+void T_resource_posix_shms_initialize(void);
+void T_resource_posix_shms_check(void);
+#define T_RESOURCE_POSIX_SHMS \
+    { { T_resource_posix_shms_initialize, \
+    T_resource_posix_shms_check, NULL } }
+
+void T_resource_posix_threads_initialize(void);
+void T_resource_posix_threads_check(void);
+#define T_RESOURCE_POSIX_THREADS \
+    { { T_resource_posix_threads_initialize, \
+    T_resource_posix_threads_check, NULL } }
+
+void T_resource_posix_timers_initialize(void);
+void T_resource_posix_timers_check(void);
+#define T_RESOURCE_POSIX_TIMERS \
+    { { T_resource_posix_timers_initialize, \
+    T_resource_posix_timers_check, NULL } }
+
+void T_resource_fds_initialize(void);
+void T_resource_fds_check(void);
+#define T_RESOURCE_FILE_DESCRIPTORS \
+    { { T_resource_fds_initialize, \
+    T_resource_fds_check, NULL } }
+#endif /* __rtems__ */
+
+/**
+ * @defgroup TheTTestFrameworkDestructors Destructors
+ *
+ * @ingroup TheTTestFramework
+ *
+ * @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 TheTTestFrameworkMeasureRuntime Runtime Measurements
+ *
+ * @ingroup TheTTestFramework
+ *
+ * @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..bf287cb37c
--- /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 <t.h>
+
+#include <errno.h>
+
+#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(const T_check_context *t, int a, int e)
+{
+	T_check_true(t, a == e, "%s == %s", T_strerror(a), T_strerror(e));
+}
+
+void T_check_eno_success(const T_check_context *t, int a)
+{
+	T_check_eno(t, a, 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..f75af7c3d1
--- /dev/null
+++ b/cpukit/libtest/t-test-checks-psx.c
@@ -0,0 +1,17 @@
+#include <t.h>
+
+#include <errno.h>
+
+void T_check_psx_error(const T_check_context *t, int a, int eeno)
+{
+	int aeno;
+
+	aeno = errno;
+	T_check_true(t, a == -1 && aeno == eeno, "%i == -1, %s == %s", a,
+	    T_strerror(aeno), T_strerror(eeno));
+}
+
+void T_check_psx_success(const T_check_context *t, int a)
+{
+	T_check_true(t, a == 0, "%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..568bb6236f
--- /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 <t.h>
+
+#include <inttypes.h>
+
+void
+T_check_eq_ptr(const T_check_context_msg *t, const void *a, const void *e)
+{
+	T_check_true(&t->base, a == e, "%s", t->msg);
+}
+
+void
+T_check_ne_ptr(const T_check_context_msg *t, const void *a, const void *e)
+{
+	T_check_true(&t->base, a != e, "%s", t->msg);
+}
+
+void
+T_check_null(const T_check_context_msg *t, const void *a)
+{
+	T_check_true(&t->base, a == NULL, "%s == NULL", t->msg);
+}
+
+void
+T_check_not_null(const T_check_context_msg *t, const void *a)
+{
+	T_check_true(&t->base, a != NULL, "%s != NULL", t->msg);
+}
+
+void
+T_check_eq_mem(const T_check_context_msg *t, const void *a, const void *e,
+    size_t n)
+{
+	T_check_true(&t->base, memcmp(a, e, n) == 0, "%s", t->msg);
+}
+
+void
+T_check_ne_mem(const T_check_context_msg *t, const void *a, const void *e,
+    size_t n)
+{
+	T_check_true(&t->base, memcmp(a, e, n) != 0, "%s", t->msg);
+}
+
+void
+T_check_eq_str(const T_check_context *t, const char *a, const char *e)
+{
+	T_check_true(t, strcmp(a, e) == 0, "\"%s\" == \"%s\"", a, e);
+}
+
+void
+T_check_ne_str(const T_check_context *t, const char *a, const char *e)
+{
+	T_check_true(t, strcmp(a, e) != 0, "\"%s\" != \"%s\"", a, e);
+}
+
+void
+T_check_eq_nstr(const T_check_context *t, const char *a, const char *e, size_t n)
+{
+	T_check_true(t, strncmp(a, e, n) == 0, "\"%.*s\" == \"%.*s\"", (int)n, a,
+	    (int)n, e);
+}
+
+void
+T_check_ne_nstr(const T_check_context *t, const char *a, const char *e, size_t n)
+{
+	T_check_true(t, strncmp(a, e, n) != 0, "\"%.*s\" != \"%.*s\"", (int)n, a,
+	    (int)n, e);
+}
+
+void
+T_check_eq_char(const T_check_context *t, char a, char e)
+{
+	T_check_true(t, a == e, "'%c' == '%c'", a, e);
+}
+
+void
+T_check_ne_char(const T_check_context *t, char a, char e)
+{
+	T_check_true(t, a != e, "'%c' != '%c'", a, e);
+}
+
+void
+T_check_eq_int(const T_check_context *t, int a, int e)
+{
+	T_check_true(t, a == e, "%i == %i", a, e);
+}
+
+void
+T_check_ne_int(const T_check_context *t, int a, int e)
+{
+	T_check_true(t, a != e, "%i != %i", a, e);
+}
+
+void
+T_check_ge_int(const T_check_context *t, int a, int e)
+{
+	T_check_true(t, a >= e, "%i >= %i", a, e);
+}
+
+void
+T_check_gt_int(const T_check_context *t, int a, int e)
+{
+	T_check_true(t, a > e, "%i > %i", a, e);
+}
+
+void
+T_check_le_int(const T_check_context *t, int a, int e)
+{
+	T_check_true(t, a <= e, "%i <= %i", a, e);
+}
+
+void
+T_check_lt_int(const T_check_context *t, int a, int e)
+{
+	T_check_true(t, a < e, "%i < %i", a, e);
+}
+
+void
+T_check_eq_uint(const T_check_context *t, unsigned int a, unsigned int e)
+{
+	T_check_true(t, a == e, "%u == %u", a, e);
+}
+
+void
+T_check_ne_uint(const T_check_context *t, unsigned int a, unsigned int e)
+{
+	T_check_true(t, a != e, "%u != %u", a, e);
+}
+
+void
+T_check_ge_uint(const T_check_context *t, unsigned int a, unsigned int e)
+{
+	T_check_true(t, a >= e, "%u >= %u", a, e);
+}
+
+void
+T_check_gt_uint(const T_check_context *t, unsigned int a, unsigned int e)
+{
+	T_check_true(t, a > e, "%u > %u", a, e);
+}
+
+void
+T_check_le_uint(const T_check_context *t, unsigned int a, unsigned int e)
+{
+	T_check_true(t, a <= e, "%u <= %u", a, e);
+}
+
+void
+T_check_lt_uint(const T_check_context *t, unsigned int a, unsigned int e)
+{
+	T_check_true(t, a < e, "%u < %u", a, e);
+}
+
+void
+T_check_eq_long(const T_check_context *t, long a, long e)
+{
+	T_check_true(t, a == e, "%li == %li", a, e);
+}
+
+void
+T_check_ne_long(const T_check_context *t, long a, long e)
+{
+	T_check_true(t, a != e, "%li != %li", a, e);
+}
+
+void
+T_check_ge_long(const T_check_context *t, long a, long e)
+{
+	T_check_true(t, a >= e, "%li >= %li", a, e);
+}
+
+void
+T_check_gt_long(const T_check_context *t, long a, long e)
+{
+	T_check_true(t, a > e, "%li > %li", a, e);
+}
+
+void
+T_check_le_long(const T_check_context *t, long a, long e)
+{
+	T_check_true(t, a <= e, "%li <= %li", a, e);
+}
+
+void
+T_check_lt_long(const T_check_context *t, long a, long e)
+{
+	T_check_true(t, a < e, "%li < %li", a, e);
+}
+
+void
+T_check_eq_ulong(const T_check_context *t, unsigned long a, unsigned long e)
+{
+	T_check_true(t, a == e, "%lu == %lu", a, e);
+}
+
+void
+T_check_ne_ulong(const T_check_context *t, unsigned long a, unsigned long e)
+{
+	T_check_true(t, a != e, "%lu != %lu", a, e);
+}
+
+void
+T_check_ge_ulong(const T_check_context *t, unsigned long a, unsigned long e)
+{
+	T_check_true(t, a >= e, "%lu >= %lu", a, e);
+}
+
+void
+T_check_gt_ulong(const T_check_context *t, unsigned long a, unsigned long e)
+{
+	T_check_true(t, a > e, "%lu > %lu", a, e);
+}
+
+void
+T_check_le_ulong(const T_check_context *t, unsigned long a, unsigned long e)
+{
+	T_check_true(t, a <= e, "%lu <= %lu", a, e);
+}
+
+void
+T_check_lt_ulong(const T_check_context *t, unsigned long a, unsigned long e)
+{
+	T_check_true(t, a < e, "%lu < %lu", a, e);
+}
+
+void
+T_check_eq_ll(const T_check_context *t, long long a, long long e)
+{
+	T_check_true(t, a == e, "%lli == %lli", a, e);
+}
+
+void
+T_check_ne_ll(const T_check_context *t, long long a, long long e)
+{
+	T_check_true(t, a != e, "%lli != %lli", a, e);
+}
+
+void
+T_check_ge_ll(const T_check_context *t, long long a, long long e)
+{
+	T_check_true(t, a >= e, "%lli >= %lli", a, e);
+}
+
+void
+T_check_gt_ll(const T_check_context *t, long long a, long long e)
+{
+	T_check_true(t, a > e, "%lli > %lli", a, e);
+}
+
+void
+T_check_le_ll(const T_check_context *t, long long a, long long e)
+{
+	T_check_true(t, a <= e, "%lli <= %lli", a, e);
+}
+
+void
+T_check_lt_ll(const T_check_context *t, long long a, long long e)
+{
+	T_check_true(t, a < e, "%lli < %lli", a, e);
+}
+
+void
+T_check_eq_ull(const T_check_context *t, unsigned long long a,
+    unsigned long long e)
+{
+	T_check_true(t, a == e, "%llu == %llu", a, e);
+}
+
+void
+T_check_ne_ull(const T_check_context *t, unsigned long long a,
+    unsigned long long e)
+{
+	T_check_true(t, a != e, "%llu != %llu", a, e);
+}
+
+void
+T_check_ge_ull(const T_check_context *t, unsigned long long a,
+    unsigned long long e)
+{
+	T_check_true(t, a >= e, "%llu >= %llu", a, e);
+}
+
+void
+T_check_gt_ull(const T_check_context *t, unsigned long long a,
+    unsigned long long e)
+{
+	T_check_true(t, a > e, "%llu > %llu", a, e);
+}
+
+void
+T_check_le_ull(const T_check_context *t, unsigned long long a,
+    unsigned long long e)
+{
+	T_check_true(t, a <= e, "%llu <= %llu", a, e);
+}
+
+void
+T_check_lt_ull(const T_check_context *t, unsigned long long a,
+    unsigned long long e)
+{
+	T_check_true(t, a < e, "%llu < %llu", a, e);
+}
diff --git a/cpukit/libtest/t-test-malloc.c b/cpukit/libtest/t-test-malloc.c
new file mode 100644
index 0000000000..2eac8f53d9
--- /dev/null
+++ b/cpukit/libtest/t-test-malloc.c
@@ -0,0 +1,96 @@
+/*
+ * 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 <t.h>
+
+#include <stdlib.h>
+
+#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;
+} T_malloc_destructor;
+
+static void
+T_malloc_destroy(T_destructor *dtor)
+{
+	free(dtor);
+}
+
+void *
+T_malloc(size_t size)
+{
+	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) {
+		T_add_destructor(&dtor->base, T_malloc_destroy);
+		++dtor;
+	}
+
+	return dtor;
+}
+
+void *
+T_calloc(size_t nelem, size_t elsize)
+{
+	return T_zalloc(nelem * elsize);
+}
+
+void *
+T_zalloc(size_t size)
+{
+	void *p;
+
+	p = T_malloc(size);
+	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..ccde7cc368
--- /dev/null
+++ b/cpukit/libtest/t-test-rtems-fds.c
@@ -0,0 +1,72 @@
+/*
+ * 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 <t.h>
+
+#include <rtems/libio_.h>
+
+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;
+}
+
+void
+T_resource_fds_initialize(void)
+{
+	T_open_fds = T_count_open_fds();
+}
+
+void
+T_resource_fds_check(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);
+	}
+}
diff --git a/cpukit/libtest/t-test-rtems-heap.c b/cpukit/libtest/t-test-rtems-heap.c
new file mode 100644
index 0000000000..266254fee5
--- /dev/null
+++ b/cpukit/libtest/t-test-rtems-heap.c
@@ -0,0 +1,95 @@
+/*
+ * 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 <t.h>
+
+#include <rtems/score/heapimpl.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/malloc.h>
+
+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));
+}
+
+void
+T_resource_heap_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);
+	}
+}
+
+void
+T_resource_heap_check(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(NULL, ok, "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(NULL, ok, "memory leak in heap");
+			memcpy(&ctx->heap_info, &info, sizeof(info));
+		}
+	}
+}
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 <t.h>
+
+#include <alloca.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rtems.h>
+
+#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..0bd6424cc2
--- /dev/null
+++ b/cpukit/libtest/t-test-rtems-objs.c
@@ -0,0 +1,277 @@
+/*
+ * 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 <t.h>
+
+#include <inttypes.h>
+
+#include <rtems/score/objectimpl.h>
+#include <rtems/score/threadimpl.h>
+#include <rtems/posix/keyimpl.h>
+
+static Objects_Maximum
+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
+objects_check(Objects_APIs api, uint16_t cls,
+    Objects_Maximum *expected, const char *name)
+{
+	Objects_Maximum count;
+	int32_t delta;
+
+	count = 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 barrier_count;
+
+void
+T_resource_rtems_barriers_initialize(void)
+{
+	barrier_count = objects_count(OBJECTS_CLASSIC_API,
+	    OBJECTS_RTEMS_BARRIERS);
+}
+
+void
+T_resource_rtems_barriers_check(void)
+{
+	objects_check(OBJECTS_CLASSIC_API, OBJECTS_RTEMS_BARRIERS,
+	    &barrier_count, "RTEMS barrier");
+}
+
+static Objects_Maximum extension_count;
+
+void
+T_resource_rtems_extensions_initialize(void)
+{
+	extension_count = objects_count(OBJECTS_CLASSIC_API,
+	    OBJECTS_RTEMS_EXTENSIONS);
+}
+
+void
+T_resource_rtems_extensions_check(void)
+{
+	objects_check(OBJECTS_CLASSIC_API, OBJECTS_RTEMS_EXTENSIONS,
+	    &extension_count, "RTEMS extension");
+}
+
+static Objects_Maximum mq_count;
+
+void
+T_resource_rtems_mqs_initialize(void)
+{
+	mq_count = objects_count(OBJECTS_CLASSIC_API,
+	    OBJECTS_RTEMS_MESSAGE_QUEUES);
+}
+
+void
+T_resource_rtems_mqs_check(void)
+{
+	objects_check(OBJECTS_CLASSIC_API, OBJECTS_RTEMS_MESSAGE_QUEUES,
+	    &mq_count, "RTEMS message queue");
+}
+
+static Objects_Maximum part_count;
+
+void
+T_resource_rtems_parts_initialize(void)
+{
+	part_count = objects_count(OBJECTS_CLASSIC_API,
+	    OBJECTS_RTEMS_PARTITIONS);
+}
+
+void
+T_resource_rtems_parts_check(void)
+{
+	objects_check(OBJECTS_CLASSIC_API, OBJECTS_RTEMS_PARTITIONS,
+	    &part_count, "RTEMS partition");
+}
+
+static Objects_Maximum period_count;
+
+void
+T_resource_rtems_periods_initialize(void)
+{
+	period_count = objects_count(OBJECTS_CLASSIC_API,
+	    OBJECTS_RTEMS_PERIODS);
+}
+
+void
+T_resource_rtems_periods_check(void)
+{
+	objects_check(OBJECTS_CLASSIC_API, OBJECTS_RTEMS_PERIODS,
+	    &period_count, "RTEMS period");
+}
+
+static Objects_Maximum region_count;
+
+void
+T_resource_rtems_regions_initialize(void)
+{
+	region_count = objects_count(OBJECTS_CLASSIC_API,
+	    OBJECTS_RTEMS_REGIONS);
+}
+
+void
+T_resource_rtems_regions_check(void)
+{
+	objects_check(OBJECTS_CLASSIC_API, OBJECTS_RTEMS_REGIONS,
+	    &region_count, "RTEMS region");
+}
+
+static Objects_Maximum sema_count;
+
+void
+T_resource_rtems_semas_initialize(void)
+{
+	sema_count = objects_count(OBJECTS_CLASSIC_API,
+	    OBJECTS_RTEMS_SEMAPHORES);
+}
+
+void
+T_resource_rtems_semas_check(void)
+{
+	objects_check(OBJECTS_CLASSIC_API, OBJECTS_RTEMS_SEMAPHORES,
+	    &sema_count, "RTEMS semaphore");
+}
+
+static Objects_Maximum task_count;
+
+void
+T_resource_rtems_tasks_initialize(void)
+{
+	task_count = objects_count(OBJECTS_CLASSIC_API,
+	    OBJECTS_RTEMS_TASKS);
+}
+
+void
+T_resource_rtems_tasks_check(void)
+{
+	_RTEMS_Lock_allocator();
+	_Thread_Kill_zombies();
+	_RTEMS_Unlock_allocator();
+
+	objects_check(OBJECTS_CLASSIC_API, OBJECTS_RTEMS_TASKS,
+	    &task_count, "RTEMS task");
+}
+
+static Objects_Maximum timer_count;
+
+void
+T_resource_rtems_timers_initialize(void)
+{
+	timer_count = objects_count(OBJECTS_CLASSIC_API,
+	    OBJECTS_RTEMS_TIMERS);
+}
+
+void
+T_resource_rtems_timers_check(void)
+{
+	objects_check(OBJECTS_CLASSIC_API, OBJECTS_RTEMS_TIMERS,
+	    &timer_count, "RTEMS timer");
+}
+
+static Objects_Maximum posix_key_count;
+
+static ssize_t posix_key_value_count;
+
+static POSIX_Keys_Control *
+get_next_posix_key(Objects_Id *id)
+{
+	return (POSIX_Keys_Control *)
+	    _Objects_Get_next(*id, &_POSIX_Keys_Information, id);
+}
+
+static ssize_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 = get_next_posix_key(&id)) != NULL ) {
+		count += (ssize_t)
+		    _Chain_Node_count_unprotected(&the_key->Key_value_pairs);
+		_Objects_Allocator_unlock();
+	}
+
+	return count;
+}
+
+void
+T_resource_posix_keys_initialize(void)
+{
+	posix_key_count = objects_count(OBJECTS_POSIX_API,
+	    OBJECTS_POSIX_KEYS);
+	posix_key_value_count = get_active_posix_key_value_pairs();
+}
+
+void
+T_resource_posix_keys_check(void)
+{
+	ssize_t count;
+	ssize_t delta;
+
+	objects_check(OBJECTS_POSIX_API, OBJECTS_POSIX_KEYS,
+	    &posix_key_count, "POSIX key");
+
+	count = get_active_posix_key_value_pairs();
+	delta = count - posix_key_value_count;
+
+	if (delta != 0) {
+		posix_key_value_count = count;
+		T_check_true(NULL, false, "POSIX key value pair leak (%zi)", delta);
+	}
+}
diff --git a/cpukit/libtest/t-test-rtems.c b/cpukit/libtest/t-test-rtems.c
new file mode 100644
index 0000000000..e3ca1d939c
--- /dev/null
+++ b/cpukit/libtest/t-test-rtems.c
@@ -0,0 +1,104 @@
+/*
+ * 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 <t.h>
+
+#include <rtems.h>
+#include <rtems/bspIo.h>
+#include <rtems/score/io.h>
+
+int
+T_vprintf(char const *fmt, va_list ap)
+{
+
+	return vprintk(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;
+}
+
+void
+T_check_rsc(const T_check_context *t, uint32_t a, uint32_t e)
+{
+	T_check_true(t, a == e, "%s == %s", rtems_status_text(a),
+	    rtems_status_text(e));
+}
+
+void
+T_check_rsc_success(const T_check_context *t, uint32_t a)
+{
+	T_check_rsc(t, a, 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 <t.h>
+
+#include <inttypes.h>
+#include <stdatomic.h>
+#include <stdio.h>
+#include <time.h>
+
+#ifdef __rtems__
+#include <rtems/counter.h>
+#include <rtems/score/timecounter.h>
+#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..8913bb15bb
--- /dev/null
+++ b/cpukit/libtest/t-test.c
@@ -0,0 +1,791 @@
+/*
+ * 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.
+ */
+
+#define _GNU_SOURCE
+
+#include <t.h>
+
+#include <sys/queue.h>
+#include <limits.h>
+#include <pthread.h>
+#include <sched.h>
+#include <setjmp.h>
+#include <stdatomic.h>
+
+#ifdef __rtems__
+#include <rtems/score/percpu.h>
+#include <rtems/score/smp.h>
+#include <rtems/score/threadimpl.h>
+#include <rtems/linkersets.h>
+#include <rtems/version.h>
+#endif /* __rtems__ */
+
+#define T_LINE_SIZE 120
+
+#define T_SCOPE_SIZE 5
+
+#define T_NO_OUTPUT INT_MAX
+
+typedef struct {
+	pthread_spinlock_t lock;
+	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 test_suite_begin_time;
+#ifdef __rtems__
+	Thread_Control *main_thread;
+	const Per_CPU_Control *main_cpu;
+#else
+	bool main_valid;
+	pthread_t main_thread;
+#endif
+	const T_config *config;
+} T_context;
+
+static T_context T_instance;
+
+static int
+T_cpu(void)
+{
+#if defined(__rtems__)
+	return (int)_SMP_Get_current_processor();
+#elif defined(__linux__)
+	return sched_getcpu();
+#else
+	return 0;
+#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);
+
+		if (executing != NULL) {
+			const char *name;
+
+			name = executing->Join_queue.Queue.name;
+
+			if ( name != NULL && name[ 0 ] != '\0' ) {
+				r = name;
+			} else {
+				uint32_t on;
+				size_t i;
+				int s;
+
+				on = executing->Object.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';
+				r = buf;
+			}
+		} else {
+			buf[0] = '?';
+			buf[1] = '\0';
+			r = 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->main_cpu = cpu_self;
+
+	if (cpu_self->isr_nest_level == 0) {
+		ctx->main_thread = _Per_CPU_Get_executing(cpu_self);
+	} else {
+		ctx->main_thread = NULL;
+	}
+
+	_ISR_Local_enable(level);
+#else
+	ctx->main_valid = true;
+	ctx->main_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(NULL, success, "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;
+}
+
+static const char *
+T_case_name_with_context(T_context *ctx)
+{
+	const T_case_context *tc;
+
+	tc = ctx->current_case;
+
+	if (tc != NULL) {
+		return tc->name;
+	} else {
+		return "?";
+	}
+}
+
+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)
+{
+	return T_case_name_with_context(&T_instance);
+}
+
+void
+T_check_true(const T_check_context *t, bool ok, 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_TEST_QUIET) == 0) {
+			step = T_fetch_add_step(ctx);
+		} else {
+			step = UINT_MAX;
+		}
+
+		if ((t->flags & T_TEST_STEP_FLAG) != 0 &&
+		     step != T_TEST_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_TEST_STEP_FROM_FLAGS(t->flags));
+		} else if (!ok) {
+			T_add_failure(ctx);
+
+			if (ctx->verbosity >= T_NORMAL) {
+				if ((t->flags & T_TEST_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_TEST_STOP) != 0) {
+				T_stop(ctx);
+			}
+		} else if ((t->flags & T_TEST_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_resource_handler(const T_config *config,
+    T_resource_action action)
+{
+	size_t i;
+	size_t n;
+	const T_resource_checker *rv;
+
+	n = config->resource_checker_count;
+	rv = config->resource_checkers;
+
+	for (i = 0; i < n; ++i) {
+		T_resource_handler handler;
+
+		handler = rv->handlers[action];
+		++rv;
+
+		if (handler != NULL) {
+			(*handler)();
+		}
+	}
+}
+
+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);
+	T_call_resource_handler(config, T_RESOURCE_INITIALIZE);
+
+	ctx->config = config;
+	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_do_log(ctx, T_QUIET, "A:%s\n", config->name);
+	T_system(ctx);
+	ctx->test_suite_begin_time = (*config->now)();
+
+	return ctx;
+}
+
+static void
+T_do_case_begin(T_context *ctx, const T_case_context *tc)
+{
+	const T_fixture *fixture;
+
+	fixture = tc->fixture;
+	ctx->verbosity = ctx->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);
+
+	if (ctx->config->case_begin != NULL) {
+		(*ctx->config->case_begin)(tc->name);
+	}
+
+	T_do_log(ctx, T_NORMAL, "B:%s\n", tc->name);
+	ctx->case_begin_time = (*ctx->config->now)();
+
+	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_fixture *fixture;
+	unsigned int planned_steps;
+	unsigned int steps;
+	unsigned int failures;
+	T_time delta;
+	T_time_string ts;
+
+	fixture = tc->fixture;
+
+	if (fixture != NULL && fixture->teardown != NULL) {
+		(*fixture->teardown)(ctx->fixture_context);
+	}
+
+	T_call_destructors(ctx);
+	T_call_resource_handler(ctx->config, T_RESOURCE_CHECK);
+
+	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 = (*ctx->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;
+
+	if (ctx->config->case_end != NULL) {
+		(*ctx->config->case_end)(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)
+{
+	T_time delta;
+	T_time_string ts;
+
+	delta = (*ctx->config->now)() - ctx->test_suite_begin_time;
+	T_do_log(ctx, T_QUIET, "Z:%s:C:%u:N:%u:F:%u:D:%s\n", ctx->config->name,
+	    ctx->overall_cases, ctx->overall_steps, ctx->overall_failures,
+	    T_time_to_string_us(delta, ts));
+#ifdef __rtems__
+	ctx->main_thread = NULL;
+	ctx->main_cpu = NULL;
+#else
+	ctx->main_valid = false;
+#endif
+
+	T_call_resource_handler(ctx->config, T_RESOURCE_DESTROY);
+	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_main;
+#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->main_thread != NULL) {
+		is_main = cpu_self->isr_nest_level == 0 &&
+		    _Per_CPU_Get_executing(cpu_self) == ctx->main_thread;
+	} else {
+		is_main = cpu_self == ctx->main_cpu;
+	}
+
+	_ISR_Local_enable(level);
+#else
+	is_main = ctx->main_valid &&
+	    pthread_equal(pthread_self(), ctx->main_thread) != 0;
+#endif
+
+	return is_main;
+}
+
+#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;
+}
-- 
2.16.4




More information about the devel mailing list