# HG changeset patch # User James Aziz # Date 1446063768 14400 # Node ID 7db129297a7349075d485db903c432978315a262 # Parent 2649ea55de87dfe851a94ff9b63e2ba30c5713cd Backport - Fix treemap scaling imprecision Reviewed-by: jkang, aazores, neugens Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2015-October/016635.html diff -r 2649ea55de87 -r 7db129297a73 vm-heap-analysis/client-swing/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/SquarifiedTreeMap.java --- a/vm-heap-analysis/client-swing/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/SquarifiedTreeMap.java Tue Oct 13 17:16:38 2015 -0400 +++ b/vm-heap-analysis/client-swing/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/SquarifiedTreeMap.java Wed Oct 28 16:22:48 2015 -0400 @@ -328,7 +328,7 @@ * @return the sum of the elements. */ private double getSum(List nodes) { - int sum = 0; + double sum = 0; for (TreeMapNode n : nodes) { sum += n.getWeight(); } @@ -433,7 +433,7 @@ // recalculate weights in percentage of their sum for (TreeMapNode node : elements) { - int w = (int) Math.round((node.getWeight()/sum) * totArea); + double w = (node.getWeight()/sum) * totArea; node.setWeight(w); } } diff -r 2649ea55de87 -r 7db129297a73 vm-heap-analysis/client-swing/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/TreeMapNode.java --- a/vm-heap-analysis/client-swing/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/TreeMapNode.java Tue Oct 13 17:16:38 2015 -0400 +++ b/vm-heap-analysis/client-swing/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/TreeMapNode.java Wed Oct 28 16:22:48 2015 -0400 @@ -107,8 +107,7 @@ private String label; /** - * The node's weight which has been set inside the constructor. Note that - * this value can be assigned just one time, using the constructor. All + * The node's weight which has been set inside the constructor. All * operations which refers to node's weight work on the weight field, that * is used to make calcs. */ @@ -329,7 +328,7 @@ * automatically to 0. * @param weight the new weight for this object. */ - public void setWeight(int w) { + public void setWeight(double w) { this.weight = w < 0 && !allowNonPositiveWeight ? 0 : w; } diff -r 2649ea55de87 -r 7db129297a73 vm-heap-analysis/client-swing/src/test/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/TreeMapNodeTest.java --- a/vm-heap-analysis/client-swing/src/test/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/TreeMapNodeTest.java Tue Oct 13 17:16:38 2015 -0400 +++ b/vm-heap-analysis/client-swing/src/test/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/TreeMapNodeTest.java Wed Oct 28 16:22:48 2015 -0400 @@ -57,6 +57,7 @@ public class TreeMapNodeTest { private TreeMapNode node; + private static final double DELTA = 0.001; @Before public void setUp() { @@ -126,9 +127,9 @@ @Test public final void testGetSetWeight() { - assertTrue(1 == node.getWeight()); + assertEquals(1.0, node.getWeight(), DELTA); node.setWeight(5); - assertTrue(5 == node.getWeight()); + assertEquals(5.0, node.getWeight(), DELTA); } @Test @@ -151,22 +152,21 @@ @Test public final void testGetSetRealWeight() { node = new TreeMapNode(null, 5); - assertTrue(node.getRealWeight() == 5); + assertEquals(5.0, node.getRealWeight(), DELTA); node.setRealWeight(8); - assertTrue(node.getRealWeight() == 8); + assertEquals(8.0, node.getRealWeight(), DELTA); } @Test public final void testAllowNonPositiveWeight() { assertFalse(TreeMapNode.isAllowNonPositiveWeight()); node.setWeight(-5); - assertTrue(node.getWeight() == 1); // the real node weight - assertTrue(node.getRealWeight() == 1); - + assertEquals(1.0, node.getWeight(), DELTA); + assertEquals(1.0, node.getRealWeight(), DELTA); TreeMapNode.setAllowNonPositiveWeight(true); node.setWeight(-5); - assertTrue(node.getWeight() == -5); + assertEquals(-5.0, node.getWeight(), DELTA); } @Test diff -r 2649ea55de87 -r 7db129297a73 vm-heap-analysis/client-swing/src/test/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/TreeProcessorTest.java --- a/vm-heap-analysis/client-swing/src/test/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/TreeProcessorTest.java Tue Oct 13 17:16:38 2015 -0400 +++ b/vm-heap-analysis/client-swing/src/test/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/TreeProcessorTest.java Wed Oct 28 16:22:48 2015 -0400 @@ -36,18 +36,21 @@ package com.redhat.thermostat.vm.heap.analysis.client.swing.internal; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.awt.geom.Rectangle2D; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; +import java.util.List; import org.junit.Before; import org.junit.Test; public class TreeProcessorTest { + private static final double DELTA = 0.1; + private static final double BASE = 2.0; + TreeMapNode node; Rectangle2D.Double area; @@ -59,35 +62,35 @@ @Test public final void testTreeProcessor() { - boolean catched = false; + boolean caught = false; // this test check all wrong combinations for constructor parameters try { TreeProcessor.processTreeMap(null, area); } catch(NullPointerException e) { - catched = true; + caught = true; } - assertTrue(catched); - catched = false; + assertTrue(caught); + caught = false; try { TreeProcessor.processTreeMap(node, null); } catch(NullPointerException e) { - catched = true; + caught = true; } - assertTrue(catched); - catched = false; + assertTrue(caught); + caught = false; try { TreeProcessor.processTreeMap(null, null); } catch(NullPointerException e) { - catched = true; + caught = true; } - assertTrue(catched); + assertTrue(caught); } @Test - public final void testProcessTreeMap() { + public final void testProcessTreeMapProcessesWholeTree() { generateTree(node, 5, 5); TreeProcessor.processTreeMap(node, area); @@ -117,4 +120,46 @@ } } } + + @Test + public final void testProcessTreeMapNodeSizing() { + final int numSiblings = 5; + final double originalDimension = 64.0; + final double smallerDimension = 32.0; + + generateSiblingTree(node, numSiblings); + + TreeProcessor.processTreeMap(node, new Rectangle2D.Double(0, 0, originalDimension, originalDimension)); + checkNodeWeightRatios(numSiblings); + + //now resize smaller + TreeProcessor.processTreeMap(node, new Rectangle2D.Double(0, 0, smallerDimension, smallerDimension)); + + //now resize back to original size + TreeProcessor.processTreeMap(node, new Rectangle2D.Double(0, 0, originalDimension, originalDimension)); + //if the first call to checkNodeWeightRatios(numSiblings) worked, this should too + checkNodeWeightRatios(numSiblings); + } + + private void generateSiblingTree(TreeMapNode root, int numSiblings) { + assertTrue(numSiblings > 1); + root.addChild(new TreeMapNode(1.0)); //this is not a random weight + for(int i = 0; i < (numSiblings - 1); i++) { + root.addChild(new TreeMapNode(Math.pow(BASE, i))); + } + } + + private void checkNodeWeightRatios(int numSiblings) { + List children = node.getChildren(); + assertEquals(numSiblings, children.size()); + TreeMapNode.sort(children); + + double weight = children.get(0).getWeight(); + for(int i = 1; i < numSiblings - 1; i++) { + double currentWeight = children.get(i).getWeight(); + //check that the ratio between node weights is approximately 2 (which is the BASE) + assertEquals(BASE, weight/currentWeight, DELTA); + weight = currentWeight; + } + } }