Ray Milkey
Committed by Gerrit Code Review

Unit tests for applications REST APIs

Change-Id: I4e8360ca9b0ca9eafe1b226b648acfe2b0676caa
...@@ -46,7 +46,7 @@ public class ApplicationsWebResource extends AbstractWebResource { ...@@ -46,7 +46,7 @@ public class ApplicationsWebResource extends AbstractWebResource {
46 46
47 @GET 47 @GET
48 @Path("{name}") 48 @Path("{name}")
49 - public Response getApplication(@PathParam("id") String name) { 49 + public Response getApplication(@PathParam("name") String name) {
50 ApplicationAdminService service = get(ApplicationAdminService.class); 50 ApplicationAdminService service = get(ApplicationAdminService.class);
51 ApplicationId appId = service.getId(name); 51 ApplicationId appId = service.getId(name);
52 return response(service, appId); 52 return response(service, appId);
......
...@@ -23,7 +23,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; ...@@ -23,7 +23,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
23 /** 23 /**
24 * Mock codec context for use in codec unit tests. 24 * Mock codec context for use in codec unit tests.
25 */ 25 */
26 -public final class MockCodecContext implements CodecContext { 26 +public class MockCodecContext implements CodecContext {
27 27
28 private ObjectMapper mapper = new ObjectMapper(); 28 private ObjectMapper mapper = new ObjectMapper();
29 private CodecManager manager = new CodecManager(); 29 private CodecManager manager = new CodecManager();
......
1 +/*
2 + * Copyright 2015 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 +package org.onosproject.rest;
17 +
18 +import java.io.InputStream;
19 +import java.net.URI;
20 +import java.util.Optional;
21 +
22 +import org.hamcrest.Description;
23 +import org.hamcrest.TypeSafeMatcher;
24 +import org.junit.After;
25 +import org.junit.Before;
26 +import org.junit.Test;
27 +import org.onlab.osgi.ServiceDirectory;
28 +import org.onlab.osgi.TestServiceDirectory;
29 +import org.onlab.rest.BaseResource;
30 +import org.onosproject.app.ApplicationAdminService;
31 +import org.onosproject.app.ApplicationService;
32 +import org.onosproject.app.ApplicationState;
33 +import org.onosproject.codec.CodecService;
34 +import org.onosproject.codec.impl.ApplicationCodec;
35 +import org.onosproject.codec.impl.CodecManager;
36 +import org.onosproject.codec.impl.MockCodecContext;
37 +import org.onosproject.core.Application;
38 +import org.onosproject.core.ApplicationId;
39 +import org.onosproject.core.DefaultApplication;
40 +import org.onosproject.core.DefaultApplicationId;
41 +import org.onosproject.core.Version;
42 +
43 +import com.eclipsesource.json.JsonArray;
44 +import com.eclipsesource.json.JsonObject;
45 +import com.google.common.collect.ImmutableSet;
46 +import com.sun.jersey.api.client.WebResource;
47 +
48 +import static org.easymock.EasyMock.createMock;
49 +import static org.easymock.EasyMock.expect;
50 +import static org.easymock.EasyMock.expectLastCall;
51 +import static org.easymock.EasyMock.isA;
52 +import static org.easymock.EasyMock.replay;
53 +import static org.easymock.EasyMock.verify;
54 +import static org.hamcrest.MatcherAssert.assertThat;
55 +import static org.hamcrest.Matchers.containsString;
56 +import static org.hamcrest.Matchers.hasSize;
57 +import static org.hamcrest.Matchers.is;
58 +import static org.hamcrest.Matchers.notNullValue;
59 +
60 +/**
61 + * Unit tests for applications REST APIs.
62 + */
63 +
64 +public class ApplicationsResourceTest extends ResourceTest {
65 +
66 + private static class MockCodecContextWithService extends MockCodecContext {
67 + private ApplicationAdminService service;
68 +
69 + MockCodecContextWithService(ApplicationAdminService service) {
70 + this.service = service;
71 + }
72 +
73 + @Override
74 + @SuppressWarnings("unchecked")
75 + public <T> T get(Class<T> serviceClass) {
76 + return (T) service;
77 + }
78 + }
79 +
80 + private ApplicationAdminService service;
81 + private ApplicationId id1 = new DefaultApplicationId(1, "app1");
82 + private ApplicationId id2 = new DefaultApplicationId(2, "app2");
83 + private ApplicationId id3 = new DefaultApplicationId(3, "app3");
84 + private ApplicationId id4 = new DefaultApplicationId(4, "app4");
85 +
86 + private static final URI FURL = URI.create("mvn:org.foo-features/1.2a/xml/features");
87 + private static final Version VER = Version.version(1, 2, "a", null);
88 +
89 + private Application app1 =
90 + new DefaultApplication(id1, VER,
91 + "app1", "origin1", ImmutableSet.of(), Optional.of(FURL),
92 + ImmutableSet.of("My Feature"));
93 + private Application app2 =
94 + new DefaultApplication(id2, VER,
95 + "app2", "origin2", ImmutableSet.of(), Optional.of(FURL),
96 + ImmutableSet.of("My Feature"));
97 + private Application app3 =
98 + new DefaultApplication(id3, VER,
99 + "app3", "origin3", ImmutableSet.of(), Optional.of(FURL),
100 + ImmutableSet.of("My Feature"));
101 + private Application app4 =
102 + new DefaultApplication(id4, VER,
103 + "app4", "origin4", ImmutableSet.of(), Optional.of(FURL),
104 + ImmutableSet.of("My Feature"));
105 +
106 + /**
107 + * Hamcrest matcher to check that an device representation in JSON matches
108 + * the actual device.
109 + */
110 + private static class AppJsonMatcher extends TypeSafeMatcher<JsonObject> {
111 + private final Application app;
112 + private String reason = "";
113 +
114 + public AppJsonMatcher(Application appValue) {
115 + app = appValue;
116 + }
117 +
118 + @Override
119 + public boolean matchesSafely(JsonObject jsonApp) {
120 + // check id
121 + short jsonId = (short) jsonApp.get("id").asInt();
122 + if (jsonId != app.id().id()) {
123 + reason = "id " + app.id().id();
124 + return false;
125 + }
126 +
127 + // check name
128 + String jsonName = jsonApp.get("name").asString();
129 + if (!jsonName.equals(app.id().name())) {
130 + reason = "name " + app.id().name();
131 + return false;
132 + }
133 +
134 + // check origin
135 + String jsonOrigin = jsonApp.get("origin").asString();
136 + if (!jsonOrigin.equals(app.origin())) {
137 + reason = "manufacturer " + app.origin();
138 + return false;
139 + }
140 +
141 + return true;
142 + }
143 +
144 + @Override
145 + public void describeTo(Description description) {
146 + description.appendText(reason);
147 + }
148 + }
149 +
150 + /**
151 + * Factory to allocate an device matcher.
152 + *
153 + * @param app application object we are looking for
154 + * @return matcher
155 + */
156 + private static AppJsonMatcher matchesApp(Application app) {
157 + return new AppJsonMatcher(app);
158 + }
159 +
160 +
161 + @Before
162 + public void setUp() {
163 + service = createMock(ApplicationAdminService.class);
164 +
165 + expect(service.getId("one"))
166 + .andReturn(id1)
167 + .anyTimes();
168 + expect(service.getId("two"))
169 + .andReturn(id2)
170 + .anyTimes();
171 + expect(service.getId("three"))
172 + .andReturn(id3)
173 + .anyTimes();
174 + expect(service.getId("four"))
175 + .andReturn(id4)
176 + .anyTimes();
177 +
178 + expect(service.getApplication(id3))
179 + .andReturn(app3)
180 + .anyTimes();
181 + expect(service.getState(isA(ApplicationId.class)))
182 + .andReturn(ApplicationState.ACTIVE)
183 + .anyTimes();
184 +
185 + // Register the services needed for the test
186 + CodecManager codecService = new CodecManager();
187 + codecService.activate();
188 + ServiceDirectory testDirectory =
189 + new TestServiceDirectory()
190 + .add(ApplicationAdminService.class, service)
191 + .add(ApplicationService.class, service)
192 + .add(CodecService.class, codecService);
193 +
194 + BaseResource.setServiceDirectory(testDirectory);
195 + }
196 +
197 + @After
198 + public void shutDown() {
199 + verify(service);
200 + }
201 +
202 + /**
203 + * Tests a GET of all applications when no applications are present.
204 + */
205 + @Test
206 + public void getAllApplicationsEmpty() {
207 + expect(service.getApplications())
208 + .andReturn(ImmutableSet.of());
209 + replay(service);
210 +
211 + WebResource rs = resource();
212 + String response = rs.path("applications").get(String.class);
213 + assertThat(response, is("{\"applications\":[]}"));
214 + }
215 +
216 + /**
217 + * Tests a GET of all applications with data.
218 + */
219 + @Test
220 + public void getAllApplicationsPopulated() {
221 + expect(service.getApplications())
222 + .andReturn(ImmutableSet.of(app1, app2, app3, app4));
223 + replay(service);
224 +
225 + WebResource rs = resource();
226 + String response = rs.path("applications").get(String.class);
227 + assertThat(response, containsString("{\"applications\":["));
228 +
229 + JsonObject result = JsonObject.readFrom(response);
230 + assertThat(result, notNullValue());
231 +
232 + assertThat(result.names(), hasSize(1));
233 + assertThat(result.names().get(0), is("applications"));
234 +
235 + JsonArray jsonApps = result.get("applications").asArray();
236 + assertThat(jsonApps, notNullValue());
237 + assertThat(jsonApps.size(), is(4));
238 +
239 + assertThat(jsonApps.get(0).asObject(), matchesApp(app1));
240 + assertThat(jsonApps.get(1).asObject(), matchesApp(app2));
241 + assertThat(jsonApps.get(2).asObject(), matchesApp(app3));
242 + assertThat(jsonApps.get(3).asObject(), matchesApp(app4));
243 + }
244 +
245 + /**
246 + * Tests a GET of a single application.
247 + */
248 + @Test
249 + public void getSingleApplication() {
250 + replay(service);
251 +
252 + WebResource rs = resource();
253 + String response = rs.path("applications/three").get(String.class);
254 +
255 + JsonObject result = JsonObject.readFrom(response);
256 + assertThat(result, notNullValue());
257 +
258 + assertThat(result, matchesApp(app3));
259 + }
260 +
261 + /**
262 + * Tests a DELETE of a single application - this should
263 + * attempt to uninstall it.
264 + */
265 + @Test
266 + public void deleteApplication() {
267 + service.uninstall(id3);
268 + expectLastCall();
269 +
270 + replay(service);
271 +
272 + WebResource rs = resource();
273 + rs.path("applications/three").delete();
274 + }
275 +
276 + /**
277 + * Tests a DELETE of a single active application - this should
278 + * attempt to uninstall it.
279 + */
280 + @Test
281 + public void deleteActiveApplication() {
282 + service.deactivate(id3);
283 + expectLastCall();
284 +
285 + replay(service);
286 +
287 + WebResource rs = resource();
288 + rs.path("applications/three/active").delete();
289 + }
290 +
291 + /**
292 + * Tests a POST operation to the "active" URL. This should attempt to
293 + * activate the application.
294 + */
295 + @Test
296 + public void postActiveApplication() {
297 + service.activate(id3);
298 + expectLastCall();
299 +
300 + replay(service);
301 +
302 + WebResource rs = resource();
303 + rs.path("applications/three/active").post();
304 + }
305 +
306 + /**
307 + * Tests a POST operation. This should attempt to
308 + * install the application.
309 + */
310 + @Test
311 + public void postApplication() {
312 + expect(service.install(isA(InputStream.class)))
313 + .andReturn(app4)
314 + .once();
315 +
316 + replay(service);
317 +
318 + ApplicationCodec codec = new ApplicationCodec();
319 + String app4Json = codec.encode(app4,
320 + new MockCodecContextWithService(service))
321 + .asText();
322 +
323 + WebResource rs = resource();
324 + String response = rs.path("applications").post(String.class, app4Json);
325 +
326 + JsonObject result = JsonObject.readFrom(response);
327 + assertThat(result, notNullValue());
328 +
329 + assertThat(result, matchesApp(app4));
330 + }
331 +}