/* * * Copyright (c) void.fm * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this list * of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * Neither the name void.fm nor the names of its contributors may be * used to endorse or promote products derived from this software without specific * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * */ package etm.core.monitor; import etm.core.aggregation.Aggregate; import etm.core.aggregation.ExecutionAggregate; import etm.core.configuration.EtmMonitorFactory; import etm.core.renderer.MeasurementRenderer; import junit.framework.TestCase; import etm.core.TestHelper; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * Concurrency tests for nested monitor. * * @author void.fm * @version $Revision$ */ public class ConcurrentNestedMonitorTest extends TestCase { protected EtmMonitor monitor; private final LockObject lock = new LockObject(); private final List allPoints = new ArrayList(); /** * tests two points with multiple threads. * * @throws Exception Unexpected exception. */ public void testThreadedTwoPoint() throws Exception { assertNotNull(monitor); final int testSize = 50; final int iterations = 100; final String testPointGroup1 = "group1"; final String testPointGroup2 = "group2"; Runner[] runnerGroup1 = new Runner[testSize]; Runner[] runnerGroup2 = new Runner[testSize]; for (int i = 0; i < testSize; i++) { runnerGroup1[i] = new Runner(testPointGroup1, iterations); runnerGroup2[i] = new Runner(testPointGroup2, iterations); } for (int i = 0; i < testSize; i++) { runnerGroup1[i].start(); runnerGroup2[i].start(); } do { synchronized (lock) { lock.wait(); if (!lock.isRunning()) { break; } } } while (true); monitor.aggregate(); final ExecutionAggregate group1 = new ExecutionAggregate(testPointGroup1); final ExecutionAggregate group2 = new ExecutionAggregate(testPointGroup2); final ExecutionAggregate nested1 = new ExecutionAggregate("nested" + testPointGroup1); final ExecutionAggregate nested2 = new ExecutionAggregate("nested" + testPointGroup2); for (int i = 0; i < allPoints.size(); i++) { EtmPoint point = (EtmPoint) allPoints.get(i); if (point.getName().equals(testPointGroup1)) { group1.addTransaction(point); } else if (point.getName().equals(testPointGroup2)) { group2.addTransaction(point); } else if (point.getName().equals("nested" + testPointGroup1)) { nested1.addTransaction(point); } else if (point.getName().equals("nested" + testPointGroup2)) { nested2.addTransaction(point); } else { fail("Unknown point " + point.getName()); } } monitor.render(new MeasurementRenderer() { public void render(Map points) { assertNotNull(points); assertTrue(points.size() == 2); assertEquals(4 * testSize * iterations, new TestHelper().countExecutions(points)); // check group 1 ExecutionAggregate aggregate = (ExecutionAggregate) points.get(testPointGroup1); assertNotNull(aggregate); assertEquals(testPointGroup1, aggregate.getName()); assertEquals(testSize * iterations, aggregate.getMeasurements()); assertEquals(group1.getTotal(), aggregate.getTotal(), 0.000001); assertEquals(group1.getMin(), aggregate.getMin(), 0.000001); assertEquals(group1.getMax(), aggregate.getMax(), 0.000001); assertTrue(aggregate.hasChilds()); Map childs1 = aggregate.getChilds(); Aggregate aggregateChild1 = (Aggregate) childs1.get("nested" + testPointGroup1); assertNotNull(aggregateChild1); assertEquals(nested1.getName(), aggregateChild1.getName()); assertEquals(testSize * iterations, aggregateChild1.getMeasurements()); assertEquals(nested1.getTotal(), aggregateChild1.getTotal(), 0.000001); assertEquals(nested1.getMin(), aggregateChild1.getMin(), 0.000001); assertEquals(nested1.getMax(), aggregateChild1.getMax(), 0.000001); // check group 2 ExecutionAggregate aggregate2 = (ExecutionAggregate) points.get(testPointGroup2); assertNotNull(aggregate2); assertEquals(testPointGroup2, aggregate2.getName()); assertEquals(testSize * iterations, aggregate2.getMeasurements()); assertEquals(group2.getTotal(), aggregate2.getTotal(), 0.000001); assertEquals(group2.getMin(), aggregate2.getMin(), 0.000001); assertEquals(group2.getMax(), aggregate2.getMax(), 0.000001); assertTrue(aggregate2.hasChilds()); Map childs2 = aggregate2.getChilds(); Aggregate aggregateChild2 = (Aggregate) childs2.get("nested" + testPointGroup2); assertNotNull(aggregateChild2); assertEquals(nested2.getName(), aggregateChild2.getName()); assertEquals(testSize * iterations, aggregateChild2.getMeasurements()); assertEquals(nested2.getTotal(), aggregateChild2.getTotal(), 0.000001); assertEquals(nested2.getMin(), aggregateChild2.getMin(), 0.000001); assertEquals(nested2.getMax(), aggregateChild2.getMax(), 0.000001); } }); } protected void tearDown() throws Exception { monitor.stop(); monitor.reset(); monitor = null; } protected void setUp() throws Exception { monitor = new NestedMonitor(EtmMonitorFactory.bestAvailableTimer()); monitor.start(); } class Runner extends Thread { List list = new ArrayList(); private String testPointName; private int runs; public Runner(String aTestPointName, int aRuns) { testPointName = aTestPointName; runs = aRuns; } public void run() { lock.increase(); try { while (runs > 0) { final EtmPoint point = monitor.createPoint(testPointName); Thread.sleep(1); final EtmPoint nested = monitor.createPoint("nested" + testPointName); Thread.sleep(1); nested.collect(); point.collect(); list.add(nested); list.add(point); runs--; } } catch (InterruptedException e) { // ignored } synchronized (allPoints) { allPoints.addAll(list); } synchronized (lock) { lock.decrease(); lock.notifyAll(); } } } class LockObject { private int instances; public synchronized void increase() { instances++; } public synchronized void decrease() { instances--; } public synchronized boolean isRunning() { return instances > 0; } } }