blob: 63c669873820ccbee9a466604ee8a1a2a0ce6df5 [file] [log] [blame]
Claudine Chiufb8b8162016-04-01 23:50:51 +00001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
Claudine Chiufb8b8162016-04-01 23:50:51 +00003 *
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 */
16
17package org.onosproject.rest.resources;
18
19import com.eclipsesource.json.Json;
20import com.eclipsesource.json.JsonArray;
21import com.eclipsesource.json.JsonObject;
22import com.google.common.collect.ImmutableList;
23import com.google.common.collect.ImmutableSet;
24import org.glassfish.jersey.client.ClientProperties;
25import org.hamcrest.Description;
26import org.hamcrest.Matchers;
27import org.hamcrest.TypeSafeMatcher;
28import org.junit.Before;
29import org.junit.Test;
30import org.onlab.osgi.ServiceDirectory;
31import org.onlab.osgi.TestServiceDirectory;
32import org.onlab.rest.BaseResource;
33import org.onosproject.codec.CodecService;
34import org.onosproject.codec.impl.CodecManager;
Claudine Chiuf6bf8d52016-04-08 01:31:54 +000035import org.onosproject.incubator.net.tunnel.TunnelId;
Claudine Chiufb8b8162016-04-01 23:50:51 +000036import org.onosproject.incubator.net.virtual.DefaultVirtualDevice;
Claudine Chiuf6bf8d52016-04-08 01:31:54 +000037import org.onosproject.incubator.net.virtual.DefaultVirtualLink;
Claudine Chiufb8b8162016-04-01 23:50:51 +000038import org.onosproject.incubator.net.virtual.DefaultVirtualNetwork;
39import org.onosproject.incubator.net.virtual.DefaultVirtualPort;
40import org.onosproject.incubator.net.virtual.NetworkId;
41import org.onosproject.incubator.net.virtual.TenantId;
42import org.onosproject.incubator.net.virtual.VirtualDevice;
Claudine Chiuf6bf8d52016-04-08 01:31:54 +000043import org.onosproject.incubator.net.virtual.VirtualLink;
Claudine Chiufb8b8162016-04-01 23:50:51 +000044import org.onosproject.incubator.net.virtual.VirtualNetwork;
45import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
46import org.onosproject.incubator.net.virtual.VirtualNetworkService;
47import org.onosproject.incubator.net.virtual.VirtualPort;
Claudine Chiuf6bf8d52016-04-08 01:31:54 +000048import org.onosproject.net.ConnectPoint;
Claudine Chiufb8b8162016-04-01 23:50:51 +000049import org.onosproject.net.DefaultAnnotations;
50import org.onosproject.net.DefaultDevice;
51import org.onosproject.net.DefaultPort;
52import org.onosproject.net.Device;
53import org.onosproject.net.DeviceId;
54import org.onosproject.net.NetTestTools;
55import org.onosproject.net.Port;
56import org.onosproject.net.PortNumber;
57
58import javax.ws.rs.BadRequestException;
59import javax.ws.rs.NotFoundException;
60import javax.ws.rs.client.Entity;
61import javax.ws.rs.client.WebTarget;
62import javax.ws.rs.core.MediaType;
63import javax.ws.rs.core.Response;
64import java.io.InputStream;
65import java.net.HttpURLConnection;
66import java.util.HashSet;
67import java.util.List;
Claudine Chiuf6bf8d52016-04-08 01:31:54 +000068import java.util.Set;
Claudine Chiufb8b8162016-04-01 23:50:51 +000069import java.util.function.BiFunction;
70import java.util.function.BiPredicate;
71import java.util.function.Function;
72
Jian Li08d65cf2016-04-20 10:07:17 -070073import static org.easymock.EasyMock.anyObject;
74import static org.easymock.EasyMock.createMock;
75import static org.easymock.EasyMock.expect;
76import static org.easymock.EasyMock.expectLastCall;
77import static org.easymock.EasyMock.replay;
78import static org.easymock.EasyMock.verify;
79import static org.hamcrest.Matchers.containsString;
80import static org.hamcrest.Matchers.hasSize;
81import static org.hamcrest.Matchers.is;
82import static org.hamcrest.Matchers.notNullValue;
83import static org.junit.Assert.assertEquals;
84import static org.junit.Assert.assertThat;
85import static org.junit.Assert.fail;
Claudine Chiufb8b8162016-04-01 23:50:51 +000086import static org.onosproject.net.PortNumber.portNumber;
87
88/**
89 * Unit tests for virtual network REST APIs.
90 */
91public class VirtualNetworkWebResourceTest extends ResourceTest {
92
93 private final VirtualNetworkAdminService mockVnetAdminService = createMock(VirtualNetworkAdminService.class);
94 private final VirtualNetworkService mockVnetService = createMock(VirtualNetworkService.class);
95 private CodecManager codecService;
96
97 final HashSet<TenantId> tenantIdSet = new HashSet<>();
Claudine Chiufb8b8162016-04-01 23:50:51 +000098 final HashSet<VirtualDevice> vdevSet = new HashSet<>();
99 final HashSet<VirtualPort> vportSet = new HashSet<>();
100
101 private static final String ID = "networkId";
102 private static final String TENANT_ID = "tenantId";
103 private static final String DEVICE_ID = "deviceId";
104 private static final String PORT_NUM = "portNum";
105 private static final String PHYS_DEVICE_ID = "physDeviceId";
106 private static final String PHYS_PORT_NUM = "physPortNum";
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000107 private static final String TUNNEL_ID = "tunnelId";
Claudine Chiufb8b8162016-04-01 23:50:51 +0000108
109 private final TenantId tenantId1 = TenantId.tenantId("TenantId1");
110 private final TenantId tenantId2 = TenantId.tenantId("TenantId2");
111 private final TenantId tenantId3 = TenantId.tenantId("TenantId3");
112 private final TenantId tenantId4 = TenantId.tenantId("TenantId4");
113
114 private final NetworkId networkId1 = NetworkId.networkId(1);
115 private final NetworkId networkId2 = NetworkId.networkId(2);
116 private final NetworkId networkId3 = NetworkId.networkId(3);
117 private final NetworkId networkId4 = NetworkId.networkId(4);
118
119 private final VirtualNetwork vnet1 = new DefaultVirtualNetwork(networkId1, tenantId3);
120 private final VirtualNetwork vnet2 = new DefaultVirtualNetwork(networkId2, tenantId3);
121 private final VirtualNetwork vnet3 = new DefaultVirtualNetwork(networkId3, tenantId3);
122 private final VirtualNetwork vnet4 = new DefaultVirtualNetwork(networkId4, tenantId3);
123
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000124 private final DeviceId devId1 = DeviceId.deviceId("devid1");
125 private final DeviceId devId2 = DeviceId.deviceId("devid2");
Claudine Chiufb8b8162016-04-01 23:50:51 +0000126 private final DeviceId devId22 = DeviceId.deviceId("dev22");
127
128 private final VirtualDevice vdev1 = new DefaultVirtualDevice(networkId3, devId1);
129 private final VirtualDevice vdev2 = new DefaultVirtualDevice(networkId3, devId2);
130
131 private final Device dev1 = NetTestTools.device("dev1");
132 private final Device dev2 = NetTestTools.device("dev2");
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000133 private final Device dev21 = NetTestTools.device("dev21");
Claudine Chiufb8b8162016-04-01 23:50:51 +0000134 private final Device dev22 = NetTestTools.device("dev22");
135
136 Port port1 = new DefaultPort(dev1, portNumber(1), true);
137 Port port2 = new DefaultPort(dev2, portNumber(2), true);
138
139 private final VirtualPort vport22 = new DefaultVirtualPort(networkId3,
140 dev22, portNumber(22), port1);
141 private final VirtualPort vport23 = new DefaultVirtualPort(networkId3,
142 dev22, portNumber(23), port2);
143
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000144 private final ConnectPoint cp11 = NetTestTools.connectPoint(devId1.toString(), 21);
145 private final ConnectPoint cp21 = NetTestTools.connectPoint(devId2.toString(), 22);
146 private final ConnectPoint cp12 = NetTestTools.connectPoint(devId1.toString(), 2);
147 private final ConnectPoint cp22 = NetTestTools.connectPoint(devId2.toString(), 22);
148
149 private final TunnelId tunnelId = TunnelId.valueOf(31);
150 private final VirtualLink vlink1 = new DefaultVirtualLink(networkId3, cp22, cp11, tunnelId);
151 private final VirtualLink vlink2 = new DefaultVirtualLink(networkId3, cp12, cp21, tunnelId);
152
Claudine Chiufb8b8162016-04-01 23:50:51 +0000153 /**
154 * Sets up the global values for all the tests.
155 */
156 @Before
157 public void setUpTest() {
158 // Register the services needed for the test
159 codecService = new CodecManager();
160 codecService.activate();
161 ServiceDirectory testDirectory =
162 new TestServiceDirectory()
163 .add(VirtualNetworkAdminService.class, mockVnetAdminService)
164 .add(VirtualNetworkService.class, mockVnetService)
165 .add(CodecService.class, codecService);
166
167 BaseResource.setServiceDirectory(testDirectory);
168 }
169
170 /**
171 * Hamcrest matcher to check that a virtual network entity representation in JSON matches
172 * the actual virtual network entity.
173 */
174 public static class JsonObjectMatcher<T> extends TypeSafeMatcher<JsonObject> {
175 private final T vnetEntity;
176 private List<String> jsonFieldNames;
177 private String reason = "";
178 private BiFunction<T, String, String> getValue; // get vnetEntity's value
179
180 public JsonObjectMatcher(T vnetEntityValue,
181 List<String> jsonFieldNames1,
182 BiFunction<T, String, String> getValue1) {
183 vnetEntity = vnetEntityValue;
184 jsonFieldNames = jsonFieldNames1;
185 getValue = getValue1;
186 }
187
188 @Override
189 public boolean matchesSafely(JsonObject jsonHost) {
190 return jsonFieldNames
191 .stream()
192 .allMatch(s -> checkField(jsonHost, s, getValue.apply(vnetEntity, s)));
193 }
194
195 private boolean checkField(JsonObject jsonHost, String jsonFieldName,
196 String objectValue) {
197 final String jsonValue = jsonHost.get(jsonFieldName).asString();
198 if (!jsonValue.equals(objectValue)) {
199 reason = jsonFieldName + " " + objectValue;
200 return false;
201 }
202 return true;
203 }
204
205 @Override
206 public void describeTo(Description description) {
207 description.appendText(reason);
208 }
209 }
210
211 /**
212 * Factory to allocate a virtual network id array matcher.
213 *
214 * @param obj virtual network id object we are looking for
215 * @return matcher
216 */
217 /**
218 * Factory to allocate a virtual network entity matcher.
219 *
220 * @param obj virtual network object we are looking for
221 * @param jsonFieldNames JSON field names to check against
222 * @param getValue function to retrieve value from virtual network object
223 * @param <T>
224 * @return JsonObjectMatcher
225 */
226 private static <T> JsonObjectMatcher matchesVnetEntity(T obj, List<String> jsonFieldNames,
227 BiFunction<T, String, String> getValue) {
228 return new JsonObjectMatcher(obj, jsonFieldNames, getValue);
229 }
230
231 /**
232 * Hamcrest matcher to check that a virtual network entity is represented properly in a JSON
233 * array of virtual network entities.
234 */
235 public static class JsonArrayMatcher<T> extends TypeSafeMatcher<JsonArray> {
236 private final T vnetEntity;
237 private String reason = "";
238 private Function<T, String> getKey; // gets vnetEntity's key
239 private BiPredicate<T, JsonObject> checkKey; // check vnetEntity's key with JSON rep'n
240 private List<String> jsonFieldNames; // field/property names
241 private BiFunction<T, String, String> getValue; // get vnetEntity's value
242
243 public JsonArrayMatcher(T vnetEntityValue, Function<T, String> getKey1,
244 BiPredicate<T, JsonObject> checkKey1,
245 List<String> jsonFieldNames1,
246 BiFunction<T, String, String> getValue1) {
247 vnetEntity = vnetEntityValue;
248 getKey = getKey1;
249 checkKey = checkKey1;
250 jsonFieldNames = jsonFieldNames1;
251 getValue = getValue1;
252 }
253
254 @Override
255 public boolean matchesSafely(JsonArray json) {
256 boolean itemFound = false;
257 final int expectedAttributes = jsonFieldNames.size();
258 for (int jsonArrayIndex = 0; jsonArrayIndex < json.size();
259 jsonArrayIndex++) {
260
261 final JsonObject jsonHost = json.get(jsonArrayIndex).asObject();
262
263 if (jsonHost.names().size() < expectedAttributes) {
264 reason = "Found a virtual network with the wrong number of attributes";
265 return false;
266 }
267
268 if (checkKey != null && checkKey.test(vnetEntity, jsonHost)) {
269 itemFound = true;
270 assertThat(jsonHost, matchesVnetEntity(vnetEntity, jsonFieldNames, getValue));
271 }
272 }
273 if (!itemFound) {
274 reason = getKey.apply(vnetEntity) + " was not found";
275 return false;
276 }
277 return true;
278 }
279
280 @Override
281 public void describeTo(Description description) {
282 description.appendText(reason);
283 }
284 }
285
286 /**
287 * Array matcher for VirtualNetwork.
288 */
289 public static class VnetJsonArrayMatcher extends JsonArrayMatcher<VirtualNetwork> {
290
291 public VnetJsonArrayMatcher(VirtualNetwork vnetIn) {
292 super(vnetIn,
293 vnet -> "Virtual network " + vnet.id().toString(),
Jian Li08d65cf2016-04-20 10:07:17 -0700294 (vnet, jsonObject) -> jsonObject.get(ID).asString().equals(vnet.id().toString()),
Claudine Chiufb8b8162016-04-01 23:50:51 +0000295 ImmutableList.of(ID, TENANT_ID),
Jian Li08d65cf2016-04-20 10:07:17 -0700296 (vnet, s) -> s.equals(ID) ? vnet.id().toString()
297 : s.equals(TENANT_ID) ? vnet.tenantId().toString()
298 : null
Claudine Chiufb8b8162016-04-01 23:50:51 +0000299 );
300 }
301 }
302
303 /**
304 * Factory to allocate a virtual network array matcher.
305 *
306 * @param vnet virtual network object we are looking for
307 * @return matcher
308 */
309 private VnetJsonArrayMatcher hasVnet(VirtualNetwork vnet) {
310 return new VnetJsonArrayMatcher(vnet);
311 }
312
313 // Tests for Virtual Networks
314
315 /**
316 * Tests the result of the REST API GET when there are no virtual networks.
317 */
318 @Test
319 public void testGetVirtualNetworksEmptyArray() {
320 expect(mockVnetAdminService.getTenantIds()).andReturn(ImmutableSet.of()).anyTimes();
321 replay(mockVnetAdminService);
322 expect(mockVnetService.getVirtualNetworks(tenantId4)).andReturn(ImmutableSet.of()).anyTimes();
323 replay(mockVnetService);
324
325 WebTarget wt = target();
326 String response = wt.path("vnets").request().get(String.class);
327 assertThat(response, is("{\"vnets\":[]}"));
328
329 verify(mockVnetService);
330 verify(mockVnetAdminService);
331 }
332
333 /**
334 * Tests the result of the REST API GET when virtual networks are defined.
335 */
336 @Test
337 public void testGetVirtualNetworksArray() {
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000338 final Set<VirtualNetwork> vnetSet = ImmutableSet.of(vnet1, vnet2, vnet3, vnet4);
Claudine Chiufb8b8162016-04-01 23:50:51 +0000339 expect(mockVnetAdminService.getTenantIds()).andReturn(ImmutableSet.of(tenantId3)).anyTimes();
340 replay(mockVnetAdminService);
Claudine Chiufb8b8162016-04-01 23:50:51 +0000341 expect(mockVnetService.getVirtualNetworks(tenantId3)).andReturn(vnetSet).anyTimes();
342 replay(mockVnetService);
343
344 WebTarget wt = target();
345 String response = wt.path("vnets").request().get(String.class);
346 assertThat(response, containsString("{\"vnets\":["));
347
348 final JsonObject result = Json.parse(response).asObject();
349 assertThat(result, notNullValue());
350
351 assertThat(result.names(), hasSize(1));
352 assertThat(result.names().get(0), is("vnets"));
353
354 final JsonArray vnetJsonArray = result.get("vnets").asArray();
355 assertThat(vnetJsonArray, notNullValue());
356 assertEquals("Virtual networks array is not the correct size.",
357 vnetSet.size(), vnetJsonArray.size());
358
359 vnetSet.forEach(vnet -> assertThat(vnetJsonArray, hasVnet(vnet)));
360
361 verify(mockVnetService);
362 verify(mockVnetAdminService);
363 }
364
365 /**
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000366 * Tests the result of the REST API GET for virtual networks with tenant id.
367 */
368 @Test
369 public void testGetVirtualNetworksByTenantId() {
370 final Set<VirtualNetwork> vnetSet = ImmutableSet.of(vnet1, vnet2, vnet3, vnet4);
371 expect(mockVnetAdminService.getTenantIds()).andReturn(ImmutableSet.of(tenantId3)).anyTimes();
372 replay(mockVnetAdminService);
373 expect(mockVnetService.getVirtualNetworks(tenantId3)).andReturn(vnetSet).anyTimes();
374 replay(mockVnetService);
375
376 WebTarget wt = target();
377 String response = wt.path("vnets/" + tenantId3.id()).request().get(String.class);
378 assertThat(response, containsString("{\"vnets\":["));
379
380 final JsonObject result = Json.parse(response).asObject();
381 assertThat(result, notNullValue());
382
383 assertThat(result.names(), hasSize(1));
384 assertThat(result.names().get(0), is("vnets"));
385
386 final JsonArray vnetJsonArray = result.get("vnets").asArray();
387 assertThat(vnetJsonArray, notNullValue());
388 assertEquals("Virtual networks array is not the correct size.",
389 vnetSet.size(), vnetJsonArray.size());
390
391 vnetSet.forEach(vnet -> assertThat(vnetJsonArray, hasVnet(vnet)));
392
393 verify(mockVnetService);
394 verify(mockVnetAdminService);
395 }
396
397 /**
398 * Tests the result of the REST API GET for virtual networks with tenant id.
399 */
400 @Test
401 public void testGetVirtualNetworksByNonExistentTenantId() {
402 String tenantIdName = "NON_EXISTENT_TENANT_ID";
403 expect(mockVnetAdminService.getTenantIds()).andReturn(ImmutableSet.of(tenantId3)).anyTimes();
404 replay(mockVnetAdminService);
405 expect(mockVnetService.getVirtualNetworks(anyObject())).andReturn(ImmutableSet.of()).anyTimes();
406 replay(mockVnetService);
407
408 WebTarget wt = target();
409
410 try {
411 wt.path("vnets/" + tenantIdName)
412 .request()
413 .get(String.class);
414 fail("Get of a non-existent virtual network did not throw an exception");
415 } catch (NotFoundException ex) {
416 assertThat(ex.getMessage(), containsString("HTTP 404 Not Found"));
417 }
418
419 verify(mockVnetService);
420 verify(mockVnetAdminService);
421 }
422
423 /**
Claudine Chiufb8b8162016-04-01 23:50:51 +0000424 * Tests adding of new virtual network using POST via JSON stream.
425 */
426 @Test
427 public void testPostVirtualNetwork() {
428 expect(mockVnetAdminService.createVirtualNetwork(tenantId2)).andReturn(vnet1);
429 expectLastCall();
430
431 replay(mockVnetAdminService);
432
433 WebTarget wt = target();
434 InputStream jsonStream = TenantWebResourceTest.class
435 .getResourceAsStream("post-tenant.json");
436
437 Response response = wt.path("vnets").request(MediaType.APPLICATION_JSON_TYPE)
438 .post(Entity.json(jsonStream));
439 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
440
441 String location = response.getLocation().getPath();
442 assertThat(location, Matchers.startsWith("/vnets/" + vnet1.id().toString()));
443
444 verify(mockVnetAdminService);
445 }
446
447 /**
448 * Tests adding of a null virtual network using POST via JSON stream.
449 */
450 @Test
451 public void testPostVirtualNetworkNullTenantId() {
452
453 replay(mockVnetAdminService);
454
455 WebTarget wt = target();
456 try {
Jian Li08d65cf2016-04-20 10:07:17 -0700457 wt.path("vnets")
Claudine Chiufb8b8162016-04-01 23:50:51 +0000458 .request(MediaType.APPLICATION_JSON_TYPE)
459 .post(Entity.json(null), String.class);
460 fail("POST of null virtual network did not throw an exception");
461 } catch (BadRequestException ex) {
462 assertThat(ex.getMessage(), containsString("HTTP 400 Bad Request"));
463 }
464
465 verify(mockVnetAdminService);
466 }
467
468 /**
469 * Tests removing a virtual network with DELETE request.
470 */
471 @Test
472 public void testDeleteVirtualNetwork() {
473 mockVnetAdminService.removeVirtualNetwork(anyObject());
474 expectLastCall();
475 replay(mockVnetAdminService);
476
477 WebTarget wt = target()
478 .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
479 Response response = wt.path("vnets/" + "2")
480 .request(MediaType.APPLICATION_JSON_TYPE)
481 .delete();
482
483 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
484
485 verify(mockVnetAdminService);
486 }
487
488 /**
489 * Tests that a DELETE of a non-existent virtual network throws an exception.
490 */
491 @Test
492 public void testDeleteNetworkNonExistentNetworkId() {
493 expect(mockVnetAdminService.getTenantIds())
494 .andReturn(ImmutableSet.of())
495 .anyTimes();
496 expectLastCall();
497
498 replay(mockVnetAdminService);
499
500 WebTarget wt = target();
501
502 try {
503 wt.path("vnets/" + "NON_EXISTENT_NETWORK_ID")
504 .request()
505 .delete(String.class);
506 fail("Delete of a non-existent virtual network did not throw an exception");
507 } catch (NotFoundException ex) {
508 assertThat(ex.getMessage(), containsString("HTTP 404 Not Found"));
509 }
510
511 verify(mockVnetAdminService);
512 }
513
514 // Tests for Virtual Device
515
516 /**
517 * Tests the result of the REST API GET when there are no virtual devices.
518 */
519 @Test
520 public void testGetVirtualDevicesEmptyArray() {
521 NetworkId networkId = networkId4;
522 expect(mockVnetService.getVirtualDevices(networkId)).andReturn(ImmutableSet.of()).anyTimes();
523 replay(mockVnetService);
524
525 WebTarget wt = target();
526 String location = "vnets/" + networkId.toString() + "/devices";
527 String response = wt.path(location).request().get(String.class);
528 assertThat(response, is("{\"devices\":[]}"));
529
530 verify(mockVnetService);
531 }
532
533 /**
534 * Tests the result of the REST API GET when virtual devices are defined.
535 */
536 @Test
537 public void testGetVirtualDevicesArray() {
538 NetworkId networkId = networkId3;
539 vdevSet.add(vdev1);
540 vdevSet.add(vdev2);
541 expect(mockVnetService.getVirtualDevices(networkId)).andReturn(vdevSet).anyTimes();
542 replay(mockVnetService);
543
544 WebTarget wt = target();
545 String location = "vnets/" + networkId.toString() + "/devices";
546 String response = wt.path(location).request().get(String.class);
547 assertThat(response, containsString("{\"devices\":["));
548
549 final JsonObject result = Json.parse(response).asObject();
550 assertThat(result, notNullValue());
551
552 assertThat(result.names(), hasSize(1));
553 assertThat(result.names().get(0), is("devices"));
554
555 final JsonArray vnetJsonArray = result.get("devices").asArray();
556 assertThat(vnetJsonArray, notNullValue());
557 assertEquals("Virtual devices array is not the correct size.",
558 vdevSet.size(), vnetJsonArray.size());
559
560 vdevSet.forEach(vdev -> assertThat(vnetJsonArray, hasVdev(vdev)));
561
562 verify(mockVnetService);
563 }
564
565 /**
566 * Array matcher for VirtualDevice.
567 */
568 public static class VdevJsonArrayMatcher extends JsonArrayMatcher<VirtualDevice> {
569
570 public VdevJsonArrayMatcher(VirtualDevice vdevIn) {
571 super(vdevIn,
572 vdev -> "Virtual device " + vdev.networkId().toString()
573 + " " + vdev.id().toString(),
Jian Li08d65cf2016-04-20 10:07:17 -0700574 (vdev, jsonObject) -> jsonObject.get(ID).asString().equals(vdev.networkId().toString())
575 && jsonObject.get(DEVICE_ID).asString().equals(vdev.id().toString()),
Claudine Chiufb8b8162016-04-01 23:50:51 +0000576 ImmutableList.of(ID, DEVICE_ID),
Jian Li08d65cf2016-04-20 10:07:17 -0700577 (vdev, s) -> s.equals(ID) ? vdev.networkId().toString()
578 : s.equals(DEVICE_ID) ? vdev.id().toString()
579 : null
Claudine Chiufb8b8162016-04-01 23:50:51 +0000580 );
581 }
582 }
583
584 /**
585 * Factory to allocate a virtual device array matcher.
586 *
587 * @param vdev virtual device object we are looking for
588 * @return matcher
589 */
590 private VdevJsonArrayMatcher hasVdev(VirtualDevice vdev) {
591 return new VdevJsonArrayMatcher(vdev);
592 }
593 /**
594 * Tests adding of new virtual device using POST via JSON stream.
595 */
596 @Test
597 public void testPostVirtualDevice() {
598 NetworkId networkId = networkId3;
599 DeviceId deviceId = devId2;
600 expect(mockVnetAdminService.createVirtualDevice(networkId, deviceId)).andReturn(vdev2);
601 expectLastCall();
602
603 replay(mockVnetAdminService);
604
605 WebTarget wt = target();
606 InputStream jsonStream = VirtualNetworkWebResourceTest.class
607 .getResourceAsStream("post-virtual-device.json");
608 String reqLocation = "vnets/" + networkId.toString() + "/devices";
609 Response response = wt.path(reqLocation).request(MediaType.APPLICATION_JSON_TYPE)
610 .post(Entity.json(jsonStream));
611 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
612
613 String location = response.getLocation().getPath();
614 assertThat(location, Matchers.startsWith("/" + reqLocation + "/" + vdev2.id().toString()));
615
616 verify(mockVnetAdminService);
617 }
618
619 /**
620 * Tests adding of a null virtual device using POST via JSON stream.
621 */
622 @Test
623 public void testPostVirtualDeviceNullJsonStream() {
624 NetworkId networkId = networkId3;
625 replay(mockVnetAdminService);
626
627 WebTarget wt = target();
628 try {
629 String reqLocation = "vnets/" + networkId.toString() + "/devices";
Jian Li08d65cf2016-04-20 10:07:17 -0700630 wt.path(reqLocation)
Claudine Chiufb8b8162016-04-01 23:50:51 +0000631 .request(MediaType.APPLICATION_JSON_TYPE)
632 .post(Entity.json(null), String.class);
633 fail("POST of null virtual device did not throw an exception");
634 } catch (BadRequestException ex) {
635 assertThat(ex.getMessage(), containsString("HTTP 400 Bad Request"));
636 }
637
638 verify(mockVnetAdminService);
639 }
640
641 /**
642 * Tests removing a virtual device with DELETE request.
643 */
644 @Test
645 public void testDeleteVirtualDevice() {
646 NetworkId networkId = networkId3;
647 DeviceId deviceId = devId2;
648 mockVnetAdminService.removeVirtualDevice(networkId, deviceId);
649 expectLastCall();
650 replay(mockVnetAdminService);
651
652 WebTarget wt = target()
653 .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
654 String reqLocation = "vnets/" + networkId.toString() + "/devices/" + deviceId.toString();
655 Response response = wt.path(reqLocation)
656 .request(MediaType.APPLICATION_JSON_TYPE)
657 .delete();
658
659 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
660
661 verify(mockVnetAdminService);
662 }
663
664 // Tests for Virtual Ports
665
666 /**
667 * Tests the result of the REST API GET when there are no virtual ports.
668 */
669 @Test
670 public void testGetVirtualPortsEmptyArray() {
671 NetworkId networkId = networkId4;
672 DeviceId deviceId = devId2;
673 expect(mockVnetService.getVirtualPorts(networkId, deviceId))
674 .andReturn(ImmutableSet.of()).anyTimes();
675 replay(mockVnetService);
676
677 WebTarget wt = target();
678 String location = "vnets/" + networkId.toString()
679 + "/devices/" + deviceId.toString() + "/ports";
680 String response = wt.path(location).request().get(String.class);
681 assertThat(response, is("{\"ports\":[]}"));
682
683 verify(mockVnetService);
684 }
685
686 /**
687 * Tests the result of the REST API GET when virtual ports are defined.
688 */
689 @Test
690 public void testGetVirtualPortsArray() {
691 NetworkId networkId = networkId3;
692 DeviceId deviceId = dev22.id();
693 vportSet.add(vport23);
694 vportSet.add(vport22);
695 expect(mockVnetService.getVirtualPorts(networkId, deviceId)).andReturn(vportSet).anyTimes();
696 replay(mockVnetService);
697
698 WebTarget wt = target();
699 String location = "vnets/" + networkId.toString()
700 + "/devices/" + deviceId.toString() + "/ports";
701 String response = wt.path(location).request().get(String.class);
702 assertThat(response, containsString("{\"ports\":["));
703
704 final JsonObject result = Json.parse(response).asObject();
705 assertThat(result, notNullValue());
706
707 assertThat(result.names(), hasSize(1));
708 assertThat(result.names().get(0), is("ports"));
709
710 final JsonArray vnetJsonArray = result.get("ports").asArray();
711 assertThat(vnetJsonArray, notNullValue());
712 assertEquals("Virtual ports array is not the correct size.",
713 vportSet.size(), vnetJsonArray.size());
714
715 vportSet.forEach(vport -> assertThat(vnetJsonArray, hasVport(vport)));
716
717 verify(mockVnetService);
718 }
719
720 /**
721 * Array matcher for VirtualPort.
722 */
723 public static class VportJsonArrayMatcher extends JsonArrayMatcher<VirtualPort> {
724
725 public VportJsonArrayMatcher(VirtualPort vportIn) {
726 super(vportIn,
727 vport -> "Virtual port " + vport.networkId().toString() + " "
728 + vport.element().id().toString() + " " + vport.number().toString(),
Jian Li08d65cf2016-04-20 10:07:17 -0700729 (vport, jsonObject) -> jsonObject.get(ID).asString().equals(vport.networkId().toString())
730 && jsonObject.get(PORT_NUM).asString().equals(vport.number().toString())
731 && jsonObject.get(DEVICE_ID).asString().equals(vport.element().id().toString()),
Claudine Chiufb8b8162016-04-01 23:50:51 +0000732 ImmutableList.of(ID, DEVICE_ID, PORT_NUM, PHYS_DEVICE_ID, PHYS_PORT_NUM),
Jian Li08d65cf2016-04-20 10:07:17 -0700733 (vport, s) -> s.equals(ID) ? vport.networkId().toString()
734 : s.equals(DEVICE_ID) ? vport.element().id().toString()
735 : s.equals(PORT_NUM) ? vport.number().toString()
736 : s.equals(PHYS_DEVICE_ID) ? vport.realizedBy().element().id().toString()
737 : s.equals(PHYS_PORT_NUM) ? vport.realizedBy().number().toString()
738 : null
Claudine Chiufb8b8162016-04-01 23:50:51 +0000739 );
740 }
741 }
742
743 /**
744 * Factory to allocate a virtual port array matcher.
745 *
746 * @param vport virtual port object we are looking for
747 * @return matcher
748 */
749 private VportJsonArrayMatcher hasVport(VirtualPort vport) {
750 return new VportJsonArrayMatcher(vport);
751 }
752
753 /**
754 * Tests adding of new virtual port using POST via JSON stream.
755 */
756 @Test
757 public void testPostVirtualPort() {
758 NetworkId networkId = networkId3;
759 DeviceId deviceId = devId22;
760 DefaultAnnotations annotations = DefaultAnnotations.builder().build();
761 Device physDevice = new DefaultDevice(null, DeviceId.deviceId("dev1"),
762 null, null, null, null, null, null, annotations);
763 Port port1 = new DefaultPort(physDevice, portNumber(1), true);
764 expect(mockVnetAdminService.createVirtualPort(networkId, deviceId, portNumber(22), port1))
765 .andReturn(vport22);
766
767 replay(mockVnetAdminService);
768
769 WebTarget wt = target();
770 InputStream jsonStream = VirtualNetworkWebResourceTest.class
771 .getResourceAsStream("post-virtual-port.json");
772 String reqLocation = "vnets/" + networkId.toString()
773 + "/devices/" + deviceId.toString() + "/ports";
774 Response response = wt.path(reqLocation).request(MediaType.APPLICATION_JSON_TYPE)
775 .post(Entity.json(jsonStream));
776 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
777
778 verify(mockVnetAdminService);
779 }
780
781 /**
782 * Tests adding of a null virtual port using POST via JSON stream.
783 */
784 @Test
785 public void testPostVirtualPortNullJsonStream() {
786 NetworkId networkId = networkId3;
787 DeviceId deviceId = devId2;
788 replay(mockVnetAdminService);
789
790 WebTarget wt = target();
791 try {
792 String reqLocation = "vnets/" + networkId.toString()
793 + "/devices/" + deviceId.toString() + "/ports";
Jian Li08d65cf2016-04-20 10:07:17 -0700794 wt.path(reqLocation)
Claudine Chiufb8b8162016-04-01 23:50:51 +0000795 .request(MediaType.APPLICATION_JSON_TYPE)
796 .post(Entity.json(null), String.class);
797 fail("POST of null virtual port did not throw an exception");
798 } catch (BadRequestException ex) {
799 assertThat(ex.getMessage(), containsString("HTTP 400 Bad Request"));
800 }
801
802 verify(mockVnetAdminService);
803 }
804
805 /**
806 * Tests removing a virtual port with DELETE request.
807 */
808 @Test
809 public void testDeleteVirtualPort() {
810 NetworkId networkId = networkId3;
811 DeviceId deviceId = devId2;
812 PortNumber portNum = portNumber(2);
813 mockVnetAdminService.removeVirtualPort(networkId, deviceId, portNum);
814 expectLastCall();
815 replay(mockVnetAdminService);
816
817 WebTarget wt = target()
818 .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
819 String reqLocation = "vnets/" + networkId.toString()
820 + "/devices/" + deviceId.toString() + "/ports/" + portNum.toLong();
821 Response response = wt.path(reqLocation)
822 .request(MediaType.APPLICATION_JSON_TYPE)
823 .delete();
824
825 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
826
827 verify(mockVnetAdminService);
828 }
829
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000830 // Tests for Virtual Links
831
832 /**
833 * Tests the result of the REST API GET when there are no virtual links.
834 */
835 @Test
836 public void testGetVirtualLinksEmptyArray() {
837 NetworkId networkId = networkId4;
838 expect(mockVnetService.getVirtualLinks(networkId)).andReturn(ImmutableSet.of()).anyTimes();
839 replay(mockVnetService);
840
841 WebTarget wt = target();
842 String location = "vnets/" + networkId.toString() + "/links";
843 String response = wt.path(location).request().get(String.class);
844 assertThat(response, is("{\"links\":[]}"));
845
846 verify(mockVnetService);
847 }
848
849 /**
850 * Tests the result of the REST API GET when virtual links are defined.
851 */
852 @Test
853 public void testGetVirtualLinksArray() {
854 NetworkId networkId = networkId3;
855 final Set<VirtualLink> vlinkSet = ImmutableSet.of(vlink1, vlink2);
856 expect(mockVnetService.getVirtualLinks(networkId)).andReturn(vlinkSet).anyTimes();
857 replay(mockVnetService);
858
859 WebTarget wt = target();
860 String location = "vnets/" + networkId.toString() + "/links";
861 String response = wt.path(location).request().get(String.class);
862 assertThat(response, containsString("{\"links\":["));
863
864 final JsonObject result = Json.parse(response).asObject();
865 assertThat(result, notNullValue());
866
867 assertThat(result.names(), hasSize(1));
868 assertThat(result.names().get(0), is("links"));
869
870 final JsonArray vnetJsonArray = result.get("links").asArray();
871 assertThat(vnetJsonArray, notNullValue());
872 assertEquals("Virtual links array is not the correct size.",
873 vlinkSet.size(), vnetJsonArray.size());
874
875 vlinkSet.forEach(vlink -> assertThat(vnetJsonArray, hasVlink(vlink)));
876
877 verify(mockVnetService);
878 }
879
880 /**
881 * Hamcrest matcher to check that a virtual link representation in JSON matches
882 * the actual virtual link.
883 */
884 public static class VirtualLinkJsonMatcher extends LinksResourceTest.LinkJsonMatcher {
885 private final VirtualLink vlink;
886 private String reason = "";
887
888 public VirtualLinkJsonMatcher(VirtualLink vlinkValue) {
889 super(vlinkValue);
890 vlink = vlinkValue;
891 }
892
893 @Override
894 public boolean matchesSafely(JsonObject jsonLink) {
895 if (!super.matchesSafely(jsonLink)) {
896 return false;
897 }
898 // check NetworkId
899 String jsonNetworkId = jsonLink.get(ID).asString();
900 String networkId = vlink.networkId().toString();
901 if (!jsonNetworkId.equals(networkId)) {
902 reason = ID + " was " + jsonNetworkId;
903 return false;
904 }
905 // check TunnelId
906 String jsonTunnelId = jsonLink.get(TUNNEL_ID).asString();
907 if (jsonTunnelId != null && vlink instanceof DefaultVirtualLink) {
908 String tunnelId = ((DefaultVirtualLink) vlink).tunnelId().toString();
909 if (!jsonTunnelId.equals(tunnelId)) {
910 reason = TUNNEL_ID + " was " + jsonTunnelId;
911 return false;
912 }
913 }
914 return true;
915 }
916
917 @Override
918 public void describeTo(Description description) {
919 description.appendText(reason);
920 }
921 }
922
923 /**
924 * Factory to allocate a virtual link matcher.
925 *
926 * @param vlink virtual link object we are looking for
927 * @return matcher
928 */
929 private static VirtualLinkJsonMatcher matchesVirtualLink(VirtualLink vlink) {
930 return new VirtualLinkJsonMatcher(vlink);
931 }
932
933 /**
934 * Hamcrest matcher to check that a virtual link is represented properly in a JSON
935 * array of links.
936 */
937 private static class VirtualLinkJsonArrayMatcher extends TypeSafeMatcher<JsonArray> {
938 private final VirtualLink vlink;
939 private String reason = "";
940
941 public VirtualLinkJsonArrayMatcher(VirtualLink vlinkValue) {
942 vlink = vlinkValue;
943 }
944
945 @Override
946 public boolean matchesSafely(JsonArray json) {
947 final int expectedAttributes = 2;
948
949 for (int jsonLinkIndex = 0; jsonLinkIndex < json.size();
950 jsonLinkIndex++) {
951
952 JsonObject jsonLink = json.get(jsonLinkIndex).asObject();
953
954 if (matchesVirtualLink(vlink).matchesSafely(jsonLink)) {
955 return true;
956 }
957 }
958 return false;
959 }
960
961 @Override
962 public void describeTo(Description description) {
963 description.appendText(reason);
964 }
965 }
966
967 /**
968 * Factory to allocate a virtual link array matcher.
969 *
970 * @param vlink virtual link object we are looking for
971 * @return matcher
972 */
973 private VirtualLinkJsonArrayMatcher hasVlink(VirtualLink vlink) {
974 return new VirtualLinkJsonArrayMatcher(vlink);
975 }
976
977 /**
978 * Tests adding of new virtual link using POST via JSON stream.
979 */
980 @Test
981 public void testPostVirtualLink() {
982 NetworkId networkId = networkId3;
983 expect(mockVnetAdminService.createVirtualLink(networkId, cp22, cp11, tunnelId))
984 .andReturn(vlink1);
985 replay(mockVnetAdminService);
986
987 WebTarget wt = target();
988 InputStream jsonStream = VirtualNetworkWebResourceTest.class
989 .getResourceAsStream("post-virtual-link.json");
990 String reqLocation = "vnets/" + networkId.toString() + "/links";
991 Response response = wt.path(reqLocation).request(MediaType.APPLICATION_JSON_TYPE)
992 .post(Entity.json(jsonStream));
993 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
994
995 String location = response.getLocation().getPath();
996 assertThat(location, Matchers.startsWith("/" + reqLocation));
997
998 verify(mockVnetAdminService);
999 }
1000
1001 /**
1002 * Tests adding of a null virtual link using POST via JSON stream.
1003 */
1004 @Test
1005 public void testPostVirtualLinkNullJsonStream() {
1006 NetworkId networkId = networkId3;
1007 replay(mockVnetAdminService);
1008
1009 WebTarget wt = target();
1010 try {
1011 String reqLocation = "vnets/" + networkId.toString() + "/links";
1012 wt.path(reqLocation)
1013 .request(MediaType.APPLICATION_JSON_TYPE)
1014 .post(Entity.json(null), String.class);
1015 fail("POST of null virtual link did not throw an exception");
1016 } catch (BadRequestException ex) {
1017 assertThat(ex.getMessage(), containsString("HTTP 400 Bad Request"));
1018 }
1019
1020 verify(mockVnetAdminService);
1021 }
1022
1023 /**
1024 * Tests removing a virtual link with DELETE request.
1025 */
1026 @Test
1027 public void testDeleteVirtualLink() {
1028 NetworkId networkId = networkId3;
1029 mockVnetAdminService.removeVirtualLink(networkId, cp22, cp11);
1030 expectLastCall();
1031 replay(mockVnetAdminService);
1032
1033 WebTarget wt = target()
1034 .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
1035 InputStream jsonStream = VirtualNetworkWebResourceTest.class
1036 .getResourceAsStream("post-virtual-link.json");
1037 String reqLocation = "vnets/" + networkId.toString() + "/links";
Jian Li08d65cf2016-04-20 10:07:17 -07001038 Response response = wt.path(reqLocation).request().method("DELETE", Entity.json(jsonStream));
Claudine Chiuf6bf8d52016-04-08 01:31:54 +00001039
1040 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
1041 verify(mockVnetAdminService);
1042 }
Claudine Chiufb8b8162016-04-01 23:50:51 +00001043}