blob: 2ab185cc736c404f5a210887b78de0e80f7b4cfb [file] [log] [blame]
Claudine Chiufb8b8162016-04-01 23:50:51 +00001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
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;
Claudine Chiu25f07be2016-06-27 16:21:21 +000024import com.google.common.collect.Sets;
Claudine Chiufb8b8162016-04-01 23:50:51 +000025import org.glassfish.jersey.client.ClientProperties;
26import org.hamcrest.Description;
27import org.hamcrest.Matchers;
28import org.hamcrest.TypeSafeMatcher;
29import org.junit.Before;
30import org.junit.Test;
31import org.onlab.osgi.ServiceDirectory;
32import org.onlab.osgi.TestServiceDirectory;
Claudine Chiu25f07be2016-06-27 16:21:21 +000033import org.onlab.packet.IpAddress;
34import org.onlab.packet.MacAddress;
35import org.onlab.packet.VlanId;
Claudine Chiufb8b8162016-04-01 23:50:51 +000036import org.onosproject.codec.CodecService;
37import org.onosproject.codec.impl.CodecManager;
38import org.onosproject.incubator.net.virtual.DefaultVirtualDevice;
Claudine Chiu25f07be2016-06-27 16:21:21 +000039import org.onosproject.incubator.net.virtual.DefaultVirtualHost;
Claudine Chiuf6bf8d52016-04-08 01:31:54 +000040import org.onosproject.incubator.net.virtual.DefaultVirtualLink;
Claudine Chiufb8b8162016-04-01 23:50:51 +000041import org.onosproject.incubator.net.virtual.DefaultVirtualNetwork;
42import org.onosproject.incubator.net.virtual.DefaultVirtualPort;
43import org.onosproject.incubator.net.virtual.NetworkId;
44import org.onosproject.incubator.net.virtual.TenantId;
45import org.onosproject.incubator.net.virtual.VirtualDevice;
Claudine Chiu25f07be2016-06-27 16:21:21 +000046import org.onosproject.incubator.net.virtual.VirtualHost;
Claudine Chiuf6bf8d52016-04-08 01:31:54 +000047import org.onosproject.incubator.net.virtual.VirtualLink;
Claudine Chiufb8b8162016-04-01 23:50:51 +000048import org.onosproject.incubator.net.virtual.VirtualNetwork;
49import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
50import org.onosproject.incubator.net.virtual.VirtualNetworkService;
51import org.onosproject.incubator.net.virtual.VirtualPort;
Claudine Chiuf6bf8d52016-04-08 01:31:54 +000052import org.onosproject.net.ConnectPoint;
Claudine Chiufb8b8162016-04-01 23:50:51 +000053import org.onosproject.net.DefaultAnnotations;
54import org.onosproject.net.DefaultDevice;
Claudine Chiufb8b8162016-04-01 23:50:51 +000055import org.onosproject.net.Device;
56import org.onosproject.net.DeviceId;
Claudine Chiu25f07be2016-06-27 16:21:21 +000057import org.onosproject.net.HostId;
58import org.onosproject.net.HostLocation;
Claudine Chiufb8b8162016-04-01 23:50:51 +000059import org.onosproject.net.NetTestTools;
Claudine Chiufb8b8162016-04-01 23:50:51 +000060import org.onosproject.net.PortNumber;
61
62import javax.ws.rs.BadRequestException;
63import javax.ws.rs.NotFoundException;
64import javax.ws.rs.client.Entity;
65import javax.ws.rs.client.WebTarget;
66import javax.ws.rs.core.MediaType;
67import javax.ws.rs.core.Response;
68import java.io.InputStream;
69import java.net.HttpURLConnection;
70import java.util.HashSet;
71import java.util.List;
Claudine Chiuf6bf8d52016-04-08 01:31:54 +000072import java.util.Set;
Claudine Chiufb8b8162016-04-01 23:50:51 +000073import java.util.function.BiFunction;
74import java.util.function.BiPredicate;
75import java.util.function.Function;
76
Ray Milkey094a1352018-01-22 14:03:54 -080077import static org.easymock.EasyMock.anyObject;
78import static org.easymock.EasyMock.createMock;
79import static org.easymock.EasyMock.expect;
80import static org.easymock.EasyMock.expectLastCall;
81import static org.easymock.EasyMock.replay;
82import static org.easymock.EasyMock.verify;
83import static org.hamcrest.Matchers.containsString;
84import static org.hamcrest.Matchers.hasSize;
85import static org.hamcrest.Matchers.is;
86import static org.hamcrest.Matchers.notNullValue;
Jian Li08d65cf2016-04-20 10:07:17 -070087import static org.junit.Assert.assertEquals;
88import static org.junit.Assert.assertThat;
89import static org.junit.Assert.fail;
Claudine Chiufb8b8162016-04-01 23:50:51 +000090import static org.onosproject.net.PortNumber.portNumber;
91
92/**
93 * Unit tests for virtual network REST APIs.
94 */
95public class VirtualNetworkWebResourceTest extends ResourceTest {
96
97 private final VirtualNetworkAdminService mockVnetAdminService = createMock(VirtualNetworkAdminService.class);
98 private final VirtualNetworkService mockVnetService = createMock(VirtualNetworkService.class);
99 private CodecManager codecService;
100
Claudine Chiu25f07be2016-06-27 16:21:21 +0000101 private final HashSet<VirtualDevice> vdevSet = new HashSet<>();
102 private final HashSet<VirtualPort> vportSet = new HashSet<>();
Claudine Chiufb8b8162016-04-01 23:50:51 +0000103
104 private static final String ID = "networkId";
105 private static final String TENANT_ID = "tenantId";
106 private static final String DEVICE_ID = "deviceId";
107 private static final String PORT_NUM = "portNum";
108 private static final String PHYS_DEVICE_ID = "physDeviceId";
109 private static final String PHYS_PORT_NUM = "physPortNum";
110
Claudine Chiufb8b8162016-04-01 23:50:51 +0000111 private final TenantId tenantId2 = TenantId.tenantId("TenantId2");
112 private final TenantId tenantId3 = TenantId.tenantId("TenantId3");
113 private final TenantId tenantId4 = TenantId.tenantId("TenantId4");
114
115 private final NetworkId networkId1 = NetworkId.networkId(1);
116 private final NetworkId networkId2 = NetworkId.networkId(2);
117 private final NetworkId networkId3 = NetworkId.networkId(3);
118 private final NetworkId networkId4 = NetworkId.networkId(4);
119
120 private final VirtualNetwork vnet1 = new DefaultVirtualNetwork(networkId1, tenantId3);
121 private final VirtualNetwork vnet2 = new DefaultVirtualNetwork(networkId2, tenantId3);
122 private final VirtualNetwork vnet3 = new DefaultVirtualNetwork(networkId3, tenantId3);
123 private final VirtualNetwork vnet4 = new DefaultVirtualNetwork(networkId4, tenantId3);
124
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000125 private final DeviceId devId1 = DeviceId.deviceId("devid1");
126 private final DeviceId devId2 = DeviceId.deviceId("devid2");
Claudine Chiufb8b8162016-04-01 23:50:51 +0000127 private final DeviceId devId22 = DeviceId.deviceId("dev22");
128
129 private final VirtualDevice vdev1 = new DefaultVirtualDevice(networkId3, devId1);
130 private final VirtualDevice vdev2 = new DefaultVirtualDevice(networkId3, devId2);
131
132 private final Device dev1 = NetTestTools.device("dev1");
133 private final Device dev2 = NetTestTools.device("dev2");
134 private final Device dev22 = NetTestTools.device("dev22");
135
Yoonseon Han6c603892016-09-01 11:52:21 -0700136 private final ConnectPoint cp1 = new ConnectPoint(dev1.id(), portNumber(1));
137 private final ConnectPoint cp2 = new ConnectPoint(dev2.id(), portNumber(2));
Claudine Chiufb8b8162016-04-01 23:50:51 +0000138
139 private final VirtualPort vport22 = new DefaultVirtualPort(networkId3,
Yoonseon Han6c603892016-09-01 11:52:21 -0700140 dev22, portNumber(22), cp1);
Claudine Chiufb8b8162016-04-01 23:50:51 +0000141 private final VirtualPort vport23 = new DefaultVirtualPort(networkId3,
Yoonseon Han6c603892016-09-01 11:52:21 -0700142 dev22, portNumber(23), cp2);
Claudine Chiufb8b8162016-04-01 23:50:51 +0000143
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
Brian Stanke9a108972016-04-11 15:25:17 -0400149 private final VirtualLink vlink1 = DefaultVirtualLink.builder()
150 .networkId(networkId3)
151 .src(cp22)
152 .dst(cp11)
153 .build();
154
155 private final VirtualLink vlink2 = DefaultVirtualLink.builder()
156 .networkId(networkId3)
157 .src(cp12)
158 .dst(cp21)
159 .build();
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000160
Claudine Chiu25f07be2016-06-27 16:21:21 +0000161 private final MacAddress mac1 = MacAddress.valueOf("00:11:00:00:00:01");
162 private final MacAddress mac2 = MacAddress.valueOf("00:22:00:00:00:02");
163 private final VlanId vlan1 = VlanId.vlanId((short) 11);
164 private final VlanId vlan2 = VlanId.vlanId((short) 22);
165 private final IpAddress ip1 = IpAddress.valueOf("10.0.0.1");
166 private final IpAddress ip2 = IpAddress.valueOf("10.0.0.2");
167 private final IpAddress ip3 = IpAddress.valueOf("10.0.0.3");
168
169 private final HostId hId1 = HostId.hostId(mac1, vlan1);
170 private final HostId hId2 = HostId.hostId(mac2, vlan2);
171 private final HostLocation loc1 = new HostLocation(devId1, portNumber(100), 123L);
172 private final HostLocation loc2 = new HostLocation(devId2, portNumber(200), 123L);
173 private final Set<IpAddress> ipSet1 = Sets.newHashSet(ip1, ip2);
174 private final Set<IpAddress> ipSet2 = Sets.newHashSet(ip1, ip3);
175 private final VirtualHost vhost1 = new DefaultVirtualHost(networkId1, hId1,
176 mac1, vlan1, loc1, ipSet1);
177 private final VirtualHost vhost2 = new DefaultVirtualHost(networkId2, hId2,
178 mac2, vlan2, loc2, ipSet2);
179
180
181
182
Claudine Chiufb8b8162016-04-01 23:50:51 +0000183 /**
184 * Sets up the global values for all the tests.
185 */
186 @Before
187 public void setUpTest() {
188 // Register the services needed for the test
189 codecService = new CodecManager();
190 codecService.activate();
191 ServiceDirectory testDirectory =
192 new TestServiceDirectory()
193 .add(VirtualNetworkAdminService.class, mockVnetAdminService)
194 .add(VirtualNetworkService.class, mockVnetService)
195 .add(CodecService.class, codecService);
196
Ray Milkey094a1352018-01-22 14:03:54 -0800197 setServiceDirectory(testDirectory);
Claudine Chiufb8b8162016-04-01 23:50:51 +0000198 }
199
200 /**
201 * Hamcrest matcher to check that a virtual network entity representation in JSON matches
202 * the actual virtual network entity.
203 */
Claudine Chiu25f07be2016-06-27 16:21:21 +0000204 private static final class JsonObjectMatcher<T> extends TypeSafeMatcher<JsonObject> {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000205 private final T vnetEntity;
206 private List<String> jsonFieldNames;
207 private String reason = "";
208 private BiFunction<T, String, String> getValue; // get vnetEntity's value
209
Claudine Chiu25f07be2016-06-27 16:21:21 +0000210 private JsonObjectMatcher(T vnetEntityValue,
211 List<String> jsonFieldNames1,
212 BiFunction<T, String, String> getValue1) {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000213 vnetEntity = vnetEntityValue;
214 jsonFieldNames = jsonFieldNames1;
215 getValue = getValue1;
216 }
217
218 @Override
219 public boolean matchesSafely(JsonObject jsonHost) {
220 return jsonFieldNames
221 .stream()
222 .allMatch(s -> checkField(jsonHost, s, getValue.apply(vnetEntity, s)));
223 }
224
225 private boolean checkField(JsonObject jsonHost, String jsonFieldName,
226 String objectValue) {
227 final String jsonValue = jsonHost.get(jsonFieldName).asString();
228 if (!jsonValue.equals(objectValue)) {
229 reason = jsonFieldName + " " + objectValue;
230 return false;
231 }
232 return true;
233 }
234
235 @Override
236 public void describeTo(Description description) {
237 description.appendText(reason);
238 }
239 }
240
241 /**
242 * Factory to allocate a virtual network id array matcher.
243 *
244 * @param obj virtual network id object we are looking for
245 * @return matcher
246 */
247 /**
248 * Factory to allocate a virtual network entity matcher.
249 *
Brian Stanke9a108972016-04-11 15:25:17 -0400250 * @param obj virtual network object we are looking for
Claudine Chiufb8b8162016-04-01 23:50:51 +0000251 * @param jsonFieldNames JSON field names to check against
Brian Stanke9a108972016-04-11 15:25:17 -0400252 * @param getValue function to retrieve value from virtual network object
Claudine Chiua98c2ea2016-04-19 16:09:18 +0000253 * @param <T> the type of virtual network object
254 * @return matcher
Claudine Chiufb8b8162016-04-01 23:50:51 +0000255 */
256 private static <T> JsonObjectMatcher matchesVnetEntity(T obj, List<String> jsonFieldNames,
Brian Stanke9a108972016-04-11 15:25:17 -0400257 BiFunction<T, String, String> getValue) {
Claudine Chiua98c2ea2016-04-19 16:09:18 +0000258 return new JsonObjectMatcher<T>(obj, jsonFieldNames, getValue);
Claudine Chiufb8b8162016-04-01 23:50:51 +0000259 }
260
261 /**
262 * Hamcrest matcher to check that a virtual network entity is represented properly in a JSON
263 * array of virtual network entities.
264 */
Claudine Chiu25f07be2016-06-27 16:21:21 +0000265 protected static class JsonArrayMatcher<T> extends TypeSafeMatcher<JsonArray> {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000266 private final T vnetEntity;
267 private String reason = "";
268 private Function<T, String> getKey; // gets vnetEntity's key
269 private BiPredicate<T, JsonObject> checkKey; // check vnetEntity's key with JSON rep'n
270 private List<String> jsonFieldNames; // field/property names
271 private BiFunction<T, String, String> getValue; // get vnetEntity's value
272
Claudine Chiu25f07be2016-06-27 16:21:21 +0000273 protected JsonArrayMatcher(T vnetEntityValue, Function<T, String> getKey1,
274 BiPredicate<T, JsonObject> checkKey1,
275 List<String> jsonFieldNames1,
276 BiFunction<T, String, String> getValue1) {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000277 vnetEntity = vnetEntityValue;
278 getKey = getKey1;
279 checkKey = checkKey1;
280 jsonFieldNames = jsonFieldNames1;
281 getValue = getValue1;
282 }
283
284 @Override
285 public boolean matchesSafely(JsonArray json) {
286 boolean itemFound = false;
287 final int expectedAttributes = jsonFieldNames.size();
288 for (int jsonArrayIndex = 0; jsonArrayIndex < json.size();
289 jsonArrayIndex++) {
290
291 final JsonObject jsonHost = json.get(jsonArrayIndex).asObject();
292
293 if (jsonHost.names().size() < expectedAttributes) {
294 reason = "Found a virtual network with the wrong number of attributes";
295 return false;
296 }
297
298 if (checkKey != null && checkKey.test(vnetEntity, jsonHost)) {
299 itemFound = true;
300 assertThat(jsonHost, matchesVnetEntity(vnetEntity, jsonFieldNames, getValue));
301 }
302 }
303 if (!itemFound) {
304 reason = getKey.apply(vnetEntity) + " was not found";
305 return false;
306 }
307 return true;
308 }
309
310 @Override
311 public void describeTo(Description description) {
312 description.appendText(reason);
313 }
314 }
315
316 /**
317 * Array matcher for VirtualNetwork.
318 */
Claudine Chiu25f07be2016-06-27 16:21:21 +0000319 private static final class VnetJsonArrayMatcher extends JsonArrayMatcher<VirtualNetwork> {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000320
Claudine Chiu25f07be2016-06-27 16:21:21 +0000321 private VnetJsonArrayMatcher(VirtualNetwork vnetIn) {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000322 super(vnetIn,
323 vnet -> "Virtual network " + vnet.id().toString(),
Jian Li08d65cf2016-04-20 10:07:17 -0700324 (vnet, jsonObject) -> jsonObject.get(ID).asString().equals(vnet.id().toString()),
Claudine Chiufb8b8162016-04-01 23:50:51 +0000325 ImmutableList.of(ID, TENANT_ID),
Jian Li08d65cf2016-04-20 10:07:17 -0700326 (vnet, s) -> s.equals(ID) ? vnet.id().toString()
327 : s.equals(TENANT_ID) ? vnet.tenantId().toString()
328 : null
Claudine Chiufb8b8162016-04-01 23:50:51 +0000329 );
330 }
331 }
332
333 /**
334 * Factory to allocate a virtual network array matcher.
335 *
336 * @param vnet virtual network object we are looking for
337 * @return matcher
338 */
339 private VnetJsonArrayMatcher hasVnet(VirtualNetwork vnet) {
340 return new VnetJsonArrayMatcher(vnet);
341 }
342
343 // Tests for Virtual Networks
344
345 /**
346 * Tests the result of the REST API GET when there are no virtual networks.
347 */
348 @Test
349 public void testGetVirtualNetworksEmptyArray() {
350 expect(mockVnetAdminService.getTenantIds()).andReturn(ImmutableSet.of()).anyTimes();
351 replay(mockVnetAdminService);
352 expect(mockVnetService.getVirtualNetworks(tenantId4)).andReturn(ImmutableSet.of()).anyTimes();
353 replay(mockVnetService);
354
355 WebTarget wt = target();
356 String response = wt.path("vnets").request().get(String.class);
357 assertThat(response, is("{\"vnets\":[]}"));
358
359 verify(mockVnetService);
360 verify(mockVnetAdminService);
361 }
362
363 /**
364 * Tests the result of the REST API GET when virtual networks are defined.
365 */
366 @Test
367 public void testGetVirtualNetworksArray() {
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000368 final Set<VirtualNetwork> vnetSet = ImmutableSet.of(vnet1, vnet2, vnet3, vnet4);
Claudine Chiufb8b8162016-04-01 23:50:51 +0000369 expect(mockVnetAdminService.getTenantIds()).andReturn(ImmutableSet.of(tenantId3)).anyTimes();
370 replay(mockVnetAdminService);
Claudine Chiufb8b8162016-04-01 23:50:51 +0000371 expect(mockVnetService.getVirtualNetworks(tenantId3)).andReturn(vnetSet).anyTimes();
372 replay(mockVnetService);
373
374 WebTarget wt = target();
375 String response = wt.path("vnets").request().get(String.class);
376 assertThat(response, containsString("{\"vnets\":["));
377
378 final JsonObject result = Json.parse(response).asObject();
379 assertThat(result, notNullValue());
380
381 assertThat(result.names(), hasSize(1));
382 assertThat(result.names().get(0), is("vnets"));
383
384 final JsonArray vnetJsonArray = result.get("vnets").asArray();
385 assertThat(vnetJsonArray, notNullValue());
386 assertEquals("Virtual networks array is not the correct size.",
387 vnetSet.size(), vnetJsonArray.size());
388
389 vnetSet.forEach(vnet -> assertThat(vnetJsonArray, hasVnet(vnet)));
390
391 verify(mockVnetService);
392 verify(mockVnetAdminService);
393 }
394
395 /**
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000396 * Tests the result of the REST API GET for virtual networks with tenant id.
397 */
398 @Test
399 public void testGetVirtualNetworksByTenantId() {
400 final Set<VirtualNetwork> vnetSet = ImmutableSet.of(vnet1, vnet2, vnet3, vnet4);
401 expect(mockVnetAdminService.getTenantIds()).andReturn(ImmutableSet.of(tenantId3)).anyTimes();
402 replay(mockVnetAdminService);
403 expect(mockVnetService.getVirtualNetworks(tenantId3)).andReturn(vnetSet).anyTimes();
404 replay(mockVnetService);
405
406 WebTarget wt = target();
407 String response = wt.path("vnets/" + tenantId3.id()).request().get(String.class);
408 assertThat(response, containsString("{\"vnets\":["));
409
410 final JsonObject result = Json.parse(response).asObject();
411 assertThat(result, notNullValue());
412
413 assertThat(result.names(), hasSize(1));
414 assertThat(result.names().get(0), is("vnets"));
415
416 final JsonArray vnetJsonArray = result.get("vnets").asArray();
417 assertThat(vnetJsonArray, notNullValue());
418 assertEquals("Virtual networks array is not the correct size.",
419 vnetSet.size(), vnetJsonArray.size());
420
421 vnetSet.forEach(vnet -> assertThat(vnetJsonArray, hasVnet(vnet)));
422
423 verify(mockVnetService);
424 verify(mockVnetAdminService);
425 }
426
427 /**
428 * Tests the result of the REST API GET for virtual networks with tenant id.
429 */
430 @Test
431 public void testGetVirtualNetworksByNonExistentTenantId() {
432 String tenantIdName = "NON_EXISTENT_TENANT_ID";
433 expect(mockVnetAdminService.getTenantIds()).andReturn(ImmutableSet.of(tenantId3)).anyTimes();
434 replay(mockVnetAdminService);
435 expect(mockVnetService.getVirtualNetworks(anyObject())).andReturn(ImmutableSet.of()).anyTimes();
436 replay(mockVnetService);
437
438 WebTarget wt = target();
439
440 try {
441 wt.path("vnets/" + tenantIdName)
442 .request()
443 .get(String.class);
444 fail("Get of a non-existent virtual network did not throw an exception");
445 } catch (NotFoundException ex) {
446 assertThat(ex.getMessage(), containsString("HTTP 404 Not Found"));
447 }
448
449 verify(mockVnetService);
450 verify(mockVnetAdminService);
451 }
452
453 /**
Claudine Chiufb8b8162016-04-01 23:50:51 +0000454 * Tests adding of new virtual network using POST via JSON stream.
455 */
456 @Test
457 public void testPostVirtualNetwork() {
458 expect(mockVnetAdminService.createVirtualNetwork(tenantId2)).andReturn(vnet1);
459 expectLastCall();
460
461 replay(mockVnetAdminService);
462
463 WebTarget wt = target();
464 InputStream jsonStream = TenantWebResourceTest.class
465 .getResourceAsStream("post-tenant.json");
466
467 Response response = wt.path("vnets").request(MediaType.APPLICATION_JSON_TYPE)
468 .post(Entity.json(jsonStream));
469 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
470
471 String location = response.getLocation().getPath();
472 assertThat(location, Matchers.startsWith("/vnets/" + vnet1.id().toString()));
473
474 verify(mockVnetAdminService);
475 }
476
477 /**
478 * Tests adding of a null virtual network using POST via JSON stream.
479 */
480 @Test
481 public void testPostVirtualNetworkNullTenantId() {
482
483 replay(mockVnetAdminService);
484
485 WebTarget wt = target();
486 try {
Jian Li08d65cf2016-04-20 10:07:17 -0700487 wt.path("vnets")
Claudine Chiufb8b8162016-04-01 23:50:51 +0000488 .request(MediaType.APPLICATION_JSON_TYPE)
489 .post(Entity.json(null), String.class);
490 fail("POST of null virtual network did not throw an exception");
491 } catch (BadRequestException ex) {
492 assertThat(ex.getMessage(), containsString("HTTP 400 Bad Request"));
493 }
494
495 verify(mockVnetAdminService);
496 }
497
498 /**
499 * Tests removing a virtual network with DELETE request.
500 */
501 @Test
502 public void testDeleteVirtualNetwork() {
503 mockVnetAdminService.removeVirtualNetwork(anyObject());
504 expectLastCall();
505 replay(mockVnetAdminService);
506
507 WebTarget wt = target()
508 .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
509 Response response = wt.path("vnets/" + "2")
510 .request(MediaType.APPLICATION_JSON_TYPE)
511 .delete();
512
Jian Lic2a542b2016-05-10 11:48:19 -0700513 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NO_CONTENT));
Claudine Chiufb8b8162016-04-01 23:50:51 +0000514
515 verify(mockVnetAdminService);
516 }
517
518 /**
519 * Tests that a DELETE of a non-existent virtual network throws an exception.
520 */
521 @Test
522 public void testDeleteNetworkNonExistentNetworkId() {
523 expect(mockVnetAdminService.getTenantIds())
524 .andReturn(ImmutableSet.of())
525 .anyTimes();
526 expectLastCall();
527
528 replay(mockVnetAdminService);
529
530 WebTarget wt = target();
531
532 try {
533 wt.path("vnets/" + "NON_EXISTENT_NETWORK_ID")
534 .request()
535 .delete(String.class);
536 fail("Delete of a non-existent virtual network did not throw an exception");
537 } catch (NotFoundException ex) {
538 assertThat(ex.getMessage(), containsString("HTTP 404 Not Found"));
539 }
540
541 verify(mockVnetAdminService);
542 }
543
544 // Tests for Virtual Device
545
546 /**
547 * Tests the result of the REST API GET when there are no virtual devices.
548 */
549 @Test
550 public void testGetVirtualDevicesEmptyArray() {
551 NetworkId networkId = networkId4;
552 expect(mockVnetService.getVirtualDevices(networkId)).andReturn(ImmutableSet.of()).anyTimes();
553 replay(mockVnetService);
554
555 WebTarget wt = target();
556 String location = "vnets/" + networkId.toString() + "/devices";
557 String response = wt.path(location).request().get(String.class);
558 assertThat(response, is("{\"devices\":[]}"));
559
560 verify(mockVnetService);
561 }
562
563 /**
564 * Tests the result of the REST API GET when virtual devices are defined.
565 */
566 @Test
567 public void testGetVirtualDevicesArray() {
568 NetworkId networkId = networkId3;
569 vdevSet.add(vdev1);
570 vdevSet.add(vdev2);
571 expect(mockVnetService.getVirtualDevices(networkId)).andReturn(vdevSet).anyTimes();
572 replay(mockVnetService);
573
574 WebTarget wt = target();
575 String location = "vnets/" + networkId.toString() + "/devices";
576 String response = wt.path(location).request().get(String.class);
577 assertThat(response, containsString("{\"devices\":["));
578
579 final JsonObject result = Json.parse(response).asObject();
580 assertThat(result, notNullValue());
581
582 assertThat(result.names(), hasSize(1));
583 assertThat(result.names().get(0), is("devices"));
584
585 final JsonArray vnetJsonArray = result.get("devices").asArray();
586 assertThat(vnetJsonArray, notNullValue());
587 assertEquals("Virtual devices array is not the correct size.",
588 vdevSet.size(), vnetJsonArray.size());
589
590 vdevSet.forEach(vdev -> assertThat(vnetJsonArray, hasVdev(vdev)));
591
592 verify(mockVnetService);
593 }
594
595 /**
596 * Array matcher for VirtualDevice.
597 */
Claudine Chiu25f07be2016-06-27 16:21:21 +0000598 private static final class VdevJsonArrayMatcher extends JsonArrayMatcher<VirtualDevice> {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000599
Claudine Chiu25f07be2016-06-27 16:21:21 +0000600 private VdevJsonArrayMatcher(VirtualDevice vdevIn) {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000601 super(vdevIn,
602 vdev -> "Virtual device " + vdev.networkId().toString()
603 + " " + vdev.id().toString(),
Jian Li08d65cf2016-04-20 10:07:17 -0700604 (vdev, jsonObject) -> jsonObject.get(ID).asString().equals(vdev.networkId().toString())
605 && jsonObject.get(DEVICE_ID).asString().equals(vdev.id().toString()),
Claudine Chiufb8b8162016-04-01 23:50:51 +0000606 ImmutableList.of(ID, DEVICE_ID),
Jian Li08d65cf2016-04-20 10:07:17 -0700607 (vdev, s) -> s.equals(ID) ? vdev.networkId().toString()
608 : s.equals(DEVICE_ID) ? vdev.id().toString()
609 : null
Claudine Chiufb8b8162016-04-01 23:50:51 +0000610 );
611 }
612 }
613
614 /**
615 * Factory to allocate a virtual device array matcher.
616 *
617 * @param vdev virtual device object we are looking for
618 * @return matcher
619 */
620 private VdevJsonArrayMatcher hasVdev(VirtualDevice vdev) {
621 return new VdevJsonArrayMatcher(vdev);
622 }
623 /**
624 * Tests adding of new virtual device using POST via JSON stream.
625 */
626 @Test
627 public void testPostVirtualDevice() {
628 NetworkId networkId = networkId3;
629 DeviceId deviceId = devId2;
630 expect(mockVnetAdminService.createVirtualDevice(networkId, deviceId)).andReturn(vdev2);
631 expectLastCall();
632
633 replay(mockVnetAdminService);
634
635 WebTarget wt = target();
636 InputStream jsonStream = VirtualNetworkWebResourceTest.class
637 .getResourceAsStream("post-virtual-device.json");
638 String reqLocation = "vnets/" + networkId.toString() + "/devices";
639 Response response = wt.path(reqLocation).request(MediaType.APPLICATION_JSON_TYPE)
640 .post(Entity.json(jsonStream));
641 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
642
643 String location = response.getLocation().getPath();
644 assertThat(location, Matchers.startsWith("/" + reqLocation + "/" + vdev2.id().toString()));
645
646 verify(mockVnetAdminService);
647 }
648
649 /**
650 * Tests adding of a null virtual device using POST via JSON stream.
651 */
652 @Test
653 public void testPostVirtualDeviceNullJsonStream() {
654 NetworkId networkId = networkId3;
655 replay(mockVnetAdminService);
656
657 WebTarget wt = target();
658 try {
659 String reqLocation = "vnets/" + networkId.toString() + "/devices";
Jian Li08d65cf2016-04-20 10:07:17 -0700660 wt.path(reqLocation)
Claudine Chiufb8b8162016-04-01 23:50:51 +0000661 .request(MediaType.APPLICATION_JSON_TYPE)
662 .post(Entity.json(null), String.class);
663 fail("POST of null virtual device did not throw an exception");
664 } catch (BadRequestException ex) {
665 assertThat(ex.getMessage(), containsString("HTTP 400 Bad Request"));
666 }
667
668 verify(mockVnetAdminService);
669 }
670
671 /**
672 * Tests removing a virtual device with DELETE request.
673 */
674 @Test
675 public void testDeleteVirtualDevice() {
676 NetworkId networkId = networkId3;
677 DeviceId deviceId = devId2;
678 mockVnetAdminService.removeVirtualDevice(networkId, deviceId);
679 expectLastCall();
680 replay(mockVnetAdminService);
681
682 WebTarget wt = target()
683 .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
684 String reqLocation = "vnets/" + networkId.toString() + "/devices/" + deviceId.toString();
685 Response response = wt.path(reqLocation)
686 .request(MediaType.APPLICATION_JSON_TYPE)
687 .delete();
688
Jian Lic2a542b2016-05-10 11:48:19 -0700689 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NO_CONTENT));
Claudine Chiufb8b8162016-04-01 23:50:51 +0000690
691 verify(mockVnetAdminService);
692 }
693
694 // Tests for Virtual Ports
695
696 /**
697 * Tests the result of the REST API GET when there are no virtual ports.
698 */
699 @Test
700 public void testGetVirtualPortsEmptyArray() {
701 NetworkId networkId = networkId4;
702 DeviceId deviceId = devId2;
703 expect(mockVnetService.getVirtualPorts(networkId, deviceId))
704 .andReturn(ImmutableSet.of()).anyTimes();
705 replay(mockVnetService);
706
707 WebTarget wt = target();
708 String location = "vnets/" + networkId.toString()
709 + "/devices/" + deviceId.toString() + "/ports";
710 String response = wt.path(location).request().get(String.class);
711 assertThat(response, is("{\"ports\":[]}"));
712
713 verify(mockVnetService);
714 }
715
716 /**
717 * Tests the result of the REST API GET when virtual ports are defined.
718 */
719 @Test
720 public void testGetVirtualPortsArray() {
721 NetworkId networkId = networkId3;
722 DeviceId deviceId = dev22.id();
723 vportSet.add(vport23);
724 vportSet.add(vport22);
725 expect(mockVnetService.getVirtualPorts(networkId, deviceId)).andReturn(vportSet).anyTimes();
726 replay(mockVnetService);
727
728 WebTarget wt = target();
729 String location = "vnets/" + networkId.toString()
730 + "/devices/" + deviceId.toString() + "/ports";
731 String response = wt.path(location).request().get(String.class);
732 assertThat(response, containsString("{\"ports\":["));
733
734 final JsonObject result = Json.parse(response).asObject();
735 assertThat(result, notNullValue());
736
737 assertThat(result.names(), hasSize(1));
738 assertThat(result.names().get(0), is("ports"));
739
740 final JsonArray vnetJsonArray = result.get("ports").asArray();
741 assertThat(vnetJsonArray, notNullValue());
742 assertEquals("Virtual ports array is not the correct size.",
Brian Stanke9a108972016-04-11 15:25:17 -0400743 vportSet.size(), vnetJsonArray.size());
Claudine Chiufb8b8162016-04-01 23:50:51 +0000744
745 vportSet.forEach(vport -> assertThat(vnetJsonArray, hasVport(vport)));
746
747 verify(mockVnetService);
748 }
749
750 /**
751 * Array matcher for VirtualPort.
752 */
Claudine Chiu25f07be2016-06-27 16:21:21 +0000753 private static final class VportJsonArrayMatcher extends JsonArrayMatcher<VirtualPort> {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000754
Claudine Chiu25f07be2016-06-27 16:21:21 +0000755 private VportJsonArrayMatcher(VirtualPort vportIn) {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000756 super(vportIn,
757 vport -> "Virtual port " + vport.networkId().toString() + " "
758 + vport.element().id().toString() + " " + vport.number().toString(),
Jian Li08d65cf2016-04-20 10:07:17 -0700759 (vport, jsonObject) -> jsonObject.get(ID).asString().equals(vport.networkId().toString())
760 && jsonObject.get(PORT_NUM).asString().equals(vport.number().toString())
761 && jsonObject.get(DEVICE_ID).asString().equals(vport.element().id().toString()),
Claudine Chiufb8b8162016-04-01 23:50:51 +0000762 ImmutableList.of(ID, DEVICE_ID, PORT_NUM, PHYS_DEVICE_ID, PHYS_PORT_NUM),
Jian Li08d65cf2016-04-20 10:07:17 -0700763 (vport, s) -> s.equals(ID) ? vport.networkId().toString()
764 : s.equals(DEVICE_ID) ? vport.element().id().toString()
765 : s.equals(PORT_NUM) ? vport.number().toString()
Yoonseon Han6c603892016-09-01 11:52:21 -0700766 : s.equals(PHYS_DEVICE_ID) ? vport.realizedBy().deviceId().toString()
767 : s.equals(PHYS_PORT_NUM) ? vport.realizedBy().port().toString()
Jian Li08d65cf2016-04-20 10:07:17 -0700768 : null
Claudine Chiufb8b8162016-04-01 23:50:51 +0000769 );
770 }
771 }
772
773 /**
774 * Factory to allocate a virtual port array matcher.
775 *
776 * @param vport virtual port object we are looking for
777 * @return matcher
778 */
779 private VportJsonArrayMatcher hasVport(VirtualPort vport) {
780 return new VportJsonArrayMatcher(vport);
781 }
782
783 /**
784 * Tests adding of new virtual port using POST via JSON stream.
785 */
786 @Test
787 public void testPostVirtualPort() {
788 NetworkId networkId = networkId3;
789 DeviceId deviceId = devId22;
790 DefaultAnnotations annotations = DefaultAnnotations.builder().build();
791 Device physDevice = new DefaultDevice(null, DeviceId.deviceId("dev1"),
Brian Stanke9a108972016-04-11 15:25:17 -0400792 null, null, null, null, null, null, annotations);
Yoonseon Han6c603892016-09-01 11:52:21 -0700793 ConnectPoint cp1 = new ConnectPoint(physDevice.id(), portNumber(1));
794 expect(mockVnetAdminService.createVirtualPort(networkId, deviceId, portNumber(22), cp1))
Claudine Chiufb8b8162016-04-01 23:50:51 +0000795 .andReturn(vport22);
796
797 replay(mockVnetAdminService);
798
799 WebTarget wt = target();
800 InputStream jsonStream = VirtualNetworkWebResourceTest.class
801 .getResourceAsStream("post-virtual-port.json");
802 String reqLocation = "vnets/" + networkId.toString()
803 + "/devices/" + deviceId.toString() + "/ports";
804 Response response = wt.path(reqLocation).request(MediaType.APPLICATION_JSON_TYPE)
805 .post(Entity.json(jsonStream));
806 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
807
808 verify(mockVnetAdminService);
809 }
810
811 /**
812 * Tests adding of a null virtual port using POST via JSON stream.
813 */
814 @Test
815 public void testPostVirtualPortNullJsonStream() {
816 NetworkId networkId = networkId3;
817 DeviceId deviceId = devId2;
818 replay(mockVnetAdminService);
819
820 WebTarget wt = target();
821 try {
822 String reqLocation = "vnets/" + networkId.toString()
823 + "/devices/" + deviceId.toString() + "/ports";
Jian Li08d65cf2016-04-20 10:07:17 -0700824 wt.path(reqLocation)
Claudine Chiufb8b8162016-04-01 23:50:51 +0000825 .request(MediaType.APPLICATION_JSON_TYPE)
826 .post(Entity.json(null), String.class);
827 fail("POST of null virtual port did not throw an exception");
828 } catch (BadRequestException ex) {
829 assertThat(ex.getMessage(), containsString("HTTP 400 Bad Request"));
830 }
831
832 verify(mockVnetAdminService);
833 }
834
835 /**
836 * Tests removing a virtual port with DELETE request.
837 */
838 @Test
839 public void testDeleteVirtualPort() {
840 NetworkId networkId = networkId3;
841 DeviceId deviceId = devId2;
842 PortNumber portNum = portNumber(2);
843 mockVnetAdminService.removeVirtualPort(networkId, deviceId, portNum);
844 expectLastCall();
845 replay(mockVnetAdminService);
846
847 WebTarget wt = target()
848 .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
849 String reqLocation = "vnets/" + networkId.toString()
Brian Stanke9a108972016-04-11 15:25:17 -0400850 + "/devices/" + deviceId.toString() + "/ports/" + portNum.toLong();
Claudine Chiufb8b8162016-04-01 23:50:51 +0000851 Response response = wt.path(reqLocation)
852 .request(MediaType.APPLICATION_JSON_TYPE)
853 .delete();
854
Jian Lic2a542b2016-05-10 11:48:19 -0700855 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NO_CONTENT));
Claudine Chiufb8b8162016-04-01 23:50:51 +0000856
857 verify(mockVnetAdminService);
858 }
859
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000860 // Tests for Virtual Links
861
862 /**
863 * Tests the result of the REST API GET when there are no virtual links.
864 */
865 @Test
866 public void testGetVirtualLinksEmptyArray() {
867 NetworkId networkId = networkId4;
868 expect(mockVnetService.getVirtualLinks(networkId)).andReturn(ImmutableSet.of()).anyTimes();
869 replay(mockVnetService);
870
871 WebTarget wt = target();
872 String location = "vnets/" + networkId.toString() + "/links";
873 String response = wt.path(location).request().get(String.class);
874 assertThat(response, is("{\"links\":[]}"));
875
876 verify(mockVnetService);
877 }
878
879 /**
880 * Tests the result of the REST API GET when virtual links are defined.
881 */
882 @Test
883 public void testGetVirtualLinksArray() {
884 NetworkId networkId = networkId3;
885 final Set<VirtualLink> vlinkSet = ImmutableSet.of(vlink1, vlink2);
886 expect(mockVnetService.getVirtualLinks(networkId)).andReturn(vlinkSet).anyTimes();
887 replay(mockVnetService);
888
889 WebTarget wt = target();
890 String location = "vnets/" + networkId.toString() + "/links";
891 String response = wt.path(location).request().get(String.class);
892 assertThat(response, containsString("{\"links\":["));
893
894 final JsonObject result = Json.parse(response).asObject();
895 assertThat(result, notNullValue());
896
897 assertThat(result.names(), hasSize(1));
898 assertThat(result.names().get(0), is("links"));
899
900 final JsonArray vnetJsonArray = result.get("links").asArray();
901 assertThat(vnetJsonArray, notNullValue());
902 assertEquals("Virtual links array is not the correct size.",
903 vlinkSet.size(), vnetJsonArray.size());
904
905 vlinkSet.forEach(vlink -> assertThat(vnetJsonArray, hasVlink(vlink)));
906
907 verify(mockVnetService);
908 }
909
910 /**
911 * Hamcrest matcher to check that a virtual link representation in JSON matches
912 * the actual virtual link.
913 */
Claudine Chiu25f07be2016-06-27 16:21:21 +0000914 private static final class VirtualLinkJsonMatcher extends LinksResourceTest.LinkJsonMatcher {
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000915 private final VirtualLink vlink;
916 private String reason = "";
917
Claudine Chiu25f07be2016-06-27 16:21:21 +0000918 private VirtualLinkJsonMatcher(VirtualLink vlinkValue) {
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000919 super(vlinkValue);
920 vlink = vlinkValue;
921 }
922
923 @Override
924 public boolean matchesSafely(JsonObject jsonLink) {
925 if (!super.matchesSafely(jsonLink)) {
926 return false;
927 }
928 // check NetworkId
929 String jsonNetworkId = jsonLink.get(ID).asString();
930 String networkId = vlink.networkId().toString();
931 if (!jsonNetworkId.equals(networkId)) {
932 reason = ID + " was " + jsonNetworkId;
933 return false;
934 }
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000935 return true;
936 }
937
938 @Override
939 public void describeTo(Description description) {
940 description.appendText(reason);
941 }
942 }
943
944 /**
945 * Factory to allocate a virtual link matcher.
946 *
947 * @param vlink virtual link object we are looking for
948 * @return matcher
949 */
950 private static VirtualLinkJsonMatcher matchesVirtualLink(VirtualLink vlink) {
951 return new VirtualLinkJsonMatcher(vlink);
952 }
953
954 /**
955 * Hamcrest matcher to check that a virtual link is represented properly in a JSON
956 * array of links.
957 */
Claudine Chiu25f07be2016-06-27 16:21:21 +0000958 private static final class VirtualLinkJsonArrayMatcher extends TypeSafeMatcher<JsonArray> {
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000959 private final VirtualLink vlink;
960 private String reason = "";
961
Claudine Chiu25f07be2016-06-27 16:21:21 +0000962 private VirtualLinkJsonArrayMatcher(VirtualLink vlinkValue) {
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000963 vlink = vlinkValue;
964 }
965
966 @Override
967 public boolean matchesSafely(JsonArray json) {
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000968 for (int jsonLinkIndex = 0; jsonLinkIndex < json.size();
969 jsonLinkIndex++) {
970
971 JsonObject jsonLink = json.get(jsonLinkIndex).asObject();
972
973 if (matchesVirtualLink(vlink).matchesSafely(jsonLink)) {
974 return true;
975 }
976 }
977 return false;
978 }
979
980 @Override
981 public void describeTo(Description description) {
982 description.appendText(reason);
983 }
984 }
985
986 /**
987 * Factory to allocate a virtual link array matcher.
988 *
989 * @param vlink virtual link object we are looking for
990 * @return matcher
991 */
992 private VirtualLinkJsonArrayMatcher hasVlink(VirtualLink vlink) {
993 return new VirtualLinkJsonArrayMatcher(vlink);
994 }
995
996 /**
997 * Tests adding of new virtual link using POST via JSON stream.
998 */
999 @Test
1000 public void testPostVirtualLink() {
1001 NetworkId networkId = networkId3;
Brian Stanke9a108972016-04-11 15:25:17 -04001002 expect(mockVnetAdminService.createVirtualLink(networkId, cp22, cp11))
Claudine Chiuf6bf8d52016-04-08 01:31:54 +00001003 .andReturn(vlink1);
1004 replay(mockVnetAdminService);
1005
1006 WebTarget wt = target();
1007 InputStream jsonStream = VirtualNetworkWebResourceTest.class
1008 .getResourceAsStream("post-virtual-link.json");
1009 String reqLocation = "vnets/" + networkId.toString() + "/links";
1010 Response response = wt.path(reqLocation).request(MediaType.APPLICATION_JSON_TYPE)
1011 .post(Entity.json(jsonStream));
1012 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
1013
1014 String location = response.getLocation().getPath();
1015 assertThat(location, Matchers.startsWith("/" + reqLocation));
1016
1017 verify(mockVnetAdminService);
1018 }
1019
1020 /**
1021 * Tests adding of a null virtual link using POST via JSON stream.
1022 */
1023 @Test
1024 public void testPostVirtualLinkNullJsonStream() {
1025 NetworkId networkId = networkId3;
1026 replay(mockVnetAdminService);
1027
1028 WebTarget wt = target();
1029 try {
1030 String reqLocation = "vnets/" + networkId.toString() + "/links";
1031 wt.path(reqLocation)
1032 .request(MediaType.APPLICATION_JSON_TYPE)
1033 .post(Entity.json(null), String.class);
1034 fail("POST of null virtual link did not throw an exception");
1035 } catch (BadRequestException ex) {
1036 assertThat(ex.getMessage(), containsString("HTTP 400 Bad Request"));
1037 }
1038
1039 verify(mockVnetAdminService);
1040 }
1041
1042 /**
1043 * Tests removing a virtual link with DELETE request.
1044 */
1045 @Test
1046 public void testDeleteVirtualLink() {
1047 NetworkId networkId = networkId3;
1048 mockVnetAdminService.removeVirtualLink(networkId, cp22, cp11);
1049 expectLastCall();
1050 replay(mockVnetAdminService);
1051
1052 WebTarget wt = target()
1053 .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
1054 InputStream jsonStream = VirtualNetworkWebResourceTest.class
1055 .getResourceAsStream("post-virtual-link.json");
1056 String reqLocation = "vnets/" + networkId.toString() + "/links";
Jian Li08d65cf2016-04-20 10:07:17 -07001057 Response response = wt.path(reqLocation).request().method("DELETE", Entity.json(jsonStream));
Claudine Chiuf6bf8d52016-04-08 01:31:54 +00001058
Jian Lic2a542b2016-05-10 11:48:19 -07001059 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NO_CONTENT));
Claudine Chiuf6bf8d52016-04-08 01:31:54 +00001060 verify(mockVnetAdminService);
1061 }
Claudine Chiu25f07be2016-06-27 16:21:21 +00001062
1063 // Tests for Virtual Hosts
1064
1065 /**
1066 * Tests the result of the REST API GET when there are no virtual hosts.
1067 */
1068 @Test
1069 public void testGetVirtualHostsEmptyArray() {
1070 NetworkId networkId = networkId4;
1071 expect(mockVnetService.getVirtualHosts(networkId)).andReturn(ImmutableSet.of()).anyTimes();
1072 replay(mockVnetService);
1073
1074 WebTarget wt = target();
1075 String location = "vnets/" + networkId.toString() + "/hosts";
1076 String response = wt.path(location).request().get(String.class);
1077 assertThat(response, is("{\"hosts\":[]}"));
1078
1079 verify(mockVnetService);
1080 }
1081
1082 /**
1083 * Tests the result of the REST API GET when virtual hosts are defined.
1084 */
1085 @Test
1086 public void testGetVirtualHostsArray() {
1087 NetworkId networkId = networkId3;
1088 final Set<VirtualHost> vhostSet = ImmutableSet.of(vhost1, vhost2);
1089 expect(mockVnetService.getVirtualHosts(networkId)).andReturn(vhostSet).anyTimes();
1090 replay(mockVnetService);
1091
1092 WebTarget wt = target();
1093 String location = "vnets/" + networkId.toString() + "/hosts";
1094 String response = wt.path(location).request().get(String.class);
1095 assertThat(response, containsString("{\"hosts\":["));
1096
1097 final JsonObject result = Json.parse(response).asObject();
1098 assertThat(result, notNullValue());
1099
1100 assertThat(result.names(), hasSize(1));
1101 assertThat(result.names().get(0), is("hosts"));
1102
1103 final JsonArray vnetJsonArray = result.get("hosts").asArray();
1104 assertThat(vnetJsonArray, notNullValue());
1105 assertEquals("Virtual hosts array is not the correct size.",
1106 vhostSet.size(), vnetJsonArray.size());
1107
1108 vhostSet.forEach(vhost -> assertThat(vnetJsonArray, hasVhost(vhost)));
1109
1110 verify(mockVnetService);
1111 }
1112
1113 /**
1114 * Hamcrest matcher to check that a virtual host representation in JSON matches
1115 * the actual virtual host.
1116 */
1117 private static final class VirtualHostJsonMatcher extends HostResourceTest.HostJsonMatcher {
1118 private final VirtualHost vhost;
1119 private String reason = "";
1120
1121 private VirtualHostJsonMatcher(VirtualHost vhostValue) {
1122 super(vhostValue);
1123 vhost = vhostValue;
1124 }
1125
1126 @Override
1127 public boolean matchesSafely(JsonObject jsonHost) {
1128 if (!super.matchesSafely(jsonHost)) {
1129 return false;
1130 }
1131 // check NetworkId
1132 String jsonNetworkId = jsonHost.get(ID).asString();
1133 String networkId = vhost.networkId().toString();
1134 if (!jsonNetworkId.equals(networkId)) {
1135 reason = ID + " was " + jsonNetworkId;
1136 return false;
1137 }
1138 return true;
1139 }
1140
1141 @Override
1142 public void describeTo(Description description) {
1143 description.appendText(reason);
1144 }
1145 }
1146
1147 /**
1148 * Factory to allocate a virtual host matcher.
1149 *
1150 * @param vhost virtual host object we are looking for
1151 * @return matcher
1152 */
1153 private static VirtualHostJsonMatcher matchesVirtualHost(VirtualHost vhost) {
1154 return new VirtualHostJsonMatcher(vhost);
1155 }
1156
1157 /**
1158 * Hamcrest matcher to check that a virtual host is represented properly in a JSON
1159 * array of hosts.
1160 */
1161 private static final class VirtualHostJsonArrayMatcher extends TypeSafeMatcher<JsonArray> {
1162 private final VirtualHost vhost;
1163 private String reason = "";
1164
1165 private VirtualHostJsonArrayMatcher(VirtualHost vhostValue) {
1166 vhost = vhostValue;
1167 }
1168
1169 @Override
1170 public boolean matchesSafely(JsonArray json) {
1171 for (int jsonHostIndex = 0; jsonHostIndex < json.size();
1172 jsonHostIndex++) {
1173
1174 JsonObject jsonHost = json.get(jsonHostIndex).asObject();
1175
1176 if (matchesVirtualHost(vhost).matchesSafely(jsonHost)) {
1177 return true;
1178 }
1179 }
1180 return false;
1181 }
1182
1183 @Override
1184 public void describeTo(Description description) {
1185 description.appendText(reason);
1186 }
1187 }
1188
1189 /**
1190 * Factory to allocate a virtual host array matcher.
1191 *
1192 * @param vhost virtual host object we are looking for
1193 * @return matcher
1194 */
1195 private VirtualHostJsonArrayMatcher hasVhost(VirtualHost vhost) {
1196 return new VirtualHostJsonArrayMatcher(vhost);
1197 }
1198
1199 /**
1200 * Tests adding of new virtual host using POST via JSON stream.
1201 */
1202 @Test
1203 public void testPostVirtualHost() {
1204 NetworkId networkId = networkId3;
1205 expect(mockVnetAdminService.createVirtualHost(networkId, hId1, mac1, vlan1, loc1, ipSet1))
1206 .andReturn(vhost1);
1207 replay(mockVnetAdminService);
1208
1209 WebTarget wt = target();
1210 InputStream jsonStream = VirtualNetworkWebResourceTest.class
1211 .getResourceAsStream("post-virtual-host.json");
1212 String reqLocation = "vnets/" + networkId.toString() + "/hosts";
1213 Response response = wt.path(reqLocation).request(MediaType.APPLICATION_JSON_TYPE)
1214 .post(Entity.json(jsonStream));
1215 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
1216
1217 String location = response.getLocation().getPath();
1218 assertThat(location, Matchers.startsWith("/" + reqLocation));
1219
1220 verify(mockVnetAdminService);
1221 }
1222
1223 /**
1224 * Tests adding of a null virtual host using POST via JSON stream.
1225 */
1226 @Test
1227 public void testPostVirtualHostNullJsonStream() {
1228 NetworkId networkId = networkId3;
1229 replay(mockVnetAdminService);
1230
1231 WebTarget wt = target();
1232 try {
1233 String reqLocation = "vnets/" + networkId.toString() + "/hosts";
1234 wt.path(reqLocation)
1235 .request(MediaType.APPLICATION_JSON_TYPE)
1236 .post(Entity.json(null), String.class);
1237 fail("POST of null virtual host did not throw an exception");
1238 } catch (BadRequestException ex) {
1239 assertThat(ex.getMessage(), containsString("HTTP 400 Bad Request"));
1240 }
1241
1242 verify(mockVnetAdminService);
1243 }
1244
1245 /**
1246 * Tests removing a virtual host with DELETE request.
1247 */
1248 @Test
1249 public void testDeleteVirtualHost() {
1250 NetworkId networkId = networkId3;
1251 mockVnetAdminService.removeVirtualHost(networkId, hId1);
1252 expectLastCall();
1253 replay(mockVnetAdminService);
1254
1255 WebTarget wt = target()
1256 .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
1257 InputStream jsonStream = VirtualNetworkWebResourceTest.class
1258 .getResourceAsStream("post-virtual-host.json");
1259 String reqLocation = "vnets/" + networkId.toString() + "/hosts";
1260 Response response = wt.path(reqLocation).request().method("DELETE", Entity.json(jsonStream));
1261
1262 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NO_CONTENT));
1263 verify(mockVnetAdminService);
1264 }
Claudine Chiufb8b8162016-04-01 23:50:51 +00001265}