mirror of
https://github.com/lightbend/config.git
synced 2025-02-22 09:10:32 +08:00
parent
a5df1fb8a2
commit
c5a9ad6974
@ -728,7 +728,8 @@ final class SimpleConfig implements Config, MergeableValue, Serializable {
|
||||
return false;
|
||||
}
|
||||
} else if (reference instanceof SimpleConfigList) {
|
||||
if (value instanceof SimpleConfigList) {
|
||||
// objects may be convertible to lists if they have numeric keys
|
||||
if (value instanceof SimpleConfigList || value instanceof SimpleConfigObject) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@ -772,6 +773,25 @@ final class SimpleConfig implements Config, MergeableValue, Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkListCompatibility(Path path, SimpleConfigList listRef,
|
||||
SimpleConfigList listValue, List<ConfigException.ValidationProblem> accumulator) {
|
||||
if (listRef.isEmpty() || listValue.isEmpty()) {
|
||||
// can't verify type, leave alone
|
||||
} else {
|
||||
AbstractConfigValue refElement = listRef.get(0);
|
||||
for (ConfigValue elem : listValue) {
|
||||
AbstractConfigValue e = (AbstractConfigValue) elem;
|
||||
if (!haveCompatibleTypes(refElement, e)) {
|
||||
addProblem(accumulator, path, e.origin(), "List at '" + path.render()
|
||||
+ "' contains wrong value type, expecting list of "
|
||||
+ getDesc(refElement) + " but got element of type " + getDesc(e));
|
||||
// don't add a problem for every last array element
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkValid(Path path, ConfigValue reference, AbstractConfigValue value,
|
||||
List<ConfigException.ValidationProblem> accumulator) {
|
||||
// Unmergeable is supposed to be impossible to encounter in here
|
||||
@ -784,22 +804,16 @@ final class SimpleConfig implements Config, MergeableValue, Serializable {
|
||||
} else if (reference instanceof SimpleConfigList && value instanceof SimpleConfigList) {
|
||||
SimpleConfigList listRef = (SimpleConfigList) reference;
|
||||
SimpleConfigList listValue = (SimpleConfigList) value;
|
||||
if (listRef.isEmpty() || listValue.isEmpty()) {
|
||||
// can't verify type, leave alone
|
||||
} else {
|
||||
AbstractConfigValue refElement = listRef.get(0);
|
||||
for (ConfigValue elem : listValue) {
|
||||
AbstractConfigValue e = (AbstractConfigValue) elem;
|
||||
if (!haveCompatibleTypes(refElement, e)) {
|
||||
addProblem(accumulator, path, e.origin(), "List at '" + path.render()
|
||||
+ "' contains wrong value type, expecting list of "
|
||||
+ getDesc(refElement) + " but got element of type "
|
||||
+ getDesc(e));
|
||||
// don't add a problem for every last array element
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
checkListCompatibility(path, listRef, listValue, accumulator);
|
||||
} else if (reference instanceof SimpleConfigList && value instanceof SimpleConfigObject) {
|
||||
// attempt conversion of indexed object to list
|
||||
SimpleConfigList listRef = (SimpleConfigList) reference;
|
||||
AbstractConfigValue listValue = DefaultTransformer.transform(value,
|
||||
ConfigValueType.LIST);
|
||||
if (listValue instanceof SimpleConfigList)
|
||||
checkListCompatibility(path, listRef, (SimpleConfigList) listValue, accumulator);
|
||||
else
|
||||
addWrongType(accumulator, reference, value, path);
|
||||
}
|
||||
} else {
|
||||
addWrongType(accumulator, reference, value, path);
|
||||
|
@ -15,8 +15,8 @@ class ValidationTest extends TestUtils {
|
||||
|
||||
sealed abstract class Problem(path: String, line: Int) {
|
||||
def check(p: ConfigException.ValidationProblem) {
|
||||
assertEquals(path, p.path())
|
||||
assertEquals(line, p.origin().lineNumber())
|
||||
assertEquals("matching path", path, p.path())
|
||||
assertEquals("matching line", line, p.origin().lineNumber())
|
||||
}
|
||||
|
||||
protected def assertMessage(p: ConfigException.ValidationProblem, re: String) {
|
||||
@ -58,7 +58,8 @@ class ValidationTest extends TestUtils {
|
||||
for ((problem, expected) <- problems zip expecteds) {
|
||||
expected.check(problem)
|
||||
}
|
||||
assertEquals(expecteds.size, problems.size)
|
||||
assertEquals("found expected validation problems, got '" + problems + "' and expected '" + expecteds + "'",
|
||||
expecteds.size, problems.size)
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -118,4 +119,59 @@ class ValidationTest extends TestUtils {
|
||||
assertTrue("expected different message, got: " + e.getMessage,
|
||||
e.getMessage.contains("resolve"))
|
||||
}
|
||||
|
||||
@Test
|
||||
def validationCatchesListOverriddenWithNumber() {
|
||||
val reference = parseConfig("""{ a : [{},{},{}] }""")
|
||||
val conf = parseConfig("""{ a : 42 }""")
|
||||
val e = intercept[ConfigException.ValidationFailed] {
|
||||
conf.checkValid(reference)
|
||||
}
|
||||
|
||||
val expecteds = Seq(WrongType("a", 1, "list", "number"))
|
||||
|
||||
checkException(e, expecteds)
|
||||
}
|
||||
|
||||
@Test
|
||||
def validationCatchesListOverriddenWithDifferentList() {
|
||||
val reference = parseConfig("""{ a : [true,false,false] }""")
|
||||
val conf = parseConfig("""{ a : [42,43] }""")
|
||||
val e = intercept[ConfigException.ValidationFailed] {
|
||||
conf.checkValid(reference)
|
||||
}
|
||||
|
||||
val expecteds = Seq(WrongElementType("a", 1, "boolean", "number"))
|
||||
|
||||
checkException(e, expecteds)
|
||||
}
|
||||
|
||||
@Test
|
||||
def validationAllowsListOverriddenWithSameTypeList() {
|
||||
val reference = parseConfig("""{ a : [1,2,3] }""")
|
||||
val conf = parseConfig("""{ a : [4,5] }""")
|
||||
conf.checkValid(reference)
|
||||
}
|
||||
|
||||
@Test
|
||||
def validationCatchesListOverriddenWithNoIndexesObject() {
|
||||
val reference = parseConfig("""{ a : [1,2,3] }""")
|
||||
val conf = parseConfig("""{ a : { notANumber: foo } }""")
|
||||
val e = intercept[ConfigException.ValidationFailed] {
|
||||
conf.checkValid(reference)
|
||||
}
|
||||
|
||||
val expecteds = Seq(WrongType("a", 1, "list", "object"))
|
||||
|
||||
checkException(e, expecteds)
|
||||
}
|
||||
|
||||
@Test
|
||||
def validationAllowsListOverriddenWithIndexedObject() {
|
||||
val reference = parseConfig("""{ a : [a,b,c] }""")
|
||||
val conf = parseConfig("""{ a : { "0" : x, "1" : y } }""")
|
||||
conf.checkValid(reference)
|
||||
assertEquals("got the sequence from overriding list with indexed object",
|
||||
Seq("x", "y"), conf.getStringList("a").asScala)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user