blob: 1041c6907b0f200f836084f6d119c5bd3e668f61 [file] [log] [blame]
/*
* 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 org.apache.commons.configuration2.tree;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.junit.Test;
/**
* Test class for {@code ImmutableNode}
*
*/
public class TestImmutableNode
{
/** Constant for a test node name. */
private static final String NAME = "testNode";
/** Constant for an attribute key. */
private static final String ATTR = "attr";
/** Constant for an attribute value. */
private static final String ATTR_VALUE = "attrValue";
/** Constant for a test node value. */
private static final Integer VALUE = 42;
/** A counter for generating unique child node names. */
private int childCounter;
/**
* Sets up a builder with default settings.
*
* @return the default builder
*/
private static ImmutableNode.Builder setUpBuilder()
{
final ImmutableNode.Builder builder = new ImmutableNode.Builder();
builder.name(NAME).value(VALUE);
return builder;
}
/**
* Tests whether a node with basic properties can be created.
*/
@Test
public void testSimpleProperties()
{
final ImmutableNode node = setUpBuilder().create();
assertEquals("Wrong node name", NAME, node.getNodeName());
assertTrue("Got children", node.getChildren().isEmpty());
assertTrue("Got attributes", node.getAttributes().isEmpty());
}
/**
* Tests that a node's children cannot be manipulated.
*/
@Test(expected = UnsupportedOperationException.class)
public void testChildrenImmutable()
{
final ImmutableNode node = setUpBuilder().create();
node.getChildren().add(null);
}
/**
* Tests that a node's attributes cannot be directly manipulated.
*/
@Test(expected = UnsupportedOperationException.class)
public void testAttributesImmutable()
{
final ImmutableNode node = setUpBuilder().create();
node.getAttributes().put("test", VALUE);
}
/**
* Checks whether a node has the expected children.
*
* @param node the node to be checked
* @param expChildren the collection with the expected children
*/
private static void checkChildNodes(final ImmutableNode node,
final Collection<ImmutableNode> expChildren)
{
assertEquals("Wrong number of child nodes", expChildren.size(), node
.getChildren().size());
final Iterator<ImmutableNode> itExp = expChildren.iterator();
int idx = 0;
for(final ImmutableNode c : node)
{
assertEquals("Wrong child at " + idx, itExp.next(), c);
idx++;
}
}
/**
* Checks whether a node has exactly the specified children.
*
* @param parent the parent node to be checked
* @param children the expected children
*/
private static void checkChildNodes(final ImmutableNode parent,
final ImmutableNode... children)
{
checkChildNodes(parent, Arrays.asList(children));
}
/**
* Tests whether child nodes can be added.
*/
@Test
public void testNodeWithChildren()
{
final int childCount = 8;
final List<ImmutableNode> childNodes = new ArrayList<>(childCount);
final ImmutableNode.Builder builder = new ImmutableNode.Builder(childCount);
for (int i = 0; i < childCount; i++)
{
final ImmutableNode.Builder childBuilder = new ImmutableNode.Builder();
final ImmutableNode child = childBuilder.name(NAME + i).value(i).create();
builder.addChild(child);
childNodes.add(child);
}
final ImmutableNode node = builder.name(NAME).create();
checkChildNodes(node, childNodes);
}
/**
* Tests whether multiple child nodes can be added to a builder.
*/
@Test
public void testNodeWithAddMultipleChildren()
{
final int childCount = 4;
final List<ImmutableNode> childNodes =
new ArrayList<>(childCount);
for (int i = 0; i < childCount; i++)
{
final ImmutableNode.Builder childBuilder = new ImmutableNode.Builder();
final ImmutableNode child = childBuilder.name(NAME + i).value(i).create();
childNodes.add(child);
}
final ImmutableNode.Builder builder = setUpBuilder();
final ImmutableNode node = builder.addChildren(childNodes).create();
checkChildNodes(node, childNodes);
}
/**
* Tests whether the builder ignores a null child node.
*/
@Test
public void testNodeWithNullChild()
{
final ImmutableNode.Builder builder = setUpBuilder();
builder.addChild(null);
final ImmutableNode node = builder.create();
checkChildNodes(node);
}
/**
* Tests that the list of children cannot be changed by a later manipulation
* of the builder.
*/
@Test
public void testNodeWithChildrenManipulateLater()
{
final ImmutableNode.Builder builder = setUpBuilder();
final ImmutableNode child =
new ImmutableNode.Builder().name("Child").create();
final ImmutableNode node = builder.addChild(child).create();
builder.addChild(new ImmutableNode.Builder().name("AnotherChild")
.create());
checkChildNodes(node, Collections.singleton(child));
}
/**
* Tests whether addChildren() can deal with null input.
*/
@Test
public void testAddChildrenNull()
{
final ImmutableNode.Builder builder = setUpBuilder();
builder.addChildren(null);
final ImmutableNode node = builder.create();
assertTrue("Got children", node.getChildren().isEmpty());
}
/**
* Tests whether null entries in a collection with new child nodes are ignored.
*/
@Test
public void testAddChildrenNullElement()
{
final ImmutableNode.Builder builder = setUpBuilder();
final List<ImmutableNode> children = Arrays.asList(createChild(), null, createChild());
builder.addChildren(children);
final ImmutableNode node = builder.create();
checkChildNodes(node, children.get(0), children.get(2));
}
/**
* Tests whether a node with attributes can be created.
*/
@Test
public void testNodeWithAttributes()
{
final ImmutableNode.Builder builder = setUpBuilder();
final int attrCount = 4;
final Map<String, Object> attrs = new HashMap<>();
for (int i = 0; i < attrCount; i++)
{
final String attrName = NAME + i;
attrs.put(attrName, i);
builder.addAttribute(attrName, i);
}
final ImmutableNode node = builder.create();
checkAttributes(node, attrs);
}
/**
* Checks whether a node has the expected attributes.
*
* @param node the node to be checked
* @param expAttrs the expected attributes
*/
private static void checkAttributes(final ImmutableNode node,
final Map<String, ?> expAttrs)
{
assertEquals("Wrong number of attributes", expAttrs.size(), node
.getAttributes().size());
for (final Map.Entry<String, ?> e : expAttrs.entrySet())
{
assertEquals("Wrong value for " + e.getKey(), e.getValue(), node
.getAttributes().get(e.getKey()));
}
}
/**
* Tests that the map of attributes cannot be changed by a later
* manipulation of the builder.
*/
@Test
public void testNodeWithAttributesManipulateLater()
{
final ImmutableNode.Builder builder = setUpBuilder();
builder.addAttribute(ATTR, ATTR_VALUE);
final ImmutableNode node = builder.create();
builder.addAttribute("attr2", "a2");
assertEquals("Wrong number of attributes", 1, node.getAttributes()
.size());
assertEquals("Wrong attribute", ATTR_VALUE, node.getAttributes().get(ATTR));
}
/**
* Tests whether multiple attributes can be added in a single operation.
*/
@Test
public void testNodeWithMultipleAttributes()
{
final ImmutableNode.Builder builder = setUpBuilder();
final int attrCount = 4;
final Map<String, Object> attrs = new HashMap<>();
for (int i = 0; i < attrCount; i++)
{
final String attrName = NAME + i;
attrs.put(attrName, i);
}
final ImmutableNode node = builder.addAttributes(attrs).create();
checkAttributes(node, attrs);
}
/**
* Tests whether addAttributes() handles null input.
*/
@Test
public void testAddAttributesNull()
{
final ImmutableNode.Builder builder = setUpBuilder();
builder.addAttributes(null);
final ImmutableNode node = builder.create();
assertTrue("Got attributes", node.getAttributes().isEmpty());
}
/**
* Creates a default node instance which can be used by tests for updating
* properties.
*
* @param value the value of the node
* @return the default node instance
*/
private ImmutableNode createDefaultNode(final Object value)
{
return createDefaultNode(NAME, value);
}
/**
* Creates a default node instance with a variable name and value that can
* be used by tests for updating properties.
*
* @param name the name of the node
* @param value the value of the node
* @return the default node instance
*/
private ImmutableNode createDefaultNode(final String name, final Object value)
{
final ImmutableNode.Builder builder = new ImmutableNode.Builder(1);
return builder.name(name).addChild(createChild())
.addAttribute("testAttr", "anotherTest").value(value).create();
}
/**
* Creates a default child node with a unique name.
*
* @return the new child node
*/
private ImmutableNode createChild()
{
final int idx = childCounter++;
return new ImmutableNode.Builder().name("Child" + idx)
.value("childValue" + idx).create();
}
/**
* Checks whether an updated node has the expected basic properties.
*
* @param org the original node
* @param updated the updated node
*/
private static void checkUpdatedNode(final ImmutableNode org,
final ImmutableNode updated)
{
assertNotSame("Same instance", org, updated);
assertEquals("Wrong node name", NAME, updated.getNodeName());
assertEquals("Wrong value", VALUE, updated.getValue());
}
/**
* Tests whether a new node with a changed value can be created.
*/
@Test
public void testSetValue()
{
final ImmutableNode node = createDefaultNode("test");
final ImmutableNode node2 = node.setValue(VALUE);
checkUpdatedNode(node, node2);
assertSame("Different children", node.getChildren(),
node2.getChildren());
assertSame("Different attributes", node.getAttributes(),
node2.getAttributes());
}
/**
* Tests whether the name of a node can be changed for a new instance.
*/
@Test
public void testSetName()
{
final ImmutableNode node = createDefaultNode("anotherName", VALUE);
final ImmutableNode node2 = node.setName(NAME);
checkUpdatedNode(node, node2);
assertSame("Different children", node.getChildren(),
node2.getChildren());
assertSame("Different attributes", node.getAttributes(),
node2.getAttributes());
}
/**
* Tests whether a child node can be added.
*/
@Test
public void testAddChild()
{
final ImmutableNode node = createDefaultNode(VALUE);
final ImmutableNode child2 =
new ImmutableNode.Builder().name("child2").create();
final ImmutableNode node2 = node.addChild(child2);
checkUpdatedNode(node, node2);
checkChildNodes(node2, node.getChildren().get(0), child2);
}
/**
* Tests getting named children.
*/
@Test
public void testGetChildrenByName()
{
final ImmutableNode node = createDefaultNode(VALUE);
final ImmutableNode child2 =
new ImmutableNode.Builder().name("child2").create();
final ImmutableNode node2 = node.addChild(child2);
checkUpdatedNode(node, node2);
assertEquals("child2", node2.getChildren("child2").get(0).getNodeName());
assertEquals(child2, node2.getChildren("child2").get(0));
}
/**
* Tests getting named children.
*/
@Test
public void testGetChildrenByNullName()
{
final ImmutableNode node = createDefaultNode(VALUE);
final ImmutableNode child2 =
new ImmutableNode.Builder().name("child2").create();
final ImmutableNode node2 = node.addChild(child2);
checkUpdatedNode(node, node2);
assertTrue(node2.getChildren(null).isEmpty());
}
/**
* Tests getting named children.
*/
@Test
public void testGetChildrenByMissingName()
{
final ImmutableNode node = createDefaultNode(VALUE);
final ImmutableNode child2 =
new ImmutableNode.Builder().name("child2").create();
final ImmutableNode node2 = node.addChild(child2);
checkUpdatedNode(node, node2);
assertTrue(node2.getChildren("NotFound").isEmpty());
}
/**
* Tests whether a new null child node is rejected.
*/
@Test(expected = IllegalArgumentException.class)
public void testAddChildNull()
{
createDefaultNode(VALUE).addChild(null);
}
/**
* Tests whether a child node can be removed.
*/
@Test
public void testRemoveChildExisting()
{
final ImmutableNode node = createDefaultNode(VALUE);
final ImmutableNode child = node.getChildren().get(0);
final ImmutableNode node2 = node.removeChild(child);
checkUpdatedNode(node, node2);
checkChildNodes(node2);
}
/**
* Tests whether the correct child node is removed if there are multiple.
*/
@Test
public void testRemoveChildMultiple()
{
final ImmutableNode childRemove = createChild();
final ImmutableNode node =
createDefaultNode(VALUE).addChild(createChild())
.addChild(childRemove).addChild(createChild());
final ImmutableNode node2 = node.removeChild(childRemove);
checkChildNodes(node2, node.getChildren().get(0), node.getChildren()
.get(1), node.getChildren().get(3));
}
/**
* Tests whether the behavior of removeChildNode() if the node in question
* is not found.
*/
@Test
public void testRemoveChildNodeNotExisting()
{
final ImmutableNode node = createDefaultNode(VALUE);
assertSame("Got different instance", node, node.removeChild(null));
}
/**
* Tests whether a child node can be replaced by another one.
*/
@Test
public void testReplaceChildExisting()
{
final ImmutableNode childRemove = createChild();
final ImmutableNode childReplace = createChild();
final ImmutableNode node = createDefaultNode(VALUE).addChild(childRemove);
final ImmutableNode node2 = node.replaceChild(childRemove, childReplace);
checkUpdatedNode(node, node2);
checkChildNodes(node2, node.getChildren().get(0), childReplace);
}
/**
* Tests replaceChild() if the child node cannot be found.
*/
@Test
public void testReplaceChildNotExisting()
{
final ImmutableNode node = createDefaultNode(VALUE);
assertSame("Got different instance", node,
node.replaceChild(createChild(), createChild()));
}
/**
* Tries to replace a child node by null.
*/
@Test(expected = IllegalArgumentException.class)
public void testReplaceChildNull()
{
createDefaultNode(VALUE).replaceChild(createChild(), null);
}
/**
* Tests whether attribute values can be set.
*/
@Test
public void testSetAttribute()
{
final ImmutableNode node = createDefaultNode(VALUE);
final ImmutableNode node2 = node.setAttribute("attr", ATTR_VALUE);
checkUpdatedNode(node, node2);
assertSame("Wrong children", node.getChildren(), node2.getChildren());
final Map<String, Object> newAttrs =
new HashMap<>(node.getAttributes());
newAttrs.put(ATTR, ATTR_VALUE);
checkAttributes(node2, newAttrs);
}
/**
* Tests whether an attribute can be overridden.
*/
@Test
public void testSetAttributeOverride()
{
final ImmutableNode.Builder builder = setUpBuilder();
final String attr2 = ATTR + "_other";
final Map<String, Object> attrs = new HashMap<>();
attrs.put(ATTR, ATTR_VALUE);
attrs.put(attr2, "someValue");
final ImmutableNode node = builder.addAttributes(attrs).create();
final ImmutableNode node2 = node.setAttribute(attr2, VALUE);
attrs.put(attr2, VALUE);
checkAttributes(node2, attrs);
}
/**
* Tests whether multiple attributes can be set.
*/
@Test
public void testSetAttributes()
{
final ImmutableNode node = createDefaultNode(VALUE);
final Map<String, Object> attributes = new HashMap<>();
attributes.put("newAttribute1", "value1");
attributes.put("newAttribute2", "value2");
final ImmutableNode node2 = node.setAttributes(attributes);
assertEquals("Wrong number of attributes", attributes.size()
+ node.getAttributes().size(), node2.getAttributes().size());
checkAttributesContained(node2, attributes);
checkAttributesContained(node2, node.getAttributes());
}
/**
* Helper method for testing whether a node contains all the attributes in
* the specified map.
*
* @param node the node to be checked
* @param attributes the map with expected attributes
*/
private static void checkAttributesContained(final ImmutableNode node,
final Map<String, Object> attributes)
{
for (final Map.Entry<String, Object> e : attributes.entrySet())
{
assertEquals("Wrong attribute value", e.getValue(), node
.getAttributes().get(e.getKey()));
}
}
/**
* Helper method for testing a setAttributes() operation which has no
* effect.
*
* @param attributes the map with attributes
*/
private void checkSetAttributesNoOp(final Map<String, Object> attributes)
{
final ImmutableNode node = createDefaultNode(VALUE);
assertSame("Node was changed", node, node.setAttributes(attributes));
}
/**
* Tests setAttributes() if an empty map is passed in.
*/
@Test
public void testSetAttributesEmpty()
{
checkSetAttributesNoOp(new HashMap<>());
}
/**
* Tests setAttributes() for null input.
*/
@Test
public void testSetAttributesNull()
{
checkSetAttributesNoOp(null);
}
/**
* Tests whether an existing attribute can be removed.
*/
@Test
public void testRemoveAttributeExisting()
{
final ImmutableNode node = createDefaultNode(VALUE);
final String attrName = node.getAttributes().keySet().iterator().next();
final ImmutableNode node2 = node.removeAttribute(attrName);
checkUpdatedNode(node, node2);
assertSame("Wrong children", node.getChildren(), node2.getChildren());
assertTrue("Attribute not deleted", node2.getAttributes().isEmpty());
}
/**
* Tests removeAttribute() if the attribute does not exist.
*/
@Test
public void testRemoveAttributeNotExisting()
{
final ImmutableNode node = createDefaultNode(VALUE);
assertSame("Got different instance", node, node.removeAttribute(ATTR));
}
/**
* Tests whether all children can be replaced at once.
*/
@Test
public void testReplaceChildren()
{
final int childCount = 8;
final Collection<ImmutableNode> newChildren =
new ArrayList<>(childCount);
for (int i = 0; i < childCount; i++)
{
newChildren.add(createChild());
}
final ImmutableNode node = createDefaultNode(VALUE);
final ImmutableNode node2 = node.replaceChildren(newChildren);
checkUpdatedNode(node, node2);
checkChildNodes(node2, newChildren);
}
/**
* Tests whether a node's children can be replaced by a null collection.
*/
@Test
public void testReplaceChildrenNullCollection()
{
final ImmutableNode node = createDefaultNode(VALUE);
final ImmutableNode node2 = node.replaceChildren(null);
checkUpdatedNode(node, node2);
checkChildNodes(node2);
}
}