blob: 3cb7c8d7391da2e947817f19ba6a8fbd20728f88 [file] [log] [blame]
Ray Milkeyf195b022015-02-03 15:13:11 -08001/*
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 */
16package org.onosproject.rest;
17
Jian Li80cfe452016-01-14 16:04:58 -080018import com.eclipsesource.json.Json;
Thomas Vachuskaebf5e542015-02-03 19:38:13 -080019import com.eclipsesource.json.JsonArray;
20import com.eclipsesource.json.JsonObject;
21import com.google.common.collect.ImmutableList;
22import com.google.common.collect.ImmutableSet;
23import com.sun.jersey.api.client.WebResource;
Ray Milkeyf195b022015-02-03 15:13:11 -080024import org.hamcrest.Description;
25import org.hamcrest.TypeSafeMatcher;
26import org.junit.After;
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.app.ApplicationAdminService;
33import org.onosproject.app.ApplicationService;
34import org.onosproject.app.ApplicationState;
35import org.onosproject.codec.CodecService;
36import org.onosproject.codec.impl.ApplicationCodec;
37import org.onosproject.codec.impl.CodecManager;
38import org.onosproject.codec.impl.MockCodecContext;
39import org.onosproject.core.Application;
40import org.onosproject.core.ApplicationId;
Changhoon Yoonbdeb88a2015-05-12 20:35:31 +090041import org.onosproject.core.ApplicationRole;
Ray Milkeyf195b022015-02-03 15:13:11 -080042import org.onosproject.core.DefaultApplication;
43import org.onosproject.core.DefaultApplicationId;
44import org.onosproject.core.Version;
45
Thomas Vachuskaebf5e542015-02-03 19:38:13 -080046import java.io.InputStream;
47import java.net.URI;
48import java.util.Optional;
Ray Milkeyf195b022015-02-03 15:13:11 -080049
Thomas Vachuskaebf5e542015-02-03 19:38:13 -080050import static org.easymock.EasyMock.*;
Ray Milkeyf195b022015-02-03 15:13:11 -080051import static org.hamcrest.MatcherAssert.assertThat;
Yuta HIGUCHI293ede02015-02-05 00:08:41 -080052import static org.hamcrest.Matchers.containsString;
53import static org.hamcrest.Matchers.hasSize;
54import static org.hamcrest.Matchers.is;
55import static org.hamcrest.Matchers.notNullValue;
Ray Milkeyf195b022015-02-03 15:13:11 -080056
57/**
58 * Unit tests for applications REST APIs.
59 */
60
61public class ApplicationsResourceTest extends ResourceTest {
62
63 private static class MockCodecContextWithService extends MockCodecContext {
64 private ApplicationAdminService service;
65
66 MockCodecContextWithService(ApplicationAdminService service) {
67 this.service = service;
68 }
69
70 @Override
71 @SuppressWarnings("unchecked")
Ray Milkey3078fc02015-05-06 16:14:14 -070072 public <T> T getService(Class<T> serviceClass) {
Ray Milkeyf195b022015-02-03 15:13:11 -080073 return (T) service;
74 }
75 }
76
77 private ApplicationAdminService service;
78 private ApplicationId id1 = new DefaultApplicationId(1, "app1");
79 private ApplicationId id2 = new DefaultApplicationId(2, "app2");
80 private ApplicationId id3 = new DefaultApplicationId(3, "app3");
81 private ApplicationId id4 = new DefaultApplicationId(4, "app4");
82
83 private static final URI FURL = URI.create("mvn:org.foo-features/1.2a/xml/features");
84 private static final Version VER = Version.version(1, 2, "a", null);
85
86 private Application app1 =
87 new DefaultApplication(id1, VER,
Jian Lic35415d2016-01-14 17:22:31 -080088 "app1", "origin1", "category1", "url1",
89 "readme1", new byte[0], ApplicationRole.ADMIN,
90 ImmutableSet.of(), Optional.of(FURL),
Thomas Vachuska761f0042015-11-11 19:10:17 -080091 ImmutableList.of("My Feature"), ImmutableList.of());
Ray Milkeyf195b022015-02-03 15:13:11 -080092 private Application app2 =
93 new DefaultApplication(id2, VER,
Jian Lic35415d2016-01-14 17:22:31 -080094 "app2", "origin2", "category2", "url2",
95 "readme2", new byte[0], ApplicationRole.ADMIN,
96 ImmutableSet.of(), Optional.of(FURL),
Thomas Vachuska761f0042015-11-11 19:10:17 -080097 ImmutableList.of("My Feature"), ImmutableList.of());
Ray Milkeyf195b022015-02-03 15:13:11 -080098 private Application app3 =
99 new DefaultApplication(id3, VER,
Jian Lic35415d2016-01-14 17:22:31 -0800100 "app3", "origin3", "category3", "url3",
101 "readme3", new byte[0], ApplicationRole.ADMIN,
102 ImmutableSet.of(), Optional.of(FURL),
Thomas Vachuska761f0042015-11-11 19:10:17 -0800103 ImmutableList.of("My Feature"), ImmutableList.of());
Ray Milkeyf195b022015-02-03 15:13:11 -0800104 private Application app4 =
105 new DefaultApplication(id4, VER,
Jian Lic35415d2016-01-14 17:22:31 -0800106 "app4", "origin4", "category4", "url4",
107 "readme4", new byte[0], ApplicationRole.ADMIN,
108 ImmutableSet.of(), Optional.of(FURL),
Thomas Vachuska761f0042015-11-11 19:10:17 -0800109 ImmutableList.of("My Feature"), ImmutableList.of());
Ray Milkeyf195b022015-02-03 15:13:11 -0800110
111 /**
Ray Milkeyed0b1662015-02-05 09:34:29 -0800112 * Hamcrest matcher to check that an application representation in JSON matches
Ray Milkeyf195b022015-02-03 15:13:11 -0800113 * the actual device.
114 */
115 private static class AppJsonMatcher extends TypeSafeMatcher<JsonObject> {
116 private final Application app;
117 private String reason = "";
118
119 public AppJsonMatcher(Application appValue) {
120 app = appValue;
121 }
122
123 @Override
124 public boolean matchesSafely(JsonObject jsonApp) {
125 // check id
126 short jsonId = (short) jsonApp.get("id").asInt();
127 if (jsonId != app.id().id()) {
128 reason = "id " + app.id().id();
129 return false;
130 }
131
132 // check name
133 String jsonName = jsonApp.get("name").asString();
134 if (!jsonName.equals(app.id().name())) {
135 reason = "name " + app.id().name();
136 return false;
137 }
138
139 // check origin
140 String jsonOrigin = jsonApp.get("origin").asString();
141 if (!jsonOrigin.equals(app.origin())) {
142 reason = "manufacturer " + app.origin();
143 return false;
144 }
145
146 return true;
147 }
148
149 @Override
150 public void describeTo(Description description) {
151 description.appendText(reason);
152 }
153 }
154
155 /**
Ray Milkeyed0b1662015-02-05 09:34:29 -0800156 * Factory to allocate an application matcher.
Ray Milkeyf195b022015-02-03 15:13:11 -0800157 *
158 * @param app application object we are looking for
159 * @return matcher
160 */
161 private static AppJsonMatcher matchesApp(Application app) {
162 return new AppJsonMatcher(app);
163 }
164
Ray Milkeyed0b1662015-02-05 09:34:29 -0800165 /**
166 * Initializes test mocks and environment.
167 */
Ray Milkeyf195b022015-02-03 15:13:11 -0800168 @Before
Ray Milkeyed0b1662015-02-05 09:34:29 -0800169 public void setUpMocks() {
Ray Milkeyf195b022015-02-03 15:13:11 -0800170 service = createMock(ApplicationAdminService.class);
171
172 expect(service.getId("one"))
173 .andReturn(id1)
174 .anyTimes();
175 expect(service.getId("two"))
176 .andReturn(id2)
177 .anyTimes();
178 expect(service.getId("three"))
179 .andReturn(id3)
180 .anyTimes();
181 expect(service.getId("four"))
182 .andReturn(id4)
183 .anyTimes();
184
185 expect(service.getApplication(id3))
186 .andReturn(app3)
187 .anyTimes();
188 expect(service.getState(isA(ApplicationId.class)))
189 .andReturn(ApplicationState.ACTIVE)
190 .anyTimes();
191
192 // Register the services needed for the test
193 CodecManager codecService = new CodecManager();
194 codecService.activate();
195 ServiceDirectory testDirectory =
196 new TestServiceDirectory()
197 .add(ApplicationAdminService.class, service)
198 .add(ApplicationService.class, service)
199 .add(CodecService.class, codecService);
200
201 BaseResource.setServiceDirectory(testDirectory);
202 }
203
Ray Milkeyed0b1662015-02-05 09:34:29 -0800204 /**
205 * Verifies test mocks.
206 */
Ray Milkeyf195b022015-02-03 15:13:11 -0800207 @After
Ray Milkeyed0b1662015-02-05 09:34:29 -0800208 public void tearDownMocks() {
Ray Milkeyf195b022015-02-03 15:13:11 -0800209 verify(service);
210 }
211
212 /**
213 * Tests a GET of all applications when no applications are present.
214 */
215 @Test
216 public void getAllApplicationsEmpty() {
217 expect(service.getApplications())
218 .andReturn(ImmutableSet.of());
219 replay(service);
220
221 WebResource rs = resource();
222 String response = rs.path("applications").get(String.class);
223 assertThat(response, is("{\"applications\":[]}"));
224 }
225
226 /**
227 * Tests a GET of all applications with data.
228 */
229 @Test
230 public void getAllApplicationsPopulated() {
231 expect(service.getApplications())
232 .andReturn(ImmutableSet.of(app1, app2, app3, app4));
233 replay(service);
234
235 WebResource rs = resource();
236 String response = rs.path("applications").get(String.class);
237 assertThat(response, containsString("{\"applications\":["));
238
Jian Li80cfe452016-01-14 16:04:58 -0800239 JsonObject result = Json.parse(response).asObject();
Ray Milkeyf195b022015-02-03 15:13:11 -0800240 assertThat(result, notNullValue());
241
242 assertThat(result.names(), hasSize(1));
243 assertThat(result.names().get(0), is("applications"));
244
245 JsonArray jsonApps = result.get("applications").asArray();
246 assertThat(jsonApps, notNullValue());
247 assertThat(jsonApps.size(), is(4));
248
249 assertThat(jsonApps.get(0).asObject(), matchesApp(app1));
250 assertThat(jsonApps.get(1).asObject(), matchesApp(app2));
251 assertThat(jsonApps.get(2).asObject(), matchesApp(app3));
252 assertThat(jsonApps.get(3).asObject(), matchesApp(app4));
253 }
254
255 /**
256 * Tests a GET of a single application.
257 */
258 @Test
259 public void getSingleApplication() {
260 replay(service);
261
262 WebResource rs = resource();
263 String response = rs.path("applications/three").get(String.class);
264
Jian Li80cfe452016-01-14 16:04:58 -0800265 JsonObject result = Json.parse(response).asObject();
Ray Milkeyf195b022015-02-03 15:13:11 -0800266 assertThat(result, notNullValue());
267
268 assertThat(result, matchesApp(app3));
269 }
270
271 /**
272 * Tests a DELETE of a single application - this should
273 * attempt to uninstall it.
274 */
275 @Test
276 public void deleteApplication() {
277 service.uninstall(id3);
278 expectLastCall();
279
280 replay(service);
281
282 WebResource rs = resource();
283 rs.path("applications/three").delete();
284 }
285
286 /**
287 * Tests a DELETE of a single active application - this should
288 * attempt to uninstall it.
289 */
290 @Test
291 public void deleteActiveApplication() {
292 service.deactivate(id3);
293 expectLastCall();
294
295 replay(service);
296
297 WebResource rs = resource();
298 rs.path("applications/three/active").delete();
299 }
300
301 /**
302 * Tests a POST operation to the "active" URL. This should attempt to
303 * activate the application.
304 */
305 @Test
306 public void postActiveApplication() {
307 service.activate(id3);
308 expectLastCall();
309
310 replay(service);
311
312 WebResource rs = resource();
313 rs.path("applications/three/active").post();
314 }
315
316 /**
317 * Tests a POST operation. This should attempt to
318 * install the application.
319 */
320 @Test
321 public void postApplication() {
322 expect(service.install(isA(InputStream.class)))
323 .andReturn(app4)
324 .once();
325
326 replay(service);
327
328 ApplicationCodec codec = new ApplicationCodec();
329 String app4Json = codec.encode(app4,
330 new MockCodecContextWithService(service))
331 .asText();
332
333 WebResource rs = resource();
334 String response = rs.path("applications").post(String.class, app4Json);
335
Jian Li80cfe452016-01-14 16:04:58 -0800336 JsonObject result = Json.parse(response).asObject();
Ray Milkeyf195b022015-02-03 15:13:11 -0800337 assertThat(result, notNullValue());
338
339 assertThat(result, matchesApp(app4));
340 }
341}