blob: 256e3c0e42e61585e4fc5775b5df5dc307c7331d [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 Li80cfe452016-01-14 16:04:58 -080022import com.eclipsesource.json.Json;
Jian Li72315152015-12-10 17:20:43 -080023import com.eclipsesource.json.JsonArray;
24import com.eclipsesource.json.JsonObject;
25import com.google.common.collect.ImmutableMap;
26import com.sun.jersey.api.client.WebResource;
Jian Li162149f2015-12-14 11:39:54 -080027import org.hamcrest.Description;
28import org.hamcrest.TypeSafeMatcher;
Jian Li72315152015-12-10 17:20:43 -080029import org.junit.After;
30import org.junit.Before;
31import org.junit.Test;
32import org.onlab.metrics.MetricsService;
33import org.onlab.osgi.ServiceDirectory;
34import org.onlab.osgi.TestServiceDirectory;
35import org.onlab.rest.BaseResource;
36import org.onosproject.codec.CodecService;
37import org.onosproject.codec.impl.CodecManager;
38
Jian Li162149f2015-12-14 11:39:54 -080039import java.util.concurrent.TimeUnit;
40
Jian Li72315152015-12-10 17:20:43 -080041import static org.easymock.EasyMock.createMock;
42import static org.easymock.EasyMock.expect;
43import static org.easymock.EasyMock.replay;
44import static org.easymock.EasyMock.verify;
45import static org.hamcrest.Matchers.containsString;
46import static org.hamcrest.Matchers.is;
47import static org.hamcrest.Matchers.notNullValue;
48import static org.junit.Assert.assertThat;
Jian Li162149f2015-12-14 11:39:54 -080049import static org.junit.Assert.assertTrue;
Jian Li72315152015-12-10 17:20:43 -080050
51/**
52 * Unit tests for Metrics REST APIs.
53 */
54public class MetricsResourceTest extends ResourceTest {
55 MetricsService mockMetricsService;
56
57 /**
58 * Initializes test mocks and environment.
59 */
60 @Before
61 public void setUpTest() {
62 mockMetricsService = createMock(MetricsService.class);
63
64 // Register the services needed for the test
65 final CodecManager codecService = new CodecManager();
66 codecService.activate();
67 ServiceDirectory testDirectory =
68 new TestServiceDirectory()
69 .add(MetricsService.class, mockMetricsService)
70 .add(CodecService.class, codecService);
71 BaseResource.setServiceDirectory(testDirectory);
72 }
73
74 /**
75 * Verifies mocks.
76 */
77 @After
78 public void tearDownTest() {
79 verify(mockMetricsService);
80 }
81
82 /**
Jian Li162149f2015-12-14 11:39:54 -080083 * Tests GetAllMetrics method.
Jian Li72315152015-12-10 17:20:43 -080084 */
85 @Test
Jian Li162149f2015-12-14 11:39:54 -080086 public void testGetAllMetrics() {
Jian Li72315152015-12-10 17:20:43 -080087 Counter onosCounter = new Counter();
88 onosCounter.inc();
89
90 Meter onosMeter = new Meter();
91 onosMeter.mark();
92
Jian Li162149f2015-12-14 11:39:54 -080093 Timer onosTimer = new Timer();
94 onosTimer.update(1, TimeUnit.MILLISECONDS);
95
Jian Li72315152015-12-10 17:20:43 -080096 ImmutableMap<String, Metric> metrics =
97 new ImmutableMap.Builder<String, Metric>()
98 .put("onosCounter", onosCounter)
99 .put("onosMeter", onosMeter)
Jian Li162149f2015-12-14 11:39:54 -0800100 .put("onosTimer", onosTimer)
Jian Li72315152015-12-10 17:20:43 -0800101 .build();
102
103 expect(mockMetricsService.getMetrics())
104 .andReturn(metrics)
105 .anyTimes();
106
107 replay(mockMetricsService);
108
109 WebResource rs = resource();
110 String response = rs.path("metrics").get(String.class);
111 assertThat(response, containsString("{\"metrics\":["));
112
Jian Li80cfe452016-01-14 16:04:58 -0800113 JsonObject result = Json.parse(response).asObject();
Jian Li72315152015-12-10 17:20:43 -0800114 assertThat(result, notNullValue());
115
116 JsonArray jsonMetrics = result.get("metrics").asArray();
117 assertThat(jsonMetrics, notNullValue());
Jian Li162149f2015-12-14 11:39:54 -0800118 assertThat(jsonMetrics.size(), is(3));
119
120 assertTrue(matchesMetric(metrics.get("onosCounter")).matchesSafely(jsonMetrics.get(0).asObject()));
121 assertTrue(matchesMetric(metrics.get("onosMeter")).matchesSafely(jsonMetrics.get(1).asObject()));
122 assertTrue(matchesMetric(metrics.get("onosTimer")).matchesSafely(jsonMetrics.get(2).asObject()));
123 }
124
125 /**
Jian Li64dd8892015-12-30 14:13:18 -0800126 * Hamcrest matcher to check that a metric representation in JSON matches
127 * the actual metric.
Jian Li162149f2015-12-14 11:39:54 -0800128 */
129 public static class MetricJsonMatcher extends TypeSafeMatcher<JsonObject> {
130 private final Metric metric;
131 private String reason = "";
132
133 public MetricJsonMatcher(Metric metricValue) {
134 this.metric = metricValue;
135 }
136
137 @Override
138 public boolean matchesSafely(JsonObject jsonObject) {
139
140 JsonObject jsonMetric = jsonObject.get("metric").asObject();
141 JsonObject jsonCounter;
142 JsonObject jsonMeter;
143 JsonObject jsonTimer;
144 Counter counter;
145 Meter meter;
146 Timer timer;
147
148 // check counter metric
149 if (jsonMetric.get("counter") != null) {
150 jsonCounter = jsonMetric.get("counter").asObject();
151 counter = (Counter) metric;
152 if (jsonCounter.get("counter").asLong() != counter.getCount()) {
153 reason = "counter " + counter.getCount();
154 return false;
155 }
156 }
157
158 // check meter metric
159 if (jsonMetric.get("meter") != null) {
160 jsonMeter = jsonMetric.get("meter").asObject();
161 meter = (Meter) metric;
162
163 if (jsonMeter.get("counter").asLong() != meter.getCount()) {
164 reason = "counter " + meter.getCount();
165 return false;
166 }
167
168 if (jsonMeter.get("1_min_rate").asDouble() != meter.getOneMinuteRate()) {
169 reason = "1 minute rate " + meter.getOneMinuteRate();
170 return false;
171 }
172
173 if (jsonMeter.get("5_min_rate").asDouble() != meter.getOneMinuteRate()) {
174 reason = "5 minute rate " + meter.getFiveMinuteRate();
175 return false;
176 }
177
178 if (jsonMeter.get("15_min_rate").asDouble() != meter.getFifteenMinuteRate()) {
179 reason = "15 minute rate " + meter.getFifteenMinuteRate();
180 return false;
181 }
182 }
183
184 if (jsonMetric.get("timer") != null) {
185 jsonTimer = jsonMetric.get("timer").asObject();
186 timer = (Timer) metric;
187
188 if (jsonTimer.get("counter").asLong() != timer.getCount()) {
189 reason = "counter " + timer.getCount();
190 return false;
191 }
192
193 if (jsonTimer.get("1_min_rate").asDouble() != timer.getOneMinuteRate()) {
194 reason = "1 minute rate " + timer.getOneMinuteRate();
195 return false;
196 }
197
198 if (jsonTimer.get("5_min_rate").asDouble() != timer.getOneMinuteRate()) {
199 reason = "5 minute rate " + timer.getFiveMinuteRate();
200 return false;
201 }
202
203 if (jsonTimer.get("15_min_rate").asDouble() != timer.getFifteenMinuteRate()) {
204 reason = "15 minute rate " + timer.getFifteenMinuteRate();
205 return false;
206 }
207
208 if (jsonTimer.get("mean").asDouble() != nanoToMs(timer.getSnapshot().getMean())) {
209 reason = "mean " + timer.getSnapshot().getMean();
210 return false;
211 }
212
213 if (jsonTimer.get("min").asDouble() != nanoToMs(timer.getSnapshot().getMin())) {
214 reason = "min " + timer.getSnapshot().getMin();
215 return false;
216 }
217
218 if (jsonTimer.get("max").asDouble() != nanoToMs(timer.getSnapshot().getMax())) {
219 reason = "max " + timer.getSnapshot().getMax();
220 return false;
221 }
222
223 if (jsonTimer.get("stddev").asDouble() != nanoToMs(timer.getSnapshot().getStdDev())) {
224 reason = "stddev " + timer.getSnapshot().getStdDev();
225 return false;
226 }
227 }
228
229 return true;
230 }
231
232 @Override
233 public void describeTo(Description description) {
234 description.appendText(reason);
235 }
236
237 private double nanoToMs(double nano) {
238 return nano / 1_000_000D;
239 }
240 }
241
242 /**
243 * Factory to allocate an metric matcher.
244 *
245 * @param metric metric object we are looking for
246 * @return matcher
247 */
248 private static MetricJsonMatcher matchesMetric(Metric metric) {
249 return new MetricJsonMatcher(metric);
Jian Li72315152015-12-10 17:20:43 -0800250 }
251}