1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
|
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2023 Meta Platforms, Inc. and affiliates.
* Copyright (c) 2023 Tejun Heo <tj@kernel.org>
* Copyright (c) 2023 David Vernet <dvernet@meta.com>
*/
#ifndef __SCX_TEST_H__
#define __SCX_TEST_H__
#include <errno.h>
#include <scx/common.h>
#include <scx/compat.h>
enum scx_test_status {
SCX_TEST_PASS = 0,
SCX_TEST_SKIP,
SCX_TEST_FAIL,
};
#define EXIT_KIND(__ent) __COMPAT_ENUM_OR_ZERO("scx_exit_kind", #__ent)
struct scx_test {
/**
* name - The name of the testcase.
*/
const char *name;
/**
* description - A description of your testcase: what it tests and is
* meant to validate.
*/
const char *description;
/*
* setup - Setup the test.
* @ctx: A pointer to a context object that will be passed to run and
* cleanup.
*
* An optional callback that allows a testcase to perform setup for its
* run. A test may return SCX_TEST_SKIP to skip the run.
*/
enum scx_test_status (*setup)(void **ctx);
/*
* run - Run the test.
* @ctx: Context set in the setup() callback. If @ctx was not set in
* setup(), it is NULL.
*
* The main test. Callers should return one of:
*
* - SCX_TEST_PASS: Test passed
* - SCX_TEST_SKIP: Test should be skipped
* - SCX_TEST_FAIL: Test failed
*
* This callback must be defined.
*/
enum scx_test_status (*run)(void *ctx);
/*
* cleanup - Perform cleanup following the test
* @ctx: Context set in the setup() callback. If @ctx was not set in
* setup(), it is NULL.
*
* An optional callback that allows a test to perform cleanup after
* being run. This callback is run even if the run() callback returns
* SCX_TEST_SKIP or SCX_TEST_FAIL. It is not run if setup() returns
* SCX_TEST_SKIP or SCX_TEST_FAIL.
*/
void (*cleanup)(void *ctx);
};
void scx_test_register(struct scx_test *test);
#define REGISTER_SCX_TEST(__test) \
__attribute__((constructor)) \
static void ___scxregister##__LINE__(void) \
{ \
scx_test_register(__test); \
}
#define SCX_ERR(__fmt, ...) \
do { \
fprintf(stderr, "ERR: %s:%d\n", __FILE__, __LINE__); \
fprintf(stderr, __fmt"\n", ##__VA_ARGS__); \
} while (0)
#define SCX_FAIL(__fmt, ...) \
do { \
SCX_ERR(__fmt, ##__VA_ARGS__); \
return SCX_TEST_FAIL; \
} while (0)
#define SCX_FAIL_IF(__cond, __fmt, ...) \
do { \
if (__cond) \
SCX_FAIL(__fmt, ##__VA_ARGS__); \
} while (0)
#define SCX_GT(_x, _y) SCX_FAIL_IF((_x) <= (_y), "Expected %s > %s (%lu > %lu)", \
#_x, #_y, (u64)(_x), (u64)(_y))
#define SCX_GE(_x, _y) SCX_FAIL_IF((_x) < (_y), "Expected %s >= %s (%lu >= %lu)", \
#_x, #_y, (u64)(_x), (u64)(_y))
#define SCX_LT(_x, _y) SCX_FAIL_IF((_x) >= (_y), "Expected %s < %s (%lu < %lu)", \
#_x, #_y, (u64)(_x), (u64)(_y))
#define SCX_LE(_x, _y) SCX_FAIL_IF((_x) > (_y), "Expected %s <= %s (%lu <= %lu)", \
#_x, #_y, (u64)(_x), (u64)(_y))
#define SCX_EQ(_x, _y) SCX_FAIL_IF((_x) != (_y), "Expected %s == %s (%lu == %lu)", \
#_x, #_y, (u64)(_x), (u64)(_y))
#define SCX_ASSERT(_x) SCX_FAIL_IF(!(_x), "Expected %s to be true (%lu)", \
#_x, (u64)(_x))
#define SCX_ECODE_VAL(__ecode) ({ \
u64 __val = 0; \
bool __found = false; \
\
__found = __COMPAT_read_enum("scx_exit_code", #__ecode, &__val); \
SCX_ASSERT(__found); \
(s64)__val; \
})
#define SCX_KIND_VAL(__kind) ({ \
u64 __val = 0; \
bool __found = false; \
\
__found = __COMPAT_read_enum("scx_exit_kind", #__kind, &__val); \
SCX_ASSERT(__found); \
__val; \
})
#endif // # __SCX_TEST_H__
|