Skip to content

Commit fd330c2

Browse files
committed
test(e2e): 220 自带一个 farm,不再靠机器碰巧装了什么
原来的那一半只能测「这台机器恰好有、而载荷没有」的库。CI 的 SubOS 里没有这种库, 于是它 SKIP —— 最需要它的地方,那条决定性断言从来没跑过。 新增 half 0:在测试自己的临时目录里建一个工程级具名 SubOS (`<proj>/.mcpp/.xlings/subos/probe/lib`),把 mcpp 自己构建的探针 .so 放进去, 然后断言产物**真的跑起来**。不写任何共享状态 —— 往本机真实 SubOS 里塞探针库正是 「一个测试的失败源于上一次运行」那类缺陷,这套件已经为它付过一次学费。 `allow_host_libs` 是必需的,而且不是绕开:没有 subos_info 的 SubOS 说不出自己的 runtime,mcpp 拒绝猜 libc 版本,hermeticity 检查如实报告回落宿主。那条声明就是 「对,我是故意的」。 顺带把 219 与两份文档里那句「farm 是最后一条」精确成「最后一条**绝对路径**」。
1 parent 1c58f22 commit fd330c2

1 file changed

Lines changed: 81 additions & 0 deletions

File tree

tests/e2e/220_farm_only_library_runs.sh

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,87 @@ set -e
2525
TMP=$(mktemp -d)
2626
trap "rm -rf $TMP" EXIT
2727

28+
# ── half 0: a farm this test OWNS ───────────────────────────────────────────
29+
#
30+
# The opportunistic half below can only measure what this machine happens to
31+
# have installed, and on a CI SubOS that is nothing the payloads do not already
32+
# provide — so it skips, and the decisive assertion never runs where it matters
33+
# most. This half builds the condition instead of hoping for it.
34+
#
35+
# A project-local named SubOS (`<project>/.mcpp/.xlings/subos/<name>`) is a real
36+
# SubOS as far as the binding is concerned, and it lives entirely inside this
37+
# test's temp directory. Nothing shared is written — writing a probe library
38+
# into the machine's actual SubOS would be the "one test's failure comes from
39+
# the previous run" defect this suite has already paid for once.
40+
#
41+
# `allow_host_libs` is required and is not a workaround: a SubOS with no
42+
# `subos_info` names no runtime, so mcpp declines payload-first rather than
43+
# guessing a libc, and the hermeticity check correctly reports the host
44+
# fallback. The declaration is what says "yes, I meant that".
45+
mkdir -p "$TMP/ownfarm/src" "$TMP/ownfarm/.mcpp/.xlings/subos/probe/lib"
46+
cd "$TMP/ownfarm"
47+
FARM_OWN="$TMP/ownfarm/.mcpp/.xlings/subos/probe/lib"
48+
49+
# The probe library, built by mcpp itself so it matches the toolchain exactly.
50+
mkdir -p "$TMP/probelib/src"
51+
cat > "$TMP/probelib/mcpp.toml" <<'EOF'
52+
[package]
53+
name = "probelib"
54+
version = "0.1.0"
55+
56+
[targets.mcppfarmprobe]
57+
kind = "shared"
58+
EOF
59+
cat > "$TMP/probelib/src/probe.cppm" <<'EOF'
60+
export module probelib.probe;
61+
export int mcpp_farm_probe() { return 42; }
62+
EOF
63+
( cd "$TMP/probelib" && "$MCPP" build > build.log 2>&1 ) || {
64+
echo "FAIL: probe library build"; cat "$TMP/probelib/build.log"; exit 1; }
65+
PROBE_SO="$(ls "$TMP"/probelib/target/*/*/bin/libmcppfarmprobe.so | head -1)"
66+
[[ -n "$PROBE_SO" ]] || { echo "FAIL: no probe .so"; ls -R "$TMP/probelib/target" | head -20; exit 1; }
67+
cp "$PROBE_SO" "$FARM_OWN/libmcppfarmprobe.so"
68+
69+
cat > mcpp.toml <<EOF
70+
[package]
71+
name = "ownfarm"
72+
version = "0.1.0"
73+
74+
[xlings]
75+
subos = "probe"
76+
77+
[build]
78+
allow_host_libs = true
79+
ldflags = ["-Wl,--no-as-needed", "-L$FARM_OWN", "-lmcppfarmprobe", "-Wl,--as-needed"]
80+
EOF
81+
echo 'int main() { return 0; }' > src/main.cpp
82+
"$MCPP" build > build.log 2>&1 || {
83+
echo "FAIL: build against a SubOS-provided library"; cat build.log; exit 1; }
84+
85+
OWN_BIN="$(ls target/*/*/bin/ownfarm | head -1)"
86+
[[ -n "$OWN_BIN" ]] || { echo "FAIL: no artifact"; exit 1; }
87+
88+
# The library exists ONLY under the SubOS view. `-L` got it linked; only the
89+
# farm entry in DT_RPATH can get it loaded — nothing else on the search path
90+
# has ever heard of it.
91+
"$OWN_BIN"
92+
rc=$?
93+
[[ $rc -eq 0 ]] || {
94+
echo "FAIL: an artifact could not load a library its own SubOS provides (exit $rc)"
95+
echo " farm: $FARM_OWN"
96+
echo " This is the run-time half of the closure: the SubOS is the"
97+
echo " sysroot at link time and must be on the search path at load time."
98+
exit 1
99+
}
100+
echo "ran: exit 0 against a library only this SubOS provides"
101+
# Measured against the previous release (2026.8.10.3) this half fails at the
102+
# BINDING — an undeclared SubOS was a hard error there — so it exercises both
103+
# halves of this change together rather than isolating the farm. The half below
104+
# isolates the farm alone, when the machine has a populated SubOS to isolate it
105+
# with; on the machine this was written on, `-lEGL` linked and exited 127 before
106+
# the change and exits 0 after.
107+
cd "$TMP"
108+
28109
# ── find a library only the farm provides ───────────────────────────────────
29110
#
30111
# Derived from the recorded closure rather than hardcoded to libGL: CI SubOSes

0 commit comments

Comments
 (0)