mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

matthew_swift
21.27.2007 416f05e35758995eedd5a5a87d0a7326dbbbc4cb
Add support for trailing arguments in sub-command argument parser (includes unit tests).
3 files added
2 files modified
781 ■■■■■ changed files
opends/src/server/org/opends/server/util/args/SubCommand.java 175 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/util/args/SubCommandArgumentParser.java 102 ●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/util/args/ArgsTestCase.java 42 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/util/args/TestSubCommand.java 297 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/util/args/TestSubCommandArgumentParser.java 165 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/util/args/SubCommand.java
@@ -28,6 +28,7 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
@@ -67,30 +68,95 @@
  // The argument parser with which this subcommand is associated.
  private SubCommandArgumentParser parser;
  // Indicates whether this parser will allow additional unnamed
  // arguments at the end of the list.
  private boolean allowsTrailingArguments;
  // The maximum number of unnamed trailing arguments that may be
  // provided.
  private int maxTrailingArguments;
  // The minimum number of unnamed trailing arguments that may be
  // provided.
  private int minTrailingArguments;
  // The display name that will be used for the trailing arguments in
  // the usage information.
  private String trailingArgsDisplayName;
  /**
   * Creates a new subcommand with the provided information. The
   * subcommand will be automatically registered with the associated
   * parser.
   *
   * @param parser
   *          The argument parser with which this subcommand is
   *          associated.
   * @param name
   *          The name of this subcommand.
   * @param descriptionID
   *          The unique ID for the description of this subcommand.
   * @param descriptionArgs
   *          The arguments to use to generate the description string
   *          for this subcommand.
   * @throws ArgumentException
   *           If the associated argument parser already has a
   *           subcommand with the same name.
   */
  public SubCommand(SubCommandArgumentParser parser, String name,
      int descriptionID, Object... descriptionArgs) throws ArgumentException
  {
    this(parser, name, false, 0, 0, null, descriptionID, descriptionArgs);
  }
  /**
   * Creates a new subcommand with the provided information.  The subcommand
   * will be automatically registered with the associated parser.
   * Creates a new subcommand with the provided information. The
   * subcommand will be automatically registered with the associated
   * parser.
   *
   * @param  parser           The argument parser with which this subcommand is
   *                          associated.
   * @param  name             The name of this subcommand.
   * @param  descriptionID    The unique ID for the description of this
   *                          subcommand.
   * @param  descriptionArgs  The arguments to use to generate the description
   *                          string for this subcommand.
   *
   * @throws  ArgumentException  If the associated argument parser already has a
   *                             subcommand with the same name.
   * @param parser
   *          The argument parser with which this subcommand is
   *          associated.
   * @param name
   *          The name of this subcommand.
   * @param allowsTrailingArguments
   *          Indicates whether this parser allows unnamed trailing
   *          arguments to be provided.
   * @param minTrailingArguments
   *          The minimum number of unnamed trailing arguments that
   *          must be provided. A value less than or equal to zero
   *          indicates that no minimum will be enforced.
   * @param maxTrailingArguments
   *          The maximum number of unnamed trailing arguments that
   *          may be provided. A value less than or equal to zero
   *          indicates that no maximum will be enforced.
   * @param trailingArgsDisplayName
   *          The display name that should be used as a placeholder
   *          for unnamed trailing arguments in the generated usage
   *          information.
   * @param descriptionID
   *          The unique ID for the description of this subcommand.
   * @param descriptionArgs
   *          The arguments to use to generate the description string
   *          for this subcommand.
   * @throws ArgumentException
   *           If the associated argument parser already has a
   *           subcommand with the same name.
   */
  public SubCommand(SubCommandArgumentParser parser, String name,
                    int descriptionID, Object... descriptionArgs)
         throws ArgumentException
      boolean allowsTrailingArguments, int minTrailingArguments,
      int maxTrailingArguments, String trailingArgsDisplayName,
      int descriptionID, Object... descriptionArgs) throws ArgumentException
  {
    this.parser        = parser;
    this.name          = name;
    this.parser = parser;
    this.name = name;
    this.descriptionID = descriptionID;
    this.allowsTrailingArguments = allowsTrailingArguments;
    this.minTrailingArguments = minTrailingArguments;
    this.maxTrailingArguments = maxTrailingArguments;
    this.trailingArgsDisplayName = trailingArgsDisplayName;
    String nameToCheck = name;
    if (parser.longArgumentsCaseSensitive())
@@ -117,7 +183,7 @@
  /**
   * Retrieves the name of this subcommand.
   *
   * @return  The name of this subcommand.
   * @return The name of this subcommand.
   */
  public String getName()
  {
@@ -309,5 +375,80 @@
      longIDMap.put(longID, argument);
    }
  }
  /**
   * Indicates whether this sub-command will allow unnamed trailing
   * arguments. These will be arguments at the end of the list that
   * are not preceded by either a long or short identifier and will
   * need to be manually parsed by the application using this parser.
   * Note that once an unnamed trailing argument has been identified,
   * all remaining arguments will be classified as such.
   *
   * @return <CODE>true</CODE> if this sub-command allows unnamed
   *         trailing arguments, or <CODE>false</CODE> if it does
   *         not.
   */
  public boolean allowsTrailingArguments()
  {
    return allowsTrailingArguments;
  }
  /**
   * Retrieves the minimum number of unnamed trailing arguments that
   * must be provided.
   *
   * @return The minimum number of unnamed trailing arguments that
   *         must be provided, or a value less than or equal to zero
   *         if no minimum will be enforced.
   */
  public int getMinTrailingArguments()
  {
    return minTrailingArguments;
  }
  /**
   * Retrieves the maximum number of unnamed trailing arguments that
   * may be provided.
   *
   * @return The maximum number of unnamed trailing arguments that may
   *         be provided, or a value less than or equal to zero if no
   *         maximum will be enforced.
   */
  public int getMaxTrailingArguments()
  {
    return maxTrailingArguments;
  }
  /**
   * Retrieves the trailing arguments display name.
   *
   * @return Returns the trailing arguments display name.
   */
  public String getTrailingArgumentsDisplayName()
  {
    return trailingArgsDisplayName;
  }
  /**
   * Retrieves the set of unnamed trailing arguments that were provided on the
   * command line.
   *
   * @return  The set of unnamed trailing arguments that were provided on the
   *          command line.
   */
  public ArrayList<String> getTrailingArguments()
  {
    return parser.getTrailingArguments();
  }
}
opends/src/server/org/opends/server/util/args/SubCommandArgumentParser.java
@@ -31,9 +31,12 @@
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Properties;
import java.util.SortedMap;
import java.util.TreeMap;
import org.opends.server.core.DirectoryServer;
@@ -61,6 +64,9 @@
  // The argument that will be used to trigger the display of usage information.
  private Argument usageArgument;
  // The set of unnamed trailing arguments that were provided for this parser.
  private ArrayList<String> trailingArguments;
  // Indicates whether subcommand and long argument names should be treated in a
  // case-sensitive manner.
  private boolean longArgumentsCaseSensitive;
@@ -82,7 +88,7 @@
  // The set of subcommands defined for this parser, referenced by subcommand
  // name.
  private HashMap<String,SubCommand> subCommands;
  private SortedMap<String,SubCommand> subCommands;
  // The total set of global arguments defined for this parser.
  private LinkedList<Argument> globalArgumentList;
@@ -128,11 +134,12 @@
    this.toolDescription            = toolDescription;
    this.longArgumentsCaseSensitive = longArgumentsCaseSensitive;
    trailingArguments  = new ArrayList<String>();
    globalArgumentList = new LinkedList<Argument>();
    globalArgumentMap  = new HashMap<String,Argument>();
    globalShortIDMap   = new HashMap<Character,Argument>();
    globalLongIDMap    = new HashMap<String,Argument>();
    subCommands        = new HashMap<String,SubCommand>();
    subCommands        = new TreeMap<String,SubCommand>();
    usageDisplayed     = false;
    rawArguments       = null;
    subCommand         = null;
@@ -331,7 +338,7 @@
   * @return  The set of subcommands defined for this argument parser,
   *          referenced by subcommand name.
   */
  public HashMap<String,SubCommand> getSubCommands()
  public SortedMap<String,SubCommand> getSubCommands()
  {
    return subCommands;
  }
@@ -649,19 +656,35 @@
         throws ArgumentException
  {
    this.rawArguments = rawArguments;
    this.subCommand = null;
    this.trailingArguments = new ArrayList<String>();
    this.usageDisplayed = false;
    boolean inTrailingArgs = false;
    int numArguments = rawArguments.length;
    for (int i=0; i < numArguments; i++)
    {
      String arg = rawArguments[i];
      if (inTrailingArgs)
      {
        trailingArguments.add(arg);
        if ((subCommand.getMaxTrailingArguments() > 0) &&
            (trailingArguments.size() > subCommand.getMaxTrailingArguments()))
        {
          int    msgID   = MSGID_ARGPARSER_TOO_MANY_TRAILING_ARGS;
          String message = getMessage(msgID, subCommand
              .getMaxTrailingArguments());
          throw new ArgumentException(msgID, message);
        }
        continue;
      }
      if (arg.equals("--"))
      {
        // This is not legal because we don't allow unnamed trailing arguments
        // in this parser.
        int    msgID   = MSGID_SUBCMDPARSER_LONG_ARG_WITHOUT_NAME;
        String message = getMessage(msgID, arg);
        throw new ArgumentException(msgID, message);
        inTrailingArgs = true;
      }
      else if (arg.startsWith("--"))
      {
@@ -1056,11 +1079,26 @@
          }
        }
      }
      else if (subCommand != null)
      {
        // It's not a short or long identifier and the sub-command has
        // already been specified, so it must be the first trailing argument.
        if (subCommand.allowsTrailingArguments())
        {
          trailingArguments.add(arg);
          inTrailingArgs = true;
        }
        else
        {
          // Trailing arguments are not allowed for this sub-command.
          int    msgID   = MSGID_ARGPARSER_DISALLOWED_TRAILING_ARGUMENT;
          String message = getMessage(msgID, arg);
          throw new ArgumentException(msgID, message);
        }
      }
      else
      {
        // It's not a short or long identifier, so check to see if it is a
        // subcommand name.  If not, then it's invalid.  If so, then make sure
        // that it was the only subcommand provided.
        // It must be the sub-command.
        String nameToCheck = arg;
        if (! longArgumentsCaseSensitive)
        {
@@ -1074,19 +1112,29 @@
          String message = getMessage(msgID, arg);
          throw new ArgumentException(msgID, message);
        }
        else if (subCommand == null)
        {
          subCommand = sc;
        }
        else
        {
          int    msgID   = MSGID_SUBCMDPARSER_MULTIPLE_SUBCOMMANDS;
          String message = getMessage(msgID, arg, subCommand.getName());
          throw new ArgumentException(msgID, message);
          subCommand = sc;
        }
      }
    }
    // If we have a sub-command and it allows trailing arguments and
    // there is a minimum number, then make sure at least that many
    // were provided.
    if (subCommand != null)
    {
      int minTrailingArguments = subCommand.getMinTrailingArguments();
      if (subCommand.allowsTrailingArguments() && (minTrailingArguments > 0))
      {
        if (trailingArguments.size() < minTrailingArguments)
        {
          int msgID = MSGID_ARGPARSER_TOO_FEW_TRAILING_ARGUMENTS;
          String message = getMessage(msgID, minTrailingArguments);
          throw new ArgumentException(msgID, message);
        }
      }
    }
    // Iterate through all the global arguments and make sure that they have
    // values or a suitable default is available.
@@ -1321,6 +1369,10 @@
    buffer.append(" ");
    buffer.append(subCommand.getName());
    buffer.append(" {options}");
    if (subCommand.allowsTrailingArguments()) {
      buffer.append(' ');
      buffer.append(subCommand.getTrailingArgumentsDisplayName());
    }
    buffer.append(EOL);
    buffer.append(subCommand.getDescription());
    buffer.append(EOL);
@@ -1479,6 +1531,20 @@
  /**
   * Retrieves the set of unnamed trailing arguments that were provided on the
   * command line.
   *
   * @return  The set of unnamed trailing arguments that were provided on the
   *          command line.
   */
  public ArrayList<String> getTrailingArguments()
  {
    return trailingArguments;
  }
  /**
   * Indicates whether the usage information has been displayed to the end user
   * either by an explicit argument like "-H" or "--help", or by a built-in
   * argument like "-?".
opends/tests/unit-tests-testng/src/server/org/opends/server/util/args/ArgsTestCase.java
New file
@@ -0,0 +1,42 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 */
package org.opends.server.util.args;
import org.opends.server.DirectoryServerTestCase;
import org.testng.annotations.Test;
/**
 * An abstract class that all args unit tests should extend.
 */
@Test(groups = { "precommit", "util" })
public abstract class ArgsTestCase extends DirectoryServerTestCase {
  // No implementation required.
}
opends/tests/unit-tests-testng/src/server/org/opends/server/util/args/TestSubCommand.java
New file
@@ -0,0 +1,297 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2007 Sun Microsystems, Inc.
 */
package org.opends.server.util.args;
import java.util.Arrays;
import org.testng.Assert;
import org.testng.annotations.Test;
/**
 * Unit tests for the SubCommand class.
 */
public final class TestSubCommand extends ArgsTestCase {
  /**
   * Tests that allowsTrailingArguments works correctly.
   *
   * @throws Exception
   *           If an unexpected problem occurred.
   */
  @Test
  public void testAllowsTrailingArgumentsFalse1() throws Exception {
    SubCommandArgumentParser parser = new SubCommandArgumentParser(this
        .getClass().getName(), "test description", true);
    SubCommand sc = new SubCommand(parser, "sub-command1", 1000);
    Assert.assertFalse(sc.allowsTrailingArguments());
  }
  /**
   * Tests that allowsTrailingArguments works correctly.
   *
   * @throws Exception
   *           If an unexpected problem occurred.
   */
  @Test
  public void testAllowsTrailingArgumentsFalse2() throws Exception {
    SubCommandArgumentParser parser = new SubCommandArgumentParser(this
        .getClass().getName(), "test description", true);
    SubCommand sc = new SubCommand(parser, "sub-command2", false, 0, 0, null,
        2000);
    Assert.assertFalse(sc.allowsTrailingArguments());
  }
  /**
   * Tests that allowsTrailingArguments works correctly.
   *
   * @throws Exception
   *           If an unexpected problem occurred.
   */
  @Test
  public void testAllowsTrailingArgumentsTrue() throws Exception {
    SubCommandArgumentParser parser = new SubCommandArgumentParser(this
        .getClass().getName(), "test description", true);
    SubCommand sc = new SubCommand(parser, "sub-command2", true, 2, 4,
        "args1 arg2 [arg3 arg4]", 2000);
    Assert.assertTrue(sc.allowsTrailingArguments());
  }
  /**
   * Tests that getMaxTrailingArguments works correctly.
   *
   * @throws Exception
   *           If an unexpected problem occurred.
   */
  @Test
  public void testGetMaxTrailingArguments1() throws Exception {
    SubCommandArgumentParser parser = new SubCommandArgumentParser(this
        .getClass().getName(), "test description", true);
    SubCommand sc = new SubCommand(parser, "sub-command1", 1000);
    Assert.assertEquals(sc.getMaxTrailingArguments(), 0);
  }
  /**
   * Tests that getMaxTrailingArguments works correctly.
   *
   * @throws Exception
   *           If an unexpected problem occurred.
   */
  @Test
  public void testGetMaxTrailingArguments2() throws Exception {
    SubCommandArgumentParser parser = new SubCommandArgumentParser(this
        .getClass().getName(), "test description", true);
    SubCommand sc = new SubCommand(parser, "sub-command2", false, 0, 0, null,
        2000);
    Assert.assertEquals(sc.getMaxTrailingArguments(), 0);
  }
  /**
   * Tests that getMaxTrailingArguments works correctly.
   *
   * @throws Exception
   *           If an unexpected problem occurred.
   */
  @Test
  public void testGetMaxTrailingArguments3() throws Exception {
    SubCommandArgumentParser parser = new SubCommandArgumentParser(this
        .getClass().getName(), "test description", true);
    SubCommand sc = new SubCommand(parser, "sub-command2", true, 2, 4,
        "args1 arg2 [arg3 arg4]", 2000);
    Assert.assertEquals(sc.getMaxTrailingArguments(), 4);
  }
  /**
   * Tests that getMinTrailingArguments works correctly.
   *
   * @throws Exception
   *           If an unexpected problem occurred.
   */
  @Test
  public void testGetMinTrailingArguments1() throws Exception {
    SubCommandArgumentParser parser = new SubCommandArgumentParser(this
        .getClass().getName(), "test description", true);
    SubCommand sc = new SubCommand(parser, "sub-command1", 1000);
    Assert.assertEquals(sc.getMinTrailingArguments(), 0);
  }
  /**
   * Tests that getMinTrailingArguments works correctly.
   *
   * @throws Exception
   *           If an unexpected problem occurred.
   */
  @Test
  public void testGetMinTrailingArguments2() throws Exception {
    SubCommandArgumentParser parser = new SubCommandArgumentParser(this
        .getClass().getName(), "test description", true);
    SubCommand sc = new SubCommand(parser, "sub-command2", false, 0, 0, null,
        2000);
    Assert.assertEquals(sc.getMinTrailingArguments(), 0);
  }
  /**
   * Tests that getMinTrailingArguments works correctly.
   *
   * @throws Exception
   *           If an unexpected problem occurred.
   */
  @Test
  public void testGetMinTrailingArguments3() throws Exception {
    SubCommandArgumentParser parser = new SubCommandArgumentParser(this
        .getClass().getName(), "test description", true);
    SubCommand sc = new SubCommand(parser, "sub-command2", true, 2, 4,
        "args1 arg2 [arg3 arg4]", 2000);
    Assert.assertEquals(sc.getMinTrailingArguments(), 2);
  }
  /**
   * Tests that getTrailingArgumentsDisplayName works correctly.
   *
   * @throws Exception
   *           If an unexpected problem occurred.
   */
  @Test
  public void testGetTrailingArgumentsDisplayName1() throws Exception {
    SubCommandArgumentParser parser = new SubCommandArgumentParser(this
        .getClass().getName(), "test description", true);
    SubCommand sc = new SubCommand(parser, "sub-command1", 1000);
    Assert.assertNull(sc.getTrailingArgumentsDisplayName());
  }
  /**
   * Tests that getTrailingArgumentsDisplayName works correctly.
   *
   * @throws Exception
   *           If an unexpected problem occurred.
   */
  @Test
  public void testGetTrailingArgumentsDisplayName2() throws Exception {
    SubCommandArgumentParser parser = new SubCommandArgumentParser(this
        .getClass().getName(), "test description", true);
    SubCommand sc = new SubCommand(parser, "sub-command2", false, 0, 0, null,
        2000);
    Assert.assertNull(sc.getTrailingArgumentsDisplayName());
  }
  /**
   * Tests that getTrailingArgumentsDisplayName works correctly.
   *
   * @throws Exception
   *           If an unexpected problem occurred.
   */
  @Test
  public void testGetTrailingArgumentsDisplayName3() throws Exception {
    SubCommandArgumentParser parser = new SubCommandArgumentParser(this
        .getClass().getName(), "test description", true);
    SubCommand sc = new SubCommand(parser, "sub-command2", true, 2, 4,
        "args1 arg2 [arg3 arg4]", 2000);
    Assert.assertEquals(sc.getTrailingArgumentsDisplayName(),
        "args1 arg2 [arg3 arg4]");
  }
  /**
   * Tests that getTrailingArguments works correctly.
   *
   * @throws Exception
   *           If an unexpected problem occurred.
   */
  @Test
  public void testGetTrailingArguments1() throws Exception {
    SubCommandArgumentParser parser = new SubCommandArgumentParser(this
        .getClass().getName(), "test description", true);
    SubCommand sc = new SubCommand(parser, "sub-command1", 1000);
    parser.parseArguments(new String[] { "sub-command1" });
    Assert.assertTrue(sc.getTrailingArguments().isEmpty());
  }
  /**
   * Tests that getTrailingArguments works correctly.
   *
   * @throws Exception
   *           If an unexpected problem occurred.
   */
  @Test
  public void testGetTrailingArguments2() throws Exception {
    SubCommandArgumentParser parser = new SubCommandArgumentParser(this
        .getClass().getName(), "test description", true);
    SubCommand sc = new SubCommand(parser, "sub-command2", false, 0, 0, null,
        2000);
    parser.parseArguments(new String[] { "sub-command2" });
    Assert.assertTrue(sc.getTrailingArguments().isEmpty());
  }
  /**
   * Tests that getTrailingArguments works correctly.
   *
   * @throws Exception
   *           If an unexpected problem occurred.
   */
  @Test
  public void testGetTrailingArguments3() throws Exception {
    SubCommandArgumentParser parser = new SubCommandArgumentParser(this
        .getClass().getName(), "test description", true);
    SubCommand sc = new SubCommand(parser, "sub-command2", true, 2, 4,
        "args1 arg2 [arg3 arg4]", 2000);
    parser
        .parseArguments(new String[] { "sub-command2", "arg1", "arg2", "arg3" });
    Assert.assertEquals(sc.getTrailingArguments(), Arrays.asList(new String[] {
        "arg1", "arg2", "arg3" }));
  }
}
opends/tests/unit-tests-testng/src/server/org/opends/server/util/args/TestSubCommandArgumentParser.java
New file
@@ -0,0 +1,165 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2007 Sun Microsystems, Inc.
 */
package org.opends.server.util.args;
import java.util.Arrays;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/**
 * Unit tests for the SubCommand class.
 */
public final class TestSubCommandArgumentParser extends ArgsTestCase {
  // The sub-command parser.
  private SubCommandArgumentParser parser;
  // First sub-command.
  private SubCommand sc1;
  // Second sub-command.
  private SubCommand sc2;
  /**
   * Create the sub-commands and parser.
   *
   * @throws Exception
   *           If something unexpected happened.
   */
  @BeforeClass
  public void setup() throws Exception {
    parser = new SubCommandArgumentParser(this.getClass().getName(),
        "test description", true);
    sc1 = new SubCommand(parser, "sub-command1", 1000);
    sc2 = new SubCommand(parser, "sub-command2", true, 2, 4,
        "args1 arg2 [arg3 arg4]", 2000);
  }
  /**
   * Test the getSubCommand method.
   *
   * @throws Exception
   *           If something unexpected happened.
   */
  @Test
  public void testGetSubCommand() throws Exception {
    Assert.assertSame(parser.getSubCommand("sub-command1"), sc1);
    Assert.assertSame(parser.getSubCommand("sub-command2"), sc2);
    Assert.assertNull(parser.getSubCommand("sub-command3"));
  }
  /**
   * Provide valid command line args.
   *
   * @return Array of valid command line args.
   */
  @DataProvider(name = "validCommandLineArgs")
  public Object[][] createValidCommandLineArgs() {
    return new Object[][] {
        { new String[] {}, null },
        { new String[] { "sub-command1" }, sc1 },
        { new String[] { "sub-command2", "one", "two" }, sc2 },
        { new String[] { "sub-command2", "one", "two", "three" }, sc2 },
        { new String[] { "sub-command2", "one", "two", "three", "four" }, sc2 }, };
  }
  /**
   * Test the parseArguments method with valid args.
   *
   * @param args
   *          The command line args.
   * @param sc
   *          The expected sub-command.
   * @throws Exception
   *           If something unexpected happened.
   */
  @Test(dataProvider = "validCommandLineArgs")
  public void testParseArgumentsWithValidArgs(String[] args, SubCommand sc)
      throws Exception {
    parser.parseArguments(args);
    // Check the correct sub-command was parsed.
    Assert.assertEquals(parser.getSubCommand(), sc);
    // Check that the trailing arguments were retrieved correctly and
    // in the right order.
    if (args.length > 1) {
      Assert.assertEquals(parser.getTrailingArguments(), Arrays.asList(Arrays
          .copyOfRange(args, 1, args.length)));
    } else {
      Assert.assertTrue(parser.getTrailingArguments().isEmpty());
    }
  }
  /**
   * Provide invalid command line args.
   *
   * @return Array of invalid command line args.
   */
  @DataProvider(name = "invalidCommandLineArgs")
  public Object[][] createInvalidCommandLineArgs() {
    return new Object[][] {
        { new String[] { "sub-command1", "one" } },
        { new String[] { "sub-command1", "one", "two" } },
        { new String[] { "sub-command2" } },
        { new String[] { "sub-command2", "one" } },
        { new String[] { "sub-command2", "one", "two", "three", "four", "five" } }, };
  }
  /**
   * Test the parseArguments method with invalid args.
   *
   * @param args
   *          The command line args.
   * @throws Exception
   *           If something unexpected happened.
   */
  @Test(dataProvider = "invalidCommandLineArgs", expectedExceptions = ArgumentException.class)
  public void testParseArgumentsWithInvalidArgs(String[] args) throws Exception {
    parser.parseArguments(args);
  }
}