Skip to content

Flaky test: LaraSystemToolsTest.testRunCommand_withComplexCommand_parsesCorrectly fails on CI due to tight 2s process timeout #116

Description

@lm-sousa

Summary

In run 33936334262 (PR #108), Build Java failed with a single test failure:

LaraSystemToolsTest > testRunCommand_withComplexCommand_parsesCorrectly() FAILED
    org.opentest4j.AssertionFailedError at LaraSystemToolsTest.java:174

Build Java passes on every other run of the same commit; the test also passes locally.

Root cause

The test (LaraUtils/test/pt/up/fe/specs/lara/LaraSystemToolsTest.java:163) runs echo "hello world" via LaraSystemTools.runCommand with a 2-second process timeout (2000000000 ns).

SpecsSystem.executeProcess reports a timeout as exit code -1:

timedOut = !process.waitFor(timeoutNanos, TimeUnit.NANOSECONDS);
...
int returnValue = timedOut ? -1 : process.exitValue();  // SpecsSystem.java:319

so the assertThat(result.getReturnValue()).isEqualTo(0) at line 174 fails.

On CI, the test took 5.021s (vs ~0.15s locally). The timeline only fits the timeout path (there is no other wait ≥5s in the code path):

  • ~2s: process.waitFor(2s) expires — the forked echo hasn't completed exec yet
  • ~3s: outputFuture.get(...) blocks in readLine until the child finally gets scheduled, execs, and exits (SpecsSystem.java:306)

Why the child was starved for ~5s on CI but not locally:

  1. LaraUtils/build.gradle sets maxParallelForks = availableProcessors() → on the 4-vCPU hosted runner, 4 fresh test JVMs fork simultaneously right when :test starts
  2. This test is the first method executed in the class, so it eats the full cold-start penalty: gradle daemon + 4 JVMs (each with a jacoco agent) initializing at once, plus a System.gc() before every spawn (SpecsSystem.java:197)
  3. Freshly booted VM ⇒ cold page cache: the first execve of echo/loader/libc faults every page from disk — locally those pages are hot in RAM

Measurements on a local machine (8 cores): warm spawn ~55ms; worst simulated case (4 fresh JVMs pinned to 4 cores, simultaneous first spawn) ~190–205ms — 10× under budget, which is why it only reproduces on CI.

Note the sibling tests use 0.5s timeouts and pass only because they run after the workers are warm — they are equally exposed.

Suggested fix

Raise the timeout in these tests (e.g., 10s), starting with testRunCommand_withComplexCommand_parsesCorrectly (and ideally the 0.5s siblings). The tests' purpose is argument parsing, not timeout enforcement, so the tight budget adds no value.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions