blob: dd8cf8ce549c3543db0db4e85707ca019c987cc7 [file] [log] [blame]
Ray Milkey26921af2014-06-30 16:27:40 -07001package net.onrc.onos.api.rest;
2
Ray Milkey26921af2014-06-30 16:27:40 -07003import com.codahale.metrics.Reservoir;
4import com.codahale.metrics.SlidingWindowReservoir;
5import com.codahale.metrics.Timer;
6import net.onrc.onos.core.intent.runtime.PathCalcRuntimeModule;
7import net.onrc.onos.core.metrics.OnosMetrics;
8import org.json.JSONArray;
9import org.json.JSONException;
10import org.json.JSONObject;
11import org.junit.After;
12import org.junit.Before;
13import org.junit.Test;
14import org.junit.runner.RunWith;
15import org.powermock.core.classloader.annotations.PrepareForTest;
16import org.powermock.modules.junit4.PowerMockRunner;
17import org.restlet.resource.ClientResource;
18
Ray Milkey26921af2014-06-30 16:27:40 -070019import static org.hamcrest.MatcherAssert.assertThat;
20import static org.hamcrest.Matchers.both;
21import static org.hamcrest.Matchers.equalTo;
22import static org.hamcrest.Matchers.greaterThanOrEqualTo;
23import static org.hamcrest.Matchers.is;
24import static org.hamcrest.Matchers.lessThan;
25import static org.hamcrest.Matchers.notNullValue;
26
27/**
28 * Unit tests for REST APIs for Timer Metrics.
29 */
30
31@RunWith(PowerMockRunner.class)
32@PrepareForTest(PathCalcRuntimeModule.class)
33public class TestRestMetricsTimers extends TestRestMetrics {
34
35 /**
36 * Create the web server and mocks required for
37 * all of the tests.
38 */
39 @Before
40 @SuppressWarnings("ununsed")
41 public void beforeTest() {
42 setRestPort(generateRandomPort());
43 setUp();
44 }
45
46 // Test data objects for Timers
47
Ray Milkey71cd2c82014-07-16 15:02:33 -070048 private static final OnosMetrics.MetricsComponent COMPONENT =
49 OnosMetrics.registerComponent("MetricsUnitTests");
50 private static final OnosMetrics.MetricsFeature FEATURE =
51 COMPONENT.registerFeature("Timers");
52
Ray Milkey26921af2014-06-30 16:27:40 -070053 // timer1 will be called 3 times
Ray Milkey49d67be2014-07-10 13:47:01 -070054 private static final String TIMER1_NAME = "timer1";
55 private static final String TIMER1_FULL_NAME =
Ray Milkey71cd2c82014-07-16 15:02:33 -070056 OnosMetrics.generateName(COMPONENT,
57 FEATURE,
Ray Milkey49d67be2014-07-10 13:47:01 -070058 TIMER1_NAME);
Ray Milkey26921af2014-06-30 16:27:40 -070059 private static final int TIMER1_COUNT = 3;
60
Ray Milkey49d67be2014-07-10 13:47:01 -070061 // timer2 will be called 10 times
62 private static final String TIMER2_NAME = "timer2";
63 private static final String TIMER2_FULL_NAME =
Ray Milkey71cd2c82014-07-16 15:02:33 -070064 OnosMetrics.generateName(COMPONENT,
65 FEATURE,
66 TIMER2_NAME);
Ray Milkey26921af2014-06-30 16:27:40 -070067 private static final int TIMER2_COUNT = 10;
68
69 private static final int RESERVOIR_SIZE = 100;
70 private Reservoir reservoir = new SlidingWindowReservoir(RESERVOIR_SIZE);
71
72 private final Timer timer1 = new Timer(reservoir, mockClock);
73 private final Timer timer2 = new Timer(reservoir, mockClock);
74
75 /**
76 * Fill in test data in the Timer objects.
77 */
78 private void fillTimers() {
79 // The mock clock will simulate ticks at MOCK_CLOCK_MILISECONDS_PER_TICK
80 // Each timer.time(), context.stop() pair will elapse
81 // MOCK_CLOCK_MILISECONDS_PER_TICK (currently 50 milliseconds)
82
83 // Initialize timer1 - 3 ticks, 50 milliseconds (simulted) apart
84 for (int i = 0; i < TIMER1_COUNT; i++) {
85 final Timer.Context context = timer1.time();
86 context.stop();
87 }
88
89 // Initialize timer2 - 10 ticks, 50 milliseconds (simulated) apart
90 for (int i = 0; i < TIMER2_COUNT; i++) {
91 final Timer.Context context = timer2.time();
92 context.stop();
93 }
94
95 // add the two timers to the registry so the REST APIs will pick them
96 // up
Ray Milkey49d67be2014-07-10 13:47:01 -070097
Ray Milkey71cd2c82014-07-16 15:02:33 -070098 OnosMetrics.registerMetric(COMPONENT,
99 FEATURE,
Ray Milkey49d67be2014-07-10 13:47:01 -0700100 TIMER1_NAME,
101 timer1);
102
Ray Milkey71cd2c82014-07-16 15:02:33 -0700103 OnosMetrics.registerMetric(COMPONENT,
104 FEATURE,
Ray Milkey49d67be2014-07-10 13:47:01 -0700105 TIMER2_NAME,
106 timer2);
Ray Milkey26921af2014-06-30 16:27:40 -0700107 }
108
109 /**
110 * Check that the time values for a JSON Timer object are within the
111 * allowed range.
112 *
113 * @param timer JSON Timer object
114 * @param timeValue expected time value
115 * @throws JSONException if any of the JSON operations fail
116 */
117 private void assertThatTimesAreInRange(JSONObject timer, int timeValue)
118 throws JSONException {
119
120 final double timerMax = timer.getDouble("max");
121 assertThat((int) timerMax,
122 is(both(greaterThanOrEqualTo(timeValue)).
123 and(lessThan(timeValue + 5))));
124
125 final double timerMin = timer.getDouble("min");
126 assertThat((int) timerMin,
127 is(both(greaterThanOrEqualTo(timeValue)).
128 and(lessThan(timeValue + 5))));
129
130 final double timerP99 = timer.getDouble("p99");
131 assertThat((int) timerP99,
132 is(both(greaterThanOrEqualTo(timeValue)).
133 and(lessThan(timeValue + 5))));
134
135 final double timerP999 = timer.getDouble("p999");
136 assertThat((int) timerP999,
137 is(both(greaterThanOrEqualTo(timeValue)).
138 and(lessThan(timeValue + 5))));
139 }
140
141 /**
142 * Remove anything that will interfere with the next test running correctly.
143 * Shuts down the test REST web server and removes the mocks.
144 */
145 @After
146 @SuppressWarnings("unused")
147 public void afterTest() {
148 tearDown();
149 }
150
151 /**
152 * Unit test for the REST APIs for Metrics Timers.
153 *
154 * @throws JSONException if any of the JSON processing fails.
155 */
156 @Test
157 public void testTimers() throws JSONException {
158 // Make some test data
159 fillTimers();
160
161 // Read the metrics from the REST API for the test data
162 final ClientResource client = new ClientResource(getBaseRestMetricsUrl());
163
164 final JSONObject metrics = getJSONObject(client);
165 assertThat(metrics.length(), is(equalTo(5)));
166
167 // There should be 2 timers
168 final JSONArray timers = metrics.getJSONArray("timers");
169 assertThat(timers, is(notNullValue()));
170 assertThat(timers.length(), is(2));
171
172
173 // There should be no historgramss, gauges, meters or counters
174 checkEmptyLists(metrics, "histograms", "gauges", "meters", "counters");
175
176 // Check the values for timer 1
177 final JSONObject timer1Values = timers.getJSONObject(0);
178 assertThat(timer1Values, is(notNullValue()));
179
180 final String timer1Name = timer1Values.getString("name");
181 assertThat(timer1Name, is(notNullValue()));
Ray Milkey49d67be2014-07-10 13:47:01 -0700182 assertThat(timer1Name, is(equalTo(TIMER1_FULL_NAME)));
Ray Milkey26921af2014-06-30 16:27:40 -0700183
184 final JSONObject timer1TimerObject = timer1Values.getJSONObject("timer");
185 assertThat(timer1TimerObject, is(notNullValue()));
186
187 final int timer1Count = timer1TimerObject.getInt("count");
188 assertThat(timer1Count, is(equalTo(TIMER1_COUNT)));
189
190 final String timer1DurationUnits = timer1TimerObject.getString("duration_units");
191 assertThat(timer1DurationUnits, is(equalTo("milliseconds")));
192
193 assertThatTimesAreInRange(timer1TimerObject,
194 MOCK_CLOCK_MILISECONDS_PER_TICK);
195
196 // Check the values for timer 2
197 final JSONObject timer2Values = timers.getJSONObject(1);
198 assertThat(timer2Values, is(notNullValue()));
199
200 final String timer2Name = timer2Values.getString("name");
201 assertThat(timer2Name, is(notNullValue()));
Ray Milkey49d67be2014-07-10 13:47:01 -0700202 assertThat(timer2Name, is(equalTo(TIMER2_FULL_NAME)));
Ray Milkey26921af2014-06-30 16:27:40 -0700203
204 final JSONObject timer2TimerObject = timer2Values.getJSONObject("timer");
205 assertThat(timer2TimerObject, is(notNullValue()));
206
207 final int timer2Count = timer2TimerObject.getInt("count");
208 assertThat(timer2Count, is(equalTo(TIMER2_COUNT)));
209
210 final String timer2DurationUnits = timer2TimerObject.getString("duration_units");
211 assertThat(timer2DurationUnits, is(equalTo("milliseconds")));
212
213 assertThatTimesAreInRange(timer2TimerObject,
214 MOCK_CLOCK_MILISECONDS_PER_TICK);
215 }
216
217}