blob: 49cfa89fd709449d40638862b29acf24167d70df [file] [log] [blame]
Jian Li72315152015-12-10 17:20:43 -08001/*
2 * Copyright 2014-2015 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.rest;
17
18import com.codahale.metrics.Counter;
19import com.codahale.metrics.Meter;
20import com.codahale.metrics.Metric;
Jian Li162149f2015-12-14 11:39:54 -080021import com.codahale.metrics.Timer;
Jian Li72315152015-12-10 17:20:43 -080022import com.eclipsesource.json.JsonArray;
23import com.eclipsesource.json.JsonObject;
24import com.google.common.collect.ImmutableMap;
25import com.sun.jersey.api.client.WebResource;
Jian Li162149f2015-12-14 11:39:54 -080026import org.hamcrest.Description;
27import org.hamcrest.TypeSafeMatcher;
Jian Li72315152015-12-10 17:20:43 -080028import org.junit.After;
29import org.junit.Before;
30import org.junit.Test;
31import org.onlab.metrics.MetricsService;
32import org.onlab.osgi.ServiceDirectory;
33import org.onlab.osgi.TestServiceDirectory;
34import org.onlab.rest.BaseResource;
35import org.onosproject.codec.CodecService;
36import org.onosproject.codec.impl.CodecManager;
37
Jian Li162149f2015-12-14 11:39:54 -080038import java.util.concurrent.TimeUnit;
39
Jian Li72315152015-12-10 17:20:43 -080040import static org.easymock.EasyMock.createMock;
41import static org.easymock.EasyMock.expect;
42import static org.easymock.EasyMock.replay;
43import static org.easymock.EasyMock.verify;
44import static org.hamcrest.Matchers.containsString;
45import static org.hamcrest.Matchers.is;
46import static org.hamcrest.Matchers.notNullValue;
47import static org.junit.Assert.assertThat;
Jian Li162149f2015-12-14 11:39:54 -080048import static org.junit.Assert.assertTrue;
Jian Li72315152015-12-10 17:20:43 -080049
50/**
51 * Unit tests for Metrics REST APIs.
52 */
53public class MetricsResourceTest extends ResourceTest {
54 MetricsService mockMetricsService;
55
56 /**
57 * Initializes test mocks and environment.
58 */
59 @Before
60 public void setUpTest() {
61 mockMetricsService = createMock(MetricsService.class);
62
63 // Register the services needed for the test
64 final CodecManager codecService = new CodecManager();
65 codecService.activate();
66 ServiceDirectory testDirectory =
67 new TestServiceDirectory()
68 .add(MetricsService.class, mockMetricsService)
69 .add(CodecService.class, codecService);
70 BaseResource.setServiceDirectory(testDirectory);
71 }
72
73 /**
74 * Verifies mocks.
75 */
76 @After
77 public void tearDownTest() {
78 verify(mockMetricsService);
79 }
80
81 /**
Jian Li162149f2015-12-14 11:39:54 -080082 * Tests GetAllMetrics method.
Jian Li72315152015-12-10 17:20:43 -080083 */
84 @Test
Jian Li162149f2015-12-14 11:39:54 -080085 public void testGetAllMetrics() {
Jian Li72315152015-12-10 17:20:43 -080086 Counter onosCounter = new Counter();
87 onosCounter.inc();
88
89 Meter onosMeter = new Meter();
90 onosMeter.mark();
91
Jian Li162149f2015-12-14 11:39:54 -080092 Timer onosTimer = new Timer();
93 onosTimer.update(1, TimeUnit.MILLISECONDS);
94
Jian Li72315152015-12-10 17:20:43 -080095 ImmutableMap<String, Metric> metrics =
96 new ImmutableMap.Builder<String, Metric>()
97 .put("onosCounter", onosCounter)
98 .put("onosMeter", onosMeter)
Jian Li162149f2015-12-14 11:39:54 -080099 .put("onosTimer", onosTimer)
Jian Li72315152015-12-10 17:20:43 -0800100 .build();
101
102 expect(mockMetricsService.getMetrics())
103 .andReturn(metrics)
104 .anyTimes();
105
106 replay(mockMetricsService);
107
108 WebResource rs = resource();
109 String response = rs.path("metrics").get(String.class);
110 assertThat(response, containsString("{\"metrics\":["));
111
112 JsonObject result = JsonObject.readFrom(response);
113 assertThat(result, notNullValue());
114
115 JsonArray jsonMetrics = result.get("metrics").asArray();
116 assertThat(jsonMetrics, notNullValue());
Jian Li162149f2015-12-14 11:39:54 -0800117 assertThat(jsonMetrics.size(), is(3));
118
119 assertTrue(matchesMetric(metrics.get("onosCounter")).matchesSafely(jsonMetrics.get(0).asObject()));
120 assertTrue(matchesMetric(metrics.get("onosMeter")).matchesSafely(jsonMetrics.get(1).asObject()));
121 assertTrue(matchesMetric(metrics.get("onosTimer")).matchesSafely(jsonMetrics.get(2).asObject()));
122 }
123
124 /**
Jian Li64dd8892015-12-30 14:13:18 -0800125 * Hamcrest matcher to check that a metric representation in JSON matches
126 * the actual metric.
Jian Li162149f2015-12-14 11:39:54 -0800127 */
128 public static class MetricJsonMatcher extends TypeSafeMatcher<JsonObject> {
129 private final Metric metric;
130 private String reason = "";
131
132 public MetricJsonMatcher(Metric metricValue) {
133 this.metric = metricValue;
134 }
135
136 @Override
137 public boolean matchesSafely(JsonObject jsonObject) {
138
139 JsonObject jsonMetric = jsonObject.get("metric").asObject();
140 JsonObject jsonCounter;
141 JsonObject jsonMeter;
142 JsonObject jsonTimer;
143 Counter counter;
144 Meter meter;
145 Timer timer;
146
147 // check counter metric
148 if (jsonMetric.get("counter") != null) {
149 jsonCounter = jsonMetric.get("counter").asObject();
150 counter = (Counter) metric;
151 if (jsonCounter.get("counter").asLong() != counter.getCount()) {
152 reason = "counter " + counter.getCount();
153 return false;
154 }
155 }
156
157 // check meter metric
158 if (jsonMetric.get("meter") != null) {
159 jsonMeter = jsonMetric.get("meter").asObject();
160 meter = (Meter) metric;
161
162 if (jsonMeter.get("counter").asLong() != meter.getCount()) {
163 reason = "counter " + meter.getCount();
164 return false;
165 }
166
167 if (jsonMeter.get("1_min_rate").asDouble() != meter.getOneMinuteRate()) {
168 reason = "1 minute rate " + meter.getOneMinuteRate();
169 return false;
170 }
171
172 if (jsonMeter.get("5_min_rate").asDouble() != meter.getOneMinuteRate()) {
173 reason = "5 minute rate " + meter.getFiveMinuteRate();
174 return false;
175 }
176
177 if (jsonMeter.get("15_min_rate").asDouble() != meter.getFifteenMinuteRate()) {
178 reason = "15 minute rate " + meter.getFifteenMinuteRate();
179 return false;
180 }
181 }
182
183 if (jsonMetric.get("timer") != null) {
184 jsonTimer = jsonMetric.get("timer").asObject();
185 timer = (Timer) metric;
186
187 if (jsonTimer.get("counter").asLong() != timer.getCount()) {
188 reason = "counter " + timer.getCount();
189 return false;
190 }
191
192 if (jsonTimer.get("1_min_rate").asDouble() != timer.getOneMinuteRate()) {
193 reason = "1 minute rate " + timer.getOneMinuteRate();
194 return false;
195 }
196
197 if (jsonTimer.get("5_min_rate").asDouble() != timer.getOneMinuteRate()) {
198 reason = "5 minute rate " + timer.getFiveMinuteRate();
199 return false;
200 }
201
202 if (jsonTimer.get("15_min_rate").asDouble() != timer.getFifteenMinuteRate()) {
203 reason = "15 minute rate " + timer.getFifteenMinuteRate();
204 return false;
205 }
206
207 if (jsonTimer.get("mean").asDouble() != nanoToMs(timer.getSnapshot().getMean())) {
208 reason = "mean " + timer.getSnapshot().getMean();
209 return false;
210 }
211
212 if (jsonTimer.get("min").asDouble() != nanoToMs(timer.getSnapshot().getMin())) {
213 reason = "min " + timer.getSnapshot().getMin();
214 return false;
215 }
216
217 if (jsonTimer.get("max").asDouble() != nanoToMs(timer.getSnapshot().getMax())) {
218 reason = "max " + timer.getSnapshot().getMax();
219 return false;
220 }
221
222 if (jsonTimer.get("stddev").asDouble() != nanoToMs(timer.getSnapshot().getStdDev())) {
223 reason = "stddev " + timer.getSnapshot().getStdDev();
224 return false;
225 }
226 }
227
228 return true;
229 }
230
231 @Override
232 public void describeTo(Description description) {
233 description.appendText(reason);
234 }
235
236 private double nanoToMs(double nano) {
237 return nano / 1_000_000D;
238 }
239 }
240
241 /**
242 * Factory to allocate an metric matcher.
243 *
244 * @param metric metric object we are looking for
245 * @return matcher
246 */
247 private static MetricJsonMatcher matchesMetric(Metric metric) {
248 return new MetricJsonMatcher(metric);
Jian Li72315152015-12-10 17:20:43 -0800249 }
250}