blob: 19fb7824b4cba1dbafb469680135b6f114da7b61 [file] [log] [blame]
Ray Milkey8fd68ca2015-01-27 15:19:09 -08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
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;
Ray Milkey8fd68ca2015-01-27 15:19:09 -080030import org.onosproject.codec.CodecService;
31import org.onosproject.codec.impl.CodecManager;
32import org.onosproject.net.DefaultPort;
33import org.onosproject.net.Device;
34import org.onosproject.net.DeviceId;
35import org.onosproject.net.MastershipRole;
36import org.onosproject.net.Port;
37import org.onosproject.net.device.DeviceService;
kalagesa42019542017-03-14 18:00:47 +053038import org.onosproject.net.driver.DefaultDriver;
Ray Milkey094a1352018-01-22 14:03:54 -080039import org.onosproject.net.driver.DriverService;
kalagesa42019542017-03-14 18:00:47 +053040import org.onosproject.net.driver.TestBehaviour;
Ray Milkey094a1352018-01-22 14:03:54 -080041import org.onosproject.net.driver.TestBehaviourImpl;
kalagesa42019542017-03-14 18:00:47 +053042import org.onosproject.net.driver.TestBehaviourTwo;
43import org.onosproject.net.driver.TestBehaviourTwoImpl;
Ray Milkey8fd68ca2015-01-27 15:19:09 -080044
Jian Li9d616492016-03-09 10:52:49 -080045import javax.ws.rs.NotFoundException;
46import javax.ws.rs.client.WebTarget;
kalagesa42019542017-03-14 18:00:47 +053047import java.util.ArrayList;
Jian Li9d616492016-03-09 10:52:49 -080048import java.util.List;
Ray Milkey8fd68ca2015-01-27 15:19:09 -080049
50import static org.easymock.EasyMock.createMock;
51import static org.easymock.EasyMock.expect;
52import static org.easymock.EasyMock.isA;
53import static org.easymock.EasyMock.replay;
54import static org.easymock.EasyMock.verify;
55import static org.hamcrest.Matchers.containsString;
56import static org.hamcrest.Matchers.equalTo;
57import static org.hamcrest.Matchers.hasSize;
58import static org.hamcrest.Matchers.is;
59import static org.hamcrest.Matchers.notNullValue;
60import static org.junit.Assert.assertThat;
61import static org.junit.Assert.fail;
62import static org.onosproject.net.NetTestTools.device;
63import static org.onosproject.net.NetTestTools.did;
64import static org.onosproject.net.PortNumber.portNumber;
65
66/**
67 * Unit tests for devices REST APIs.
68 */
Ray Milkey9c3d3362015-01-28 10:39:56 -080069public class DevicesResourceTest extends ResourceTest {
Ray Milkey8fd68ca2015-01-27 15:19:09 -080070 DeviceService mockDeviceService;
kalagesa42019542017-03-14 18:00:47 +053071 DriverService mockDriverService;
72 DefaultDriver driver = new DefaultDriver("ovs", new ArrayList<>(), "Circus", "lux", "1.2a",
73 ImmutableMap.of(TestBehaviour.class,
74 TestBehaviourImpl.class,
75 TestBehaviourTwo.class,
76 TestBehaviourTwoImpl.class),
77 ImmutableMap.of("foo", "bar"));
Ray Milkey8fd68ca2015-01-27 15:19:09 -080078
79 /**
Ray Milkey8fd68ca2015-01-27 15:19:09 -080080 * Hamcrest matcher to check that an device representation in JSON matches
81 * the actual device.
82 */
83 public static class DeviceJsonMatcher extends TypeSafeMatcher<JsonObject> {
84 private final Device device;
85 private String reason = "";
86
87 public DeviceJsonMatcher(Device deviceValue) {
88 device = deviceValue;
89 }
90
91 @Override
92 public boolean matchesSafely(JsonObject jsonDevice) {
93 // check id
94 String jsonId = jsonDevice.get("id").asString();
95 if (!jsonId.equals(device.id().toString())) {
96 reason = "id " + device.id().toString();
97 return false;
98 }
99
100 // check type
101 String jsonType = jsonDevice.get("type").asString();
102 if (!jsonType.equals(device.type().toString())) {
103 reason = "appId " + device.type().toString();
104 return false;
105 }
106
107 // check manufacturer
108 String jsonManufacturer = jsonDevice.get("mfr").asString();
109 if (!jsonManufacturer.equals(device.manufacturer())) {
110 reason = "manufacturer " + device.manufacturer();
111 return false;
112 }
113
114 // check HW version field
115 String jsonHwVersion = jsonDevice.get("hw").asString();
kalagesa42019542017-03-14 18:00:47 +0530116
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800117 if (!jsonHwVersion.equals(device.hwVersion())) {
118 reason = "hw Version " + device.hwVersion();
119 return false;
120 }
121
122 // check SW version field
123 String jsonSwVersion = jsonDevice.get("sw").asString();
124 if (!jsonSwVersion.equals(device.swVersion())) {
125 reason = "sw Version " + device.swVersion();
126 return false;
127 }
128
129 // check serial number field
130 String jsonSerialNumber = jsonDevice.get("serial").asString();
131 if (!jsonSerialNumber.equals(device.serialNumber())) {
132 reason = "serial number " + device.serialNumber();
133 return false;
134 }
135
136 // check chassis id field
137 String jsonChassisId = jsonDevice.get("chassisId").asString();
138 if (!jsonChassisId.equals(device.chassisId().toString())) {
139 reason = "Chassis id " + device.chassisId().toString();
140 return false;
141 }
142
143 return true;
144 }
145
146 @Override
147 public void describeTo(Description description) {
148 description.appendText(reason);
149 }
150 }
151
152 /**
153 * Factory to allocate an device matcher.
154 *
155 * @param device device object we are looking for
156 * @return matcher
157 */
158 private static DeviceJsonMatcher matchesDevice(Device device) {
159 return new DeviceJsonMatcher(device);
160 }
161
162 /**
163 * Hamcrest matcher to check that an device is represented properly in a JSON
164 * array of devices.
165 */
166 private static class DeviceJsonArrayMatcher extends TypeSafeMatcher<JsonArray> {
167 private final Device device;
168 private String reason = "";
169
170 public DeviceJsonArrayMatcher(Device deviceValue) {
171 device = deviceValue;
172 }
173
174 @Override
175 public boolean matchesSafely(JsonArray json) {
Ray Milkey054e23d2018-03-22 13:37:11 -0700176 final int minExpectedAttributes = 11;
177 final int maxExpectedAttributes = 12;
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800178
179 boolean deviceFound = false;
180
181 for (int jsonDeviceIndex = 0; jsonDeviceIndex < json.size();
182 jsonDeviceIndex++) {
183
184 JsonObject jsonDevice = json.get(jsonDeviceIndex).asObject();
185
186 if (jsonDevice.names().size() < minExpectedAttributes ||
187 jsonDevice.names().size() > maxExpectedAttributes) {
188 reason = "Found a device with the wrong number of attributes";
189 return false;
190 }
191
192 String jsonDeviceId = jsonDevice.get("id").asString();
193 if (jsonDeviceId.equals(device.id().toString())) {
194 deviceFound = true;
195
196 // We found the correct device, check attribute values
197 assertThat(jsonDevice, matchesDevice(device));
198 }
199 }
200 if (!deviceFound) {
201 reason = "Device with id " + device.id().toString() + " not found";
202 return false;
203 } else {
204 return true;
205 }
206 }
207
208 @Override
209 public void describeTo(Description description) {
210 description.appendText(reason);
211 }
212 }
213
214 /**
215 * Factory to allocate an device array matcher.
216 *
217 * @param device device object we are looking for
218 * @return matcher
219 */
220 private static DeviceJsonArrayMatcher hasDevice(Device device) {
221 return new DeviceJsonArrayMatcher(device);
222 }
223
Ray Milkeyed0b1662015-02-05 09:34:29 -0800224 /**
225 * Initializes test mocks and environment.
226 */
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800227 @Before
Ray Milkeyed0b1662015-02-05 09:34:29 -0800228 public void setUpMocks() {
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800229 mockDeviceService = createMock(DeviceService.class);
kalagesa42019542017-03-14 18:00:47 +0530230 mockDriverService = createMock(DriverService.class);
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800231 expect(mockDeviceService.isAvailable(isA(DeviceId.class)))
232 .andReturn(true)
233 .anyTimes();
234 expect(mockDeviceService.getRole(isA(DeviceId.class)))
235 .andReturn(MastershipRole.MASTER)
236 .anyTimes();
Ray Milkey054e23d2018-03-22 13:37:11 -0700237 expect(mockDeviceService.getLastUpdatedInstant(isA(DeviceId.class)))
238 .andReturn(0L)
239 .anyTimes();
240 expect(mockDeviceService.localStatus(isA(DeviceId.class)))
241 .andReturn("")
242 .anyTimes();
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800243
kalagesa42019542017-03-14 18:00:47 +0530244
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800245 // Register the services needed for the test
246 CodecManager codecService = new CodecManager();
247 codecService.activate();
248 ServiceDirectory testDirectory =
249 new TestServiceDirectory()
250 .add(DeviceService.class, mockDeviceService)
kalagesa42019542017-03-14 18:00:47 +0530251 .add(DriverService.class, mockDriverService)
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800252 .add(CodecService.class, codecService);
253
Ray Milkey094a1352018-01-22 14:03:54 -0800254 setServiceDirectory(testDirectory);
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800255 }
256
Ray Milkeyed0b1662015-02-05 09:34:29 -0800257 /**
258 * Verifies test mocks.
259 */
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800260 @After
Ray Milkeyed0b1662015-02-05 09:34:29 -0800261 public void tearDownMocks() {
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800262 verify(mockDeviceService);
263 }
264
265 /**
266 * Tests the result of the rest api GET when there are no devices.
267 */
268 @Test
269 public void testDevicesEmptyArray() {
270 expect(mockDeviceService.getDevices()).andReturn(ImmutableList.of());
271 replay(mockDeviceService);
272
Jian Li9d616492016-03-09 10:52:49 -0800273 WebTarget wt = target();
274 String response = wt.path("devices").request().get(String.class);
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800275 assertThat(response, is("{\"devices\":[]}"));
276 }
277
278 /**
279 * Tests the result of the rest api GET when there are devices present.
280 */
281 @Test
282 public void testDevices() {
283 Device device1 = device("dev1");
284 Device device2 = device("dev2");
285 Device device3 = device("dev3");
286
287 expect(mockDeviceService.getDevices())
288 .andReturn(ImmutableList.of(device1, device2, device3))
289 .anyTimes();
290
291 replay(mockDeviceService);
292
kalagesa42019542017-03-14 18:00:47 +0530293 expect(mockDriverService.getDriver(did("dev1")))
294 .andReturn(driver)
295 .anyTimes();
296
297 expect(mockDriverService.getDriver(did("dev2")))
298 .andReturn(driver)
299 .anyTimes();
300
301 expect(mockDriverService.getDriver(did("dev3")))
302 .andReturn(driver)
303 .anyTimes();
304
305 replay(mockDriverService);
306
307
308
Jian Li9d616492016-03-09 10:52:49 -0800309 WebTarget wt = target();
310 String response = wt.path("devices").request().get(String.class);
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800311 assertThat(response, containsString("{\"devices\":["));
312
Jian Li80cfe452016-01-14 16:04:58 -0800313 JsonObject result = Json.parse(response).asObject();
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800314 assertThat(result, notNullValue());
315
316 assertThat(result.names(), hasSize(1));
317 assertThat(result.names().get(0), is("devices"));
318
319 JsonArray jsonDevices = result.get("devices").asArray();
320 assertThat(jsonDevices, notNullValue());
321 assertThat(jsonDevices.size(), is(3));
322
323 assertThat(jsonDevices, hasDevice(device1));
324 assertThat(jsonDevices, hasDevice(device2));
325 assertThat(jsonDevices, hasDevice(device3));
326 }
327
328 /**
329 * Tests the result of a rest api GET for a single device.
330 */
331 @Test
332 public void testDevicesSingle() {
333
334 String deviceIdString = "testdevice";
335 DeviceId deviceId = did(deviceIdString);
336 Device device = device(deviceIdString);
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800337 expect(mockDeviceService.getDevice(deviceId))
338 .andReturn(device)
339 .once();
340 replay(mockDeviceService);
kalagesa42019542017-03-14 18:00:47 +0530341 expect(mockDriverService.getDriver(deviceId))
342 .andReturn(driver)
343 .anyTimes();
344 replay(mockDriverService);
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800345
Jian Li9d616492016-03-09 10:52:49 -0800346 WebTarget wt = target();
347 String response = wt.path("devices/" + deviceId).request().get(String.class);
Jian Li80cfe452016-01-14 16:04:58 -0800348 JsonObject result = Json.parse(response).asObject();
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800349 assertThat(result, matchesDevice(device));
350 }
351
352 /**
353 * Tests the result of a rest api GET for the ports of a single device.
354 */
355 @Test
356 public void testDeviceAndPorts() {
357
358 String deviceIdString = "testdevice";
359 DeviceId deviceId = did(deviceIdString);
360 Device device = device(deviceIdString);
361
kalagesa42019542017-03-14 18:00:47 +0530362
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800363 Port port1 = new DefaultPort(device, portNumber(1), true);
364 Port port2 = new DefaultPort(device, portNumber(2), true);
365 Port port3 = new DefaultPort(device, portNumber(3), true);
366 List<Port> ports = ImmutableList.of(port1, port2, port3);
367
368 expect(mockDeviceService.getDevice(deviceId))
369 .andReturn(device)
370 .once();
371
372 expect(mockDeviceService.getPorts(deviceId))
373 .andReturn(ports)
374 .once();
375 replay(mockDeviceService);
376
kalagesa42019542017-03-14 18:00:47 +0530377 expect(mockDriverService.getDriver(deviceId))
378 .andReturn(driver)
379 .anyTimes();
380 replay(mockDriverService);
381
382
Jian Li9d616492016-03-09 10:52:49 -0800383 WebTarget wt = target();
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800384 String response =
Jian Li9d616492016-03-09 10:52:49 -0800385 wt.path("devices/" + deviceId + "/ports").request()
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800386 .get(String.class);
Jian Li80cfe452016-01-14 16:04:58 -0800387 JsonObject result = Json.parse(response).asObject();
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800388 assertThat(result, matchesDevice(device));
389
390 JsonArray jsonPorts = result.get("ports").asArray();
391 assertThat(jsonPorts.size(), is(3));
392 for (int portIndex = 0; portIndex < jsonPorts.size(); portIndex++) {
393 JsonObject jsonPort = jsonPorts.get(portIndex).asObject();
394
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800395 assertThat(jsonPort.get("port").asString(),
396 is(Integer.toString(portIndex + 1)));
397 assertThat(jsonPort.get("isEnabled").asBoolean(),
398 is(true));
399 assertThat(jsonPort.get("type").asString(),
400 equalTo("copper"));
401 assertThat(jsonPort.get("portSpeed").asLong(),
402 is(1000L));
403 }
404 }
405
406 /**
407 * Tests that a fetch of a non-existent device object throws an exception.
408 */
409 @Test
410 public void testBadGet() {
411
412 expect(mockDeviceService.getDevice(isA(DeviceId.class)))
413 .andReturn(null)
414 .anyTimes();
415 replay(mockDeviceService);
416
Jian Li9d616492016-03-09 10:52:49 -0800417 WebTarget wt = target();
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800418 try {
Jian Li9d616492016-03-09 10:52:49 -0800419 wt.path("devices/0").request().get(String.class);
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800420 fail("Fetch of non-existent device did not throw an exception");
Jian Li9d616492016-03-09 10:52:49 -0800421 } catch (NotFoundException ex) {
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800422 assertThat(ex.getMessage(),
Jian Li9d616492016-03-09 10:52:49 -0800423 containsString("HTTP 404 Not Found"));
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800424 }
425 }
426}