Add more robust ConfigNode tests

Add more robust tests for ConfigNode classes. Add tests to
test arrays, duplicate removal, and addition of non-existent
paths.
This commit is contained in:
Preben Ingvaldsen 2015-03-10 13:44:37 -07:00
parent fa0aaeabbf
commit 3166db4d72
2 changed files with 83 additions and 24 deletions

View File

@ -45,11 +45,25 @@ class ConfigNodeTest extends TestUtils {
assertEquals(finalText, newNode.render())
}
private def replaceInComplexValueTest(nodes: List[ConfigNode], origText: String, newText: String, replaceVal: ConfigNodeValue, replacePath: String) {
val complexNode = configNodeComplexValue(nodes)
assertEquals(complexNode.render(), origText)
val newNode = complexNode.setValueOnPath(Path.newPath(replacePath), replaceVal)
assertEquals(newNode.render(), newText)
private def replaceDuplicatesTest(value1: ConfigNodeValue, value2: ConfigNodeValue, value3: ConfigNodeValue) {
val key = nodeUnquotedKey("foo")
val keyValPair1 = nodeKeyValuePair(key, value1)
val keyValPair2 = nodeKeyValuePair(key, value2)
val keyValPair3 = nodeKeyValuePair(key, value3)
val complexNode = configNodeComplexValue(List(keyValPair1, keyValPair2, keyValPair3))
val origText = keyValPair1.render() + keyValPair2.render() + keyValPair3.render()
val finalText = key.render() + " : 15"
assertEquals(origText, complexNode.render())
assertEquals(finalText, complexNode.setValueOnPath(Path.newPath("foo"), nodeInt(15)).render())
}
private def nonExistentPathTest(value: ConfigNodeValue) {
val node = configNodeComplexValue(List(nodeKeyValuePair(nodeUnquotedKey("bar"), nodeInt(15))))
assertEquals("bar : 15", node.render())
val newNode = node.setValueOnPath(Path.newPath("foo"), value)
val finalText = "bar : 15\nfoo : " + value.render() + "\n"
assertEquals(finalText, newNode.render())
}
@Test
@ -107,34 +121,61 @@ class ConfigNodeTest extends TestUtils {
}
@Test
def replaceNodesTopLevel() {
def replaceNodes() {
//Ensure simple values can be replaced by other simple values
topLevelValueReplaceTest(configNodeSimpleValue(tokenInt(10)), configNodeSimpleValue(tokenInt(15)))
topLevelValueReplaceTest(configNodeSimpleValue(tokenLong(10000)), configNodeSimpleValue(tokenInt(20)))
topLevelValueReplaceTest(configNodeSimpleValue(tokenDouble(3.14159)), configNodeSimpleValue(tokenLong(10000)))
topLevelValueReplaceTest(configNodeSimpleValue(tokenFalse), configNodeSimpleValue(tokenTrue))
topLevelValueReplaceTest(configNodeSimpleValue(tokenTrue), configNodeSimpleValue(tokenNull))
topLevelValueReplaceTest(configNodeSimpleValue(tokenNull), configNodeSimpleValue(tokenString("Hello my name is string")))
topLevelValueReplaceTest(configNodeSimpleValue(tokenString("Hello my name is string")), configNodeSimpleValue(tokenUnquoted("mynameisunquotedstring")))
topLevelValueReplaceTest(configNodeSimpleValue(tokenUnquoted("mynameisunquotedstring")), configNodeSimpleValue(tokenKeySubstitution("c.d")))
topLevelValueReplaceTest(configNodeSimpleValue(tokenInt(10)), configNodeSimpleValue(tokenOptionalSubstitution(tokenUnquoted("x.y"))))
topLevelValueReplaceTest(configNodeSimpleValue(tokenInt(10)), configNodeSimpleValue(tokenSubstitution(tokenUnquoted("a.b"))))
topLevelValueReplaceTest(configNodeSimpleValue(tokenSubstitution(tokenUnquoted("a.b"))), configNodeSimpleValue(tokenInt(10)))
topLevelValueReplaceTest(nodeInt(10), nodeInt(15))
topLevelValueReplaceTest(nodeLong(10000), nodeInt(20))
topLevelValueReplaceTest(nodeDouble(3.14159), nodeLong(10000))
topLevelValueReplaceTest(nodeFalse, nodeTrue)
topLevelValueReplaceTest(nodeTrue, nodeNull)
topLevelValueReplaceTest(nodeNull, nodeString("Hello my name is string"))
topLevelValueReplaceTest(nodeString("Hello my name is string"), nodeUnquotedText("mynameisunquotedstring"))
topLevelValueReplaceTest(nodeUnquotedText("mynameisunquotedstring"), nodeKeySubstitution("c.d"))
topLevelValueReplaceTest(nodeInt(10), nodeOptionalSubstitution(tokenUnquoted("x.y")))
topLevelValueReplaceTest(nodeInt(10), nodeSubstitution(tokenUnquoted("a.b")))
topLevelValueReplaceTest(nodeSubstitution(tokenUnquoted("a.b")), nodeInt(10))
// Ensure arrays can be replaced
val array = configNodeComplexValue(List(nodeOpenBracket, nodeInt(10), nodeSpace, nodeComma, nodeSpace, nodeInt(15), nodeCloseBracket))
topLevelValueReplaceTest(nodeInt(10), array)
topLevelValueReplaceTest(array, nodeInt(10))
topLevelValueReplaceTest(array, configNodeComplexValue(List(nodeOpenBrace, nodeCloseBrace)))
//Ensure maps can be replaced
val nestedMap = configNodeComplexValue(List(nodeOpenBrace, nodeUnquotedKey("abc"),
nodeColon, configNodeSimpleValue(tokenString("a string")),
nodeCloseBrace))
topLevelValueReplaceTest(nestedMap, configNodeSimpleValue(tokenInt(10)))
topLevelValueReplaceTest(configNodeSimpleValue(tokenInt(10)), nestedMap)
topLevelValueReplaceTest(nestedMap, nodeInt(10))
topLevelValueReplaceTest(nodeInt(10), nestedMap)
topLevelValueReplaceTest(array, nestedMap)
topLevelValueReplaceTest(nestedMap, array)
topLevelValueReplaceTest(nestedMap, configNodeComplexValue(List(nodeOpenBrace, nodeCloseBrace)))
//Ensure a key with format "a.b" will be properly replaced
topLevelValueReplaceTest(configNodeSimpleValue(tokenInt(10)), nestedMap, tokenUnquoted("foo.bar"))
topLevelValueReplaceTest(nodeInt(10), nestedMap, tokenUnquoted("foo.bar"))
}
@Test
def replaceInNestedMapComplexValue() {
def removeDuplicates() {
val emptyMapNode = configNodeComplexValue(List(nodeOpenBrace, nodeCloseBrace))
val emptyArrayNode = configNodeComplexValue(List(nodeOpenBracket, nodeCloseBracket))
//Ensure duplicates of a key are removed from a map
replaceDuplicatesTest(nodeInt(10), nodeTrue, nodeNull)
replaceDuplicatesTest(emptyMapNode, emptyMapNode, emptyMapNode)
replaceDuplicatesTest(emptyArrayNode, emptyArrayNode, emptyArrayNode)
replaceDuplicatesTest(nodeInt(10), emptyMapNode, emptyArrayNode)
}
@Test
def addNonExistentPaths() {
nonExistentPathTest(nodeInt(10))
nonExistentPathTest(configNodeComplexValue(List(nodeOpenBracket, nodeInt(15), nodeCloseBracket)))
nonExistentPathTest(configNodeComplexValue(List(nodeOpenBrace, nodeKeyValuePair(nodeUnquotedKey("foo"), nodeDouble(3.14), nodeSpace))))
}
@Test
def replaceNestedNodes() {
// Test that all features of node replacement in a map work in a complex map containing nested maps
val origText = "foo : bar\nbaz : {\n\t\"abc.def\" : 123\n\t//This is a comment about the below setting\n\n\tabc : {\n\t\t" +
"def : \"this is a string\"\n\t\tghi : ${\"a.b\"}\n\t}\n}\nbaz.abc.ghi : 52\nbaz.abc.ghi : 53\n}"
val lowestLevelMap = configNodeComplexValue(List(nodeOpenBrace, nodeLine(6),
@ -161,10 +202,10 @@ class ConfigNodeTest extends TestUtils {
var newNode = origNode.setValueOnPath(Path.newPath("baz.\"abc.def\""), configNodeSimpleValue(tokenTrue))
newNode = newNode.setValueOnPath(Path.newPath("baz.abc.def"), configNodeSimpleValue(tokenFalse))
// Repeats are removed
// Repeats are removed from nested maps
newNode = newNode.setValueOnPath(Path.newPath("baz.abc.ghi"), configNodeSimpleValue(tokenUnquoted("randomunquotedString")))
// Missing paths are added to the top level
// Missing paths are added to the top level if they don't appear anywhere, including in nested maps
newNode = newNode.setValueOnPath(Path.newPath("baz.abc.this.does.not.exist"), configNodeSimpleValue(tokenUnquoted("doesnotexist")))
// The above operations cause the resultant map to be rendered properly

View File

@ -683,20 +683,38 @@ abstract trait TestUtils {
def nodeSpace = new ConfigNodeBasic(tokenUnquoted(" "))
def nodeOpenBrace = new ConfigNodeBasic(Tokens.OPEN_CURLY)
def nodeCloseBrace = new ConfigNodeBasic(Tokens.CLOSE_CURLY)
def nodeOpenBracket = new ConfigNodeBasic(Tokens.OPEN_SQUARE)
def nodeCloseBracket = new ConfigNodeBasic(Tokens.CLOSE_SQUARE)
def nodeComma = new ConfigNodeBasic(Tokens.COMMA)
def nodeLine(line: Integer) = new ConfigNodeBasic(tokenLine(line))
def nodeWhitespace(whitespace: String) = new ConfigNodeBasic(tokenWhitespace(whitespace))
def nodeQuotedKey(key: String) = configNodeKey(tokenString(key))
def nodeUnquotedKey(key: String) = configNodeKey(tokenUnquoted(key))
def nodeKeyValuePair(key: ConfigNodeKey, value: ConfigNodeValue) = {
val nodes = List(key, nodeSpace, nodeColon, nodeSpace, value)
new ConfigNodeKeyValue(nodes.asJavaCollection)
}
def nodeKeyValuePair(key: ConfigNodeKey, value: ConfigNodeValue, trailingWhitespace: ConfigNodeBasic) = {
val nodes = List(key, nodeSpace, nodeColon, nodeSpace, value, trailingWhitespace)
new ConfigNodeKeyValue(nodes.asJavaCollection)
}
def nodeKeyValuePair(leadingWhitespace: ConfigNodeBasic, key: ConfigNodeKey, value: ConfigNodeValue, trailingWhitespace: ConfigNodeBasic) = {
val nodes = List(leadingWhitespace, key, nodeSpace, nodeColon, nodeSpace, value, trailingWhitespace)
new ConfigNodeKeyValue(nodes.asJavaCollection);
new ConfigNodeKeyValue(nodes.asJavaCollection)
}
def nodeInt(value: Integer) = new ConfigNodeSimpleValue(tokenInt(value))
def nodeString(value: String) = new ConfigNodeSimpleValue(tokenString(value))
def nodeLong(value: Long) = new ConfigNodeSimpleValue(tokenLong(value))
def nodeDouble(value: Double) = new ConfigNodeSimpleValue(tokenDouble(value))
def nodeTrue = new ConfigNodeSimpleValue(tokenTrue)
def nodeFalse = new ConfigNodeSimpleValue(tokenFalse)
def nodeCommentHash(text: String) = new ConfigNodeBasic(tokenCommentHash(text))
def nodeCommentDoubleSlash(text: String) = new ConfigNodeBasic(tokenCommentDoubleSlash(text))
def nodeUnquotedText(text: String) = new ConfigNodeSimpleValue(tokenUnquoted(text))
def nodeNull = new ConfigNodeSimpleValue(tokenNull)
def nodeKeySubstitution(s: String) = new ConfigNodeSimpleValue(tokenKeySubstitution(s))
def nodeOptionalSubstitution(expression: Token*) = new ConfigNodeSimpleValue(tokenOptionalSubstitution(expression: _*))
def nodeSubstitution(expression: Token*) = new ConfigNodeSimpleValue(tokenSubstitution(expression: _*))
// this is importantly NOT using Path.newPath, which relies on
// the parser; in the test suite we are often testing the parser,