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
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
use *;
use crateMutexExt;
// ─── SYNTHETIC-TOPOLOGY OFFSET CONVENTION ────────────────────
//
// Tests in this module that touch real `/tmp/ktstr-llc-*.lock`
// files choose LLC indices in the 90000..=99999 range to avoid
// collision with any real host's LLC count (modern server
// sockets top out around 1024 LLCs). Per-test offsets are
// subdivided by 100:
// 90000-90999: acquire_resource_locks / per-CPU path tests
// 91000-91999: acquire_cpu_locks tests
// 92000-92999: reserved
// 93000-93999: acquire_llc_plan (none-cap, EX-peer, SH-peer)
// — each sub-test picks its own sub-range
// (93000-93099, 93100-93199, …) so leaked state
// from a panicking prior test doesn't cross-
// contaminate.
// 94000-94099: acquire_llc_plan cross-node spill (mems union
// invariant, I1).
// 94100-99999: reserved for future LLC-level tests.
// Tests that build a HostTopology in memory but do NOT touch
// real /tmp paths use small indices (0, 1, 2, …) because no
// cross-process collision is possible.
//
// When adding a new test that flocks under /tmp, pick an
// unused 100-entry sub-range in 90000-99999 and document the
// claim in a comment at the test site so the next author
// doesn't accidentally re-use it.
// ─────────────────────────────────────────────────────────────
/// Collect the distinct host NUMA node IDs the given CPUs belong
/// to. Tests that assert "these N CPUs all live on one NUMA node"
/// (or span two) route through this helper so the CPU → node
/// lookup and the single-CPU default stay in one place rather
/// than duplicating the same closure across every assertion
/// site.
// -- synthetic topology mapping tests --
/// Backwards-compat helper: builds a synthetic HostTopology from
/// LLC-group CPU lists, assigning each group to a NUMA node equal
/// to its positional index (LLC 0 → node 0, LLC 1 → node 1, …).
/// Delegates to [`HostTopology::new_for_tests`].
///
/// Kept as a thin wrapper so the many existing call sites that
/// pass only CPU lists (no explicit NUMA info) don't have to
/// thread node ids through their parameter lists.
// -- NUMA-aware pinning tests --
/// Backwards-compat helper: builds a synthetic HostTopology from
/// `(numa_node, cpu_list)` pairs. Delegates to
/// [`HostTopology::new_for_tests`], flipping the tuple order to
/// `(cpus, node)` so the underlying constructor presents a
/// consistent `(cpus, node)` shape to callers that build pairs
/// directly.
/// RAII guard for a per-test LLC lockfile path prefix. Installs
/// a `{tempdir}/llc-` prefix into [`LLC_LOCK_PREFIX_OVERRIDE`]
/// on construction and unsets it on Drop. Two parallel tests
/// using this guard each get their own tempdir, so their
/// `acquire_llc_plan` lockfiles can't collide. Eliminates the
/// 90K+ empty `LlcGroup` padding that earlier tests used to
/// sidestep collision with real host LLC indices.
///
/// Uses [`tempfile::TempDir`] so cleanup runs via RAII on panic
/// — a panicking test can't leak `/tmp` lockfiles into other
/// test runs.
/// RAII guard for a per-test CPU lockfile path prefix. Mirrors
/// [`LlcLockPrefixGuard`] for the CPU-lock side of the
/// `acquire_resource_locks` path. See that struct's doc for the
/// per-test-tempdir + panic-safe-cleanup rationale.
/// RAII bundle that installs BOTH [`LlcLockPrefixGuard`] AND
/// [`CpuLockPrefixGuard`] in one call. Used by any test that hits
/// both LLC and CPU lockfile families — `acquire_resource_locks`
/// (LLC + per-CPU), `acquire_cpu_locks` (CPU + the LLC shared lock
/// from `acquire_llc_shared_locks`), or any future helper that
/// composes the two. Each test gets its own per-tempdir prefix for
/// both lockfile families, so cross-run / cross-process
/// collisions on `/tmp/ktstr-llc-*.lock` and `/tmp/ktstr-cpu-*.lock`
/// cannot occur. When in doubt about which guard to pick, default
/// to this bundle — over-provisioning a tempdir is cheap and is
/// always safe; under-provisioning leaks production-path test
/// collisions.
/// RAII guard for a per-test override of
/// [`host_allowed_cpus`]'s return value via
/// [`ALLOWED_CPUS_OVERRIDE`]. Lets tests pin the 30%-default and
/// allowed-cpu filtering math to a known input regardless of
/// what the CI runner's real sched_getaffinity returns. Unset on
/// Drop so a panicking test cannot leak state across the suite.
;
/// Destructure a `LockOutcome::Acquired { llc_offset, locks }` or
/// panic with a stable diagnostic on `Unavailable`. `ctx` is an
/// optional site-specific clause that the panic message inlines
/// after "expected Acquired" with a single leading space:
/// `None` produces `"expected Acquired, got Unavailable: ..."`,
/// `Some("in cargo-test mode")` produces
/// `"expected Acquired in cargo-test mode, got Unavailable: ..."`.
/// The helper owns the space-prefix so callers cannot accidentally
/// produce `"expected Acquiredfoo"` by forgetting it.
///
/// See [`expect_unavailable`] for tests that expect the
/// `Unavailable` branch instead.
/// Destructure a `LockOutcome::Unavailable(reason)` for tests that
/// EXPECT the unavailable branch and assert on the reason string.
/// Panics on `Acquired`. `ctx` follows the same convention as
/// [`unwrap_acquired`]: `None` produces
/// `"expected Unavailable, got Acquired"`,
/// `Some("while lock is held")` produces
/// `"expected Unavailable while lock is held, got Acquired"`.
// ---------------------------------------------------------------
// CpuCap — construction, env resolution, acquire-time bounding
// ---------------------------------------------------------------
/// Serialize KTSTR_CPU_CAP env-var mutation across test threads.
/// std::env::set_var is process-wide (unsafe in edition 2024);
/// parallel tests would race if each mutated the same variable
/// without coordination. Every env-touching test below takes
/// this mutex for the duration of the test body.
/// RAII guard for scoped `std::env::set_var` mutation inside a
/// test. On construction sets the variable to `value`; on Drop
/// removes it regardless of whether the test body panicked or
/// returned early. Pairs with [`env_lock`] — callers take the
/// mutex first, then mint the guard, so two env-touching tests
/// never observe each other's intermediate state.
///
/// Replaces the bare `unsafe { set_var(..) } ... unsafe {
/// remove_var(..) }` pairs that appeared in every env-set test:
/// an early return or panic between the set and the remove used
/// to leak the env var into subsequent tests serialized on the
/// same mutex. `Drop` closes that leak.
// ---------------------------------------------------------------
// NUMA primitives — host_llcs_by_numa_node / with_capacity /
// sorted_by_distance
// ---------------------------------------------------------------
/// Backwards-compat helper: forwards to
/// [`HostTopology::new_for_tests`]. Kept so existing tests that
/// reference `synth_host_topo` don't need to be renamed in lock-
/// step with the consolidation — the single authoritative
/// constructor is `new_for_tests`, this and
/// [`synthetic_topo`] / [`synthetic_topo_numa`] are thin adapters
/// over it.
// Test groups extracted from the original flat tests.rs; the helper fns
// and RAII scaffolding structs above stay here so every group reaches
// them as a child module via `use super::*`.