summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorEric Rowe <erowe@google.com>2013-03-04 15:34:53 -0800
committerEric Rowe <erowe@google.com>2013-05-02 10:53:03 -0700
commit511abd69a77c39e67e03e84651005687fb654d52 (patch)
treeb3cd81e2787b932a8b30c57fa4cd066f774b62c3 /tests
parent399ac3a3d0dce227fee66eb81c289cea9150428a (diff)
downloadloganalysis-511abd69a77c39e67e03e84651005687fb654d52.tar.gz
Add support for @Option and command line parsing
Change-Id: I496356112e6f6b8003231414f21185937e32d0f0
Diffstat (limited to 'tests')
-rw-r--r--tests/src/com/android/loganalysis/UnitTests.java8
-rw-r--r--tests/src/com/android/loganalysis/util/config/ArgsOptionParserTest.java629
-rw-r--r--tests/src/com/android/loganalysis/util/config/OptionSetterTest.java836
-rw-r--r--tests/src/com/android/loganalysis/util/config/OptionUpdateRuleTest.java91
4 files changed, 1564 insertions, 0 deletions
diff --git a/tests/src/com/android/loganalysis/UnitTests.java b/tests/src/com/android/loganalysis/UnitTests.java
index d3b63e1..6fb0ad3 100644
--- a/tests/src/com/android/loganalysis/UnitTests.java
+++ b/tests/src/com/android/loganalysis/UnitTests.java
@@ -51,6 +51,9 @@ import com.android.loganalysis.util.ArrayUtilTest;
import com.android.loganalysis.util.LogPatternUtilTest;
import com.android.loganalysis.util.LogTailUtilTest;
import com.android.loganalysis.util.RegexTrieTest;
+import com.android.loganalysis.util.config.ArgsOptionParserTest;
+import com.android.loganalysis.util.config.OptionSetterTest;
+import com.android.loganalysis.util.config.OptionUpdateRuleTest;
import junit.framework.Test;
import junit.framework.TestSuite;
@@ -107,6 +110,11 @@ public class UnitTests extends TestSuite {
addTestSuite(LogPatternUtilTest.class);
addTestSuite(LogTailUtilTest.class);
addTestSuite(RegexTrieTest.class);
+
+ // util.config
+ addTestSuite(ArgsOptionParserTest.class);
+ addTestSuite(OptionSetterTest.class);
+ addTestSuite(OptionUpdateRuleTest.class);
}
public static Test suite() {
diff --git a/tests/src/com/android/loganalysis/util/config/ArgsOptionParserTest.java b/tests/src/com/android/loganalysis/util/config/ArgsOptionParserTest.java
new file mode 100644
index 0000000..524cfa0
--- /dev/null
+++ b/tests/src/com/android/loganalysis/util/config/ArgsOptionParserTest.java
@@ -0,0 +1,629 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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 com.android.loganalysis.util.config;
+
+import com.android.loganalysis.util.config.Option.Importance;
+
+import junit.framework.TestCase;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Unit tests for {@link ArgsOptionParser}.
+ */
+@SuppressWarnings("unused")
+public class ArgsOptionParserTest extends TestCase {
+
+ /**
+ * An option source with one {@link Option} specified.
+ */
+ private static class OneOptionSource {
+
+ private static final String DEFAULT_VALUE = "default";
+ private static final String OPTION_NAME = "my_option";
+ private static final String OPTION_DESC = "option description";
+
+ @Option(name=OPTION_NAME, shortName='o', description=OPTION_DESC)
+ private String mMyOption = DEFAULT_VALUE;
+ }
+
+ /**
+ * An option source with one {@link Option} specified.
+ */
+ private static class MapOptionSource {
+
+ private static final String OPTION_NAME = "my_option";
+ private static final String OPTION_DESC = "option description";
+
+ @Option(name=OPTION_NAME, shortName='o', description=OPTION_DESC)
+ private Map<Integer, Boolean> mMyOption = new HashMap<Integer, Boolean>();
+ }
+
+ /**
+ * An option source with boolean {@link Option} specified.
+ */
+ private static class BooleanOptionSource {
+
+ private static final boolean DEFAULT_BOOL = false;
+ private static final String DEFAULT_VALUE = "default";
+
+ @Option(name="my_boolean", shortName='b')
+ private boolean mMyBool = DEFAULT_BOOL;
+
+ @Option(name="my_option", shortName='o')
+ protected String mMyOption = DEFAULT_VALUE;
+ }
+
+ /**
+ * An option source with boolean {@link Option} specified with default = true.
+ */
+ private static class BooleanTrueOptionSource {
+
+ private static final boolean DEFAULT_BOOL = true;
+
+ @Option(name="my_boolean", shortName='b')
+ private boolean mMyBool = DEFAULT_BOOL;
+ }
+
+ /**
+ * An option source that has a superclass with options
+ */
+ private static class InheritedOptionSource extends OneOptionSource {
+
+ private static final String OPTION_NAME = "my_sub_option";
+ private static final String OPTION_DESC = "sub description";
+
+ @Option(name=OPTION_NAME, description=OPTION_DESC)
+ private String mMySubOption = "";
+ }
+
+ /**
+ * An option source for testing the {@link Option#importance()} settings
+ */
+ private static class ImportantOptionSource {
+
+ private static final String IMPORTANT_OPTION_NAME = "important_option";
+ private static final String IMPORTANT_UNSET_OPTION_NAME = "unset_important_option";
+ private static final String UNIMPORTANT_OPTION_NAME = "unimportant_option";
+
+ @Option(name = IMPORTANT_OPTION_NAME, description = IMPORTANT_OPTION_NAME,
+ importance = Importance.ALWAYS)
+ private String mImportantOption = "foo";
+
+ @Option(name = IMPORTANT_UNSET_OPTION_NAME, description = IMPORTANT_UNSET_OPTION_NAME,
+ importance = Importance.IF_UNSET)
+ private String mImportantUnsetOption = null;
+
+ @Option(name = UNIMPORTANT_OPTION_NAME, description = UNIMPORTANT_OPTION_NAME,
+ importance = Importance.NEVER)
+ private String mUnimportantOption = null;
+
+ ImportantOptionSource(String setOption) {
+ mImportantUnsetOption = setOption;
+ }
+
+ ImportantOptionSource() {
+ }
+ }
+
+ /**
+ * Option source whose options shouldn't end up in the global namespace
+ */
+ @OptionClass(alias = "ngos", global_namespace = false)
+ private static class NonGlobalOptionSource {
+ @Option(name = "option")
+ Boolean mOption = null;
+ }
+
+ /**
+ * Option source with mandatory options
+ */
+ private static class MandatoryOptionSourceNoDefault {
+ @Option(name = "no-default", mandatory = true)
+ private String mNoDefaultOption;
+ }
+
+ /**
+ * Option source with mandatory options
+ */
+ private static class MandatoryOptionSourceNull {
+ @Option(name = "null", mandatory = true)
+ private String mNullOption = null;
+ }
+
+ /**
+ * Option source with mandatory options
+ */
+ private static class MandatoryOptionSourceEmptyCollection {
+ @Option(name = "empty-collection", mandatory = true)
+ private Collection<String> mEmptyCollection = new ArrayList<String>(0);
+ }
+
+ /**
+ * Option source with mandatory options
+ */
+ private static class MandatoryOptionSourceEmptyMap {
+ @Option(name = "empty-map", mandatory = true)
+ private Map<String, String> mEmptyMap = new HashMap<String, String>();
+ }
+
+ /**
+ * An option source that exercises the {@link OptionUpdateRule}s.
+ */
+ private static class OptionUpdateRuleSource {
+
+ public static final String DEFAULT_VALUE = "5 default";
+ public static final String BIGGER_VALUE = "9 bigger";
+ public static final String SMALLER_VALUE = "0 smaller";
+
+ @Option(name = "default")
+ private String mDefaultOption = DEFAULT_VALUE;
+
+ @Option(name = "first", updateRule = OptionUpdateRule.FIRST)
+ private String mFirstOption = DEFAULT_VALUE;
+
+ @Option(name = "last", updateRule = OptionUpdateRule.LAST)
+ private String mLastOption = DEFAULT_VALUE;
+
+ @Option(name = "greatest", updateRule = OptionUpdateRule.GREATEST)
+ private String mGreatestOption = DEFAULT_VALUE;
+
+ @Option(name = "least", updateRule = OptionUpdateRule.LEAST)
+ private String mLeastOption = DEFAULT_VALUE;
+
+ @Option(name = "immutable", updateRule = OptionUpdateRule.IMMUTABLE)
+ private String mImmutableOption = DEFAULT_VALUE;
+
+ @Option(name = "null-immutable", updateRule = OptionUpdateRule.IMMUTABLE)
+ private String mNullImmutableOption = null;
+ }
+
+ /**
+ * Verify that {@link OptionUpdateRule}s work properly when the update compares to greater-than
+ * the default value.
+ */
+ public void testOptionUpdateRule_greater() throws Exception {
+ OptionUpdateRuleSource object = new OptionUpdateRuleSource();
+ ArgsOptionParser parser = new ArgsOptionParser(object);
+ final String current = OptionUpdateRuleSource.DEFAULT_VALUE;
+ final String big = OptionUpdateRuleSource.BIGGER_VALUE;
+
+ parser.parse(new String[] {"--default", big, "--first", big, "--last", big,
+ "--greatest", big, "--least", big});
+ assertEquals(current, object.mFirstOption);
+ assertEquals(big, object.mLastOption);
+ assertEquals(big, object.mDefaultOption); // default should be LAST
+ assertEquals(big, object.mGreatestOption);
+ assertEquals(current, object.mLeastOption);
+ }
+
+ /**
+ * Verify that {@link OptionUpdateRule}s work properly when the update compares to greater-than
+ * the default value.
+ */
+ public void testOptionUpdateRule_lesser() throws Exception {
+ OptionUpdateRuleSource object = new OptionUpdateRuleSource();
+ ArgsOptionParser parser = new ArgsOptionParser(object);
+ final String current = OptionUpdateRuleSource.DEFAULT_VALUE;
+ final String small = OptionUpdateRuleSource.SMALLER_VALUE;
+
+ parser.parse(new String[] {"--default", small, "--first", small, "--last", small,
+ "--greatest", small, "--least", small});
+ assertEquals(current, object.mFirstOption);
+ assertEquals(small, object.mLastOption);
+ assertEquals(small, object.mDefaultOption); // default should be LAST
+ assertEquals(current, object.mGreatestOption);
+ assertEquals(small, object.mLeastOption);
+ }
+
+ /**
+ * Verify that {@link OptionUpdateRule}s work properly when the update compares to greater-than
+ * the default value.
+ */
+ public void testOptionUpdateRule_immutable() throws Exception {
+ OptionUpdateRuleSource object = new OptionUpdateRuleSource();
+ ArgsOptionParser parser = new ArgsOptionParser(object);
+ final String update = OptionUpdateRuleSource.BIGGER_VALUE;
+
+ try {
+ parser.parse(new String[] {"--immutable", update});
+ fail("ConfigurationException not thrown when updating an IMMUTABLE option");
+ } catch (ConfigurationException e) {
+ // expected
+ }
+
+ assertNull(object.mNullImmutableOption);
+ parser.parse(new String[] {"--null-immutable", update});
+ assertEquals(update, object.mNullImmutableOption);
+
+ try {
+ parser.parse(new String[] {"--null-immutable", update});
+ fail("ConfigurationException not thrown when updating an IMMUTABLE option");
+ } catch (ConfigurationException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Setting an option with a namespace alias should work fine
+ */
+ public void testNonGlobalOptionSource_alias() throws Exception {
+ NonGlobalOptionSource source = new NonGlobalOptionSource();
+ ArgsOptionParser parser = new ArgsOptionParser(source);
+
+ assertNull(source.mOption);
+ parser.parse(new String[] {"--ngos:option"});
+ assertTrue(source.mOption);
+ parser.parse(new String[] {"--ngos:no-option"});
+ assertFalse(source.mOption);
+ }
+
+ /**
+ * Setting an option with a classname namespace should work fine
+ */
+ public void testNonGlobalOptionSource_className() throws Exception {
+ NonGlobalOptionSource source = new NonGlobalOptionSource();
+ ArgsOptionParser parser = new ArgsOptionParser(source);
+
+ assertNull(source.mOption);
+ parser.parse(new String[] {String.format("--%s:option", source.getClass().getName())});
+ assertTrue(source.mOption);
+ parser.parse(new String[] {String.format("--%s:no-option", source.getClass().getName())});
+ assertFalse(source.mOption);
+ }
+
+ /**
+ * Setting an option without a namespace should fail
+ */
+ public void testNonGlobalOptionSource_global() throws Exception {
+ NonGlobalOptionSource source = new NonGlobalOptionSource();
+ ArgsOptionParser parser = new ArgsOptionParser(source);
+
+ assertNull(source.mOption);
+ try {
+ parser.parse(new String[] {"--option"});
+ fail("ConfigurationException not thrown when assigning a global option to an @Option " +
+ "field in a non-global-namespace class");
+ } catch (ConfigurationException e) {
+ // expected
+ }
+
+ try {
+ parser.parse(new String[] {"--no-option"});
+ fail("ConfigurationException not thrown when assigning a global option to an @Option " +
+ "field in a non-global-namespace class");
+ } catch (ConfigurationException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Test passing an empty argument list for an object that has one option specified.
+ * <p/>
+ * Expected that the option field should retain its default value.
+ */
+ public void testParse_noArg() throws ConfigurationException {
+ OneOptionSource object = new OneOptionSource();
+ ArgsOptionParser parser = new ArgsOptionParser(object);
+ parser.parse(new String[] {});
+ assertEquals(OneOptionSource.DEFAULT_VALUE, object.mMyOption);
+ }
+
+ /**
+ * Test passing an single argument for an object that has one option specified.
+ */
+ public void testParse_oneArg() throws ConfigurationException {
+ OneOptionSource object = new OneOptionSource();
+ ArgsOptionParser parser = new ArgsOptionParser(object);
+ final String expectedValue = "set";
+ parser.parse(new String[] {"--my_option", expectedValue});
+ assertEquals(expectedValue, object.mMyOption);
+ }
+
+ /**
+ * Test passing an single argument for an object that has one option specified.
+ */
+ public void testParse_oneMapArg() throws ConfigurationException {
+ MapOptionSource object = new MapOptionSource();
+ ArgsOptionParser parser = new ArgsOptionParser(object);
+ final int expectedKey = 13;
+ final boolean expectedValue = true;
+ parser.parse(new String[] {"--my_option", Integer.toString(expectedKey),
+ Boolean.toString(expectedValue)});
+ assertNotNull(object.mMyOption);
+ assertEquals(1, object.mMyOption.size());
+ assertEquals(expectedValue, (boolean) object.mMyOption.get(expectedKey));
+ }
+
+ /**
+ * Test passing an single argument for an object that has one option specified.
+ */
+ public void testParseMapArg_mismatchKeyType() throws ConfigurationException {
+ MapOptionSource object = new MapOptionSource();
+ ArgsOptionParser parser = new ArgsOptionParser(object);
+ final String expectedKey = "istanbul";
+ final boolean expectedValue = true;
+ try {
+ parser.parse(new String[] {"--my_option", expectedKey, Boolean.toString(expectedValue)});
+ fail("ConfigurationException not thrown");
+ } catch (ConfigurationException e) {
+ // expect an exception that explicitly mentions that the "key" is incorrect
+ assertTrue(String.format("Expected exception message to contain 'key': %s",
+ e.getMessage()), e.getMessage().contains("key"));
+ assertTrue(String.format("Expected exception message to contain '%s': %s",
+ expectedKey, e.getMessage()), e.getMessage().contains(expectedKey));
+ }
+ }
+
+ /**
+ * Test passing an single argument for an object that has one option specified.
+ */
+ public void testParseMapArg_mismatchValueType() throws ConfigurationException {
+ MapOptionSource object = new MapOptionSource();
+ ArgsOptionParser parser = new ArgsOptionParser(object);
+ final int expectedKey = 13;
+ final String expectedValue = "notconstantinople";
+ try {
+ parser.parse(new String[] {"--my_option", Integer.toString(expectedKey), expectedValue});
+ fail("ConfigurationException not thrown");
+ } catch (ConfigurationException e) {
+ // expect an exception that explicitly mentions that the "value" is incorrect
+ assertTrue(String.format("Expected exception message to contain 'value': '%s'",
+ e.getMessage()), e.getMessage().contains("value"));
+ assertTrue(String.format("Expected exception message to contain '%s': %s",
+ expectedValue, e.getMessage()), e.getMessage().contains(expectedValue));
+ }
+ }
+
+ /**
+ * Test passing an single argument for an object that has one option specified.
+ */
+ public void testParseMapArg_missingKey() throws ConfigurationException {
+ MapOptionSource object = new MapOptionSource();
+ ArgsOptionParser parser = new ArgsOptionParser(object);
+ try {
+ parser.parse(new String[] {"--my_option"});
+ fail("ConfigurationException not thrown");
+ } catch (ConfigurationException e) {
+ // expect an exception that explicitly mentions that the "key" is incorrect
+ assertTrue(String.format("Expected exception message to contain 'key': '%s'",
+ e.getMessage()), e.getMessage().contains("key"));
+ }
+ }
+
+ /**
+ * Test passing an single argument for an object that has one option specified.
+ */
+ public void testParseMapArg_missingValue() throws ConfigurationException {
+ MapOptionSource object = new MapOptionSource();
+ ArgsOptionParser parser = new ArgsOptionParser(object);
+ final int expectedKey = 13;
+ try {
+ parser.parse(new String[] {"--my_option", Integer.toString(expectedKey)});
+ fail("ConfigurationException not thrown");
+ } catch (ConfigurationException e) {
+ // expect an exception that explicitly mentions that the "value" is incorrect
+ assertTrue(String.format("Expected exception message to contain 'value': '%s'",
+ e.getMessage()), e.getMessage().contains("value"));
+ }
+ }
+
+ /**
+ * Test passing an single argument for an object that has one option specified, using the
+ * option=value notation.
+ */
+ public void testParse_oneArgEquals() throws ConfigurationException {
+ OneOptionSource object = new OneOptionSource();
+ ArgsOptionParser parser = new ArgsOptionParser(object);
+ final String expectedValue = "set";
+ parser.parse(new String[] {String.format("--my_option=%s", expectedValue)});
+ assertEquals(expectedValue, object.mMyOption);
+ }
+
+ /**
+ * Test passing a single argument for an object that has one option specified, using the
+ * short option notation.
+ */
+ public void testParse_oneShortArg() throws ConfigurationException {
+ OneOptionSource object = new OneOptionSource();
+ ArgsOptionParser parser = new ArgsOptionParser(object);
+ final String expectedValue = "set";
+ parser.parse(new String[] {"-o", expectedValue});
+ assertEquals(expectedValue, object.mMyOption);
+ }
+
+ /**
+ * Test that "--" marks the beginning of positional arguments
+ */
+ public void testParse_posArgs() throws ConfigurationException {
+ OneOptionSource object = new OneOptionSource();
+ ArgsOptionParser parser = new ArgsOptionParser(object);
+ final String expectedValue = "set";
+ // have a position argument with a long option prefix, to try to confuse the parser
+ final String posArg = "--unused";
+ List<String> leftOver = parser.parse(new String[] {"-o", expectedValue, "--", posArg});
+ assertEquals(expectedValue, object.mMyOption);
+ assertTrue(leftOver.contains(posArg));
+ }
+
+ /**
+ * Test passing a single boolean argument.
+ */
+ public void testParse_boolArg() throws ConfigurationException {
+ BooleanOptionSource object = new BooleanOptionSource();
+ ArgsOptionParser parser = new ArgsOptionParser(object);
+ parser.parse(new String[] {"-b"});
+ assertTrue(object.mMyBool);
+ }
+
+ /**
+ * Test passing a boolean argument with another short argument.
+ */
+ public void testParse_boolTwoArg() throws ConfigurationException {
+ BooleanOptionSource object = new BooleanOptionSource();
+ ArgsOptionParser parser = new ArgsOptionParser(object);
+ final String expectedValue = "set";
+ parser.parse(new String[] {"-bo", expectedValue});
+ assertTrue(object.mMyBool);
+ assertEquals(expectedValue, object.mMyOption);
+ }
+
+ /**
+ * Test passing a boolean argument with another short argument, with value concatenated.
+ * e.g -bovalue
+ */
+ public void testParse_boolTwoArgValue() throws ConfigurationException {
+ BooleanOptionSource object = new BooleanOptionSource();
+ ArgsOptionParser parser = new ArgsOptionParser(object);
+ final String expectedValue = "set";
+ parser.parse(new String[] {String.format("-bo%s", expectedValue)});
+ assertTrue(object.mMyBool);
+ assertEquals(expectedValue, object.mMyOption);
+ }
+
+ /**
+ * Test the "--no-<bool option>" syntax
+ */
+ public void testParse_boolFalse() throws ConfigurationException {
+ BooleanTrueOptionSource object = new BooleanTrueOptionSource();
+ ArgsOptionParser parser = new ArgsOptionParser(object);
+ parser.parse(new String[] {"--no-my_boolean"});
+ assertFalse(object.mMyBool);
+ }
+
+ /**
+ * Test the boolean long option syntax
+ */
+ public void testParse_boolLong() throws ConfigurationException {
+ BooleanOptionSource object = new BooleanOptionSource();
+ ArgsOptionParser parser = new ArgsOptionParser(object);
+ parser.parse(new String[] {"--my_boolean"});
+ assertTrue(object.mMyBool);
+ }
+
+ /**
+ * Test passing arg string where value is missing
+ */
+ public void testParse_missingValue() throws ConfigurationException {
+ OneOptionSource object = new OneOptionSource();
+ ArgsOptionParser parser = new ArgsOptionParser(object);
+ try {
+ parser.parse(new String[] {"--my_option"});
+ fail("ConfigurationException not thrown");
+ } catch (ConfigurationException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Test parsing args for an option that does not exist.
+ */
+ public void testParse_optionNotPresent() throws ConfigurationException {
+ OneOptionSource object = new OneOptionSource();
+ ArgsOptionParser parser = new ArgsOptionParser(object);
+ try {
+ parser.parse(new String[] {"--my_option", "set", "--not_here", "value"});
+ fail("ConfigurationException not thrown");
+ } catch (ConfigurationException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Test that help text is displayed for all fields
+ */
+ public void testGetOptionHelp() {
+ String help = ArgsOptionParser.getOptionHelp(false, new InheritedOptionSource());
+ assertTrue(help.contains(InheritedOptionSource.OPTION_NAME));
+ assertTrue(help.contains(InheritedOptionSource.OPTION_DESC));
+ assertTrue(help.contains(OneOptionSource.OPTION_NAME));
+ assertTrue(help.contains(OneOptionSource.OPTION_DESC));
+ assertTrue(help.contains(OneOptionSource.DEFAULT_VALUE));
+ }
+
+ /**
+ * Test displaying important only help text
+ */
+ public void testGetOptionHelp_important() {
+ String help = ArgsOptionParser.getOptionHelp(true, new ImportantOptionSource());
+ assertTrue(help.contains(ImportantOptionSource.IMPORTANT_OPTION_NAME));
+ assertTrue(help.contains(ImportantOptionSource.IMPORTANT_UNSET_OPTION_NAME));
+ assertFalse(help.contains(ImportantOptionSource.UNIMPORTANT_OPTION_NAME));
+ }
+
+ /**
+ * Test that {@link Importance#IF_UNSET} {@link Option}s are hidden from help if set.
+ */
+ public void testGetOptionHelp_importantUnset() {
+ String help = ArgsOptionParser.getOptionHelp(true, new ImportantOptionSource("foo"));
+ assertTrue(help.contains(ImportantOptionSource.IMPORTANT_OPTION_NAME));
+ assertFalse(help.contains(ImportantOptionSource.IMPORTANT_UNSET_OPTION_NAME));
+ assertFalse(help.contains(ImportantOptionSource.UNIMPORTANT_OPTION_NAME));
+ }
+
+ public void testMandatoryOption_noDefault() throws Exception {
+ MandatoryOptionSourceNoDefault object = new MandatoryOptionSourceNoDefault();
+ ArgsOptionParser parser = new ArgsOptionParser(object);
+ // expect success
+ parser.parse(new String[] {});
+ try {
+ parser.validateMandatoryOptions();
+ fail("ConfigurationException not thrown");
+ } catch (ConfigurationException e) {
+ // expected
+ }
+ }
+
+ public void testMandatoryOption_null() throws Exception {
+ MandatoryOptionSourceNull object = new MandatoryOptionSourceNull();
+ ArgsOptionParser parser = new ArgsOptionParser(object);
+ parser.parse(new String[] {});
+ try {
+ parser.validateMandatoryOptions();
+ fail("ConfigurationException not thrown");
+ } catch (ConfigurationException e) {
+ // expected
+ }
+ }
+
+ public void testMandatoryOption_emptyCollection() throws Exception {
+ MandatoryOptionSourceEmptyCollection object = new MandatoryOptionSourceEmptyCollection();
+ ArgsOptionParser parser = new ArgsOptionParser(object);
+ parser.parse(new String[] {});
+ try {
+ parser.validateMandatoryOptions();
+ fail("ConfigurationException not thrown");
+ } catch (ConfigurationException e) {
+ // expected
+ }
+ }
+
+ public void testMandatoryOption_emptyMap() throws Exception {
+ MandatoryOptionSourceEmptyMap object = new MandatoryOptionSourceEmptyMap();
+ ArgsOptionParser parser = new ArgsOptionParser(object);
+ parser.parse(new String[] {});
+ try {
+ parser.validateMandatoryOptions();
+ fail("ConfigurationException not thrown");
+ } catch (ConfigurationException e) {
+ // expected
+ }
+ }
+}
diff --git a/tests/src/com/android/loganalysis/util/config/OptionSetterTest.java b/tests/src/com/android/loganalysis/util/config/OptionSetterTest.java
new file mode 100644
index 0000000..dbac942
--- /dev/null
+++ b/tests/src/com/android/loganalysis/util/config/OptionSetterTest.java
@@ -0,0 +1,836 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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 com.android.loganalysis.util.config;
+
+import junit.framework.TestCase;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Unit tests for {@link OptionSetter}.
+ */
+public class OptionSetterTest extends TestCase {
+
+ /** Option source with generic type. */
+ private static class GenericTypeOptionSource {
+ @SuppressWarnings("unused")
+ @Option(name = "my_option", shortName = 'o')
+ private Collection<?> mMyOption;
+ }
+
+ /** Option source with unparameterized type. */
+ private static class CollectionTypeOptionSource {
+ @SuppressWarnings("unused")
+ @Option(name = "my_option", shortName = 'o')
+ private Collection mMyOption;
+ }
+
+ private static class MyGeneric<T> {
+ }
+
+ /** Option source with unparameterized type. */
+ private static class NonCollectionGenericTypeOptionSource {
+ @SuppressWarnings("unused")
+ @Option(name = "my_option", shortName = 'o')
+ private MyGeneric<String> mMyOption;
+ }
+
+ /** Option source with options with same name. */
+ private static class DuplicateOptionSource {
+ @SuppressWarnings("unused")
+ @Option(name = "string", shortName = 's')
+ private String mMyOption;
+
+ @SuppressWarnings("unused")
+ @Option(name = "string", shortName = 's')
+ private String mMyDuplicateOption;
+ }
+
+ /** Option source with an option with same name as AllTypesOptionSource. */
+ @OptionClass(alias = "shared")
+ private static class SharedOptionSource {
+ @Option(name = "string", shortName = 's')
+ private String mMyOption;
+
+ @SuppressWarnings("unused")
+ @Option(name = "enum")
+ private DefaultEnumClass mEnum = null;
+
+ @SuppressWarnings("unused")
+ @Option(name = "string_collection")
+ private Collection<String> mStringCollection = new ArrayList<String>();
+
+ @Option(name = "enumMap")
+ private Map<DefaultEnumClass, CustomEnumClass> mEnumMap =
+ new HashMap<DefaultEnumClass, CustomEnumClass>();
+
+ @Option(name = "enumCollection")
+ private Collection<DefaultEnumClass> mEnumCollection =
+ new ArrayList<DefaultEnumClass>();
+ }
+
+ /**
+ * Option source with an option with same name as AllTypesOptionSource, but a different type.
+ */
+ private static class SharedOptionWrongTypeSource {
+ @SuppressWarnings("unused")
+ @Option(name = "string", shortName = 's')
+ private int mMyOption;
+ }
+
+ /** option source with all supported types. */
+ @OptionClass(alias = "all")
+ private static class AllTypesOptionSource {
+ @Option(name = "string_collection")
+ private final Collection<String> mStringCollection = new ArrayList<String>();
+
+ @Option(name = "string_string_map")
+ private Map<String, String> mStringMap = new HashMap<String, String>();
+
+ @Option(name = "string")
+ private String mString = null;
+
+ @Option(name = "boolean")
+ private boolean mBool = false;
+
+ @Option(name = "booleanObj")
+ private Boolean mBooleanObj = false;
+
+ @Option(name = "byte")
+ private byte mByte = 0;
+
+ @Option(name = "byteObj")
+ private Byte mByteObj = 0;
+
+ @Option(name = "short")
+ private short mShort = 0;
+
+ @Option(name = "shortObj")
+ private Short mShortObj = null;
+
+ @Option(name = "int")
+ private int mInt = 0;
+
+ @Option(name = "intObj")
+ private Integer mIntObj = 0;
+
+ @Option(name = "long")
+ private long mLong = 0;
+
+ @Option(name = "longObj")
+ private Long mLongObj = null;
+
+ @Option(name = "float")
+ private float mFloat = 0;
+
+ @Option(name = "floatObj")
+ private Float mFloatObj = null;
+
+ @Option(name = "double")
+ private double mDouble = 0;
+
+ @Option(name = "doubleObj")
+ private Double mDoubleObj = null;
+
+ @Option(name = "file")
+ private File mFile = null;
+
+ @Option(name = "enum")
+ private DefaultEnumClass mEnum = null;
+
+ @Option(name = "customEnum")
+ private CustomEnumClass mCustomEnum = null;
+
+ @Option(name = "enumMap")
+ private Map<DefaultEnumClass, CustomEnumClass> mEnumMap =
+ new HashMap<DefaultEnumClass, CustomEnumClass>();
+
+ @Option(name = "enumCollection")
+ private Collection<DefaultEnumClass> mEnumCollection =
+ new ArrayList<DefaultEnumClass>();
+ }
+
+ private static class ParentOptionSource {
+ @Option(name = "string")
+ private String mString = null;
+
+ protected String getParentString() {
+ return mString;
+ }
+ }
+
+ private static class ChildOptionSource extends ParentOptionSource {
+ @Option(name = "child-string")
+ private String mChildString = null;
+ }
+
+ /**
+ * Option source with invalid option name.
+ */
+ private static class BadOptionNameSource {
+ @SuppressWarnings("unused")
+ @Option(name = "bad:string", shortName = 's')
+ private int mMyOption;
+ }
+
+ private static enum DefaultEnumClass {
+ VAL1, VAL3, VAL2;
+ }
+
+ private static enum CustomEnumClass {
+ VAL1(42);
+
+ private int mVal;
+
+ CustomEnumClass(int val) {
+ mVal = val;
+ }
+
+ public int getVal() {
+ return mVal;
+ }
+ }
+
+ private static class FinalOption {
+ @Option(name = "final-string", description="final field, not allowed")
+ private final String mFinal= "foo";
+ }
+
+ /**
+ * Test creating an {@link OptionSetter} for a source with invalid option type.
+ */
+ public void testOptionSetter_noType() {
+ try {
+ new OptionSetter(new GenericTypeOptionSource());
+ fail("ConfigurationException not thrown");
+ } catch (ConfigurationException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Test creating an {@link OptionSetter} for a source with duplicate option names.
+ */
+ public void testOptionSetter_duplicateOptions() {
+ try {
+ new OptionSetter(new DuplicateOptionSource());
+ fail("ConfigurationException not thrown");
+ } catch (ConfigurationException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Test option with same name can be used in multiple option sources.
+ */
+ public void testOptionSetter_sharedOptions() throws ConfigurationException {
+ AllTypesOptionSource object1 = new AllTypesOptionSource();
+ SharedOptionSource object2 = new SharedOptionSource();
+ OptionSetter setter = new OptionSetter(object1, object2);
+ setter.setOptionValue("string", "test");
+ assertEquals("test", object1.mString);
+ assertEquals("test", object2.mMyOption);
+ }
+
+ /**
+ * Test {@link OptionSetter#setOptionValue(String, String)} for Enums used as the key and value
+ * of a {@link Map}.
+ */
+ public void testOptionSetter_sharedEnumMap() throws ConfigurationException {
+ AllTypesOptionSource object1 = new AllTypesOptionSource();
+ SharedOptionSource object2 = new SharedOptionSource();
+
+ final String key = "VAL1";
+ final String value = "VAL1";
+ final DefaultEnumClass expectedKey = DefaultEnumClass.VAL1;
+ final CustomEnumClass expectedValue = CustomEnumClass.VAL1;
+
+ // Actually set the key/value pair
+ OptionSetter parser = new OptionSetter(object1, object2);
+ parser.setOptionMapValue("enumMap", key, value);
+
+ // verify object1
+ assertEquals(1, object1.mEnumMap.size());
+ assertNotNull(object1.mEnumMap.get(expectedKey));
+ assertEquals(expectedValue, object1.mEnumMap.get(expectedKey));
+
+ // verify object2
+ assertEquals(1, object2.mEnumMap.size());
+ assertNotNull(object2.mEnumMap.get(expectedKey));
+ assertEquals(expectedValue, object2.mEnumMap.get(expectedKey));
+ }
+
+
+ /**
+ * Test {@link OptionSetter#setOptionValue(String, String)} for Enums used as the key and value
+ * of a {@link Map}.
+ */
+ public void testOptionSetter_sharedEnumCollection() throws ConfigurationException {
+ AllTypesOptionSource object1 = new AllTypesOptionSource();
+ SharedOptionSource object2 = new SharedOptionSource();
+
+ final String value = "VAL1";
+ final DefaultEnumClass expectedValue = DefaultEnumClass.VAL1;
+
+ // Actually add the element
+ OptionSetter parser = new OptionSetter(object1, object2);
+ parser.setOptionValue("enumCollection", value);
+
+ // verify object1
+ assertEquals(1, object1.mEnumCollection.size());
+ assertTrue(object1.mEnumCollection.contains(expectedValue));
+
+ // verify object2
+ assertEquals(1, object2.mEnumCollection.size());
+ assertTrue(object2.mEnumCollection.contains(expectedValue));
+ }
+
+
+ /**
+ * Test that multiple options with same name must have the same type.
+ */
+ public void testOptionSetter_sharedOptionsDiffType() throws ConfigurationException {
+ try {
+ new OptionSetter(new AllTypesOptionSource(), new SharedOptionWrongTypeSource());
+ fail("ConfigurationException not thrown");
+ } catch (ConfigurationException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Test namespaced options using class names.
+ */
+ public void testOptionSetter_namespacedClassName() throws ConfigurationException {
+ AllTypesOptionSource object1 = new AllTypesOptionSource();
+ SharedOptionSource object2 = new SharedOptionSource();
+ OptionSetter setter = new OptionSetter(object1, object2);
+ setter.setOptionValue(AllTypesOptionSource.class.getName() + ":string", "alltest");
+ setter.setOptionValue(SharedOptionSource.class.getName() + ":string", "sharedtest");
+ assertEquals("alltest", object1.mString);
+ assertEquals("sharedtest", object2.mMyOption);
+ }
+
+ /**
+ * Test namespaced options using OptionClass aliases
+ */
+ public void testOptionSetter_namespacedAlias() throws ConfigurationException {
+ AllTypesOptionSource object1 = new AllTypesOptionSource();
+ SharedOptionSource object2 = new SharedOptionSource();
+ OptionSetter setter = new OptionSetter(object1, object2);
+ setter.setOptionValue("all:string", "alltest");
+ setter.setOptionValue("shared:string", "sharedtest");
+ assertEquals("alltest", object1.mString);
+ assertEquals("sharedtest", object2.mMyOption);
+ }
+
+ /**
+ * Test creating an {@link OptionSetter} for a Collection with no type.
+ */
+ public void testOptionSetter_unparamType() {
+ try {
+ new OptionSetter(new CollectionTypeOptionSource());
+ fail("ConfigurationException not thrown");
+ } catch (ConfigurationException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Test creating an {@link OptionSetter} for a non collection option with generic type
+ */
+ public void testOptionSetter_genericType() {
+ try {
+ new OptionSetter(new NonCollectionGenericTypeOptionSource());
+ fail("ConfigurationException not thrown");
+ } catch (ConfigurationException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Test creating an {@link OptionSetter} for class with inherited options
+ */
+ public void testOptionSetter_inheritedOptions() throws ConfigurationException {
+ ChildOptionSource source = new ChildOptionSource();
+ OptionSetter setter = new OptionSetter(source);
+ setter.setOptionValue("string", "parent");
+ setter.setOptionValue("child-string", "child");
+ assertEquals("parent", source.getParentString());
+ assertEquals("child", source.mChildString);
+ }
+
+ /**
+ * Test that options with {@link OptionSetter#NAMESPACE_SEPARATOR} are rejected
+ */
+ public void testOptionSetter_badOptionName() throws ConfigurationException {
+ try {
+ new OptionSetter(new BadOptionNameSource());
+ fail("ConfigurationException not thrown");
+ } catch (ConfigurationException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Test {@link OptionSetter#isBooleanOption(String)} when passed an unknown option name
+ */
+ public void testIsBooleanOption_unknown() throws ConfigurationException {
+ OptionSetter parser = new OptionSetter(new AllTypesOptionSource());
+ try {
+ parser.isBooleanOption("unknown");
+ fail("ConfigurationException not thrown");
+ } catch (ConfigurationException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Test {@link OptionSetter#isBooleanOption(String)} when passed boolean option name
+ */
+ public void testIsBooleanOption_true() throws ConfigurationException {
+ OptionSetter parser = new OptionSetter(new AllTypesOptionSource());
+ assertTrue(parser.isBooleanOption("boolean"));
+ }
+
+ /**
+ * Test {@link OptionSetter#isBooleanOption(String)} when passed boolean option name for a
+ * Boolean object
+ */
+ public void testIsBooleanOption_objTrue() throws ConfigurationException {
+ OptionSetter parser = new OptionSetter(new AllTypesOptionSource());
+ assertTrue(parser.isBooleanOption("booleanObj"));
+ }
+
+ /**
+ * Test {@link OptionSetter#isBooleanOption(String)} when passed non-boolean option
+ */
+ public void testIsBooleanOption_false() throws ConfigurationException {
+ OptionSetter parser = new OptionSetter(new AllTypesOptionSource());
+ assertFalse(parser.isBooleanOption("string"));
+ }
+
+ /**
+ * Test {@link OptionSetter#setOptionValue(String, String)} when passed an unknown option name
+ */
+ public void testSetOptionValue_unknown() throws ConfigurationException {
+ OptionSetter parser = new OptionSetter(new AllTypesOptionSource());
+ try {
+ parser.setOptionValue("unknown", "foo");
+ fail("ConfigurationException not thrown");
+ } catch (ConfigurationException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Test setting a value for a option with an unknown generic type.
+ */
+ public void testSetOptionValue_unknownType() throws ConfigurationException {
+ OptionSetter parser = new OptionSetter(new AllTypesOptionSource());
+ try {
+ parser.setOptionValue("my_option", "foo");
+ fail("ConfigurationException not thrown");
+ } catch (ConfigurationException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Test setting a value for a non-parameterized Collection
+ */
+ public void testSetOptionValue_unparameterizedType() throws ConfigurationException {
+ OptionSetter parser = new OptionSetter(new AllTypesOptionSource());
+ try {
+ parser.setOptionValue("my_option", "foo");
+ fail("ConfigurationException not thrown");
+ } catch (ConfigurationException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Test {@link OptionSetter#setOptionValue(String, String)} for a String.
+ */
+ public void testSetOptionValue_string() throws ConfigurationException {
+ AllTypesOptionSource optionSource = new AllTypesOptionSource();
+ final String expectedValue = "stringvalue";
+ assertSetOptionValue(optionSource, "string", expectedValue);
+ assertEquals(expectedValue, optionSource.mString);
+ }
+
+ /**
+ * Test {@link OptionSetter#setOptionValue(String, String)} for a Collection.
+ */
+ public void testSetOptionValue_collection() throws ConfigurationException, IOException {
+ AllTypesOptionSource optionSource = new AllTypesOptionSource();
+ final String expectedValue = "stringvalue";
+ assertSetOptionValue(optionSource, "string_collection", expectedValue);
+ assertEquals(1, optionSource.mStringCollection.size());
+ assertTrue(optionSource.mStringCollection.contains(expectedValue));
+ }
+
+ /**
+ * Test {@link OptionSetter#setOptionValue(String, String)} for a Map.
+ */
+ public void testSetOptionValue_map() throws ConfigurationException, IOException {
+ AllTypesOptionSource optionSource = new AllTypesOptionSource();
+ final String expectedKey = "stringkey";
+ final String expectedValue = "stringvalue";
+
+ // Actually set the key/value pair
+ OptionSetter parser = new OptionSetter(optionSource);
+ parser.setOptionMapValue("string_string_map", expectedKey, expectedValue);
+
+ assertEquals(1, optionSource.mStringMap.size());
+ assertNotNull(optionSource.mStringMap.get(expectedKey));
+ assertEquals(expectedValue, optionSource.mStringMap.get(expectedKey));
+ }
+
+ /**
+ * Test {@link OptionSetter#setOptionValue(String, String)} for a boolean.
+ */
+ public void testSetOptionValue_boolean() throws ConfigurationException {
+ AllTypesOptionSource optionSource = new AllTypesOptionSource();
+ assertSetOptionValue(optionSource, "boolean", "true");
+ assertEquals(true, optionSource.mBool);
+ }
+
+ /**
+ * Test {@link OptionSetter#setOptionValue(String, String)} for a boolean for a non-boolean
+ * value.
+ */
+ public void testSetOptionValue_booleanInvalid() throws ConfigurationException {
+ AllTypesOptionSource optionSource = new AllTypesOptionSource();
+ assertSetOptionValueInvalid(optionSource, "boolean", "blah");
+ }
+
+ /**
+ * Test {@link OptionSetter#setOptionValue(String, String)} for a Boolean.
+ */
+ public void testSetOptionValue_booleanObj() throws ConfigurationException {
+ AllTypesOptionSource optionSource = new AllTypesOptionSource();
+ assertSetOptionValue(optionSource, "booleanObj", "true");
+ assertTrue(optionSource.mBooleanObj);
+ }
+
+ /**
+ * Test {@link OptionSetter#setOptionValue(String, String)} for a byte.
+ */
+ public void testSetOptionValue_byte() throws ConfigurationException {
+ AllTypesOptionSource optionSource = new AllTypesOptionSource();
+ assertSetOptionValue(optionSource, "byte", "2");
+ assertEquals(2, optionSource.mByte);
+ }
+
+ /**
+ * Test {@link OptionSetter#setOptionValue(String, String)} for a byte for an invalid value.
+ */
+ public void testSetOptionValue_byteInvalid() throws ConfigurationException {
+ AllTypesOptionSource optionSource = new AllTypesOptionSource();
+ assertSetOptionValueInvalid(optionSource, "byte", "blah");
+ }
+
+ /**
+ * Test {@link OptionSetter#setOptionValue(String, String)} for a Byte.
+ */
+ public void testSetOptionValue_byteObj() throws ConfigurationException {
+ AllTypesOptionSource optionSource = new AllTypesOptionSource();
+ assertSetOptionValue(optionSource, "byteObj", "2");
+ assertTrue(2 == optionSource.mByteObj);
+ }
+
+ /**
+ * Test {@link OptionSetter#setOptionValue(String, String)} for a short.
+ */
+ public void testSetOptionValue_short() throws ConfigurationException {
+ AllTypesOptionSource optionSource = new AllTypesOptionSource();
+ assertSetOptionValue(optionSource, "short", "2");
+ assertTrue(2 == optionSource.mShort);
+ }
+
+ /**
+ * Test {@link OptionSetter#setOptionValue(String, String)} for a Short.
+ */
+ public void testSetOptionValue_shortObj() throws ConfigurationException {
+ AllTypesOptionSource optionSource = new AllTypesOptionSource();
+ assertSetOptionValue(optionSource, "shortObj", "2");
+ assertTrue(2 == optionSource.mShortObj);
+ }
+
+ /**
+ * Test {@link OptionSetter#setOptionValue(String, String)} for a short for an invalid value.
+ */
+ public void testSetOptionValue_shortInvalid() throws ConfigurationException {
+ AllTypesOptionSource optionSource = new AllTypesOptionSource();
+ assertSetOptionValueInvalid(optionSource, "short", "blah");
+ }
+
+ /**
+ * Test {@link OptionSetter#setOptionValue(String, String)} for a int.
+ */
+ public void testSetOptionValue_int() throws ConfigurationException {
+ AllTypesOptionSource optionSource = new AllTypesOptionSource();
+ assertSetOptionValue(optionSource, "int", "2");
+ assertTrue(2 == optionSource.mInt);
+ }
+
+ /**
+ * Test {@link OptionSetter#setOptionValue(String, String)} for a Integer.
+ */
+ public void testSetOptionValue_intObj() throws ConfigurationException {
+ AllTypesOptionSource optionSource = new AllTypesOptionSource();
+ assertSetOptionValue(optionSource, "intObj", "2");
+ assertTrue(2 == optionSource.mIntObj);
+ }
+
+ /**
+ * Test {@link OptionSetter#setOptionValue(String, String)} for a int for an invalid value.
+ */
+ public void testSetOptionValue_intInvalid() throws ConfigurationException {
+ AllTypesOptionSource optionSource = new AllTypesOptionSource();
+ assertSetOptionValueInvalid(optionSource, "int", "blah");
+ }
+
+ /**
+ * Test {@link OptionSetter#setOptionValue(String, String)} for a long.
+ */
+ public void testSetOptionValue_long() throws ConfigurationException {
+ AllTypesOptionSource optionSource = new AllTypesOptionSource();
+ assertSetOptionValue(optionSource, "long", "2");
+ assertTrue(2 == optionSource.mLong);
+ }
+
+ /**
+ * Test {@link OptionSetter#setOptionValue(String, String)} for a Long.
+ */
+ public void testSetOptionValue_longObj() throws ConfigurationException {
+ AllTypesOptionSource optionSource = new AllTypesOptionSource();
+ assertSetOptionValue(optionSource, "longObj", "2");
+ assertTrue(2 == optionSource.mLongObj);
+ }
+
+ /**
+ * Test {@link OptionSetter#setOptionValue(String, String)} for a long for an invalid value.
+ */
+ public void testSetOptionValue_longInvalid() throws ConfigurationException {
+ AllTypesOptionSource optionSource = new AllTypesOptionSource();
+ assertSetOptionValueInvalid(optionSource, "long", "blah");
+ }
+
+ /**
+ * Test {@link OptionSetter#setOptionValue(String, String)} for a float.
+ */
+ public void testSetOptionValue_float() throws ConfigurationException {
+ AllTypesOptionSource optionSource = new AllTypesOptionSource();
+ assertSetOptionValue(optionSource, "float", "2.1");
+ assertEquals(2.1, optionSource.mFloat, 0.01);
+ }
+
+ /**
+ * Test {@link OptionSetter#setOptionValue(String, String)} for a Float.
+ */
+ public void testSetOptionValue_floatObj() throws ConfigurationException {
+ AllTypesOptionSource optionSource = new AllTypesOptionSource();
+ assertSetOptionValue(optionSource, "floatObj", "2.1");
+ assertEquals(2.1, optionSource.mFloatObj, 0.01);
+ }
+
+ /**
+ * Test {@link OptionSetter#setOptionValue(String, String)} for a float for an invalid value.
+ */
+ public void testSetOptionValue_floatInvalid() throws ConfigurationException {
+ AllTypesOptionSource optionSource = new AllTypesOptionSource();
+ assertSetOptionValueInvalid(optionSource, "float", "blah");
+ }
+
+ /**
+ * Test {@link OptionSetter#setOptionValue(String, String)} for a float.
+ */
+ public void testSetOptionValue_double() throws ConfigurationException {
+ AllTypesOptionSource optionSource = new AllTypesOptionSource();
+ assertSetOptionValue(optionSource, "double", "2.1");
+ assertEquals(2.1, optionSource.mDouble, 0.01);
+ }
+
+ /**
+ * Test {@link OptionSetter#setOptionValue(String, String)} for a Float.
+ */
+ public void testSetOptionValue_doubleObj() throws ConfigurationException {
+ AllTypesOptionSource optionSource = new AllTypesOptionSource();
+ assertSetOptionValue(optionSource, "doubleObj", "2.1");
+ assertEquals(2.1, optionSource.mDoubleObj, 0.01);
+ }
+
+ /**
+ * Test {@link OptionSetter#setOptionValue(String, String)} for a double for an invalid value.
+ */
+ public void testSetOptionValue_doubleInvalid() throws ConfigurationException {
+ AllTypesOptionSource optionSource = new AllTypesOptionSource();
+ assertSetOptionValueInvalid(optionSource, "double", "blah");
+ }
+
+ /**
+ * Test {@link OptionSetter#setOptionValue(String, String)} for a File.
+ */
+ public void testSetOptionValue_file() throws ConfigurationException, IOException {
+ AllTypesOptionSource optionSource = new AllTypesOptionSource();
+ File tmpFile = File.createTempFile("testSetOptionValue_file", "txt");
+ try {
+ assertSetOptionValue(optionSource, "file", tmpFile.getAbsolutePath());
+ assertEquals(tmpFile.getAbsolutePath(), optionSource.mFile.getAbsolutePath());
+ } finally {
+ tmpFile.delete();
+ }
+ }
+
+ /**
+ * Test {@link OptionSetter#setOptionValue(String, String)} for an Enum.
+ */
+ public void testSetOptionValue_enum() throws ConfigurationException {
+ AllTypesOptionSource optionSource = new AllTypesOptionSource();
+ assertSetOptionValue(optionSource, "enum", "VAL1");
+ assertEquals(DefaultEnumClass.VAL1, optionSource.mEnum);
+ }
+
+ /**
+ * Test {@link OptionSetter#setOptionValue(String, String)} for an Enum. Specifically make sure
+ * that we fall back properly, so that a mixed-case value will be silently mapped to an
+ * uppercase version, since Enum constants tend to be uppercase by convention.
+ */
+ public void testSetOptionValue_enumMixedCase() throws ConfigurationException {
+ AllTypesOptionSource optionSource = new AllTypesOptionSource();
+ assertSetOptionValue(optionSource, "enum", "Val1");
+ assertEquals(DefaultEnumClass.VAL1, optionSource.mEnum);
+ }
+
+ /**
+ * Test {@link OptionSetter#setOptionValue(String, String)} for an Enum with custom values.
+ */
+ public void testSetOptionValue_customEnum() throws ConfigurationException {
+ AllTypesOptionSource optionSource = new AllTypesOptionSource();
+ assertSetOptionValue(optionSource, "customEnum", "VAL1");
+ assertEquals(CustomEnumClass.VAL1, optionSource.mCustomEnum);
+ assertEquals(42, optionSource.mCustomEnum.getVal());
+ }
+
+ /**
+ * Test {@link OptionSetter#setOptionValue(String, String)} for Enums used as the key and value
+ * of a {@link Map}.
+ */
+ public void testSetOptionValue_enumMap() throws ConfigurationException {
+ AllTypesOptionSource optionSource = new AllTypesOptionSource();
+
+ final String key = "VAL1";
+ final String value = "VAL1";
+ final DefaultEnumClass expectedKey = DefaultEnumClass.VAL1;
+ final CustomEnumClass expectedValue = CustomEnumClass.VAL1;
+
+ // Actually set the key/value pair
+ OptionSetter parser = new OptionSetter(optionSource);
+ parser.setOptionMapValue("enumMap", key, value);
+
+ assertEquals(1, optionSource.mEnumMap.size());
+ assertNotNull(optionSource.mEnumMap.get(expectedKey));
+ assertEquals(expectedValue, optionSource.mEnumMap.get(expectedKey));
+ }
+
+
+ /**
+ * Test {@link OptionSetter#setOptionValue(String, String)} for Enums used as the key and value
+ * of a {@link Map}.
+ */
+ public void testSetOptionValue_enumCollection() throws ConfigurationException {
+ AllTypesOptionSource optionSource = new AllTypesOptionSource();
+
+ final String value = "VAL1";
+ final DefaultEnumClass expectedValue = DefaultEnumClass.VAL1;
+
+ assertSetOptionValue(optionSource, "enumCollection", value);
+
+ assertEquals(1, optionSource.mEnumCollection.size());
+ assertTrue(optionSource.mEnumCollection.contains(expectedValue));
+ }
+
+
+ /**
+ * Test {@link OptionSetter#setOptionValue(String, String)} for an Enum.
+ */
+ public void testSetOptionValue_enumBadValue() throws ConfigurationException {
+ AllTypesOptionSource optionSource = new AllTypesOptionSource();
+ try {
+ assertSetOptionValue(optionSource, "enum", "noexist");
+ fail("ConfigurationException not thrown");
+ } catch (ConfigurationException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Make sure that Enum documentation shows the defaults properly
+ */
+ public void testEnumDocs() throws Exception {
+ // We assume here that the fields are returned in declaration order, as documented in the
+ // {@link Enum} javadoc.
+ String expectedValues = " Valid values: [VAL1, VAL3, VAL2]";
+ Field field = AllTypesOptionSource.class.getDeclaredField("mEnum");
+ String actualValues = OptionSetter.getEnumFieldValuesAsString(field);
+ assertEquals(expectedValues, actualValues);
+ }
+
+ /**
+ * Test {@link OptionSetter} for a final field
+ */
+ public void testOptionSetter_finalField() throws ConfigurationException {
+ FinalOption optionSource = new FinalOption();
+ try {
+ new OptionSetter(optionSource);
+ fail("ConfigurationException not thrown");
+ } catch (ConfigurationException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Perform {@link OptionSetter#setOptionValue(String, String)} for a given option.
+ */
+ private void assertSetOptionValue(AllTypesOptionSource optionSource, final String optionName,
+ final String expectedValue) throws ConfigurationException {
+ OptionSetter parser = new OptionSetter(optionSource);
+ parser.setOptionValue(optionName, expectedValue);
+ }
+
+ /**
+ * Perform {@link OptionSetter#setOptionValue(String, String)} for a given option, with an
+ * invalid value for the option type.
+ */
+ private void assertSetOptionValueInvalid(AllTypesOptionSource optionSource,
+ final String optionName, final String expectedValue) {
+ try {
+ assertSetOptionValue(optionSource, optionName, expectedValue);
+ fail("ConfigurationException not thrown");
+ } catch (ConfigurationException e) {
+ // expected
+ }
+ }
+}
diff --git a/tests/src/com/android/loganalysis/util/config/OptionUpdateRuleTest.java b/tests/src/com/android/loganalysis/util/config/OptionUpdateRuleTest.java
new file mode 100644
index 0000000..3dc187f
--- /dev/null
+++ b/tests/src/com/android/loganalysis/util/config/OptionUpdateRuleTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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 com.android.loganalysis.util.config;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for {@link OptionUpdateRule}
+ */
+public class OptionUpdateRuleTest extends TestCase {
+ private static final String mOptionName = "option-name";
+ private static final Object mCurrent = "5 current value";
+ private static final Object mUpdate = "5 update value";
+ private static final Object mSmallUpdate = "0 update value";
+ private static final Object mBigUpdate = "9 update value";
+
+ public void testFirst_simple() throws Exception {
+ assertEquals(mUpdate, OptionUpdateRule.FIRST.update(mOptionName, null, mUpdate));
+ assertEquals(mCurrent, OptionUpdateRule.FIRST.update(mOptionName, mCurrent, mUpdate));
+ }
+
+ public void testLast_simple() throws Exception {
+ assertEquals(mUpdate, OptionUpdateRule.LAST.update(mOptionName, null, mUpdate));
+ assertEquals(mUpdate, OptionUpdateRule.LAST.update(mOptionName, mCurrent, mUpdate));
+ }
+
+ public void testGreatest_simple() throws Exception {
+ assertEquals(mSmallUpdate,
+ OptionUpdateRule.GREATEST.update(mOptionName, null, mSmallUpdate));
+ assertEquals(mCurrent,
+ OptionUpdateRule.GREATEST.update(mOptionName, mCurrent, mSmallUpdate));
+ assertEquals(mBigUpdate,
+ OptionUpdateRule.GREATEST.update(mOptionName, mCurrent, mBigUpdate));
+ }
+
+ public void testLeast_simple() throws Exception {
+ assertEquals(mBigUpdate,
+ OptionUpdateRule.LEAST.update(mOptionName, null, mBigUpdate));
+ assertEquals(mSmallUpdate,
+ OptionUpdateRule.LEAST.update(mOptionName, mCurrent, mSmallUpdate));
+ assertEquals(mCurrent,
+ OptionUpdateRule.LEAST.update(mOptionName, mCurrent, mBigUpdate));
+ }
+
+ public void testImmutable_simple() throws Exception {
+ assertEquals(mUpdate, OptionUpdateRule.IMMUTABLE.update(mOptionName, null, mUpdate));
+ try {
+ OptionUpdateRule.IMMUTABLE.update(mOptionName, mCurrent, mUpdate);
+ fail("ConfigurationException not thrown when updating an IMMUTABLE option");
+ } catch (ConfigurationException e) {
+ // expected
+ }
+ }
+
+ public void testInvalidComparison() throws Exception {
+ try {
+ // Strings aren't comparable with integers
+ OptionUpdateRule.GREATEST.update(mOptionName, 13, mUpdate);
+ fail("ConfigurationException not thrown for invalid comparison.");
+ } catch (ConfigurationException e) {
+ // Expected. Moreover, the exception should be actionable, so make sure we mention the
+ // specific mismatching types.
+ final String msg = e.getMessage();
+ assertTrue(msg.contains("Integer"));
+ assertTrue(msg.contains("String"));
+ }
+ }
+
+ public void testNotComparable() throws Exception {
+ try {
+ OptionUpdateRule.LEAST.update(mOptionName, new Exception("hi"), mUpdate);
+ } catch (ConfigurationException e) {
+ // expected
+ }
+ }
+}
+