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