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)

Reply via email to