blob: e6670b400fc0f01f854915d371658b4d499096e2 [file] [log] [blame]
package net.onrc.onos.api.rest;
import com.codahale.metrics.Metric;
import com.codahale.metrics.MetricSet;
import com.codahale.metrics.Reservoir;
import com.codahale.metrics.SlidingWindowReservoir;
import com.codahale.metrics.Timer;
import net.onrc.onos.core.intent.runtime.PathCalcRuntimeModule;
import net.onrc.onos.core.metrics.OnosMetrics;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.restlet.resource.ClientResource;
import java.util.HashMap;
import java.util.Map;
import static com.codahale.metrics.MetricRegistry.name;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.both;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.lessThan;
import static org.hamcrest.Matchers.notNullValue;
/**
* Unit tests for REST APIs for Timer Metrics.
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest(PathCalcRuntimeModule.class)
public class TestRestMetricsTimers extends TestRestMetrics {
/**
* Create the web server and mocks required for
* all of the tests.
*/
@Before
@SuppressWarnings("ununsed")
public void beforeTest() {
setRestPort(generateRandomPort());
setUp();
}
// Test data objects for Timers
// timer1 will be called 3 times
private static final String TIMER1_NAME = name(TestRestMetricsTimers.class,
"timer1");
private static final int TIMER1_COUNT = 3;
// timer1 will be called 10 times
private static final String TIMER2_NAME = name(TestRestMetricsTimers.class,
"timer2");
private static final int TIMER2_COUNT = 10;
private static final int RESERVOIR_SIZE = 100;
private Reservoir reservoir = new SlidingWindowReservoir(RESERVOIR_SIZE);
private final Timer timer1 = new Timer(reservoir, mockClock);
private final Timer timer2 = new Timer(reservoir, mockClock);
/**
* Fill in test data in the Timer objects.
*/
private void fillTimers() {
// The mock clock will simulate ticks at MOCK_CLOCK_MILISECONDS_PER_TICK
// Each timer.time(), context.stop() pair will elapse
// MOCK_CLOCK_MILISECONDS_PER_TICK (currently 50 milliseconds)
// Initialize timer1 - 3 ticks, 50 milliseconds (simulted) apart
for (int i = 0; i < TIMER1_COUNT; i++) {
final Timer.Context context = timer1.time();
context.stop();
}
// Initialize timer2 - 10 ticks, 50 milliseconds (simulated) apart
for (int i = 0; i < TIMER2_COUNT; i++) {
final Timer.Context context = timer2.time();
context.stop();
}
// add the two timers to the registry so the REST APIs will pick them
// up
final MetricSet timerSet = new MetricSet() {
@Override
public Map<String, Metric> getMetrics() {
final Map<String, Metric> timers = new HashMap<>();
timers.put(TIMER1_NAME, timer1);
timers.put(TIMER2_NAME, timer2);
return timers;
}
};
OnosMetrics.getMetricsRegistry().registerAll(timerSet);
}
/**
* Check that the time values for a JSON Timer object are within the
* allowed range.
*
* @param timer JSON Timer object
* @param timeValue expected time value
* @throws JSONException if any of the JSON operations fail
*/
private void assertThatTimesAreInRange(JSONObject timer, int timeValue)
throws JSONException {
final double timerMax = timer.getDouble("max");
assertThat((int) timerMax,
is(both(greaterThanOrEqualTo(timeValue)).
and(lessThan(timeValue + 5))));
final double timerMin = timer.getDouble("min");
assertThat((int) timerMin,
is(both(greaterThanOrEqualTo(timeValue)).
and(lessThan(timeValue + 5))));
final double timerP99 = timer.getDouble("p99");
assertThat((int) timerP99,
is(both(greaterThanOrEqualTo(timeValue)).
and(lessThan(timeValue + 5))));
final double timerP999 = timer.getDouble("p999");
assertThat((int) timerP999,
is(both(greaterThanOrEqualTo(timeValue)).
and(lessThan(timeValue + 5))));
}
/**
* Remove anything that will interfere with the next test running correctly.
* Shuts down the test REST web server and removes the mocks.
*/
@After
@SuppressWarnings("unused")
public void afterTest() {
tearDown();
}
/**
* Unit test for the REST APIs for Metrics Timers.
*
* @throws JSONException if any of the JSON processing fails.
*/
@Test
public void testTimers() throws JSONException {
// Make some test data
fillTimers();
// Read the metrics from the REST API for the test data
final ClientResource client = new ClientResource(getBaseRestMetricsUrl());
final JSONObject metrics = getJSONObject(client);
assertThat(metrics.length(), is(equalTo(5)));
// There should be 2 timers
final JSONArray timers = metrics.getJSONArray("timers");
assertThat(timers, is(notNullValue()));
assertThat(timers.length(), is(2));
// There should be no historgramss, gauges, meters or counters
checkEmptyLists(metrics, "histograms", "gauges", "meters", "counters");
// Check the values for timer 1
final JSONObject timer1Values = timers.getJSONObject(0);
assertThat(timer1Values, is(notNullValue()));
final String timer1Name = timer1Values.getString("name");
assertThat(timer1Name, is(notNullValue()));
assertThat(timer1Name, is(equalTo(TIMER1_NAME)));
final JSONObject timer1TimerObject = timer1Values.getJSONObject("timer");
assertThat(timer1TimerObject, is(notNullValue()));
final int timer1Count = timer1TimerObject.getInt("count");
assertThat(timer1Count, is(equalTo(TIMER1_COUNT)));
final String timer1DurationUnits = timer1TimerObject.getString("duration_units");
assertThat(timer1DurationUnits, is(equalTo("milliseconds")));
assertThatTimesAreInRange(timer1TimerObject,
MOCK_CLOCK_MILISECONDS_PER_TICK);
// Check the values for timer 2
final JSONObject timer2Values = timers.getJSONObject(1);
assertThat(timer2Values, is(notNullValue()));
final String timer2Name = timer2Values.getString("name");
assertThat(timer2Name, is(notNullValue()));
assertThat(timer2Name, is(equalTo(TIMER2_NAME)));
final JSONObject timer2TimerObject = timer2Values.getJSONObject("timer");
assertThat(timer2TimerObject, is(notNullValue()));
final int timer2Count = timer2TimerObject.getInt("count");
assertThat(timer2Count, is(equalTo(TIMER2_COUNT)));
final String timer2DurationUnits = timer2TimerObject.getString("duration_units");
assertThat(timer2DurationUnits, is(equalTo("milliseconds")));
assertThatTimesAreInRange(timer2TimerObject,
MOCK_CLOCK_MILISECONDS_PER_TICK);
}
}