blob: 75d33a84b60634606f62b2a37c0a161a8b6ee6a2 [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) {
176 final int minExpectedAttributes = 9;
177 final int maxExpectedAttributes = 10;
178
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();
237
kalagesa42019542017-03-14 18:00:47 +0530238
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800239 // Register the services needed for the test
240 CodecManager codecService = new CodecManager();
241 codecService.activate();
242 ServiceDirectory testDirectory =
243 new TestServiceDirectory()
244 .add(DeviceService.class, mockDeviceService)
kalagesa42019542017-03-14 18:00:47 +0530245 .add(DriverService.class, mockDriverService)
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800246 .add(CodecService.class, codecService);
247
Ray Milkey094a1352018-01-22 14:03:54 -0800248 setServiceDirectory(testDirectory);
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800249 }
250
Ray Milkeyed0b1662015-02-05 09:34:29 -0800251 /**
252 * Verifies test mocks.
253 */
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800254 @After
Ray Milkeyed0b1662015-02-05 09:34:29 -0800255 public void tearDownMocks() {
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800256 verify(mockDeviceService);
257 }
258
259 /**
260 * Tests the result of the rest api GET when there are no devices.
261 */
262 @Test
263 public void testDevicesEmptyArray() {
264 expect(mockDeviceService.getDevices()).andReturn(ImmutableList.of());
265 replay(mockDeviceService);
266
Jian Li9d616492016-03-09 10:52:49 -0800267 WebTarget wt = target();
268 String response = wt.path("devices").request().get(String.class);
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800269 assertThat(response, is("{\"devices\":[]}"));
270 }
271
272 /**
273 * Tests the result of the rest api GET when there are devices present.
274 */
275 @Test
276 public void testDevices() {
277 Device device1 = device("dev1");
278 Device device2 = device("dev2");
279 Device device3 = device("dev3");
280
281 expect(mockDeviceService.getDevices())
282 .andReturn(ImmutableList.of(device1, device2, device3))
283 .anyTimes();
284
285 replay(mockDeviceService);
286
kalagesa42019542017-03-14 18:00:47 +0530287 expect(mockDriverService.getDriver(did("dev1")))
288 .andReturn(driver)
289 .anyTimes();
290
291 expect(mockDriverService.getDriver(did("dev2")))
292 .andReturn(driver)
293 .anyTimes();
294
295 expect(mockDriverService.getDriver(did("dev3")))
296 .andReturn(driver)
297 .anyTimes();
298
299 replay(mockDriverService);
300
301
302
Jian Li9d616492016-03-09 10:52:49 -0800303 WebTarget wt = target();
304 String response = wt.path("devices").request().get(String.class);
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800305 assertThat(response, containsString("{\"devices\":["));
306
Jian Li80cfe452016-01-14 16:04:58 -0800307 JsonObject result = Json.parse(response).asObject();
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800308 assertThat(result, notNullValue());
309
310 assertThat(result.names(), hasSize(1));
311 assertThat(result.names().get(0), is("devices"));
312
313 JsonArray jsonDevices = result.get("devices").asArray();
314 assertThat(jsonDevices, notNullValue());
315 assertThat(jsonDevices.size(), is(3));
316
317 assertThat(jsonDevices, hasDevice(device1));
318 assertThat(jsonDevices, hasDevice(device2));
319 assertThat(jsonDevices, hasDevice(device3));
320 }
321
322 /**
323 * Tests the result of a rest api GET for a single device.
324 */
325 @Test
326 public void testDevicesSingle() {
327
328 String deviceIdString = "testdevice";
329 DeviceId deviceId = did(deviceIdString);
330 Device device = device(deviceIdString);
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800331 expect(mockDeviceService.getDevice(deviceId))
332 .andReturn(device)
333 .once();
334 replay(mockDeviceService);
kalagesa42019542017-03-14 18:00:47 +0530335 expect(mockDriverService.getDriver(deviceId))
336 .andReturn(driver)
337 .anyTimes();
338 replay(mockDriverService);
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800339
Jian Li9d616492016-03-09 10:52:49 -0800340 WebTarget wt = target();
341 String response = wt.path("devices/" + deviceId).request().get(String.class);
Jian Li80cfe452016-01-14 16:04:58 -0800342 JsonObject result = Json.parse(response).asObject();
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800343 assertThat(result, matchesDevice(device));
344 }
345
346 /**
347 * Tests the result of a rest api GET for the ports of a single device.
348 */
349 @Test
350 public void testDeviceAndPorts() {
351
352 String deviceIdString = "testdevice";
353 DeviceId deviceId = did(deviceIdString);
354 Device device = device(deviceIdString);
355
kalagesa42019542017-03-14 18:00:47 +0530356
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800357 Port port1 = new DefaultPort(device, portNumber(1), true);
358 Port port2 = new DefaultPort(device, portNumber(2), true);
359 Port port3 = new DefaultPort(device, portNumber(3), true);
360 List<Port> ports = ImmutableList.of(port1, port2, port3);
361
362 expect(mockDeviceService.getDevice(deviceId))
363 .andReturn(device)
364 .once();
365
366 expect(mockDeviceService.getPorts(deviceId))
367 .andReturn(ports)
368 .once();
369 replay(mockDeviceService);
370
kalagesa42019542017-03-14 18:00:47 +0530371 expect(mockDriverService.getDriver(deviceId))
372 .andReturn(driver)
373 .anyTimes();
374 replay(mockDriverService);
375
376
Jian Li9d616492016-03-09 10:52:49 -0800377 WebTarget wt = target();
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800378 String response =
Jian Li9d616492016-03-09 10:52:49 -0800379 wt.path("devices/" + deviceId + "/ports").request()
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800380 .get(String.class);
Jian Li80cfe452016-01-14 16:04:58 -0800381 JsonObject result = Json.parse(response).asObject();
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800382 assertThat(result, matchesDevice(device));
383
384 JsonArray jsonPorts = result.get("ports").asArray();
385 assertThat(jsonPorts.size(), is(3));
386 for (int portIndex = 0; portIndex < jsonPorts.size(); portIndex++) {
387 JsonObject jsonPort = jsonPorts.get(portIndex).asObject();
388
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800389 assertThat(jsonPort.get("port").asString(),
390 is(Integer.toString(portIndex + 1)));
391 assertThat(jsonPort.get("isEnabled").asBoolean(),
392 is(true));
393 assertThat(jsonPort.get("type").asString(),
394 equalTo("copper"));
395 assertThat(jsonPort.get("portSpeed").asLong(),
396 is(1000L));
397 }
398 }
399
400 /**
401 * Tests that a fetch of a non-existent device object throws an exception.
402 */
403 @Test
404 public void testBadGet() {
405
406 expect(mockDeviceService.getDevice(isA(DeviceId.class)))
407 .andReturn(null)
408 .anyTimes();
409 replay(mockDeviceService);
410
Jian Li9d616492016-03-09 10:52:49 -0800411 WebTarget wt = target();
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800412 try {
Jian Li9d616492016-03-09 10:52:49 -0800413 wt.path("devices/0").request().get(String.class);
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800414 fail("Fetch of non-existent device did not throw an exception");
Jian Li9d616492016-03-09 10:52:49 -0800415 } catch (NotFoundException ex) {
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800416 assertThat(ex.getMessage(),
Jian Li9d616492016-03-09 10:52:49 -0800417 containsString("HTTP 404 Not Found"));
Ray Milkey8fd68ca2015-01-27 15:19:09 -0800418 }
419 }
420}