REST API's for tenants, virtual networks, virtual devices ad virtual ports.
Change-Id: I80abe14a083fce3dc6246118af8874028109388f
REST API's for tenants, virtual networks, virtual devices ad virtual ports.
Change-Id: Ib6c3d69d396e57822bae23f5bf3101c8b9c0b95c
diff --git a/web/api/src/test/java/org/onosproject/rest/resources/TenantWebResourceTest.java b/web/api/src/test/java/org/onosproject/rest/resources/TenantWebResourceTest.java
new file mode 100644
index 0000000..03b6e4e
--- /dev/null
+++ b/web/api/src/test/java/org/onosproject/rest/resources/TenantWebResourceTest.java
@@ -0,0 +1,342 @@
+/*
+ * Copyright 2016 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.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.virtual.TenantId;
+import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
+
+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 static org.easymock.EasyMock.*;
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+/**
+ * Unit tests for tenant REST APIs.
+ */
+public class TenantWebResourceTest extends ResourceTest {
+
+ private final VirtualNetworkAdminService mockVnetAdminService = createMock(VirtualNetworkAdminService.class);
+
+ final HashSet<TenantId> tenantIdSet = new HashSet<>();
+
+ private static final String ID = "id";
+
+ 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");
+
+ /**
+ * Sets up the global values for all the tests.
+ */
+ @Before
+ public void setUpTest() {
+ // Register the services needed for the test
+ CodecManager codecService = new CodecManager();
+ codecService.activate();
+ ServiceDirectory testDirectory =
+ new TestServiceDirectory()
+ .add(VirtualNetworkAdminService.class, mockVnetAdminService)
+ .add(CodecService.class, codecService);
+
+ BaseResource.setServiceDirectory(testDirectory);
+ }
+
+ /**
+ * Hamcrest matcher to check that a tenant id representation in JSON matches
+ * the actual tenant id.
+ */
+ public static class TenantIdJsonMatcher extends TypeSafeMatcher<JsonObject> {
+ private final TenantId tenantId;
+ private String reason = "";
+
+ public TenantIdJsonMatcher(TenantId tenantIdValue) {
+ tenantId = tenantIdValue;
+ }
+
+ @Override
+ public boolean matchesSafely(JsonObject jsonHost) {
+ // Check the tenant id
+ final String jsonId = jsonHost.get(ID).asString();
+ if (!jsonId.equals(tenantId.id())) {
+ reason = ID + " " + tenantId.id();
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText(reason);
+ }
+ }
+
+ /**
+ * Factory to allocate a tenant id array matcher.
+ *
+ * @param tenantId tenant id object we are looking for
+ * @return matcher
+ */
+ private static TenantIdJsonMatcher matchesTenantId(TenantId tenantId) {
+ return new TenantIdJsonMatcher(tenantId);
+ }
+
+ /**
+ * Hamcrest matcher to check that a tenant id is represented properly in a JSON
+ * array of tenant ids.
+ */
+ public static class TenantIdJsonArrayMatcher extends TypeSafeMatcher<JsonArray> {
+ private final TenantId tenantId;
+ private String reason = "";
+
+ public TenantIdJsonArrayMatcher(TenantId tenantIdValue) {
+ tenantId = tenantIdValue;
+ }
+
+ @Override
+ public boolean matchesSafely(JsonArray json) {
+ boolean tenantIdFound = false;
+ final int expectedAttributes = 1;
+ for (int tenantIdIndex = 0; tenantIdIndex < json.size();
+ tenantIdIndex++) {
+
+ final JsonObject jsonHost = json.get(tenantIdIndex).asObject();
+
+ // Only 1 attribute - ID.
+ if (jsonHost.names().size() < expectedAttributes) {
+ reason = "Found a tenant id with the wrong number of attributes";
+ return false;
+ }
+
+ final String jsonDeviceKeyId = jsonHost.get(ID).asString();
+ if (jsonDeviceKeyId.equals(tenantId.id())) {
+ tenantIdFound = true;
+
+ // We found the correct tenant id, check the tenant id attribute values
+ assertThat(jsonHost, matchesTenantId(tenantId));
+ }
+ }
+ if (!tenantIdFound) {
+ reason = "Tenant id " + tenantId.id() + " was not found";
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText(reason);
+ }
+ }
+
+ /**
+ * Factory to allocate a tenant id array matcher.
+ *
+ * @param tenantId tenant id object we are looking for
+ * @return matcher
+ */
+ private static TenantIdJsonArrayMatcher hasTenantId(TenantId tenantId) {
+ return new TenantIdJsonArrayMatcher(tenantId);
+ }
+
+ /**
+ * Tests the result of the REST API GET when there are no tenant ids.
+ */
+ @Test
+ public void testGetTenantsEmptyArray() {
+ expect(mockVnetAdminService.getTenantIds()).andReturn(ImmutableSet.of()).anyTimes();
+ replay(mockVnetAdminService);
+
+ WebTarget wt = target();
+ String response = wt.path("tenants").request().get(String.class);
+ assertThat(response, is("{\"tenants\":[]}"));
+
+ verify(mockVnetAdminService);
+ }
+
+ /**
+ * Tests the result of the REST API GET when tenant ids are defined.
+ */
+ @Test
+ public void testGetTenantIdsArray() {
+ tenantIdSet.add(tenantId1);
+ tenantIdSet.add(tenantId2);
+ tenantIdSet.add(tenantId3);
+ tenantIdSet.add(tenantId4);
+ expect(mockVnetAdminService.getTenantIds()).andReturn(tenantIdSet).anyTimes();
+ replay(mockVnetAdminService);
+
+ WebTarget wt = target();
+ String response = wt.path("tenants").request().get(String.class);
+ assertThat(response, containsString("{\"tenants\":["));
+
+ final JsonObject result = Json.parse(response).asObject();
+ assertThat(result, notNullValue());
+
+ assertThat(result.names(), hasSize(1));
+ assertThat(result.names().get(0), is("tenants"));
+
+ final JsonArray tenantIds = result.get("tenants").asArray();
+ assertThat(tenantIds, notNullValue());
+ assertEquals("Device keys array is not the correct size.",
+ tenantIdSet.size(), tenantIds.size());
+
+ tenantIdSet.forEach(tenantId -> assertThat(tenantIds, hasTenantId(tenantId)));
+
+ verify(mockVnetAdminService);
+ }
+
+ /**
+ * Tests adding of new tenant id using POST via JSON stream.
+ */
+ @Test
+ public void testPost() {
+ mockVnetAdminService.registerTenantId(anyObject());
+ tenantIdSet.add(tenantId2);
+ expect(mockVnetAdminService.getTenantIds()).andReturn(tenantIdSet).anyTimes();
+ expectLastCall();
+
+ replay(mockVnetAdminService);
+
+ WebTarget wt = target();
+ InputStream jsonStream = TenantWebResourceTest.class
+ .getResourceAsStream("post-tenant.json");
+
+ Response response = wt.path("tenants").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("/tenants/" + tenantId2));
+
+ verify(mockVnetAdminService);
+ }
+
+ /**
+ * Tests adding of a null tenant id using POST via JSON stream.
+ */
+ @Test
+ public void testPostNullTenantId() {
+
+ replay(mockVnetAdminService);
+
+ WebTarget wt = target();
+ try {
+ String response = wt.path("tenants")
+ .request(MediaType.APPLICATION_JSON_TYPE)
+ .post(Entity.json(null), String.class);
+ fail("POST of null tenant id did not throw an exception");
+ } catch (BadRequestException ex) {
+ assertThat(ex.getMessage(), containsString("HTTP 400 Bad Request"));
+ }
+
+ verify(mockVnetAdminService);
+ }
+
+ /**
+ * Tests removing a tenant id with DELETE request.
+ */
+ @Test
+ public void testDelete() {
+ expect(mockVnetAdminService.getTenantIds())
+ .andReturn(ImmutableSet.of(tenantId2)).anyTimes();
+ mockVnetAdminService.unregisterTenantId(anyObject());
+ expectLastCall();
+ replay(mockVnetAdminService);
+
+ WebTarget wt = target()
+ .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
+ Response response = wt.path("tenants/" + tenantId2)
+ .request(MediaType.APPLICATION_JSON_TYPE)
+ .delete();
+
+ assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
+
+ verify(mockVnetAdminService);
+ }
+
+ /**
+ * Tests removing a tenant id with DELETE request via JSON stream.
+ */
+ @Test
+ public void testDeleteViaJson() {
+ mockVnetAdminService.unregisterTenantId(anyObject());
+ expectLastCall();
+ replay(mockVnetAdminService);
+
+ WebTarget wt = target()
+ .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
+ InputStream jsonStream = TenantWebResourceTest.class
+ .getResourceAsStream("post-tenant.json");
+ Response response = wt.request().method("DELETE", Entity.json(jsonStream));
+
+// assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
+
+// verify(mockVnetAdminService);
+ }
+
+ /**
+ * Tests that a DELETE of a non-existent tenant id throws an exception.
+ */
+ @Test
+ public void testDeleteNonExistentDeviceKey() {
+ expect(mockVnetAdminService.getTenantIds())
+ .andReturn(ImmutableSet.of())
+ .anyTimes();
+ expectLastCall();
+
+ replay(mockVnetAdminService);
+
+ WebTarget wt = target();
+
+ try {
+ wt.path("tenants/" + "NON_EXISTENT_TENANT_ID")
+ .request()
+ .delete(String.class);
+ fail("Delete of a non-existent tenant did not throw an exception");
+ } catch (NotFoundException ex) {
+ assertThat(ex.getMessage(), containsString("HTTP 404 Not Found"));
+ }
+
+ verify(mockVnetAdminService);
+ }
+}
diff --git a/web/api/src/test/java/org/onosproject/rest/resources/VirtualNetworkWebResourceTest.java b/web/api/src/test/java/org/onosproject/rest/resources/VirtualNetworkWebResourceTest.java
new file mode 100644
index 0000000..9581e3a
--- /dev/null
+++ b/web/api/src/test/java/org/onosproject/rest/resources/VirtualNetworkWebResourceTest.java
@@ -0,0 +1,760 @@
+/*
+ * Copyright 2016 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.virtual.DefaultVirtualDevice;
+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.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.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.function.BiFunction;
+import java.util.function.BiPredicate;
+import java.util.function.Function;
+
+import static org.easymock.EasyMock.*;
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+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<VirtualNetwork> vnetSet = 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 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 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);
+
+ /**
+ * 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) -> {
+ return jsonObject.get(ID).asString().equals(vnet.id().toString()); },
+ ImmutableList.of(ID, TENANT_ID),
+ (vnet, s) -> {
+ return 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() {
+ expect(mockVnetAdminService.getTenantIds()).andReturn(ImmutableSet.of(tenantId3)).anyTimes();
+ replay(mockVnetAdminService);
+ vnetSet.add(vnet1);
+ vnetSet.add(vnet2);
+ vnetSet.add(vnet3);
+ vnetSet.add(vnet4);
+ 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 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 {
+ String response = 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) -> {
+ return jsonObject.get(ID).asString().equals(vdev.networkId().toString())
+ && jsonObject.get(DEVICE_ID).asString().equals(vdev.id().toString()); },
+ ImmutableList.of(ID, DEVICE_ID),
+ (vdev, s) -> {
+ return 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";
+ String response = 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) -> {
+ return 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) -> {
+ return 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";
+ String response = 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);
+ }
+
+ // TODO Tests for Virtual Links
+}
diff --git a/web/api/src/test/resources/org/onosproject/rest/resources/post-tenant.json b/web/api/src/test/resources/org/onosproject/rest/resources/post-tenant.json
new file mode 100644
index 0000000..407f9a2
--- /dev/null
+++ b/web/api/src/test/resources/org/onosproject/rest/resources/post-tenant.json
@@ -0,0 +1,3 @@
+{
+ "id": "TenantId2"
+}
diff --git a/web/api/src/test/resources/org/onosproject/rest/resources/post-virtual-device.json b/web/api/src/test/resources/org/onosproject/rest/resources/post-virtual-device.json
new file mode 100644
index 0000000..fbd129c
--- /dev/null
+++ b/web/api/src/test/resources/org/onosproject/rest/resources/post-virtual-device.json
@@ -0,0 +1,4 @@
+{
+ "networkId": "3",
+ "deviceId": "devId2"
+}
diff --git a/web/api/src/test/resources/org/onosproject/rest/resources/post-virtual-port.json b/web/api/src/test/resources/org/onosproject/rest/resources/post-virtual-port.json
new file mode 100644
index 0000000..1d60842
--- /dev/null
+++ b/web/api/src/test/resources/org/onosproject/rest/resources/post-virtual-port.json
@@ -0,0 +1,7 @@
+{
+ "networkId": "3",
+ "deviceId": "dev22",
+ "portNum": "22",
+ "physDeviceId": "dev1",
+ "physPortNum": "1"
+}