Detangling incubator: virtual nets, tunnels, resource labels, oh my
- virtual networking moved to /apps/virtual; with CLI & REST API
- tunnels and labels moved to /apps/tunnel; with CLI & REST API; UI disabled for now
- protobuf/models moved to /core/protobuf/models
- defunct grpc/rpc registry stuff left under /graveyard
- compile dependencies on /incubator moved to respective modules for compilation
- run-time dependencies will need to be re-tested for dependent apps
- /graveyard will be removed in not-too-distant future
Change-Id: I0a0b995c635487edcf95a352f50dd162186b0b39
diff --git a/apps/virtual/app/src/test/java/org/onosproject/incubator/net/virtual/rest/TenantWebResourceTest.java b/apps/virtual/app/src/test/java/org/onosproject/incubator/net/virtual/rest/TenantWebResourceTest.java
new file mode 100644
index 0000000..def32c5
--- /dev/null
+++ b/apps/virtual/app/src/test/java/org/onosproject/incubator/net/virtual/rest/TenantWebResourceTest.java
@@ -0,0 +1,334 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * 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.incubator.net.virtual.rest;
+
+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.Ignore;
+import org.junit.Test;
+import org.onlab.osgi.ServiceDirectory;
+import org.onlab.osgi.TestServiceDirectory;
+import org.onosproject.codec.CodecService;
+import org.onosproject.codec.impl.CodecManager;
+import org.onosproject.net.TenantId;
+import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
+import org.onosproject.rest.resources.ResourceTest;
+
+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.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;
+
+/**
+ * Unit tests for tenant REST APIs.
+ */
+@Ignore
+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);
+
+ 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_NO_CONTENT));
+
+ 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);
+ }
+}