Skip to content

tests: keep the Linux tests true with Ubuntu 26.04's coreutils - #1554

Merged
Pedro Henrique Penna (ppenna) merged 2 commits into
devfrom
agents/issue-1537-ubuntu-2604-coreutils
Nov 12, 2026
Merged

Pedro Henrique Penna (ppenna) merged 2 commits into
devfrom
agents/issue-1537-ubuntu-2604-coreutils

Conversation

@ppenna

@ppenna Pedro Henrique Penna (ppenna) commented Nov 12, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #1537

What and why

Between 11:22 and 11:47 UTC on 2026-11-12, GitHub moved ubuntu-latest from Ubuntu 24.04 to Ubuntu 26.04 (image ubuntu-26.04 20261101.186.1), where coreutils is uutils' Rust multi-call coreutils (rust-coreutils 0.10.0) rather than GNU's. Two tests that dev carries assume GNU coreutils, so every dev pull request now fails Required status check. The first dev-based run on 26.04, #1551's 43269651949 at a159c4a0b0a, failed exactly these two jobs:

  • nvx-rs / ubuntu-latest: guest::exec::tests::a_stalled_sink_stalls_only_its_own_execution_and_loses_nothing panicked at src/guest/exec/tests.rs:318:5 (1901 library tests passed, 1 failed).
  • NVX CLI / Linux: test_linux_runners_terminate_openvmm_left_by_earlier_jobs failed with coreutils: unknown program 'nvx-leak-2581' (2198 tests, failures=1, errors=1, both from that test).

Both are test assumptions, not product bugs, so this fixes the tests and pins no runner. It ports the two commits of #1535, which fixed the same tests on feature/nvx-refactor and passed on 26.04 in 43220514149. dev's copies of the four tests were identical to feature/nvx-refactor's before those commits, and both commits apply unchanged; their messages only add where they come from and how the tests failed on dev:

  1. tests: outgrow the pipe that uutils' head grows, from aa144f7c091. When N is more than 64 KiB, uutils' head -c N first grows its output pipe with F_SETPIPE_SZ to min(N, 1 MiB) (send_n_bytes at 0.10.0). So head -c 262144 fit in its pipe instead of blocking, ended, and closed its standard error, which gave the "stalled" execution an event to report. The test now writes MORE_THAN_A_PIPE_HOLDS, 4 MiB, since a program without privileges can grow a pipe to /proc/sys/fs/pipe-max-size, 1 MiB by default, at most. Two tests that pass on 26.04 only by margin change too: cancellation_ends_a_stalled_program_and_the_caller_discards_the_rest, which passed only because uutils grows its pipe to exactly 256 KiB, now writes 4 MiB, and guest::managed_agent::dispatch::tests::output_beyond_the_cap_ends_the_workload_after_the_reads_that_fit, whose 1.5 MiB could finish in a 1 MiB pipe once the agent had read 0.5 MiB, now writes 3 MiB.
  2. tests: run the leaked-OpenVMM stand-in as Python, from 35af82af156. The test copied sleep to a stand-in named nvx-leak-<pid>, which the step under test finds by its process name. uutils' multi-call binary picks its program by the name of the file that it runs, so the copy exited at once, and setting argv[0] doesn't help, since the glibc build that Ubuntu ships takes the path that the kernel ran (AT_EXECFN) over argv[0] (validation.rs at 0.10.0). The stand-in is now a link, named for the stand-in, to the Python interpreter, which sleeps, and the test expects the command line that the step prints. Everything else that it checks is unchanged.

Other GNU coreutils assumptions on dev. dev still carries test code that feature/nvx-refactor has deleted, which #1535's run therefore never exercised on 26.04: nvx-rs/src/guest/exec/binding/tests.rs, the runtime adapter in tests/runtime-adapter/, the integration tests nvx-rs/tests/{fake_openvmm,managed_lifecycle,store,supervisor,template_capture}.rs, and the artifact bundling step. I searched them, and the other tests and CI scripts that run on ubuntu-latest, for head -c, for the other uutils programs that grow a pipe (tail, tee, yes, and cat through splice), and for coreutils programs run under another name. None needs a change:

  • The binding tests have head -c write 24 or 32 KiB, for which uutils doesn't grow the pipe, or 16 MiB, which no pipe holds, and their cat /dev/zero never ends. All of them passed on 26.04 in 43269651949.
  • The runtime adapter's tests that run on the runner use seq, sleep, env, true, and cat copying its input or /dev/zero, none of them under another name or counting on a pipe's size; its yes test only simulates the program.
  • host::process::tests::linux::a_process_whose_command_name_is_not_utf8_can_be_examined runs sleep through a link with another name, with argv[0] set to sleep. It passed on 26.04 in both 43269651949 and 43220514149, and printed no unknown program.

The runtime adapter, the integration tests, and the steps after the library tests of nvx-rs / ubuntu-latest didn't run in 43269651949, which stopped at the first failure; this pull request's run, below, passed them on 26.04.

Size. Test code only, in two Rust test files and one Python test module. No public API, contract, or version changes.

Validation

Check Result
Linux, nvx-kvm-test (virtual machine, Azure Linux 3.0, kernel 6.6), temporary worktree at 90cbd4554ac: cargo test --locked --all-features --lib -- --exact with the three changed tests and a_process_whose_command_name_is_not_utf8_can_be_examined, 3 rounds each with GNU coreutils 9.4 and with uutils 0.10.0 first in PATH Pass, 4 of 4 in every round
Same host, the base's (83764f5ab0f) test files, same command With uutils, a_stalled_sink_... panics at src/guest/exec/tests.rs:318:5 in all 3 rounds, as in CI; with GNU coreutils, all pass
Same host: python3 -m unittest scripts.test_nvx_tools.CiConfigurationTests.test_linux_runners_terminate_openvmm_left_by_earlier_jobs, twice each with GNU coreutils and with uutils 0.10.0 Pass at this head. At the base, passes with GNU coreutils, and fails with uutils as in CI: coreutils: unknown program 'nvx-leak-48303', failures=1, errors=1
Same host: cargo test --locked --all-features --lib -- guest::exec:: guest::managed_agent::dispatch::, with GNU coreutils and with uutils 0.10.0; cargo clippy --locked --all-targets --all-features -- -D warnings Pass: 103 passed, 0 failed, 0 ignored, and their isolated children, in both; Clippy passes
Windows: python scripts/local_gates.py --base origin/dev --only test-changes markdown-links test-layout nvx-rs-format --run Pass
Windows: the Python checks of the quality-code gate: ruff check and ruff format --check of scripts .github/specula, compileall, pyright --pythonplatform Linux and Windows Pass. Its shellcheck and shfmt didn't run, since Docker can't mount the checkout from Git Bash here; no shell script changes
Windows: the changed Python test, whose Linux part is skipped Pass
CI run 43275945795 at 90cbd4554ac, whose Linux jobs ran on image ubuntu-26.04 20261101.186.1 Every job passes, Required status check included. nvx-rs / ubuntu-latest ran all its steps, which 43269651949 never reached: the library tests (1902 passed, 19 ignored), the integration and doc tests, the bundling check, the guest binaries, and the runtime adapter in its three configurations, with no unknown program in its log. NVX CLI / Linux ran 2198 tests (OK, 36 skipped) and the 84 adversarial tests

uutils 0.10.0's glibc build needs glibc 2.39, which the host's 2.38 lacks, so the host ran the release's musl build. It grows pipes as the glibc build does, but it reads argv[0] rather than AT_EXECFN. No Ubuntu 26.04 machine was available apart from GitHub's runners, so this pull request's run on ubuntu-latest, above, is the authoritative check.

Tests modified

python scripts/check_test_changes.py --base origin/dev lists 4 changes to existing tests, plus 1 addition, the constant MORE_THAN_A_PIPE_HOLDS. Each change keeps what the test checks:

  • a_stalled_sink_stalls_only_its_own_execution_and_loses_nothing writes 4 MiB instead of 256 KiB, so its program still blocks once uutils' head grows its pipe.
  • cancellation_ends_a_stalled_program_and_the_caller_discards_the_rest writes 4 MiB instead of 256 KiB after its first page, for the same reason.
  • output_beyond_the_cap_ends_the_workload_after_the_reads_that_fit writes 3 MiB instead of 1.5 MiB, so the workload can't finish before the agent reads past its 1 MiB cap.
  • test_linux_runners_terminate_openvmm_left_by_earlier_jobs runs Python through a link named for its stand-in, where it ran a copy of sleep, which a multi-call coreutils won't run under another name, and expects that command line.

The openvmm gitlink doesn't move.

On Ubuntu 26.04, head is uutils' head, and `head -c N` grows its output
pipe to N bytes, up to 1 MiB, before it copies them. Three tests have
`head -c` write more than a pipe of the default 64 KiB holds, expecting
it to block until the reader takes some:

- guest::exec::tests::a_stalled_sink_stalls_only_its_own_execution_and_loses_nothing
  wrote 256 KiB, which its grown pipe held whole, so head ended, its
  standard error closed, and the stalled execution had an event to
  report. It failed on every ubuntu-latest runner once that label moved
  to Ubuntu 26.04.
- guest::exec::tests::cancellation_ends_a_stalled_program_and_the_caller_discards_the_rest
  wrote 256 KiB after 4 KiB, which still overfills a pipe grown to
  256 KiB, but which a head that grows it more would not.
- guest::managed_agent::dispatch::tests::output_beyond_the_cap_ends_the_workload_after_the_reads_that_fit
  wrote 1.5 MiB, of which a grown pipe holds 1 MiB, so head could end
  and the workload leave its marker once the agent had read 0.5 MiB,
  before the agent read beyond its 1 MiB cap and ended the workload.

Each now writes more than a pipe holds even once the program grows it:
4 MiB in the exec tests, and 3 MiB in the dispatch test, which head can
finish only once the agent has read 2 MiB.

This ports aa144f7 of feature/nvx-refactor (#1535) to dev, whose
three tests were the same. On dev, the first failed the same way, at
src/guest/exec/tests.rs:318, in the nvx-rs / ubuntu-latest job of run
43269651949 on the ubuntu-26.04 image.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
test_linux_runners_terminate_openvmm_left_by_earlier_jobs copied sleep
to a uniquely named stand-in, which the step under test finds by its
process name. On Ubuntu 26.04, sleep is uutils' multi-call coreutils,
which picks its program by the name of the file that it runs, so the
stand-in ended at once with "coreutils: unknown program 'nvx-leak-...'",
and the step found nothing to terminate. Running the copy with argv[0]
set to sleep doesn't help: uutils' glibc build, which Ubuntu ships,
takes the path that the kernel ran (AT_EXECFN) over argv[0].

The stand-in is now a link to the Python interpreter, named for the
stand-in, that sleeps: the kernel names the process after the link, and
Python runs under any name. The test expects the step to print that
command line.

This ports 35af82a of feature/nvx-refactor (#1535) to dev, whose
test was the same. On dev, it failed the same way, with "coreutils:
unknown program 'nvx-leak-2581'", in the NVX CLI / Linux job of run
43269651949 on the ubuntu-26.04 image.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 12, 2026 18:04
@ppenna Pedro Henrique Penna (ppenna) added the tests-modified Changes existing tests, test data, or test wiring label Nov 12, 2026
@github-actions

Copy link
Copy Markdown
Contributor

This pull request changes existing tests

It modifies or removes 4 existing test asset(s), listed below. Review each with care: a change to a test can hide a regression that the test caught. See doc/contribute.md#changes-to-existing-tests.

Test code

Change What Before After
modified test fn a_stalled_sink_stalls_only_its_own_execution_and_loses_nothing in guest::exec::tests nvx-rs/src/guest/exec/tests.rs:290 nvx-rs/src/guest/exec/tests.rs:296
modified test fn cancellation_ends_a_stalled_program_and_the_caller_discards_the_rest in guest::exec::tests nvx-rs/src/guest/exec/tests.rs:337 nvx-rs/src/guest/exec/tests.rs:343
modified test fn output_beyond_the_cap_ends_the_workload_after_the_reads_that_fit in guest::managed_agent::dispatch::tests nvx-rs/src/guest/managed_agent/dispatch/tests.rs:1367 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:1367
modified test def CiConfigurationTests.test_linux_runners_terminate_openvmm_left_by_earlier_jobs in scripts/test_nvx_tools.py scripts/test_nvx_tools.py:11446 scripts/test_nvx_tools.py:11446

Relocated unchanged: 0; added: 1. Compared the merge base 83764f5ab0f3 with 90cbd4554ac5.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues remain for the Linux test compatibility updates.

No open issues 🎉

What changed in this PR

Updates Linux tests to work with Ubuntu 26.04’s uutils coreutils, addressing #1537 without changing production code or pinning CI runners.

Changes:

  • Increases test output sizes so pipe growth cannot undermine backpressure, cancellation, or output-limit checks.
  • Replaces the renamed sleep executable with a Python-based stand-in for leaked-process cleanup tests.
File Description
scripts/​test_nvx_tools.py Uses a named Python symlink as the leaked-process stand-in and updates expected command output.
nvx-rs/​src/​guest/​managed_agent/​dispatch/​tests.rs Raises workload output to 3 MiB to preserve the output-limit test’s blocking behavior.
nvx-rs/​src/​guest/​exec/​tests.rs Uses a shared 4 MiB output size for stalled-sink and cancellation tests.

Review effort: Balanced

@ppenna
Pedro Henrique Penna (ppenna) added this pull request to the merge queue Nov 12, 2026
Merged via the queue into dev with commit cc12bae Nov 12, 2026
52 checks passed
@ppenna
Pedro Henrique Penna (ppenna) deleted the agents/issue-1537-ubuntu-2604-coreutils branch November 12, 2026 18:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

tests-modified Changes existing tests, test data, or test wiring

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CI: two tests on dev assume GNU coreutils, which ubuntu-latest (now 26.04) no longer has

2 participants