-
Notifications
You must be signed in to change notification settings - Fork 425
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
negated boolean value handled differently in 4.7.0 #1880
Comments
Did this used to work differently? @Test
public void optionIsTrueByDefault() {
final CommandLine commandLine = new CommandLine(new TestCommand());
final CommandLine.ParseResult parseResult = commandLine.parseArgs();
final TestCommand command = (TestCommand) parseResult.commandSpec().userObject();
assertTrue(command.interactive);
}
@Test
public void optionFalseWhenSpecified() {
final TestCommand command = new TestCommand();
new CommandLine(command).parseArgs("--no-interactive");
assertFalse(command.interactive);
}
@Test
public void optionTrueWhenNegatedFormSpecified() {
final TestCommand command = new TestCommand();
new CommandLine(command).parseArgs("--interactive");
assertTrue(command.interactive);
}
@Test
public void optionCanBeSetToFalse() {
final TestCommand command = new TestCommand();
//CommandLine.tracer().setLevel(CommandLine.TraceLevel.DEBUG);
new CommandLine(command).parseArgs("--no-interactive=false");
assertFalse(command.interactive);
}
@Test
public void optionNegatedFormSetToFalseIsTrue() {
final TestCommand command = new TestCommand();
new CommandLine(command).parseArgs("--interactive=false");
assertTrue(command.interactive);
} |
yeah your last test works differently in 4.6
|
Created a slightly larger test case that covers negatable options with and without @CommandLine.Command
static class TestCommand implements Runnable {
@CommandLine.Option(
names = {"--no-interactive"},
defaultValue = "true",
negatable = true
)
public boolean interactive;
@CommandLine.Option(
names = {"--no-autonomous"},
defaultValue = "false",
negatable = true
)
public boolean autonomous;
@CommandLine.Option(
names = {"--daemon"},
defaultValue = "true",
negatable = true
)
public boolean daemon;
@CommandLine.Option(
names = {"--human"},
defaultValue = "false",
negatable = true
)
public boolean human;
@Override
public void run() {}
}
@Test
public void optionNotSpecified() {
final TestCommand command = new TestCommand();
new CommandLine(command).parseArgs();
assertAll(
() -> assertTrue(command.interactive, "interactive"),
() -> assertFalse(command.autonomous, "autonomous"),
() -> assertTrue(command.daemon, "daemon"),
() -> assertFalse(command.human, "human")
);
}
@Test
public void optionSpecifiedWithoutValue() {
final TestCommand command = new TestCommand();
new CommandLine(command).parseArgs("--interactive", "--autonomous", "--daemon", "--human");
assertAll(
() -> assertTrue(command.interactive, "interactive"),
() -> assertFalse(command.autonomous, "autonomous"),
() -> assertFalse(command.daemon, "daemon"),
() -> assertTrue(command.human, "human")
);
}
@Test
public void optionSpecifiedWithBooleanTrue() {
final TestCommand command = new TestCommand();
new CommandLine(command).parseArgs("--interactive=true", "--autonomous=true", "--daemon=true", "--human=true");
assertAll(
() -> assertFalse(command.interactive, "interactive"), // FAIL in 4.6
() -> assertFalse(command.autonomous, "autonomous"), // FAIL in 4.6
() -> assertTrue(command.daemon, "daemon"),
() -> assertTrue(command.human, "human")
);
}
@Test
public void optionSpecifiedWithBooleanFalse() {
final TestCommand command = new TestCommand();
new CommandLine(command).parseArgs("--interactive=false", "--autonomous=false", "--daemon=false", "--human=false");
assertAll(
() -> assertTrue(command.interactive, "interactive"), // FAIL in 4.6
() -> assertTrue(command.autonomous, "autonomous"), // FAIL in 4.6
() -> assertFalse(command.daemon, "daemon"),
() -> assertFalse(command.human, "human")
);
}
@Test
public void optionSpecifiedWithNegatedForm() {
final TestCommand command = new TestCommand();
new CommandLine(command).parseArgs("--no-interactive", "--no-autonomous", "--no-daemon", "--no-human");
assertAll(
() -> assertFalse(command.interactive, "interactive"),
() -> assertTrue(command.autonomous, "autonomous"),
() -> assertTrue(command.daemon, "daemon"),
() -> assertFalse(command.human, "human")
);
}
@Test
public void optionSpecifiedWithNegatedFormUsingBooleanTrue() {
final TestCommand command = new TestCommand();
new CommandLine(command).parseArgs("--no-interactive=true", "--no-autonomous=true", "--no-daemon=true", "--no-human=true");
assertAll(
() -> assertTrue(command.interactive, "interactive"),
() -> assertTrue(command.autonomous, "autonomous"),
() -> assertFalse(command.daemon, "daemon"), // FAIL in 4.6
() -> assertFalse(command.human, "human") // FAIL in 4.6
);
}
@Test
public void optionSpecifiedWithNegatedFormUsingBooleanFalse() {
final TestCommand command = new TestCommand();
new CommandLine(command).parseArgs("--no-interactive=false", "--no-autonomous=false", "--no-daemon=false", "--no-human=false");
assertAll(
() -> assertFalse(command.interactive, "interactive"),
() -> assertFalse(command.autonomous, "autonomous"),
() -> assertTrue(command.daemon, "daemon"), // FAIL in 4.6
() -> assertTrue(command.human, "human") // FAIL in 4.6
);
} |
Thank you for this extensive test! Very helpful! Do you think that the old 4.6.0 behaviour is more intuitive than the 4.7 behaviour? |
The expected behavior in #1642 is the same as the
However, a negatable option that is true by default looks weird to me:
I think the major reason this looks weird to me is that in my mind
This treats @CommandLine.Command
static class TestCommand implements Runnable {
@CommandLine.Option(
names = {"--wanted"}, // this changed
defaultValue = "true",
fallbackValue = "true", // this is new
negatable = true
)
public boolean wanted;
@Override
public void run() {}
}
@Test
public void optionNotSpecified() {
final var command = new TestCommand();
new CommandLine(command).parseArgs();
assertTrue(command.wanted, "wanted");
}
@Test
public void optionSpecifiedWithoutValue() {
final var command = new TestCommand();
new CommandLine(command).parseArgs("--wanted");
assertTrue(command.wanted, "wanted");
}
@Test
public void optionSpecifiedWithBooleanTrue() {
final var command = new TestCommand();
new CommandLine(command).parseArgs("--wanted=true");
assertTrue(command.wanted, "wanted");
}
@Test
public void optionSpecifiedWithBooleanFalse() {
final var command = new TestCommand();
new CommandLine(command).parseArgs("--wanted=false");
assertFalse(command.wanted, "wanted");
}
@Test
public void optionSpecifiedWithNegatedForm() {
final var command = new TestCommand();
new CommandLine(command).parseArgs("--no-wanted");
assertFalse(command.wanted, "wanted");
}
@Test
public void optionSpecifiedWithNegatedFormUsingBooleanTrue() {
final var command = new TestCommand();
new CommandLine(command).parseArgs("--no-wanted=true");
assertFalse(command.wanted, "wanted");
}
@Test
public void optionSpecifiedWithNegatedFormUsingBooleanFalse() {
final var command = new TestCommand();
new CommandLine(command).parseArgs("--no-wanted=false");
assertTrue(command.wanted, "wanted");
} This deviates from the docs about negatable options that are true by default but I think it's nicer for users. Feel free to close this one & thanks for helping! |
I finally had time to think this through. Nice! Your solution is much better than the current recommendation in the manual. The current recommendation of defining the option as I will update the user manual to recommend your solution instead:
|
Done. The docs have been updated. |
Not sure if this was done intentionally but I could not find anything in the release notes thus this ticket.
The following test cases work fine in 4.6.3 but not entirely in 4.7.0:
The second test case uses
--interactive=false
which does not seem to work anymore on a negatable option.The text was updated successfully, but these errors were encountered: