fix(java): picocli ParameterException for browse --depth; warn on --parent 0
Replaces the raw IllegalArgumentException thrown by GalaxyBrowseCommand for --depth < 0 with a CommandLine.ParameterException so picocli surfaces a clean single-line error instead of an unhandled stack trace. Adds an upper bound of 50 (matching the Python client) so --depth > 50 is also rejected cleanly. Emits a stderr warning when --parent 0 is supplied explicitly, matching Go/Rust client behaviour, because gobject id 0 is the server's root-walk sentinel and passing it via --parent is almost always a mistake. Adds three new tests: negative depth, depth > 50, and the --parent 0 warning path.
This commit is contained in:
+17
-3
@@ -458,16 +458,24 @@ public final class MxGatewayCli implements Callable<Integer> {
|
||||
name = "galaxy-browse",
|
||||
description = "Browses the Galaxy hierarchy via GalaxyRepository.BrowseChildren.")
|
||||
static final class GalaxyBrowseCommand extends GalaxyCommand {
|
||||
@Spec
|
||||
private CommandSpec spec;
|
||||
|
||||
@Option(
|
||||
names = "--parent",
|
||||
defaultValue = "-1",
|
||||
description = "Parent gobject id to browse one level of children for; omit to walk the roots.")
|
||||
description =
|
||||
"Parent gobject id to browse one level of children for."
|
||||
+ " Use the default (omit) to walk root nodes;"
|
||||
+ " gobject id 0 is reserved by the server to mean roots.")
|
||||
int parent;
|
||||
|
||||
@Option(
|
||||
names = "--depth",
|
||||
defaultValue = "0",
|
||||
description = "When walking roots, eagerly expand this many further levels before printing.")
|
||||
description =
|
||||
"When walking roots, eagerly expand this many further levels before printing."
|
||||
+ " Must be between 0 and 50 inclusive.")
|
||||
int depth;
|
||||
|
||||
@Option(names = "--category-ids", description = "Comma-separated category ids to include.")
|
||||
@@ -491,11 +499,17 @@ public final class MxGatewayCli implements Callable<Integer> {
|
||||
@Override
|
||||
public Integer call() {
|
||||
if (depth < 0) {
|
||||
throw new IllegalArgumentException("--depth must be non-negative");
|
||||
throw new CommandLine.ParameterException(spec.commandLine(), "--depth must be non-negative");
|
||||
}
|
||||
if (depth > 50) {
|
||||
throw new CommandLine.ParameterException(spec.commandLine(), "--depth must be at most 50");
|
||||
}
|
||||
BrowseChildrenOptions options = buildOptions();
|
||||
PrintWriter out = common.spec.commandLine().getOut();
|
||||
PrintWriter err = common.spec.commandLine().getErr();
|
||||
if (parent == 0) {
|
||||
err.println("warning: --parent 0 is the server sentinel for root nodes; omit --parent to walk roots instead.");
|
||||
}
|
||||
try (GalaxyRepositoryClient client = connect()) {
|
||||
if (parent >= 0) {
|
||||
if (depth > 0) {
|
||||
|
||||
+47
@@ -215,6 +215,53 @@ final class MxGatewayCliTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void galaxyBrowseNegativeDepthYieldsNonZeroExitViaParameterException() {
|
||||
// Fix: --depth validation must surface as a picocli ParameterException
|
||||
// (clean error line on stderr) rather than an unhandled IllegalArgumentException
|
||||
// stack trace. Picocli maps ParameterException to exit code 2.
|
||||
CliRun run = execute(new FakeClientFactory(), "galaxy-browse", "--depth", "-1");
|
||||
|
||||
assertFalse(run.exitCode() == 0, "expected non-zero exit for --depth -1");
|
||||
// Picocli writes ParameterException messages to the error writer.
|
||||
assertTrue(run.errors().contains("--depth"), "expected --depth in error output: " + run.errors());
|
||||
}
|
||||
|
||||
@Test
|
||||
void galaxyBrowseDepthAbove50YieldsNonZeroExit() {
|
||||
CliRun run = execute(new FakeClientFactory(), "galaxy-browse", "--depth", "51");
|
||||
|
||||
assertFalse(run.exitCode() == 0, "expected non-zero exit for --depth 51");
|
||||
assertTrue(run.errors().contains("--depth"), "expected --depth in error output: " + run.errors());
|
||||
}
|
||||
|
||||
@Test
|
||||
void galaxyBrowseParentZeroEmitsWarningToStderr() {
|
||||
// --parent 0 is the server sentinel for roots; passing it explicitly is
|
||||
// almost certainly a mistake. The CLI must print a warning to stderr
|
||||
// (matching Go/Rust client behaviour) but must still attempt the call
|
||||
// (exit behaviour depends on gateway reachability, not tested here;
|
||||
// we only assert the warning path is triggered by checking the error
|
||||
// writer before any gRPC connection is attempted).
|
||||
//
|
||||
// GalaxyBrowseCommand connects to a real GalaxyRepositoryClient, so the
|
||||
// call() body will throw after printing the warning when no gateway is
|
||||
// reachable. We only assert the warning appears on stderr.
|
||||
StringWriter output = new StringWriter();
|
||||
StringWriter errors = new StringWriter();
|
||||
// Non-zero exit is expected (no live gateway), but the warning must
|
||||
// appear on stderr regardless of what happens next.
|
||||
MxGatewayCli.execute(
|
||||
new FakeClientFactory(),
|
||||
new PrintWriter(output, true),
|
||||
new PrintWriter(errors, true),
|
||||
"galaxy-browse", "--parent", "0", "--depth", "1");
|
||||
|
||||
assertTrue(
|
||||
errors.toString().contains("--parent 0"),
|
||||
"expected '--parent 0' warning on stderr; got: " + errors);
|
||||
}
|
||||
|
||||
// ---- galaxy command-name aliases (D9-java) ----
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user