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