summaryrefslogtreecommitdiff
path: root/ptunit/include/ptunit.h
diff options
context:
space:
mode:
Diffstat (limited to 'ptunit/include/ptunit.h')
-rw-r--r--ptunit/include/ptunit.h463
1 files changed, 463 insertions, 0 deletions
diff --git a/ptunit/include/ptunit.h b/ptunit/include/ptunit.h
new file mode 100644
index 0000000000000..eed6109c17a55
--- /dev/null
+++ b/ptunit/include/ptunit.h
@@ -0,0 +1,463 @@
+/*
+ * Copyright (c) 2013-2019, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * 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 PTUNIT_H
+#define PTUNIT_H
+
+#include <stdint.h>
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* A source location for reporting unit test fails. */
+struct ptunit_srcloc {
+ /* The source file. */
+ const char *file;
+
+ /* The source line. */
+ uint32_t line;
+};
+
+/* A unit test result type.
+ *
+ * This distinguishes the various potential results of a unit test.
+ */
+enum ptunit_result_type {
+ /* The test has passed. */
+ ptur_passed,
+
+ /* The test has been skipped. */
+ ptur_skipped,
+
+ /* The test failed a signed/unsigned integer comparison. */
+ ptur_failed_signed_int,
+ ptur_failed_unsigned_int,
+
+ /* The test failed a pointer comparison. */
+ ptur_failed_pointer,
+
+ /* The test failed a string comparison. */
+ ptur_failed_str
+};
+
+/* A unit test result.
+ *
+ * We separate test execution and result reporting. A unit test function
+ * returns a structured result that can later be used for reporting.
+ */
+struct ptunit_failed_signed_int {
+ /* The expression that failed. */
+ const char *expr;
+
+ /* A string representation of the comparison operation. */
+ const char *cmp;
+
+ /* The expected value. */
+ int64_t expected;
+
+ /* The actual value. */
+ int64_t actual;
+};
+
+struct ptunit_failed_unsigned_int {
+ /* The expression that failed. */
+ const char *expr;
+
+ /* A string representation of the comparison operation. */
+ const char *cmp;
+
+ /* The expected value. */
+ uint64_t expected;
+
+ /* The actual value. */
+ uint64_t actual;
+};
+
+struct ptunit_failed_pointer {
+ /* The expression that failed. */
+ const char *expr;
+
+ /* A string representation of the comparison operation. */
+ const char *cmp;
+
+ /* The expected value. */
+ const void *expected;
+
+ /* The actual value. */
+ const void *actual;
+};
+
+struct ptunit_failed_str {
+ /* The expression that failed. */
+ const char *expr;
+
+ /* A string representation of the comparison operation. */
+ const char *cmp;
+
+ /* The expected value. */
+ char *expected;
+
+ /* The actual value. */
+ char *actual;
+};
+
+struct ptunit_result {
+ /* The test result type. */
+ enum ptunit_result_type type;
+
+ /* Test result details depending on the result type. */
+ struct {
+ /* The source location of the fail. */
+ struct ptunit_srcloc where;
+
+ union {
+ struct ptunit_failed_signed_int signed_int;
+ struct ptunit_failed_unsigned_int unsigned_int;
+ struct ptunit_failed_pointer pointer;
+ struct ptunit_failed_str str;
+ } variant;
+ } failed;
+};
+
+/* A unit test function. */
+typedef struct ptunit_result (*ptunit_tfun_t)(void);
+
+/* A unit test.
+ *
+ * This is used for logging and reporting.
+ *
+ * It is not used for running tests or even for storing tests to be run at a
+ * later time.
+ */
+struct ptunit_test {
+ /* The test name. */
+ const char *name;
+
+ /* The optional test arguments. */
+ const char *args;
+
+ /* The test result. */
+ struct ptunit_result result;
+};
+
+/* A unit test suite.
+ *
+ * This is a simple summary of all tests that have been run.
+ */
+struct ptunit_suite {
+ /* An optional suite name. */
+ const char *name;
+
+ /* The number of total tests. */
+ uint32_t nr_tests;
+
+ /* The number of tests that have been skipped. */
+ uint32_t nr_skips;
+
+ /* The number of tests that have failed. */
+ uint32_t nr_fails;
+};
+
+/* Create a unit test source location. */
+extern struct ptunit_srcloc ptunit_mk_srcloc(const char *file, uint32_t line);
+
+#define ptu_here() ptunit_mk_srcloc(__FILE__, __LINE__)
+
+
+/* Create unit test passed and not run results. */
+extern struct ptunit_result ptunit_mk_passed(void);
+extern struct ptunit_result ptunit_mk_skipped(void);
+
+/* Create a unit test failed signed int result. */
+extern struct ptunit_result ptunit_mk_failed_signed_int(const char *expr,
+ const char *cmp,
+ struct ptunit_srcloc,
+ int64_t actual,
+ int64_t expected);
+
+#define ptunit_int_cmp(A, E, C) \
+ do { \
+ int64_t a = (A), e = (E); \
+ \
+ if (!(a C e)) \
+ return ptunit_mk_failed_signed_int(#A #C #E, #C, \
+ ptu_here(), \
+ a, e); \
+ } while (0)
+
+
+/* Create a unit test failed unsigned int result. */
+extern struct ptunit_result ptunit_mk_failed_unsigned_int(const char *expr,
+ const char *cmp,
+ struct ptunit_srcloc,
+ uint64_t actual,
+ uint64_t expected);
+
+#define ptunit_uint_cmp(A, E, C) \
+ do { \
+ uint64_t a = (A), e = (E); \
+ \
+ if (!(a C e)) \
+ return ptunit_mk_failed_unsigned_int(#A #C #E, #C, \
+ ptu_here(), \
+ a, e); \
+ } while (0)
+
+
+/* Create a unit test failed pointer result. */
+extern struct ptunit_result ptunit_mk_failed_pointer(const char *expr,
+ const char *cmp,
+ struct ptunit_srcloc,
+ const void *actual,
+ const void *expected);
+
+#define ptunit_ptr_cmp(A, E, C) \
+ do { \
+ const void *a = (A), *e = (E); \
+ \
+ if (!(a C e)) \
+ return ptunit_mk_failed_pointer(#A #C #E, #C, \
+ ptu_here(), \
+ a, e); \
+ } while (0)
+
+
+/* Create a unit test failed string result. */
+extern struct ptunit_result ptunit_mk_failed_str(const char *expr,
+ const char *cmp,
+ struct ptunit_srcloc,
+ const char *actual,
+ const char *expected);
+
+#define ptunit_str_cmp(A, E, C) \
+ do { \
+ const char *a = (A), *e = (E); \
+ \
+ if (!a || !e || !(strcmp(a, e) C 0)) \
+ return ptunit_mk_failed_str(#A "~"#C #E, "~"#C, \
+ ptu_here(), \
+ a, e); \
+ } while (0)
+
+
+/* Run a sub-unit test; return on fail. */
+
+#define ptunit_subtest(T, ...) \
+ do { \
+ struct ptunit_result result; \
+ \
+ result = (T)(__VA_ARGS__); \
+ if (result.type != ptur_passed) \
+ return result; \
+ } while (0)
+
+
+/* Run a sub-unit test; return on fail from here. */
+
+#define ptunit_check(T, ...) \
+ do { \
+ struct ptunit_result result; \
+ \
+ result = (T)(__VA_ARGS__); \
+ if (result.type != ptur_passed) { \
+ result.failed.where = ptu_here(); \
+ return result; \
+ } \
+ } while (0)
+
+
+/* Create a unit test. */
+extern struct ptunit_test ptunit_mk_test(const char *name, const char *args);
+
+/* Destroy a unit test. */
+extern void ptunit_fini_test(struct ptunit_test *);
+
+/* Create a unit test suite. */
+extern struct ptunit_suite ptunit_mk_suite(int argc, char **argv);
+
+/* Log a unit test result.
+ *
+ * This may also report test fails depending on the configuration.
+ */
+extern void ptunit_log_test(struct ptunit_suite *, const struct ptunit_test *);
+
+/* Print a summary report for a unit test suite.
+ *
+ * Returns the number of failed tests (capped to fit into an int) on success.
+ * Returns -1 if @suite is NULL.
+ */
+extern int ptunit_report(const struct ptunit_suite *suite);
+
+/* Run a single simple unit test and log its result. */
+
+#define ptunit_run(S, T) \
+ do { \
+ struct ptunit_test test; \
+ \
+ test = ptunit_mk_test(#T, NULL); \
+ test.result = (T)(); \
+ \
+ ptunit_log_test(S, &test); \
+ ptunit_fini_test(&test); \
+ } while (0)
+
+
+/* Run a single parameterized unit test and log its result. */
+
+#define ptunit_run_p(S, T, ...) \
+ do { \
+ struct ptunit_test test; \
+ \
+ test = ptunit_mk_test(#T, #__VA_ARGS__); \
+ test.result = (T)(__VA_ARGS__); \
+ \
+ ptunit_log_test(S, &test); \
+ ptunit_fini_test(&test); \
+ } while (0)
+
+
+/* Run a single unit test with fixture and an explict argument list.
+ *
+ * The first argument in the argument list is typically the fixture.
+ */
+
+#define ptunit_frun(R, T, F, ...) \
+ do { \
+ struct ptunit_result *pr = &(R); \
+ \
+ pr->type = ptur_passed; \
+ if ((F)->init) \
+ *pr = (F)->init(F); \
+ \
+ if (pr->type == ptur_passed) { \
+ *pr = (T)(__VA_ARGS__); \
+ \
+ if ((F)->fini) { \
+ if (pr->type == ptur_passed) \
+ *pr = (F)->fini(F); \
+ else \
+ (void) (F)->fini(F); \
+ } \
+ } \
+ } while (0)
+
+
+/* Run a single unit test with fixture and log its result. */
+
+#define ptunit_run_f(S, T, F) \
+ do { \
+ struct ptunit_test test; \
+ \
+ test = ptunit_mk_test(#T, #F); \
+ \
+ ptunit_frun(test.result, T, &(F), &(F)); \
+ \
+ ptunit_log_test(S, &test); \
+ ptunit_fini_test(&test); \
+ } while (0)
+
+
+/* Run a single parameterized unit test with fixture and log its result. */
+
+#define ptunit_run_fp(S, T, F, ...) \
+ do { \
+ struct ptunit_test test; \
+ \
+ test = ptunit_mk_test(#T, #F ", " #__VA_ARGS__); \
+ \
+ ptunit_frun(test.result, T, &(F), &(F), __VA_ARGS__); \
+ \
+ ptunit_log_test(S, &test); \
+ ptunit_fini_test(&test); \
+ } while (0)
+
+
+
+/* The actual macros to be used in unit tests.
+ *
+ * Do not use the above ptunit_ macros directly.
+ */
+
+#define ptu_int_eq(A, E) ptunit_int_cmp(A, E, ==)
+#define ptu_int_ne(A, E) ptunit_int_cmp(A, E, !=)
+#define ptu_int_gt(A, E) ptunit_int_cmp(A, E, >)
+#define ptu_int_ge(A, E) ptunit_int_cmp(A, E, >=)
+#define ptu_int_lt(A, E) ptunit_int_cmp(A, E, <)
+#define ptu_int_le(A, E) ptunit_int_cmp(A, E, <=)
+
+#define ptu_uint_eq(A, E) ptunit_uint_cmp(A, E, ==)
+#define ptu_uint_ne(A, E) ptunit_uint_cmp(A, E, !=)
+#define ptu_uint_gt(A, E) ptunit_uint_cmp(A, E, >)
+#define ptu_uint_ge(A, E) ptunit_uint_cmp(A, E, >=)
+#define ptu_uint_lt(A, E) ptunit_uint_cmp(A, E, <)
+#define ptu_uint_le(A, E) ptunit_uint_cmp(A, E, <=)
+
+#define ptu_ptr_eq(A, E) ptunit_ptr_cmp(A, E, ==)
+#define ptu_ptr_ne(A, E) ptunit_ptr_cmp(A, E, !=)
+#define ptu_ptr_gt(A, E) ptunit_ptr_cmp(A, E, >)
+#define ptu_ptr_ge(A, E) ptunit_ptr_cmp(A, E, >=)
+#define ptu_ptr_lt(A, E) ptunit_ptr_cmp(A, E, <)
+#define ptu_ptr_le(A, E) ptunit_ptr_cmp(A, E, <=)
+#define ptu_null(A) ptunit_ptr_cmp(A, NULL, ==)
+#define ptu_ptr(A) ptunit_ptr_cmp(A, NULL, !=)
+
+#define ptu_str_eq(A, E) ptunit_str_cmp(A, E, ==)
+#define ptu_str_ne(A, E) ptunit_str_cmp(A, E, !=)
+
+/* Indicate that a unit test passed. */
+#define ptu_passed() ptunit_mk_passed()
+
+/* Skip a unit test. */
+#define ptu_skipped() ptunit_mk_skipped()
+
+/* Run a sub-unit test; return on fail. */
+#define ptu_test(T, ...) ptunit_subtest(T, __VA_ARGS__)
+
+/* Run a sub-unit test; return on fail from here. */
+#define ptu_check(T, ...) ptunit_check(T, __VA_ARGS__)
+
+/* Run a single unit test. */
+#define ptu_run(S, T) ptunit_run(&(S), T)
+
+/* Run a single parameterized unit test. */
+#define ptu_run_p(S, T, ...) ptunit_run_p(&(S), T, __VA_ARGS__)
+
+/* Run a single unit test with fixture. */
+#define ptu_run_f(S, T, F) ptunit_run_f(&(S), T, F)
+
+/* Run a single parameterized unit test with fixture. */
+#define ptu_run_fp(S, T, F, ...) ptunit_run_fp(&(S), T, F, __VA_ARGS__)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PTUNIT_H */