libtmux-junit5 gives each test its own tmux server on its own socket, and takes
it back afterwards.
@ExtendWith(TmuxExtension.class)
final class MyTest {
@Test
void aWindowCanBeMade(Server server) {
server.sessions().get(0).newWindow("built");
}
}The extension resolves Server and TmuxSocketPath. It never claims a bare
Path parameter, so another extension is free to resolve those.
What that hands you:
server.sessions().size(); // → 1
server.sessions().get(0).name(); // → libtmux
socket.startsWith("/tmp/libtmux-java-test/"); // → trueBefore the test, it creates a private directory and socket, registers the object that owns them before any process exists, starts tmux with an explicitly empty config, and checks tmux agrees about which socket it is listening on.
Afterwards it proves the daemon exited by asking, rather than assuming a kill won its race, and only then unlinks the socket and removes the directory. If exit cannot be proved, it preserves the failure rather than deleting a socket a live daemon still owns.
Teardown runs whether the test passed, failed or errored. That is checked by running a deliberately failing test in a nested engine and inspecting what it left behind — a test cannot watch its own teardown.
Every test task runs with a short TMUX_TMPDIR under
/tmp/libtmux-java-test/, and with TMUX and TMUX_PANE removed. Its
16-character hexadecimal namespace hashes the canonical worktree, task path,
and Gradle daemon process. That separates concurrent invocations without
spending the socket path's limited bytes. Before use, the task prunes empty
directory scaffolding but refuses to remove a stale file or socket. A command
that omits its -S therefore cannot reach the tmux you are working in.
Explicitly named-socket tests capture the server process and reported inode,
then reclaim only that inode after the process has exited.
This is enforced by the build rather than by every test remembering, because the code under test is exactly what is allowed to be wrong. The suite asserts the quarantine is in place.
The real-tmux suites run against each release the library supports, given a tree of tmux builds with one directory per lane:
$ ./gradlew testTmuxMatrix -PlibtmuxMatrix=/path/to/tmux/buildsEach lane declares which tmux it covers and the suite checks the running server
agrees. Without that, a lane that silently ignored the configured binary would
run against whatever is on PATH and report exactly the same green.
Two version differences are handled inside the library and are worth knowing about, because both are silent:
pane_floating_flagdoes not exist before tmux 3.7, and the format expands to nothing rather than to zero.Pane.floating()is anOptionalthat is empty when the running tmux cannot say, rather than defaulting tofalse.- tmux 3.7 exactly ends the whole server when
break-panehas to name the new window itself, and silently discards a name it is given.Pane.breakOut()works around both.