test(hostagent): stop the standby tests reading the runner's own disks
Some checks are pending
Build and Test / Secret Scan (push) Waiting to run
Build and Test / Detect changed areas (push) Waiting to run
Build and Test / Frontend (push) Blocked by required conditions
Build and Test / Backend tests (api) (push) Blocked by required conditions
Build and Test / Backend tests (rest-0) (push) Blocked by required conditions
Build and Test / Backend tests (rest-1) (push) Blocked by required conditions
Build and Test / Script smoke tests & backend build (push) Blocked by required conditions
Build and Test / Benchmarks (push) Blocked by required conditions
Canonical Governance / governance (push) Waiting to run
Core E2E Tests / Validate E2E tier selection (push) Waiting to run
Core E2E Tests / Playwright Core E2E (shard 1/8) (push) Blocked by required conditions
Core E2E Tests / Playwright Core E2E (shard 2/8) (push) Blocked by required conditions
Core E2E Tests / Playwright Core E2E (shard 3/8) (push) Blocked by required conditions
Core E2E Tests / Playwright Core E2E (shard 4/8) (push) Blocked by required conditions
Core E2E Tests / Playwright Core E2E (shard 5/8) (push) Blocked by required conditions
Core E2E Tests / Playwright Core E2E (shard 6/8) (push) Blocked by required conditions
Core E2E Tests / Playwright Core E2E (shard 7/8) (push) Blocked by required conditions
Core E2E Tests / Playwright Core E2E (shard 8/8) (push) Blocked by required conditions
Core E2E Tests / Agent registration lifecycle (push) Waiting to run
Core E2E Tests / E2E verdict (push) Blocked by required conditions
Unified Agent Native Verification / Linux ARM64 (push) Waiting to run
Unified Agent Native Verification / Linux x64 (push) Waiting to run
Unified Agent Native Verification / Windows x64 (push) Waiting to run
Unified Agent Native Verification / macOS ARM64 (push) Waiting to run
Unified Agent Native Verification / macOS Intel (push) Waiting to run
Unified Agent Native Verification / FreeBSD cross-build contract (push) Waiting to run

TestCollectDeviceSMARTStandby and its observability twin stub smartctl's
execution but not the device-class probe, so collectDeviceSMART fell through
to the *runner's* real /sys/block/sda/queue/rotational.

smartctlArgs only sends the -n standby guard when the disk is not a confirmed
SSD (#1516), and smartctlArgsUseStandbyExitStatus gates the standby reading of
exit status 3 on that guard having been sent. On a Linux host whose own
/dev/sda is non-rotational the guard is dropped, exit 3 stops meaning standby,
and both tests fail deterministically:

    run smartctl for /dev/sda: exit status 3

They pass on macOS only because linuxNonRotationalBlockDevice returns false off
Linux, and on Linux only where /dev/sda is absent or spinning. That makes the
release-qualification suite unrunnable on an ordinary SSD-backed Linux worker.

Pin the probed disk to rotational through the package's existing stubLinuxSysfs
seam so the guard is always in play. Product behaviour is untouched; this only
stops two unit tests depending on the hardware underneath them.
This commit is contained in:
rcourtman 2026-08-19 09:45:44 +01:00
parent 44d53edcbf
commit 2d801e20f3
2 changed files with 18 additions and 0 deletions

View file

@ -118,6 +118,14 @@ func TestCollectDeviceSMART_LogsStructuredContextWhenDeviceInStandby(t *testing.
execLookPath = origLook
})
// Same host-sysfs leak as TestCollectDeviceSMARTStandby: the -n standby
// guard, and therefore the standby meaning of exit status 3, depends on
// the probed disk not being a confirmed SSD. Pin it to rotational instead
// of reading the runner's own /sys/block/sda/queue/rotational.
stubLinuxSysfs(t, []string{"sda"}, map[string]string{
"/sys/block/sda/queue/rotational": "1\n",
})
execLookPath = func(string) (string, error) { return "smartctl", nil }
smartRunCommandOutput = func(ctx context.Context, name string, args ...string) ([]byte, error) {
return exec.CommandContext(ctx, "sh", "-c", "exit 3").Output()

View file

@ -584,6 +584,16 @@ func TestCollectDeviceSMARTStandby(t *testing.T) {
timeNow = origNow
})
// smartctlArgs only sends the -n standby guard for disks that are not
// confirmed SSDs, and exit status 3 only means standby when that guard
// was sent. Without a stubbed sysfs this reads the *runner's* real
// /sys/block/sda/queue/rotational, so the case under test evaporates on
// any Linux host whose own /dev/sda is an SSD. Pin the probed disk to
// rotational so the guard is always in play.
stubLinuxSysfs(t, []string{"sda"}, map[string]string{
"/sys/block/sda/queue/rotational": "1\n",
})
fixed := time.Date(2024, 2, 3, 4, 5, 6, 0, time.UTC)
timeNow = func() time.Time { return fixed }
execLookPath = func(string) (string, error) { return "smartctl", nil }