blob: 54f1beae3e21dfc23ad9708f023ae187242bb89f [file] [log] [blame]
Brian Stankeb9170d92016-02-19 14:18:42 -05001/*
2 * Copyright 2016 Open Networking Laboratory
3 *
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;
18
19import com.eclipsesource.json.Json;
20import com.eclipsesource.json.JsonArray;
21import com.eclipsesource.json.JsonObject;
22import com.sun.jersey.api.client.ClientResponse;
23import com.sun.jersey.api.client.UniformInterfaceException;
24import com.sun.jersey.api.client.WebResource;
25import org.hamcrest.Description;
26import org.hamcrest.Matchers;
27import org.hamcrest.TypeSafeMatcher;
Brian Stankeb9170d92016-02-19 14:18:42 -050028import org.junit.Before;
29import org.junit.Test;
30import org.onlab.osgi.ServiceDirectory;
31import org.onlab.osgi.TestServiceDirectory;
32import org.onlab.rest.BaseResource;
33import org.onosproject.codec.CodecService;
34import org.onosproject.codec.impl.CodecManager;
35import org.onosproject.net.key.DeviceKey;
36import org.onosproject.net.key.DeviceKeyAdminService;
37import org.onosproject.net.key.DeviceKeyId;
38import org.onosproject.net.key.DeviceKeyService;
39
40import javax.ws.rs.core.MediaType;
41import java.io.InputStream;
42import java.net.HttpURLConnection;
43import java.util.HashSet;
44
45import static org.easymock.EasyMock.*;
46import static org.hamcrest.Matchers.*;
47import static org.junit.Assert.*;
48
49/**
50 * Unit tests for device key REST APIs.
51 */
52public class DeviceKeyWebResourceTest extends ResourceTest {
53
54 final DeviceKeyService mockDeviceKeyService = createMock(DeviceKeyService.class);
55 final DeviceKeyAdminService mockDeviceKeyAdminService = createMock(DeviceKeyAdminService.class);
56
57 final HashSet<DeviceKey> deviceKeySet = new HashSet<>();
58
59 private static final String ID = "id";
60 private static final String TYPE = "type";
61 private static final String LABEL = "label";
62 private static final String COMMUNITY_NAME = "community_name";
63 private static final String USERNAME = "username";
64 private static final String PASSWORD = "password";
65
66 private final String deviceKeyId1 = "DeviceKeyId1";
67 private final String deviceKeyId2 = "DeviceKeyId2";
68 private final String deviceKeyId3 = "DeviceKeyId3";
Brian Stankeb8ff6412016-02-25 14:16:19 -050069 private final String deviceKeyId4 = "DeviceKeyId4";
Brian Stankeb9170d92016-02-19 14:18:42 -050070 private final String deviceKeyLabel = "DeviceKeyLabel";
71 private final String deviceKeyCommunityName = "DeviceKeyCommunityName";
72 private final String deviceKeyUsername = "DeviceKeyUsername";
73 private final String deviceKeyPassword = "DeviceKeyPassword";
74
75 private final DeviceKey deviceKey1 = DeviceKey.createDeviceKeyUsingCommunityName(
76 DeviceKeyId.deviceKeyId(deviceKeyId1), deviceKeyLabel, deviceKeyCommunityName);
77 private final DeviceKey deviceKey2 = DeviceKey.createDeviceKeyUsingUsernamePassword(
Brian Stankeb8ff6412016-02-25 14:16:19 -050078 DeviceKeyId.deviceKeyId(deviceKeyId2), null, deviceKeyUsername, deviceKeyPassword);
79 private final DeviceKey deviceKey3 = DeviceKey.createDeviceKeyUsingUsernamePassword(
80 DeviceKeyId.deviceKeyId(deviceKeyId3), null, null, null);
81 private final DeviceKey deviceKey4 = DeviceKey.createDeviceKeyUsingCommunityName(
82 DeviceKeyId.deviceKeyId(deviceKeyId4), null, null);
Brian Stankeb9170d92016-02-19 14:18:42 -050083
84 /**
85 * Initializes test mocks and environment.
86 */
87 @Before
88 public void setUpMocks() {
89 expect(mockDeviceKeyService.getDeviceKeys()).andReturn(deviceKeySet).anyTimes();
90
91 // Register the services needed for the test
92 CodecManager codecService = new CodecManager();
93 codecService.activate();
94 ServiceDirectory testDirectory =
95 new TestServiceDirectory()
96 .add(DeviceKeyService.class, mockDeviceKeyService)
97 .add(DeviceKeyAdminService.class, mockDeviceKeyAdminService)
98 .add(CodecService.class, codecService);
99
100 BaseResource.setServiceDirectory(testDirectory);
101 }
102
103 /**
Brian Stankeb9170d92016-02-19 14:18:42 -0500104 * Hamcrest matcher to check that a device key representation in JSON matches
105 * the actual device key.
106 */
107 public static class DeviceKeyJsonMatcher extends TypeSafeMatcher<JsonObject> {
108 private final DeviceKey deviceKey;
109 private String reason = "";
110
111 public DeviceKeyJsonMatcher(DeviceKey deviceKeyValue) {
112 deviceKey = deviceKeyValue;
113 }
114
115 @Override
116 public boolean matchesSafely(JsonObject jsonHost) {
117 // Check the device key id
118 final String jsonId = jsonHost.get(ID).asString();
119 if (!jsonId.equals(deviceKey.deviceKeyId().id().toString())) {
120 reason = ID + " " + deviceKey.deviceKeyId().id().toString();
121 return false;
122 }
123
124 // Check the device key label
Brian Stankeb8ff6412016-02-25 14:16:19 -0500125 final String jsonLabel = (jsonHost.get(LABEL).isNull()) ? null : jsonHost.get(LABEL).asString();
126 if (deviceKey.label() != null) {
127 if ((jsonLabel == null) || !jsonLabel.equals(deviceKey.label())) {
128 reason = LABEL + " " + deviceKey.label();
129 return false;
130 }
Brian Stankeb9170d92016-02-19 14:18:42 -0500131 }
132
133 // Check the device key type
134 final String jsonType = jsonHost.get(TYPE).asString();
135 if (!jsonType.equals(deviceKey.type().toString())) {
136 reason = TYPE + " " + deviceKey.type().toString();
137 return false;
138 }
139
140 if (jsonType.equals(DeviceKey.Type.COMMUNITY_NAME.toString())) {
141 // Check the device key community name
Brian Stankeb8ff6412016-02-25 14:16:19 -0500142 final String jsonCommunityName = jsonHost.get(COMMUNITY_NAME).isNull() ?
143 null : jsonHost.get(COMMUNITY_NAME).asString();
144 if (deviceKey.asCommunityName().name() != null) {
145 if (!jsonCommunityName.equals(deviceKey.asCommunityName().name().toString())) {
146 reason = COMMUNITY_NAME + " " + deviceKey.asCommunityName().name().toString();
147 return false;
148 }
Brian Stankeb9170d92016-02-19 14:18:42 -0500149 }
150 } else if (jsonType.equals(DeviceKey.Type.USERNAME_PASSWORD.toString())) {
151 // Check the device key username
Brian Stankeb8ff6412016-02-25 14:16:19 -0500152 final String jsonUsername = jsonHost.get(USERNAME).isNull() ?
153 null : jsonHost.get(USERNAME).asString();
154 if (deviceKey.asUsernamePassword().username() != null) {
155 if (!jsonUsername.equals(deviceKey.asUsernamePassword().username().toString())) {
156 reason = USERNAME + " " + deviceKey.asUsernamePassword().username().toString();
157 return false;
158 }
Brian Stankeb9170d92016-02-19 14:18:42 -0500159 }
160
161 // Check the device key password
Brian Stankeb8ff6412016-02-25 14:16:19 -0500162 final String jsonPassword = jsonHost.get(PASSWORD).isNull() ?
163 null : jsonHost.get(PASSWORD).asString();
164 if (deviceKey.asUsernamePassword().password() != null) {
165 if (!jsonPassword.equals(deviceKey.asUsernamePassword().password().toString())) {
166 reason = PASSWORD + " " + deviceKey.asUsernamePassword().password().toString();
167 return false;
168 }
Brian Stankeb9170d92016-02-19 14:18:42 -0500169 }
170 } else {
171 reason = "Unknown " + TYPE + " " + deviceKey.type().toString();
172 return false;
173 }
174
175 return true;
176 }
177
178 @Override
179 public void describeTo(Description description) {
180 description.appendText(reason);
181 }
182 }
183
184 /**
185 * Factory to allocate a device key array matcher.
186 *
187 * @param deviceKey device key object we are looking for
188 * @return matcher
189 */
190 private static DeviceKeyJsonMatcher matchesDeviceKey(DeviceKey deviceKey) {
191 return new DeviceKeyJsonMatcher(deviceKey);
192 }
193
194 /**
195 * Hamcrest matcher to check that a device key is represented properly in a JSON
196 * array of device keys.
197 */
198 public static class DeviceKeyJsonArrayMatcher extends TypeSafeMatcher<JsonArray> {
199 private final DeviceKey deviceKey;
200 private String reason = "";
201
202 public DeviceKeyJsonArrayMatcher(DeviceKey deviceKeyValue) {
203 deviceKey = deviceKeyValue;
204 }
205
206 @Override
207 public boolean matchesSafely(JsonArray json) {
208 boolean deviceKeyFound = false;
209 final int expectedAttributes = 5;
210 for (int jsonDeviceKeyIndex = 0; jsonDeviceKeyIndex < json.size();
211 jsonDeviceKeyIndex++) {
212
213 final JsonObject jsonHost = json.get(jsonDeviceKeyIndex).asObject();
214
215 // Device keys can have a variable number of attribute so we check
216 // that there is a minimum number.
217 if (jsonHost.names().size() < expectedAttributes) {
218 reason = "Found a device key with the wrong number of attributes";
219 return false;
220 }
221
222 final String jsonDeviceKeyId = jsonHost.get(ID).asString();
223 if (jsonDeviceKeyId.equals(deviceKey.deviceKeyId().id().toString())) {
224 deviceKeyFound = true;
225
226 // We found the correct device key, check the device key attribute values
227 assertThat(jsonHost, matchesDeviceKey(deviceKey));
228 }
229 }
230 if (!deviceKeyFound) {
231 reason = "Device key with id " + deviceKey.deviceKeyId().id().toString() + " was not found";
232 return false;
233 } else {
234 return true;
235 }
236 }
237
238 @Override
239 public void describeTo(Description description) {
240 description.appendText(reason);
241 }
242 }
243
244 /**
245 * Factory to allocate a device key array matcher.
246 *
247 * @param deviceKey device key object we are looking for
248 * @return matcher
249 */
250 private static DeviceKeyJsonArrayMatcher hasDeviceKey(DeviceKey deviceKey) {
251 return new DeviceKeyJsonArrayMatcher(deviceKey);
252 }
253
254 /**
255 * Tests the result of the REST API GET when there are no device keys.
256 */
257 @Test
258 public void testGetDeviceKeysEmptyArray() {
259 replay(mockDeviceKeyService);
Brian Stankeb9170d92016-02-19 14:18:42 -0500260
261 WebResource rs = resource();
262 String response = rs.path("keys").get(String.class);
263 assertThat(response, is("{\"keys\":[]}"));
Brian Stankeb8ff6412016-02-25 14:16:19 -0500264
265 verify(mockDeviceKeyService);
Brian Stankeb9170d92016-02-19 14:18:42 -0500266 }
267
268 /**
269 * Tests the result of the REST API GET when device keys are defined.
270 */
271 @Test
272 public void testGetDeviceKeysArray() {
273 replay(mockDeviceKeyService);
Brian Stankeb9170d92016-02-19 14:18:42 -0500274 deviceKeySet.add(deviceKey1);
275 deviceKeySet.add(deviceKey2);
Brian Stankeb8ff6412016-02-25 14:16:19 -0500276 deviceKeySet.add(deviceKey3);
277 deviceKeySet.add(deviceKey4);
Brian Stankeb9170d92016-02-19 14:18:42 -0500278
279 WebResource rs = resource();
280 String response = rs.path("keys").get(String.class);
281 assertThat(response, containsString("{\"keys\":["));
282
283 final JsonObject result = Json.parse(response).asObject();
284 assertThat(result, notNullValue());
285
286 assertThat(result.names(), hasSize(1));
287 assertThat(result.names().get(0), is("keys"));
288
289 final JsonArray deviceKeys = result.get("keys").asArray();
290 assertThat(deviceKeys, notNullValue());
Brian Stankeb8ff6412016-02-25 14:16:19 -0500291 assertEquals("Device keys array is not the correct size.", 4, deviceKeys.size());
Brian Stankeb9170d92016-02-19 14:18:42 -0500292
293 assertThat(deviceKeys, hasDeviceKey(deviceKey1));
294 assertThat(deviceKeys, hasDeviceKey(deviceKey2));
Brian Stankeb8ff6412016-02-25 14:16:19 -0500295 assertThat(deviceKeys, hasDeviceKey(deviceKey3));
296 assertThat(deviceKeys, hasDeviceKey(deviceKey4));
297
298 verify(mockDeviceKeyService);
Brian Stankeb9170d92016-02-19 14:18:42 -0500299 }
300
301 /**
302 * Tests the result of the REST API GET using a device key identifier.
303 */
304 @Test
305 public void testGetDeviceKeyById() {
306 deviceKeySet.add(deviceKey1);
307
308 expect(mockDeviceKeyService.getDeviceKey(DeviceKeyId.deviceKeyId(deviceKeyId1)))
309 .andReturn(deviceKey1)
310 .anyTimes();
311 replay(mockDeviceKeyService);
Brian Stankeb9170d92016-02-19 14:18:42 -0500312
313 WebResource rs = resource();
314 String response = rs.path("keys/" + deviceKeyId1).get(String.class);
315 final JsonObject result = Json.parse(response).asObject();
316 assertThat(result, notNullValue());
317
318 assertThat(result, matchesDeviceKey(deviceKey1));
Brian Stankeb8ff6412016-02-25 14:16:19 -0500319
320 verify(mockDeviceKeyService);
Brian Stankeb9170d92016-02-19 14:18:42 -0500321 }
322
323 /**
324 * Tests that a GET of a non-existent object throws an exception.
325 */
326 @Test
327 public void testGetNonExistentDeviceKey() {
328
329 expect(mockDeviceKeyService.getDeviceKey(DeviceKeyId.deviceKeyId(deviceKeyId1)))
330 .andReturn(null)
331 .anyTimes();
332 replay(mockDeviceKeyService);
Brian Stankeb9170d92016-02-19 14:18:42 -0500333
334 WebResource rs = resource();
335 try {
336 String response = rs.path("keys/" + deviceKeyId1).get(String.class);
337 fail("GET of a non-existent device key did not throw an exception");
338 } catch (UniformInterfaceException ex) {
339 assertThat(ex.getMessage(),
340 containsString("returned a response status of"));
341 }
Brian Stankeb8ff6412016-02-25 14:16:19 -0500342
343 verify(mockDeviceKeyService);
Brian Stankeb9170d92016-02-19 14:18:42 -0500344 }
345
346 /**
347 * Tests adding of new device key using POST via JSON stream.
348 */
349 @Test
350 public void testPost() {
351
352 mockDeviceKeyAdminService.addKey(anyObject());
353 expectLastCall();
354
Brian Stankeb9170d92016-02-19 14:18:42 -0500355 replay(mockDeviceKeyAdminService);
356
357 WebResource rs = resource();
358 InputStream jsonStream = DeviceKeyWebResourceTest.class
359 .getResourceAsStream("post-device-key.json");
360
361 ClientResponse response = rs.path("keys")
362 .type(MediaType.APPLICATION_JSON_TYPE)
363 .post(ClientResponse.class, jsonStream);
364 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
365
366 String location = response.getLocation().getPath();
367 assertThat(location, Matchers.startsWith("/keys/" + deviceKeyId3));
Brian Stankeb8ff6412016-02-25 14:16:19 -0500368
369 verify(mockDeviceKeyAdminService);
Brian Stankeb9170d92016-02-19 14:18:42 -0500370 }
371
372 /**
373 * Tests adding of a null device key using POST via JSON stream.
374 */
375 @Test
376 public void testPostNullDeviceKey() {
377
Brian Stankeb9170d92016-02-19 14:18:42 -0500378 replay(mockDeviceKeyAdminService);
379
380 WebResource rs = resource();
381 try {
382 String response = rs.path("keys")
383 .type(MediaType.APPLICATION_JSON_TYPE)
384 .post(String.class);
385 fail("POST of null device key did not throw an exception");
386 } catch (UniformInterfaceException ex) {
387 assertThat(ex.getMessage(),
388 containsString("returned a response status of"));
389 }
Brian Stankeb8ff6412016-02-25 14:16:19 -0500390
391 verify(mockDeviceKeyAdminService);
Brian Stankeb9170d92016-02-19 14:18:42 -0500392 }
393
394 /**
395 * Tests removing a device key with DELETE request.
396 */
397 @Test
398 public void testDelete() {
399 expect(mockDeviceKeyService.getDeviceKey(DeviceKeyId.deviceKeyId(deviceKeyId2)))
400 .andReturn(deviceKey2)
401 .anyTimes();
402 mockDeviceKeyAdminService.removeKey(anyObject());
403 expectLastCall();
404
405 replay(mockDeviceKeyService);
406 replay(mockDeviceKeyAdminService);
407
408 WebResource rs = resource();
409
410 ClientResponse response = rs.path("keys/" + deviceKeyId2)
411 .type(MediaType.APPLICATION_JSON_TYPE)
412 .delete(ClientResponse.class);
413 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
Brian Stankeb8ff6412016-02-25 14:16:19 -0500414
415 verify(mockDeviceKeyService);
416 verify(mockDeviceKeyAdminService);
Brian Stankeb9170d92016-02-19 14:18:42 -0500417 }
418
419 /**
420 * Tests that a DELETE of a non-existent device key throws an exception.
421 */
422 @Test
423 public void testDeleteNonExistentDeviceKey() {
424 expect(mockDeviceKeyService.getDeviceKey(anyObject()))
425 .andReturn(null)
426 .anyTimes();
427
428 expectLastCall();
429
430 replay(mockDeviceKeyService);
431 replay(mockDeviceKeyAdminService);
432
433 WebResource rs = resource();
434
435 try {
436 String response = rs.path("keys/" + "NON_EXISTENT_DEVICE_KEY")
437 .delete(String.class);
438 fail("Delete of a non-existent device key did not throw an exception");
439 } catch (UniformInterfaceException ex) {
440 assertThat(ex.getMessage(),
441 containsString("returned a response status of"));
442 }
Brian Stankeb8ff6412016-02-25 14:16:19 -0500443
444 verify(mockDeviceKeyService);
445 verify(mockDeviceKeyAdminService);
Brian Stankeb9170d92016-02-19 14:18:42 -0500446 }
447}