Maintain SimpleConfigObject.resolveStatus when adding/removing keys

withOnlyKey, withoutKey were buggy and didn't correctly update the
resolved status.
This commit is contained in:
Havoc Pennington 2012-02-24 23:47:51 -05:00
parent a59e31f744
commit 7844f13dfa
2 changed files with 42 additions and 10 deletions

View File

@ -40,12 +40,7 @@ final class SimpleConfigObject extends AbstractConfigObject {
this.ignoresFallbacks = ignoresFallbacks;
// Kind of an expensive debug check. Comment out?
boolean allResolved = true;
for (AbstractConfigValue v : value.values()) {
if (v.resolveStatus() != ResolveStatus.RESOLVED)
allResolved = false;
}
if (this.resolved != allResolved)
if (status != ResolveStatus.fromValues(value.values()))
throw new ConfigException.BugOrBroken("Wrong resolved status on " + this);
}
@ -89,7 +84,7 @@ final class SimpleConfigObject extends AbstractConfigObject {
return null;
} else {
return new SimpleConfigObject(origin(), Collections.singletonMap(key, v),
resolveStatus(), ignoresFallbacks);
v.resolveStatus(), ignoresFallbacks);
}
}
@ -98,7 +93,7 @@ final class SimpleConfigObject extends AbstractConfigObject {
SimpleConfigObject o = withOnlyPathOrNull(path);
if (o == null) {
return new SimpleConfigObject(origin(),
Collections.<String, AbstractConfigValue> emptyMap(), resolveStatus(),
Collections.<String, AbstractConfigValue> emptyMap(), ResolveStatus.RESOLVED,
ignoresFallbacks);
} else {
return o;
@ -116,7 +111,8 @@ final class SimpleConfigObject extends AbstractConfigObject {
Map<String, AbstractConfigValue> updated = new HashMap<String, AbstractConfigValue>(
value);
updated.put(key, v);
return new SimpleConfigObject(origin(), updated, resolveStatus(), ignoresFallbacks);
return new SimpleConfigObject(origin(), updated, ResolveStatus.fromValues(updated
.values()), ignoresFallbacks);
} else if (next != null || v == null) {
// can't descend, nothing to remove
return this;
@ -127,7 +123,8 @@ final class SimpleConfigObject extends AbstractConfigObject {
if (!old.getKey().equals(key))
smaller.put(old.getKey(), old.getValue());
}
return new SimpleConfigObject(origin(), smaller, resolveStatus(), ignoresFallbacks);
return new SimpleConfigObject(origin(), smaller, ResolveStatus.fromValues(smaller
.values()), ignoresFallbacks);
}
}

View File

@ -723,6 +723,23 @@ class ConfigValueTest extends TestUtils {
assertEquals("keep only nonexistent underneath nested non-object", parseObject("{ }"), obj.toConfig.withOnlyPath("c.d.z.nonexistent").root)
}
@Test
def withOnlyInvolvingUnresolved() {
val obj = parseObject("{ a = {}, a=${x}, b=${y}, b=${z}, x={asf:1}, y=2, z=3 }")
assertEquals("keep only a.asf", parseObject("{ a={asf:1} }"), obj.toConfig.resolve.withOnlyPath("a.asf").root)
intercept[ConfigException.UnresolvedSubstitution] {
obj.withOnlyKey("a").toConfig.resolve
}
intercept[ConfigException.UnresolvedSubstitution] {
obj.withOnlyKey("b").toConfig.resolve
}
assertEquals(ResolveStatus.UNRESOLVED, obj.resolveStatus())
assertEquals(ResolveStatus.RESOLVED, obj.withOnlyKey("z").resolveStatus())
}
@Test
def without() {
val obj = parseObject("{ a=1, b=2, c.d.y=3, e.f.g=4, c.d.z=5 }")
@ -734,4 +751,22 @@ class ConfigValueTest extends TestUtils {
assertEquals("without nonexistent path", parseObject("{ a=1, b=2, c.d.y=3, e.f.g=4, c.d.z=5 }"), obj.toConfig.withoutPath("q.w.e.r.t.y").root)
assertEquals("without nonexistent path with existing prefix", parseObject("{ a=1, b=2, c.d.y=3, e.f.g=4, c.d.z=5 }"), obj.toConfig.withoutPath("a.foo").root)
}
@Test
def withoutInvolvingUnresolved() {
val obj = parseObject("{ a = {}, a=${x}, b=${y}, b=${z}, x={asf:1}, y=2, z=3 }")
assertEquals("without a.asf", parseObject("{ a={}, b=3, x={asf:1}, y=2, z=3 }"), obj.toConfig.resolve.withoutPath("a.asf").root)
intercept[ConfigException.UnresolvedSubstitution] {
obj.withoutKey("x").toConfig.resolve
}
intercept[ConfigException.UnresolvedSubstitution] {
obj.withoutKey("z").toConfig.resolve
}
assertEquals(ResolveStatus.UNRESOLVED, obj.resolveStatus())
assertEquals(ResolveStatus.UNRESOLVED, obj.withoutKey("a").resolveStatus())
assertEquals(ResolveStatus.RESOLVED, obj.withoutKey("a").withoutKey("b").resolveStatus())
}
}