1#pragma once
2#include <atomic.h>
3#include <console/crash.h>
4#include <nightmare/nightmare.h>
5#include <nightmare/perturb.h>
6#include <stringify.h>
7#include <sync/event.h>
8#include <test/conc.h>
9#include <thread/queue.h>
10#include <time/timer.h>
11#include <watchdog.h>
12
13#define nightmare_panic(fmt, ...) \
14 do { \
15 char _nm_msg[CRASH_MSG_MAX]; \
16 snprintf(_nm_msg, sizeof(_nm_msg), fmt, ##__VA_ARGS__); \
17 crash_full(&(struct crash_context) { \
18 .source = CRASH_SOURCE_NIGHTMARE, \
19 .formats = CRASH_FMT_DEFAULT, \
20 .file = __FILE__, \
21 .line = __LINE__, \
22 .func = __func__, \
23 .msg = _nm_msg, \
24 }); \
25 } while (0)
26
27struct nightmare_cmdline_config {
28 const char *selector;
29 fx32_32_t intensity;
30 uint64_t seed;
31 bool seed_present;
32 enum nightmare_seed_mode seed_mode;
33 time_ms_t duration_ms;
34 time_ms_t drain_grace_ms;
35 time_ms_t stat_interval_ms;
36 time_ms_t stall_threshold_ms;
37 enum test_on_stall on_stall;
38 uint64_t boot_index;
39 const char *campaign_id;
40 struct cmdline_list perturb;
41 bool perturb_present;
42};
43
44#define NIGHTMARE_MAX_PERTURBERS 8
45
46struct nightmare_runtime {
47 struct nightmare_ctx ctx;
48
49 struct test_conc conc;
50
51 atomic_size_t finding_count;
52 atomic_bool terminal;
53 atomic_bool perturb_verdict_ready;
54 struct nightmare_verdict perturb_verdict;
55 char perturb_reason[64];
56 char perturb_msg[256];
57 size_t perturber_count;
58 const struct test_perturb_desc *perturbers[NIGHTMARE_MAX_PERTURBERS];
59 struct timer soft_timer;
60 struct timer hard_timer;
61 time_ms_t started_ms;
62 time_ms_t stat_interval_ms;
63 const char *campaign_id;
64 uint64_t boot_index;
65 char caps[256];
66};
67
68extern struct nightmare_runtime nightmare_runtime;
69extern struct test_liveness_state nightmare_liveness;
70
71void nightmare_publish_stop(enum test_stop reason);
72void nightmare_cmdline_get(struct nightmare_cmdline_config *config);
73void nightmare_thread_main(void *arg);
74void nightmare_heartbeat_main(void *arg);
75void nightmare_publish_perturb_verdict(struct nightmare_verdict verdict);
76bool nightmare_load_perturb_verdict(struct nightmare_verdict *out);
77enum nightmare_result
78nightmare_result_with_findings(enum nightmare_result result, size_t findings);
79struct nightmare_verdict
80nightmare_verdict_for_stop(struct nightmare_verdict verdict,
81 enum test_stop stop);
82
83STRINGIFY_DECLARE_ENUM(nightmare_result) {
84 switch (stringify_in) {
85 case NIGHTMARE_RESULT_OK: return "ok";
86 case NIGHTMARE_RESULT_FINDING: return "finding";
87 case NIGHTMARE_RESULT_FAIL: return "fail";
88 case NIGHTMARE_RESULT_STALL: return "stall";
89 case NIGHTMARE_RESULT_SKIP: return "skip";
90 default: cc_unreachable();
91 }
92}
93
94STRINGIFY_DECLARE(nightmare_skip_to_str, enum nightmare_skip_reason) {
95 switch (stringify_in) {
96 case NIGHTMARE_SKIP_NONE: return "none";
97 case NIGHTMARE_SKIP_NOT_COMPILED: return "not_compiled";
98 case NIGHTMARE_SKIP_NO_SUCH_NIGHTMARE: return "no_such_nightmare";
99 case NIGHTMARE_SKIP_NEEDS_SMP: return "needs_smp";
100 case NIGHTMARE_SKIP_NEEDS_PREEMPT: return "needs_preempt";
101 case NIGHTMARE_SKIP_NEEDS_ASAN: return "needs_asan";
102 case NIGHTMARE_SKIP_NEEDS_INJECT: return "needs_inject";
103 case NIGHTMARE_SKIP_RAM_LOW: return "ram_low";
104 case NIGHTMARE_SKIP_SEED_UNUSED: return "seed_unused";
105 case NIGHTMARE_SKIP_SEED_MISSING: return "seed_missing";
106 case NIGHTMARE_SKIP_SERVICE_MISSING: return "service_missing";
107 case NIGHTMARE_SKIP_PREPARE_REFUSED: return "prepare_refused";
108 default: return "unknown";
109 }
110}
111
112STRINGIFY_DECLARE_ENUM(nightmare_seed_policy) {
113 switch (stringify_in) {
114 case NIGHTMARE_SEED_IGNORED: return "ignored";
115 case NIGHTMARE_SEED_OPTIONAL: return "optional";
116 case NIGHTMARE_SEED_REQUIRED: return "required";
117 default: cc_unreachable();
118 }
119}
120
121STRINGIFY_DECLARE_ENUM(nightmare_seed_mode) {
122 switch (stringify_in) {
123 case NIGHTMARE_SEED_SPLIT: return "split";
124 case NIGHTMARE_SEED_SEEDFUL: return "seedful";
125 case NIGHTMARE_SEED_SEEDLESS: return "seedless";
126 default: cc_unreachable();
127 }
128}
129
130bool nightmare_liveness_start(time_ms_t threshold_ms,
131 enum test_on_stall policy);
132void nightmare_liveness_stop(void);
133void nightmare_liveness_poll(void);
134