Skip to content

Cover the sender thread and an interrupted close() - #29

Merged
dmccoystephenson merged 1 commit into
mainfrom
feature/thread-and-interrupt-tests
Oct 24, 2026
Merged

dmccoystephenson merged 1 commit into
mainfrom
feature/thread-and-interrupt-tests

Conversation

@dmccoystephenson

Copy link
Copy Markdown
Member

Stage B: unit-test expansion (sender thread lifecycle). Only TraceClientTest.java is changed; production code is not touched.

Summary

  • report_sendsFromOneDaemonThreadNamedForTheApplication: a slow server holds the first request while five reports are queued. The test then checks that exactly one live thread named trace-client/ThreadProbe exists and that it is a daemon. This pins the class Javadoc's "single daemon thread owned by this client" promise. It also pins the property that a client never keeps the host JVM from exiting.
  • close_whenInterruptedReturnsAtOnceAndKeepsTheInterruptFlag: with a request held in flight, the caller is interrupted before close(). The test checks that close() returns in under 2 s (the drain bound is 5 s) and that the interrupt flag is still set afterwards. This covers the catch (InterruptedException) branch of close(), which no test reached before.

Both are characterization tests of current behaviour, and no bug was found.

Test plan

  • mvn -B verify run locally: Tests run: 86, Failures: 0, Errors: 0, Skipped: 0, and both new tests appear in the surefire report
  • CI matrix build (8), build (17), build (21) green on the PR head

Deferred issues

All three open issues require a maintainer decision and were not picked for this cycle:

No tracking issue. This gap was found during triage by comparing the branches of TraceClient.java against TraceClientTest.java.

This PR description was drafted during a Gardener session (https://github.com/Stephenson-Software/gardener).

🤖 Generated with Claude Code


drafted by Claude on behalf of Daniel Stephenson

The class Javadoc promises a single daemon thread, and close() cuts the
drain short and restores the interrupt when the caller is interrupted.
Neither was asserted. One test holds a request on a slow server and
checks that exactly one thread named trace-client/<application> exists
and that it is a daemon. The other interrupts the caller before close()
and checks that close() returns well inside the drain timeout with the
interrupt flag still set.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dmccoystephenson

Copy link
Copy Markdown
Member Author

Self-review rubric (scored against the diff and command output; this is not an independent review):

  • Scope: PASS. gh pr diff 29 touches only src/test/java/software/stephenson/trace/TraceClientTest.java and adds two tests.
  • Tests-new: PASS (n/a). No public method was added.
  • Tests-fix: n/a. No fix is included. As a substitute check, a temporary mutation of TraceClient.java was run: setDaemon(true) was changed to false, and Thread.currentThread().interrupt() was removed from close(). Both new tests then FAILED (Tests run: 2, Failures: 2). After the mutation was reverted they PASS, so each test can detect a regression of the property it covers. The mutation was never committed.
  • Sibling structure: PASS. The tests reuse the slow-server/CountDownLatch pattern of close_stillReturnsWithinTheTimeoutWhenTheServerHangs, use the subject_behaviour names, and include Arrange/Act/Assert comments.
  • Sibling renames: n/a.
  • Docs: PASS. No behaviour changed. The tests pin the class Javadoc's "single daemon thread" claim and the existing close() interrupt handling.
  • Issue resolution: n/a. No Closes.
  • CI: PASS. build (8), build (17) and build (21) are green on the head.
  • No dependencies / single file / Java 8: PASS. pom.xml and src/main are untouched. The test code uses only Java 8 APIs (Thread.getAllStackTraces, streams), and build (8) is green.
  • Never throws / non-blocking / env seam / version / opt-out contract: n/a. Production code is untouched.

Findings:

  • src/test/java/software/stephenson/trace/TraceClientTest.java:626: the elapsedMs < 2_000 bound is timing-based. Against the 5 s drain it leaves a wide margin, and locally close() returned in single-digit milliseconds, so flake risk looks low. It is listed with the other timing-sensitive tests for the flake watch.
  • src/test/java/software/stephenson/trace/TraceClientTest.java:653: if the inFlight.await assertion fails, the extra slow server is not stopped. This leak-on-failure pattern matches the existing slow-server tests and only matters when the test is already failing, so it was left as is for consistency.

Summary: the PR adds characterization tests only, and the mutation check confirms both carry signal. With CI green and no do-not-auto-merge path touched, it meets the merge bar.

This review comment was drafted during a Gardener session (https://github.com/Stephenson-Software/gardener).


drafted by Claude on behalf of Daniel Stephenson

@dmccoystephenson
dmccoystephenson merged commit 10433f8 into main Oct 24, 2026
3 checks passed
@dmccoystephenson
dmccoystephenson deleted the feature/thread-and-interrupt-tests branch October 24, 2026 07:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant