From 76bbe43ece90ad78306ba2e5c349f33f0bf13fde Mon Sep 17 00:00:00 2001 From: Neil Wilson Date: Mon, 28 Nov 2022 14:10:18 -0600 Subject: [PATCH] Fix an issue with mutually dependent arguments Fixed a bug in the argument parser's support for mutually dependent arguments. In a mutually dependent argument set, if any one of the arguments is provided, then all of the other arguments in the set must also be provided, but there was a problem with support for sets containing three or more elements. In such cases, the argument parser would only enforce that at least two arguments from the set were present. --- docs/release-notes.html | 10 ++ .../unboundid/util/args/ArgumentParser.java | 13 ++- .../util/args/ArgumentParserTestCase.java | 104 +++++++++++++++++- 3 files changed, 119 insertions(+), 8 deletions(-) diff --git a/docs/release-notes.html b/docs/release-notes.html index 4061bfad5..06b61973c 100644 --- a/docs/release-notes.html +++ b/docs/release-notes.html @@ -27,6 +27,16 @@

Version 6.0.7



+
  • + Fixed a bug in the argument parser's support for mutually dependent arguments. + In a mutually dependent argument set, if any one of the arguments is provided, + then all of the other arguments in the set must also be provided, but there was + a problem with support for sets containing three or more elements. In such + cases, the argument parser would only enforce that at least two arguments from + the set were present. +

    +
  • +
  • Added JSONObject methods for retrieving fields by name using case-insensitive matching. By default, JSON field names are treated in a case-sensitive manner, diff --git a/src/com/unboundid/util/args/ArgumentParser.java b/src/com/unboundid/util/args/ArgumentParser.java index aea6156da..18f8288a1 100644 --- a/src/com/unboundid/util/args/ArgumentParser.java +++ b/src/com/unboundid/util/args/ArgumentParser.java @@ -55,7 +55,6 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.LinkedHashMap; @@ -1488,12 +1487,14 @@ public void addMutuallyDependentArgumentSet( " that is not registered with the argument parser."); } - final Set allArgsSet = new HashSet<>(arguments); - for (final Argument a : allArgsSet) + final List allArgsList = new ArrayList<>(arguments); + for (int i=0; i < allArgsList.size(); i++) { - final Set dependentArgs = new HashSet<>(allArgsSet); - dependentArgs.remove(a); - addDependentArgumentSet(a, dependentArgs); + for (int j=(i+1); j < allArgsList.size(); j++) + { + addDependentArgumentSet(allArgsList.get(i), allArgsList.get(j)); + addDependentArgumentSet(allArgsList.get(j), allArgsList.get(i)); + } } } diff --git a/tests/unit/src/com/unboundid/util/args/ArgumentParserTestCase.java b/tests/unit/src/com/unboundid/util/args/ArgumentParserTestCase.java index dd84e1748..72c8b9c4f 100644 --- a/tests/unit/src/com/unboundid/util/args/ArgumentParserTestCase.java +++ b/tests/unit/src/com/unboundid/util/args/ArgumentParserTestCase.java @@ -604,13 +604,15 @@ public void testAddMutuallyDependentArgumentSet() assertNotNull(p.getDependentArgumentSets()); assertFalse(p.getDependentArgumentSets().isEmpty()); - assertEquals(p.getDependentArgumentSets().size(), 2); + assertEquals(p.getDependentArgumentSets().size(), 2, + String.valueOf(p.getDependentArgumentSets())); p.addMutuallyDependentArgumentSet(c, d, e); assertNotNull(p.getDependentArgumentSets()); assertFalse(p.getDependentArgumentSets().isEmpty()); - assertEquals(p.getDependentArgumentSets().size(), 5); + assertEquals(p.getDependentArgumentSets().size(), 8, + String.valueOf(p.getDependentArgumentSets())); try { @@ -702,6 +704,104 @@ public void testAddMutuallyDependentArgumentSet() { // This was expected. } + + + // Make sure that the parser properly rejects attempts to use mutually + // dependent arguments without each other. + try + { + p.reset(); + p.parse(new String[] { "-a" }); + fail("Expected an exception when providing a but not b"); + } + catch (final ArgumentException ex) + { + // This was expected. + } + + try + { + p.reset(); + p.parse(new String[] { "-b" }); + fail("Expected an exception when providing b but not a"); + } + catch (final ArgumentException ex) + { + // This was expected. + } + + p.reset(); + p.parse(new String[] { "-a", "-b" }); + + + try + { + p.reset(); + p.parse(new String[] { "-c" }); + fail("Expected an exception when providing c but not d or e"); + } + catch (final ArgumentException ex) + { + // This was expected. + } + + try + { + p.reset(); + p.parse(new String[] { "-d" }); + fail("Expected an exception when providing d but not c or e"); + } + catch (final ArgumentException ex) + { + // This was expected. + } + + try + { + p.reset(); + p.parse(new String[] { "-e" }); + fail("Expected an exception when providing e but not c or d"); + } + catch (final ArgumentException ex) + { + // This was expected. + } + + try + { + p.reset(); + p.parse(new String[] { "-c", "-d" }); + fail("Expected an exception when providing c and d but not e"); + } + catch (final ArgumentException ex) + { + // This was expected. + } + + try + { + p.reset(); + p.parse(new String[] { "-c", "-e" }); + fail("Expected an exception when providing c and e but not d"); + } + catch (final ArgumentException ex) + { + // This was expected. + } + + try + { + p.reset(); + p.parse(new String[] { "-d", "-e" }); + fail("Expected an exception when providing d and e but not c"); + } + catch (final ArgumentException ex) + { + // This was expected. + } + + p.reset(); + p.parse(new String[] { "-c", "-d", "-e" }); }