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
//! Test-side backend for the diagnostics production already emits.
//!
//! Production instruments its solvers through the `log` facade — the BMS
//! intercept-solve counters, the GL-ladder rung histogram, the cell-moment cache
//! stats, the certificate-bound discriminator. Every one of those is a
//! `log::info!`, and **the `log` facade drops every record until some binary
//! installs a backend**. No test binary in this workspace installed one, so all
//! of that instrumentation has been running and producing nothing, in unit tests
//! and integration tests alike. Two lanes independently spent hours re-deriving
//! facts these lines already carried (#2472's non-terminating marginal-slope
//! cluster; the `[CERTIFICATE-BOUND]` discriminator). This module is the missing
//! half.
//!
//! It lives in `gam-runtime` rather than `gam-test-support` for the reason that
//! crate's own header gives: a helper owning no model-layer type belongs in a
//! leaf, so depending on it does not drag the solver stack into an unrelated
//! test build. `gam-runtime` already owns the observability modules (`span`,
//! `process_monitor`, `loop_progress`) and already depends on `log`.
//! `gam-test-support` re-exports it for consumers that use that path.
//!
//! Following the workspace convention for `test_support` modules, this is a
//! plain always-compiled `pub mod`: a `cfg(test)` gate would make it invisible
//! to exactly the downstream integration binaries that need it.
use Write;
use Once;
use ;
/// Records that could not be written to stderr.
///
/// A logger that silently fails to emit is the exact defect this module exists
/// to remove, so the failures are counted rather than discarded — panicking
/// inside `log::Log::log` is not an option (it runs from arbitrary call sites,
/// including ones holding locks), but going quiet is what got us here.
/// [`diagnostic_write_failures`] lets a caller assert its diagnostics actually
/// reached the stream.
static WRITE_FAILURES: AtomicUsize = new;
/// Writes every record at or above `Info` straight to stderr, one line at a
/// time, flushing each.
///
/// Per-record flushing is the whole point rather than an inefficiency: the
/// diagnostics worth reading belong to runs that do not finish. A test killed at
/// the per-test cap, or a fit abandoned after hours, must leave its trace
/// behind — buffering it into a summary that never prints is how 17 core-hours
/// produced zero lines.
;
static DIAGNOSTIC_LOGGER: StderrDiagnosticLogger = StderrDiagnosticLogger;
static INSTALL_ONCE: Once = new;
/// Install the stderr diagnostic backend for this process, once.
///
/// Call it from any test that wants to read production's `log::info!` output.
/// It is safe to call from every test in a binary and from several binaries at
/// once: `log::set_logger` may only be called once per process, so the work is
/// behind a [`Once`], and a losing call is treated as success — some other
/// backend is already receiving the records, which is the outcome the caller
/// wanted.
///
/// The level is chosen in code (`Info`) and is deliberately not configurable
/// from the environment: the workspace bans environment-dependent behaviour, and
/// a diagnostic you have to know an env var to see is one nobody sees.
/// How many records this backend failed to write.
///
/// Nonzero means diagnostics were lost, which for a run being read for its
/// instrumentation is a failed measurement rather than a cosmetic problem.
/// Replay a cgroup-constrained memory environment without needing the machine
/// to be in it.
///
/// The two knobs are deliberately the two that #2684 conflated:
///
/// * `cgroup_limit_bytes` is the job's hard ceiling — the CAPACITY. It is a
/// property of how the process was launched and does not move while it runs.
/// * `cgroup_current_bytes` is how much of that ceiling is charged RIGHT NOW —
/// the load. It moves continuously, and on any cgroup that has done file I/O
/// it sits near the ceiling because page cache fills whatever is free.
///
/// Holding the first fixed while sweeping the second is what lets a test ask
/// "does this decision depend on ambient load?" as an assertion instead of an
/// argument. The returned observation is built by the same constructor the live
/// probe uses, so its derived `working_set`/`available` arithmetic is the
/// shipped arithmetic and not a second implementation that could agree with the
/// first only by luck.
///
/// The host numbers are taken as parameters too, because the host's own free
/// memory is the other half of the conflation: the incident this exists for had
/// hundreds of GB free on the host while the job's cgroup reported kilobytes.