Skip to content

Commit 5d92352

Browse files
committed
testing: a case sees only the payloads it states, and one CI criterion reads narration from stderr
Two failures from the other platforms, with one cause each. The kit left the real build's `MCPP_XPKG_*` in the environment. These cases run inside a build program, which the engine gives one `_DIR`, `_PROGRAM` and `_SOURCE` per payload its package declares -- including `pending`, for a payload declared `provision = "on-request"` that nothing has asked for. Eight vcpkg cases therefore asked for `xim:vcpkg` and planned nothing wherever the payload was not installed, and passed wherever it was: 19 of 27 on macOS arm64 and on Windows, 27 of 27 here. The keys are derived from package names, so they are enumerated rather than listed. Measured both ways on the same binary with the inherited value present: 19 of 27 before, 27 of 27 after. The spirv fixture's step asserted on a status line while capturing stdout alone. mcpp writes narration to standard error from 2026.10.1.1, so the log was empty and the step reported that the rule had not run while it had.
1 parent e042567 commit 5d92352

2 files changed

Lines changed: 40 additions & 2 deletions

File tree

‎.github/workflows/ci.yml‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -746,7 +746,11 @@ jobs:
746746
grep -v '^[[:space:]]*#' mcpp.toml | grep -n 'host-module'
747747
exit 1
748748
fi
749-
"$MCPP" build | tee build.log
749+
# `2>&1`, BECAUSE THE LINE THIS ASSERTS ON IS NARRATION. mcpp writes
750+
# every status line to standard error from 2026.10.1.1 (the output
751+
# streams design), so a step that captures stdout alone reads an empty
752+
# log and reports that the rule did not run while it did.
753+
"$MCPP" build 2>&1 | tee build.log
750754
grep -q 'Rules mcpp.rules.spirv' build.log \
751755
|| { echo "FAIL: the build did not report which rule it ran"; exit 1; }
752756
"$MCPP" run | tee run.log

‎src/testing.cppm‎

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@
3939

4040
module;
4141
#include <stdlib.h>
42+
#if !defined(_WIN32)
43+
#include <unistd.h> // environ -- the kit clears the real build's MCPP_XPKG_*
44+
#endif
4245

4346
export module mcpp.plugins.testing;
4447

@@ -71,10 +74,39 @@ inline constexpr std::string_view kKeys[] = {
7174
"MCPP_TOOL_ENV", "MCPP_TOOLSET_IDENTITY", "MCPP_MSVC_INSTANCE_DIR", "MCPP_NINJA",
7275
"MCPP_CXX_RUNTIME", "MCPP_MSVC_CRT_LINKAGE",
7376
// Sources (0.19.0, mcpp#755): which phase is running. The per-payload keys
74-
// are stated by `context::xpkg*`, which names them itself.
77+
// are stated by `context::xpkg*`, which names them itself, and the ones the
78+
// real build set are cleared by `inherited_payload_keys`.
7579
"MCPP_PHASE",
7680
};
7781

82+
// EVERY `MCPP_XPKG_*` THE REAL BUILD SET, so that a case sees only the payloads
83+
// it states. These cases run inside a build program, and the engine gives that
84+
// program one `_DIR`, `_PROGRAM` and `_SOURCE` for each payload its package
85+
// declares -- `pending` among them, for a payload declared
86+
// `provision = "on-request"` and not installed. Inherited, that made the eight
87+
// vcpkg cases ask for `xim:vcpkg` and plan nothing on a host where it was not
88+
// installed, while passing on one where it was; the symptom was a plan with the
89+
// prefix mapping but no install action (measured on macOS arm64, 0.19.0).
90+
//
91+
// Enumerated rather than listed: the keys are derived from package names, so no
92+
// fixed list can cover the next payload a member reads.
93+
inline std::vector<std::string> inherited_payload_keys() {
94+
#if defined(_WIN32)
95+
char** env = _environ;
96+
#else
97+
char** env = environ;
98+
#endif
99+
std::vector<std::string> out;
100+
for (char** e = env; e && *e; ++e) {
101+
std::string_view entry(*e);
102+
const auto eq = entry.find('=');
103+
if (eq == std::string_view::npos) continue;
104+
const auto name = entry.substr(0, eq);
105+
if (name.starts_with("MCPP_XPKG_")) out.emplace_back(name);
106+
}
107+
return out;
108+
}
109+
78110
inline std::string read_file(const std::filesystem::path& p) {
79111
std::ifstream in(p, std::ios::binary);
80112
return {std::istreambuf_iterator<char>(in), std::istreambuf_iterator<char>()};
@@ -293,6 +325,8 @@ inline int run(int argc, char** argv, std::span<const test_case> cases) {
293325
// The union of the keys any case states, beside the kit's own list.
294326
std::vector<std::string> keys;
295327
for (auto k : detail::kKeys) keys.emplace_back(k);
328+
for (auto& k : detail::inherited_payload_keys())
329+
if (std::ranges::find(keys, k) == keys.end()) keys.push_back(std::move(k));
296330
for (auto const& c : cases)
297331
for (auto const& kv : c.ctx.values)
298332
if (std::ranges::find(keys, kv.first) == keys.end()) keys.push_back(kv.first);

0 commit comments

Comments
 (0)