/** * Define a new configuration with no special validation logic * @param name The name of the config parameter * @param type The type of the config * @param defaultValue The default value to use if this config isn't present * @param importance The importance of this config: is this something you will likely need to change. * @param documentation The documentation string for the config * @return This ConfigDef so you can chain calls */ public ConfigDef define(String name, Type type, Object defaultValue, Importance importance, String documentation) { return define(name, type, defaultValue, null, importance, documentation); }
/** * Define a new configuration with no default value and no special validation logic * @param name The name of the config parameter * @param type The type of the config * @param importance The importance of this config: is this something you will likely need to change. * @param documentation The documentation string for the config * @return This ConfigDef so you can chain calls */ public ConfigDef define(String name, Type type, Importance importance, String documentation) { return define(name, type, NO_DEFAULT_VALUE, null, importance, documentation); }
/** * Define a new configuration with no group, no order in group, no width, no display name, no dependents and no custom recommender * @param name the name of the config parameter * @param type the type of the config * @param defaultValue the default value to use if this config isn't present * @param validator the validator to use in checking the correctness of the config * @param importance the importance of this config * @param documentation the documentation string for the config * @return This ConfigDef so you can chain calls */ public ConfigDef define(String name, Type type, Object defaultValue, Validator validator, Importance importance, String documentation) { return define(name, type, defaultValue, validator, importance, documentation, null, -1, Width.NONE, name); }
/** * Define a new configuration with no default value, no special validation logic, no dependents and no custom recommender * @param name the name of the config parameter * @param type the type of the config * @param importance the importance of this config * @param documentation the documentation string for the config * @param group the group this config belongs to * @param orderInGroup the order of this config in the group * @param width the width of the config * @param displayName the name suitable for display * @return This ConfigDef so you can chain calls */ public ConfigDef define(String name, Type type, Importance importance, String documentation, String group, int orderInGroup, Width width, String displayName) { return define(name, type, NO_DEFAULT_VALUE, null, importance, documentation, group, orderInGroup, width, displayName, Collections.<String>emptyList()); }
/** * Define a new internal configuration. Internal configuration won't show up in the docs and aren't * intended for general use. * @param name The name of the config parameter * @param type The type of the config * @param defaultValue The default value to use if this config isn't present * @param importance * @return This ConfigDef so you can chain calls */ public ConfigDef defineInternal(final String name, final Type type, final Object defaultValue, final Importance importance) { return define(new ConfigKey(name, type, defaultValue, null, importance, "", "", -1, Width.NONE, name, Collections.<String>emptyList(), null, true)); }
@Test public void testGroupInference() { List<String> expected1 = Arrays.asList("group1", "group2"); ConfigDef def1 = new ConfigDef() .define("a", Type.INT, Importance.HIGH, "docs", "group1", 1, Width.SHORT, "a") .define("b", Type.INT, Importance.HIGH, "docs", "group2", 1, Width.SHORT, "b") .define("c", Type.INT, Importance.HIGH, "docs", "group1", 2, Width.SHORT, "c"); assertEquals(expected1, def1.groups()); List<String> expected2 = Arrays.asList("group2", "group1"); ConfigDef def2 = new ConfigDef() .define("a", Type.INT, Importance.HIGH, "docs", "group2", 1, Width.SHORT, "a") .define("b", Type.INT, Importance.HIGH, "docs", "group2", 2, Width.SHORT, "b") .define("c", Type.INT, Importance.HIGH, "docs", "group1", 2, Width.SHORT, "c"); assertEquals(expected2, def2.groups()); }
@Test public void testBaseConfigDefDependents() { // Creating a ConfigDef based on another should compute the correct number of configs with no parent, even // if the base ConfigDef has already computed its parentless configs final ConfigDef baseConfigDef = new ConfigDef().define("a", Type.STRING, Importance.LOW, "docs"); assertEquals(new HashSet<>(Arrays.asList("a")), baseConfigDef.getConfigsWithNoParent()); final ConfigDef configDef = new ConfigDef(baseConfigDef) .define("parent", Type.STRING, Importance.HIGH, "parent docs", "group", 1, Width.LONG, "Parent", Collections.singletonList("child")) .define("child", Type.STRING, Importance.HIGH, "docs"); assertEquals(new HashSet<>(Arrays.asList("a", "parent")), configDef.getConfigsWithNoParent()); }
@Test(expected = ConfigException.class) public void testMissingDependentConfigs() { // Should not be possible to parse a config if a dependent config has not been defined final ConfigDef configDef = new ConfigDef() .define("parent", Type.STRING, Importance.HIGH, "parent docs", "group", 1, Width.LONG, "Parent", Collections.singletonList("child")); configDef.parse(Collections.emptyMap()); }
@Test public void testNestedClass() { // getName(), not getSimpleName() or getCanonicalName(), is the version that should be able to locate the class Map<String, Object> props = Collections.<String, Object>singletonMap("name", NestedClass.class.getName()); new ConfigDef().define("name", Type.CLASS, Importance.HIGH, "docs").parse(props); }
private void testBadInputs(Type type, Object... values) { for (Object value : values) { Map<String, Object> m = new HashMap<String, Object>(); m.put("name", value); ConfigDef def = new ConfigDef().define("name", type, Importance.HIGH, "docs"); try { def.parse(m); fail("Expected a config exception on bad input for value " + value); } catch (ConfigException e) { // this is good } } }
@Test(expected = ConfigException.class) public void testInvalidDefault() { new ConfigDef().define("a", Type.INT, "hello", Importance.HIGH, "docs"); }
@Test public void testNames() { final ConfigDef configDef = new ConfigDef() .define("a", Type.STRING, Importance.LOW, "docs") .define("b", Type.STRING, Importance.LOW, "docs"); Set<String> names = configDef.names(); assertEquals(new HashSet<>(Arrays.asList("a", "b")), names); // should be unmodifiable try { names.add("new"); fail(); } catch (UnsupportedOperationException e) { // expected } }
@Test public void testParsingEmptyDefaultValueForStringFieldShouldSucceed() { new ConfigDef().define("a", Type.STRING, "", ConfigDef.Importance.HIGH, "docs") .parse(new HashMap<String, Object>()); }
@Test public void testNullDefault() { ConfigDef def = new ConfigDef().define("a", Type.INT, null, null, null, "docs"); Map<String, Object> vals = def.parse(new Properties()); assertEquals(null, vals.get("a")); }
@Test(expected = ConfigException.class) public void testMissingRequired() { new ConfigDef().define("a", Type.INT, Importance.HIGH, "docs").parse(new HashMap<String, Object>()); }
@Test public void testNullDefaultWithValidator() { final String key = "enum_test"; ConfigDef def = new ConfigDef(); def.define(key, Type.STRING, ConfigDef.NO_DEFAULT_VALUE, ValidString.in("ONE", "TWO", "THREE"), Importance.HIGH, "docs"); Properties props = new Properties(); props.put(key, "ONE"); Map<String, Object> vals = def.parse(props); assertEquals("ONE", vals.get(key)); }
@Test(expected = ConfigException.class) public void testInvalidDefaultRange() { new ConfigDef().define("name", Type.INT, -1, Range.between(0, 10), Importance.HIGH, "docs"); }
@Test(expected = ConfigException.class) public void testInvalidDefaultString() { new ConfigDef().define("name", Type.STRING, "bad", ValidString.in("valid", "values"), Importance.HIGH, "docs"); }
@Test public void testEmptyList() { AbstractConfig conf; ConfigDef configDef = new ConfigDef().define("a", Type.LIST, "", new ConfigDef.NonNullValidator(), Importance.HIGH, "doc"); conf = new AbstractConfig(configDef, Collections.emptyMap()); assertEquals(Collections.emptyList(), conf.getList("a")); conf = new AbstractConfig(configDef, Collections.singletonMap("a", "")); assertEquals(Collections.emptyList(), conf.getList("a")); conf = new AbstractConfig(configDef, Collections.singletonMap("a", "b,c,d")); assertEquals(Arrays.asList("b", "c", "d"), conf.getList("a")); }