blob: 67b04c837f7e3c2f76df809d90a4a197a04947ac [file] [log] [blame]
Ray Milkey8fd68ca2015-01-27 15:19:09 -08001/*
2 * Copyright 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 java.util.List;
19
20import org.hamcrest.Description;
21import org.hamcrest.TypeSafeMatcher;
22import org.junit.After;
23import org.junit.Before;
24import org.junit.Test;
25import org.onlab.osgi.ServiceDirectory;
26import org.onlab.osgi.TestServiceDirectory;
27import org.onlab.rest.BaseResource;
28import org.onosproject.codec.CodecService;
29import org.onosproject.codec.impl.CodecManager;
30import org.onosproject.net.DefaultPort;
31import org.onosproject.net.Device;
32import org.onosproject.net.DeviceId;
33import org.onosproject.net.MastershipRole;
34import org.onosproject.net.Port;
35import org.onosproject.net.device.DeviceService;
36
37import com.eclipsesource.json.JsonArray;
38import com.eclipsesource.json.JsonObject;
39import com.google.common.collect.ImmutableList;
40import com.sun.jersey.api.client.UniformInterfaceException;
41import com.sun.jersey.api.client.WebResource;
42import com.sun.jersey.test.framework.JerseyTest;
43
44import static org.easymock.EasyMock.createMock;
45import static org.easymock.EasyMock.expect;
46import static org.easymock.EasyMock.isA;
47import static org.easymock.EasyMock.replay;
48import static org.easymock.EasyMock.verify;
49import static org.hamcrest.Matchers.containsString;
50import static org.hamcrest.Matchers.equalTo;
51import static org.hamcrest.Matchers.hasSize;
52import static org.hamcrest.Matchers.is;
53import static org.hamcrest.Matchers.notNullValue;
54import static org.junit.Assert.assertThat;
55import static org.junit.Assert.fail;
56import static org.onosproject.net.NetTestTools.device;
57import static org.onosproject.net.NetTestTools.did;
58import static org.onosproject.net.PortNumber.portNumber;
59
60/**
61 * Unit tests for devices REST APIs.
62 */
63public class DevicesResourceTest extends JerseyTest {
64 DeviceService mockDeviceService;
65
66 /**
67 * Constructs the test.
68 */
69 public DevicesResourceTest() {
70 super("org.onosproject.rest");
71 }
72
73 /**
74 * Hamcrest matcher to check that an device representation in JSON matches
75 * the actual device.
76 */
77 public static class DeviceJsonMatcher extends TypeSafeMatcher<JsonObject> {
78 private final Device device;
79 private String reason = "";
80
81 public DeviceJsonMatcher(Device deviceValue) {
82 device = deviceValue;
83 }
84
85 @Override
86 public boolean matchesSafely(JsonObject jsonDevice) {
87 // check id
88 String jsonId = jsonDevice.get("id").asString();
89 if (!jsonId.equals(device.id().toString())) {
90 reason = "id " + device.id().toString();
91 return false;
92 }
93
94 // check type
95 String jsonType = jsonDevice.get("type").asString();
96 if (!jsonType.equals(device.type().toString())) {
97 reason = "appId " + device.type().toString();
98 return false;
99 }
100
101 // check manufacturer
102 String jsonManufacturer = jsonDevice.get("mfr").asString();
103 if (!jsonManufacturer.equals(device.manufacturer())) {
104 reason = "manufacturer " + device.manufacturer();
105 return false;
106 }
107
108 // check HW version field
109 String jsonHwVersion = jsonDevice.get("hw").asString();
110 if (!jsonHwVersion.equals(device.hwVersion())) {
111 reason = "hw Version " + device.hwVersion();
112 return false;
113 }
114
115 // check SW version field
116 String jsonSwVersion = jsonDevice.get("sw").asString();
117 if (!jsonSwVersion.equals(device.swVersion())) {
118 reason = "sw Version " + device.swVersion();
119 return false;
120 }
121
122 // check serial number field
123 String jsonSerialNumber = jsonDevice.get("serial").asString();
124 if (!jsonSerialNumber.equals(device.serialNumber())) {
125 reason = "serial number " + device.serialNumber();
126 return false;
127 }
128
129 // check chassis id field
130 String jsonChassisId = jsonDevice.get("chassisId").asString();
131 if (!jsonChassisId.equals(device.chassisId().toString())) {
132 reason = "Chassis id " + device.chassisId().toString();
133 return false;
134 }
135
136 return true;
137 }
138
139 @Override
140 public void describeTo(Description description) {
141 description.appendText(reason);
142 }
143 }
144
145 /**
146 * Factory to allocate an device matcher.
147 *
148 * @param device device object we are looking for
149 * @return matcher
150 */
151 private static DeviceJsonMatcher matchesDevice(Device device) {
152 return new DeviceJsonMatcher(device);
153 }
154
155 /**
156 * Hamcrest matcher to check that an device is represented properly in a JSON
157 * array of devices.
158 */
159 private static class DeviceJsonArrayMatcher extends TypeSafeMatcher<JsonArray> {
160 private final Device device;
161 private String reason = "";
162
163 public DeviceJsonArrayMatcher(Device deviceValue) {
164 device = deviceValue;
165 }
166
167 @Override
168 public boolean matchesSafely(JsonArray json) {
169 final int minExpectedAttributes = 9;
170 final int maxExpectedAttributes = 10;
171
172 boolean deviceFound = false;
173
174 for (int jsonDeviceIndex = 0; jsonDeviceIndex < json.size();
175 jsonDeviceIndex++) {
176
177 JsonObject jsonDevice = json.get(jsonDeviceIndex).asObject();
178
179 if (jsonDevice.names().size() < minExpectedAttributes ||
180 jsonDevice.names().size() > maxExpectedAttributes) {
181 reason = "Found a device with the wrong number of attributes";
182 return false;
183 }
184
185 String jsonDeviceId = jsonDevice.get("id").asString();
186 if (jsonDeviceId.equals(device.id().toString())) {
187 deviceFound = true;
188
189 // We found the correct device, check attribute values
190 assertThat(jsonDevice, matchesDevice(device));
191 }
192 }
193 if (!deviceFound) {
194 reason = "Device with id " + device.id().toString() + " not found";
195 return false;
196 } else {
197 return true;
198 }
199 }
200
201 @Override
202 public void describeTo(Description description) {
203 description.appendText(reason);
204 }
205 }
206
207 /**
208 * Factory to allocate an device array matcher.
209 *
210 * @param device device object we are looking for
211 * @return matcher
212 */
213 private static DeviceJsonArrayMatcher hasDevice(Device device) {
214 return new DeviceJsonArrayMatcher(device);
215 }
216
217 @Before
218 public void setUp() {
219 mockDeviceService = createMock(DeviceService.class);
220
221 expect(mockDeviceService.isAvailable(isA(DeviceId.class)))
222 .andReturn(true)
223 .anyTimes();
224 expect(mockDeviceService.getRole(isA(DeviceId.class)))
225 .andReturn(MastershipRole.MASTER)
226 .anyTimes();
227
228 // Register the services needed for the test
229 CodecManager codecService = new CodecManager();
230 codecService.activate();
231 ServiceDirectory testDirectory =
232 new TestServiceDirectory()
233 .add(DeviceService.class, mockDeviceService)
234 .add(CodecService.class, codecService);
235
236 BaseResource.setServiceDirectory(testDirectory);
237
238
239 }
240
241 @After
242 public void tearDown() throws Exception {
243 super.tearDown();
244 verify(mockDeviceService);
245 }
246
247 /**
248 * Tests the result of the rest api GET when there are no devices.
249 */
250 @Test
251 public void testDevicesEmptyArray() {
252 expect(mockDeviceService.getDevices()).andReturn(ImmutableList.of());
253 replay(mockDeviceService);
254
255 WebResource rs = resource();
256 String response = rs.path("devices").get(String.class);
257 assertThat(response, is("{\"devices\":[]}"));
258 }
259
260 /**
261 * Tests the result of the rest api GET when there are devices present.
262 */
263 @Test
264 public void testDevices() {
265 Device device1 = device("dev1");
266 Device device2 = device("dev2");
267 Device device3 = device("dev3");
268
269 expect(mockDeviceService.getDevices())
270 .andReturn(ImmutableList.of(device1, device2, device3))
271 .anyTimes();
272
273 replay(mockDeviceService);
274
275 WebResource rs = resource();
276 String response = rs.path("devices").get(String.class);
277 assertThat(response, containsString("{\"devices\":["));
278
279 JsonObject result = JsonObject.readFrom(response);
280 assertThat(result, notNullValue());
281
282 assertThat(result.names(), hasSize(1));
283 assertThat(result.names().get(0), is("devices"));
284
285 JsonArray jsonDevices = result.get("devices").asArray();
286 assertThat(jsonDevices, notNullValue());
287 assertThat(jsonDevices.size(), is(3));
288
289 assertThat(jsonDevices, hasDevice(device1));
290 assertThat(jsonDevices, hasDevice(device2));
291 assertThat(jsonDevices, hasDevice(device3));
292 }
293
294 /**
295 * Tests the result of a rest api GET for a single device.
296 */
297 @Test
298 public void testDevicesSingle() {
299
300 String deviceIdString = "testdevice";
301 DeviceId deviceId = did(deviceIdString);
302 Device device = device(deviceIdString);
303
304 expect(mockDeviceService.getDevice(deviceId))
305 .andReturn(device)
306 .once();
307 replay(mockDeviceService);
308
309 WebResource rs = resource();
310 String response = rs.path("devices/" + deviceId).get(String.class);
311 JsonObject result = JsonObject.readFrom(response);
312 assertThat(result, matchesDevice(device));
313 }
314
315 /**
316 * Tests the result of a rest api GET for the ports of a single device.
317 */
318 @Test
319 public void testDeviceAndPorts() {
320
321 String deviceIdString = "testdevice";
322 DeviceId deviceId = did(deviceIdString);
323 Device device = device(deviceIdString);
324
325 Port port1 = new DefaultPort(device, portNumber(1), true);
326 Port port2 = new DefaultPort(device, portNumber(2), true);
327 Port port3 = new DefaultPort(device, portNumber(3), true);
328 List<Port> ports = ImmutableList.of(port1, port2, port3);
329
330 expect(mockDeviceService.getDevice(deviceId))
331 .andReturn(device)
332 .once();
333
334 expect(mockDeviceService.getPorts(deviceId))
335 .andReturn(ports)
336 .once();
337 replay(mockDeviceService);
338
339 WebResource rs = resource();
340 String response =
341 rs.path("devices/" + deviceId + "/ports")
342 .get(String.class);
343 JsonObject result = JsonObject.readFrom(response);
344 assertThat(result, matchesDevice(device));
345
346 JsonArray jsonPorts = result.get("ports").asArray();
347 assertThat(jsonPorts.size(), is(3));
348 for (int portIndex = 0; portIndex < jsonPorts.size(); portIndex++) {
349 JsonObject jsonPort = jsonPorts.get(portIndex).asObject();
350
351 assertThat(jsonPort.size(), is(4));
352 assertThat(jsonPort.get("port").asString(),
353 is(Integer.toString(portIndex + 1)));
354 assertThat(jsonPort.get("isEnabled").asBoolean(),
355 is(true));
356 assertThat(jsonPort.get("type").asString(),
357 equalTo("copper"));
358 assertThat(jsonPort.get("portSpeed").asLong(),
359 is(1000L));
360 }
361 }
362
363 /**
364 * Tests that a fetch of a non-existent device object throws an exception.
365 */
366 @Test
367 public void testBadGet() {
368
369 expect(mockDeviceService.getDevice(isA(DeviceId.class)))
370 .andReturn(null)
371 .anyTimes();
372 replay(mockDeviceService);
373
374 WebResource rs = resource();
375 try {
376 rs.path("devices/0").get(String.class);
377 fail("Fetch of non-existent device did not throw an exception");
378 } catch (UniformInterfaceException ex) {
379 assertThat(ex.getMessage(),
380 containsString("returned a response status of"));
381 }
382 }
383}