1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
//! The one way a test says it did not run.
//!
//! Invariant: a suite that skips does it through [`skipping`], so exactly one
//! phrase reaches the classifier and exactly one lever turns a skip into a
//! failure. A suite that prints its own sentence is invisible to
//! `inillucent-testrun --strict`, and a suite that returns without printing is
//! invisible to everything.
//!
//! It also holds [`remove_database`], the one way a test clears a scratch
//! database before reusing its path, because a database here is a file plus
//! numbered log segments and every copy of that list elsewhere forgot the
//! segments.
//!
//! **Why this is in the bottom crate rather than in the test harness
//! (task-1969, 4.6).** `inillucent_compat::differential::skipping` was the
//! original home, and three crates could not reach it: the layering contract
//! refuses a production crate a dependency on the harness, even as a
//! dev-dependency, because that puts harness code in the engine's test surface.
//! So `inillucent-driver`, `inillucent-cli` and `inillucent-tree` each printed
//! their own `eprintln!`, `inillucent-remote` kept a private copy of this
//! function, and all four were dropped by `testrun.rs`'s classifier because the
//! phrase alone is not the signal it reads. `inillucent-base` is below every one
//! of them, so the helper reaches them all without an upward edge, and the
//! compat helper now delegates here rather than owning a second copy.
//!
//! The module is behind `#[cfg(any(test, feature = "testing"))]` so a shipped
//! build of `inillucent-base` does not carry it. Each consumer turns the feature
//! on from its own `[dev-dependencies]`, which is on for that crate's test
//! targets and off everywhere else.
// **This module may panic, and the crate-level deny is why the allow is here.**
// Panicking is the function's purpose: under `INILLUCENT_STRICT` a skip has to
// fail the test that skipped, because that is what names the case rather than
// the binary. The bans at the crate root exist to keep panics out of paths that
// read persistent bytes, and this path reads an environment variable.
/// What a strict run's skip panic says after the marker.
///
/// **A skip and a failure are different things and the report has to keep them
/// apart (task-1932, H10).** `--strict` makes a skip fail the test, which is
/// what names the case rather than the binary - but a suite that skipped did
/// not evidence a problem, it evidenced nothing, and listing it under FAILED
/// would put a second wrong label on the same event. `inillucent-testrun`'s
/// `missing_prerequisites` reads this sentinel to tell one from the other: a
/// target whose every failure carries it is hollow, and a target with even one
/// failure that does not is a failure.
pub const STRICT_SKIP: &str = " - and this run is strict, so a skip is a failure";
/// The marker every skip message ends with.
///
/// `tests/inillucent-testing-tdd.md` ยง9 asks for one phrase and
/// `inillucent-testrun`'s classifier matches this one. It is a constant so that
/// a test can assert on it rather than on a literal typed twice.
pub const MARKER: &str = "; skipping";
/// Says why a case did not run, and fails the case when the run is strict.
///
/// **One marker and one decision, in one place (task-1932, H10; task-1969,
/// 4.6).** Every skip site in the workspace ends its message with `; skipping`,
/// which is what `testrun`'s classifier matches. Before task-1932 there were
/// three phrasings and a list of six substrings trying to catch them; before
/// task-1969 there were four crates that could not reach the helper at all and
/// printed the phrase without the panic, so `--strict` dropped them.
///
/// `INILLUCENT_STRICT` makes the skip a failure of the test rather than a
/// classification of the binary. `inillucent-testrun --strict` sets it, and the
/// panic then names the test and the thing that is missing. That matters most
/// in a binary that runs other tests, because a skip of one case there was
/// invisible to `--strict` by both routes.
///
/// @param reason - what is missing, without the marker
/// Removes a database file and every file the engine or SQLite keeps beside it.
///
/// **The log is not one file (task-2110, bugs 1 and 7).** The engine writes its
/// log as numbered segments, `<name>-wal.0000000001` and on, and the helpers
/// this replaces removed `<name>-wal` and nothing else. A test that reuses a
/// scratch path then opened a new database beside the last run's segments, and
/// the engine replayed them into it: `new_engine_surface` failed with "table t
/// already exists" after any run of it that had been stopped partway, which
/// read as a defect in whatever the branch had changed. The segments are found
/// by listing the directory because their numbers are not predictable - a chain
/// can start anywhere once a checkpoint has removed its early segments.
///
/// Every removal ignores a missing file, so this is also what a test calls
/// before it creates a database.
///
/// @param path - the database file