/* * Copyright © 2014 Cask Data, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package co.cask.cdap.common.options; import co.cask.cdap.common.utils.OSDetector; import org.junit.Assert; import org.junit.Test; import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.util.List; /** * */ public class OptionsParserTest { private static class MyFlags { @Option(usage = "a boolean flag") private boolean flagNoValue; @Option protected boolean flagOneDashBoolean; @Option(name = "flagFloat") public float flagNumber; @Option public double flagDouble; @Option public int flagInt; @Option public long flagLong; @Option public short flagShort; @Option public String flagString; @Option public String flagDefault = "defaultValue"; // These two parameters may be controlled by explicit flags or by the environment. @Option(name = "home", envVar = "HOME", hidden = true) public String homeVar = "somedefault"; @Option(name = "missing", envVar = "MISSING_ENV_VAR_XXXXXXX", hidden = true) public String missingEnv = "missing"; private String notAFlag; public boolean getFlagNoValue() { return flagNoValue; } public boolean getFlagOneDashBoolean() { return flagOneDashBoolean; } public float getFlagFloat() { return flagNumber; } } private static class MySubclassedFlags extends MyFlags { @Option public String flagSubclass; } private static class UnsupportedTypeFlags { @Option private Object unsupportedFlagType; } private static class DuplicateFlagDeclaration { @Option private int myFlag; @Option(name = "myFlag") private String myDuplicateFlag; } private static class HelpOverride { @Option public boolean help; @Option public String foo; } @Test public void testParse() { MyFlags myFlags = new MyFlags(); String[] args = new String[] { "nonFlagArg1", "--flagNoValue", "-flagOneDashBoolean=false", "nonFlagArg2", "--flagFloat=-10.234", "--flagDouble=0.1", "--flagInt=-3", "--flagShort=10", "--flagLong=123", "--flagString=foo", }; List<String> nonFlagArgs = OptionsParser.init(myFlags, args, "OptionsParserTest", "0.1.0", System.out); Assert.assertTrue(myFlags.getFlagNoValue()); Assert.assertFalse(myFlags.getFlagOneDashBoolean()); Assert.assertEquals(-10.234f, myFlags.getFlagFloat(), 0.0001f); Assert.assertEquals(0.1, myFlags.flagDouble, 0.0001f); Assert.assertEquals(-3, myFlags.flagInt); Assert.assertEquals(10, myFlags.flagShort); Assert.assertEquals(123, myFlags.flagLong); Assert.assertTrue(myFlags.flagString.equals("foo")); Assert.assertTrue(myFlags.flagDefault.equals("defaultValue")); Assert.assertEquals(2, nonFlagArgs.size()); Assert.assertTrue(nonFlagArgs.get(0).equals("nonFlagArg1")); Assert.assertTrue(nonFlagArgs.get(1).equals("nonFlagArg2")); } @Test public void testUnrecognizedFlag() { MyFlags myFlags = new MyFlags(); String[] args = new String[] { "nonFlagArg1", "--flagNoValue", "-flagOneDashBoolean=false", "nonFlagArg2", "--flagFloat=-10.234", "--notAFlag=foo", }; try { OptionsParser.init(myFlags, args, "OptionsParserTest", "0.1.0", System.out); Assert.assertTrue(false); // Should have thrown an exception. } catch (UnrecognizedOptionException e) { Assert.assertTrue(e.getMessage().contains("notAFlag")); } } @Test public void testUnsupportedFlagType() { UnsupportedTypeFlags myFlags = new UnsupportedTypeFlags(); String[] args = new String[] { "--unsupportedFlagType=null", }; try { OptionsParser.init(myFlags, args, "OptionsParserTest", "0.1.0", System.out); Assert.assertTrue(false); // Should have thrown an exception. } catch (UnsupportedOptionTypeException e) { Assert.assertTrue(e.getMessage().contains("unsupportedFlagType")); } } @Test public void testIllegalFlagValue() { MyFlags myFlags = new MyFlags(); String[] args = new String[] { "--flagFloat=notANumber", }; try { OptionsParser.init(myFlags, args, "OptionsParserTest", "0.1.0", System.out); Assert.assertTrue(false); // Should have thrown an exception. } catch (IllegalOptionValueException e) { Assert.assertTrue(e.getMessage().contains("flagFloat")); } } @Test public void testHexInt() { MyFlags myFlags = new MyFlags(); String[] args = new String[] { "--flagInt=0xA", }; try { OptionsParser.init(myFlags, args, "OptionsParserTest", "0.1.0", System.out); Assert.assertTrue(false); // Should have thrown an exception. } catch (IllegalOptionValueException e) { // Parsing hex is not supported. Assert.assertTrue(e.getMessage().contains("flagInt")); } } @Test public void testNoEqualsSeparator() { MyFlags myFlags = new MyFlags(); String[] args = new String[] { "--flagInt", "5", }; try { OptionsParser.init(myFlags, args, "OptionsParserTest", "0.1.0", System.out); Assert.assertTrue(false); // Should have thrown an exception. } catch (IllegalOptionValueException e) { // This will be treated as a flag without a value. Assert.assertTrue(e.getMessage().contains("flagInt")); } } @Test public void testDuplicateFlags() { DuplicateFlagDeclaration myFlags = new DuplicateFlagDeclaration(); try { OptionsParser.init(myFlags, new String[] {}, "OptionsParserTest", "0.1.0", System.out); Assert.assertTrue(false); // Should have thrown an exception. } catch (DuplicateOptionException e) { Assert.assertTrue(e.getMessage().contains("myFlag")); } } @Test public void testHelpOverride() { HelpOverride myFlags = new HelpOverride(); ByteArrayOutputStream out = new ByteArrayOutputStream(); OptionsParser.init(myFlags, new String[] {"--help", "--foo=bar"}, "OptionsParserTest", "0.1.0", new PrintStream(out)); // No usage info should have printed, since we declared our own help flag. Assert.assertTrue(out.toString().isEmpty()); Assert.assertTrue(myFlags.help); Assert.assertTrue(myFlags.foo.equals("bar")); } @Test public void testIgnoreAfterDoubleDashMarker() { MyFlags myFlags = new MyFlags(); OptionsParser.init(myFlags, new String[] {"--flagInt=7", "--", "--flagDefault=foo"}, "OptionsParserTest", "0.1.0", System.out); Assert.assertEquals(7, myFlags.flagInt); // flagDefault should not have changed, since it was after the "--". Assert.assertEquals("defaultValue" , myFlags.flagDefault); } @Test public void testKeepLatestFlag() { MyFlags myFlags = new MyFlags(); OptionsParser.init(myFlags, new String[] {"--flagInt=7", "--flagInt=8"}, "OptionsParserTest", "0.1.0", System.out); // Keeps the last flag value. Assert.assertEquals(8, myFlags.flagInt); } @Test public void testSubclassedFlags() { // Make sure the subclass inherits its superclass's flags. MySubclassedFlags myFlags = new MySubclassedFlags(); Assert.assertNotNull(OptionsParser.init(myFlags, new String[] {"--flagInt=7", "--flagSubclass=foo"}, "OptionsParserTest", "0.1.0", System.out)); Assert.assertEquals(7, myFlags.flagInt); Assert.assertEquals("foo", myFlags.flagSubclass); } @Test public void testEnvVarFlags() { // Ignore this test if windows as this does not work if (OSDetector.isWindows()) { return; } MyFlags myFlags = new MyFlags(); OptionsParser.init(myFlags, new String[] { "--flagInt=7" }, "OptionsParserTest", "0.1.0", System.out); Assert.assertTrue(myFlags.homeVar.startsWith("/")); // should be some path. myFlags = new MyFlags(); OptionsParser.init(myFlags, new String[] { "--home=meep" }, "OptionsParserTest", "0.1.0", System.out); Assert.assertEquals("meep", myFlags.homeVar); myFlags = new MyFlags(); OptionsParser.init(myFlags, new String[] { "--missing=wombat" }, "OptionsParserTest", "0.1.0", System.out); Assert.assertEquals("wombat", myFlags.missingEnv); myFlags = new MyFlags(); OptionsParser.init(myFlags, new String[] { }, "OptionsParserTest", "0.1.0", System.out); Assert.assertEquals("missing", myFlags.missingEnv); } }