include/nightmare_test.h View source View on GitHub
struct nightmare_role {
enum nightmare_role_type type;
const char *name;
size_t count;
void (*worker)(void *);
void *arg;
};
struct nightmare_watchdog {
atomic_uint last_progress;
time_t last_kick_ms;
};
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 {
const char *name;
struct nightmare_watchdog *watchdog;
time_t default_runtime_ms;
size_t default_threads;
_Atomic enum nightmare_state state;
_Atomic 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_local {
void *data;
size_t len;
};
struct nightmare_thread {
_Atomic (struct thread *) th;
struct nightmare_test *test;
enum nightmare_role_type role;
struct nightmare_local local;
};
struct nightmare_thread_group {
struct nightmare_thread *threads;
size_t count;
};
struct nightmare {
struct nightmare_test *test;
struct nightmare_thread *self;
struct nightmare_watchdog *watchdog;
};
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, const char *name, void (*worker)(void *), size_t count, void *arg);
bool nightmare_should_stop(void);
void nightmare_chaos_pause();
void nightmare_kick(struct nightmare_watchdog *w);
void nightmare_spawn_roles(struct nightmare_test * *, struct nightmare_thread_group * *);
void nightmare_join_roles(struct nightmare_thread_group * *);
enum nightmare_test_error nightmare_run(struct nightmare_test *t);
bool nightmare_watchdog_expired(struct nightmare_watchdog *w, time_t timeout_ms);
void nightmare_watchdog_init(struct nightmare_watchdog *w);
void nightmare_set_local(void *d, size_t l);
struct nightmare_local nightmare_get_local();
struct nightmare_thread nightmare_get_thread();
#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))
#define NIGHTMARE_DEFINE_TEST(__name, __runtime_ms, __threads) \
LINKER_SECTION_OBJECT(struct nightmare_test, nightmare_tests) \
__nightmare_test_##name = { \
.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)