blob: 720bd9a5fc10826f4c4ec868ed85e152918ebf82 [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;
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.onlab.rest.BaseResource;
37import org.onosproject.codec.CodecService;
38import org.onosproject.codec.impl.CodecManager;
39import org.onosproject.incubator.net.virtual.DefaultVirtualDevice;
Claudine Chiu25f07be2016-06-27 16:21:21 +000040import org.onosproject.incubator.net.virtual.DefaultVirtualHost;
Claudine Chiuf6bf8d52016-04-08 01:31:54 +000041import org.onosproject.incubator.net.virtual.DefaultVirtualLink;
Claudine Chiufb8b8162016-04-01 23:50:51 +000042import org.onosproject.incubator.net.virtual.DefaultVirtualNetwork;
43import org.onosproject.incubator.net.virtual.DefaultVirtualPort;
44import org.onosproject.incubator.net.virtual.NetworkId;
45import org.onosproject.incubator.net.virtual.TenantId;
46import org.onosproject.incubator.net.virtual.VirtualDevice;
Claudine Chiu25f07be2016-06-27 16:21:21 +000047import org.onosproject.incubator.net.virtual.VirtualHost;
Claudine Chiuf6bf8d52016-04-08 01:31:54 +000048import org.onosproject.incubator.net.virtual.VirtualLink;
Claudine Chiufb8b8162016-04-01 23:50:51 +000049import org.onosproject.incubator.net.virtual.VirtualNetwork;
50import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
51import org.onosproject.incubator.net.virtual.VirtualNetworkService;
52import org.onosproject.incubator.net.virtual.VirtualPort;
Claudine Chiuf6bf8d52016-04-08 01:31:54 +000053import org.onosproject.net.ConnectPoint;
Claudine Chiufb8b8162016-04-01 23:50:51 +000054import org.onosproject.net.DefaultAnnotations;
55import org.onosproject.net.DefaultDevice;
56import org.onosproject.net.DefaultPort;
57import org.onosproject.net.Device;
58import org.onosproject.net.DeviceId;
Claudine Chiu25f07be2016-06-27 16:21:21 +000059import org.onosproject.net.HostId;
60import org.onosproject.net.HostLocation;
Claudine Chiufb8b8162016-04-01 23:50:51 +000061import org.onosproject.net.NetTestTools;
62import org.onosproject.net.Port;
63import org.onosproject.net.PortNumber;
64
65import javax.ws.rs.BadRequestException;
66import javax.ws.rs.NotFoundException;
67import javax.ws.rs.client.Entity;
68import javax.ws.rs.client.WebTarget;
69import javax.ws.rs.core.MediaType;
70import javax.ws.rs.core.Response;
71import java.io.InputStream;
72import java.net.HttpURLConnection;
73import java.util.HashSet;
74import java.util.List;
Claudine Chiuf6bf8d52016-04-08 01:31:54 +000075import java.util.Set;
Claudine Chiufb8b8162016-04-01 23:50:51 +000076import java.util.function.BiFunction;
77import java.util.function.BiPredicate;
78import java.util.function.Function;
79
Jian Li08d65cf2016-04-20 10:07:17 -070080import static org.easymock.EasyMock.anyObject;
81import static org.easymock.EasyMock.createMock;
82import static org.easymock.EasyMock.expect;
83import static org.easymock.EasyMock.expectLastCall;
84import static org.easymock.EasyMock.replay;
85import static org.easymock.EasyMock.verify;
86import static org.hamcrest.Matchers.containsString;
87import static org.hamcrest.Matchers.hasSize;
88import static org.hamcrest.Matchers.is;
89import static org.hamcrest.Matchers.notNullValue;
90import static org.junit.Assert.assertEquals;
91import static org.junit.Assert.assertThat;
92import static org.junit.Assert.fail;
Claudine Chiufb8b8162016-04-01 23:50:51 +000093import static org.onosproject.net.PortNumber.portNumber;
94
95/**
96 * Unit tests for virtual network REST APIs.
97 */
98public class VirtualNetworkWebResourceTest extends ResourceTest {
99
100 private final VirtualNetworkAdminService mockVnetAdminService = createMock(VirtualNetworkAdminService.class);
101 private final VirtualNetworkService mockVnetService = createMock(VirtualNetworkService.class);
102 private CodecManager codecService;
103
Claudine Chiu25f07be2016-06-27 16:21:21 +0000104 private final HashSet<VirtualDevice> vdevSet = new HashSet<>();
105 private final HashSet<VirtualPort> vportSet = new HashSet<>();
Claudine Chiufb8b8162016-04-01 23:50:51 +0000106
107 private static final String ID = "networkId";
108 private static final String TENANT_ID = "tenantId";
109 private static final String DEVICE_ID = "deviceId";
110 private static final String PORT_NUM = "portNum";
111 private static final String PHYS_DEVICE_ID = "physDeviceId";
112 private static final String PHYS_PORT_NUM = "physPortNum";
113
Claudine Chiufb8b8162016-04-01 23:50:51 +0000114 private final TenantId tenantId2 = TenantId.tenantId("TenantId2");
115 private final TenantId tenantId3 = TenantId.tenantId("TenantId3");
116 private final TenantId tenantId4 = TenantId.tenantId("TenantId4");
117
118 private final NetworkId networkId1 = NetworkId.networkId(1);
119 private final NetworkId networkId2 = NetworkId.networkId(2);
120 private final NetworkId networkId3 = NetworkId.networkId(3);
121 private final NetworkId networkId4 = NetworkId.networkId(4);
122
123 private final VirtualNetwork vnet1 = new DefaultVirtualNetwork(networkId1, tenantId3);
124 private final VirtualNetwork vnet2 = new DefaultVirtualNetwork(networkId2, tenantId3);
125 private final VirtualNetwork vnet3 = new DefaultVirtualNetwork(networkId3, tenantId3);
126 private final VirtualNetwork vnet4 = new DefaultVirtualNetwork(networkId4, tenantId3);
127
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000128 private final DeviceId devId1 = DeviceId.deviceId("devid1");
129 private final DeviceId devId2 = DeviceId.deviceId("devid2");
Claudine Chiufb8b8162016-04-01 23:50:51 +0000130 private final DeviceId devId22 = DeviceId.deviceId("dev22");
131
132 private final VirtualDevice vdev1 = new DefaultVirtualDevice(networkId3, devId1);
133 private final VirtualDevice vdev2 = new DefaultVirtualDevice(networkId3, devId2);
134
135 private final Device dev1 = NetTestTools.device("dev1");
136 private final Device dev2 = NetTestTools.device("dev2");
137 private final Device dev22 = NetTestTools.device("dev22");
138
Claudine Chiu25f07be2016-06-27 16:21:21 +0000139 private final Port port1 = new DefaultPort(dev1, portNumber(1), true);
140 private final Port port2 = new DefaultPort(dev2, portNumber(2), true);
Claudine Chiufb8b8162016-04-01 23:50:51 +0000141
142 private final VirtualPort vport22 = new DefaultVirtualPort(networkId3,
Brian Stanke9a108972016-04-11 15:25:17 -0400143 dev22, portNumber(22), port1);
Claudine Chiufb8b8162016-04-01 23:50:51 +0000144 private final VirtualPort vport23 = new DefaultVirtualPort(networkId3,
Brian Stanke9a108972016-04-11 15:25:17 -0400145 dev22, portNumber(23), port2);
Claudine Chiufb8b8162016-04-01 23:50:51 +0000146
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000147 private final ConnectPoint cp11 = NetTestTools.connectPoint(devId1.toString(), 21);
148 private final ConnectPoint cp21 = NetTestTools.connectPoint(devId2.toString(), 22);
149 private final ConnectPoint cp12 = NetTestTools.connectPoint(devId1.toString(), 2);
150 private final ConnectPoint cp22 = NetTestTools.connectPoint(devId2.toString(), 22);
151
Brian Stanke9a108972016-04-11 15:25:17 -0400152 private final VirtualLink vlink1 = DefaultVirtualLink.builder()
153 .networkId(networkId3)
154 .src(cp22)
155 .dst(cp11)
156 .build();
157
158 private final VirtualLink vlink2 = DefaultVirtualLink.builder()
159 .networkId(networkId3)
160 .src(cp12)
161 .dst(cp21)
162 .build();
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000163
Claudine Chiu25f07be2016-06-27 16:21:21 +0000164 private final MacAddress mac1 = MacAddress.valueOf("00:11:00:00:00:01");
165 private final MacAddress mac2 = MacAddress.valueOf("00:22:00:00:00:02");
166 private final VlanId vlan1 = VlanId.vlanId((short) 11);
167 private final VlanId vlan2 = VlanId.vlanId((short) 22);
168 private final IpAddress ip1 = IpAddress.valueOf("10.0.0.1");
169 private final IpAddress ip2 = IpAddress.valueOf("10.0.0.2");
170 private final IpAddress ip3 = IpAddress.valueOf("10.0.0.3");
171
172 private final HostId hId1 = HostId.hostId(mac1, vlan1);
173 private final HostId hId2 = HostId.hostId(mac2, vlan2);
174 private final HostLocation loc1 = new HostLocation(devId1, portNumber(100), 123L);
175 private final HostLocation loc2 = new HostLocation(devId2, portNumber(200), 123L);
176 private final Set<IpAddress> ipSet1 = Sets.newHashSet(ip1, ip2);
177 private final Set<IpAddress> ipSet2 = Sets.newHashSet(ip1, ip3);
178 private final VirtualHost vhost1 = new DefaultVirtualHost(networkId1, hId1,
179 mac1, vlan1, loc1, ipSet1);
180 private final VirtualHost vhost2 = new DefaultVirtualHost(networkId2, hId2,
181 mac2, vlan2, loc2, ipSet2);
182
183
184
185
Claudine Chiufb8b8162016-04-01 23:50:51 +0000186 /**
187 * Sets up the global values for all the tests.
188 */
189 @Before
190 public void setUpTest() {
191 // Register the services needed for the test
192 codecService = new CodecManager();
193 codecService.activate();
194 ServiceDirectory testDirectory =
195 new TestServiceDirectory()
196 .add(VirtualNetworkAdminService.class, mockVnetAdminService)
197 .add(VirtualNetworkService.class, mockVnetService)
198 .add(CodecService.class, codecService);
199
200 BaseResource.setServiceDirectory(testDirectory);
201 }
202
203 /**
204 * Hamcrest matcher to check that a virtual network entity representation in JSON matches
205 * the actual virtual network entity.
206 */
Claudine Chiu25f07be2016-06-27 16:21:21 +0000207 private static final class JsonObjectMatcher<T> extends TypeSafeMatcher<JsonObject> {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000208 private final T vnetEntity;
209 private List<String> jsonFieldNames;
210 private String reason = "";
211 private BiFunction<T, String, String> getValue; // get vnetEntity's value
212
Claudine Chiu25f07be2016-06-27 16:21:21 +0000213 private JsonObjectMatcher(T vnetEntityValue,
214 List<String> jsonFieldNames1,
215 BiFunction<T, String, String> getValue1) {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000216 vnetEntity = vnetEntityValue;
217 jsonFieldNames = jsonFieldNames1;
218 getValue = getValue1;
219 }
220
221 @Override
222 public boolean matchesSafely(JsonObject jsonHost) {
223 return jsonFieldNames
224 .stream()
225 .allMatch(s -> checkField(jsonHost, s, getValue.apply(vnetEntity, s)));
226 }
227
228 private boolean checkField(JsonObject jsonHost, String jsonFieldName,
229 String objectValue) {
230 final String jsonValue = jsonHost.get(jsonFieldName).asString();
231 if (!jsonValue.equals(objectValue)) {
232 reason = jsonFieldName + " " + objectValue;
233 return false;
234 }
235 return true;
236 }
237
238 @Override
239 public void describeTo(Description description) {
240 description.appendText(reason);
241 }
242 }
243
244 /**
245 * Factory to allocate a virtual network id array matcher.
246 *
247 * @param obj virtual network id object we are looking for
248 * @return matcher
249 */
250 /**
251 * Factory to allocate a virtual network entity matcher.
252 *
Brian Stanke9a108972016-04-11 15:25:17 -0400253 * @param obj virtual network object we are looking for
Claudine Chiufb8b8162016-04-01 23:50:51 +0000254 * @param jsonFieldNames JSON field names to check against
Brian Stanke9a108972016-04-11 15:25:17 -0400255 * @param getValue function to retrieve value from virtual network object
Claudine Chiua98c2ea2016-04-19 16:09:18 +0000256 * @param <T> the type of virtual network object
257 * @return matcher
Claudine Chiufb8b8162016-04-01 23:50:51 +0000258 */
259 private static <T> JsonObjectMatcher matchesVnetEntity(T obj, List<String> jsonFieldNames,
Brian Stanke9a108972016-04-11 15:25:17 -0400260 BiFunction<T, String, String> getValue) {
Claudine Chiua98c2ea2016-04-19 16:09:18 +0000261 return new JsonObjectMatcher<T>(obj, jsonFieldNames, getValue);
Claudine Chiufb8b8162016-04-01 23:50:51 +0000262 }
263
264 /**
265 * Hamcrest matcher to check that a virtual network entity is represented properly in a JSON
266 * array of virtual network entities.
267 */
Claudine Chiu25f07be2016-06-27 16:21:21 +0000268 protected static class JsonArrayMatcher<T> extends TypeSafeMatcher<JsonArray> {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000269 private final T vnetEntity;
270 private String reason = "";
271 private Function<T, String> getKey; // gets vnetEntity's key
272 private BiPredicate<T, JsonObject> checkKey; // check vnetEntity's key with JSON rep'n
273 private List<String> jsonFieldNames; // field/property names
274 private BiFunction<T, String, String> getValue; // get vnetEntity's value
275
Claudine Chiu25f07be2016-06-27 16:21:21 +0000276 protected JsonArrayMatcher(T vnetEntityValue, Function<T, String> getKey1,
277 BiPredicate<T, JsonObject> checkKey1,
278 List<String> jsonFieldNames1,
279 BiFunction<T, String, String> getValue1) {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000280 vnetEntity = vnetEntityValue;
281 getKey = getKey1;
282 checkKey = checkKey1;
283 jsonFieldNames = jsonFieldNames1;
284 getValue = getValue1;
285 }
286
287 @Override
288 public boolean matchesSafely(JsonArray json) {
289 boolean itemFound = false;
290 final int expectedAttributes = jsonFieldNames.size();
291 for (int jsonArrayIndex = 0; jsonArrayIndex < json.size();
292 jsonArrayIndex++) {
293
294 final JsonObject jsonHost = json.get(jsonArrayIndex).asObject();
295
296 if (jsonHost.names().size() < expectedAttributes) {
297 reason = "Found a virtual network with the wrong number of attributes";
298 return false;
299 }
300
301 if (checkKey != null && checkKey.test(vnetEntity, jsonHost)) {
302 itemFound = true;
303 assertThat(jsonHost, matchesVnetEntity(vnetEntity, jsonFieldNames, getValue));
304 }
305 }
306 if (!itemFound) {
307 reason = getKey.apply(vnetEntity) + " was not found";
308 return false;
309 }
310 return true;
311 }
312
313 @Override
314 public void describeTo(Description description) {
315 description.appendText(reason);
316 }
317 }
318
319 /**
320 * Array matcher for VirtualNetwork.
321 */
Claudine Chiu25f07be2016-06-27 16:21:21 +0000322 private static final class VnetJsonArrayMatcher extends JsonArrayMatcher<VirtualNetwork> {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000323
Claudine Chiu25f07be2016-06-27 16:21:21 +0000324 private VnetJsonArrayMatcher(VirtualNetwork vnetIn) {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000325 super(vnetIn,
326 vnet -> "Virtual network " + vnet.id().toString(),
Jian Li08d65cf2016-04-20 10:07:17 -0700327 (vnet, jsonObject) -> jsonObject.get(ID).asString().equals(vnet.id().toString()),
Claudine Chiufb8b8162016-04-01 23:50:51 +0000328 ImmutableList.of(ID, TENANT_ID),
Jian Li08d65cf2016-04-20 10:07:17 -0700329 (vnet, s) -> s.equals(ID) ? vnet.id().toString()
330 : s.equals(TENANT_ID) ? vnet.tenantId().toString()
331 : null
Claudine Chiufb8b8162016-04-01 23:50:51 +0000332 );
333 }
334 }
335
336 /**
337 * Factory to allocate a virtual network array matcher.
338 *
339 * @param vnet virtual network object we are looking for
340 * @return matcher
341 */
342 private VnetJsonArrayMatcher hasVnet(VirtualNetwork vnet) {
343 return new VnetJsonArrayMatcher(vnet);
344 }
345
346 // Tests for Virtual Networks
347
348 /**
349 * Tests the result of the REST API GET when there are no virtual networks.
350 */
351 @Test
352 public void testGetVirtualNetworksEmptyArray() {
353 expect(mockVnetAdminService.getTenantIds()).andReturn(ImmutableSet.of()).anyTimes();
354 replay(mockVnetAdminService);
355 expect(mockVnetService.getVirtualNetworks(tenantId4)).andReturn(ImmutableSet.of()).anyTimes();
356 replay(mockVnetService);
357
358 WebTarget wt = target();
359 String response = wt.path("vnets").request().get(String.class);
360 assertThat(response, is("{\"vnets\":[]}"));
361
362 verify(mockVnetService);
363 verify(mockVnetAdminService);
364 }
365
366 /**
367 * Tests the result of the REST API GET when virtual networks are defined.
368 */
369 @Test
370 public void testGetVirtualNetworksArray() {
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000371 final Set<VirtualNetwork> vnetSet = ImmutableSet.of(vnet1, vnet2, vnet3, vnet4);
Claudine Chiufb8b8162016-04-01 23:50:51 +0000372 expect(mockVnetAdminService.getTenantIds()).andReturn(ImmutableSet.of(tenantId3)).anyTimes();
373 replay(mockVnetAdminService);
Claudine Chiufb8b8162016-04-01 23:50:51 +0000374 expect(mockVnetService.getVirtualNetworks(tenantId3)).andReturn(vnetSet).anyTimes();
375 replay(mockVnetService);
376
377 WebTarget wt = target();
378 String response = wt.path("vnets").request().get(String.class);
379 assertThat(response, containsString("{\"vnets\":["));
380
381 final JsonObject result = Json.parse(response).asObject();
382 assertThat(result, notNullValue());
383
384 assertThat(result.names(), hasSize(1));
385 assertThat(result.names().get(0), is("vnets"));
386
387 final JsonArray vnetJsonArray = result.get("vnets").asArray();
388 assertThat(vnetJsonArray, notNullValue());
389 assertEquals("Virtual networks array is not the correct size.",
390 vnetSet.size(), vnetJsonArray.size());
391
392 vnetSet.forEach(vnet -> assertThat(vnetJsonArray, hasVnet(vnet)));
393
394 verify(mockVnetService);
395 verify(mockVnetAdminService);
396 }
397
398 /**
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000399 * Tests the result of the REST API GET for virtual networks with tenant id.
400 */
401 @Test
402 public void testGetVirtualNetworksByTenantId() {
403 final Set<VirtualNetwork> vnetSet = ImmutableSet.of(vnet1, vnet2, vnet3, vnet4);
404 expect(mockVnetAdminService.getTenantIds()).andReturn(ImmutableSet.of(tenantId3)).anyTimes();
405 replay(mockVnetAdminService);
406 expect(mockVnetService.getVirtualNetworks(tenantId3)).andReturn(vnetSet).anyTimes();
407 replay(mockVnetService);
408
409 WebTarget wt = target();
410 String response = wt.path("vnets/" + tenantId3.id()).request().get(String.class);
411 assertThat(response, containsString("{\"vnets\":["));
412
413 final JsonObject result = Json.parse(response).asObject();
414 assertThat(result, notNullValue());
415
416 assertThat(result.names(), hasSize(1));
417 assertThat(result.names().get(0), is("vnets"));
418
419 final JsonArray vnetJsonArray = result.get("vnets").asArray();
420 assertThat(vnetJsonArray, notNullValue());
421 assertEquals("Virtual networks array is not the correct size.",
422 vnetSet.size(), vnetJsonArray.size());
423
424 vnetSet.forEach(vnet -> assertThat(vnetJsonArray, hasVnet(vnet)));
425
426 verify(mockVnetService);
427 verify(mockVnetAdminService);
428 }
429
430 /**
431 * Tests the result of the REST API GET for virtual networks with tenant id.
432 */
433 @Test
434 public void testGetVirtualNetworksByNonExistentTenantId() {
435 String tenantIdName = "NON_EXISTENT_TENANT_ID";
436 expect(mockVnetAdminService.getTenantIds()).andReturn(ImmutableSet.of(tenantId3)).anyTimes();
437 replay(mockVnetAdminService);
438 expect(mockVnetService.getVirtualNetworks(anyObject())).andReturn(ImmutableSet.of()).anyTimes();
439 replay(mockVnetService);
440
441 WebTarget wt = target();
442
443 try {
444 wt.path("vnets/" + tenantIdName)
445 .request()
446 .get(String.class);
447 fail("Get of a non-existent virtual network did not throw an exception");
448 } catch (NotFoundException ex) {
449 assertThat(ex.getMessage(), containsString("HTTP 404 Not Found"));
450 }
451
452 verify(mockVnetService);
453 verify(mockVnetAdminService);
454 }
455
456 /**
Claudine Chiufb8b8162016-04-01 23:50:51 +0000457 * Tests adding of new virtual network using POST via JSON stream.
458 */
459 @Test
460 public void testPostVirtualNetwork() {
461 expect(mockVnetAdminService.createVirtualNetwork(tenantId2)).andReturn(vnet1);
462 expectLastCall();
463
464 replay(mockVnetAdminService);
465
466 WebTarget wt = target();
467 InputStream jsonStream = TenantWebResourceTest.class
468 .getResourceAsStream("post-tenant.json");
469
470 Response response = wt.path("vnets").request(MediaType.APPLICATION_JSON_TYPE)
471 .post(Entity.json(jsonStream));
472 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
473
474 String location = response.getLocation().getPath();
475 assertThat(location, Matchers.startsWith("/vnets/" + vnet1.id().toString()));
476
477 verify(mockVnetAdminService);
478 }
479
480 /**
481 * Tests adding of a null virtual network using POST via JSON stream.
482 */
483 @Test
484 public void testPostVirtualNetworkNullTenantId() {
485
486 replay(mockVnetAdminService);
487
488 WebTarget wt = target();
489 try {
Jian Li08d65cf2016-04-20 10:07:17 -0700490 wt.path("vnets")
Claudine Chiufb8b8162016-04-01 23:50:51 +0000491 .request(MediaType.APPLICATION_JSON_TYPE)
492 .post(Entity.json(null), String.class);
493 fail("POST of null virtual network did not throw an exception");
494 } catch (BadRequestException ex) {
495 assertThat(ex.getMessage(), containsString("HTTP 400 Bad Request"));
496 }
497
498 verify(mockVnetAdminService);
499 }
500
501 /**
502 * Tests removing a virtual network with DELETE request.
503 */
504 @Test
505 public void testDeleteVirtualNetwork() {
506 mockVnetAdminService.removeVirtualNetwork(anyObject());
507 expectLastCall();
508 replay(mockVnetAdminService);
509
510 WebTarget wt = target()
511 .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
512 Response response = wt.path("vnets/" + "2")
513 .request(MediaType.APPLICATION_JSON_TYPE)
514 .delete();
515
Jian Lic2a542b2016-05-10 11:48:19 -0700516 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NO_CONTENT));
Claudine Chiufb8b8162016-04-01 23:50:51 +0000517
518 verify(mockVnetAdminService);
519 }
520
521 /**
522 * Tests that a DELETE of a non-existent virtual network throws an exception.
523 */
524 @Test
525 public void testDeleteNetworkNonExistentNetworkId() {
526 expect(mockVnetAdminService.getTenantIds())
527 .andReturn(ImmutableSet.of())
528 .anyTimes();
529 expectLastCall();
530
531 replay(mockVnetAdminService);
532
533 WebTarget wt = target();
534
535 try {
536 wt.path("vnets/" + "NON_EXISTENT_NETWORK_ID")
537 .request()
538 .delete(String.class);
539 fail("Delete of a non-existent virtual network did not throw an exception");
540 } catch (NotFoundException ex) {
541 assertThat(ex.getMessage(), containsString("HTTP 404 Not Found"));
542 }
543
544 verify(mockVnetAdminService);
545 }
546
547 // Tests for Virtual Device
548
549 /**
550 * Tests the result of the REST API GET when there are no virtual devices.
551 */
552 @Test
553 public void testGetVirtualDevicesEmptyArray() {
554 NetworkId networkId = networkId4;
555 expect(mockVnetService.getVirtualDevices(networkId)).andReturn(ImmutableSet.of()).anyTimes();
556 replay(mockVnetService);
557
558 WebTarget wt = target();
559 String location = "vnets/" + networkId.toString() + "/devices";
560 String response = wt.path(location).request().get(String.class);
561 assertThat(response, is("{\"devices\":[]}"));
562
563 verify(mockVnetService);
564 }
565
566 /**
567 * Tests the result of the REST API GET when virtual devices are defined.
568 */
569 @Test
570 public void testGetVirtualDevicesArray() {
571 NetworkId networkId = networkId3;
572 vdevSet.add(vdev1);
573 vdevSet.add(vdev2);
574 expect(mockVnetService.getVirtualDevices(networkId)).andReturn(vdevSet).anyTimes();
575 replay(mockVnetService);
576
577 WebTarget wt = target();
578 String location = "vnets/" + networkId.toString() + "/devices";
579 String response = wt.path(location).request().get(String.class);
580 assertThat(response, containsString("{\"devices\":["));
581
582 final JsonObject result = Json.parse(response).asObject();
583 assertThat(result, notNullValue());
584
585 assertThat(result.names(), hasSize(1));
586 assertThat(result.names().get(0), is("devices"));
587
588 final JsonArray vnetJsonArray = result.get("devices").asArray();
589 assertThat(vnetJsonArray, notNullValue());
590 assertEquals("Virtual devices array is not the correct size.",
591 vdevSet.size(), vnetJsonArray.size());
592
593 vdevSet.forEach(vdev -> assertThat(vnetJsonArray, hasVdev(vdev)));
594
595 verify(mockVnetService);
596 }
597
598 /**
599 * Array matcher for VirtualDevice.
600 */
Claudine Chiu25f07be2016-06-27 16:21:21 +0000601 private static final class VdevJsonArrayMatcher extends JsonArrayMatcher<VirtualDevice> {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000602
Claudine Chiu25f07be2016-06-27 16:21:21 +0000603 private VdevJsonArrayMatcher(VirtualDevice vdevIn) {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000604 super(vdevIn,
605 vdev -> "Virtual device " + vdev.networkId().toString()
606 + " " + vdev.id().toString(),
Jian Li08d65cf2016-04-20 10:07:17 -0700607 (vdev, jsonObject) -> jsonObject.get(ID).asString().equals(vdev.networkId().toString())
608 && jsonObject.get(DEVICE_ID).asString().equals(vdev.id().toString()),
Claudine Chiufb8b8162016-04-01 23:50:51 +0000609 ImmutableList.of(ID, DEVICE_ID),
Jian Li08d65cf2016-04-20 10:07:17 -0700610 (vdev, s) -> s.equals(ID) ? vdev.networkId().toString()
611 : s.equals(DEVICE_ID) ? vdev.id().toString()
612 : null
Claudine Chiufb8b8162016-04-01 23:50:51 +0000613 );
614 }
615 }
616
617 /**
618 * Factory to allocate a virtual device array matcher.
619 *
620 * @param vdev virtual device object we are looking for
621 * @return matcher
622 */
623 private VdevJsonArrayMatcher hasVdev(VirtualDevice vdev) {
624 return new VdevJsonArrayMatcher(vdev);
625 }
626 /**
627 * Tests adding of new virtual device using POST via JSON stream.
628 */
629 @Test
630 public void testPostVirtualDevice() {
631 NetworkId networkId = networkId3;
632 DeviceId deviceId = devId2;
633 expect(mockVnetAdminService.createVirtualDevice(networkId, deviceId)).andReturn(vdev2);
634 expectLastCall();
635
636 replay(mockVnetAdminService);
637
638 WebTarget wt = target();
639 InputStream jsonStream = VirtualNetworkWebResourceTest.class
640 .getResourceAsStream("post-virtual-device.json");
641 String reqLocation = "vnets/" + networkId.toString() + "/devices";
642 Response response = wt.path(reqLocation).request(MediaType.APPLICATION_JSON_TYPE)
643 .post(Entity.json(jsonStream));
644 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
645
646 String location = response.getLocation().getPath();
647 assertThat(location, Matchers.startsWith("/" + reqLocation + "/" + vdev2.id().toString()));
648
649 verify(mockVnetAdminService);
650 }
651
652 /**
653 * Tests adding of a null virtual device using POST via JSON stream.
654 */
655 @Test
656 public void testPostVirtualDeviceNullJsonStream() {
657 NetworkId networkId = networkId3;
658 replay(mockVnetAdminService);
659
660 WebTarget wt = target();
661 try {
662 String reqLocation = "vnets/" + networkId.toString() + "/devices";
Jian Li08d65cf2016-04-20 10:07:17 -0700663 wt.path(reqLocation)
Claudine Chiufb8b8162016-04-01 23:50:51 +0000664 .request(MediaType.APPLICATION_JSON_TYPE)
665 .post(Entity.json(null), String.class);
666 fail("POST of null virtual device did not throw an exception");
667 } catch (BadRequestException ex) {
668 assertThat(ex.getMessage(), containsString("HTTP 400 Bad Request"));
669 }
670
671 verify(mockVnetAdminService);
672 }
673
674 /**
675 * Tests removing a virtual device with DELETE request.
676 */
677 @Test
678 public void testDeleteVirtualDevice() {
679 NetworkId networkId = networkId3;
680 DeviceId deviceId = devId2;
681 mockVnetAdminService.removeVirtualDevice(networkId, deviceId);
682 expectLastCall();
683 replay(mockVnetAdminService);
684
685 WebTarget wt = target()
686 .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
687 String reqLocation = "vnets/" + networkId.toString() + "/devices/" + deviceId.toString();
688 Response response = wt.path(reqLocation)
689 .request(MediaType.APPLICATION_JSON_TYPE)
690 .delete();
691
Jian Lic2a542b2016-05-10 11:48:19 -0700692 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NO_CONTENT));
Claudine Chiufb8b8162016-04-01 23:50:51 +0000693
694 verify(mockVnetAdminService);
695 }
696
697 // Tests for Virtual Ports
698
699 /**
700 * Tests the result of the REST API GET when there are no virtual ports.
701 */
702 @Test
703 public void testGetVirtualPortsEmptyArray() {
704 NetworkId networkId = networkId4;
705 DeviceId deviceId = devId2;
706 expect(mockVnetService.getVirtualPorts(networkId, deviceId))
707 .andReturn(ImmutableSet.of()).anyTimes();
708 replay(mockVnetService);
709
710 WebTarget wt = target();
711 String location = "vnets/" + networkId.toString()
712 + "/devices/" + deviceId.toString() + "/ports";
713 String response = wt.path(location).request().get(String.class);
714 assertThat(response, is("{\"ports\":[]}"));
715
716 verify(mockVnetService);
717 }
718
719 /**
720 * Tests the result of the REST API GET when virtual ports are defined.
721 */
722 @Test
723 public void testGetVirtualPortsArray() {
724 NetworkId networkId = networkId3;
725 DeviceId deviceId = dev22.id();
726 vportSet.add(vport23);
727 vportSet.add(vport22);
728 expect(mockVnetService.getVirtualPorts(networkId, deviceId)).andReturn(vportSet).anyTimes();
729 replay(mockVnetService);
730
731 WebTarget wt = target();
732 String location = "vnets/" + networkId.toString()
733 + "/devices/" + deviceId.toString() + "/ports";
734 String response = wt.path(location).request().get(String.class);
735 assertThat(response, containsString("{\"ports\":["));
736
737 final JsonObject result = Json.parse(response).asObject();
738 assertThat(result, notNullValue());
739
740 assertThat(result.names(), hasSize(1));
741 assertThat(result.names().get(0), is("ports"));
742
743 final JsonArray vnetJsonArray = result.get("ports").asArray();
744 assertThat(vnetJsonArray, notNullValue());
745 assertEquals("Virtual ports array is not the correct size.",
Brian Stanke9a108972016-04-11 15:25:17 -0400746 vportSet.size(), vnetJsonArray.size());
Claudine Chiufb8b8162016-04-01 23:50:51 +0000747
748 vportSet.forEach(vport -> assertThat(vnetJsonArray, hasVport(vport)));
749
750 verify(mockVnetService);
751 }
752
753 /**
754 * Array matcher for VirtualPort.
755 */
Claudine Chiu25f07be2016-06-27 16:21:21 +0000756 private static final class VportJsonArrayMatcher extends JsonArrayMatcher<VirtualPort> {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000757
Claudine Chiu25f07be2016-06-27 16:21:21 +0000758 private VportJsonArrayMatcher(VirtualPort vportIn) {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000759 super(vportIn,
760 vport -> "Virtual port " + vport.networkId().toString() + " "
761 + vport.element().id().toString() + " " + vport.number().toString(),
Jian Li08d65cf2016-04-20 10:07:17 -0700762 (vport, jsonObject) -> jsonObject.get(ID).asString().equals(vport.networkId().toString())
763 && jsonObject.get(PORT_NUM).asString().equals(vport.number().toString())
764 && jsonObject.get(DEVICE_ID).asString().equals(vport.element().id().toString()),
Claudine Chiufb8b8162016-04-01 23:50:51 +0000765 ImmutableList.of(ID, DEVICE_ID, PORT_NUM, PHYS_DEVICE_ID, PHYS_PORT_NUM),
Jian Li08d65cf2016-04-20 10:07:17 -0700766 (vport, s) -> s.equals(ID) ? vport.networkId().toString()
767 : s.equals(DEVICE_ID) ? vport.element().id().toString()
768 : s.equals(PORT_NUM) ? vport.number().toString()
769 : s.equals(PHYS_DEVICE_ID) ? vport.realizedBy().element().id().toString()
770 : s.equals(PHYS_PORT_NUM) ? vport.realizedBy().number().toString()
771 : null
Claudine Chiufb8b8162016-04-01 23:50:51 +0000772 );
773 }
774 }
775
776 /**
777 * Factory to allocate a virtual port array matcher.
778 *
779 * @param vport virtual port object we are looking for
780 * @return matcher
781 */
782 private VportJsonArrayMatcher hasVport(VirtualPort vport) {
783 return new VportJsonArrayMatcher(vport);
784 }
785
786 /**
787 * Tests adding of new virtual port using POST via JSON stream.
788 */
789 @Test
790 public void testPostVirtualPort() {
791 NetworkId networkId = networkId3;
792 DeviceId deviceId = devId22;
793 DefaultAnnotations annotations = DefaultAnnotations.builder().build();
794 Device physDevice = new DefaultDevice(null, DeviceId.deviceId("dev1"),
Brian Stanke9a108972016-04-11 15:25:17 -0400795 null, null, null, null, null, null, annotations);
Claudine Chiufb8b8162016-04-01 23:50:51 +0000796 Port port1 = new DefaultPort(physDevice, portNumber(1), true);
797 expect(mockVnetAdminService.createVirtualPort(networkId, deviceId, portNumber(22), port1))
798 .andReturn(vport22);
799
800 replay(mockVnetAdminService);
801
802 WebTarget wt = target();
803 InputStream jsonStream = VirtualNetworkWebResourceTest.class
804 .getResourceAsStream("post-virtual-port.json");
805 String reqLocation = "vnets/" + networkId.toString()
806 + "/devices/" + deviceId.toString() + "/ports";
807 Response response = wt.path(reqLocation).request(MediaType.APPLICATION_JSON_TYPE)
808 .post(Entity.json(jsonStream));
809 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
810
811 verify(mockVnetAdminService);
812 }
813
814 /**
815 * Tests adding of a null virtual port using POST via JSON stream.
816 */
817 @Test
818 public void testPostVirtualPortNullJsonStream() {
819 NetworkId networkId = networkId3;
820 DeviceId deviceId = devId2;
821 replay(mockVnetAdminService);
822
823 WebTarget wt = target();
824 try {
825 String reqLocation = "vnets/" + networkId.toString()
826 + "/devices/" + deviceId.toString() + "/ports";
Jian Li08d65cf2016-04-20 10:07:17 -0700827 wt.path(reqLocation)
Claudine Chiufb8b8162016-04-01 23:50:51 +0000828 .request(MediaType.APPLICATION_JSON_TYPE)
829 .post(Entity.json(null), String.class);
830 fail("POST of null virtual port did not throw an exception");
831 } catch (BadRequestException ex) {
832 assertThat(ex.getMessage(), containsString("HTTP 400 Bad Request"));
833 }
834
835 verify(mockVnetAdminService);
836 }
837
838 /**
839 * Tests removing a virtual port with DELETE request.
840 */
841 @Test
842 public void testDeleteVirtualPort() {
843 NetworkId networkId = networkId3;
844 DeviceId deviceId = devId2;
845 PortNumber portNum = portNumber(2);
846 mockVnetAdminService.removeVirtualPort(networkId, deviceId, portNum);
847 expectLastCall();
848 replay(mockVnetAdminService);
849
850 WebTarget wt = target()
851 .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
852 String reqLocation = "vnets/" + networkId.toString()
Brian Stanke9a108972016-04-11 15:25:17 -0400853 + "/devices/" + deviceId.toString() + "/ports/" + portNum.toLong();
Claudine Chiufb8b8162016-04-01 23:50:51 +0000854 Response response = wt.path(reqLocation)
855 .request(MediaType.APPLICATION_JSON_TYPE)
856 .delete();
857
Jian Lic2a542b2016-05-10 11:48:19 -0700858 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NO_CONTENT));
Claudine Chiufb8b8162016-04-01 23:50:51 +0000859
860 verify(mockVnetAdminService);
861 }
862
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000863 // Tests for Virtual Links
864
865 /**
866 * Tests the result of the REST API GET when there are no virtual links.
867 */
868 @Test
869 public void testGetVirtualLinksEmptyArray() {
870 NetworkId networkId = networkId4;
871 expect(mockVnetService.getVirtualLinks(networkId)).andReturn(ImmutableSet.of()).anyTimes();
872 replay(mockVnetService);
873
874 WebTarget wt = target();
875 String location = "vnets/" + networkId.toString() + "/links";
876 String response = wt.path(location).request().get(String.class);
877 assertThat(response, is("{\"links\":[]}"));
878
879 verify(mockVnetService);
880 }
881
882 /**
883 * Tests the result of the REST API GET when virtual links are defined.
884 */
885 @Test
886 public void testGetVirtualLinksArray() {
887 NetworkId networkId = networkId3;
888 final Set<VirtualLink> vlinkSet = ImmutableSet.of(vlink1, vlink2);
889 expect(mockVnetService.getVirtualLinks(networkId)).andReturn(vlinkSet).anyTimes();
890 replay(mockVnetService);
891
892 WebTarget wt = target();
893 String location = "vnets/" + networkId.toString() + "/links";
894 String response = wt.path(location).request().get(String.class);
895 assertThat(response, containsString("{\"links\":["));
896
897 final JsonObject result = Json.parse(response).asObject();
898 assertThat(result, notNullValue());
899
900 assertThat(result.names(), hasSize(1));
901 assertThat(result.names().get(0), is("links"));
902
903 final JsonArray vnetJsonArray = result.get("links").asArray();
904 assertThat(vnetJsonArray, notNullValue());
905 assertEquals("Virtual links array is not the correct size.",
906 vlinkSet.size(), vnetJsonArray.size());
907
908 vlinkSet.forEach(vlink -> assertThat(vnetJsonArray, hasVlink(vlink)));
909
910 verify(mockVnetService);
911 }
912
913 /**
914 * Hamcrest matcher to check that a virtual link representation in JSON matches
915 * the actual virtual link.
916 */
Claudine Chiu25f07be2016-06-27 16:21:21 +0000917 private static final class VirtualLinkJsonMatcher extends LinksResourceTest.LinkJsonMatcher {
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000918 private final VirtualLink vlink;
919 private String reason = "";
920
Claudine Chiu25f07be2016-06-27 16:21:21 +0000921 private VirtualLinkJsonMatcher(VirtualLink vlinkValue) {
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000922 super(vlinkValue);
923 vlink = vlinkValue;
924 }
925
926 @Override
927 public boolean matchesSafely(JsonObject jsonLink) {
928 if (!super.matchesSafely(jsonLink)) {
929 return false;
930 }
931 // check NetworkId
932 String jsonNetworkId = jsonLink.get(ID).asString();
933 String networkId = vlink.networkId().toString();
934 if (!jsonNetworkId.equals(networkId)) {
935 reason = ID + " was " + jsonNetworkId;
936 return false;
937 }
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000938 return true;
939 }
940
941 @Override
942 public void describeTo(Description description) {
943 description.appendText(reason);
944 }
945 }
946
947 /**
948 * Factory to allocate a virtual link matcher.
949 *
950 * @param vlink virtual link object we are looking for
951 * @return matcher
952 */
953 private static VirtualLinkJsonMatcher matchesVirtualLink(VirtualLink vlink) {
954 return new VirtualLinkJsonMatcher(vlink);
955 }
956
957 /**
958 * Hamcrest matcher to check that a virtual link is represented properly in a JSON
959 * array of links.
960 */
Claudine Chiu25f07be2016-06-27 16:21:21 +0000961 private static final class VirtualLinkJsonArrayMatcher extends TypeSafeMatcher<JsonArray> {
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000962 private final VirtualLink vlink;
963 private String reason = "";
964
Claudine Chiu25f07be2016-06-27 16:21:21 +0000965 private VirtualLinkJsonArrayMatcher(VirtualLink vlinkValue) {
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000966 vlink = vlinkValue;
967 }
968
969 @Override
970 public boolean matchesSafely(JsonArray json) {
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000971 for (int jsonLinkIndex = 0; jsonLinkIndex < json.size();
972 jsonLinkIndex++) {
973
974 JsonObject jsonLink = json.get(jsonLinkIndex).asObject();
975
976 if (matchesVirtualLink(vlink).matchesSafely(jsonLink)) {
977 return true;
978 }
979 }
980 return false;
981 }
982
983 @Override
984 public void describeTo(Description description) {
985 description.appendText(reason);
986 }
987 }
988
989 /**
990 * Factory to allocate a virtual link array matcher.
991 *
992 * @param vlink virtual link object we are looking for
993 * @return matcher
994 */
995 private VirtualLinkJsonArrayMatcher hasVlink(VirtualLink vlink) {
996 return new VirtualLinkJsonArrayMatcher(vlink);
997 }
998
999 /**
1000 * Tests adding of new virtual link using POST via JSON stream.
1001 */
1002 @Test
1003 public void testPostVirtualLink() {
1004 NetworkId networkId = networkId3;
Brian Stanke9a108972016-04-11 15:25:17 -04001005 expect(mockVnetAdminService.createVirtualLink(networkId, cp22, cp11))
Claudine Chiuf6bf8d52016-04-08 01:31:54 +00001006 .andReturn(vlink1);
1007 replay(mockVnetAdminService);
1008
1009 WebTarget wt = target();
1010 InputStream jsonStream = VirtualNetworkWebResourceTest.class
1011 .getResourceAsStream("post-virtual-link.json");
1012 String reqLocation = "vnets/" + networkId.toString() + "/links";
1013 Response response = wt.path(reqLocation).request(MediaType.APPLICATION_JSON_TYPE)
1014 .post(Entity.json(jsonStream));
1015 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
1016
1017 String location = response.getLocation().getPath();
1018 assertThat(location, Matchers.startsWith("/" + reqLocation));
1019
1020 verify(mockVnetAdminService);
1021 }
1022
1023 /**
1024 * Tests adding of a null virtual link using POST via JSON stream.
1025 */
1026 @Test
1027 public void testPostVirtualLinkNullJsonStream() {
1028 NetworkId networkId = networkId3;
1029 replay(mockVnetAdminService);
1030
1031 WebTarget wt = target();
1032 try {
1033 String reqLocation = "vnets/" + networkId.toString() + "/links";
1034 wt.path(reqLocation)
1035 .request(MediaType.APPLICATION_JSON_TYPE)
1036 .post(Entity.json(null), String.class);
1037 fail("POST of null virtual link did not throw an exception");
1038 } catch (BadRequestException ex) {
1039 assertThat(ex.getMessage(), containsString("HTTP 400 Bad Request"));
1040 }
1041
1042 verify(mockVnetAdminService);
1043 }
1044
1045 /**
1046 * Tests removing a virtual link with DELETE request.
1047 */
1048 @Test
1049 public void testDeleteVirtualLink() {
1050 NetworkId networkId = networkId3;
1051 mockVnetAdminService.removeVirtualLink(networkId, cp22, cp11);
1052 expectLastCall();
1053 replay(mockVnetAdminService);
1054
1055 WebTarget wt = target()
1056 .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
1057 InputStream jsonStream = VirtualNetworkWebResourceTest.class
1058 .getResourceAsStream("post-virtual-link.json");
1059 String reqLocation = "vnets/" + networkId.toString() + "/links";
Jian Li08d65cf2016-04-20 10:07:17 -07001060 Response response = wt.path(reqLocation).request().method("DELETE", Entity.json(jsonStream));
Claudine Chiuf6bf8d52016-04-08 01:31:54 +00001061
Jian Lic2a542b2016-05-10 11:48:19 -07001062 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NO_CONTENT));
Claudine Chiuf6bf8d52016-04-08 01:31:54 +00001063 verify(mockVnetAdminService);
1064 }
Claudine Chiu25f07be2016-06-27 16:21:21 +00001065
1066 // Tests for Virtual Hosts
1067
1068 /**
1069 * Tests the result of the REST API GET when there are no virtual hosts.
1070 */
1071 @Test
1072 public void testGetVirtualHostsEmptyArray() {
1073 NetworkId networkId = networkId4;
1074 expect(mockVnetService.getVirtualHosts(networkId)).andReturn(ImmutableSet.of()).anyTimes();
1075 replay(mockVnetService);
1076
1077 WebTarget wt = target();
1078 String location = "vnets/" + networkId.toString() + "/hosts";
1079 String response = wt.path(location).request().get(String.class);
1080 assertThat(response, is("{\"hosts\":[]}"));
1081
1082 verify(mockVnetService);
1083 }
1084
1085 /**
1086 * Tests the result of the REST API GET when virtual hosts are defined.
1087 */
1088 @Test
1089 public void testGetVirtualHostsArray() {
1090 NetworkId networkId = networkId3;
1091 final Set<VirtualHost> vhostSet = ImmutableSet.of(vhost1, vhost2);
1092 expect(mockVnetService.getVirtualHosts(networkId)).andReturn(vhostSet).anyTimes();
1093 replay(mockVnetService);
1094
1095 WebTarget wt = target();
1096 String location = "vnets/" + networkId.toString() + "/hosts";
1097 String response = wt.path(location).request().get(String.class);
1098 assertThat(response, containsString("{\"hosts\":["));
1099
1100 final JsonObject result = Json.parse(response).asObject();
1101 assertThat(result, notNullValue());
1102
1103 assertThat(result.names(), hasSize(1));
1104 assertThat(result.names().get(0), is("hosts"));
1105
1106 final JsonArray vnetJsonArray = result.get("hosts").asArray();
1107 assertThat(vnetJsonArray, notNullValue());
1108 assertEquals("Virtual hosts array is not the correct size.",
1109 vhostSet.size(), vnetJsonArray.size());
1110
1111 vhostSet.forEach(vhost -> assertThat(vnetJsonArray, hasVhost(vhost)));
1112
1113 verify(mockVnetService);
1114 }
1115
1116 /**
1117 * Hamcrest matcher to check that a virtual host representation in JSON matches
1118 * the actual virtual host.
1119 */
1120 private static final class VirtualHostJsonMatcher extends HostResourceTest.HostJsonMatcher {
1121 private final VirtualHost vhost;
1122 private String reason = "";
1123
1124 private VirtualHostJsonMatcher(VirtualHost vhostValue) {
1125 super(vhostValue);
1126 vhost = vhostValue;
1127 }
1128
1129 @Override
1130 public boolean matchesSafely(JsonObject jsonHost) {
1131 if (!super.matchesSafely(jsonHost)) {
1132 return false;
1133 }
1134 // check NetworkId
1135 String jsonNetworkId = jsonHost.get(ID).asString();
1136 String networkId = vhost.networkId().toString();
1137 if (!jsonNetworkId.equals(networkId)) {
1138 reason = ID + " was " + jsonNetworkId;
1139 return false;
1140 }
1141 return true;
1142 }
1143
1144 @Override
1145 public void describeTo(Description description) {
1146 description.appendText(reason);
1147 }
1148 }
1149
1150 /**
1151 * Factory to allocate a virtual host matcher.
1152 *
1153 * @param vhost virtual host object we are looking for
1154 * @return matcher
1155 */
1156 private static VirtualHostJsonMatcher matchesVirtualHost(VirtualHost vhost) {
1157 return new VirtualHostJsonMatcher(vhost);
1158 }
1159
1160 /**
1161 * Hamcrest matcher to check that a virtual host is represented properly in a JSON
1162 * array of hosts.
1163 */
1164 private static final class VirtualHostJsonArrayMatcher extends TypeSafeMatcher<JsonArray> {
1165 private final VirtualHost vhost;
1166 private String reason = "";
1167
1168 private VirtualHostJsonArrayMatcher(VirtualHost vhostValue) {
1169 vhost = vhostValue;
1170 }
1171
1172 @Override
1173 public boolean matchesSafely(JsonArray json) {
1174 for (int jsonHostIndex = 0; jsonHostIndex < json.size();
1175 jsonHostIndex++) {
1176
1177 JsonObject jsonHost = json.get(jsonHostIndex).asObject();
1178
1179 if (matchesVirtualHost(vhost).matchesSafely(jsonHost)) {
1180 return true;
1181 }
1182 }
1183 return false;
1184 }
1185
1186 @Override
1187 public void describeTo(Description description) {
1188 description.appendText(reason);
1189 }
1190 }
1191
1192 /**
1193 * Factory to allocate a virtual host array matcher.
1194 *
1195 * @param vhost virtual host object we are looking for
1196 * @return matcher
1197 */
1198 private VirtualHostJsonArrayMatcher hasVhost(VirtualHost vhost) {
1199 return new VirtualHostJsonArrayMatcher(vhost);
1200 }
1201
1202 /**
1203 * Tests adding of new virtual host using POST via JSON stream.
1204 */
1205 @Test
1206 public void testPostVirtualHost() {
1207 NetworkId networkId = networkId3;
1208 expect(mockVnetAdminService.createVirtualHost(networkId, hId1, mac1, vlan1, loc1, ipSet1))
1209 .andReturn(vhost1);
1210 replay(mockVnetAdminService);
1211
1212 WebTarget wt = target();
1213 InputStream jsonStream = VirtualNetworkWebResourceTest.class
1214 .getResourceAsStream("post-virtual-host.json");
1215 String reqLocation = "vnets/" + networkId.toString() + "/hosts";
1216 Response response = wt.path(reqLocation).request(MediaType.APPLICATION_JSON_TYPE)
1217 .post(Entity.json(jsonStream));
1218 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
1219
1220 String location = response.getLocation().getPath();
1221 assertThat(location, Matchers.startsWith("/" + reqLocation));
1222
1223 verify(mockVnetAdminService);
1224 }
1225
1226 /**
1227 * Tests adding of a null virtual host using POST via JSON stream.
1228 */
1229 @Test
1230 public void testPostVirtualHostNullJsonStream() {
1231 NetworkId networkId = networkId3;
1232 replay(mockVnetAdminService);
1233
1234 WebTarget wt = target();
1235 try {
1236 String reqLocation = "vnets/" + networkId.toString() + "/hosts";
1237 wt.path(reqLocation)
1238 .request(MediaType.APPLICATION_JSON_TYPE)
1239 .post(Entity.json(null), String.class);
1240 fail("POST of null virtual host did not throw an exception");
1241 } catch (BadRequestException ex) {
1242 assertThat(ex.getMessage(), containsString("HTTP 400 Bad Request"));
1243 }
1244
1245 verify(mockVnetAdminService);
1246 }
1247
1248 /**
1249 * Tests removing a virtual host with DELETE request.
1250 */
1251 @Test
1252 public void testDeleteVirtualHost() {
1253 NetworkId networkId = networkId3;
1254 mockVnetAdminService.removeVirtualHost(networkId, hId1);
1255 expectLastCall();
1256 replay(mockVnetAdminService);
1257
1258 WebTarget wt = target()
1259 .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
1260 InputStream jsonStream = VirtualNetworkWebResourceTest.class
1261 .getResourceAsStream("post-virtual-host.json");
1262 String reqLocation = "vnets/" + networkId.toString() + "/hosts";
1263 Response response = wt.path(reqLocation).request().method("DELETE", Entity.json(jsonStream));
1264
1265 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NO_CONTENT));
1266 verify(mockVnetAdminService);
1267 }
Claudine Chiufb8b8162016-04-01 23:50:51 +00001268}