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
//! Shared by the integration tests that need a language toolchain.
/// Record that a test is being skipped, or fail if this environment promised
/// the toolchain would be there.
///
/// These tests skip on a machine without the toolchain, so a contributor
/// without Go or a JDK can still run the suite. That is exactly the property
/// that makes them worthless in CI unless something checks: a job whose
/// toolchain setup silently failed would skip every test and report success,
/// and the language would look verified while nothing had run.
///
/// CI sets `SUPERCOV_REQUIRE_GO=1` or `SUPERCOV_REQUIRE_JVM=1`, which turns
/// the skip into the failure it should be there.
/// Find a build tool or compiler, or `None` on a machine without it.
///
/// More than a PATH lookup, for two reasons. Homebrew's installs are not on a
/// non-login shell's PATH on macOS, which is where this suite is usually
/// developed. And on Windows `mvn` and `gradle` are `.cmd` scripts: Rust's
/// `Command` resolves a bare name to `.exe` and nothing else, so asking for
/// `mvn` there finds nothing at all and every JVM test would skip on the one
/// platform whose differences most deserve a test.
/// Whether the toolchain can build the fixture, deciding it by trying only
/// when the answer could change what happens.
///
/// These tests build the fixture once to learn whether its dependencies
/// resolve here, and skip when they do not — a cold cache with no network is a
/// real situation on someone's laptop. In CI it is not: `SUPERCOV_REQUIRE_*`
/// says skipping is forbidden, so a fixture that cannot build must fail the
/// job whether it is discovered now or a moment later. Asking anyway doubles
/// every Maven and Gradle invocation in the suite for an answer that cannot be
/// acted on.
/// A classpath from its entries.
///
/// The separator is a colon everywhere except Windows, where it is a
/// semicolon — a colon there is read as part of a drive letter, so every entry
/// after the first is lost and the compiler reports a package that plainly
/// exists as missing.
/// The major Java release a compiler supports, from its own `-version`.
///
/// A fixture may need a language feature older compilers do not have — record
/// patterns are Java 21 — and that is not the same as the toolchain being
/// absent. The require flag exists to catch a missing toolchain; a present one
/// that is simply older should skip the cases it cannot express and run the
/// rest.
/// Serialise the tests that drive a real Maven or Gradle build.
///
/// `npm run test:jvm` passes `--test-threads=1`, which says plainly that these
/// cannot run alongside each other -- but `cargo test --workspace` does not,
/// and three CI jobs plus `release:check` use exactly that. On macOS and Linux
/// the parallel run is merely faster; on Windows it stops. The filesystem job
/// went from eleven minutes on main to over seventy on the branch that added
/// these tests, on both Windows runners, while macOS ran the same command in
/// eleven and Linux in seven.
///
/// A flag on one script cannot protect a command someone else runs, so the
/// rule belongs in the test rather than in the way it is invoked. Cargo runs
/// test binaries one at a time, so a lock per process is enough.
///
/// A panicking test poisons the mutex; the guard is taken anyway, because a
/// failed test must not turn every later one into a second failure that hides
/// it.