Skip to content
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

Incorrect results when using ArgGroup + defaultValue + split + List/Set #2349

Open
mithungonsalvez opened this issue Nov 4, 2024 · 2 comments
Milestone

Comments

@mithungonsalvez
Copy link

mithungonsalvez commented Nov 4, 2024

Hello,

When using the features ArgsGroup along with defaultValue and split, the value reported from the second group is not correct as per the arguments provided.

Sample code with error:

public class TestParser {

    public static void main(String[] ignore) {
        String[] rawArgs = new String[]{
                "--type=ONE", "--actions=CREATE,DELETE",
                "--type=TWO", "--actions=CREATE",
                "--type=THREE",
                "--type=FOUR", "--actions=CREATE,UPDATE"
        };
        Args args = new Args();
        new CommandLine(args).parseArgs(rawArgs);

        args.groups.forEach(g -> System.out.printf("%5s = %s\n", g.type, g.actions));
    }

    public static class Args {
        @ArgGroup(exclusive = false, multiplicity = "1..4")
        private List<Group> groups;
    }

    public static class Group {
        @Option(names = "--type", required = true)
        private String type;

        @Option(names = "--actions", defaultValue = "CREATE,UPDATE,DELETE", split = ",")
        private Set<String> actions;
    }

}

Actual Result:

  ONE = [CREATE, DELETE]
  TWO = [CREATE, UPDATE, DELETE]
THREE = [CREATE, UPDATE, DELETE]
 FOUR = [CREATE, UPDATE, DELETE]

Expected Result:

  ONE = [CREATE, DELETE]
  TWO = [CREATE]
THREE = [CREATE, UPDATE, DELETE]
 FOUR = [CREATE, UPDATE]

Here, we can see that the results are using the default value starting from the second item in the ArgGroup.

Details:

JDK: temurin-21.jdk
Picocli version: 4.7.6
@remkop
Copy link
Owner

remkop commented Nov 4, 2024

Thank you for raising this!

I'll have to look with -Dpicocli.trace=INFO (or =DEBUG) to see what is happening.

@remkop remkop added this to the 4.7.7 milestone Dec 9, 2024
@remkop
Copy link
Owner

remkop commented Dec 20, 2024

Note to self:

package picocli;

import org.junit.Test;
import picocli.CommandLine.ArgGroup;
import picocli.CommandLine.Option;

import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import static org.junit.Assert.assertEquals;

public class Issue2349 {
    static class TestParser {
        static class Args {
            @ArgGroup(exclusive = false, multiplicity = "1..4")
            private List<Group> groups;
        }

        static class Group {
            @Option(names = "--type", required = true)
            private String type;

            @Option(names = "--actions", defaultValue = "CREATE,UPDATE,DELETE", split = ",")
            private Set<String> actions;

            public Group() {}

            Group(String type, Set<String> actions) {
                this.type = type;
                this.actions = actions;
            }

            @Override
            public boolean equals(Object o) {
                if (this == o) return true;
                if (o == null || getClass() != o.getClass()) return false;
                Group group = (Group) o;
                return equals(type, group.type) && equals(actions, group.actions);
            }
            public static boolean equals(Object a, Object b) {
                return (a == b) || (a != null && a.equals(b));
            }

            @Override
            public int hashCode() {
                return Arrays.hashCode(new Object[] {type, actions});
            }

            @Override
            public String toString() {
                return String.format("%s %s", type, actions);
            }
        }
    }

    @Test
    public void issue2349() {
        String[] rawArgs = new String[]{
            "--type=ONE", "--actions=CREATE,DELETE",
            "--type=TWO", "--actions=CREATE",
            "--type=THREE",
            "--type=FOUR", "--actions=CREATE,UPDATE"
        };
        TestParser.Args args = new TestParser.Args();
        new CommandLine(args).parseArgs(rawArgs);

        TestParser.Group[] expected = new TestParser.Group[] {
            new TestParser.Group("ONE", new HashSet<>(Arrays.asList("CREATE", "DELETE"))),
            new TestParser.Group("TWO", new HashSet<>(Arrays.asList("CREATE"))),
            new TestParser.Group("THREE", new HashSet<>(Arrays.asList("CREATE", "UPDATE", "DELETE"))),
            new TestParser.Group("FOUR", new HashSet<>(Arrays.asList("CREATE", "UPDATE"))),
        };

        for (int i = 0; i < expected.length; i++) {
            TestParser.Group actual = args.groups.get(i);
            assertEquals("group[" + i + "]", expected[i], actual);
        }
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants