blob: c4e474bb232ea3ed38ee8faf739e6381d2aa5f31 [file] [log] [blame]
Ray Milkey8fd68ca2015-01-27 15:19:09 -08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
Ray Milkey8fd68ca2015-01-27 15:19:09 -08003 *
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 */
Jian Li8ae91202016-03-24 14:36:16 -070016package org.onosproject.rest.resources;
Ray Milkey8fd68ca2015-01-27 15:19:09 -080017
Jian Li80cfe452016-01-14 16:04:58 -080018import com.eclipsesource.json.Json;
Jian Li9d616492016-03-09 10:52:49 -080019import com.eclipsesource.json.JsonArray;
20import com.eclipsesource.json.JsonObject;
21import com.google.common.collect.ImmutableList;
kalagesa42019542017-03-14 18:00:47 +053022import com.google.common.collect.ImmutableMap;
Ray Milkey8fd68ca2015-01-27 15:19:09 -080023import org.hamcrest.Description;
24import org.hamcrest.TypeSafeMatcher;
25import org.junit.After;
26import org.junit.Before;
27import org.junit.Test;
28import org.onlab.osgi.ServiceDirectory;
29import org.onlab.osgi.TestServiceDirectory;
30import org.onlab.rest.BaseResource;
31import org.onosproject.codec.CodecService;
32import org.onosproject.codec.impl.CodecManager;
33import org.onosproject.net.DefaultPort;
34import org.onosproject.net.Device;
35import org.onosproject.net.DeviceId;
36import org.onosproject.net.MastershipRole;
37import org.onosproject.net.Port;
38import org.onosproject.net.device.DeviceService;
kalagesa42019542017-03-14 18:00:47 +053039import org.onosproject.net.driver.DriverService;
40import org.onosproject.net.driver.DefaultDriver;
41import org.onosproject.net.driver.TestBehaviourImpl;
42import org.onosproject.net.driver.TestBehaviour;
43import org.onosproject.net.driver.TestBehaviourTwo;
44import org.onosproject.net.driver.TestBehaviourTwoImpl;
Ray Milkey8fd68ca2015-01-27 15:19:09 -080045
Jian Li9d616492016-03-09 10:52:49 -080046import javax.ws.rs.NotFoundException;
47import javax.ws.rs.client.WebTarget;
kalagesa42019542017-03-14 18:00:47 +053048
49import java.util.ArrayList;
Jian Li9d616492016-03-09 10:52:49 -080050import java.util.List;
Ray Milkey8fd68ca2015-01-27 15:19:09 -080051
52import static org.easymock.EasyMock.createMock;
53import static org.easymock.EasyMock.expect;
54import static org.easymock.EasyMock.isA;
55import static org.easymock.EasyMock.replay;
56import static org.easymock.EasyMock.verify;
57import static org.hamcrest.Matchers.containsString;
58import static org.hamcrest.Matchers.equalTo;
59import static org.hamcrest.Matchers.hasSize;
60import static org.hamcrest.Matchers.is;
61import static org.hamcrest.Matchers.notNullValue;
62import static org.junit.Assert.assertThat;
63import static org.junit.Assert.fail;
64import static org.onosproject.net.NetTestTools.device;
65import static org.onosproject.net.NetTestTools.did;
66import static org.onosproject.net.PortNumber.portNumber;
67
68/**
69 * Unit tests for devices REST APIs.
70 */
Ray Milkey9c3d3362015-01-28 10:39:56 -080071public class DevicesResourceTest extends ResourceTest {
Ray Milkey8fd68ca2015-01-27 15:19:09 -080072 DeviceService mockDeviceService;
kalagesa42019542017-03-14 18:00:47 +053073 DriverService mockDriverService;
74 DefaultDriver driver = new DefaultDriver("ovs", new ArrayList<>(), "Circus", "lux", "1.2a",
75 ImmutableMap.of(TestBehaviour.class,
76 TestBehaviourImpl.class,
77 TestBehaviourTwo.class,
78 TestBehaviourTwoImpl.class),
79 ImmutableMap.of("foo", "bar"));
Ray Milkey8fd68ca2015-01-27 15:19:09 -080080
81 /**
Ray Milkey8fd68ca2015-01-27 15:19:09 -080082 * Hamcrest matcher to check that an device representation in JSON matches
83 * the actual device.
84 */
85 public static class DeviceJsonMatcher extends TypeSafeMatcher<JsonObject> {
86 private final Device device;
87 private String reason = "";
88
89 public DeviceJsonMatcher(Device deviceValue) {
90 device = deviceValue;
91 }
92
93 @Override
94 public boolean matchesSafely(JsonObject jsonDevice) {
95 // check id
96 String jsonId = jsonDevice.get("id").asString();
97 if (!jsonId.equals(device.id().toString())) {
98 reason = "id " + device.id().toString();
99 return false;
100 }
101
102 // check type
103 String jsonType = jsonDevice.get("type").asString();
104 if (!jsonType.equals(device.type().toString())) {
105 reason = "appId " + device.type().toString();
106 return false;
107 }
108
109 // check manufacturer
110 String jsonManufacturer = jsonDevice.get("mfr").asString();
111 if (!jsonManufacturer.equals(device.manufacturer())) {
112 reason = "manufacturer " + device.manufacturer();
113 return false;
114 }
115
116 // check HW version field
117 String jsonHwVersion = jsonDevice.get("hw").asString();
kalagesa42019542017-03-14 18:00:47 +0530118
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800119 if (!jsonHwVersion.equals(device.hwVersion())) {
120 reason = "hw Version " + device.hwVersion();
121 return false;
122 }
123
124 // check SW version field
125 String jsonSwVersion = jsonDevice.get("sw").asString();
126 if (!jsonSwVersion.equals(device.swVersion())) {
127 reason = "sw Version " + device.swVersion();
128 return false;
129 }
130
131 // check serial number field
132 String jsonSerialNumber = jsonDevice.get("serial").asString();
133 if (!jsonSerialNumber.equals(device.serialNumber())) {
134 reason = "serial number " + device.serialNumber();
135 return false;
136 }
137
138 // check chassis id field
139 String jsonChassisId = jsonDevice.get("chassisId").asString();
140 if (!jsonChassisId.equals(device.chassisId().toString())) {
141 reason = "Chassis id " + device.chassisId().toString();
142 return false;
143 }
144
145 return true;
146 }
147
148 @Override
149 public void describeTo(Description description) {
150 description.appendText(reason);
151 }
152 }
153
154 /**
155 * Factory to allocate an device matcher.
156 *
157 * @param device device object we are looking for
158 * @return matcher
159 */
160 private static DeviceJsonMatcher matchesDevice(Device device) {
161 return new DeviceJsonMatcher(device);
162 }
163
164 /**
165 * Hamcrest matcher to check that an device is represented properly in a JSON
166 * array of devices.
167 */
168 private static class DeviceJsonArrayMatcher extends TypeSafeMatcher<JsonArray> {
169 private final Device device;
170 private String reason = "";
171
172 public DeviceJsonArrayMatcher(Device deviceValue) {
173 device = deviceValue;
174 }
175
176 @Override
177 public boolean matchesSafely(JsonArray json) {
178 final int minExpectedAttributes = 9;
179 final int maxExpectedAttributes = 10;
180
181 boolean deviceFound = false;
182
183 for (int jsonDeviceIndex = 0; jsonDeviceIndex < json.size();
184 jsonDeviceIndex++) {
185
186 JsonObject jsonDevice = json.get(jsonDeviceIndex).asObject();
187
188 if (jsonDevice.names().size() < minExpectedAttributes ||
189 jsonDevice.names().size() > maxExpectedAttributes) {
190 reason = "Found a device with the wrong number of attributes";
191 return false;
192 }
193
194 String jsonDeviceId = jsonDevice.get("id").asString();
195 if (jsonDeviceId.equals(device.id().toString())) {
196 deviceFound = true;
197
198 // We found the correct device, check attribute values
199 assertThat(jsonDevice, matchesDevice(device));
200 }
201 }
202 if (!deviceFound) {
203 reason = "Device with id " + device.id().toString() + " not found";
204 return false;
205 } else {
206 return true;
207 }
208 }
209
210 @Override
211 public void describeTo(Description description) {
212 description.appendText(reason);
213 }
214 }
215
216 /**
217 * Factory to allocate an device array matcher.
218 *
219 * @param device device object we are looking for
220 * @return matcher
221 */
222 private static DeviceJsonArrayMatcher hasDevice(Device device) {
223 return new DeviceJsonArrayMatcher(device);
224 }
225
Ray Milkeyed0b1662015-02-05 09:34:29 -0800226 /**
227 * Initializes test mocks and environment.
228 */
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800229 @Before
Ray Milkeyed0b1662015-02-05 09:34:29 -0800230 public void setUpMocks() {
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800231 mockDeviceService = createMock(DeviceService.class);
kalagesa42019542017-03-14 18:00:47 +0530232 mockDriverService = createMock(DriverService.class);
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800233 expect(mockDeviceService.isAvailable(isA(DeviceId.class)))
234 .andReturn(true)
235 .anyTimes();
236 expect(mockDeviceService.getRole(isA(DeviceId.class)))
237 .andReturn(MastershipRole.MASTER)
238 .anyTimes();
239
kalagesa42019542017-03-14 18:00:47 +0530240
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800241 // Register the services needed for the test
242 CodecManager codecService = new CodecManager();
243 codecService.activate();
244 ServiceDirectory testDirectory =
245 new TestServiceDirectory()
246 .add(DeviceService.class, mockDeviceService)
kalagesa42019542017-03-14 18:00:47 +0530247 .add(DriverService.class, mockDriverService)
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800248 .add(CodecService.class, codecService);
249
250 BaseResource.setServiceDirectory(testDirectory);
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800251 }
252
Ray Milkeyed0b1662015-02-05 09:34:29 -0800253 /**
254 * Verifies test mocks.
255 */
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800256 @After
Ray Milkeyed0b1662015-02-05 09:34:29 -0800257 public void tearDownMocks() {
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800258 verify(mockDeviceService);
259 }
260
261 /**
262 * Tests the result of the rest api GET when there are no devices.
263 */
264 @Test
265 public void testDevicesEmptyArray() {
266 expect(mockDeviceService.getDevices()).andReturn(ImmutableList.of());
267 replay(mockDeviceService);
268
Jian Li9d616492016-03-09 10:52:49 -0800269 WebTarget wt = target();
270 String response = wt.path("devices").request().get(String.class);
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800271 assertThat(response, is("{\"devices\":[]}"));
272 }
273
274 /**
275 * Tests the result of the rest api GET when there are devices present.
276 */
277 @Test
278 public void testDevices() {
279 Device device1 = device("dev1");
280 Device device2 = device("dev2");
281 Device device3 = device("dev3");
282
283 expect(mockDeviceService.getDevices())
284 .andReturn(ImmutableList.of(device1, device2, device3))
285 .anyTimes();
286
287 replay(mockDeviceService);
288
kalagesa42019542017-03-14 18:00:47 +0530289 expect(mockDriverService.getDriver(did("dev1")))
290 .andReturn(driver)
291 .anyTimes();
292
293 expect(mockDriverService.getDriver(did("dev2")))
294 .andReturn(driver)
295 .anyTimes();
296
297 expect(mockDriverService.getDriver(did("dev3")))
298 .andReturn(driver)
299 .anyTimes();
300
301 replay(mockDriverService);
302
303
304
Jian Li9d616492016-03-09 10:52:49 -0800305 WebTarget wt = target();
306 String response = wt.path("devices").request().get(String.class);
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800307 assertThat(response, containsString("{\"devices\":["));
308
Jian Li80cfe452016-01-14 16:04:58 -0800309 JsonObject result = Json.parse(response).asObject();
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800310 assertThat(result, notNullValue());
311
312 assertThat(result.names(), hasSize(1));
313 assertThat(result.names().get(0), is("devices"));
314
315 JsonArray jsonDevices = result.get("devices").asArray();
316 assertThat(jsonDevices, notNullValue());
317 assertThat(jsonDevices.size(), is(3));
318
319 assertThat(jsonDevices, hasDevice(device1));
320 assertThat(jsonDevices, hasDevice(device2));
321 assertThat(jsonDevices, hasDevice(device3));
322 }
323
324 /**
325 * Tests the result of a rest api GET for a single device.
326 */
327 @Test
328 public void testDevicesSingle() {
329
330 String deviceIdString = "testdevice";
331 DeviceId deviceId = did(deviceIdString);
332 Device device = device(deviceIdString);
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800333 expect(mockDeviceService.getDevice(deviceId))
334 .andReturn(device)
335 .once();
336 replay(mockDeviceService);
kalagesa42019542017-03-14 18:00:47 +0530337 expect(mockDriverService.getDriver(deviceId))
338 .andReturn(driver)
339 .anyTimes();
340 replay(mockDriverService);
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800341
Jian Li9d616492016-03-09 10:52:49 -0800342 WebTarget wt = target();
343 String response = wt.path("devices/" + deviceId).request().get(String.class);
Jian Li80cfe452016-01-14 16:04:58 -0800344 JsonObject result = Json.parse(response).asObject();
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800345 assertThat(result, matchesDevice(device));
346 }
347
348 /**
349 * Tests the result of a rest api GET for the ports of a single device.
350 */
351 @Test
352 public void testDeviceAndPorts() {
353
354 String deviceIdString = "testdevice";
355 DeviceId deviceId = did(deviceIdString);
356 Device device = device(deviceIdString);
357
kalagesa42019542017-03-14 18:00:47 +0530358
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800359 Port port1 = new DefaultPort(device, portNumber(1), true);
360 Port port2 = new DefaultPort(device, portNumber(2), true);
361 Port port3 = new DefaultPort(device, portNumber(3), true);
362 List<Port> ports = ImmutableList.of(port1, port2, port3);
363
364 expect(mockDeviceService.getDevice(deviceId))
365 .andReturn(device)
366 .once();
367
368 expect(mockDeviceService.getPorts(deviceId))
369 .andReturn(ports)
370 .once();
371 replay(mockDeviceService);
372
kalagesa42019542017-03-14 18:00:47 +0530373 expect(mockDriverService.getDriver(deviceId))
374 .andReturn(driver)
375 .anyTimes();
376 replay(mockDriverService);
377
378
Jian Li9d616492016-03-09 10:52:49 -0800379 WebTarget wt = target();
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800380 String response =
Jian Li9d616492016-03-09 10:52:49 -0800381 wt.path("devices/" + deviceId + "/ports").request()
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800382 .get(String.class);
Jian Li80cfe452016-01-14 16:04:58 -0800383 JsonObject result = Json.parse(response).asObject();
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800384 assertThat(result, matchesDevice(device));
385
386 JsonArray jsonPorts = result.get("ports").asArray();
387 assertThat(jsonPorts.size(), is(3));
388 for (int portIndex = 0; portIndex < jsonPorts.size(); portIndex++) {
389 JsonObject jsonPort = jsonPorts.get(portIndex).asObject();
390
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800391 assertThat(jsonPort.get("port").asString(),
392 is(Integer.toString(portIndex + 1)));
393 assertThat(jsonPort.get("isEnabled").asBoolean(),
394 is(true));
395 assertThat(jsonPort.get("type").asString(),
396 equalTo("copper"));
397 assertThat(jsonPort.get("portSpeed").asLong(),
398 is(1000L));
399 }
400 }
401
402 /**
403 * Tests that a fetch of a non-existent device object throws an exception.
404 */
405 @Test
406 public void testBadGet() {
407
408 expect(mockDeviceService.getDevice(isA(DeviceId.class)))
409 .andReturn(null)
410 .anyTimes();
411 replay(mockDeviceService);
412
Jian Li9d616492016-03-09 10:52:49 -0800413 WebTarget wt = target();
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800414 try {
Jian Li9d616492016-03-09 10:52:49 -0800415 wt.path("devices/0").request().get(String.class);
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800416 fail("Fetch of non-existent device did not throw an exception");
Jian Li9d616492016-03-09 10:52:49 -0800417 } catch (NotFoundException ex) {
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800418 assertThat(ex.getMessage(),
Jian Li9d616492016-03-09 10:52:49 -0800419 containsString("HTTP 404 Not Found"));
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800420 }
421 }
422}