Ruiqi Dong created CLI-347:
------------------------------
Summary: Options.addOptionGroup() does not remove required options
from requiredOpts list
Key: CLI-347
URL: https://issues.apache.org/jira/browse/CLI-347
Project: Commons CLI
Issue Type: Bug
Reporter: Ruiqi Dong
When a required Option is added to an OptionGroup via
{{{}Options.addOptionGroup(){}}}, the option's {{required}} flag is correctly
set to false, but the option's key remains in the {{requiredOpts}} list. This
violates the documented design principle that "an Option cannot be required if
it is in an OptionGroup".
*Impact:*
* {{getRequiredOptions()}} returns incorrect results
* Breaks the contract that options in OptionGroups cannot be required
* May cause incorrect validation behavior during command line parsing
* Inconsistent behavior depending on the order of operations
*Test Case:*
{code:java}
@Test
public void testRequiredOptionInGroupShouldNotBeInRequiredList() {
// Create a required option
Option option = new Option("a", "along", false, "Option A");
option.setRequired(true);
// Add required option to Options
Options options = new Options();
options.addOption(option);
// Verify option is in required list
assertTrue(options.getRequiredOptions().contains("a"));
// Create OptionGroup and add the same option
OptionGroup group = new OptionGroup();
group.addOption(option);
// Add OptionGroup to Options
options.addOptionGroup(group);
// Verify option's required flag is false
assertFalse(options.getOption("a").isRequired());
// This assertion fails - demonstrating the bug
assertFalse(options.getRequiredOptions().contains("a"),
"Option in group should NOT be in required options list");
} {code}
*Test Failure Scenario:*
In the {{addOptionGroup()}} method, while the code correctly sets
{{{}option.setRequired(false){}}}, it does not remove the option's key from the
{{requiredOpts}} list. The {{addOption()}} method only adds to {{requiredOpts}}
when {{isRequired()}} is true, but never removes entries when the required
status changes.
{code:java}
[ERROR]
org.apache.commons.cli.OptionsTest.testRequiredOptionInGroupShouldNotBeInRequiredList
-- Time elapsed: 0.001 s <<< FAILURE!
org.opentest4j.AssertionFailedError: Option in group should NOT be in required
options list ==> expected: <false> but was: <true>
at
org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:151)
at
org.junit.jupiter.api.AssertionFailureBuilder.buildAndThrow(AssertionFailureBuilder.java:132)
at org.junit.jupiter.api.AssertFalse.failNotFalse(AssertFalse.java:63)
at org.junit.jupiter.api.AssertFalse.assertFalse(AssertFalse.java:36)
at org.junit.jupiter.api.Assertions.assertFalse(Assertions.java:239)
at
org.apache.commons.cli.OptionsTest.testRequiredOptionInGroupShouldNotBeInRequiredList(OptionsTest.java:55)
at java.lang.reflect.Method.invoke(Method.java:498)
at java.util.ArrayList.forEach(ArrayList.java:1259)
at java.util.ArrayList.forEach(ArrayList.java:1259) {code}
*Proposed Fix:*
The {{addOptionGroup()}} method should remove the option from {{requiredOpts}}
after setting required to false:
{code:java}
public Options addOptionGroup(final OptionGroup group) {
if (group.isRequired()) {
requiredOpts.add(group);
}
for (final Option option : group.getOptions()) {
option.setRequired(false);
// Remove option from requiredOpts list
requiredOpts.remove(option.getKey());
addOption(option);
optionGroups.put(option.getKey(), group);
}
return this;
} {code}
--
This message was sent by Atlassian Jira
(v8.20.10#820010)