/*
* The MIT License
*
* Copyright 2011 Sony Ericsson Mobile Communications. All rights reserved.
* Copyright 2012 Sony Mobile Communications AB. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.sonyericsson.hudson.plugins.metadata.model.values;
import com.sonyericsson.hudson.plugins.metadata.model.Metadata;
import com.sonyericsson.hudson.plugins.metadata.model.MetadataParent;
import com.sonyericsson.hudson.plugins.metadata.model.definitions.AbstractMetadataDefinition;
import com.sonyericsson.hudson.plugins.metadata.model.definitions.MetadataDefinition;
import com.sonyericsson.hudson.plugins.metadata.model.definitions.StringMetadataDefinition;
import com.sonyericsson.hudson.plugins.metadata.model.definitions.TreeNodeMetadataDefinition;
import org.junit.Test;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
/**
* Tests for {@link ParentUtil}.
*
* @author Robert Sandell <robert.sandell@sonyericsson.com>
*/
public class ParentUtilTest {
/**
* Tests to add one child to a tree-node.
*
* @throws Exception if so.
*/
@Test
public void testAddChildValue() throws Exception {
TreeNodeMetadataValue parent = new TreeNodeMetadataValue("root");
assertNull(parent.addChild(new StringMetadataValue("child1", "value")));
assertNotNull(parent.getChild("child1"));
}
/**
* Tests to add one null child to a tree-node.
*
* @throws Exception if so.
*/
@Test(expected = IllegalArgumentException.class)
public void testAddChildValueNull() throws Exception {
TreeNodeMetadataValue parent = new TreeNodeMetadataValue("root");
parent.addChild(null);
}
/**
* Tests to add a non empty list of children to the constructor of a tree-node.
*
* @throws Exception if so.
*/
@Test
public void testAddChildrenNonEmpty() throws Exception {
List<MetadataValue> nonEmptyList = new LinkedList<MetadataValue>();
StringMetadataValue sampleValue = new StringMetadataValue(
"sampleName", "sampleValue", "sampleDescription", false);
nonEmptyList.add(sampleValue);
TreeNodeMetadataValue parent = new TreeNodeMetadataValue(
"parentName", "parentDescription", nonEmptyList, false);
assertNotNull(parent.getChild("sampleName"));
}
/**
* Tests to add an empty list of children to the constructor of a tree-node.
*
* @throws Exception if so.
*/
@Test
public void testAddChildrenEmpty() throws Exception {
List<MetadataValue> emptyList = new LinkedList<MetadataValue>();
TreeNodeMetadataValue parent = new TreeNodeMetadataValue("parentName", "parentDescription", emptyList, false);
assertNull(parent.getChild("someName"));
}
/**
* Tests to add one straight branch one/two/three=value to a tree-node.
*
* @throws Exception if so.
*/
@Test
public void testAddChildValueTree() throws Exception {
TreeNodeMetadataValue parent = new TreeNodeMetadataValue("root");
AbstractMetadataValue path = TreeStructureUtil.createPath("value", "description", "one", "two", "three");
assertNull(parent.addChild(path));
assertEquals("value", ((MetadataParent)((MetadataParent)parent.getChild("one"))
.getChild("two")).getChild("three").getValue());
}
/**
* Tests to add one tree structure into another with some leftovers expected because they already existed.
*
* @throws Exception if so.
*/
@Test
public void testAddChildValueTreeNotAllMerged() throws Exception {
/*
_start tree_
root
child1
child11=something
child2=something
child3
child31
child311=something
child312=something
_tree to add_
child1
child12=something
child2=something else
child3
child31
child312=something else
child313=something
_expected result_
root
child1
child11=something
child12=something
child2=something
child3
child31
child311=something
child312=something
child313=something
_expected leftovers_
child2=something else
child3
child31
child312=something else
*/
TreeNodeMetadataValue[] startTree = TreeStructureUtil.createTreePath("", "root", "child1");
TreeNodeMetadataValue startChild1 = startTree[1];
startChild1.addChild(new StringMetadataValue("child11", "something"));
TreeNodeMetadataValue startRoot = startTree[0];
startRoot.addChild(new StringMetadataValue("child2", "something"));
TreeStructureUtil.addValue(startRoot, "something", "", "child3", "child31", "child311");
TreeStructureUtil.addValue(startRoot, "something", "", "child3", "child31", "child312");
TreeNodeMetadataValue addRoot = TreeStructureUtil.createPath("something", "", "root", "child1", "child12");
TreeStructureUtil.addValue(addRoot, "something else", "", "child2");
TreeStructureUtil.addValue(addRoot, "something else", "", "child3", "child31", "child312");
TreeStructureUtil.addValue(addRoot, "something", "", "child3", "child31", "child313");
Collection<MetadataValue> returnedValues = startRoot.addChildren(addRoot.getChildren());
//Verify the tree
Metadata leaf = TreeStructureUtil.getPath(startRoot, "child1", "child11");
assertNotNull(leaf);
assertEquals("something", leaf.getValue());
leaf = TreeStructureUtil.getPath(startRoot, "child1", "child12");
assertNotNull(leaf);
assertEquals("something", leaf.getValue());
leaf = TreeStructureUtil.getPath(startRoot, "child2");
assertNotNull(leaf);
assertEquals("something", leaf.getValue());
leaf = TreeStructureUtil.getPath(startRoot, "child3", "child31", "child311");
assertNotNull(leaf);
assertEquals("something", leaf.getValue());
leaf = TreeStructureUtil.getPath(startRoot, "child3", "child31", "child312");
assertNotNull(leaf);
assertEquals("something", leaf.getValue());
leaf = TreeStructureUtil.getPath(startRoot, "child3", "child31", "child313");
assertNotNull(leaf);
assertEquals("something", leaf.getValue());
//Verify the leftovers
assertNotNull(returnedValues);
Metadata child2 = null;
Metadata child3 = null;
for (Metadata value : returnedValues) {
if (value.getName().equalsIgnoreCase("child2")) {
child2 = value;
} else if (value.getName().equalsIgnoreCase("child3")) {
child3 = value;
} else {
fail("More values returned than expected! " + value.getName() + ": " + value.getValue());
}
}
assertNotNull(child2);
assertEquals("something else", child2.getValue());
assertNotNull(child3);
Metadata child31 = ((MetadataParent)child3).getChild("child31");
assertNotNull(child31);
assertEquals("something else", ((MetadataParent)child31).getChild("child312").getValue());
}
/**
* Tests to add one tree structure into another with some leftovers expected because they already existed.
*
* @throws Exception if so.
*/
@Test
public void testAddChildDefinitionTreeNotAllMerged() throws Exception {
/*
_start tree_
root
child1
child11=something
child2=something
child3
child31
child311=something
child312=something
_tree to add_
child1
child12=something
child2=something else
child3
child31
child312=something else
child313=something
_expected result_
root
child1
child11=something
child12=something
child2=something
child3
child31
child311=something
child312=something
child313=something
_expected leftovers_
child2=something else
child3
child31
child312=something else
*/
TreeNodeMetadataDefinition[] startTree = createTreePath("", "root", "child1");
TreeNodeMetadataDefinition startChild1 = startTree[1];
startChild1.addChild(new StringMetadataDefinition("child11", "something"));
TreeNodeMetadataDefinition startRoot = startTree[0];
startRoot.addChild(new StringMetadataDefinition("child2", "something"));
addValue(startRoot, "something", "", "child3", "child31", "child311");
addValue(startRoot, "something", "", "child3", "child31", "child312");
TreeNodeMetadataDefinition addRoot = createPath("something", "", "root", "child1", "child12");
addValue(addRoot, "something else", "", "child2");
addValue(addRoot, "something else", "", "child3", "child31", "child312");
addValue(addRoot, "something", "", "child3", "child31", "child313");
Collection<MetadataDefinition> returnedValues = startRoot.addChildren(addRoot.getChildren());
//Verify the tree
Metadata leaf = TreeStructureUtil.getPath(startRoot, "child1", "child11");
assertNotNull(leaf);
assertEquals("something", leaf.getValue());
leaf = TreeStructureUtil.getPath(startRoot, "child1", "child12");
assertNotNull(leaf);
assertEquals("something", leaf.getValue());
leaf = TreeStructureUtil.getPath(startRoot, "child2");
assertNotNull(leaf);
assertEquals("something", leaf.getValue());
leaf = TreeStructureUtil.getPath(startRoot, "child3", "child31", "child311");
assertNotNull(leaf);
assertEquals("something", leaf.getValue());
leaf = TreeStructureUtil.getPath(startRoot, "child3", "child31", "child312");
assertNotNull(leaf);
assertEquals("something", leaf.getValue());
leaf = TreeStructureUtil.getPath(startRoot, "child3", "child31", "child313");
assertNotNull(leaf);
assertEquals("something", leaf.getValue());
//Verify the leftovers
assertNotNull(returnedValues);
Metadata child2 = null;
Metadata child3 = null;
for (Metadata value : returnedValues) {
if (value.getName().equalsIgnoreCase("child2")) {
child2 = value;
} else if (value.getName().equalsIgnoreCase("child3")) {
child3 = value;
} else {
fail("More values returned than expected! " + value.getName() + ": " + value.getValue());
}
}
assertNotNull(child2);
assertEquals("something else", child2.getValue());
assertNotNull(child3);
Metadata child31 = ((MetadataParent)child3).getChild("child31");
assertNotNull(child31);
assertEquals("something else", ((MetadataParent)child31).getChild("child312").getValue());
}
/**
* Tests to add one tree structure into another with some leftovers expected
* because they already existed and are of different type.
* I.e. Trying to add a leaf where there is a node and vice versa.
*
* @throws Exception if so.
*/
@Test
public void testAddChildValueTreeNotAllMergedLeafOnNode() throws Exception {
/*
_start tree_
root
child1
child11=something
child2
child21
child211=something
child3=something
_tree to add_
child1
child11
child111=something
child2
child21=something else
child4=something
_expected result_
root
child1
child11=something
child2
child21
child211=something
child3=something
child4=something
_expected leftovers_
child1
child11
child111=something
child2
child21=something else
*/
TreeNodeMetadataValue[] startTree = TreeStructureUtil.createTreePath("", "root", "child1");
TreeNodeMetadataValue startChild1 = startTree[1];
startChild1.addChild(new StringMetadataValue("child11", "something"));
TreeNodeMetadataValue startRoot = startTree[0];
TreeStructureUtil.addValue(startRoot, "something", "", "child2", "child21", "child211");
startRoot.addChild(new StringMetadataValue("child3", "something"));
TreeNodeMetadataValue addRoot = TreeStructureUtil.createPath("something else", "",
"root", "child1", "child11", "child111");
TreeStructureUtil.addValue(addRoot, "something else", "", "child2", "child21");
TreeStructureUtil.addValue(addRoot, "something", "", "child4");
Collection<MetadataValue> returnedValues = startRoot.addChildren(addRoot.getChildren());
//Verify the tree
Metadata leaf = TreeStructureUtil.getPath(startRoot, "child1", "child11");
assertNotNull(leaf);
assertEquals("something", leaf.getValue());
leaf = TreeStructureUtil.getPath(startRoot, "child2", "child21", "child211");
assertNotNull(leaf);
assertEquals("something", leaf.getValue());
leaf = TreeStructureUtil.getPath(startRoot, "child3");
assertNotNull(leaf);
assertEquals("something", leaf.getValue());
leaf = TreeStructureUtil.getPath(startRoot, "child4");
assertNotNull(leaf);
assertEquals("something", leaf.getValue());
//Verify the leftovers
assertNotNull(returnedValues);
Metadata child1 = null;
Metadata child2 = null;
for (Metadata value : returnedValues) {
if (value.getName().equalsIgnoreCase("child1")) {
child1 = value;
} else if (value.getName().equalsIgnoreCase("child2")) {
child2 = value;
} else {
fail("More values returned than expected! " + value.getName() + ": " + value.getValue());
}
}
assertNotNull(child1);
Metadata child11 = ((MetadataParent)child1).getChild("child11");
assertNotNull(child11);
Metadata child111 = ((MetadataParent)child11).getChild("child111");
assertEquals("something else", child111.getValue());
assertNotNull(child2);
assertEquals("something else", ((MetadataParent)child2).getChild("child21").getValue());
}
/**
* Tests
* {@link ParentUtil#replaceChild(com.sonyericsson.hudson.plugins.metadata.model.MetadataParent, MetadataValue)}
* and
* {@link ParentUtil#replaceChildren(com.sonyericsson.hudson.plugins.metadata.model.MetadataParent, java.util.List)}.
* @throws Exception if so.
*/
@Test
public void testReplaceChildren() throws Exception {
/*
Original tree
child1
child12 = original
child13
child2
child3
child31
child32 = original
child4 = original
Replace tree
child1
child12 = replace
child14
child3
child32 = replace
child4
child41 = replace
child5
Expected result
child1
child12 = replace
child13
child14
child2
child3
child31
child32 = replace
child4
child41 = replace
child5
*/
TreeNodeMetadataValue[] startTree = TreeStructureUtil.createTreePath("", "root", "child1");
TreeNodeMetadataValue startRoot = startTree[0];
TreeStructureUtil.addValue(startRoot, "original", "", "child1", "child12");
TreeStructureUtil.addValue(startRoot, "original", "", "child1", "child13");
TreeStructureUtil.addValue(startRoot, "original", "", "child2");
TreeStructureUtil.addValue(startRoot, "original", "", "child3", "child31");
TreeStructureUtil.addValue(startRoot, "original", "", "child3", "child32");
TreeStructureUtil.addValue(startRoot, "original", "", "child4");
TreeNodeMetadataValue[] replaceTree = TreeStructureUtil.createTreePath("", "root", "child1");
TreeNodeMetadataValue replaceRoot = replaceTree[0];
TreeStructureUtil.addValue(replaceRoot, "replace", "", "child1", "child12");
TreeStructureUtil.addValue(replaceRoot, "orig-replace", "", "child1", "child14");
TreeStructureUtil.addValue(replaceRoot, "replace", "", "child3", "child32");
TreeStructureUtil.addValue(replaceRoot, "replace", "", "child4", "child41");
TreeStructureUtil.addValue(replaceRoot, "orig-replace", "", "child5");
ParentUtil.replaceChildren(startRoot, replaceRoot.getValue());
assertEquals("replace", TreeStructureUtil.getPath(startRoot, "child1", "child12").getValue());
assertEquals("orig-replace", TreeStructureUtil.getPath(startRoot, "child1", "child14").getValue());
assertEquals("replace", TreeStructureUtil.getPath(startRoot, "child3", "child32").getValue());
assertEquals("replace", TreeStructureUtil.getPath(startRoot, "child4", "child41").getValue());
assertEquals("orig-replace", TreeStructureUtil.getPath(startRoot, "child5").getValue());
}
/**
* Tests
* {@link ParentUtil#removeChild(com.sonyericsson.hudson.plugins.metadata.model.MetadataParent,
* com.sonyericsson.hudson.plugins.metadata.model.Metadata)}
* and
* {@link ParentUtil#removeEmptyBranches(com.sonyericsson.hudson.plugins.metadata.model.MetadataParent)}.
* @throws Exception if so.
*/
@Test
public void testRemoveChildren() throws Exception {
TreeNodeMetadataValue[] startTree = TreeStructureUtil.createTreePath("", "root", "child1");
TreeNodeMetadataValue startRoot = startTree[0];
TreeStructureUtil.addValue(startRoot, "original", "", "child1", "child12");
TreeStructureUtil.addValue(startRoot, "original", "", "child1", "child13");
TreeStructureUtil.addValue(startRoot, "original", "", "child2");
TreeStructureUtil.prettyPrint(startRoot, " ");
MetadataValue val = TreeStructureUtil.getPath(startRoot, "child1", "child12");
MetadataValue val2 = TreeStructureUtil.getPath(startRoot, "child1", "child13");
TreeNodeMetadataValue tree = (TreeNodeMetadataValue)TreeStructureUtil.getPath(startRoot, "child1");
assertEquals(2, tree.getChildren().size());
ParentUtil.removeChild(tree, val);
ParentUtil.removeChild(tree, val2);
assertEquals(0, tree.getChildren().size());
ParentUtil.removeEmptyBranches(startRoot);
assertEquals(1, startRoot.getChildren().size());
}
/**
* Tests
* {@link ParentUtil#removeChild(java.util.Collection, com.sonyericsson.hudson.plugins.metadata.model.Metadata)}.
* @throws Exception if so.
*/
@Test
public void testRemoveChildrenFromCollection() throws Exception {
List<MetadataValue> list = new LinkedList<MetadataValue>();
StringMetadataValue stringMetadataValue = new StringMetadataValue("test", "description", "myvalue");
list.add(stringMetadataValue);
assertEquals(1, list.size());
ParentUtil.removeChild(list, stringMetadataValue);
assertEquals(0, list.size());
}
/**
* Creates a straight tree-path. The method returns an array where index 0 is the root and index 1 is the leaf.
*
* @param description the description of the root.
* @param path the path to create.
* @return the root and the leaf.
*/
public static TreeNodeMetadataDefinition[] createTreePath(String description, String... path) {
TreeNodeMetadataDefinition[] arr = new TreeNodeMetadataDefinition[2];
arr[1] = new TreeNodeMetadataDefinition(path[path.length - 1], description);
arr[0] = createPath(arr[1], Arrays.copyOf(path, path.length - 1));
return arr;
}
/**
* Creates a tree structured path with the provided leaf at the end.
*
* @param leaf the leaf to put in the end.
* @param parentPath the path to the leaf.
* @return the root node of the path.
*/
public static TreeNodeMetadataDefinition createPath(AbstractMetadataDefinition leaf, String... parentPath) {
if (parentPath == null || parentPath.length < 1) {
throw new IllegalArgumentException("The leaf must have at least one parent.");
}
TreeNodeMetadataDefinition root = null;
TreeNodeMetadataDefinition parent = null;
for (String name : parentPath) {
TreeNodeMetadataDefinition val = new TreeNodeMetadataDefinition(name);
if (parent != null) {
parent.addChild(val);
}
parent = val;
if (root == null) {
root = val;
}
}
parent.addChild(leaf);
return root;
}
/**
* Creates a path where the last element is a string with the provided value and description.
*
* @param value the value
* @param description the description
* @param path the full path to the leaf.
* @return the tree.
*/
public static TreeNodeMetadataDefinition createPath(String value, String description, String... path) {
StringMetadataDefinition str = new StringMetadataDefinition(path[path.length - 1], description, value, false);
return createPath(str, Arrays.copyOf(path, path.length - 1));
}
/**
* Adds a {@link StringMetadataValue} to the root node with the specified path.
*
* @param root the root to add the tree to.
* @param value the string value of the leaf node.
* @param description the description of the leaf node.
* @param path the path to the leaf from the root.
* @return true if there was no merge conflicts.
*/
public static boolean addValue(MetadataParent root, String value, String description, String... path) {
StringMetadataDefinition sVal = new StringMetadataDefinition(path[path.length - 1], description, value, false);
return addValue(root, sVal, Arrays.copyOf(path, path.length - 1));
}
/**
* Adds a value with the specified path to the root.
*
* @param root the root to add the tree to.
* @param value the value of the leaf.
* @param parentPath the path of the parent of the leaf from the root.
* @return true if there was no merge conflicts.
*/
public static boolean addValue(MetadataParent root, AbstractMetadataDefinition value, String... parentPath) {
if (parentPath == null || parentPath.length <= 0) {
return root.addChild(value) == null;
} else {
TreeNodeMetadataDefinition path = createPath(value, parentPath);
return root.addChild(path) == null;
}
}
}