diff --git a/pom.xml b/pom.xml index 034fce13e..cf647667d 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.baidu.hugegraph hugegraph-common - 1.6.16 + 1.7.0 hugegraph-common https://github.com/hugegraph/hugegraph-common @@ -218,7 +218,7 @@ - 1.6.16.0 + 1.7.0.0 diff --git a/src/main/java/com/baidu/hugegraph/config/ConfigConvOption.java b/src/main/java/com/baidu/hugegraph/config/ConfigConvOption.java index 9f354d086..f67d0e478 100644 --- a/src/main/java/com/baidu/hugegraph/config/ConfigConvOption.java +++ b/src/main/java/com/baidu/hugegraph/config/ConfigConvOption.java @@ -21,27 +21,29 @@ import java.util.function.Function; +import com.baidu.hugegraph.util.E; import com.google.common.base.Predicate; -public class ConfigConvOption extends TypedOption { +public class ConfigConvOption extends TypedOption { - private final Function converter; + private final Function converter; - public ConfigConvOption(String name, String desc, Predicate pred, - Function convert, String value) { + public ConfigConvOption(String name, String desc, Predicate pred, + Function convert, T value) { this(name, false, desc, pred, convert, value); } + @SuppressWarnings("unchecked") public ConfigConvOption(String name, boolean required, String desc, - Predicate pred, Function convert, - String value) { - super(name, required, desc, pred, String.class, value); + Predicate pred, Function convert, + T value) { + super(name, required, desc, pred, (Class) value.getClass(), value); + E.checkNotNull(convert, "convert"); this.converter = convert; } @Override - public R convert(Object value) { - assert value instanceof String; - return this.converter.apply((String) value); + public R convert(T value) { + return this.converter.apply(value); } } diff --git a/src/main/java/com/baidu/hugegraph/config/ConfigListConvOption.java b/src/main/java/com/baidu/hugegraph/config/ConfigListConvOption.java index 6d5fa9589..8162500c7 100644 --- a/src/main/java/com/baidu/hugegraph/config/ConfigListConvOption.java +++ b/src/main/java/com/baidu/hugegraph/config/ConfigListConvOption.java @@ -35,15 +35,8 @@ public class ConfigListConvOption extends TypedOption, List> { @SuppressWarnings("unchecked") public ConfigListConvOption(String name, String desc, Predicate> pred, Function convert, - T value) { - this(name, desc, pred, convert, (Class) value.getClass(), value); - } - - @SuppressWarnings("unchecked") - public ConfigListConvOption(String name, String desc, - Predicate> pred, Function convert, - Class clazz, T... values) { - this(name, false, desc, pred, convert, clazz, Arrays.asList(values)); + T... values) { + this(name, false, desc, pred, convert, null, Arrays.asList(values)); } @SuppressWarnings("unchecked") @@ -52,21 +45,33 @@ public ConfigListConvOption(String name, boolean required, String desc, Class clazz, List values) { super(name, required, desc, pred, (Class>) values.getClass(), values); + E.checkNotNull(convert, "convert"); + if (clazz == null && values.size() > 0) { + clazz = (Class) values.get(0).getClass(); + } E.checkArgumentNotNull(clazz, "Element class can't be null"); this.elemClass = clazz; this.converter = convert; } @Override - public List convert(Object value) { - List results = ConfigListOption.convert(value, part -> { - return super.convert(part, this.elemClass); + protected boolean forList() { + return true; + } + + @Override + protected List parse(Object value) { + return ConfigListOption.convert(value, part -> { + return this.parse(part, this.elemClass); }); + } - List enums = new ArrayList<>(results.size()); - for (T elem : results) { - enums.add(this.converter.apply(elem)); + @Override + public List convert(List values) { + List results = new ArrayList<>(values.size()); + for (T value : values) { + results.add(this.converter.apply(value)); } - return enums; + return results; } } diff --git a/src/main/java/com/baidu/hugegraph/config/ConfigListOption.java b/src/main/java/com/baidu/hugegraph/config/ConfigListOption.java index 9add0bc94..565e9c71b 100644 --- a/src/main/java/com/baidu/hugegraph/config/ConfigListOption.java +++ b/src/main/java/com/baidu/hugegraph/config/ConfigListOption.java @@ -33,15 +33,8 @@ public class ConfigListOption extends ConfigOption> { @SuppressWarnings("unchecked") public ConfigListOption(String name, String desc, - Predicate> pred, T value) { - this(name, desc, pred, (Class) value.getClass(), value); - } - - @SuppressWarnings("unchecked") - public ConfigListOption(String name, String desc, - Predicate> pred, Class clazz, - T... values) { - this(name, false, desc, pred, clazz, Arrays.asList(values)); + Predicate> pred, T... values) { + this(name, false, desc, pred, null, Arrays.asList(values)); } @SuppressWarnings("unchecked") @@ -50,13 +43,21 @@ public ConfigListOption(String name, boolean required, String desc, List values) { super(name, required, desc, pred, (Class>) values.getClass(), values); + if (clazz == null && values.size() > 0) { + clazz = (Class) values.get(0).getClass(); + } E.checkArgumentNotNull(clazz, "Element class can't be null"); this.elemClass = clazz; } @Override - public List convert(Object value) { - return convert(value, part -> super.convert(part, this.elemClass)); + protected boolean forList() { + return true; + } + + @Override + protected List parse(Object value) { + return convert(value, part -> this.parse(part, this.elemClass)); } @SuppressWarnings("unchecked") diff --git a/src/main/java/com/baidu/hugegraph/config/HugeConfig.java b/src/main/java/com/baidu/hugegraph/config/HugeConfig.java index 7dc6ec8c1..1c9b16b8e 100644 --- a/src/main/java/com/baidu/hugegraph/config/HugeConfig.java +++ b/src/main/java/com/baidu/hugegraph/config/HugeConfig.java @@ -48,9 +48,6 @@ public HugeConfig(Configuration config) { Iterator keys = config.getKeys(); while (keys.hasNext()) { String key = keys.next(); - if (key.contains("..")) { - key = key.replace("..", "."); - } this.addProperty(key, config.getProperty(key)); } this.checkRequiredOptions(); @@ -145,17 +142,7 @@ private Object validateOption(String key, Object value) { "Invalid value for key '%s': %s", key, value); TypedOption option = OptionSpace.get(key); - Class dataType = option.dataType(); - - if (List.class.isAssignableFrom(dataType)) { - E.checkState(option instanceof ConfigListOption, - "List option must be registered with " + - "class ConfigListOption"); - } - - value = option.convert(value); - option.check(value); - return value; + return option.parseConvert(value); } private void checkRequiredOptions() { diff --git a/src/main/java/com/baidu/hugegraph/config/OptionHolder.java b/src/main/java/com/baidu/hugegraph/config/OptionHolder.java index 6b5c398d9..e5c5be6a6 100644 --- a/src/main/java/com/baidu/hugegraph/config/OptionHolder.java +++ b/src/main/java/com/baidu/hugegraph/config/OptionHolder.java @@ -40,6 +40,10 @@ public OptionHolder() { protected void registerOptions() { for (Field field : this.getClass().getFields()) { + if (!TypedOption.class.isAssignableFrom(field.getType())) { + // Skip if not option + continue; + } try { TypedOption option = (TypedOption) field.get(this); // Fields of subclass first, don't overwrite by superclass diff --git a/src/main/java/com/baidu/hugegraph/config/OptionSpace.java b/src/main/java/com/baidu/hugegraph/config/OptionSpace.java index 485fb81d2..8e633fa26 100644 --- a/src/main/java/com/baidu/hugegraph/config/OptionSpace.java +++ b/src/main/java/com/baidu/hugegraph/config/OptionSpace.java @@ -21,12 +21,15 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Collections; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import org.slf4j.Logger; +import com.baidu.hugegraph.util.E; import com.baidu.hugegraph.util.Log; public final class OptionSpace { @@ -62,7 +65,15 @@ public static void register(String module, String holder) { Exception exception = null; try { Method method = clazz.getMethod(INSTANCE_METHOD); + if (!Modifier.isStatic(method.getModifiers())) { + throw new NoSuchMethodException(INSTANCE_METHOD); + } instance = (OptionHolder) method.invoke(null); + if (instance == null) { + exception = new ConfigException( + "Returned null from %s() method", + INSTANCE_METHOD); + } } catch (NoSuchMethodException e) { LOG.warn("Class {} does not has static method {}.", holder, INSTANCE_METHOD); @@ -91,6 +102,7 @@ public static void register(String module, OptionHolder holder) { LOG.warn("Already registered option holder: {} ({})", module, holders.get(module)); } + E.checkArgumentNotNull(holder, "OptionHolder can't be null"); holders.put(module, holder.getClass()); options.putAll(holder.options()); LOG.debug("Registered options for OptionHolder: {}", @@ -98,10 +110,10 @@ public static void register(String module, OptionHolder holder) { } public static Set keys() { - return options.keySet(); + return Collections.unmodifiableSet(options.keySet()); } - public static Boolean containKey(String key) { + public static boolean containKey(String key) { return options.containsKey(key); } diff --git a/src/main/java/com/baidu/hugegraph/config/TypedOption.java b/src/main/java/com/baidu/hugegraph/config/TypedOption.java index 91fb7ea33..57d77c6fa 100644 --- a/src/main/java/com/baidu/hugegraph/config/TypedOption.java +++ b/src/main/java/com/baidu/hugegraph/config/TypedOption.java @@ -112,14 +112,24 @@ public R defaultValue() { return this.convert(this.defaultValue); } + public R parseConvert(Object value) { + T parsed = this.parse(value); + this.check(parsed); + return this.convert(parsed); + } + @SuppressWarnings("unchecked") - public R convert(Object value) { - return (R) this.convert(value, this.dataType); + protected T parse(Object value) { + return (T) this.parse(value, this.dataType); } - public Object convert(Object value, Class dataType) { + protected Object parse(Object value, Class dataType) { if (dataType.equals(String.class)) { return value; + } else if (List.class.isAssignableFrom(dataType)) { + E.checkState(this.forList(), + "List option can't be registered with class %s", + this.getClass().getSimpleName()); } // Use PropertyConverter method `toXXX` convert value @@ -138,20 +148,35 @@ public Object convert(Object value, Class dataType) { } } - public void check(Object value) { + protected void check(Object value) { E.checkNotNull(value, "value", this.name); - E.checkArgument(this.dataType.isInstance(value), - "Invalid type of value '%s' for option '%s'", - value, this.name); + if (!this.dataType.isInstance(value)) { + throw new ConfigException( + "Invalid type of value '%s' for option '%s', " + + "expect type %s but got %s", value, this.name, + this.dataType.getSimpleName(), + value.getClass().getSimpleName()); + } + if (this.checkFunc != null) { @SuppressWarnings("unchecked") T result = (T) value; - E.checkArgument(this.checkFunc.apply(result), - "Invalid option value for '%s': %s", - this.name, value); + if (!this.checkFunc.apply(result)) { + throw new ConfigException("Invalid option value for '%s': %s", + this.name, value); + } } } + @SuppressWarnings("unchecked") + protected R convert(T value) { + return (R) value; + } + + protected boolean forList() { + return false; + } + @Override public String toString() { return String.format("[%s]%s=%s", this.dataType.getSimpleName(), diff --git a/src/main/java/com/baidu/hugegraph/version/CommonVersion.java b/src/main/java/com/baidu/hugegraph/version/CommonVersion.java index 0e4d2be9f..27048fd3a 100644 --- a/src/main/java/com/baidu/hugegraph/version/CommonVersion.java +++ b/src/main/java/com/baidu/hugegraph/version/CommonVersion.java @@ -27,5 +27,5 @@ public class CommonVersion { // The second parameter of Version.of() is for all-in-one JAR public static final Version VERSION = Version.of(CommonVersion.class, - "1.6.16"); + "1.7.0"); } diff --git a/src/test/java/com/baidu/hugegraph/unit/UnitTestSuite.java b/src/test/java/com/baidu/hugegraph/unit/UnitTestSuite.java index a8d597a6e..4d292d626 100644 --- a/src/test/java/com/baidu/hugegraph/unit/UnitTestSuite.java +++ b/src/test/java/com/baidu/hugegraph/unit/UnitTestSuite.java @@ -24,9 +24,10 @@ import com.baidu.hugegraph.testutil.AssertTest; import com.baidu.hugegraph.testutil.WhiteboxTest; -import com.baidu.hugegraph.unit.concurrent.RowLockTest; import com.baidu.hugegraph.unit.concurrent.LockGroupTest; +import com.baidu.hugegraph.unit.concurrent.RowLockTest; import com.baidu.hugegraph.unit.config.HugeConfigTest; +import com.baidu.hugegraph.unit.config.OptionSpaceTest; import com.baidu.hugegraph.unit.date.SafeDateFormatTest; import com.baidu.hugegraph.unit.event.EventHubTest; import com.baidu.hugegraph.unit.iterator.ExtendableIteratorTest; @@ -60,6 +61,7 @@ LockGroupTest.class, RowLockTest.class, HugeConfigTest.class, + OptionSpaceTest.class, SafeDateFormatTest.class, EventHubTest.class, PerfUtilTest.class, diff --git a/src/test/java/com/baidu/hugegraph/unit/config/HugeConfigTest.java b/src/test/java/com/baidu/hugegraph/unit/config/HugeConfigTest.java index 131cedc9c..30369d091 100644 --- a/src/test/java/com/baidu/hugegraph/unit/config/HugeConfigTest.java +++ b/src/test/java/com/baidu/hugegraph/unit/config/HugeConfigTest.java @@ -28,6 +28,7 @@ import static com.baidu.hugegraph.config.OptionChecker.rangeInt; import java.util.Arrays; +import java.util.List; import org.apache.commons.configuration.Configuration; import org.apache.commons.configuration.PropertiesConfiguration; @@ -35,6 +36,7 @@ import org.junit.Test; import com.baidu.hugegraph.config.ConfigConvOption; +import com.baidu.hugegraph.config.ConfigException; import com.baidu.hugegraph.config.ConfigListConvOption; import com.baidu.hugegraph.config.ConfigListOption; import com.baidu.hugegraph.config.ConfigOption; @@ -44,18 +46,51 @@ import com.baidu.hugegraph.testutil.Assert; import com.baidu.hugegraph.testutil.Whitebox; import com.baidu.hugegraph.unit.BaseUnitTest; +import com.google.common.base.Predicate; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; public class HugeConfigTest extends BaseUnitTest { - private static final String CONF = - "src/test/java/com/baidu/hugegraph/unit/config/test.conf"; + private static final String PATH = + "src/test/java/com/baidu/hugegraph/unit/config/"; + private static final String CONF = PATH + "test.conf"; @BeforeClass public static void init() { OptionSpace.register("test", TestOptions.class.getName()); } + @Test + public void testOptionDataType() { + Assert.assertEquals(String.class, TestOptions.text1.dataType()); + Assert.assertEquals(Integer.class, TestOptions.int1.dataType()); + Assert.assertEquals(Long.class, TestOptions.long1.dataType()); + Assert.assertEquals(Float.class, TestOptions.float1.dataType()); + Assert.assertEquals(Double.class, TestOptions.double1.dataType()); + Assert.assertEquals(Boolean.class, TestOptions.bool.dataType()); + + Assert.assertEquals(List.class, TestOptions.list.dataType()); + Assert.assertEquals(List.class, TestOptions.map.dataType()); + + Assert.assertEquals(String.class, TestOptions.weekday.dataType()); + Assert.assertEquals(List.class, TestOptions.weekdays.dataType()); + } + + @Test + public void testOptionDesc() { + Assert.assertEquals("description of group1.text1", + TestOptions.text1.desc()); + Assert.assertEquals("description of group1.text2 sub", + TestSubOptions.text2.desc()); + } + + @Test + public void testOptionRequired() { + Assert.assertEquals(false, TestOptions.text1.required()); + Assert.assertEquals(true, TestSubOptions.text2.required()); + } + @Test public void testOptionsToString() { Assert.assertEquals("[String]group1.text1=text1-value", @@ -83,6 +118,126 @@ public void testOptionsToString() { TestSubOptions.textsub.toString()); } + @Test + public void testOptionWithError() { + Assert.assertThrows(ConfigException.class, () -> { + new ConfigOption<>( + "group1.text", + "description of group1.text", + disallowEmpty(), + "" + ); + }); + + Assert.assertThrows(ConfigException.class, () -> { + new ConfigOption<>( + "group1.choice", + "description of group1.choice", + allowValues("CHOICE-1", "CHOICE-2", "CHOICE-3"), + "CHOICE-4" + ); + }); + + Assert.assertThrows(ConfigException.class, () -> { + new ConfigListOption<>( + "group1.list", + true, + "description of group1.list", + disallowEmpty(), + String.class, + ImmutableList.of() + ); + }); + + Assert.assertThrows(ConfigException.class, () -> { + new ConfigOption<>( + "group1.int", + "description of group1.int", + positiveInt(), + 0 + ); + }); + + Assert.assertThrows(ConfigException.class, () -> { + new ConfigOption<>( + "group1.int", + "description of group1.int", + nonNegativeInt(), + -1 + ); + }); + + Assert.assertThrows(ConfigException.class, () -> { + new ConfigOption<>( + "group1.long", + "description of group1.long", + rangeInt(1L, 100L), + 0L + ); + }); + + Assert.assertThrows(ConfigException.class, () -> { + new ConfigOption<>( + "group1.long", + "description of group1.long", + rangeInt(1L, 100L), + 101L + ); + }); + + Assert.assertThrows(ConfigException.class, () -> { + new ConfigOption<>( + "group1.double", + "description of group1.double", + rangeDouble(1D, 10D), + 0D + ); + }); + + Assert.assertThrows(ConfigException.class, () -> { + new ConfigOption<>( + "group1.double", + "description of group1.double", + rangeDouble(1D, 10D), + 11D + ); + }); + + Assert.assertThrows(ConfigException.class, () -> { + new ConfigListOption<>( + "group1.list", + "description of list with invalid default values", + disallowEmpty() + ); + }); + + Assert.assertThrows(IllegalArgumentException.class, () -> { + new ConfigListOption<>( + "group1.list", + "description of list with invalid default values", + null + ); + }); + + Assert.assertThrows(ConfigException.class, () -> { + new ConfigListConvOption( + "group1.list_conv", + "description of list_conv with invalid default values", + disallowEmpty(), + s -> WeekDay.valueOf(s) + ); + }); + + Assert.assertThrows(IllegalArgumentException.class, () -> { + new ConfigListConvOption( + "group1.list_conv", + "description of list_conv with invalid default values", + null, + s -> WeekDay.valueOf(s) + ); + }); + } + @Test public void testHugeConfig() throws Exception { Configuration conf = new PropertiesConfiguration(); @@ -105,15 +260,19 @@ public void testHugeConfig() throws Exception { Assert.assertEquals(true, config.get(TestOptions.bool)); - Assert.assertEquals(WeekDay.WEDNESDAY, config.get(TestOptions.weekday)); - Assert.assertEquals(Arrays.asList(WeekDay.SATURDAY, WeekDay.SUNDAY), - config.get(TestOptions.weekdays)); - Assert.assertEquals(Arrays.asList("list-value1", "list-value2"), config.get(TestOptions.list)); Assert.assertEquals(ImmutableMap.of("key1", "value1", "key2", "value2"), config.getMap(TestOptions.map)); + + Assert.assertEquals(WeekDay.WEDNESDAY, config.get(TestOptions.weekday)); + Assert.assertEquals(Arrays.asList(WeekDay.SATURDAY, WeekDay.SUNDAY), + config.get(TestOptions.weekdays)); + + Assert.assertThrows(ConfigException.class, () -> { + new HugeConfig((Configuration) null); + }); } @Test @@ -140,6 +299,10 @@ public void testHugeConfigWithFile() throws Exception { Assert.assertEquals(ImmutableMap.of("key1", "value1", "key3", "value3"), config.getMap(TestOptions.map)); + + Assert.assertEquals(WeekDay.SUNDAY, config.get(TestOptions.weekday)); + Assert.assertEquals(Arrays.asList(WeekDay.SATURDAY, WeekDay.FRIDAY), + config.get(TestOptions.weekdays)); } @Test @@ -166,6 +329,36 @@ public void testHugeConfigWithOverride() throws Exception { config.get(TestSubOptions.textsub)); } + @Test + public void testHugeConfigWithTypeError() { + OptionSpace.register("test-type-error", + TestOptionsWithTypeError.class.getName()); + + Assert.assertThrows(ConfigException.class, () -> { + new HugeConfig(PATH + "test-type-error.conf"); + }); + } + + @Test + public void testHugeConfigWithCheckError() throws Exception { + OptionSpace.register("test-check-error", + TestOptionsWithCheckError.class.getName()); + + Assert.assertThrows(ConfigException.class, () -> { + new HugeConfig(PATH + "test-check-error.conf"); + }); + } + + @Test + public void testHugeConfigWithListOptionError() throws Exception { + OptionSpace.register("test-list-error", + TestOptionsWithListError.class.getName()); + + Assert.assertThrows(IllegalStateException.class, () -> { + new HugeConfig(PATH + "test-list-error.conf"); + }); + } + public static class TestOptions extends OptionHolder { private static volatile TestOptions instance; @@ -190,7 +383,6 @@ public static synchronized TestOptions instance() { new ConfigOption<>( "group1.text2", "description of group1.text2", - disallowEmpty(), "text2-value" ); @@ -258,7 +450,7 @@ public static synchronized TestOptions instance() { true ); - public static final ConfigConvOption weekday = + public static final ConfigConvOption weekday = new ConfigConvOption<>( "group1.weekday", "description of group1.weekday", @@ -275,7 +467,6 @@ public static synchronized TestOptions instance() { inValues("SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY"), WeekDay::valueOf, - String.class, "SATURDAY", "SUNDAY" ); @@ -284,7 +475,6 @@ public static synchronized TestOptions instance() { "group1.list", "description of group1.list", disallowEmpty(), - String.class, "list-value1", "list-value2" ); @@ -293,7 +483,6 @@ public static synchronized TestOptions instance() { "group1.map", "description of group1.map", disallowEmpty(), - String.class, "key1:value1", "key2:value2" ); } @@ -303,8 +492,10 @@ public static class TestSubOptions extends TestOptions { public static final ConfigOption text2 = new ConfigOption<>( "group1.text2", - "description of group1.text2", + true, + "description of group1.text2 sub", disallowEmpty(), + String.class, "text2-value-override" ); @@ -317,6 +508,86 @@ public static class TestSubOptions extends TestOptions { ); } + public static class TestOptionsWithTypeError extends OptionHolder { + + private static volatile TestOptionsWithTypeError instance; + + public static synchronized TestOptionsWithTypeError instance() { + if (instance == null) { + instance = new TestOptionsWithTypeError(); + instance.registerOptions(); + } + return instance; + } + + public static final ConfigOption intError = + new ConfigOption<>( + "group1.int_type_error", + "description of group1.int_type_error", + rangeInt(1, 100), + 1 + ); + } + + public static class TestOptionsWithCheckError extends OptionHolder { + + private static volatile TestOptionsWithCheckError instance; + + public static synchronized TestOptionsWithCheckError instance() { + if (instance == null) { + instance = new TestOptionsWithCheckError(); + instance.registerOptions(); + } + return instance; + } + + public static final ConfigOption intError = + new ConfigOption<>( + "group1.int_check_error", + "description of group1.int_check_error", + rangeInt(1, 100), + 1 + ); + } + + public static class TestOptionsWithListError extends OptionHolder { + + private static volatile TestOptionsWithListError instance; + + public static synchronized TestOptionsWithListError instance() { + if (instance == null) { + instance = new TestOptionsWithListError(); + instance.registerOptions(); + } + return instance; + } + + public static final InvalidConfigListOption listError = + new InvalidConfigListOption<>( + "group1.list_for_list_error", + "description of group1.list_for_list_error", + disallowEmpty(), + 1 + ); + + static class InvalidConfigListOption extends ConfigOption> { + + @SuppressWarnings("unchecked") + public InvalidConfigListOption(String name, String desc, + Predicate> pred, + T... values) { + super(name, false, desc, pred, + (Class>) Arrays.asList(values).getClass(), + Arrays.asList(values)); + } + + @Override + protected boolean forList() { + return false; + } + } + } + public enum WeekDay { SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY; diff --git a/src/test/java/com/baidu/hugegraph/unit/config/OptionSpaceTest.java b/src/test/java/com/baidu/hugegraph/unit/config/OptionSpaceTest.java new file mode 100644 index 000000000..3ff2c0512 --- /dev/null +++ b/src/test/java/com/baidu/hugegraph/unit/config/OptionSpaceTest.java @@ -0,0 +1,217 @@ +/* + * Copyright 2017 HugeGraph Authors + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to You 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.baidu.hugegraph.unit.config; + +import static com.baidu.hugegraph.config.OptionChecker.disallowEmpty; + +import org.junit.Test; + +import com.baidu.hugegraph.config.ConfigException; +import com.baidu.hugegraph.config.ConfigOption; +import com.baidu.hugegraph.config.OptionHolder; +import com.baidu.hugegraph.config.OptionSpace; +import com.baidu.hugegraph.testutil.Assert; +import com.baidu.hugegraph.unit.BaseUnitTest; +import com.google.common.base.Predicate; + +public class OptionSpaceTest extends BaseUnitTest { + + @Test + public void tesRegister() { + int oldSize = OptionSpace.keys().size(); + + OptionSpace.register("testgroup1", OptionHolder1.class.getName()); + Assert.assertEquals(oldSize + 2, OptionSpace.keys().size()); + Assert.assertTrue(OptionSpace.containKey("testgroup1.text1")); + Assert.assertTrue(OptionSpace.containKey("testgroup1.text2")); + + OptionSpace.register("testgroup1", new OptionHolder1()); + Assert.assertEquals(oldSize + 2, OptionSpace.keys().size()); + Assert.assertTrue(OptionSpace.containKey("testgroup1.text1")); + Assert.assertTrue(OptionSpace.containKey("testgroup1.text2")); + + OptionSpace.register("testgroup2", OptionHolder2.class.getName()); + Assert.assertEquals(oldSize + 4, OptionSpace.keys().size()); + + Assert.assertTrue(OptionSpace.containKey("testgroup1.text1")); + Assert.assertTrue(OptionSpace.containKey("testgroup1.text2")); + Assert.assertTrue(OptionSpace.containKey("testgroup2.text1")); + Assert.assertTrue(OptionSpace.containKey("testgroup2.text2")); + + Assert.assertEquals("text1 value", + OptionSpace.get("testgroup1.text1").defaultValue()); + Assert.assertEquals("text2 value", + OptionSpace.get("testgroup1.text2").defaultValue()); + Assert.assertEquals("text1 value", + OptionSpace.get("testgroup2.text1").defaultValue()); + Assert.assertEquals("text2 value", + OptionSpace.get("testgroup2.text2").defaultValue()); + } + + @Test + public void testRegisterWithError() { + Assert.assertThrows(ConfigException.class, () -> { + OptionSpace.register("test-error", "fake"); + }); + + Assert.assertThrows(ConfigException.class, () -> { + OptionSpace.register("test-error", Exception.class.getName()); + }); + + Assert.assertThrows(ConfigException.class, () -> { + OptionSpace.register("test-error", + OptionHolderWithoutInstance.class.getName()); + }); + + Assert.assertThrows(ConfigException.class, () -> { + OptionSpace.register("test-error", OptionHolderWithNonStaticInstance + .class.getName()); + }); + + Assert.assertThrows(ConfigException.class, () -> { + OptionSpace.register("test-error", + OptionHolderWithInstanceNull.class.getName()); + }); + + Assert.assertThrows(ConfigException.class, () -> { + OptionSpace.register("test-error", + OptionHolderWithInstanceThrow.class.getName()); + }); + + Assert.assertThrows(ConfigException.class, () -> { + OptionSpace.register("test-error", + OptionHolderWithInvalidOption.class.getName()); + }); + } + + public static class OptionHolderWithoutInstance extends OptionHolder { + // no instance() + } + + public static class OptionHolderWithNonStaticInstance extends OptionHolder { + + // not static instance() + public OptionHolderWithNonStaticInstance instance() { + return new OptionHolderWithNonStaticInstance(); + } + } + + public static class OptionHolderWithInstanceNull extends OptionHolder { + + public static OptionHolderWithInstanceNull instance() { + return null; + } + } + + public static class OptionHolderWithInstanceThrow extends OptionHolder { + + public static OptionHolderWithInstanceNull instance() { + throw new RuntimeException("test error"); + } + } + + public static class OptionHolderWithInvalidOption extends OptionHolder { + + public static OptionHolderWithInvalidOption instance() { + return new OptionHolderWithInvalidOption(); + } + + private OptionHolderWithInvalidOption() { + this.registerOptions(); + } + + public static final String fake = "fake"; + + public static final ConfigOption invalid = + new InvalidOption<>( + "group1.text1", + "description of group1.text1", + disallowEmpty(), + "value" + ); + + public static class InvalidOption extends ConfigOption { + + public InvalidOption(String name, String desc, + Predicate pred, T value) { + super(name, desc, pred, value); + } + + @Override + public String name() { + throw new RuntimeException("fake"); + } + } + } + + public static class OptionHolder1 extends OptionHolder { + + public static OptionHolder1 instance() { + return new OptionHolder1(); + } + + OptionHolder1() { + this.registerOptions(); + } + + public static final ConfigOption text1 = + new ConfigOption<>( + "testgroup1.text1", + "description of testgroup1.text1", + disallowEmpty(), + "text1 value" + ); + + public static final ConfigOption text2 = + new ConfigOption<>( + "testgroup1.text2", + "description of testgroup1.text2", + disallowEmpty(), + "text2 value" + ); + } + + public static class OptionHolder2 extends OptionHolder { + + public static OptionHolder2 instance() { + return new OptionHolder2(); + } + + OptionHolder2() { + this.registerOptions(); + } + + public static final ConfigOption text1 = + new ConfigOption<>( + "testgroup2.text1", + "description of testgroup2.text1", + disallowEmpty(), + "text1 value" + ); + + public static final ConfigOption text2 = + new ConfigOption<>( + "testgroup2.text2", + "description of testgroup2.text2", + disallowEmpty(), + "text2 value" + ); + } +} diff --git a/src/test/java/com/baidu/hugegraph/unit/config/test-check-error.conf b/src/test/java/com/baidu/hugegraph/unit/config/test-check-error.conf new file mode 100644 index 000000000..53aec1846 --- /dev/null +++ b/src/test/java/com/baidu/hugegraph/unit/config/test-check-error.conf @@ -0,0 +1 @@ +group1.int_check_error=101 diff --git a/src/test/java/com/baidu/hugegraph/unit/config/test-list-error.conf b/src/test/java/com/baidu/hugegraph/unit/config/test-list-error.conf new file mode 100644 index 000000000..907b197f4 --- /dev/null +++ b/src/test/java/com/baidu/hugegraph/unit/config/test-list-error.conf @@ -0,0 +1,2 @@ +group1.list_for_list_error=[1,2,3] + diff --git a/src/test/java/com/baidu/hugegraph/unit/config/test-type-error.conf b/src/test/java/com/baidu/hugegraph/unit/config/test-type-error.conf new file mode 100644 index 000000000..ac70d4891 --- /dev/null +++ b/src/test/java/com/baidu/hugegraph/unit/config/test-type-error.conf @@ -0,0 +1 @@ +group1.int_type_error=string diff --git a/src/test/java/com/baidu/hugegraph/unit/config/test.conf b/src/test/java/com/baidu/hugegraph/unit/config/test.conf index bf31c70f6..bd2ea2a85 100644 --- a/src/test/java/com/baidu/hugegraph/unit/config/test.conf +++ b/src/test/java/com/baidu/hugegraph/unit/config/test.conf @@ -14,3 +14,8 @@ group1.bool=false group1.list=[file-v1, file-v2, file-v3] group1.map=[key1:value1, key3:value3] + +group1.weekday=SUNDAY +group1.weekdays=[SATURDAY, FRIDAY] + +group1.no-used=value