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