/* * TestTreeSetGreedy.java of project jchart2d - Junit test case * for class TreeSetGreedy. * Copyright (C) Achim Westermann, created on 16.05.2005, 18:58:11 * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * If you modify or optimize the code in a useful way please let me know. * Achim.Westermann@gmx.de * */ package info.monitorenter.util.collections; import info.monitorenter.gui.chart.ITrace2D; import java.io.PrintWriter; import java.io.StringWriter; import junit.framework.Assert; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; /** * Junit test case for class <code>{@link TreeSetGreedy}</code>. * <p> * * @author <a href="mailto:Achim.Westermann@gmx.de">Achim Westermann </a> * */ public class TestTreeSetGreedy extends TestCase { /** * Helper class for adding as element to the tested * <code>{@link TreeSetGreedy}</code>. * <p> * * @author <a href="mailto:Achim.Westermann@gmx.de">Achim Westermann</a> * * * @version $Revision: 1.8 $ */ final class Element implements IComparableProperty { /** Generated <code>serialVersionUID</code>. */ private static final long serialVersionUID = -615304987571740852L; /** The internal comparable. */ private Number m_compare = new Integer(ITrace2D.ZINDEX_MAX); /** * Defcon. * <p> */ public Element() { super(); } /** * @see info.monitorenter.util.collections.IComparableProperty#getComparableProperty() */ public Number getComparableProperty() { return this.m_compare; } /** * @see info.monitorenter.util.collections.IComparableProperty#setComparableProperty(java.lang.Number) */ public void setComparableProperty(final Number n) { this.m_compare = n; } /** * @see java.lang.Object#toString() */ @Override public String toString() { StringBuffer ret = new StringBuffer(this.m_compare.toString()); return ret.toString(); } } /** * Test suite for this test class. * <p> * * @return the test suite */ public static Test suite() { TestSuite suite = new TestSuite(); suite.setName(TestTreeSetGreedy.class.getName()); suite.addTest(new TestTreeSetGreedy("testAdd")); suite.addTest(new TestTreeSetGreedy("testAdd10RemoveCenter")); suite.addTest(new TestTreeSetGreedy("testAddEqual10")); suite.addTest(new TestTreeSetGreedy("testAddEqual2")); suite.addTest(new TestTreeSetGreedy("testAddEqual3")); suite.addTest(new TestTreeSetGreedy("testAddEqual5")); suite.addTest(new TestTreeSetGreedy("testAddIdentical2")); suite.addTest(new TestTreeSetGreedy("testAddRemoveEqual10")); suite.addTest(new TestTreeSetGreedy("testAddRemoveEqual2")); suite.addTest(new TestTreeSetGreedy("testAddRemoveEqual3")); suite.addTest(new TestTreeSetGreedy("testAddRemoveEqual5")); suite.addTest(new TestTreeSetGreedy("testMultiThreadingAddRemove")); return suite; } /** The instance to test. */ protected TreeSetGreedy<IComparableProperty> m_test; /** * Creates an instance with the given name. * <p> * * @param testName * the name of the test case. */ public TestTreeSetGreedy(final String testName) { super(testName); } /** * @see junit.framework.TestCase#setUp() */ @Override protected void setUp() throws Exception { super.setUp(); this.m_test = new TreeSetGreedy<IComparableProperty>(); } /** * @see junit.framework.TestCase#tearDown() */ @Override protected void tearDown() throws Exception { super.tearDown(); this.m_test = null; } /** * Add an element and ensure size is 1. * <p> * */ public void testAdd() { Assert.assertNotNull(this.m_test); this.m_test.add(new Element()); Assert.assertEquals(1, this.m_test.size()); } /** * Add 1,1,1,1 and remove one element that is in the center of the order * (assuming that they will get different numbers due to correct add * mechanism). * <p> * */ public void testAdd10RemoveCenter() { Assert.assertNotNull(this.m_test); IComparableProperty e1 = new Element(); IComparableProperty e2 = new Element(); IComparableProperty e3 = new Element(); IComparableProperty e4 = new Element(); IComparableProperty e5 = new Element(); IComparableProperty e6 = new Element(); IComparableProperty e7 = new Element(); IComparableProperty e8 = new Element(); IComparableProperty e9 = new Element(); IComparableProperty e10 = new Element(); // add this.m_test.add(e1); this.m_test.add(e2); this.m_test.add(e3); this.m_test.add(e4); this.m_test.add(e5); this.m_test.add(e6); this.m_test.add(e7); this.m_test.add(e8); this.m_test.add(e9); this.m_test.add(e10); // remove this.m_test.remove(e6); System.out.println("testAdd10RemoveCenter"); System.out.println(this.m_test); Assert.assertEquals("Unexpected size: " + this.m_test, this.m_test.size(), 9); } /** * Add 1,1,1,1,1 and test, wether all numbers are different. * <p> * */ public void testAddEqual10() { Assert.assertNotNull(this.m_test); IComparableProperty e1 = new Element(); IComparableProperty e2 = new Element(); IComparableProperty e3 = new Element(); IComparableProperty e4 = new Element(); IComparableProperty e5 = new Element(); IComparableProperty e6 = new Element(); IComparableProperty e7 = new Element(); IComparableProperty e8 = new Element(); IComparableProperty e9 = new Element(); IComparableProperty e10 = new Element(); this.m_test.add(e1); this.m_test.add(e2); this.m_test.add(e3); this.m_test.add(e4); this.m_test.add(e5); this.m_test.add(e6); this.m_test.add(e7); this.m_test.add(e8); this.m_test.add(e9); this.m_test.add(e10); System.out.println("testAddEqual10"); System.out.println(this.m_test); Assert.assertEquals(10, this.m_test.size()); } /** * Add two distinct <code>{@link IComparableProperty}</code> elements with * equal comparable and ensure size is 2. * <p> * */ public void testAddEqual2() { Assert.assertNotNull(this.m_test); IComparableProperty e1 = new Element(); IComparableProperty e2 = new Element(); this.m_test.add(e1); this.m_test.add(e2); System.out.println("testAddEqual2"); System.out.println(this.m_test); Assert.assertEquals(this.m_test.size(), 2); } /** * Add 1,1,1 and test, wether all numbers are different. * <p> */ public void testAddEqual3() { Assert.assertNotNull(this.m_test); IComparableProperty e1 = new Element(); IComparableProperty e2 = new Element(); IComparableProperty e3 = new Element(); this.m_test.add(e1); this.m_test.add(e2); this.m_test.add(e3); System.out.println("testAddEqual3"); System.out.println(this.m_test); Assert.assertEquals(3, this.m_test.size()); } /** * Add 1,1,1,1,1 and test, wether all numbers are different. * <p> * */ public void testAddEqual5() { Assert.assertNotNull(this.m_test); IComparableProperty e1 = new Element(); IComparableProperty e2 = new Element(); IComparableProperty e3 = new Element(); IComparableProperty e4 = new Element(); IComparableProperty e5 = new Element(); this.m_test.add(e1); this.m_test.add(e2); this.m_test.add(e3); this.m_test.add(e4); this.m_test.add(e5); System.out.println("testAddEqual5"); System.out.println(this.m_test); Assert.assertEquals(5, this.m_test.size()); } /** * Add two identical elements and ensure that the 2nd operation fails. * <p> * */ public void testAddIdentical2() { Assert.assertNotNull(this.m_test); IComparableProperty e1 = new Element(); this.m_test.add(e1); boolean success = this.m_test.add(e1); System.out.println("testAddIdentical"); System.out.println(this.m_test); Assert.assertFalse(success); } /** * Add 1,1,1,1,1,1,1,1,1,1, remove them and ensure that no elements remain. * <p> * */ public void testAddRemoveEqual10() { Assert.assertNotNull(this.m_test); IComparableProperty e1 = new Element(); IComparableProperty e2 = new Element(); IComparableProperty e3 = new Element(); IComparableProperty e4 = new Element(); IComparableProperty e5 = new Element(); IComparableProperty e6 = new Element(); IComparableProperty e7 = new Element(); IComparableProperty e8 = new Element(); IComparableProperty e9 = new Element(); IComparableProperty e10 = new Element(); // add this.m_test.add(e1); this.m_test.add(e2); this.m_test.add(e3); this.m_test.add(e4); this.m_test.add(e5); this.m_test.add(e6); this.m_test.add(e7); this.m_test.add(e8); this.m_test.add(e9); this.m_test.add(e10); // remove this.m_test.remove(e1); this.m_test.remove(e2); this.m_test.remove(e3); this.m_test.remove(e4); this.m_test.remove(e5); this.m_test.remove(e6); this.m_test.remove(e7); this.m_test.remove(e8); this.m_test.remove(e9); this.m_test.remove(e10); System.out.println("testAddRemoveEqual10"); System.out.println(this.m_test); Assert.assertEquals("Unexpected remaining elements: " + this.m_test, this.m_test.size(), 0); } /** * Add two distinct <code>{@link IComparableProperty}</code> elements with * equal comparable, remove them and ensure size is 0. * <p> * */ public void testAddRemoveEqual2() { Assert.assertNotNull(this.m_test); IComparableProperty e1 = new Element(); IComparableProperty e2 = new Element(); // add this.m_test.add(e1); this.m_test.add(e2); // remove this.m_test.remove(e1); this.m_test.remove(e2); System.out.println("testAddRemoveEqual2"); System.out.println(this.m_test); Assert.assertEquals("Unexpected remaining elements: " + this.m_test, this.m_test.size(), 0); } /** * Add 1,1,1, remove then and ensure that zero elements remain. * <p> * */ public void testAddRemoveEqual3() { Assert.assertNotNull(this.m_test); IComparableProperty e1 = new Element(); IComparableProperty e2 = new Element(); IComparableProperty e3 = new Element(); // add this.m_test.add(e1); this.m_test.add(e2); this.m_test.add(e3); // remove this.m_test.remove(e1); this.m_test.remove(e2); this.m_test.remove(e3); System.out.println("testAddRemoveEqual3"); System.out.println(this.m_test); Assert.assertEquals("Unexpected remaining elements: " + this.m_test, this.m_test.size(), 0); } /** * Add 1,1,1,1,1, remove them and ensure that no elements remain. * <p> * */ public void testAddRemoveEqual5() { Assert.assertNotNull(this.m_test); IComparableProperty e1 = new Element(); IComparableProperty e2 = new Element(); IComparableProperty e3 = new Element(); IComparableProperty e4 = new Element(); IComparableProperty e5 = new Element(); // add this.m_test.add(e1); this.m_test.add(e2); this.m_test.add(e3); this.m_test.add(e4); this.m_test.add(e5); // remove this.m_test.remove(e1); this.m_test.remove(e2); this.m_test.remove(e3); this.m_test.remove(e4); this.m_test.remove(e5); System.out.println("testAddRemoveEqual5"); System.out.println(this.m_test); Assert.assertEquals("Unexpected remaining elements: " + this.m_test, this.m_test.size(), 0); } /** * Starting 20 Threads that will remove and add inital equal elements (with an * internal comparableProperty of {@link ITrace2D#ZINDEX_MAX}) each 50 times * with arbitrary sleep times. Each Thread will ensure that it's own * {@link IComparableProperty} will be removed from the {@link TreeSetGreedy} * after removing it and assert this by calling the remove call a 2nd time and * looking for the returned boolean. The main Thread will wait until all * Threads have terminated. * * */ public void testMultiThreadingAddRemove() { /** * Helper class that iteratively adds an element, asserts that the operation * was successful and then removes it again and asserts again that removing * was successful. * <p> * * @author <a href="mailto:Achim.Westermann@gmx.de">Achim Westermann</a> * * * @version $Revision: 1.8 $ */ class TreeSetGreedyAddRemover extends Thread { /** Amount of instances to use concurrently. */ public static final int INSTANCES = 30; /** Amount of maximum sleep time between add / remove cycles in ms. */ protected static final int MAX_SLEEP = 2000; /** Element to add / remove. */ private IComparableProperty m_element = new Element(); /** Exception caught. */ protected Exception m_failure = null; /** Amount of add / remove cycles per instance. */ private final int m_iterations = 20; /** Flag to stop this Thread at a checked codepoint. */ protected boolean m_stop = false; /** * Defcon. * <p> */ public TreeSetGreedyAddRemover() { super(); } /** * @see java.lang.Thread#run() */ @Override public void run() { boolean success = false; long sleep; for (int i = 0; i < this.m_iterations && !this.m_stop; i++) { try { System.out.println(this.getName() + " adding: " + this.m_element); success = TestTreeSetGreedy.this.m_test.add(this.m_element); try { Assert.assertTrue("Add operation unsuccessful!", success); } catch (Exception fail) { fail.printStackTrace(System.err); this.m_failure = fail; } sleep = (long) (Math.random() * TreeSetGreedyAddRemover.MAX_SLEEP); System.out.println(this.getName() + " sleeping for : " + sleep + " ms."); Thread.sleep(sleep); System.out.println(this.getName() + " removing: " + this.m_element); success = TestTreeSetGreedy.this.m_test.remove(this.m_element); try { Assert.assertTrue("Remove operation unsuccessful!", success); } catch (Exception fail) { fail.printStackTrace(System.err); this.m_failure = fail; } success = TestTreeSetGreedy.this.m_test.remove(this.m_element); try { // avoid ConcurrentModificationException for toString() of test: Assert.assertFalse("A remove operation of my own removed element was successful! ", success); } catch (Exception fail) { fail.printStackTrace(System.err); this.m_failure = fail; } } catch (InterruptedException e) { Assert.fail("Caught an InterruptedExcetpion: " + e.toString()); } catch (Exception fail) { fail.printStackTrace(System.err); this.m_failure = fail; } } } } TreeSetGreedyAddRemover[] threads = new TreeSetGreedyAddRemover[TreeSetGreedyAddRemover.INSTANCES]; for (int i = 0; i < TreeSetGreedyAddRemover.INSTANCES; i++) { threads[i] = new TreeSetGreedyAddRemover(); } for (int i = 0; i < TreeSetGreedyAddRemover.INSTANCES; i++) { threads[i].setDaemon(true); } for (int i = 0; i < TreeSetGreedyAddRemover.INSTANCES; i++) { threads[i].start(); } boolean allFinished = false; while (!allFinished) { allFinished = true; for (int i = 0; i < TreeSetGreedyAddRemover.INSTANCES; i++) { if (threads[i].m_failure != null) { // clean output: stop threads, wait for them to finish and then fail. Exception failure = threads[i].m_failure; for (int j = 0; j < TreeSetGreedyAddRemover.INSTANCES; j++) { threads[j].m_stop = true; } try { Thread.sleep(TreeSetGreedyAddRemover.MAX_SLEEP + 1000); } catch (InterruptedException e1) { e1.printStackTrace(); } StringWriter trace = new StringWriter(); PrintWriter tracePrint = new PrintWriter(trace); failure.printStackTrace(tracePrint); tracePrint.flush(); tracePrint.close(); Assert.fail(trace.toString()); } allFinished &= !threads[i].isAlive(); } try { Thread.sleep(400); } catch (InterruptedException e) { Assert.fail("Caught an InterruptedExcetpion: " + e.toString()); } } System.out.println("testMultiThreadingAddRemove() finished."); } }