Skip to content

Commit 9f17e35

Browse files
test: two failures the local filesystem was hiding
The container helper read the exit code by taking everything after its marker and parsing it as a number. stdout and stderr arrive on one stream there, and which lands last is buffering rather than order - so a run that writes a diagnostic to stderr can put it AFTER the marker, and the parse then swallows it. It failed on amd64 and passed on arm64 in the same run, which is the signature. The first line after the marker is what it needs, and that does not depend on interleaving. Pre-existing: any test using the helper could have hit it at any time. The symlink bound was mine. It caps the measurement to prove the walk did not follow the link, and 10,000 had no room left in it once entries are measured by what they occupy: on ext4 a three-entry tree is 12,288 bytes of blocks, while APFS reports none for a directory at all - so the same figure passed here and failed in CI. Raised to 50,000, which is an order of magnitude below the 100,000 sitting behind the link and four times above the floor. Reproduced rather than guessed at: run in a Linux container, a directory reports 8 blocks where the local one reports none. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 7ae3f43 commit 9f17e35

2 files changed

Lines changed: 18 additions & 2 deletions

File tree

cmd/flux-op/inspect_test.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,13 @@ func TestInspectFindsASymlinkAndDoesNotFollowIt(t *testing.T) {
6666
if !result.hasIrregular {
6767
t.Error("the symlink was not reported")
6868
}
69-
if result.bytes > 10000 {
69+
// Bounded well below the 100,000 bytes behind the link and well above the
70+
// handful of blocks a three-entry tree occupies. The old bound of 10,000 was
71+
// calibrated against apparent sizes and had no room in it once entries were
72+
// measured by what they occupy: on ext4 this tree is 12,288 bytes of blocks
73+
// and on APFS it is a fraction of that, so the same figure passed locally
74+
// and failed in CI.
75+
if result.bytes > 50000 {
7076
t.Errorf("measured %d bytes - the walk followed the link and measured what is behind it", result.bytes)
7177
}
7278
}

test/container/container_test.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,17 @@ func fluxOp(t *testing.T, volume, stdin string, args ...string) outcome {
130130
if index < 0 {
131131
t.Fatalf("flux-op never reported an exit code:\n%s", result.output)
132132
}
133-
code, err := strconv.Atoi(strings.TrimSpace(result.output[index+len(marker):]))
133+
// The first line after the marker, not everything after it. stdout and
134+
// stderr arrive on one stream here, and which lands last is a matter of
135+
// buffering rather than of order - so a run that writes to stderr can put a
136+
// diagnostic AFTER the marker, and reading to the end then parses the
137+
// diagnostic as part of the number. That failed on one architecture and
138+
// passed on the other in the same run.
139+
tail := result.output[index+len(marker):]
140+
if newline := strings.IndexByte(tail, '\n'); newline >= 0 {
141+
tail = tail[:newline]
142+
}
143+
code, err := strconv.Atoi(strings.TrimSpace(tail))
134144
if err != nil {
135145
t.Fatalf("could not read the exit code:\n%s", result.output)
136146
}

0 commit comments

Comments
 (0)