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