Nightmare test framework
struct nightmare_role { enum nightmare_role_type type; char *name; size_t count; void (*worker)(void *); void *arg;};struct nightmare_role referenced types:
struct nightmare_watchdog { atomic_uint last_progress; time_t last_kick_ms;};struct nightmare_watchdog referenced types:
struct nightmare_report { char *buffer; size_t buffer_len; void (*write_fn)(struct nightmare_report *r, const char *msg, size_t len); uint32_t flags;};struct nightmare_test { char *name; struct nightmare_watchdog *watchdog; time_t default_runtime_ms; size_t default_threads; enum nightmare_state state; enum nightmare_test_error error; struct nightmare_role roles[NIGHTMARE_ROLE_MAX]; size_t role_count; void (*reset)(struct nightmare_test *); void (*init)(struct nightmare_test *); enum nightmare_test_error (*start)( struct nightmare_test *); void (*stop)(struct nightmare_test *); void (*shutdown)(struct nightmare_test *); void (*report)(struct nightmare_test *, struct nightmare_report *); size_t message_count; char **messages; void *private;};struct nightmare_test referenced types:
struct nightmare_watchdogtime_tenum nightmare_stateenum nightmare_test_errorstruct nightmare_role
struct nightmare_local { void *data; size_t len;};struct nightmare_thread { (struct thread *) th; struct nightmare_test *test; enum nightmare_role_type role; struct nightmare_local local;};struct nightmare_thread referenced types:
struct nightmare_thread_group { struct nightmare_thread *threads; size_t count;};struct nightmare_thread_group referenced types:
struct nightmare { struct nightmare_test *test; struct nightmare_thread *self; struct nightmare_watchdog *watchdog;};struct nightmare referenced types:
enum nightmare_role_type { NIGHTMARE_ROLE_GENERIC, NIGHTMARE_ROLE_SLEEPER, NIGHTMARE_ROLE_WAKER, NIGHTMARE_ROLE_MIGRATOR, NIGHTMARE_ROLE_APC_SPAMMER, NIGHTMARE_ROLE_FORKER, NIGHTMARE_ROLE_ALLOCATOR, NIGHTMARE_ROLE_INVALIDATOR, NIGHTMARE_ROLE_MAX,};enum nightmare_test_error { NIGHTMARE_ERR_OK, NIGHTMARE_ERR_FAIL, NIGHTMARE_ERR_RETRY, NIGHTMARE_ERR_PANIC,};enum nightmare_state { NIGHTMARE_UNINIT, NIGHTMARE_READY, NIGHTMARE_RUNNING, NIGHTMARE_STOPPED,};void nightmare_add_role(struct nightmare_test *t, enum nightmare_role_type type, char *name, void (*worker)(void *), size_t count, void *arg);nightmare_add_role referenced types:
bool nightmare_should_stop(void);void nightmare_chaos_pause();void nightmare_kick(struct nightmare_watchdog *w);nightmare_kick referenced types:
bool nightmare_watchdog_expired(struct nightmare_watchdog *w, time_t timeout_ms);nightmare_watchdog_expired referenced types:
void nightmare_watchdog_init(struct nightmare_watchdog *w);nightmare_watchdog_init referenced types:
void nightmare_set_local(void *d, size_t l);struct nightmare_local nightmare_get_local();nightmare_get_local referenced types:
struct nightmare_thread nightmare_get_thread();nightmare_get_thread referenced types:
Defines
Section titled “Defines”#define NIGHTMARE_THREAD_ENTRY(__name) static void __name(void *__arg)#define NIGHTMARE_RESET_FN_NAME(__name) __name##_reset#define NIGHTMARE_INIT_FN_NAME(__name) __name##_init#define NIGHTMARE_START_FN_NAME(__name) __name##_start#define NIGHTMARE_STOP_FN_NAME(__name) __name##_stop#define NIGHTMARE_SHUTDOWN_FN_NAME(__name) __name##_shutdown#define NIGHTMARE_REPORT_FN_NAME(__name) __name##_report#define NIGHTMARE_THREAD_ENTRY_INIT() \ (void) __arg; \ struct nightmare_test *SELF = nightmare_get_thread()->test; \ (void) SELF;#define NIGHTMARE_THREAD_ENTRY_EXIT() \ atomic_store(&nightmare_get_thread()->th, NULL)#define NIGHTMARE_FN_INIT() (void) SELF;#define NIGHTMARE_DEFINE_RESET(__name) \ static void NIGHTMARE_RESET_FN_NAME(__name)(struct nightmare_test * SELF)#define NIGHTMARE_DEFINE_INIT(__name) \ static void NIGHTMARE_INIT_FN_NAME(__name)(struct nightmare_test * SELF)#define NIGHTMARE_DEFINE_START(__name) \ static enum nightmare_test_error NIGHTMARE_START_FN_NAME(__name)( \ struct nightmare_test * SELF)#define NIGHTMARE_DEFINE_STOP(__name) \ static void NIGHTMARE_STOP_FN_NAME(__name)(struct nightmare_test * SELF)#define NIGHTMARE_DEFINE_SHUTDOWN(__name) \ static void NIGHTMARE_SHUTDOWN_FN_NAME(__name)(struct nightmare_test * SELF)#define NIGHTMARE_DEFINE_REPORT(__name) \ static void NIGHTMARE_REPORT_FN_NAME(__name)( \ struct nightmare_test * SELF, struct nightmare_report * REPORT)#define NIGHTMARE_IMPL_RESET(__name) NIGHTMARE_DEFINE_RESET(__name)#define NIGHTMARE_IMPL_INIT(__name) NIGHTMARE_DEFINE_INIT(__name)#define NIGHTMARE_IMPL_START(__name) NIGHTMARE_DEFINE_START(__name)#define NIGHTMARE_IMPL_STOP(__name) NIGHTMARE_DEFINE_STOP(__name)#define NIGHTMARE_IMPL_SHUTDOWN(__name) NIGHTMARE_DEFINE_SHUTDOWN(__name)#define NIGHTMARE_IMPL_REPORT(__name) NIGHTMARE_DEFINE_REPORT(__name)#define NIGHTMARE_RETURN_ERROR(__err) \ do { \ atomic_store(&SELF->error, __err); \ return __err; \ } while (0)#define NIGHTMARE_SET_STATE(__nm, __state) \ do { \ atomic_store(&__nm->state, __state); \ } while (0)#define NIGHTMARE_ASSERT(cond) \ do { \ if (!(cond)) \ NIGHTMARE_RETURN_ERROR(NIGHTMARE_ERR_FAIL); \ } while (0)#define NIGHTMARE_PROGRESS() nightmare_kick(SELF->watchdog)#define NIGHTMARE_ASSERT_EQ(a, b) NIGHTMARE_ASSERT((a) == (b))NIGHTMARE_DEFINE_TEST(__name, __runtime_ms, __threads)
Section titled “NIGHTMARE_DEFINE_TEST(__name, __runtime_ms, __threads)”#define NIGHTMARE_DEFINE_TEST(__name, __runtime_ms, __threads) \ static struct nightmare_test __nightmare_test_##name \ __attribute__((section(".kernel_nightmare_tests"), used)) = { \ .name = #__name, \ .default_runtime_ms = __runtime_ms, \ .default_threads = __threads, \ .state = NIGHTMARE_UNINIT, \ .error = NIGHTMARE_ERR_OK, \ .roles = {0}, \ .role_count = 0, \ .reset = NIGHTMARE_RESET_FN_NAME(__name), \ .init = NIGHTMARE_INIT_FN_NAME(__name), \ .start = NIGHTMARE_START_FN_NAME(__name), \ .stop = NIGHTMARE_STOP_FN_NAME(__name), \ .shutdown = NIGHTMARE_SHUTDOWN_FN_NAME(__name), \ .report = NIGHTMARE_REPORT_FN_NAME(__name), \ }#define NIGHTMARE_ADD_MESSAGE(msg) \ do { \ SELF->messages = krealloc(SELF->messages, \ sizeof(char *) * ++SELF->message_count, ); \ SELF->messages[SELF->message_count - 1] = msg; \ } while (0)