1#include <log.h>
2#include <nightmare_test.h>
3#include <string.h>
4
5LOG_SITE_DECLARE_DEFAULT(nightmare);
6LOG_HANDLE_DECLARE_DEFAULT(nightmare);
7
8#define nightmare_log(lvl, fmt, ...) \
9 log(LOG_SITE(nightmare), LOG_HANDLE(nightmare), lvl, fmt, ##__VA_ARGS__)
10
11#define nightmare_err(fmt, ...) nightmare_log(LOG_ERROR, fmt, ##__VA_ARGS__)
12#define nightmare_warn(fmt, ...) nightmare_log(LOG_WARN, fmt, ##__VA_ARGS__)
13#define nightmare_info(fmt, ...) nightmare_log(LOG_INFO, fmt, ##__VA_ARGS__)
14#define nightmare_debug(fmt, ...) nightmare_log(LOG_DEBUG, fmt, ##__VA_ARGS__)
15#define nightmare_trace(fmt, ...) nightmare_log(LOG_TRACE, fmt, ##__VA_ARGS__)
16
17void nightmare_default_report_writer(struct nightmare_report *r, const char *c,
18 size_t s) {
19 size_t where_to_start = r->buffer_len;
20 r->buffer_len += s;
21 r->buffer = krealloc(r->buffer, r->buffer_len);
22 memcpy(r->buffer + where_to_start, c, s);
23}
24
25void nightmare_tests_start(void) {
26 struct nightmare_test *t;
27
28 for (t = __skernel_nightmare_tests; t < __ekernel_nightmare_tests; t++) {
29
30 struct nightmare_watchdog wd;
31 nightmare_watchdog_init(w: &wd);
32 t->watchdog = &wd;
33
34 NIGHTMARE_SET_STATE(t, NIGHTMARE_UNINIT);
35 if (t->reset)
36 t->reset(t);
37
38 if (t->init)
39 t->init(t);
40
41 NIGHTMARE_SET_STATE(t, NIGHTMARE_READY);
42
43 NIGHTMARE_SET_STATE(t, NIGHTMARE_RUNNING);
44 atomic_store(&t->error, NIGHTMARE_ERR_OK);
45
46 enum nightmare_test_error err = NIGHTMARE_ERR_OK;
47
48 if (t->start)
49 err = t->start(t);
50
51 atomic_store(&t->error, err);
52
53 if (err == NIGHTMARE_ERR_OK || err == NIGHTMARE_ERR_FAIL) {
54 if (t->stop)
55 t->stop(t);
56 } else {
57 if (t->shutdown)
58 t->shutdown(t);
59 }
60
61 NIGHTMARE_SET_STATE(t, NIGHTMARE_STOPPED);
62
63 struct nightmare_report rpt = {
64 .buffer = NULL,
65 .buffer_len = 0,
66 .write_fn = nightmare_default_report_writer,
67 .flags = 0,
68 };
69
70 if (t->report)
71 t->report(t, &rpt);
72
73 nightmare_info("test %-20s => %d\n", t->name, err);
74 }
75}
76
77static size_t nightmare_count_threads(struct nightmare_test *nt) {
78 size_t acc = 0;
79 for (size_t i = 0; i < nt->role_count; i++) {
80 acc += nt->roles[i].count;
81 }
82 return acc;
83}
84
85void nightmare_spawn_roles(struct nightmare_test *test,
86 struct nightmare_thread_group *group) {
87 group->threads = kmalloc(nightmare_count_threads(test) *
88 sizeof(struct nightmare_thread));
89
90 size_t g_idx = 0;
91 for (size_t i = 0; i < test->role_count; i++) {
92 struct nightmare_role *nr = &test->roles[i];
93 struct nightmare_thread *nt = &group->threads[g_idx];
94
95 for (size_t j = 0; j < nr->count; j++) {
96 nt->role = nr->type;
97 nt->test = test;
98 nt->th = thread_create(name: (char *) nr->name, entry_point: nr->worker, arg: nr->arg);
99 nt->th->private = nt;
100
101 thread_enqueue(t: nt->th);
102
103 g_idx++;
104 }
105 }
106}
107
108void nightmare_join_roles(struct nightmare_thread_group *ntg) {
109 for (size_t i = 0; i < ntg->count; i++)
110 if (atomic_load(&ntg->threads[i].th))
111 scheduler_yield();
112}
113