/*
* NOTE: This copyright does *not* cover user programs that use HQ
* program services by normal system calls through the application
* program interfaces provided as part of the Hyperic Plug-in Development
* Kit or the Hyperic Client Development Kit - this is merely considered
* normal use of the program, and does *not* fall under the heading of
* "derived work".
*
* Copyright (C) [2004-2008], Hyperic, Inc.
* This file is part of HQ.
*
* HQ is free software; you can redistribute it and/or modify
* it under the terms version 2 of the GNU General Public License as
* published by the Free Software Foundation. This program 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 General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*/
package org.hyperic.hq.common;
import junit.framework.TestCase;
/**
* Tests the MethodInvocationMetricsGroup class.
*/
public class MethodInvocationMetricsGroupTest extends TestCase {
/**
* Creates an instance.
*
* @param name
*/
public MethodInvocationMetricsGroupTest(String name) {
super(name);
}
/**
* Expect IllegalArgumentException.
*/
public void testIllegalQueueCapacity() throws Exception {
try {
new MethodInvocationMetricsGroup("myGroup", -1);
fail("Expect IllegalArgumentException");
} catch (IllegalArgumentException e) {
// expected outcome
} catch (Exception e) {
fail("Expect IllegalArgumentException instead of: "+e);
}
try {
new MethodInvocationMetricsGroup("myGroup", 0);
fail("Expect IllegalArgumentException");
} catch (IllegalArgumentException e) {
// expected outcome
} catch (Exception e) {
fail("Expect IllegalArgumentException instead of: "+e);
}
}
public void testSetGroupName() {
MethodInvocationMetricsGroup metricsGroup =
new MethodInvocationMetricsGroup(null);
assertEquals("", metricsGroup.getMetricGroupName());
MethodInvocationMetricsGroup newMetricsGroup =
new MethodInvocationMetricsGroup("myGroup");
assertEquals("myGroup", newMetricsGroup.getMetricGroupName());
}
public void testGetMetricsNoInvocationTimesAdded() {
MethodInvocationMetricsGroup metricsGroup =
new MethodInvocationMetricsGroup(null);
assertNoMetrics(metricsGroup);
}
public void testAddInvocationsPriorToFlushBelowQueueCapacity() {
MethodInvocationMetricsGroup metricsGroup =
new MethodInvocationMetricsGroup(null);
assertEquals(MethodInvocationMetricsGroup.DEFAULT_QUEUE_CAPACITY,
metricsGroup.getQueueCapacity());
assertTrue(metricsGroup.getQueueCapacity() > 2);
metricsGroup.addInvocationTime(1);
metricsGroup.addInvocationTime(2);
assertNoMetrics(metricsGroup);
}
public void testAddInvocationsPriorToFlushExceedQueueCapacity() {
int capacity = 3;
MethodInvocationMetricsGroup metricsGroup =
new MethodInvocationMetricsGroup(null, capacity);
assertEquals(capacity, metricsGroup.getQueueCapacity());
metricsGroup.addInvocationTime(0);
metricsGroup.addInvocationTime(1);
metricsGroup.addInvocationTime(2);
// the capacity is now full - the next time we add an invocation
// time there will be metrics
assertNoMetrics(metricsGroup);
metricsGroup.addInvocationTime(3);
assertEquals(4, metricsGroup.getNumberInvocations());
assertEquals(3, metricsGroup.getMaxInvocationTime());
assertEquals(0, metricsGroup.getMinInvocationTime());
assertEquals(1.5, metricsGroup.getAverageInvocationTime(), 0.0);
}
public void testAddInvocationsSynchronously() {
MethodInvocationMetricsGroup metricsGroup =
new MethodInvocationMetricsGroup(null);
metricsGroup.addInvocationTimeSynch(0);
metricsGroup.addInvocationTimeSynch(1);
metricsGroup.addInvocationTimeSynch(2);
metricsGroup.addInvocationTimeSynch(3);
assertEquals(4, metricsGroup.getNumberInvocations());
assertEquals(3, metricsGroup.getMaxInvocationTime());
assertEquals(0, metricsGroup.getMinInvocationTime());
assertEquals(1.5, metricsGroup.getAverageInvocationTime(), 0.0);
}
public void testAddInvocationsFlushExplicitly() {
MethodInvocationMetricsGroup metricsGroup =
new MethodInvocationMetricsGroup(null);
assertTrue(metricsGroup.getQueueCapacity() > 4);
metricsGroup.addInvocationTime(0);
metricsGroup.addInvocationTime(1);
metricsGroup.addInvocationTime(2);
metricsGroup.addInvocationTime(3);
// there should be no metrics before the flush
assertNoMetrics(metricsGroup);
metricsGroup.flush();
assertEquals(4, metricsGroup.getNumberInvocations());
assertEquals(3, metricsGroup.getMaxInvocationTime());
assertEquals(0, metricsGroup.getMinInvocationTime());
assertEquals(1.5, metricsGroup.getAverageInvocationTime(), 0.0);
}
/**
* The min invocation time should always be set initially to the first
* collected invocation time.
*/
public void testMinInvocationTimeInitializedCorrectly() {
MethodInvocationMetricsGroup metricsGroup =
new MethodInvocationMetricsGroup(null);
metricsGroup.addInvocationTime(1000);
metricsGroup.flush();
assertEquals(1, metricsGroup.getNumberInvocations());
assertEquals(1000, metricsGroup.getMaxInvocationTime());
assertEquals(1000, metricsGroup.getMinInvocationTime());
assertEquals(1000.0, metricsGroup.getAverageInvocationTime(), 0.0);
}
public void testMetricCalculations() {
MethodInvocationMetricsGroup metricsGroup =
new MethodInvocationMetricsGroup(null);
metricsGroup.addInvocationTime(4000);
metricsGroup.addInvocationTime(3000);
metricsGroup.addInvocationTime(2000);
metricsGroup.flush();
assertEquals(3, metricsGroup.getNumberInvocations());
assertEquals(4000, metricsGroup.getMaxInvocationTime());
assertEquals(2000, metricsGroup.getMinInvocationTime());
assertEquals(3000.0, metricsGroup.getAverageInvocationTime(), 0.0);
// now add some more invocation times and flush again
metricsGroup.addInvocationTime(5000);
metricsGroup.addInvocationTime(1000);
metricsGroup.flush();
assertEquals(5, metricsGroup.getNumberInvocations());
assertEquals(5000, metricsGroup.getMaxInvocationTime());
assertEquals(1000, metricsGroup.getMinInvocationTime());
assertEquals(3000.0, metricsGroup.getAverageInvocationTime(), 0.0);
}
public void testResetMetrics() {
MethodInvocationMetricsGroup metricsGroup =
new MethodInvocationMetricsGroup(null);
metricsGroup.addInvocationTime(1000);
metricsGroup.flush();
assertEquals(1, metricsGroup.getNumberInvocations());
assertEquals(1000, metricsGroup.getMaxInvocationTime());
assertEquals(1000, metricsGroup.getMinInvocationTime());
assertEquals(1000.0, metricsGroup.getAverageInvocationTime(), 0.0);
// now reset the metrics
metricsGroup.reset();
assertNoMetrics(metricsGroup);
}
/**
* Test the performance of adding method invocation times synchronously,
* evaluating the group metrics immediately.
*/
public void testSynchInsertionPerformance() throws Exception {
MethodInvocationMetricsGroup metricsGroup =
new MethodInvocationMetricsGroup(null);
int numThreads = 10;
int numInserts = 100000;
InsertionThread[] threads = new InsertionThread[numThreads];
for (int i = 0; i < threads.length; i++) {
threads[i] = new InsertionThread(metricsGroup, numInserts, false);
}
long start = System.currentTimeMillis();
for (int i = 0; i < threads.length; i++) {
threads[i].start();
}
for (int i = 0; i < threads.length; i++) {
threads[i].join();
}
System.out.println("total insert time (sync): "+(System.currentTimeMillis()-start));
}
/**
* Test the performance of adding method invocation times asynchronously,
* evaluating the group metrics only on flush.
*/
public void testAsyncInsertionPerformance() throws Exception {
MethodInvocationMetricsGroup metricsGroup =
new MethodInvocationMetricsGroup(null);
int numThreads = 10;
int numInserts = 100000;
InsertionThread[] threads = new InsertionThread[numThreads];
for (int i = 0; i < threads.length; i++) {
threads[i] = new InsertionThread(metricsGroup, numInserts, true);
}
long start = System.currentTimeMillis();
for (int i = 0; i < threads.length; i++) {
threads[i].start();
}
for (int i = 0; i < threads.length; i++) {
threads[i].join();
}
System.out.println("total insert time (async): "+(System.currentTimeMillis()-start));
}
private static class InsertionThread extends Thread {
private final MethodInvocationMetricsGroup _metricsGroup;
private final int _numInserts;
private final boolean _async;
public InsertionThread(MethodInvocationMetricsGroup metricsGroup,
int numInserts,
boolean async) {
super("Insertion Thread");
setDaemon(true);
_metricsGroup = metricsGroup;
_numInserts = numInserts;
_async = async;
}
public void run() {
for (int i = 0; i < _numInserts; i++) {
if (_async) {
_metricsGroup.addInvocationTime(i);
} else {
_metricsGroup.addInvocationTimeSynch(i);
}
}
if (_async) {
_metricsGroup.flush();
}
}
}
private void assertNoMetrics(MethodInvocationMetricsGroup metricsGroup) {
assertEquals(0, metricsGroup.getNumberInvocations());
assertEquals(0, metricsGroup.getMaxInvocationTime());
assertEquals(0, metricsGroup.getMinInvocationTime());
assertTrue(Double.isNaN(metricsGroup.getAverageInvocationTime()));
}
}