blob: def32c543046cb04bf26da99702de74928797e6c [file] [log] [blame]
Claudine Chiufb8b8162016-04-01 23:50:51 +00001/*
Thomas Vachuska52f2cd12018-11-08 21:20:04 -08002 * Copyright 2018-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
Thomas Vachuska52f2cd12018-11-08 21:20:04 -080017package org.onosproject.incubator.net.virtual.rest;
Claudine Chiufb8b8162016-04-01 23:50:51 +000018
19import com.eclipsesource.json.Json;
20import com.eclipsesource.json.JsonArray;
21import com.eclipsesource.json.JsonObject;
22import com.google.common.collect.ImmutableSet;
23import org.glassfish.jersey.client.ClientProperties;
24import org.hamcrest.Description;
25import org.hamcrest.Matchers;
26import org.hamcrest.TypeSafeMatcher;
27import org.junit.Before;
Thomas Vachuska52f2cd12018-11-08 21:20:04 -080028import org.junit.Ignore;
Claudine Chiufb8b8162016-04-01 23:50:51 +000029import org.junit.Test;
30import org.onlab.osgi.ServiceDirectory;
31import org.onlab.osgi.TestServiceDirectory;
Claudine Chiufb8b8162016-04-01 23:50:51 +000032import org.onosproject.codec.CodecService;
33import org.onosproject.codec.impl.CodecManager;
Thomas Vachuska52f2cd12018-11-08 21:20:04 -080034import org.onosproject.net.TenantId;
Claudine Chiufb8b8162016-04-01 23:50:51 +000035import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
Thomas Vachuska52f2cd12018-11-08 21:20:04 -080036import org.onosproject.rest.resources.ResourceTest;
Claudine Chiufb8b8162016-04-01 23:50:51 +000037
38import javax.ws.rs.BadRequestException;
39import javax.ws.rs.NotFoundException;
40import javax.ws.rs.client.Entity;
41import javax.ws.rs.client.WebTarget;
42import javax.ws.rs.core.MediaType;
43import javax.ws.rs.core.Response;
44import java.io.InputStream;
45import java.net.HttpURLConnection;
46import java.util.HashSet;
47
Ray Milkey094a1352018-01-22 14:03:54 -080048import static org.easymock.EasyMock.anyObject;
49import static org.easymock.EasyMock.createMock;
50import static org.easymock.EasyMock.expect;
51import static org.easymock.EasyMock.expectLastCall;
52import static org.easymock.EasyMock.replay;
53import static org.easymock.EasyMock.verify;
54import static org.hamcrest.Matchers.containsString;
55import static org.hamcrest.Matchers.hasSize;
56import static org.hamcrest.Matchers.is;
57import static org.hamcrest.Matchers.notNullValue;
58import static org.junit.Assert.assertEquals;
59import static org.junit.Assert.assertThat;
60import static org.junit.Assert.fail;
Claudine Chiufb8b8162016-04-01 23:50:51 +000061
62/**
63 * Unit tests for tenant REST APIs.
64 */
Thomas Vachuska52f2cd12018-11-08 21:20:04 -080065@Ignore
Claudine Chiufb8b8162016-04-01 23:50:51 +000066public class TenantWebResourceTest extends ResourceTest {
67
68 private final VirtualNetworkAdminService mockVnetAdminService = createMock(VirtualNetworkAdminService.class);
69
70 final HashSet<TenantId> tenantIdSet = new HashSet<>();
71
72 private static final String ID = "id";
73
74 private final TenantId tenantId1 = TenantId.tenantId("TenantId1");
75 private final TenantId tenantId2 = TenantId.tenantId("TenantId2");
76 private final TenantId tenantId3 = TenantId.tenantId("TenantId3");
77 private final TenantId tenantId4 = TenantId.tenantId("TenantId4");
78
79 /**
80 * Sets up the global values for all the tests.
81 */
82 @Before
83 public void setUpTest() {
84 // Register the services needed for the test
85 CodecManager codecService = new CodecManager();
86 codecService.activate();
87 ServiceDirectory testDirectory =
88 new TestServiceDirectory()
89 .add(VirtualNetworkAdminService.class, mockVnetAdminService)
90 .add(CodecService.class, codecService);
91
Ray Milkey094a1352018-01-22 14:03:54 -080092 setServiceDirectory(testDirectory);
Claudine Chiufb8b8162016-04-01 23:50:51 +000093 }
94
95 /**
96 * Hamcrest matcher to check that a tenant id representation in JSON matches
97 * the actual tenant id.
98 */
99 public static class TenantIdJsonMatcher extends TypeSafeMatcher<JsonObject> {
100 private final TenantId tenantId;
101 private String reason = "";
102
103 public TenantIdJsonMatcher(TenantId tenantIdValue) {
104 tenantId = tenantIdValue;
105 }
106
107 @Override
108 public boolean matchesSafely(JsonObject jsonHost) {
109 // Check the tenant id
110 final String jsonId = jsonHost.get(ID).asString();
111 if (!jsonId.equals(tenantId.id())) {
112 reason = ID + " " + tenantId.id();
113 return false;
114 }
115
116 return true;
117 }
118
119 @Override
120 public void describeTo(Description description) {
121 description.appendText(reason);
122 }
123 }
124
125 /**
126 * Factory to allocate a tenant id array matcher.
127 *
128 * @param tenantId tenant id object we are looking for
129 * @return matcher
130 */
131 private static TenantIdJsonMatcher matchesTenantId(TenantId tenantId) {
132 return new TenantIdJsonMatcher(tenantId);
133 }
134
135 /**
136 * Hamcrest matcher to check that a tenant id is represented properly in a JSON
137 * array of tenant ids.
138 */
139 public static class TenantIdJsonArrayMatcher extends TypeSafeMatcher<JsonArray> {
140 private final TenantId tenantId;
141 private String reason = "";
142
143 public TenantIdJsonArrayMatcher(TenantId tenantIdValue) {
144 tenantId = tenantIdValue;
145 }
146
147 @Override
148 public boolean matchesSafely(JsonArray json) {
149 boolean tenantIdFound = false;
150 final int expectedAttributes = 1;
151 for (int tenantIdIndex = 0; tenantIdIndex < json.size();
152 tenantIdIndex++) {
153
154 final JsonObject jsonHost = json.get(tenantIdIndex).asObject();
155
156 // Only 1 attribute - ID.
157 if (jsonHost.names().size() < expectedAttributes) {
158 reason = "Found a tenant id with the wrong number of attributes";
159 return false;
160 }
161
162 final String jsonDeviceKeyId = jsonHost.get(ID).asString();
163 if (jsonDeviceKeyId.equals(tenantId.id())) {
164 tenantIdFound = true;
165
166 // We found the correct tenant id, check the tenant id attribute values
167 assertThat(jsonHost, matchesTenantId(tenantId));
168 }
169 }
170 if (!tenantIdFound) {
171 reason = "Tenant id " + tenantId.id() + " was not found";
172 return false;
173 }
174 return true;
175 }
176
177 @Override
178 public void describeTo(Description description) {
179 description.appendText(reason);
180 }
181 }
182
183 /**
184 * Factory to allocate a tenant id array matcher.
185 *
186 * @param tenantId tenant id object we are looking for
187 * @return matcher
188 */
189 private static TenantIdJsonArrayMatcher hasTenantId(TenantId tenantId) {
190 return new TenantIdJsonArrayMatcher(tenantId);
191 }
192
193 /**
194 * Tests the result of the REST API GET when there are no tenant ids.
195 */
196 @Test
197 public void testGetTenantsEmptyArray() {
198 expect(mockVnetAdminService.getTenantIds()).andReturn(ImmutableSet.of()).anyTimes();
199 replay(mockVnetAdminService);
200
201 WebTarget wt = target();
202 String response = wt.path("tenants").request().get(String.class);
203 assertThat(response, is("{\"tenants\":[]}"));
204
205 verify(mockVnetAdminService);
206 }
207
208 /**
209 * Tests the result of the REST API GET when tenant ids are defined.
210 */
211 @Test
212 public void testGetTenantIdsArray() {
213 tenantIdSet.add(tenantId1);
214 tenantIdSet.add(tenantId2);
215 tenantIdSet.add(tenantId3);
216 tenantIdSet.add(tenantId4);
217 expect(mockVnetAdminService.getTenantIds()).andReturn(tenantIdSet).anyTimes();
218 replay(mockVnetAdminService);
219
220 WebTarget wt = target();
221 String response = wt.path("tenants").request().get(String.class);
222 assertThat(response, containsString("{\"tenants\":["));
223
224 final JsonObject result = Json.parse(response).asObject();
225 assertThat(result, notNullValue());
226
227 assertThat(result.names(), hasSize(1));
228 assertThat(result.names().get(0), is("tenants"));
229
230 final JsonArray tenantIds = result.get("tenants").asArray();
231 assertThat(tenantIds, notNullValue());
232 assertEquals("Device keys array is not the correct size.",
233 tenantIdSet.size(), tenantIds.size());
234
235 tenantIdSet.forEach(tenantId -> assertThat(tenantIds, hasTenantId(tenantId)));
236
237 verify(mockVnetAdminService);
238 }
239
240 /**
241 * Tests adding of new tenant id using POST via JSON stream.
242 */
243 @Test
244 public void testPost() {
245 mockVnetAdminService.registerTenantId(anyObject());
246 tenantIdSet.add(tenantId2);
247 expect(mockVnetAdminService.getTenantIds()).andReturn(tenantIdSet).anyTimes();
248 expectLastCall();
249
250 replay(mockVnetAdminService);
251
252 WebTarget wt = target();
253 InputStream jsonStream = TenantWebResourceTest.class
254 .getResourceAsStream("post-tenant.json");
255
256 Response response = wt.path("tenants").request(MediaType.APPLICATION_JSON_TYPE)
257 .post(Entity.json(jsonStream));
258 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
259
260 String location = response.getLocation().getPath();
261 assertThat(location, Matchers.startsWith("/tenants/" + tenantId2));
262
263 verify(mockVnetAdminService);
264 }
265
266 /**
267 * Tests adding of a null tenant id using POST via JSON stream.
268 */
269 @Test
270 public void testPostNullTenantId() {
271
272 replay(mockVnetAdminService);
273
274 WebTarget wt = target();
275 try {
276 String response = wt.path("tenants")
277 .request(MediaType.APPLICATION_JSON_TYPE)
278 .post(Entity.json(null), String.class);
279 fail("POST of null tenant id did not throw an exception");
280 } catch (BadRequestException ex) {
281 assertThat(ex.getMessage(), containsString("HTTP 400 Bad Request"));
282 }
283
284 verify(mockVnetAdminService);
285 }
286
287 /**
288 * Tests removing a tenant id with DELETE request.
289 */
290 @Test
291 public void testDelete() {
292 expect(mockVnetAdminService.getTenantIds())
293 .andReturn(ImmutableSet.of(tenantId2)).anyTimes();
294 mockVnetAdminService.unregisterTenantId(anyObject());
295 expectLastCall();
296 replay(mockVnetAdminService);
297
298 WebTarget wt = target()
299 .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
300 Response response = wt.path("tenants/" + tenantId2)
301 .request(MediaType.APPLICATION_JSON_TYPE)
302 .delete();
303
Jian Lic2a542b2016-05-10 11:48:19 -0700304 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NO_CONTENT));
Claudine Chiufb8b8162016-04-01 23:50:51 +0000305
306 verify(mockVnetAdminService);
307 }
308
309 /**
Claudine Chiufb8b8162016-04-01 23:50:51 +0000310 * Tests that a DELETE of a non-existent tenant id throws an exception.
311 */
312 @Test
313 public void testDeleteNonExistentDeviceKey() {
314 expect(mockVnetAdminService.getTenantIds())
315 .andReturn(ImmutableSet.of())
316 .anyTimes();
317 expectLastCall();
318
319 replay(mockVnetAdminService);
320
321 WebTarget wt = target();
322
323 try {
324 wt.path("tenants/" + "NON_EXISTENT_TENANT_ID")
325 .request()
326 .delete(String.class);
327 fail("Delete of a non-existent tenant did not throw an exception");
328 } catch (NotFoundException ex) {
329 assertThat(ex.getMessage(), containsString("HTTP 404 Not Found"));
330 }
331
332 verify(mockVnetAdminService);
333 }
334}