This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to branch master
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-launcher.git


The following commit(s) were added to refs/heads/master by this push:
     new 3cefbd3  SLING-10186 - Enhance cli parsing on sling-feature-launcher
3cefbd3 is described below

commit 3cefbd39ed17a9c880a07e2b4d7d5a1ce1526e35
Author: Stefan Bischof <[email protected]>
AuthorDate: Wed Mar 10 09:37:21 2021 +0100

    SLING-10186 - Enhance cli parsing on sling-feature-launcher
    
    - extract opts as Constants
    - add longOpt to Options
    - fix plural in description
    - use Builder-pattern to build Options
    - set numberOfArgs , valueSeparator(',')
    - accept (but ignore) empty options without ParsingExceptions
      using .optionalArg(true) and Optionals
    - option to set loglevel on verbose Option
    - update common-cli version
    - add cli parse tests
    
    Signed-off-by: Stefan Bischof <[email protected]>
---
 pom.xml                                            |   2 +-
 .../apache/sling/feature/launcher/impl/Main.java   | 316 ++++++++++++++-------
 .../sling/feature/launcher/impl/MainTest.java      | 151 +++++++++-
 3 files changed, 361 insertions(+), 108 deletions(-)

diff --git a/pom.xml b/pom.xml
index f8ed699..e16c2a0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -143,7 +143,7 @@
         <dependency>
              <groupId>commons-cli</groupId>
              <artifactId>commons-cli</artifactId>
-             <version>1.3.1</version>
+             <version>1.4</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
diff --git a/src/main/java/org/apache/sling/feature/launcher/impl/Main.java 
b/src/main/java/org/apache/sling/feature/launcher/impl/Main.java
index 1d182a4..3d5fcc9 100644
--- a/src/main/java/org/apache/sling/feature/launcher/impl/Main.java
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/Main.java
@@ -18,13 +18,20 @@ package org.apache.sling.feature.launcher.impl;
 
 import java.io.File;
 import java.util.AbstractMap;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Properties;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
-import org.apache.commons.cli.BasicParser;
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.DefaultParser;
 import org.apache.commons.cli.HelpFormatter;
 import org.apache.commons.cli.Option;
 import org.apache.commons.cli.Options;
@@ -34,30 +41,57 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * This is the launcher main class.
- * It parses command line parameters and prepares the launcher.
+ * This is the launcher main class. It parses command line parameters and
+ * prepares the launcher.
  */
 public class Main {
 
+    public static final String OPT_OSGI_FRAMEWORK_ARTIFACT = "fa";
+
+    public static final String OPT_FELIX_FRAMEWORK_VERSION = "fv";
+
+    public static final String OPT_EXTENSION_CONFIGURATION = "ec";
+
+    public static final String OPT_HOME_DIR = "p";
+
+    public static final String OPT_CACHE_DIR = "c";
+
+    public static final String OPT_VERBOSE = "v";
+
+    public static final String OPT_VARIABLE_VALUES = "V";
+
+    public static final String OPT_FRAMEWORK_PROPERTIES = "D";
+
+    public static final String OPT_FEATURE_FILES = "f";
+
+    public static final String OPT_REPOSITORY_URLS = "u";
+
+    public static final String OPT_CONFIG_CLASH = "CC";
+
+    public static final String OPT_ARTICACT_CLASH = "C";
+
     private static Logger LOGGER;
 
     private static Logger LOG() {
-        if ( LOGGER == null ) {
+
+        if (LOGGER == null) {
             LOGGER = LoggerFactory.getLogger("launcher");
         }
         return LOGGER;
     }
 
     /** Split a string into key and value */
-    static String[] split(final String val) {
-        final int pos = val.indexOf('=');
-        if ( pos == -1 ) {
-            return new String[] {val, "true"};
+    static String[] splitKeyVal(final String keyVal) {
+
+        final int pos = keyVal.indexOf('=');
+        if (pos == -1) {
+            return new String[] { keyVal, "true" };
         }
-        return new String[] {val.substring(0, pos), val.substring(pos + 1)};
+        return new String[] { keyVal.substring(0, pos), keyVal.substring(pos + 
1) };
     }
 
     static Map.Entry<String, Map<String, String>> splitMap(final String val) {
+
         String[] split1 = val.split(":");
 
         if (split1.length < 2) {
@@ -66,116 +100,199 @@ public class Main {
 
         Map<String, String> m = new HashMap<>();
         for (String kv : split1[1].split(",")) {
-            String[] keyval = split(kv);
+            String[] keyval = splitKeyVal(kv);
             m.put(keyval[0], keyval[1]);
         }
 
         return new AbstractMap.SimpleEntry<>(split1[0], m);
     }
 
+    private static Optional<String> extractValueFromOption(CommandLine cl, 
String opt) {
+
+        return extractValueFromOption(cl, opt, null);
+    }
+
+    private static Optional<String> extractValueFromOption(CommandLine cl, 
String opt,
+            String defaultVaue) {
+
+        return Optional.ofNullable(cl.getOptionValue(opt, defaultVaue));
+    }
+
+    private static Optional<List<String>> extractValuesFromOption(CommandLine 
cl, String opt) {
+
+        String[] values = cl.getOptionValues(opt);
+        if (Objects.isNull(values)) {
+            return Optional.empty();
+        }
+        return Optional.of(Stream.of(values).collect(Collectors.toList()));
+    }
+
     /**
      * Parse the command line parameters and update a configuration object.
+     * 
      * @param args Command line parameters
      * @return Configuration object.
      */
-    private static void parseArgs(final LauncherConfig config, final String[] 
args) {
-        final Options options = new Options();
-
-        final Option artifactClashOverride = new Option("C", true, "Set 
artifact clash override");
-        final Option configClashOverride = new Option("CC", true, "Set config 
clash override");
-        final Option repoOption =  new Option("u", true, "Set repository url");
-        final Option featureOption =  new Option("f", true, "Set feature 
files");
-        final Option fwkProperties = new Option("D", true, "Set framework 
properties");
-        final Option varValue = new Option("V", true, "Set variable value");
-        final Option debugOption = new Option("v", false, "Verbose");
-        debugOption.setArgs(0);
-        final Option cacheOption = new Option("c", true, "Set cache dir");
-        final Option homeOption = new Option("p", true, "Set home dir");
-
-        final Option extensionConfiguration = new Option("ec", true, "Provide 
extension configuration, format: extensionName:key1=val1,key2=val2");
-        final Option frameworkVersionOption = new Option("fv", true, "Set 
Apache Felix framework version (default 
".concat(Bootstrap.FELIX_FRAMEWORK_VERSION) + ")");
-        final Option frameworkArtifactOption = new Option("fa", true, "Set 
OSGi framework artifact (overrides Apache Felix framework version)");
-
-        options.addOption(artifactClashOverride);
-        options.addOption(configClashOverride);
-        options.addOption(repoOption);
-        options.addOption(featureOption);
-        options.addOption(fwkProperties);
-        options.addOption(varValue);
-        options.addOption(debugOption);
-        options.addOption(cacheOption);
-        options.addOption(homeOption);
-        options.addOption(extensionConfiguration);
-        options.addOption(frameworkVersionOption);
-        options.addOption(frameworkArtifactOption);
-
-        final CommandLineParser clp = new BasicParser();
+    protected static void parseArgs(final LauncherConfig config, final 
String[] args) {
+
+        final Option artifactClashOverride = Option.builder(OPT_ARTICACT_CLASH)
+                .longOpt("artifact-clash")
+                .desc("Set artifact clash override")
+                .optionalArg(true)
+                .numberOfArgs(Option.UNLIMITED_VALUES)
+                .build();
+
+        final Option configClashOverride = Option.builder(OPT_CONFIG_CLASH)
+                .longOpt("config-clash")
+                .desc("Set config clash override")
+                .optionalArg(true)
+                .numberOfArgs(Option.UNLIMITED_VALUES)
+                .build();
+
+        final Option repoOption = Option.builder(OPT_REPOSITORY_URLS)
+                .longOpt("repository-urls")
+                .desc("Set repository urls")
+                .optionalArg(true)
+                .valueSeparator(',')
+                .numberOfArgs(Option.UNLIMITED_VALUES)
+                .build();
+
+        final Option featureOption = Option.builder(OPT_FEATURE_FILES)
+                .longOpt("feature-files")
+                .desc("Set feature files")
+                .optionalArg(true)
+                .valueSeparator(',')
+                .numberOfArgs(Option.UNLIMITED_VALUES)
+                .build();
+
+        final Option fwkProperties = Option.builder(OPT_FRAMEWORK_PROPERTIES)
+                .longOpt("framework-properties")
+                .desc("Set framework properties")
+                .optionalArg(true)
+                .numberOfArgs(Option.UNLIMITED_VALUES)
+                .build();
+
+        final Option varValue = Option.builder(OPT_VARIABLE_VALUES)
+                .longOpt("variable-values")
+                .desc("Set variable values")
+                .optionalArg(true)
+                .numberOfArgs(Option.UNLIMITED_VALUES)
+                .build();
+
+        final Option debugOption = Option.builder(OPT_VERBOSE)
+                .longOpt("verbose")
+                .desc("Verbose")
+                .optionalArg(true)
+                .numberOfArgs(1)
+                .build();
+
+        final Option cacheOption = Option.builder(OPT_CACHE_DIR)
+                .longOpt("cache_dir")
+                .desc("Set cache dir")
+                .optionalArg(true)
+                .numberOfArgs(1)
+                .build();
+
+        final Option homeOption = Option.builder(OPT_HOME_DIR)
+                .longOpt("home_dir")
+                .desc("Set home dir")
+                .optionalArg(true)
+                .numberOfArgs(1)
+                .build();
+
+        final Option extensionConfiguration = 
Option.builder(OPT_EXTENSION_CONFIGURATION)
+                .longOpt("extension_configuration")
+                .desc("Provide extension configuration, format: 
extensionName:key1=val1,key2=val2")
+                .optionalArg(true)
+                .numberOfArgs(Option.UNLIMITED_VALUES)
+                .build();
+
+        final Option frameworkVersionOption = 
Option.builder(OPT_FELIX_FRAMEWORK_VERSION)
+                .longOpt("felix-framework-version")
+                .desc("Set Apache Felix framework version (default "
+                        .concat(Bootstrap.FELIX_FRAMEWORK_VERSION) + ")")
+                .optionalArg(true)
+                .numberOfArgs(1)
+                .build();
+
+        final Option frameworkArtifactOption = 
Option.builder(OPT_OSGI_FRAMEWORK_ARTIFACT)
+                .longOpt("osgi-framework-artifact")
+                .desc("Set OSGi framework artifact (overrides Apache Felix 
framework version)")
+                .optionalArg(true)
+                .numberOfArgs(1)
+                .build();
+
+        final Options options = new Options().addOption(artifactClashOverride)
+                .addOption(configClashOverride)
+                .addOption(repoOption)
+                .addOption(featureOption)
+                .addOption(fwkProperties)
+                .addOption(varValue)
+                .addOption(debugOption)
+                .addOption(cacheOption)
+                .addOption(homeOption)
+                .addOption(extensionConfiguration)
+                .addOption(frameworkVersionOption)
+                .addOption(frameworkArtifactOption);
+
+        final CommandLineParser clp = new DefaultParser();
         try {
             final CommandLine cl = clp.parse(options, args);
 
-            if ( cl.hasOption(repoOption.getOpt()) ) {
-                final String value = cl.getOptionValue(repoOption.getOpt());
-                config.setRepositoryUrls(value.split(","));
-            }
-            if ( cl.hasOption(artifactClashOverride.getOpt()) ) {
-                for(final String override : 
cl.getOptionValues(artifactClashOverride.getOpt())) {
-                    
config.getArtifactClashOverrides().add(ArtifactId.parse(override));
-                }
-            }
-            if ( cl.hasOption(configClashOverride.getOpt()) ) {
-                for(final String override : 
cl.getOptionValues(configClashOverride.getOpt())) {
-                    final String[] keyVal = split(override);
-                    config.getConfigClashOverrides().put(keyVal[0], keyVal[1]);
-                }
-            }
-            if ( cl.hasOption(fwkProperties.getOpt()) ) {
-                for(final String value : 
cl.getOptionValues(fwkProperties.getOpt())) {
-                    final String[] keyVal = split(value);
+            extractValuesFromOption(cl, OPT_REPOSITORY_URLS).ifPresent(
+                    values -> 
config.setRepositoryUrls(values.stream().toArray(String[]::new)));
 
-                    
config.getInstallation().getFrameworkProperties().put(keyVal[0], keyVal[1]);
-                }
-            }
-            if ( cl.hasOption(varValue.getOpt()) ) {
-                for(final String optVal : 
cl.getOptionValues(varValue.getOpt())) {
-                    final String[] keyVal = split(optVal);
+            extractValuesFromOption(cl, OPT_ARTICACT_CLASH).ifPresent(values 
-> values
+                    .forEach(v -> 
config.getArtifactClashOverrides().add(ArtifactId.parse(v))));
 
-                    config.getVariables().put(keyVal[0], keyVal[1]);
-                }
-            }
-            if ( cl.hasOption(debugOption.getOpt()) ) {
-                System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", 
"debug");
+            Properties cfgCProps = cl.getOptionProperties(OPT_CONFIG_CLASH);
+            for (final String name : cfgCProps.stringPropertyNames()) {
+                config.getConfigClashOverrides().put(name, 
cfgCProps.getProperty(name));
             }
 
-            if ( cl.hasOption(featureOption.getOpt()) ) {
-                for(final String optVal : 
cl.getOptionValues(featureOption.getOpt())) {
-                    config.addFeatureFiles(optVal.split(","));
-                }
+            Properties fwProps = 
cl.getOptionProperties(OPT_FRAMEWORK_PROPERTIES);
+            for (final String name : fwProps.stringPropertyNames()) {
+                config.getInstallation()
+                        .getFrameworkProperties()
+                        .put(name, fwProps.getProperty(name));
             }
-            if (cl.hasOption(cacheOption.getOpt())) {
-                config.setCacheDirectory(new 
File(cl.getOptionValue(cacheOption.getOpt())));
-            }
-            if (cl.hasOption(homeOption.getOpt())) {
-                config.setHomeDirectory(new 
File(cl.getOptionValue(homeOption.getOpt())));
-            }
-            if (cl.hasOption(extensionConfiguration.getOpt())) {
-                for(final String optVal : 
cl.getOptionValues(extensionConfiguration.getOpt())) {
-                    Map.Entry<String, Map<String, String>> xc = 
splitMap(optVal);
-                    Map<String, Map<String, String>> ec = 
config.getExtensionConfiguration();
-                    Map<String, String> c = ec.get(xc.getKey());
-                    if (c == null) {
-                        c = new HashMap<>();
-                        ec.put(xc.getKey(), c);
-                    }
-                    c.putAll(xc.getValue());
-                }
-            }
-            if (cl.hasOption(frameworkVersionOption.getOpt())) {
-                
config.setFrameworkVersion(cl.getOptionValue(frameworkVersionOption.getOpt()));
-            }
-            if (cl.hasOption(frameworkArtifactOption.getOpt())) {
-                
config.setFrameworkArtifact(cl.getOptionValue(frameworkArtifactOption.getOpt()));
+
+            Properties varProps = cl.getOptionProperties(OPT_VARIABLE_VALUES);
+            for (final String name : varProps.stringPropertyNames()) {
+                config.getVariables().put(name, varProps.getProperty(name));
             }
-        } catch ( final ParseException pe) {
+
+            extractValueFromOption(cl, OPT_VERBOSE, "debug").ifPresent(
+                    value -> 
System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", value));
+
+            extractValuesFromOption(cl, 
OPT_FEATURE_FILES).orElseGet(ArrayList::new)
+                    .forEach(config::addFeatureFiles);
+
+            extractValueFromOption(cl, OPT_CACHE_DIR).map(File::new)
+                    .ifPresent(config::setCacheDirectory);
+
+            extractValueFromOption(cl, OPT_HOME_DIR).map(File::new)
+                    .ifPresent(config::setHomeDirectory);
+
+            extractValuesFromOption(cl, OPT_EXTENSION_CONFIGURATION)
+                    .ifPresent(values -> values.forEach(v -> {
+                        Map.Entry<String, Map<String, String>> xc = 
splitMap(v);
+                        Map<String, Map<String, String>> ec = 
config.getExtensionConfiguration();
+                        Map<String, String> c = ec.get(xc.getKey());
+                        if (c == null) {
+                            c = new HashMap<>();
+                            ec.put(xc.getKey(), c);
+                        }
+                        c.putAll(xc.getValue());
+                    }));
+
+            extractValueFromOption(cl, OPT_FELIX_FRAMEWORK_VERSION)
+                    .ifPresent(config::setFrameworkVersion);
+
+            extractValueFromOption(cl, OPT_OSGI_FRAMEWORK_ARTIFACT)
+                    .ifPresent(config::setFrameworkArtifact);
+
+        } catch (final ParseException pe) {
             Main.LOG().error("Unable to parse command line: {}", 
pe.getMessage(), pe);
 
             HelpFormatter formatter = new HelpFormatter();
@@ -186,6 +303,7 @@ public class Main {
     }
 
     public static void main(final String[] args) {
+
         // setup logging
         System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "info");
         System.setProperty("org.slf4j.simpleLogger.showThreadName", "false");
diff --git a/src/test/java/org/apache/sling/feature/launcher/impl/MainTest.java 
b/src/test/java/org/apache/sling/feature/launcher/impl/MainTest.java
index ddcfe12..fad9f3f 100644
--- a/src/test/java/org/apache/sling/feature/launcher/impl/MainTest.java
+++ b/src/test/java/org/apache/sling/feature/launcher/impl/MainTest.java
@@ -16,36 +16,171 @@
  */
 package org.apache.sling.feature.launcher.impl;
 
-import org.junit.Test;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
 
 import java.util.AbstractMap;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
+import org.apache.sling.feature.ArtifactId;
+import org.junit.Test;
 
 public class MainTest {
+
     @Test
     public void testSplitCommandlineArgs() {
-        assertArrayEquals(new String[] {"hi", "ho"}, Main.split("hi=ho"));
-        assertArrayEquals(new String[] {"hi.de.hi", "true"}, 
Main.split("hi.de.hi"));
+
+        assertArrayEquals(new String[] { "hi", "ho" }, 
Main.splitKeyVal("hi=ho"));
+        assertArrayEquals(new String[] { "hi.de.hi", "true" }, 
Main.splitKeyVal("hi.de.hi"));
     }
 
     @Test
     public void testSplitMapCommandlineArgs() {
+
         assertEquals(new AbstractMap.SimpleEntry<>("foo", 
Collections.singletonMap("bar", "tar")),
                 Main.splitMap("foo:bar=tar"));
 
         assertEquals(new AbstractMap.SimpleEntry<>("hello", 
Collections.emptyMap()),
                 Main.splitMap("hello"));
 
-        Map<String,String> em = new HashMap<>();
+        Map<String, String> em = new HashMap<>();
         em.put("a.b.c", "d.e.f");
         em.put("h.i.j", "k.l.m");
         Map.Entry<String, Map<String, String>> e = new 
AbstractMap.SimpleEntry<>("ding.dong", em);
-        assertEquals(e,
-                Main.splitMap("ding.dong:a.b.c=d.e.f,h.i.j=k.l.m"));
+        assertEquals(e, Main.splitMap("ding.dong:a.b.c=d.e.f,h.i.j=k.l.m"));
+    }
+
+    LauncherConfig noActionAllowesConfig = mock(LauncherConfig.class, 
invocationOnMock -> {
+        throw new RuntimeException(invocationOnMock.getMethod().getName());
+    });
+
+    @Test
+    public void testParse() {
+
+        Main.parseArgs(noActionAllowesConfig, new String[] {});
+    }
+
+    @Test
+    public void testParseVerbose() {
+
+        Main.parseArgs(noActionAllowesConfig, new String[] { "-v", "debug" });
+        assertEquals("debug", 
System.getProperty("org.slf4j.simpleLogger.defaultLogLevel"));
+
+        Main.parseArgs(noActionAllowesConfig, new String[] { "-v" });
+        assertEquals("debug", 
System.getProperty("org.slf4j.simpleLogger.defaultLogLevel"));
+
+        Main.parseArgs(noActionAllowesConfig, new String[] { "-v", "warn" });
+        assertEquals("warn", 
System.getProperty("org.slf4j.simpleLogger.defaultLogLevel"));
+
+    }
+
+    @Test
+    public void testParseHome() {
+
+        Main.parseArgs(noActionAllowesConfig, new String[] { "-p" });
+
+        LauncherConfig config = new LauncherConfig();
+        Main.parseArgs(config, new String[] { "-p", "foo" });
+        assertEquals("foo", config.getHomeDirectory().toString());
+
+    }
+
+    @Test
+    public void testParseCacheDir() {
+
+        Main.parseArgs(noActionAllowesConfig, new String[] { "-c" });
+
+        LauncherConfig config = new LauncherConfig();
+        Main.parseArgs(config, new String[] { "-c", "foo" });
+        assertEquals("foo", config.getCacheDirectory().toString());
+
+    }
+
+    @Test
+    public void testParseFelixFwVersion() {
+
+        Main.parseArgs(noActionAllowesConfig, new String[] { "-fv" });
+
+        LauncherConfig config = new LauncherConfig();
+        Main.parseArgs(config, new String[] { "-fv", "foo" });
+        assertEquals("foo", config.getFrameworkVersion().toString());
+
+    }
+
+    @Test
+    public void testParseOSGiFwArtifact() {
+
+        Main.parseArgs(noActionAllowesConfig, new String[] { "-fa" });
+
+        LauncherConfig config = new LauncherConfig();
+        Main.parseArgs(config, new String[] { "-fa", "foo" });
+        assertEquals("foo", config.getFrameworkArtifact());
+
+    }
+
+    @Test
+    public void testParse_Artifact_Clash() {
+
+        Main.parseArgs(noActionAllowesConfig, new String[] { "-C" });
+
+        LauncherConfig config = new LauncherConfig();
+        Main.parseArgs(config, new String[] { "-C", "foo:bar:1" });
+        
assertTrue(config.getArtifactClashOverrides().contains(ArtifactId.parse("foo:bar:1")));
+
+        config = new LauncherConfig();
+        Main.parseArgs(config, new String[] { "-C", "foo:bar:1", "foo:bar:2" 
});
+        
assertTrue(config.getArtifactClashOverrides().contains(ArtifactId.parse("foo:bar:1")));
+        
assertTrue(config.getArtifactClashOverrides().contains(ArtifactId.parse("foo:bar:2")));
+
+        config = new LauncherConfig();
+        Main.parseArgs(config, new String[] { "-C", "foo:bar:1", "-C", 
"foo:bar:2" });
+        
assertTrue(config.getArtifactClashOverrides().contains(ArtifactId.parse("foo:bar:1")));
+        
assertTrue(config.getArtifactClashOverrides().contains(ArtifactId.parse("foo:bar:2")));
+
     }
+
+    @Test
+    public void testParse_RepoUrls() {
+
+        Main.parseArgs(noActionAllowesConfig, new String[] { "-u" });
+
+        LauncherConfig config = new LauncherConfig();
+        Main.parseArgs(config, new String[] { "-u", "foo" });
+        assertArrayEquals(config.getRepositoryUrls(), new Object[] { "foo" });
+
+        config = new LauncherConfig();
+        Main.parseArgs(config, new String[] { "-u", "foo", "bar" });
+        assertArrayEquals(config.getRepositoryUrls(), new Object[] { "foo", 
"bar" });
+
+        config = new LauncherConfig();
+        Main.parseArgs(config, new String[] { "-u", "foo", "-u", "bar" });
+        assertArrayEquals(config.getRepositoryUrls(), new Object[] { "foo", 
"bar" });
+
+    }
+
+    @Test
+    public void testParse_FeatureFiles() {
+
+        Main.parseArgs(noActionAllowesConfig, new String[] { "-f" });
+
+        LauncherConfig config = new LauncherConfig();
+        Main.parseArgs(config, new String[] { "-f", "foo" });
+        assertTrue(config.getFeatureFiles().contains("foo"));
+
+        config = new LauncherConfig();
+        Main.parseArgs(config, new String[] { "-f", "foo", "bar" });
+        assertTrue(config.getFeatureFiles().contains("foo"));
+        assertTrue(config.getFeatureFiles().contains("bar"));
+
+        config = new LauncherConfig();
+        Main.parseArgs(config, new String[] { "-f", "foo", "-f", "bar" });
+        assertTrue(config.getFeatureFiles().contains("foo"));
+        assertTrue(config.getFeatureFiles().contains("bar"));
+
+    }
+
 }

Reply via email to