blob: 63c669873820ccbee9a466604ee8a1a2a0ce6df5 [file] [log] [blame]
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.rest.resources;
import com.eclipsesource.json.Json;
import com.eclipsesource.json.JsonArray;
import com.eclipsesource.json.JsonObject;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import org.glassfish.jersey.client.ClientProperties;
import org.hamcrest.Description;
import org.hamcrest.Matchers;
import org.hamcrest.TypeSafeMatcher;
import org.junit.Before;
import org.junit.Test;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
import org.onlab.rest.BaseResource;
import org.onosproject.codec.CodecService;
import org.onosproject.codec.impl.CodecManager;
import org.onosproject.incubator.net.tunnel.TunnelId;
import org.onosproject.incubator.net.virtual.DefaultVirtualDevice;
import org.onosproject.incubator.net.virtual.DefaultVirtualLink;
import org.onosproject.incubator.net.virtual.DefaultVirtualNetwork;
import org.onosproject.incubator.net.virtual.DefaultVirtualPort;
import org.onosproject.incubator.net.virtual.NetworkId;
import org.onosproject.incubator.net.virtual.TenantId;
import org.onosproject.incubator.net.virtual.VirtualDevice;
import org.onosproject.incubator.net.virtual.VirtualLink;
import org.onosproject.incubator.net.virtual.VirtualNetwork;
import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
import org.onosproject.incubator.net.virtual.VirtualNetworkService;
import org.onosproject.incubator.net.virtual.VirtualPort;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.DefaultDevice;
import org.onosproject.net.DefaultPort;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.NetTestTools;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import javax.ws.rs.BadRequestException;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Function;
import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import static org.onosproject.net.PortNumber.portNumber;
/**
* Unit tests for virtual network REST APIs.
*/
public class VirtualNetworkWebResourceTest extends ResourceTest {
private final VirtualNetworkAdminService mockVnetAdminService = createMock(VirtualNetworkAdminService.class);
private final VirtualNetworkService mockVnetService = createMock(VirtualNetworkService.class);
private CodecManager codecService;
final HashSet<TenantId> tenantIdSet = new HashSet<>();
final HashSet<VirtualDevice> vdevSet = new HashSet<>();
final HashSet<VirtualPort> vportSet = new HashSet<>();
private static final String ID = "networkId";
private static final String TENANT_ID = "tenantId";
private static final String DEVICE_ID = "deviceId";
private static final String PORT_NUM = "portNum";
private static final String PHYS_DEVICE_ID = "physDeviceId";
private static final String PHYS_PORT_NUM = "physPortNum";
private static final String TUNNEL_ID = "tunnelId";
private final TenantId tenantId1 = TenantId.tenantId("TenantId1");
private final TenantId tenantId2 = TenantId.tenantId("TenantId2");
private final TenantId tenantId3 = TenantId.tenantId("TenantId3");
private final TenantId tenantId4 = TenantId.tenantId("TenantId4");
private final NetworkId networkId1 = NetworkId.networkId(1);
private final NetworkId networkId2 = NetworkId.networkId(2);
private final NetworkId networkId3 = NetworkId.networkId(3);
private final NetworkId networkId4 = NetworkId.networkId(4);
private final VirtualNetwork vnet1 = new DefaultVirtualNetwork(networkId1, tenantId3);
private final VirtualNetwork vnet2 = new DefaultVirtualNetwork(networkId2, tenantId3);
private final VirtualNetwork vnet3 = new DefaultVirtualNetwork(networkId3, tenantId3);
private final VirtualNetwork vnet4 = new DefaultVirtualNetwork(networkId4, tenantId3);
private final DeviceId devId1 = DeviceId.deviceId("devid1");
private final DeviceId devId2 = DeviceId.deviceId("devid2");
private final DeviceId devId22 = DeviceId.deviceId("dev22");
private final VirtualDevice vdev1 = new DefaultVirtualDevice(networkId3, devId1);
private final VirtualDevice vdev2 = new DefaultVirtualDevice(networkId3, devId2);
private final Device dev1 = NetTestTools.device("dev1");
private final Device dev2 = NetTestTools.device("dev2");
private final Device dev21 = NetTestTools.device("dev21");
private final Device dev22 = NetTestTools.device("dev22");
Port port1 = new DefaultPort(dev1, portNumber(1), true);
Port port2 = new DefaultPort(dev2, portNumber(2), true);
private final VirtualPort vport22 = new DefaultVirtualPort(networkId3,
dev22, portNumber(22), port1);
private final VirtualPort vport23 = new DefaultVirtualPort(networkId3,
dev22, portNumber(23), port2);
private final ConnectPoint cp11 = NetTestTools.connectPoint(devId1.toString(), 21);
private final ConnectPoint cp21 = NetTestTools.connectPoint(devId2.toString(), 22);
private final ConnectPoint cp12 = NetTestTools.connectPoint(devId1.toString(), 2);
private final ConnectPoint cp22 = NetTestTools.connectPoint(devId2.toString(), 22);
private final TunnelId tunnelId = TunnelId.valueOf(31);
private final VirtualLink vlink1 = new DefaultVirtualLink(networkId3, cp22, cp11, tunnelId);
private final VirtualLink vlink2 = new DefaultVirtualLink(networkId3, cp12, cp21, tunnelId);
/**
* Sets up the global values for all the tests.
*/
@Before
public void setUpTest() {
// Register the services needed for the test
codecService = new CodecManager();
codecService.activate();
ServiceDirectory testDirectory =
new TestServiceDirectory()
.add(VirtualNetworkAdminService.class, mockVnetAdminService)
.add(VirtualNetworkService.class, mockVnetService)
.add(CodecService.class, codecService);
BaseResource.setServiceDirectory(testDirectory);
}
/**
* Hamcrest matcher to check that a virtual network entity representation in JSON matches
* the actual virtual network entity.
*/
public static class JsonObjectMatcher<T> extends TypeSafeMatcher<JsonObject> {
private final T vnetEntity;
private List<String> jsonFieldNames;
private String reason = "";
private BiFunction<T, String, String> getValue; // get vnetEntity's value
public JsonObjectMatcher(T vnetEntityValue,
List<String> jsonFieldNames1,
BiFunction<T, String, String> getValue1) {
vnetEntity = vnetEntityValue;
jsonFieldNames = jsonFieldNames1;
getValue = getValue1;
}
@Override
public boolean matchesSafely(JsonObject jsonHost) {
return jsonFieldNames
.stream()
.allMatch(s -> checkField(jsonHost, s, getValue.apply(vnetEntity, s)));
}
private boolean checkField(JsonObject jsonHost, String jsonFieldName,
String objectValue) {
final String jsonValue = jsonHost.get(jsonFieldName).asString();
if (!jsonValue.equals(objectValue)) {
reason = jsonFieldName + " " + objectValue;
return false;
}
return true;
}
@Override
public void describeTo(Description description) {
description.appendText(reason);
}
}
/**
* Factory to allocate a virtual network id array matcher.
*
* @param obj virtual network id object we are looking for
* @return matcher
*/
/**
* Factory to allocate a virtual network entity matcher.
*
* @param obj virtual network object we are looking for
* @param jsonFieldNames JSON field names to check against
* @param getValue function to retrieve value from virtual network object
* @param <T>
* @return JsonObjectMatcher
*/
private static <T> JsonObjectMatcher matchesVnetEntity(T obj, List<String> jsonFieldNames,
BiFunction<T, String, String> getValue) {
return new JsonObjectMatcher(obj, jsonFieldNames, getValue);
}
/**
* Hamcrest matcher to check that a virtual network entity is represented properly in a JSON
* array of virtual network entities.
*/
public static class JsonArrayMatcher<T> extends TypeSafeMatcher<JsonArray> {
private final T vnetEntity;
private String reason = "";
private Function<T, String> getKey; // gets vnetEntity's key
private BiPredicate<T, JsonObject> checkKey; // check vnetEntity's key with JSON rep'n
private List<String> jsonFieldNames; // field/property names
private BiFunction<T, String, String> getValue; // get vnetEntity's value
public JsonArrayMatcher(T vnetEntityValue, Function<T, String> getKey1,
BiPredicate<T, JsonObject> checkKey1,
List<String> jsonFieldNames1,
BiFunction<T, String, String> getValue1) {
vnetEntity = vnetEntityValue;
getKey = getKey1;
checkKey = checkKey1;
jsonFieldNames = jsonFieldNames1;
getValue = getValue1;
}
@Override
public boolean matchesSafely(JsonArray json) {
boolean itemFound = false;
final int expectedAttributes = jsonFieldNames.size();
for (int jsonArrayIndex = 0; jsonArrayIndex < json.size();
jsonArrayIndex++) {
final JsonObject jsonHost = json.get(jsonArrayIndex).asObject();
if (jsonHost.names().size() < expectedAttributes) {
reason = "Found a virtual network with the wrong number of attributes";
return false;
}
if (checkKey != null && checkKey.test(vnetEntity, jsonHost)) {
itemFound = true;
assertThat(jsonHost, matchesVnetEntity(vnetEntity, jsonFieldNames, getValue));
}
}
if (!itemFound) {
reason = getKey.apply(vnetEntity) + " was not found";
return false;
}
return true;
}
@Override
public void describeTo(Description description) {
description.appendText(reason);
}
}
/**
* Array matcher for VirtualNetwork.
*/
public static class VnetJsonArrayMatcher extends JsonArrayMatcher<VirtualNetwork> {
public VnetJsonArrayMatcher(VirtualNetwork vnetIn) {
super(vnetIn,
vnet -> "Virtual network " + vnet.id().toString(),
(vnet, jsonObject) -> jsonObject.get(ID).asString().equals(vnet.id().toString()),
ImmutableList.of(ID, TENANT_ID),
(vnet, s) -> s.equals(ID) ? vnet.id().toString()
: s.equals(TENANT_ID) ? vnet.tenantId().toString()
: null
);
}
}
/**
* Factory to allocate a virtual network array matcher.
*
* @param vnet virtual network object we are looking for
* @return matcher
*/
private VnetJsonArrayMatcher hasVnet(VirtualNetwork vnet) {
return new VnetJsonArrayMatcher(vnet);
}
// Tests for Virtual Networks
/**
* Tests the result of the REST API GET when there are no virtual networks.
*/
@Test
public void testGetVirtualNetworksEmptyArray() {
expect(mockVnetAdminService.getTenantIds()).andReturn(ImmutableSet.of()).anyTimes();
replay(mockVnetAdminService);
expect(mockVnetService.getVirtualNetworks(tenantId4)).andReturn(ImmutableSet.of()).anyTimes();
replay(mockVnetService);
WebTarget wt = target();
String response = wt.path("vnets").request().get(String.class);
assertThat(response, is("{\"vnets\":[]}"));
verify(mockVnetService);
verify(mockVnetAdminService);
}
/**
* Tests the result of the REST API GET when virtual networks are defined.
*/
@Test
public void testGetVirtualNetworksArray() {
final Set<VirtualNetwork> vnetSet = ImmutableSet.of(vnet1, vnet2, vnet3, vnet4);
expect(mockVnetAdminService.getTenantIds()).andReturn(ImmutableSet.of(tenantId3)).anyTimes();
replay(mockVnetAdminService);
expect(mockVnetService.getVirtualNetworks(tenantId3)).andReturn(vnetSet).anyTimes();
replay(mockVnetService);
WebTarget wt = target();
String response = wt.path("vnets").request().get(String.class);
assertThat(response, containsString("{\"vnets\":["));
final JsonObject result = Json.parse(response).asObject();
assertThat(result, notNullValue());
assertThat(result.names(), hasSize(1));
assertThat(result.names().get(0), is("vnets"));
final JsonArray vnetJsonArray = result.get("vnets").asArray();
assertThat(vnetJsonArray, notNullValue());
assertEquals("Virtual networks array is not the correct size.",
vnetSet.size(), vnetJsonArray.size());
vnetSet.forEach(vnet -> assertThat(vnetJsonArray, hasVnet(vnet)));
verify(mockVnetService);
verify(mockVnetAdminService);
}
/**
* Tests the result of the REST API GET for virtual networks with tenant id.
*/
@Test
public void testGetVirtualNetworksByTenantId() {
final Set<VirtualNetwork> vnetSet = ImmutableSet.of(vnet1, vnet2, vnet3, vnet4);
expect(mockVnetAdminService.getTenantIds()).andReturn(ImmutableSet.of(tenantId3)).anyTimes();
replay(mockVnetAdminService);
expect(mockVnetService.getVirtualNetworks(tenantId3)).andReturn(vnetSet).anyTimes();
replay(mockVnetService);
WebTarget wt = target();
String response = wt.path("vnets/" + tenantId3.id()).request().get(String.class);
assertThat(response, containsString("{\"vnets\":["));
final JsonObject result = Json.parse(response).asObject();
assertThat(result, notNullValue());
assertThat(result.names(), hasSize(1));
assertThat(result.names().get(0), is("vnets"));
final JsonArray vnetJsonArray = result.get("vnets").asArray();
assertThat(vnetJsonArray, notNullValue());
assertEquals("Virtual networks array is not the correct size.",
vnetSet.size(), vnetJsonArray.size());
vnetSet.forEach(vnet -> assertThat(vnetJsonArray, hasVnet(vnet)));
verify(mockVnetService);
verify(mockVnetAdminService);
}
/**
* Tests the result of the REST API GET for virtual networks with tenant id.
*/
@Test
public void testGetVirtualNetworksByNonExistentTenantId() {
String tenantIdName = "NON_EXISTENT_TENANT_ID";
expect(mockVnetAdminService.getTenantIds()).andReturn(ImmutableSet.of(tenantId3)).anyTimes();
replay(mockVnetAdminService);
expect(mockVnetService.getVirtualNetworks(anyObject())).andReturn(ImmutableSet.of()).anyTimes();
replay(mockVnetService);
WebTarget wt = target();
try {
wt.path("vnets/" + tenantIdName)
.request()
.get(String.class);
fail("Get of a non-existent virtual network did not throw an exception");
} catch (NotFoundException ex) {
assertThat(ex.getMessage(), containsString("HTTP 404 Not Found"));
}
verify(mockVnetService);
verify(mockVnetAdminService);
}
/**
* Tests adding of new virtual network using POST via JSON stream.
*/
@Test
public void testPostVirtualNetwork() {
expect(mockVnetAdminService.createVirtualNetwork(tenantId2)).andReturn(vnet1);
expectLastCall();
replay(mockVnetAdminService);
WebTarget wt = target();
InputStream jsonStream = TenantWebResourceTest.class
.getResourceAsStream("post-tenant.json");
Response response = wt.path("vnets").request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.json(jsonStream));
assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
String location = response.getLocation().getPath();
assertThat(location, Matchers.startsWith("/vnets/" + vnet1.id().toString()));
verify(mockVnetAdminService);
}
/**
* Tests adding of a null virtual network using POST via JSON stream.
*/
@Test
public void testPostVirtualNetworkNullTenantId() {
replay(mockVnetAdminService);
WebTarget wt = target();
try {
wt.path("vnets")
.request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.json(null), String.class);
fail("POST of null virtual network did not throw an exception");
} catch (BadRequestException ex) {
assertThat(ex.getMessage(), containsString("HTTP 400 Bad Request"));
}
verify(mockVnetAdminService);
}
/**
* Tests removing a virtual network with DELETE request.
*/
@Test
public void testDeleteVirtualNetwork() {
mockVnetAdminService.removeVirtualNetwork(anyObject());
expectLastCall();
replay(mockVnetAdminService);
WebTarget wt = target()
.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
Response response = wt.path("vnets/" + "2")
.request(MediaType.APPLICATION_JSON_TYPE)
.delete();
assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
verify(mockVnetAdminService);
}
/**
* Tests that a DELETE of a non-existent virtual network throws an exception.
*/
@Test
public void testDeleteNetworkNonExistentNetworkId() {
expect(mockVnetAdminService.getTenantIds())
.andReturn(ImmutableSet.of())
.anyTimes();
expectLastCall();
replay(mockVnetAdminService);
WebTarget wt = target();
try {
wt.path("vnets/" + "NON_EXISTENT_NETWORK_ID")
.request()
.delete(String.class);
fail("Delete of a non-existent virtual network did not throw an exception");
} catch (NotFoundException ex) {
assertThat(ex.getMessage(), containsString("HTTP 404 Not Found"));
}
verify(mockVnetAdminService);
}
// Tests for Virtual Device
/**
* Tests the result of the REST API GET when there are no virtual devices.
*/
@Test
public void testGetVirtualDevicesEmptyArray() {
NetworkId networkId = networkId4;
expect(mockVnetService.getVirtualDevices(networkId)).andReturn(ImmutableSet.of()).anyTimes();
replay(mockVnetService);
WebTarget wt = target();
String location = "vnets/" + networkId.toString() + "/devices";
String response = wt.path(location).request().get(String.class);
assertThat(response, is("{\"devices\":[]}"));
verify(mockVnetService);
}
/**
* Tests the result of the REST API GET when virtual devices are defined.
*/
@Test
public void testGetVirtualDevicesArray() {
NetworkId networkId = networkId3;
vdevSet.add(vdev1);
vdevSet.add(vdev2);
expect(mockVnetService.getVirtualDevices(networkId)).andReturn(vdevSet).anyTimes();
replay(mockVnetService);
WebTarget wt = target();
String location = "vnets/" + networkId.toString() + "/devices";
String response = wt.path(location).request().get(String.class);
assertThat(response, containsString("{\"devices\":["));
final JsonObject result = Json.parse(response).asObject();
assertThat(result, notNullValue());
assertThat(result.names(), hasSize(1));
assertThat(result.names().get(0), is("devices"));
final JsonArray vnetJsonArray = result.get("devices").asArray();
assertThat(vnetJsonArray, notNullValue());
assertEquals("Virtual devices array is not the correct size.",
vdevSet.size(), vnetJsonArray.size());
vdevSet.forEach(vdev -> assertThat(vnetJsonArray, hasVdev(vdev)));
verify(mockVnetService);
}
/**
* Array matcher for VirtualDevice.
*/
public static class VdevJsonArrayMatcher extends JsonArrayMatcher<VirtualDevice> {
public VdevJsonArrayMatcher(VirtualDevice vdevIn) {
super(vdevIn,
vdev -> "Virtual device " + vdev.networkId().toString()
+ " " + vdev.id().toString(),
(vdev, jsonObject) -> jsonObject.get(ID).asString().equals(vdev.networkId().toString())
&& jsonObject.get(DEVICE_ID).asString().equals(vdev.id().toString()),
ImmutableList.of(ID, DEVICE_ID),
(vdev, s) -> s.equals(ID) ? vdev.networkId().toString()
: s.equals(DEVICE_ID) ? vdev.id().toString()
: null
);
}
}
/**
* Factory to allocate a virtual device array matcher.
*
* @param vdev virtual device object we are looking for
* @return matcher
*/
private VdevJsonArrayMatcher hasVdev(VirtualDevice vdev) {
return new VdevJsonArrayMatcher(vdev);
}
/**
* Tests adding of new virtual device using POST via JSON stream.
*/
@Test
public void testPostVirtualDevice() {
NetworkId networkId = networkId3;
DeviceId deviceId = devId2;
expect(mockVnetAdminService.createVirtualDevice(networkId, deviceId)).andReturn(vdev2);
expectLastCall();
replay(mockVnetAdminService);
WebTarget wt = target();
InputStream jsonStream = VirtualNetworkWebResourceTest.class
.getResourceAsStream("post-virtual-device.json");
String reqLocation = "vnets/" + networkId.toString() + "/devices";
Response response = wt.path(reqLocation).request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.json(jsonStream));
assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
String location = response.getLocation().getPath();
assertThat(location, Matchers.startsWith("/" + reqLocation + "/" + vdev2.id().toString()));
verify(mockVnetAdminService);
}
/**
* Tests adding of a null virtual device using POST via JSON stream.
*/
@Test
public void testPostVirtualDeviceNullJsonStream() {
NetworkId networkId = networkId3;
replay(mockVnetAdminService);
WebTarget wt = target();
try {
String reqLocation = "vnets/" + networkId.toString() + "/devices";
wt.path(reqLocation)
.request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.json(null), String.class);
fail("POST of null virtual device did not throw an exception");
} catch (BadRequestException ex) {
assertThat(ex.getMessage(), containsString("HTTP 400 Bad Request"));
}
verify(mockVnetAdminService);
}
/**
* Tests removing a virtual device with DELETE request.
*/
@Test
public void testDeleteVirtualDevice() {
NetworkId networkId = networkId3;
DeviceId deviceId = devId2;
mockVnetAdminService.removeVirtualDevice(networkId, deviceId);
expectLastCall();
replay(mockVnetAdminService);
WebTarget wt = target()
.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
String reqLocation = "vnets/" + networkId.toString() + "/devices/" + deviceId.toString();
Response response = wt.path(reqLocation)
.request(MediaType.APPLICATION_JSON_TYPE)
.delete();
assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
verify(mockVnetAdminService);
}
// Tests for Virtual Ports
/**
* Tests the result of the REST API GET when there are no virtual ports.
*/
@Test
public void testGetVirtualPortsEmptyArray() {
NetworkId networkId = networkId4;
DeviceId deviceId = devId2;
expect(mockVnetService.getVirtualPorts(networkId, deviceId))
.andReturn(ImmutableSet.of()).anyTimes();
replay(mockVnetService);
WebTarget wt = target();
String location = "vnets/" + networkId.toString()
+ "/devices/" + deviceId.toString() + "/ports";
String response = wt.path(location).request().get(String.class);
assertThat(response, is("{\"ports\":[]}"));
verify(mockVnetService);
}
/**
* Tests the result of the REST API GET when virtual ports are defined.
*/
@Test
public void testGetVirtualPortsArray() {
NetworkId networkId = networkId3;
DeviceId deviceId = dev22.id();
vportSet.add(vport23);
vportSet.add(vport22);
expect(mockVnetService.getVirtualPorts(networkId, deviceId)).andReturn(vportSet).anyTimes();
replay(mockVnetService);
WebTarget wt = target();
String location = "vnets/" + networkId.toString()
+ "/devices/" + deviceId.toString() + "/ports";
String response = wt.path(location).request().get(String.class);
assertThat(response, containsString("{\"ports\":["));
final JsonObject result = Json.parse(response).asObject();
assertThat(result, notNullValue());
assertThat(result.names(), hasSize(1));
assertThat(result.names().get(0), is("ports"));
final JsonArray vnetJsonArray = result.get("ports").asArray();
assertThat(vnetJsonArray, notNullValue());
assertEquals("Virtual ports array is not the correct size.",
vportSet.size(), vnetJsonArray.size());
vportSet.forEach(vport -> assertThat(vnetJsonArray, hasVport(vport)));
verify(mockVnetService);
}
/**
* Array matcher for VirtualPort.
*/
public static class VportJsonArrayMatcher extends JsonArrayMatcher<VirtualPort> {
public VportJsonArrayMatcher(VirtualPort vportIn) {
super(vportIn,
vport -> "Virtual port " + vport.networkId().toString() + " "
+ vport.element().id().toString() + " " + vport.number().toString(),
(vport, jsonObject) -> jsonObject.get(ID).asString().equals(vport.networkId().toString())
&& jsonObject.get(PORT_NUM).asString().equals(vport.number().toString())
&& jsonObject.get(DEVICE_ID).asString().equals(vport.element().id().toString()),
ImmutableList.of(ID, DEVICE_ID, PORT_NUM, PHYS_DEVICE_ID, PHYS_PORT_NUM),
(vport, s) -> s.equals(ID) ? vport.networkId().toString()
: s.equals(DEVICE_ID) ? vport.element().id().toString()
: s.equals(PORT_NUM) ? vport.number().toString()
: s.equals(PHYS_DEVICE_ID) ? vport.realizedBy().element().id().toString()
: s.equals(PHYS_PORT_NUM) ? vport.realizedBy().number().toString()
: null
);
}
}
/**
* Factory to allocate a virtual port array matcher.
*
* @param vport virtual port object we are looking for
* @return matcher
*/
private VportJsonArrayMatcher hasVport(VirtualPort vport) {
return new VportJsonArrayMatcher(vport);
}
/**
* Tests adding of new virtual port using POST via JSON stream.
*/
@Test
public void testPostVirtualPort() {
NetworkId networkId = networkId3;
DeviceId deviceId = devId22;
DefaultAnnotations annotations = DefaultAnnotations.builder().build();
Device physDevice = new DefaultDevice(null, DeviceId.deviceId("dev1"),
null, null, null, null, null, null, annotations);
Port port1 = new DefaultPort(physDevice, portNumber(1), true);
expect(mockVnetAdminService.createVirtualPort(networkId, deviceId, portNumber(22), port1))
.andReturn(vport22);
replay(mockVnetAdminService);
WebTarget wt = target();
InputStream jsonStream = VirtualNetworkWebResourceTest.class
.getResourceAsStream("post-virtual-port.json");
String reqLocation = "vnets/" + networkId.toString()
+ "/devices/" + deviceId.toString() + "/ports";
Response response = wt.path(reqLocation).request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.json(jsonStream));
assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
verify(mockVnetAdminService);
}
/**
* Tests adding of a null virtual port using POST via JSON stream.
*/
@Test
public void testPostVirtualPortNullJsonStream() {
NetworkId networkId = networkId3;
DeviceId deviceId = devId2;
replay(mockVnetAdminService);
WebTarget wt = target();
try {
String reqLocation = "vnets/" + networkId.toString()
+ "/devices/" + deviceId.toString() + "/ports";
wt.path(reqLocation)
.request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.json(null), String.class);
fail("POST of null virtual port did not throw an exception");
} catch (BadRequestException ex) {
assertThat(ex.getMessage(), containsString("HTTP 400 Bad Request"));
}
verify(mockVnetAdminService);
}
/**
* Tests removing a virtual port with DELETE request.
*/
@Test
public void testDeleteVirtualPort() {
NetworkId networkId = networkId3;
DeviceId deviceId = devId2;
PortNumber portNum = portNumber(2);
mockVnetAdminService.removeVirtualPort(networkId, deviceId, portNum);
expectLastCall();
replay(mockVnetAdminService);
WebTarget wt = target()
.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
String reqLocation = "vnets/" + networkId.toString()
+ "/devices/" + deviceId.toString() + "/ports/" + portNum.toLong();
Response response = wt.path(reqLocation)
.request(MediaType.APPLICATION_JSON_TYPE)
.delete();
assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
verify(mockVnetAdminService);
}
// Tests for Virtual Links
/**
* Tests the result of the REST API GET when there are no virtual links.
*/
@Test
public void testGetVirtualLinksEmptyArray() {
NetworkId networkId = networkId4;
expect(mockVnetService.getVirtualLinks(networkId)).andReturn(ImmutableSet.of()).anyTimes();
replay(mockVnetService);
WebTarget wt = target();
String location = "vnets/" + networkId.toString() + "/links";
String response = wt.path(location).request().get(String.class);
assertThat(response, is("{\"links\":[]}"));
verify(mockVnetService);
}
/**
* Tests the result of the REST API GET when virtual links are defined.
*/
@Test
public void testGetVirtualLinksArray() {
NetworkId networkId = networkId3;
final Set<VirtualLink> vlinkSet = ImmutableSet.of(vlink1, vlink2);
expect(mockVnetService.getVirtualLinks(networkId)).andReturn(vlinkSet).anyTimes();
replay(mockVnetService);
WebTarget wt = target();
String location = "vnets/" + networkId.toString() + "/links";
String response = wt.path(location).request().get(String.class);
assertThat(response, containsString("{\"links\":["));
final JsonObject result = Json.parse(response).asObject();
assertThat(result, notNullValue());
assertThat(result.names(), hasSize(1));
assertThat(result.names().get(0), is("links"));
final JsonArray vnetJsonArray = result.get("links").asArray();
assertThat(vnetJsonArray, notNullValue());
assertEquals("Virtual links array is not the correct size.",
vlinkSet.size(), vnetJsonArray.size());
vlinkSet.forEach(vlink -> assertThat(vnetJsonArray, hasVlink(vlink)));
verify(mockVnetService);
}
/**
* Hamcrest matcher to check that a virtual link representation in JSON matches
* the actual virtual link.
*/
public static class VirtualLinkJsonMatcher extends LinksResourceTest.LinkJsonMatcher {
private final VirtualLink vlink;
private String reason = "";
public VirtualLinkJsonMatcher(VirtualLink vlinkValue) {
super(vlinkValue);
vlink = vlinkValue;
}
@Override
public boolean matchesSafely(JsonObject jsonLink) {
if (!super.matchesSafely(jsonLink)) {
return false;
}
// check NetworkId
String jsonNetworkId = jsonLink.get(ID).asString();
String networkId = vlink.networkId().toString();
if (!jsonNetworkId.equals(networkId)) {
reason = ID + " was " + jsonNetworkId;
return false;
}
// check TunnelId
String jsonTunnelId = jsonLink.get(TUNNEL_ID).asString();
if (jsonTunnelId != null && vlink instanceof DefaultVirtualLink) {
String tunnelId = ((DefaultVirtualLink) vlink).tunnelId().toString();
if (!jsonTunnelId.equals(tunnelId)) {
reason = TUNNEL_ID + " was " + jsonTunnelId;
return false;
}
}
return true;
}
@Override
public void describeTo(Description description) {
description.appendText(reason);
}
}
/**
* Factory to allocate a virtual link matcher.
*
* @param vlink virtual link object we are looking for
* @return matcher
*/
private static VirtualLinkJsonMatcher matchesVirtualLink(VirtualLink vlink) {
return new VirtualLinkJsonMatcher(vlink);
}
/**
* Hamcrest matcher to check that a virtual link is represented properly in a JSON
* array of links.
*/
private static class VirtualLinkJsonArrayMatcher extends TypeSafeMatcher<JsonArray> {
private final VirtualLink vlink;
private String reason = "";
public VirtualLinkJsonArrayMatcher(VirtualLink vlinkValue) {
vlink = vlinkValue;
}
@Override
public boolean matchesSafely(JsonArray json) {
final int expectedAttributes = 2;
for (int jsonLinkIndex = 0; jsonLinkIndex < json.size();
jsonLinkIndex++) {
JsonObject jsonLink = json.get(jsonLinkIndex).asObject();
if (matchesVirtualLink(vlink).matchesSafely(jsonLink)) {
return true;
}
}
return false;
}
@Override
public void describeTo(Description description) {
description.appendText(reason);
}
}
/**
* Factory to allocate a virtual link array matcher.
*
* @param vlink virtual link object we are looking for
* @return matcher
*/
private VirtualLinkJsonArrayMatcher hasVlink(VirtualLink vlink) {
return new VirtualLinkJsonArrayMatcher(vlink);
}
/**
* Tests adding of new virtual link using POST via JSON stream.
*/
@Test
public void testPostVirtualLink() {
NetworkId networkId = networkId3;
expect(mockVnetAdminService.createVirtualLink(networkId, cp22, cp11, tunnelId))
.andReturn(vlink1);
replay(mockVnetAdminService);
WebTarget wt = target();
InputStream jsonStream = VirtualNetworkWebResourceTest.class
.getResourceAsStream("post-virtual-link.json");
String reqLocation = "vnets/" + networkId.toString() + "/links";
Response response = wt.path(reqLocation).request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.json(jsonStream));
assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
String location = response.getLocation().getPath();
assertThat(location, Matchers.startsWith("/" + reqLocation));
verify(mockVnetAdminService);
}
/**
* Tests adding of a null virtual link using POST via JSON stream.
*/
@Test
public void testPostVirtualLinkNullJsonStream() {
NetworkId networkId = networkId3;
replay(mockVnetAdminService);
WebTarget wt = target();
try {
String reqLocation = "vnets/" + networkId.toString() + "/links";
wt.path(reqLocation)
.request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.json(null), String.class);
fail("POST of null virtual link did not throw an exception");
} catch (BadRequestException ex) {
assertThat(ex.getMessage(), containsString("HTTP 400 Bad Request"));
}
verify(mockVnetAdminService);
}
/**
* Tests removing a virtual link with DELETE request.
*/
@Test
public void testDeleteVirtualLink() {
NetworkId networkId = networkId3;
mockVnetAdminService.removeVirtualLink(networkId, cp22, cp11);
expectLastCall();
replay(mockVnetAdminService);
WebTarget wt = target()
.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
InputStream jsonStream = VirtualNetworkWebResourceTest.class
.getResourceAsStream("post-virtual-link.json");
String reqLocation = "vnets/" + networkId.toString() + "/links";
Response response = wt.path(reqLocation).request().method("DELETE", Entity.json(jsonStream));
assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
verify(mockVnetAdminService);
}
}