blob: 540381d218a16c30a93318a396c3c62d9c07e054 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2019 École Polytechnique de Montréal
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License 2.0 which
* accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
package org.eclipse.tracecompass.incubator.analysis.core.tests.weighted;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.tracecompass.incubator.analysis.core.tests.stubs.weighted.SimpleTree;
import org.eclipse.tracecompass.incubator.analysis.core.tests.stubs.weighted.WeightedTreeProviderStub;
import org.eclipse.tracecompass.incubator.analysis.core.weighted.tree.ITree;
import org.eclipse.tracecompass.incubator.analysis.core.weighted.tree.IWeightedTreeProvider;
import org.eclipse.tracecompass.incubator.analysis.core.weighted.tree.IWeightedTreeSet;
import org.eclipse.tracecompass.incubator.analysis.core.weighted.tree.WeightedTree;
import org.eclipse.tracecompass.incubator.analysis.core.weighted.tree.WeightedTreeSet;
import org.eclipse.tracecompass.incubator.analysis.core.weighted.tree.WeightedTreeUtils;
import org.eclipse.tracecompass.incubator.analysis.core.weighted.tree.diff.DifferentialWeightedTree;
import org.eclipse.tracecompass.incubator.analysis.core.weighted.tree.diff.DifferentialWeightedTreeProvider;
import org.junit.Before;
import org.junit.Test;
/**
* Test the operations on the the {@link WeightedTreeUtils} class
*
* @author Geneviève Bastien
*/
@NonNullByDefault
public class WeightedTreeUtilsTest {
private static final Integer VALUE1 = 1;
private static final Integer VALUE2 = 2;
private static final Integer VALUE3 = 3;
private static final Integer VALUE4 = 4;
private static final Integer VALUE5 = 5;
private @Nullable List<WeightedTree<Integer>> fTree1;
private @Nullable List<WeightedTree<Integer>> fTree2;
/**
* Prepare data for the test
*/
@Before
public void setupTrees() {
// Create a simple tree with 2 elements and a level of children
List<WeightedTree<Integer>> tree1 = new ArrayList<>();
List<WeightedTree<Integer>> tree2 = new ArrayList<>();
/**
* <pre>
* Create a first collection of tree
* * 1 -> 10
* | * 2 -> 4
* | * 3 -> 3
* | * 3 -> 1
* * 2 -> 10
* | * 4 -> 5
* | * 5 -> 5
* </pre>
*/
WeightedTree<Integer> element1 = new WeightedTree<>(VALUE1, 10);
element1.addChild(new WeightedTree<>(VALUE2, 4));
WeightedTree<Integer> element2 = new WeightedTree<>(VALUE3, 3);
element1.addChild(element2);
element2.addChild(new WeightedTree<>(VALUE3, 1));
tree1.add(element1);
element1 = new WeightedTree<>(VALUE2, 10);
element1.addChild(new WeightedTree<>(VALUE4, 5));
element1.addChild(new WeightedTree<>(VALUE5, 5));
tree1.add(element1);
fTree1 = tree1;
/**
* <pre>
* Create a second collection of tree
* * 1 -> 10
* | * 2 -> 3
* | * 3 -> 3
* | * 3 -> 1
* * 2 -> 20
* | * 4 -> 10
* | * 5 -> 10
* | * 3 -> 5
* </pre>
*/
element1 = new WeightedTree<>(VALUE1, 10);
element1.addChild(new WeightedTree<>(VALUE2, 3));
element2 = new WeightedTree<>(VALUE3, 3);
element1.addChild(element2);
element2.addChild(new WeightedTree<>(VALUE3, 1));
tree2.add(element1);
element1 = new WeightedTree<>(VALUE2, 20);
element1.addChild(new WeightedTree<>(VALUE4, 10));
element2 = new WeightedTree<>(VALUE5, 10);
element1.addChild(element2);
element2.addChild(new WeightedTree<>(VALUE3, 5));
tree2.add(element1);
fTree2 = tree2;
}
/**
* Test the {@link WeightedTreeUtils#diffTrees(Collection, Collection)}
* method with simple trees
*/
@Test
public void testDiffTree() {
List<WeightedTree<Integer>> tree1 = fTree1;
List<WeightedTree<Integer>> tree2 = fTree2;
assertNotNull(tree1);
assertNotNull(tree2);
// Differentiate tree1 and tree2
Collection<DifferentialWeightedTree<Integer>> diffTrees = WeightedTreeUtils.diffTrees(tree1, tree2);
verifyDiffTrees12(diffTrees);
// Reverse: Differentiate tree2 and tree1
diffTrees = WeightedTreeUtils.diffTrees(tree2, tree1);
verifyDiffTrees21(diffTrees);
}
/**
* Test the
* {@link WeightedTreeUtils#diffTreeSets(IWeightedTreeProvider, IWeightedTreeSet, IWeightedTreeSet)}
* with treesets having a single element, that are not identical in both
* trees
*/
@Test
public void testDiffTreeSetOneElement() {
// Prepare the treesets for this test case
String element1 = "elementForTree1";
String element2 = "elementForTree2";
WeightedTreeSet<Integer, String> treeSet1 = new WeightedTreeSet<>();
WeightedTreeSet<Integer, String> treeSet2 = new WeightedTreeSet<>();
List<WeightedTree<Integer>> tree1 = fTree1;
List<WeightedTree<Integer>> tree2 = fTree2;
assertNotNull(tree1);
assertNotNull(tree2);
tree1.forEach(t -> treeSet1.addWeightedTree(element1, t));
tree2.forEach(t -> treeSet2.addWeightedTree(element2, t));
// Differentiate treeset1 and treeset2
WeightedTreeProviderStub<Integer, String> provider = new WeightedTreeProviderStub<>();
DifferentialWeightedTreeProvider<Integer> diffProvider = WeightedTreeUtils.diffTreeSets(provider, treeSet1, treeSet2);
assertNotNull(diffProvider);
IWeightedTreeSet<Integer, Object, DifferentialWeightedTree<Integer>> treeSet = diffProvider.getTreeSet();
// Make sure there is one element in the treeset and it's the same as element1
Collection<Object> elements = treeSet.getElements();
assertEquals("Number of elements in diff tree", 1, elements.size());
Object element = elements.iterator().next();
assertEquals("element in diffTree", element1, element);
Collection<DifferentialWeightedTree<Integer>> diffTrees = treeSet.getTreesFor(element);
verifyDiffTrees12(diffTrees);
}
/**
* Test the
* {@link WeightedTreeUtils#diffTreeSets(IWeightedTreeProvider, IWeightedTreeSet, IWeightedTreeSet)}
* with treesets having the exact same elements
* trees
*/
@Test
public void testDiffTreeSetSameElements() {
// Prepare the treesets for this test case
String element1 = "element1";
String element2 = "element2";
WeightedTreeSet<Integer, String> treeSet1 = new WeightedTreeSet<>();
WeightedTreeSet<Integer, String> treeSet2 = new WeightedTreeSet<>();
List<WeightedTree<Integer>> tree1 = fTree1;
List<WeightedTree<Integer>> tree2 = fTree2;
assertNotNull(tree1);
assertNotNull(tree2);
// For treeset1, add tree1 for element1 and tree2 for element2
tree1.forEach(t -> treeSet1.addWeightedTree(element1, t));
tree2.forEach(t -> treeSet1.addWeightedTree(element2, t));
// Switch the trees for treeSet2: tree2 for el1, tree1 for el2
tree1.forEach(t -> treeSet2.addWeightedTree(element2, t));
tree2.forEach(t -> treeSet2.addWeightedTree(element1, t));
// Differentiate treeset1 and treeset2
WeightedTreeProviderStub<Integer, String> provider = new WeightedTreeProviderStub<>();
DifferentialWeightedTreeProvider<Integer> diffProvider = WeightedTreeUtils.diffTreeSets(provider, treeSet1, treeSet2);
assertNotNull(diffProvider);
IWeightedTreeSet<Integer, Object, DifferentialWeightedTree<Integer>> treeSet = diffProvider.getTreeSet();
// Make sure the 2 elements are present in the treeset and their data is correct
Collection<Object> elements = treeSet.getElements();
assertEquals("Number of elements in diff tree", 2, elements.size());
// Compare trees for element1
Collection<DifferentialWeightedTree<Integer>> diffTrees = treeSet.getTreesFor(element1);
assertFalse(diffTrees.isEmpty());
verifyDiffTrees12(diffTrees);
// Compare trees for element2
diffTrees = treeSet.getTreesFor(element2);
assertFalse(diffTrees.isEmpty());
verifyDiffTrees21(diffTrees);
}
/**
* Test the
* {@link WeightedTreeUtils#diffTreeSets(IWeightedTreeProvider, IWeightedTreeSet, IWeightedTreeSet)}
* with treesets having elements with the same name, in a tree structure
* trees
*/
@Test
public void testDiffTreeSetNamedElementsTree() {
// Prepare the treesets for this test case
String element1 = "element1";
String element2 = "element2";
String element3 = "element3";
WeightedTreeSet<Integer, SimpleTree> treeSet1 = new WeightedTreeSet<>();
WeightedTreeSet<Integer, SimpleTree> treeSet2 = new WeightedTreeSet<>();
List<WeightedTree<Integer>> tree1 = Objects.requireNonNull(fTree1);
List<WeightedTree<Integer>> tree2 = Objects.requireNonNull(fTree2);
// For treeset1, add tree1 for childEl11 and tree2 for childEl12
// Prepare elements
SimpleTree parentEl1 = new SimpleTree(element1);
SimpleTree childEl11 = new SimpleTree(element2);
SimpleTree childEl12 = new SimpleTree(element3);
parentEl1.addChild(childEl11);
parentEl1.addChild(childEl12);
tree1.forEach(t -> treeSet1.addWeightedTree(childEl11, t));
tree2.forEach(t -> treeSet1.addWeightedTree(childEl12, t));
// Switch the trees for treeSet2: tree2 for childEl21, tree1 for childEl22
SimpleTree parentEl2 = new SimpleTree(element1);
SimpleTree childEl21 = new SimpleTree(element2);
SimpleTree childEl22 = new SimpleTree(element3);
parentEl2.addChild(childEl21);
parentEl2.addChild(childEl22);
tree1.forEach(t -> treeSet2.addWeightedTree(childEl22, t));
tree2.forEach(t -> treeSet2.addWeightedTree(childEl21, t));
// Differentiate treeset1 and treeset2
WeightedTreeProviderStub<Integer, String> provider = new WeightedTreeProviderStub<>();
DifferentialWeightedTreeProvider<Integer> diffProvider = WeightedTreeUtils.diffTreeSets(provider, treeSet1, treeSet2);
assertNotNull(diffProvider);
IWeightedTreeSet<Integer, Object, DifferentialWeightedTree<Integer>> treeSet = diffProvider.getTreeSet();
// Make sure the element hierarchy is the same as treeset 1
Collection<Object> elements = treeSet.getElements();
assertEquals("Number of elements in diff tree", 1, elements.size());
Object diffParentEl = elements.iterator().next();
assertEquals("Same element as treeset1", parentEl1, diffParentEl);
Collection<ITree> children = ((SimpleTree) diffParentEl).getChildren();
assertEquals("Number of children", 2, children.size());
// Compare trees for element1
Collection<DifferentialWeightedTree<Integer>> diffTrees = treeSet.getTreesFor(childEl11);
assertFalse(diffTrees.isEmpty());
verifyDiffTrees12(diffTrees);
// Compare trees for element2
diffTrees = treeSet.getTreesFor(childEl12);
assertFalse(diffTrees.isEmpty());
verifyDiffTrees21(diffTrees);
}
/**
* Test the
* {@link WeightedTreeUtils#diffTreeSets(IWeightedTreeProvider, IWeightedTreeSet, IWeightedTreeSet)}
* with treesets having 2 elements each, but only one with the same name
* trees
*/
@Test
public void testDiffTreeSetNamedElementsMixed() {
// Prepare the treesets for this test case
String element1 = "element1";
String element2 = "element2";
String element3 = "element3";
String element4 = "element4";
WeightedTreeSet<Integer, SimpleTree> treeSet1 = new WeightedTreeSet<>();
WeightedTreeSet<Integer, SimpleTree> treeSet2 = new WeightedTreeSet<>();
List<WeightedTree<Integer>> tree1 = Objects.requireNonNull(fTree1);
List<WeightedTree<Integer>> tree2 = Objects.requireNonNull(fTree2);
// For treeset1, add tree1 for element1 and tree2 for element2
// Prepare elements
SimpleTree parentEl1 = new SimpleTree(element1);
SimpleTree childEl11 = new SimpleTree(element2);
SimpleTree childEl12 = new SimpleTree(element3);
parentEl1.addChild(childEl11);
parentEl1.addChild(childEl12);
tree1.forEach(t -> treeSet1.addWeightedTree(childEl11, t));
tree2.forEach(t -> treeSet1.addWeightedTree(childEl12, t));
// Switch the trees for treeSet2: tree2 for el1, tree1 for el2
// Child 2 of parent element does not match any name from other tree set
SimpleTree parentEl2 = new SimpleTree(element1);
SimpleTree childEl21 = new SimpleTree(element2);
SimpleTree childEl22 = new SimpleTree(element4);
parentEl2.addChild(childEl21);
parentEl2.addChild(childEl22);
tree1.forEach(t -> treeSet2.addWeightedTree(childEl22, t));
tree2.forEach(t -> treeSet2.addWeightedTree(childEl21, t));
// Differentiate treeset1 and treeset2
WeightedTreeProviderStub<Integer, String> provider = new WeightedTreeProviderStub<>();
DifferentialWeightedTreeProvider<Integer> diffProvider = WeightedTreeUtils.diffTreeSets(provider, treeSet1, treeSet2);
assertNotNull(diffProvider);
IWeightedTreeSet<Integer, Object, DifferentialWeightedTree<Integer>> treeSet = diffProvider.getTreeSet();
// Make sure the element hierarchy is the same as treeset 1
Collection<Object> elements = treeSet.getElements();
assertEquals("Number of elements in diff tree", 1, elements.size());
Object diffParentEl = elements.iterator().next();
assertEquals("Same element as treeset1", parentEl1, diffParentEl);
Collection<ITree> children = ((SimpleTree) diffParentEl).getChildren();
assertEquals("Number of children", 2, children.size());
// Compare trees for element1
Collection<DifferentialWeightedTree<Integer>> diffTrees = treeSet.getTreesFor(childEl11);
assertFalse(diffTrees.isEmpty());
verifyDiffTrees12(diffTrees);
// The second element should have no trees
diffTrees = treeSet.getTreesFor(childEl12);
assertTrue(diffTrees.isEmpty());
}
/**
* Test the
* {@link WeightedTreeUtils#diffTreeSets(IWeightedTreeProvider, IWeightedTreeSet, IWeightedTreeSet)}
* with treesets having multiple elements, but none in common
* trees
*/
@Test
public void testDiffTreeSetUnpairedElements() {
// Prepare the treesets for this test case
String element1 = "element1";
String element2 = "element2";
String element3 = "element3";
String element4 = "element4";
WeightedTreeSet<Integer, String> treeSet1 = new WeightedTreeSet<>();
WeightedTreeSet<Integer, String> treeSet2 = new WeightedTreeSet<>();
List<WeightedTree<Integer>> tree1 = fTree1;
List<WeightedTree<Integer>> tree2 = fTree2;
assertNotNull(tree1);
assertNotNull(tree2);
// For treeset1, add tree1 for element1 and tree2 for element2
tree1.forEach(t -> treeSet1.addWeightedTree(element1, t));
tree2.forEach(t -> treeSet1.addWeightedTree(element2, t));
// Switch the trees for treeSet2: tree2 for el1, tree1 for el2
tree1.forEach(t -> treeSet2.addWeightedTree(element3, t));
tree2.forEach(t -> treeSet2.addWeightedTree(element4, t));
// Differentiate treeset1 and treeset2
WeightedTreeProviderStub<Integer, String> provider = new WeightedTreeProviderStub<>();
DifferentialWeightedTreeProvider<Integer> diffProvider = WeightedTreeUtils.diffTreeSets(provider, treeSet1, treeSet2);
assertNull(diffProvider);
}
private static void verifyDiffTrees12(Collection<DifferentialWeightedTree<Integer>> diffTrees) {
assertEquals("Size of differential tree", 2, diffTrees.size());
// Compare the first element
Collection<DifferentialWeightedTree<Integer>> nextTree = getAndVerifyTree(diffTrees, VALUE1, 10, 0);
assertEquals("Size of differential tree level 2", 2, nextTree.size());
getAndVerifyTree(nextTree, VALUE2, 3, -0.25);
nextTree = getAndVerifyTree(nextTree, VALUE3, 3, 0);
assertEquals("Size of diferential tree level 3", 1, nextTree.size());
getAndVerifyTree(nextTree, VALUE3, 1, 0);
// Compare the second element
nextTree = getAndVerifyTree(diffTrees, VALUE2, 20, 1.0);
assertEquals("Size of differential tree level 2", 2, nextTree.size());
getAndVerifyTree(nextTree, VALUE4, 10, 1.0);
nextTree = getAndVerifyTree(nextTree, VALUE5, 10, 1.0);
assertEquals("Size of diferential tree level 3", 1, nextTree.size());
getAndVerifyTree(nextTree, VALUE3, 5, Double.NaN);
}
private static void verifyDiffTrees21(Collection<DifferentialWeightedTree<Integer>> diffTrees) {
assertEquals("Size of differential tree", 2, diffTrees.size());
// Compare the first element
Collection<DifferentialWeightedTree<Integer>> nextTree = getAndVerifyTree(diffTrees, VALUE1, 10, 0);
assertEquals("Size of differential tree level 2", 2, nextTree.size());
getAndVerifyTree(nextTree, VALUE2, 4, 0.33333);
nextTree = getAndVerifyTree(nextTree, VALUE3, 3, 0);
assertEquals("Size of diferential tree level 3", 1, nextTree.size());
getAndVerifyTree(nextTree, VALUE3, 1, 0);
// Compare the first element
nextTree = getAndVerifyTree(diffTrees, VALUE2, 10, -0.5);
assertEquals("Size of differential tree level 2", 2, nextTree.size());
getAndVerifyTree(nextTree, VALUE4, 5, -0.5);
nextTree = getAndVerifyTree(nextTree, VALUE5, 5, -0.5);
assertTrue(nextTree.isEmpty());
}
private static Collection<DifferentialWeightedTree<Integer>> getAndVerifyTree(Collection<DifferentialWeightedTree<Integer>> diffTrees, Integer element, int expectedWeight, double expectedDiff) {
for (DifferentialWeightedTree<Integer> tree : diffTrees) {
List<DifferentialWeightedTree<Integer>> children = new ArrayList<>();
if (tree.getObject().equals(element)) {
// Found the tree, verify its values and return its children
assertEquals("Base weight of " + element, expectedWeight, tree.getWeight());
assertEquals("Differential value of " + element, expectedDiff, tree.getDifference(), 0.001);
for (WeightedTree<Integer> child : tree.getChildren()) {
children.add((DifferentialWeightedTree<Integer>) child);
}
return children;
}
}
throw new NullPointerException("Tree not found for object " + element);
}
}