diff --git a/fleetd/src/test/java/dev/ltms/fleet/member/ClaudeCodeLauncherTest.java b/fleetd/src/test/java/dev/ltms/fleet/member/ClaudeCodeLauncherTest.java index beea11f..255e947 100644 --- a/fleetd/src/test/java/dev/ltms/fleet/member/ClaudeCodeLauncherTest.java +++ b/fleetd/src/test/java/dev/ltms/fleet/member/ClaudeCodeLauncherTest.java @@ -23,7 +23,6 @@ import org.slf4j.LoggerFactory; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.attribute.PosixFileAttributeView; import java.nio.file.attribute.PosixFilePermissions; import java.util.List; import java.util.Map; @@ -1802,11 +1801,37 @@ class ClaudeCodeLauncherTest { 0, System::currentTimeMillis, () -> { }, null, null, null, config); } - /** The current process's own primary group — resolvable on whatever host runs this test. */ - private static String currentUserGroup() throws IOException { - PosixFileAttributeView view = Files.getFileAttributeView(Path.of("."), PosixFileAttributeView.class); - assumeTrue(view != null, "this host's filesystem does not support POSIX group ownership"); - return view.readAttributes().group().getName(); + /** + * The current process's REAL primary group — resolved via {@code id -gn}, never by reading a + * directory's owning group (fleetd #225). Those two coincide only by accident: a directory's + * group is whichever group happened to own the path Maven was started from — {@code staff} in + * a home checkout, {@code wheel} under {@code /private/tmp} on macOS — and the fix-up this test + * exercises then fails for real when the operator is not a member of that borrowed group, + * exactly the case {@code assumeTrue(view != null, ...)} never covered (it only detects a + * filesystem with no POSIX groups at all, not a resolvable-but-wrong one). Skips (never fails) + * when {@code id} is unavailable or its primary group cannot be resolved on this host. + */ + private static String currentUserGroup() { + String out; + boolean ok; + try { + Process p = new ProcessBuilder("id", "-gn").redirectErrorStream(true).start(); + try (java.io.BufferedReader r = new java.io.BufferedReader( + new java.io.InputStreamReader(p.getInputStream(), java.nio.charset.StandardCharsets.UTF_8))) { + out = r.lines().collect(java.util.stream.Collectors.joining("\n")).trim(); + } + ok = p.waitFor(5, java.util.concurrent.TimeUnit.SECONDS) && p.exitValue() == 0 && !out.isBlank(); + } catch (IOException e) { + out = null; + ok = false; + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + out = null; + ok = false; + } + assumeTrue(ok, "cannot resolve this process's real primary group via `id -gn` on this host " + + "— skipping a POSIX-group-dependent test rather than failing it"); + return out; } /**