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
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
//! Simulation assertion macros — [`always!`](crate::always) /
//! [`sometimes!`](crate::sometimes) — plus the per-run non-vacuity registry
//! (sim-testing W6, issue #1797).
//!
//! This is the **semantic core** of the op-driver stack: the two assertions a
//! sim-test author reaches for, and the thread-local reachability registry the
//! forthcoming `sim-sweep` binary aggregates across seeds to prove a green run
//! was *non-vacuous* (every reachability target a run claimed to observe was
//! actually satisfied at least once).
//!
//! # The two assertions
//!
//! - [`always!`](crate::always) is a **hard invariant**. `always!(cond)` (or
//! `always!(cond, "fmt {}", args…)`) panics the instant `cond` is false. Under
//! [`#[sim_test]`](crate::sim_test) the panic is caught, the copy-pasteable
//! `AUTUMN_SIM_SEED=…` replay line is printed, and the test fails — so an
//! `always!` violation reproduces bit-for-bit. The panic message is
//! deliberately greppable (`always! invariant violated`) and carries the
//! stringified condition plus any caller message.
//!
//! - [`sometimes!`](crate::sometimes) is a **reachability target**.
//! `sometimes!(cond, "label")` records `"label"` as *observed* in the per-run
//! registry, and marks it *satisfied* when `cond` is true. Within a single
//! seed run a reachability target may legitimately never fire, so a
//! [`#[sim_test]`](crate::sim_test) does **not** auto-fail on an unsatisfied
//! label — that would make reachability assertions useless. Instead the
//! registry is exposed for the sweep to aggregate across many seeds and fail
//! the sweep if some label was seen but never satisfied by *any* seed
//! (non-vacuous green). For an explicit single-run check, call
//! [`assert_all_sometimes_satisfied`].
//!
//! # Registry model (thread-local, deterministic)
//!
//! The registry is a thread-local pair of [`BTreeSet`]s (observed / satisfied),
//! keyed by label string. `BTreeSet` (not `HashSet`) keeps panic-message and
//! snapshot ordering stable across runs, which the determinism contract
//! requires.
//!
//! Thread-local is the correct isolation boundary under the test harness: libtest
//! runs each `#[test]` on its own thread, so two tests touching the global
//! registry concurrently never interfere — each observes its own thread's
//! registry. [`Sim::from_seed`](crate::sim::Sim::from_seed) resets the current
//! thread's registry so every seed run starts clean, and the sweep (which runs
//! seeds sequentially on one thread) reads [`sometimes_snapshot`] after each seed
//! before resetting for the next.
use RefCell;
use BTreeSet;
thread_local!
/// The per-run reachability registry backing [`sometimes!`](crate::sometimes).
///
/// Tracks two label sets: every label **observed** (a `sometimes!` was reached)
/// and the subset that was **satisfied** (its condition was true at least once).
/// A label that is observed but never satisfied is the non-vacuity signal the
/// sweep fails on.
/// Record a [`sometimes!`](crate::sometimes) observation on the current thread's
/// registry.
///
/// Hidden plumbing the [`sometimes!`](crate::sometimes) macro expands to — not a
/// stable API. Call the macro, not this function.
/// Reset the current thread's reachability registry to empty.
///
/// Called by [`Sim::from_seed`](crate::sim::Sim::from_seed) so each seed run
/// starts clean, and exposed for the sweep to reset between seeds after reading
/// its [`sometimes_snapshot`].
/// Snapshot the current thread's registry as `(observed, satisfied)` label sets.
///
/// The sweep reads this after each seed run to fold the seed's reachability into
/// its cross-seed aggregate before resetting for the next seed.
/// The labels observed but never satisfied on the current thread's registry
/// (stable sorted order).
///
/// Convenience over [`sometimes_snapshot`] for callers that only need the
/// non-vacuity gap.
/// Assert that every [`sometimes!`](crate::sometimes) label observed this run was
/// also satisfied at least once, panicking otherwise.
///
/// For explicit single-run non-vacuity checks. The cross-seed aggregation the
/// sweep performs is the more powerful form (a label may need many seeds to be
/// satisfied once), so a [`#[sim_test]`](crate::sim_test) body typically does
/// **not** call this directly.
///
/// # Panics
///
/// Panics, listing the never-satisfied labels in stable sorted order, if any
/// observed label was never satisfied.
/// Assert a **hard invariant** that must hold at this point in the simulation.
///
/// `always!(cond)` panics the instant `cond` is false; `always!(cond, "fmt {}",
/// args…)` appends a caller-formatted message. Under
/// [`#[sim_test]`](crate::sim_test) the panic is caught and the deterministic
/// `AUTUMN_SIM_SEED=…` replay line is printed, so a violation reproduces exactly.
/// The message always contains the greppable prefix `always! invariant violated`
/// and the stringified condition.
///
/// ```
/// use autumn_web::always;
///
/// always!(1 + 1 == 2);
/// let balance = 10;
/// always!(balance >= 0, "balance must never go negative, was {}", balance);
/// ```
/// Record a **reachability target** — an interesting state the simulation should
/// sometimes reach across seeds.
///
/// `sometimes!(cond, "label")` registers `"label"` as observed and marks it
/// satisfied when `cond` is true, evaluating `cond` exactly once. It never
/// panics and never fails the current run on its own — an unsatisfied label
/// fails the *sweep*, which aggregates reachability across many seeds (see the
/// [module docs](self)). Use [`assert_all_sometimes_satisfied`] for an explicit
/// single-run check.
///
/// ```
/// use autumn_web::sometimes;
///
/// let queued = 5;
/// sometimes!(queued > 0, "queue-was-non-empty");
/// sometimes!(queued > 100, "queue-hit-backpressure");
/// ```