blob: 808c3d10dacff2f50fc659bdd8bbb75d2eb2015d [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;
Jian Li70773462020-02-05 16:23:53 +090063import javax.ws.rs.InternalServerErrorException;
Claudine Chiufb8b8162016-04-01 23:50:51 +000064import javax.ws.rs.NotFoundException;
65import javax.ws.rs.client.Entity;
66import javax.ws.rs.client.WebTarget;
67import javax.ws.rs.core.MediaType;
68import javax.ws.rs.core.Response;
69import java.io.InputStream;
70import java.net.HttpURLConnection;
71import java.util.HashSet;
72import java.util.List;
Claudine Chiuf6bf8d52016-04-08 01:31:54 +000073import java.util.Set;
Claudine Chiufb8b8162016-04-01 23:50:51 +000074import java.util.function.BiFunction;
75import java.util.function.BiPredicate;
76import java.util.function.Function;
77
Ray Milkey094a1352018-01-22 14:03:54 -080078import static org.easymock.EasyMock.anyObject;
79import static org.easymock.EasyMock.createMock;
80import static org.easymock.EasyMock.expect;
81import static org.easymock.EasyMock.expectLastCall;
82import static org.easymock.EasyMock.replay;
83import static org.easymock.EasyMock.verify;
84import static org.hamcrest.Matchers.containsString;
85import static org.hamcrest.Matchers.hasSize;
86import static org.hamcrest.Matchers.is;
87import static org.hamcrest.Matchers.notNullValue;
Jian Li08d65cf2016-04-20 10:07:17 -070088import static org.junit.Assert.assertEquals;
89import static org.junit.Assert.assertThat;
90import static org.junit.Assert.fail;
Claudine Chiufb8b8162016-04-01 23:50:51 +000091import static org.onosproject.net.PortNumber.portNumber;
92
93/**
94 * Unit tests for virtual network REST APIs.
95 */
96public class VirtualNetworkWebResourceTest extends ResourceTest {
97
98 private final VirtualNetworkAdminService mockVnetAdminService = createMock(VirtualNetworkAdminService.class);
99 private final VirtualNetworkService mockVnetService = createMock(VirtualNetworkService.class);
100 private CodecManager codecService;
101
Claudine Chiu25f07be2016-06-27 16:21:21 +0000102 private final HashSet<VirtualDevice> vdevSet = new HashSet<>();
103 private final HashSet<VirtualPort> vportSet = new HashSet<>();
Claudine Chiufb8b8162016-04-01 23:50:51 +0000104
105 private static final String ID = "networkId";
106 private static final String TENANT_ID = "tenantId";
107 private static final String DEVICE_ID = "deviceId";
108 private static final String PORT_NUM = "portNum";
109 private static final String PHYS_DEVICE_ID = "physDeviceId";
110 private static final String PHYS_PORT_NUM = "physPortNum";
111
Claudine Chiufb8b8162016-04-01 23:50:51 +0000112 private final TenantId tenantId2 = TenantId.tenantId("TenantId2");
113 private final TenantId tenantId3 = TenantId.tenantId("TenantId3");
114 private final TenantId tenantId4 = TenantId.tenantId("TenantId4");
115
116 private final NetworkId networkId1 = NetworkId.networkId(1);
117 private final NetworkId networkId2 = NetworkId.networkId(2);
118 private final NetworkId networkId3 = NetworkId.networkId(3);
119 private final NetworkId networkId4 = NetworkId.networkId(4);
120
121 private final VirtualNetwork vnet1 = new DefaultVirtualNetwork(networkId1, tenantId3);
122 private final VirtualNetwork vnet2 = new DefaultVirtualNetwork(networkId2, tenantId3);
123 private final VirtualNetwork vnet3 = new DefaultVirtualNetwork(networkId3, tenantId3);
124 private final VirtualNetwork vnet4 = new DefaultVirtualNetwork(networkId4, tenantId3);
125
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000126 private final DeviceId devId1 = DeviceId.deviceId("devid1");
127 private final DeviceId devId2 = DeviceId.deviceId("devid2");
Claudine Chiufb8b8162016-04-01 23:50:51 +0000128 private final DeviceId devId22 = DeviceId.deviceId("dev22");
129
130 private final VirtualDevice vdev1 = new DefaultVirtualDevice(networkId3, devId1);
131 private final VirtualDevice vdev2 = new DefaultVirtualDevice(networkId3, devId2);
132
133 private final Device dev1 = NetTestTools.device("dev1");
134 private final Device dev2 = NetTestTools.device("dev2");
135 private final Device dev22 = NetTestTools.device("dev22");
136
Yoonseon Han6c603892016-09-01 11:52:21 -0700137 private final ConnectPoint cp1 = new ConnectPoint(dev1.id(), portNumber(1));
138 private final ConnectPoint cp2 = new ConnectPoint(dev2.id(), portNumber(2));
Claudine Chiufb8b8162016-04-01 23:50:51 +0000139
140 private final VirtualPort vport22 = new DefaultVirtualPort(networkId3,
Yoonseon Han6c603892016-09-01 11:52:21 -0700141 dev22, portNumber(22), cp1);
Claudine Chiufb8b8162016-04-01 23:50:51 +0000142 private final VirtualPort vport23 = new DefaultVirtualPort(networkId3,
Yoonseon Han6c603892016-09-01 11:52:21 -0700143 dev22, portNumber(23), cp2);
Claudine Chiufb8b8162016-04-01 23:50:51 +0000144
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000145 private final ConnectPoint cp11 = NetTestTools.connectPoint(devId1.toString(), 21);
146 private final ConnectPoint cp21 = NetTestTools.connectPoint(devId2.toString(), 22);
147 private final ConnectPoint cp12 = NetTestTools.connectPoint(devId1.toString(), 2);
148 private final ConnectPoint cp22 = NetTestTools.connectPoint(devId2.toString(), 22);
149
Brian Stanke9a108972016-04-11 15:25:17 -0400150 private final VirtualLink vlink1 = DefaultVirtualLink.builder()
151 .networkId(networkId3)
152 .src(cp22)
153 .dst(cp11)
154 .build();
155
156 private final VirtualLink vlink2 = DefaultVirtualLink.builder()
157 .networkId(networkId3)
158 .src(cp12)
159 .dst(cp21)
160 .build();
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000161
Claudine Chiu25f07be2016-06-27 16:21:21 +0000162 private final MacAddress mac1 = MacAddress.valueOf("00:11:00:00:00:01");
163 private final MacAddress mac2 = MacAddress.valueOf("00:22:00:00:00:02");
164 private final VlanId vlan1 = VlanId.vlanId((short) 11);
165 private final VlanId vlan2 = VlanId.vlanId((short) 22);
166 private final IpAddress ip1 = IpAddress.valueOf("10.0.0.1");
167 private final IpAddress ip2 = IpAddress.valueOf("10.0.0.2");
168 private final IpAddress ip3 = IpAddress.valueOf("10.0.0.3");
169
170 private final HostId hId1 = HostId.hostId(mac1, vlan1);
171 private final HostId hId2 = HostId.hostId(mac2, vlan2);
172 private final HostLocation loc1 = new HostLocation(devId1, portNumber(100), 123L);
173 private final HostLocation loc2 = new HostLocation(devId2, portNumber(200), 123L);
174 private final Set<IpAddress> ipSet1 = Sets.newHashSet(ip1, ip2);
175 private final Set<IpAddress> ipSet2 = Sets.newHashSet(ip1, ip3);
176 private final VirtualHost vhost1 = new DefaultVirtualHost(networkId1, hId1,
177 mac1, vlan1, loc1, ipSet1);
178 private final VirtualHost vhost2 = new DefaultVirtualHost(networkId2, hId2,
179 mac2, vlan2, loc2, ipSet2);
180
181
182
183
Claudine Chiufb8b8162016-04-01 23:50:51 +0000184 /**
185 * Sets up the global values for all the tests.
186 */
187 @Before
188 public void setUpTest() {
189 // Register the services needed for the test
190 codecService = new CodecManager();
191 codecService.activate();
192 ServiceDirectory testDirectory =
193 new TestServiceDirectory()
194 .add(VirtualNetworkAdminService.class, mockVnetAdminService)
195 .add(VirtualNetworkService.class, mockVnetService)
196 .add(CodecService.class, codecService);
197
Ray Milkey094a1352018-01-22 14:03:54 -0800198 setServiceDirectory(testDirectory);
Claudine Chiufb8b8162016-04-01 23:50:51 +0000199 }
200
201 /**
202 * Hamcrest matcher to check that a virtual network entity representation in JSON matches
203 * the actual virtual network entity.
204 */
Claudine Chiu25f07be2016-06-27 16:21:21 +0000205 private static final class JsonObjectMatcher<T> extends TypeSafeMatcher<JsonObject> {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000206 private final T vnetEntity;
207 private List<String> jsonFieldNames;
208 private String reason = "";
209 private BiFunction<T, String, String> getValue; // get vnetEntity's value
210
Claudine Chiu25f07be2016-06-27 16:21:21 +0000211 private JsonObjectMatcher(T vnetEntityValue,
212 List<String> jsonFieldNames1,
213 BiFunction<T, String, String> getValue1) {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000214 vnetEntity = vnetEntityValue;
215 jsonFieldNames = jsonFieldNames1;
216 getValue = getValue1;
217 }
218
219 @Override
220 public boolean matchesSafely(JsonObject jsonHost) {
221 return jsonFieldNames
222 .stream()
223 .allMatch(s -> checkField(jsonHost, s, getValue.apply(vnetEntity, s)));
224 }
225
226 private boolean checkField(JsonObject jsonHost, String jsonFieldName,
227 String objectValue) {
228 final String jsonValue = jsonHost.get(jsonFieldName).asString();
229 if (!jsonValue.equals(objectValue)) {
230 reason = jsonFieldName + " " + objectValue;
231 return false;
232 }
233 return true;
234 }
235
236 @Override
237 public void describeTo(Description description) {
238 description.appendText(reason);
239 }
240 }
241
242 /**
243 * Factory to allocate a virtual network id array matcher.
244 *
245 * @param obj virtual network id object we are looking for
246 * @return matcher
247 */
248 /**
249 * Factory to allocate a virtual network entity matcher.
250 *
Brian Stanke9a108972016-04-11 15:25:17 -0400251 * @param obj virtual network object we are looking for
Claudine Chiufb8b8162016-04-01 23:50:51 +0000252 * @param jsonFieldNames JSON field names to check against
Brian Stanke9a108972016-04-11 15:25:17 -0400253 * @param getValue function to retrieve value from virtual network object
Claudine Chiua98c2ea2016-04-19 16:09:18 +0000254 * @param <T> the type of virtual network object
255 * @return matcher
Claudine Chiufb8b8162016-04-01 23:50:51 +0000256 */
257 private static <T> JsonObjectMatcher matchesVnetEntity(T obj, List<String> jsonFieldNames,
Brian Stanke9a108972016-04-11 15:25:17 -0400258 BiFunction<T, String, String> getValue) {
Claudine Chiua98c2ea2016-04-19 16:09:18 +0000259 return new JsonObjectMatcher<T>(obj, jsonFieldNames, getValue);
Claudine Chiufb8b8162016-04-01 23:50:51 +0000260 }
261
262 /**
263 * Hamcrest matcher to check that a virtual network entity is represented properly in a JSON
264 * array of virtual network entities.
265 */
Claudine Chiu25f07be2016-06-27 16:21:21 +0000266 protected static class JsonArrayMatcher<T> extends TypeSafeMatcher<JsonArray> {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000267 private final T vnetEntity;
268 private String reason = "";
269 private Function<T, String> getKey; // gets vnetEntity's key
270 private BiPredicate<T, JsonObject> checkKey; // check vnetEntity's key with JSON rep'n
271 private List<String> jsonFieldNames; // field/property names
272 private BiFunction<T, String, String> getValue; // get vnetEntity's value
273
Claudine Chiu25f07be2016-06-27 16:21:21 +0000274 protected JsonArrayMatcher(T vnetEntityValue, Function<T, String> getKey1,
275 BiPredicate<T, JsonObject> checkKey1,
276 List<String> jsonFieldNames1,
277 BiFunction<T, String, String> getValue1) {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000278 vnetEntity = vnetEntityValue;
279 getKey = getKey1;
280 checkKey = checkKey1;
281 jsonFieldNames = jsonFieldNames1;
282 getValue = getValue1;
283 }
284
285 @Override
286 public boolean matchesSafely(JsonArray json) {
287 boolean itemFound = false;
288 final int expectedAttributes = jsonFieldNames.size();
289 for (int jsonArrayIndex = 0; jsonArrayIndex < json.size();
290 jsonArrayIndex++) {
291
292 final JsonObject jsonHost = json.get(jsonArrayIndex).asObject();
293
294 if (jsonHost.names().size() < expectedAttributes) {
295 reason = "Found a virtual network with the wrong number of attributes";
296 return false;
297 }
298
299 if (checkKey != null && checkKey.test(vnetEntity, jsonHost)) {
300 itemFound = true;
301 assertThat(jsonHost, matchesVnetEntity(vnetEntity, jsonFieldNames, getValue));
302 }
303 }
304 if (!itemFound) {
305 reason = getKey.apply(vnetEntity) + " was not found";
306 return false;
307 }
308 return true;
309 }
310
311 @Override
312 public void describeTo(Description description) {
313 description.appendText(reason);
314 }
315 }
316
317 /**
318 * Array matcher for VirtualNetwork.
319 */
Claudine Chiu25f07be2016-06-27 16:21:21 +0000320 private static final class VnetJsonArrayMatcher extends JsonArrayMatcher<VirtualNetwork> {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000321
Claudine Chiu25f07be2016-06-27 16:21:21 +0000322 private VnetJsonArrayMatcher(VirtualNetwork vnetIn) {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000323 super(vnetIn,
324 vnet -> "Virtual network " + vnet.id().toString(),
Jian Li08d65cf2016-04-20 10:07:17 -0700325 (vnet, jsonObject) -> jsonObject.get(ID).asString().equals(vnet.id().toString()),
Claudine Chiufb8b8162016-04-01 23:50:51 +0000326 ImmutableList.of(ID, TENANT_ID),
Jian Li08d65cf2016-04-20 10:07:17 -0700327 (vnet, s) -> s.equals(ID) ? vnet.id().toString()
328 : s.equals(TENANT_ID) ? vnet.tenantId().toString()
329 : null
Claudine Chiufb8b8162016-04-01 23:50:51 +0000330 );
331 }
332 }
333
334 /**
335 * Factory to allocate a virtual network array matcher.
336 *
337 * @param vnet virtual network object we are looking for
338 * @return matcher
339 */
340 private VnetJsonArrayMatcher hasVnet(VirtualNetwork vnet) {
341 return new VnetJsonArrayMatcher(vnet);
342 }
343
344 // Tests for Virtual Networks
345
346 /**
347 * Tests the result of the REST API GET when there are no virtual networks.
348 */
349 @Test
350 public void testGetVirtualNetworksEmptyArray() {
351 expect(mockVnetAdminService.getTenantIds()).andReturn(ImmutableSet.of()).anyTimes();
352 replay(mockVnetAdminService);
353 expect(mockVnetService.getVirtualNetworks(tenantId4)).andReturn(ImmutableSet.of()).anyTimes();
354 replay(mockVnetService);
355
356 WebTarget wt = target();
357 String response = wt.path("vnets").request().get(String.class);
358 assertThat(response, is("{\"vnets\":[]}"));
359
360 verify(mockVnetService);
361 verify(mockVnetAdminService);
362 }
363
364 /**
365 * Tests the result of the REST API GET when virtual networks are defined.
366 */
367 @Test
368 public void testGetVirtualNetworksArray() {
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000369 final Set<VirtualNetwork> vnetSet = ImmutableSet.of(vnet1, vnet2, vnet3, vnet4);
Claudine Chiufb8b8162016-04-01 23:50:51 +0000370 expect(mockVnetAdminService.getTenantIds()).andReturn(ImmutableSet.of(tenantId3)).anyTimes();
371 replay(mockVnetAdminService);
Claudine Chiufb8b8162016-04-01 23:50:51 +0000372 expect(mockVnetService.getVirtualNetworks(tenantId3)).andReturn(vnetSet).anyTimes();
373 replay(mockVnetService);
374
375 WebTarget wt = target();
376 String response = wt.path("vnets").request().get(String.class);
377 assertThat(response, containsString("{\"vnets\":["));
378
379 final JsonObject result = Json.parse(response).asObject();
380 assertThat(result, notNullValue());
381
382 assertThat(result.names(), hasSize(1));
383 assertThat(result.names().get(0), is("vnets"));
384
385 final JsonArray vnetJsonArray = result.get("vnets").asArray();
386 assertThat(vnetJsonArray, notNullValue());
387 assertEquals("Virtual networks array is not the correct size.",
388 vnetSet.size(), vnetJsonArray.size());
389
390 vnetSet.forEach(vnet -> assertThat(vnetJsonArray, hasVnet(vnet)));
391
392 verify(mockVnetService);
393 verify(mockVnetAdminService);
394 }
395
396 /**
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000397 * Tests the result of the REST API GET for virtual networks with tenant id.
398 */
399 @Test
400 public void testGetVirtualNetworksByTenantId() {
401 final Set<VirtualNetwork> vnetSet = ImmutableSet.of(vnet1, vnet2, vnet3, vnet4);
402 expect(mockVnetAdminService.getTenantIds()).andReturn(ImmutableSet.of(tenantId3)).anyTimes();
403 replay(mockVnetAdminService);
404 expect(mockVnetService.getVirtualNetworks(tenantId3)).andReturn(vnetSet).anyTimes();
405 replay(mockVnetService);
406
407 WebTarget wt = target();
408 String response = wt.path("vnets/" + tenantId3.id()).request().get(String.class);
409 assertThat(response, containsString("{\"vnets\":["));
410
411 final JsonObject result = Json.parse(response).asObject();
412 assertThat(result, notNullValue());
413
414 assertThat(result.names(), hasSize(1));
415 assertThat(result.names().get(0), is("vnets"));
416
417 final JsonArray vnetJsonArray = result.get("vnets").asArray();
418 assertThat(vnetJsonArray, notNullValue());
419 assertEquals("Virtual networks array is not the correct size.",
420 vnetSet.size(), vnetJsonArray.size());
421
422 vnetSet.forEach(vnet -> assertThat(vnetJsonArray, hasVnet(vnet)));
423
424 verify(mockVnetService);
425 verify(mockVnetAdminService);
426 }
427
428 /**
429 * Tests the result of the REST API GET for virtual networks with tenant id.
430 */
431 @Test
432 public void testGetVirtualNetworksByNonExistentTenantId() {
433 String tenantIdName = "NON_EXISTENT_TENANT_ID";
434 expect(mockVnetAdminService.getTenantIds()).andReturn(ImmutableSet.of(tenantId3)).anyTimes();
435 replay(mockVnetAdminService);
436 expect(mockVnetService.getVirtualNetworks(anyObject())).andReturn(ImmutableSet.of()).anyTimes();
437 replay(mockVnetService);
438
439 WebTarget wt = target();
440
441 try {
442 wt.path("vnets/" + tenantIdName)
443 .request()
444 .get(String.class);
445 fail("Get of a non-existent virtual network did not throw an exception");
446 } catch (NotFoundException ex) {
447 assertThat(ex.getMessage(), containsString("HTTP 404 Not Found"));
448 }
449
450 verify(mockVnetService);
451 verify(mockVnetAdminService);
452 }
453
454 /**
Claudine Chiufb8b8162016-04-01 23:50:51 +0000455 * Tests adding of new virtual network using POST via JSON stream.
456 */
457 @Test
458 public void testPostVirtualNetwork() {
459 expect(mockVnetAdminService.createVirtualNetwork(tenantId2)).andReturn(vnet1);
460 expectLastCall();
461
462 replay(mockVnetAdminService);
463
464 WebTarget wt = target();
465 InputStream jsonStream = TenantWebResourceTest.class
466 .getResourceAsStream("post-tenant.json");
467
468 Response response = wt.path("vnets").request(MediaType.APPLICATION_JSON_TYPE)
469 .post(Entity.json(jsonStream));
470 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
471
472 String location = response.getLocation().getPath();
473 assertThat(location, Matchers.startsWith("/vnets/" + vnet1.id().toString()));
474
475 verify(mockVnetAdminService);
476 }
477
478 /**
479 * Tests adding of a null virtual network using POST via JSON stream.
480 */
481 @Test
482 public void testPostVirtualNetworkNullTenantId() {
483
484 replay(mockVnetAdminService);
485
486 WebTarget wt = target();
487 try {
Jian Li08d65cf2016-04-20 10:07:17 -0700488 wt.path("vnets")
Claudine Chiufb8b8162016-04-01 23:50:51 +0000489 .request(MediaType.APPLICATION_JSON_TYPE)
490 .post(Entity.json(null), String.class);
491 fail("POST of null virtual network did not throw an exception");
492 } catch (BadRequestException ex) {
493 assertThat(ex.getMessage(), containsString("HTTP 400 Bad Request"));
Jian Li70773462020-02-05 16:23:53 +0900494 } catch (InternalServerErrorException ex) {
495 assertThat(ex.getMessage(), containsString("HTTP 500 Internal Server Error"));
Claudine Chiufb8b8162016-04-01 23:50:51 +0000496 }
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"));
Jian Li70773462020-02-05 16:23:53 +0900669 } catch (InternalServerErrorException ex) {
670 assertThat(ex.getMessage(), containsString("HTTP 500 Internal Server Error"));
Claudine Chiufb8b8162016-04-01 23:50:51 +0000671 }
672
673 verify(mockVnetAdminService);
674 }
675
676 /**
677 * Tests removing a virtual device with DELETE request.
678 */
679 @Test
680 public void testDeleteVirtualDevice() {
681 NetworkId networkId = networkId3;
682 DeviceId deviceId = devId2;
683 mockVnetAdminService.removeVirtualDevice(networkId, deviceId);
684 expectLastCall();
685 replay(mockVnetAdminService);
686
687 WebTarget wt = target()
688 .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
689 String reqLocation = "vnets/" + networkId.toString() + "/devices/" + deviceId.toString();
690 Response response = wt.path(reqLocation)
691 .request(MediaType.APPLICATION_JSON_TYPE)
692 .delete();
693
Jian Lic2a542b2016-05-10 11:48:19 -0700694 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NO_CONTENT));
Claudine Chiufb8b8162016-04-01 23:50:51 +0000695
696 verify(mockVnetAdminService);
697 }
698
699 // Tests for Virtual Ports
700
701 /**
702 * Tests the result of the REST API GET when there are no virtual ports.
703 */
704 @Test
705 public void testGetVirtualPortsEmptyArray() {
706 NetworkId networkId = networkId4;
707 DeviceId deviceId = devId2;
708 expect(mockVnetService.getVirtualPorts(networkId, deviceId))
709 .andReturn(ImmutableSet.of()).anyTimes();
710 replay(mockVnetService);
711
712 WebTarget wt = target();
713 String location = "vnets/" + networkId.toString()
714 + "/devices/" + deviceId.toString() + "/ports";
715 String response = wt.path(location).request().get(String.class);
716 assertThat(response, is("{\"ports\":[]}"));
717
718 verify(mockVnetService);
719 }
720
721 /**
722 * Tests the result of the REST API GET when virtual ports are defined.
723 */
724 @Test
725 public void testGetVirtualPortsArray() {
726 NetworkId networkId = networkId3;
727 DeviceId deviceId = dev22.id();
728 vportSet.add(vport23);
729 vportSet.add(vport22);
730 expect(mockVnetService.getVirtualPorts(networkId, deviceId)).andReturn(vportSet).anyTimes();
731 replay(mockVnetService);
732
733 WebTarget wt = target();
734 String location = "vnets/" + networkId.toString()
735 + "/devices/" + deviceId.toString() + "/ports";
736 String response = wt.path(location).request().get(String.class);
737 assertThat(response, containsString("{\"ports\":["));
738
739 final JsonObject result = Json.parse(response).asObject();
740 assertThat(result, notNullValue());
741
742 assertThat(result.names(), hasSize(1));
743 assertThat(result.names().get(0), is("ports"));
744
745 final JsonArray vnetJsonArray = result.get("ports").asArray();
746 assertThat(vnetJsonArray, notNullValue());
747 assertEquals("Virtual ports array is not the correct size.",
Brian Stanke9a108972016-04-11 15:25:17 -0400748 vportSet.size(), vnetJsonArray.size());
Claudine Chiufb8b8162016-04-01 23:50:51 +0000749
750 vportSet.forEach(vport -> assertThat(vnetJsonArray, hasVport(vport)));
751
752 verify(mockVnetService);
753 }
754
755 /**
756 * Array matcher for VirtualPort.
757 */
Claudine Chiu25f07be2016-06-27 16:21:21 +0000758 private static final class VportJsonArrayMatcher extends JsonArrayMatcher<VirtualPort> {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000759
Claudine Chiu25f07be2016-06-27 16:21:21 +0000760 private VportJsonArrayMatcher(VirtualPort vportIn) {
Claudine Chiufb8b8162016-04-01 23:50:51 +0000761 super(vportIn,
762 vport -> "Virtual port " + vport.networkId().toString() + " "
763 + vport.element().id().toString() + " " + vport.number().toString(),
Jian Li08d65cf2016-04-20 10:07:17 -0700764 (vport, jsonObject) -> jsonObject.get(ID).asString().equals(vport.networkId().toString())
765 && jsonObject.get(PORT_NUM).asString().equals(vport.number().toString())
766 && jsonObject.get(DEVICE_ID).asString().equals(vport.element().id().toString()),
Claudine Chiufb8b8162016-04-01 23:50:51 +0000767 ImmutableList.of(ID, DEVICE_ID, PORT_NUM, PHYS_DEVICE_ID, PHYS_PORT_NUM),
Jian Li08d65cf2016-04-20 10:07:17 -0700768 (vport, s) -> s.equals(ID) ? vport.networkId().toString()
769 : s.equals(DEVICE_ID) ? vport.element().id().toString()
770 : s.equals(PORT_NUM) ? vport.number().toString()
Yoonseon Han6c603892016-09-01 11:52:21 -0700771 : s.equals(PHYS_DEVICE_ID) ? vport.realizedBy().deviceId().toString()
772 : s.equals(PHYS_PORT_NUM) ? vport.realizedBy().port().toString()
Jian Li08d65cf2016-04-20 10:07:17 -0700773 : null
Claudine Chiufb8b8162016-04-01 23:50:51 +0000774 );
775 }
776 }
777
778 /**
779 * Factory to allocate a virtual port array matcher.
780 *
781 * @param vport virtual port object we are looking for
782 * @return matcher
783 */
784 private VportJsonArrayMatcher hasVport(VirtualPort vport) {
785 return new VportJsonArrayMatcher(vport);
786 }
787
788 /**
789 * Tests adding of new virtual port using POST via JSON stream.
790 */
791 @Test
792 public void testPostVirtualPort() {
793 NetworkId networkId = networkId3;
794 DeviceId deviceId = devId22;
795 DefaultAnnotations annotations = DefaultAnnotations.builder().build();
796 Device physDevice = new DefaultDevice(null, DeviceId.deviceId("dev1"),
Brian Stanke9a108972016-04-11 15:25:17 -0400797 null, null, null, null, null, null, annotations);
Yoonseon Han6c603892016-09-01 11:52:21 -0700798 ConnectPoint cp1 = new ConnectPoint(physDevice.id(), portNumber(1));
799 expect(mockVnetAdminService.createVirtualPort(networkId, deviceId, portNumber(22), cp1))
Claudine Chiufb8b8162016-04-01 23:50:51 +0000800 .andReturn(vport22);
801
802 replay(mockVnetAdminService);
803
804 WebTarget wt = target();
805 InputStream jsonStream = VirtualNetworkWebResourceTest.class
806 .getResourceAsStream("post-virtual-port.json");
807 String reqLocation = "vnets/" + networkId.toString()
808 + "/devices/" + deviceId.toString() + "/ports";
809 Response response = wt.path(reqLocation).request(MediaType.APPLICATION_JSON_TYPE)
810 .post(Entity.json(jsonStream));
811 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
812
813 verify(mockVnetAdminService);
814 }
815
816 /**
817 * Tests adding of a null virtual port using POST via JSON stream.
818 */
819 @Test
820 public void testPostVirtualPortNullJsonStream() {
821 NetworkId networkId = networkId3;
822 DeviceId deviceId = devId2;
823 replay(mockVnetAdminService);
824
825 WebTarget wt = target();
826 try {
827 String reqLocation = "vnets/" + networkId.toString()
828 + "/devices/" + deviceId.toString() + "/ports";
Jian Li08d65cf2016-04-20 10:07:17 -0700829 wt.path(reqLocation)
Claudine Chiufb8b8162016-04-01 23:50:51 +0000830 .request(MediaType.APPLICATION_JSON_TYPE)
831 .post(Entity.json(null), String.class);
832 fail("POST of null virtual port did not throw an exception");
833 } catch (BadRequestException ex) {
834 assertThat(ex.getMessage(), containsString("HTTP 400 Bad Request"));
Jian Li70773462020-02-05 16:23:53 +0900835 } catch (InternalServerErrorException ex) {
836 assertThat(ex.getMessage(), containsString("HTTP 500 Internal Server Error"));
Claudine Chiufb8b8162016-04-01 23:50:51 +0000837 }
838
839 verify(mockVnetAdminService);
840 }
841
842 /**
843 * Tests removing a virtual port with DELETE request.
844 */
845 @Test
846 public void testDeleteVirtualPort() {
847 NetworkId networkId = networkId3;
848 DeviceId deviceId = devId2;
849 PortNumber portNum = portNumber(2);
850 mockVnetAdminService.removeVirtualPort(networkId, deviceId, portNum);
851 expectLastCall();
852 replay(mockVnetAdminService);
853
854 WebTarget wt = target()
855 .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
856 String reqLocation = "vnets/" + networkId.toString()
Brian Stanke9a108972016-04-11 15:25:17 -0400857 + "/devices/" + deviceId.toString() + "/ports/" + portNum.toLong();
Claudine Chiufb8b8162016-04-01 23:50:51 +0000858 Response response = wt.path(reqLocation)
859 .request(MediaType.APPLICATION_JSON_TYPE)
860 .delete();
861
Jian Lic2a542b2016-05-10 11:48:19 -0700862 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NO_CONTENT));
Claudine Chiufb8b8162016-04-01 23:50:51 +0000863
864 verify(mockVnetAdminService);
865 }
866
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000867 // Tests for Virtual Links
868
869 /**
870 * Tests the result of the REST API GET when there are no virtual links.
871 */
872 @Test
873 public void testGetVirtualLinksEmptyArray() {
874 NetworkId networkId = networkId4;
875 expect(mockVnetService.getVirtualLinks(networkId)).andReturn(ImmutableSet.of()).anyTimes();
876 replay(mockVnetService);
877
878 WebTarget wt = target();
879 String location = "vnets/" + networkId.toString() + "/links";
880 String response = wt.path(location).request().get(String.class);
881 assertThat(response, is("{\"links\":[]}"));
882
883 verify(mockVnetService);
884 }
885
886 /**
887 * Tests the result of the REST API GET when virtual links are defined.
888 */
889 @Test
890 public void testGetVirtualLinksArray() {
891 NetworkId networkId = networkId3;
892 final Set<VirtualLink> vlinkSet = ImmutableSet.of(vlink1, vlink2);
893 expect(mockVnetService.getVirtualLinks(networkId)).andReturn(vlinkSet).anyTimes();
894 replay(mockVnetService);
895
896 WebTarget wt = target();
897 String location = "vnets/" + networkId.toString() + "/links";
898 String response = wt.path(location).request().get(String.class);
899 assertThat(response, containsString("{\"links\":["));
900
901 final JsonObject result = Json.parse(response).asObject();
902 assertThat(result, notNullValue());
903
904 assertThat(result.names(), hasSize(1));
905 assertThat(result.names().get(0), is("links"));
906
907 final JsonArray vnetJsonArray = result.get("links").asArray();
908 assertThat(vnetJsonArray, notNullValue());
909 assertEquals("Virtual links array is not the correct size.",
910 vlinkSet.size(), vnetJsonArray.size());
911
912 vlinkSet.forEach(vlink -> assertThat(vnetJsonArray, hasVlink(vlink)));
913
914 verify(mockVnetService);
915 }
916
917 /**
918 * Hamcrest matcher to check that a virtual link representation in JSON matches
919 * the actual virtual link.
920 */
Claudine Chiu25f07be2016-06-27 16:21:21 +0000921 private static final class VirtualLinkJsonMatcher extends LinksResourceTest.LinkJsonMatcher {
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000922 private final VirtualLink vlink;
923 private String reason = "";
924
Claudine Chiu25f07be2016-06-27 16:21:21 +0000925 private VirtualLinkJsonMatcher(VirtualLink vlinkValue) {
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000926 super(vlinkValue);
927 vlink = vlinkValue;
928 }
929
930 @Override
931 public boolean matchesSafely(JsonObject jsonLink) {
932 if (!super.matchesSafely(jsonLink)) {
933 return false;
934 }
935 // check NetworkId
936 String jsonNetworkId = jsonLink.get(ID).asString();
937 String networkId = vlink.networkId().toString();
938 if (!jsonNetworkId.equals(networkId)) {
939 reason = ID + " was " + jsonNetworkId;
940 return false;
941 }
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000942 return true;
943 }
944
945 @Override
946 public void describeTo(Description description) {
947 description.appendText(reason);
948 }
949 }
950
951 /**
952 * Factory to allocate a virtual link matcher.
953 *
954 * @param vlink virtual link object we are looking for
955 * @return matcher
956 */
957 private static VirtualLinkJsonMatcher matchesVirtualLink(VirtualLink vlink) {
958 return new VirtualLinkJsonMatcher(vlink);
959 }
960
961 /**
962 * Hamcrest matcher to check that a virtual link is represented properly in a JSON
963 * array of links.
964 */
Claudine Chiu25f07be2016-06-27 16:21:21 +0000965 private static final class VirtualLinkJsonArrayMatcher extends TypeSafeMatcher<JsonArray> {
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000966 private final VirtualLink vlink;
967 private String reason = "";
968
Claudine Chiu25f07be2016-06-27 16:21:21 +0000969 private VirtualLinkJsonArrayMatcher(VirtualLink vlinkValue) {
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000970 vlink = vlinkValue;
971 }
972
973 @Override
974 public boolean matchesSafely(JsonArray json) {
Claudine Chiuf6bf8d52016-04-08 01:31:54 +0000975 for (int jsonLinkIndex = 0; jsonLinkIndex < json.size();
976 jsonLinkIndex++) {
977
978 JsonObject jsonLink = json.get(jsonLinkIndex).asObject();
979
980 if (matchesVirtualLink(vlink).matchesSafely(jsonLink)) {
981 return true;
982 }
983 }
984 return false;
985 }
986
987 @Override
988 public void describeTo(Description description) {
989 description.appendText(reason);
990 }
991 }
992
993 /**
994 * Factory to allocate a virtual link array matcher.
995 *
996 * @param vlink virtual link object we are looking for
997 * @return matcher
998 */
999 private VirtualLinkJsonArrayMatcher hasVlink(VirtualLink vlink) {
1000 return new VirtualLinkJsonArrayMatcher(vlink);
1001 }
1002
1003 /**
1004 * Tests adding of new virtual link using POST via JSON stream.
1005 */
1006 @Test
1007 public void testPostVirtualLink() {
1008 NetworkId networkId = networkId3;
Brian Stanke9a108972016-04-11 15:25:17 -04001009 expect(mockVnetAdminService.createVirtualLink(networkId, cp22, cp11))
Claudine Chiuf6bf8d52016-04-08 01:31:54 +00001010 .andReturn(vlink1);
1011 replay(mockVnetAdminService);
1012
1013 WebTarget wt = target();
1014 InputStream jsonStream = VirtualNetworkWebResourceTest.class
1015 .getResourceAsStream("post-virtual-link.json");
1016 String reqLocation = "vnets/" + networkId.toString() + "/links";
1017 Response response = wt.path(reqLocation).request(MediaType.APPLICATION_JSON_TYPE)
1018 .post(Entity.json(jsonStream));
1019 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
1020
1021 String location = response.getLocation().getPath();
1022 assertThat(location, Matchers.startsWith("/" + reqLocation));
1023
1024 verify(mockVnetAdminService);
1025 }
1026
1027 /**
1028 * Tests adding of a null virtual link using POST via JSON stream.
1029 */
1030 @Test
1031 public void testPostVirtualLinkNullJsonStream() {
1032 NetworkId networkId = networkId3;
1033 replay(mockVnetAdminService);
1034
1035 WebTarget wt = target();
1036 try {
1037 String reqLocation = "vnets/" + networkId.toString() + "/links";
1038 wt.path(reqLocation)
1039 .request(MediaType.APPLICATION_JSON_TYPE)
1040 .post(Entity.json(null), String.class);
1041 fail("POST of null virtual link did not throw an exception");
1042 } catch (BadRequestException ex) {
1043 assertThat(ex.getMessage(), containsString("HTTP 400 Bad Request"));
Jian Li70773462020-02-05 16:23:53 +09001044 } catch (InternalServerErrorException ex) {
1045 assertThat(ex.getMessage(), containsString("HTTP 500 Internal Server Error"));
Claudine Chiuf6bf8d52016-04-08 01:31:54 +00001046 }
1047
1048 verify(mockVnetAdminService);
1049 }
1050
1051 /**
1052 * Tests removing a virtual link with DELETE request.
1053 */
1054 @Test
1055 public void testDeleteVirtualLink() {
1056 NetworkId networkId = networkId3;
1057 mockVnetAdminService.removeVirtualLink(networkId, cp22, cp11);
1058 expectLastCall();
1059 replay(mockVnetAdminService);
1060
1061 WebTarget wt = target()
1062 .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
1063 InputStream jsonStream = VirtualNetworkWebResourceTest.class
1064 .getResourceAsStream("post-virtual-link.json");
1065 String reqLocation = "vnets/" + networkId.toString() + "/links";
Jian Li08d65cf2016-04-20 10:07:17 -07001066 Response response = wt.path(reqLocation).request().method("DELETE", Entity.json(jsonStream));
Claudine Chiuf6bf8d52016-04-08 01:31:54 +00001067
Jian Lic2a542b2016-05-10 11:48:19 -07001068 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NO_CONTENT));
Claudine Chiuf6bf8d52016-04-08 01:31:54 +00001069 verify(mockVnetAdminService);
1070 }
Claudine Chiu25f07be2016-06-27 16:21:21 +00001071
1072 // Tests for Virtual Hosts
1073
1074 /**
1075 * Tests the result of the REST API GET when there are no virtual hosts.
1076 */
1077 @Test
1078 public void testGetVirtualHostsEmptyArray() {
1079 NetworkId networkId = networkId4;
1080 expect(mockVnetService.getVirtualHosts(networkId)).andReturn(ImmutableSet.of()).anyTimes();
1081 replay(mockVnetService);
1082
1083 WebTarget wt = target();
1084 String location = "vnets/" + networkId.toString() + "/hosts";
1085 String response = wt.path(location).request().get(String.class);
1086 assertThat(response, is("{\"hosts\":[]}"));
1087
1088 verify(mockVnetService);
1089 }
1090
1091 /**
1092 * Tests the result of the REST API GET when virtual hosts are defined.
1093 */
1094 @Test
1095 public void testGetVirtualHostsArray() {
1096 NetworkId networkId = networkId3;
1097 final Set<VirtualHost> vhostSet = ImmutableSet.of(vhost1, vhost2);
1098 expect(mockVnetService.getVirtualHosts(networkId)).andReturn(vhostSet).anyTimes();
1099 replay(mockVnetService);
1100
1101 WebTarget wt = target();
1102 String location = "vnets/" + networkId.toString() + "/hosts";
1103 String response = wt.path(location).request().get(String.class);
1104 assertThat(response, containsString("{\"hosts\":["));
1105
1106 final JsonObject result = Json.parse(response).asObject();
1107 assertThat(result, notNullValue());
1108
1109 assertThat(result.names(), hasSize(1));
1110 assertThat(result.names().get(0), is("hosts"));
1111
1112 final JsonArray vnetJsonArray = result.get("hosts").asArray();
1113 assertThat(vnetJsonArray, notNullValue());
1114 assertEquals("Virtual hosts array is not the correct size.",
1115 vhostSet.size(), vnetJsonArray.size());
1116
1117 vhostSet.forEach(vhost -> assertThat(vnetJsonArray, hasVhost(vhost)));
1118
1119 verify(mockVnetService);
1120 }
1121
1122 /**
1123 * Hamcrest matcher to check that a virtual host representation in JSON matches
1124 * the actual virtual host.
1125 */
1126 private static final class VirtualHostJsonMatcher extends HostResourceTest.HostJsonMatcher {
1127 private final VirtualHost vhost;
1128 private String reason = "";
1129
1130 private VirtualHostJsonMatcher(VirtualHost vhostValue) {
1131 super(vhostValue);
1132 vhost = vhostValue;
1133 }
1134
1135 @Override
1136 public boolean matchesSafely(JsonObject jsonHost) {
1137 if (!super.matchesSafely(jsonHost)) {
1138 return false;
1139 }
1140 // check NetworkId
1141 String jsonNetworkId = jsonHost.get(ID).asString();
1142 String networkId = vhost.networkId().toString();
1143 if (!jsonNetworkId.equals(networkId)) {
1144 reason = ID + " was " + jsonNetworkId;
1145 return false;
1146 }
1147 return true;
1148 }
1149
1150 @Override
1151 public void describeTo(Description description) {
1152 description.appendText(reason);
1153 }
1154 }
1155
1156 /**
1157 * Factory to allocate a virtual host matcher.
1158 *
1159 * @param vhost virtual host object we are looking for
1160 * @return matcher
1161 */
1162 private static VirtualHostJsonMatcher matchesVirtualHost(VirtualHost vhost) {
1163 return new VirtualHostJsonMatcher(vhost);
1164 }
1165
1166 /**
1167 * Hamcrest matcher to check that a virtual host is represented properly in a JSON
1168 * array of hosts.
1169 */
1170 private static final class VirtualHostJsonArrayMatcher extends TypeSafeMatcher<JsonArray> {
1171 private final VirtualHost vhost;
1172 private String reason = "";
1173
1174 private VirtualHostJsonArrayMatcher(VirtualHost vhostValue) {
1175 vhost = vhostValue;
1176 }
1177
1178 @Override
1179 public boolean matchesSafely(JsonArray json) {
1180 for (int jsonHostIndex = 0; jsonHostIndex < json.size();
1181 jsonHostIndex++) {
1182
1183 JsonObject jsonHost = json.get(jsonHostIndex).asObject();
1184
1185 if (matchesVirtualHost(vhost).matchesSafely(jsonHost)) {
1186 return true;
1187 }
1188 }
1189 return false;
1190 }
1191
1192 @Override
1193 public void describeTo(Description description) {
1194 description.appendText(reason);
1195 }
1196 }
1197
1198 /**
1199 * Factory to allocate a virtual host array matcher.
1200 *
1201 * @param vhost virtual host object we are looking for
1202 * @return matcher
1203 */
1204 private VirtualHostJsonArrayMatcher hasVhost(VirtualHost vhost) {
1205 return new VirtualHostJsonArrayMatcher(vhost);
1206 }
1207
1208 /**
1209 * Tests adding of new virtual host using POST via JSON stream.
1210 */
1211 @Test
1212 public void testPostVirtualHost() {
1213 NetworkId networkId = networkId3;
1214 expect(mockVnetAdminService.createVirtualHost(networkId, hId1, mac1, vlan1, loc1, ipSet1))
1215 .andReturn(vhost1);
1216 replay(mockVnetAdminService);
1217
1218 WebTarget wt = target();
1219 InputStream jsonStream = VirtualNetworkWebResourceTest.class
1220 .getResourceAsStream("post-virtual-host.json");
1221 String reqLocation = "vnets/" + networkId.toString() + "/hosts";
1222 Response response = wt.path(reqLocation).request(MediaType.APPLICATION_JSON_TYPE)
1223 .post(Entity.json(jsonStream));
1224 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
1225
1226 String location = response.getLocation().getPath();
1227 assertThat(location, Matchers.startsWith("/" + reqLocation));
1228
1229 verify(mockVnetAdminService);
1230 }
1231
1232 /**
1233 * Tests adding of a null virtual host using POST via JSON stream.
1234 */
1235 @Test
1236 public void testPostVirtualHostNullJsonStream() {
1237 NetworkId networkId = networkId3;
1238 replay(mockVnetAdminService);
1239
1240 WebTarget wt = target();
1241 try {
1242 String reqLocation = "vnets/" + networkId.toString() + "/hosts";
1243 wt.path(reqLocation)
1244 .request(MediaType.APPLICATION_JSON_TYPE)
1245 .post(Entity.json(null), String.class);
1246 fail("POST of null virtual host did not throw an exception");
1247 } catch (BadRequestException ex) {
1248 assertThat(ex.getMessage(), containsString("HTTP 400 Bad Request"));
Jian Li70773462020-02-05 16:23:53 +09001249 } catch (InternalServerErrorException ex) {
1250 assertThat(ex.getMessage(), containsString("HTTP 500 Internal Server Error"));
Claudine Chiu25f07be2016-06-27 16:21:21 +00001251 }
1252
1253 verify(mockVnetAdminService);
1254 }
1255
1256 /**
1257 * Tests removing a virtual host with DELETE request.
1258 */
1259 @Test
1260 public void testDeleteVirtualHost() {
1261 NetworkId networkId = networkId3;
1262 mockVnetAdminService.removeVirtualHost(networkId, hId1);
1263 expectLastCall();
1264 replay(mockVnetAdminService);
1265
1266 WebTarget wt = target()
1267 .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
1268 InputStream jsonStream = VirtualNetworkWebResourceTest.class
1269 .getResourceAsStream("post-virtual-host.json");
1270 String reqLocation = "vnets/" + networkId.toString() + "/hosts";
1271 Response response = wt.path(reqLocation).request().method("DELETE", Entity.json(jsonStream));
1272
1273 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NO_CONTENT));
1274 verify(mockVnetAdminService);
1275 }
Claudine Chiufb8b8162016-04-01 23:50:51 +00001276}