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
//! Shared test-support harness for Cabin's integration test
//! binaries (`cli.rs`, `cabin_examples.rs`).
//!
//! This module exists so the `cabin()` command builder — and in
//! particular its environment-scrub list, which is the harness's
//! reproducibility contract — lives in exactly one place. Each test
//! binary declares `mod common;` and the file is compiled as a
//! private submodule of that binary (Cargo does not treat
//! `tests/common/mod.rs` as its own test target).
use Stdio;
use Command;
/// `Command` builder pointed at the test-built `cabin` binary, with
/// the full environment scrub every integration test relies on so a
/// test only ever sees the inputs it sets explicitly.
///
/// The env-scrub list below is the harness's correctness contract:
/// toolchain / wrapper / build-flag / cache / pkg-config / color
/// leaks are the most common reason a test that passes locally fails
/// in CI (or vice versa). Tests that exercise env precedence opt back
/// in by calling `.env(KEY, VALUE)` *after* this helper — `assert_cmd`
/// applies env mutations in declaration order, so a later `.env(...)`
/// overrides this `.env_remove(...)`.
/// Pin `CABIN_CACHE_HOME` to a deterministic temp path. Tests
/// routinely strip `HOME` for config isolation, which would
/// otherwise leave the user-global cache fallback
/// (`$CABIN_CACHE_HOME` ▶ `$XDG_CACHE_HOME/cabin` ▶
/// `$HOME/.cache/cabin`) with nothing to resolve to in CI,
/// where `XDG_CACHE_HOME` is unset. The cache is
/// content-addressed, so parallel writers to the same path are
/// safe. Tests that observe cache state still pass an explicit
/// `--cache-dir`, which takes precedence.
/// Whether Ninja is available on `PATH`. Cabin invokes Ninja
/// directly for every `cabin build` / `cabin test` integration
/// test that produces real artifacts; tests gate on this
/// helper to skip cleanly on environments without it.
/// Whether at least one of Cabin's documented C compiler
/// fallbacks is on `PATH` (`cc` / `clang` / `gcc`). Tests that
/// compile `.c` translation units gate on this helper so they
/// do not silently fall through to a `MissingCCompiler` error
/// at planner time on a system that has only a C++ compiler.
/// Whether at least one of Cabin's documented C++ compiler
/// fallbacks is on `PATH` (`c++` / `clang++` / `g++`).
/// Whether the integration tests that build C++ targets via
/// real Ninja can run. Use this for tests that link only C++
/// translation units. Tests that touch C must use
/// [`c_and_cxx_build_tools_available`] instead.
/// Whether the integration tests that build *both* C/C++
/// targets via real Ninja can run. Required by every test that
/// compiles `.c` sources alongside C++ sources, and by pure-C
/// tests (Cabin still requires a C++ compiler at toolchain
/// resolution time even when only C is built).