blob: eeac8867738a139a3da660c9033237fc9766e86e [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,
Changhoon Yoonbdeb88a2015-05-12 20:35:31 +090088 "app1", "origin1", ApplicationRole.ADMIN, ImmutableSet.of(), Optional.of(FURL),
Thomas Vachuska761f0042015-11-11 19:10:17 -080089 ImmutableList.of("My Feature"), ImmutableList.of());
Ray Milkeyf195b022015-02-03 15:13:11 -080090 private Application app2 =
91 new DefaultApplication(id2, VER,
Changhoon Yoonbdeb88a2015-05-12 20:35:31 +090092 "app2", "origin2", ApplicationRole.ADMIN, ImmutableSet.of(), Optional.of(FURL),
Thomas Vachuska761f0042015-11-11 19:10:17 -080093 ImmutableList.of("My Feature"), ImmutableList.of());
Ray Milkeyf195b022015-02-03 15:13:11 -080094 private Application app3 =
95 new DefaultApplication(id3, VER,
Changhoon Yoonbdeb88a2015-05-12 20:35:31 +090096 "app3", "origin3", ApplicationRole.ADMIN, 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 app4 =
99 new DefaultApplication(id4, VER,
Changhoon Yoonbdeb88a2015-05-12 20:35:31 +0900100 "app4", "origin4", ApplicationRole.ADMIN, ImmutableSet.of(), Optional.of(FURL),
Thomas Vachuska761f0042015-11-11 19:10:17 -0800101 ImmutableList.of("My Feature"), ImmutableList.of());
Ray Milkeyf195b022015-02-03 15:13:11 -0800102
103 /**
Ray Milkeyed0b1662015-02-05 09:34:29 -0800104 * Hamcrest matcher to check that an application representation in JSON matches
Ray Milkeyf195b022015-02-03 15:13:11 -0800105 * the actual device.
106 */
107 private static class AppJsonMatcher extends TypeSafeMatcher<JsonObject> {
108 private final Application app;
109 private String reason = "";
110
111 public AppJsonMatcher(Application appValue) {
112 app = appValue;
113 }
114
115 @Override
116 public boolean matchesSafely(JsonObject jsonApp) {
117 // check id
118 short jsonId = (short) jsonApp.get("id").asInt();
119 if (jsonId != app.id().id()) {
120 reason = "id " + app.id().id();
121 return false;
122 }
123
124 // check name
125 String jsonName = jsonApp.get("name").asString();
126 if (!jsonName.equals(app.id().name())) {
127 reason = "name " + app.id().name();
128 return false;
129 }
130
131 // check origin
132 String jsonOrigin = jsonApp.get("origin").asString();
133 if (!jsonOrigin.equals(app.origin())) {
134 reason = "manufacturer " + app.origin();
135 return false;
136 }
137
138 return true;
139 }
140
141 @Override
142 public void describeTo(Description description) {
143 description.appendText(reason);
144 }
145 }
146
147 /**
Ray Milkeyed0b1662015-02-05 09:34:29 -0800148 * Factory to allocate an application matcher.
Ray Milkeyf195b022015-02-03 15:13:11 -0800149 *
150 * @param app application object we are looking for
151 * @return matcher
152 */
153 private static AppJsonMatcher matchesApp(Application app) {
154 return new AppJsonMatcher(app);
155 }
156
Ray Milkeyed0b1662015-02-05 09:34:29 -0800157 /**
158 * Initializes test mocks and environment.
159 */
Ray Milkeyf195b022015-02-03 15:13:11 -0800160 @Before
Ray Milkeyed0b1662015-02-05 09:34:29 -0800161 public void setUpMocks() {
Ray Milkeyf195b022015-02-03 15:13:11 -0800162 service = createMock(ApplicationAdminService.class);
163
164 expect(service.getId("one"))
165 .andReturn(id1)
166 .anyTimes();
167 expect(service.getId("two"))
168 .andReturn(id2)
169 .anyTimes();
170 expect(service.getId("three"))
171 .andReturn(id3)
172 .anyTimes();
173 expect(service.getId("four"))
174 .andReturn(id4)
175 .anyTimes();
176
177 expect(service.getApplication(id3))
178 .andReturn(app3)
179 .anyTimes();
180 expect(service.getState(isA(ApplicationId.class)))
181 .andReturn(ApplicationState.ACTIVE)
182 .anyTimes();
183
184 // Register the services needed for the test
185 CodecManager codecService = new CodecManager();
186 codecService.activate();
187 ServiceDirectory testDirectory =
188 new TestServiceDirectory()
189 .add(ApplicationAdminService.class, service)
190 .add(ApplicationService.class, service)
191 .add(CodecService.class, codecService);
192
193 BaseResource.setServiceDirectory(testDirectory);
194 }
195
Ray Milkeyed0b1662015-02-05 09:34:29 -0800196 /**
197 * Verifies test mocks.
198 */
Ray Milkeyf195b022015-02-03 15:13:11 -0800199 @After
Ray Milkeyed0b1662015-02-05 09:34:29 -0800200 public void tearDownMocks() {
Ray Milkeyf195b022015-02-03 15:13:11 -0800201 verify(service);
202 }
203
204 /**
205 * Tests a GET of all applications when no applications are present.
206 */
207 @Test
208 public void getAllApplicationsEmpty() {
209 expect(service.getApplications())
210 .andReturn(ImmutableSet.of());
211 replay(service);
212
213 WebResource rs = resource();
214 String response = rs.path("applications").get(String.class);
215 assertThat(response, is("{\"applications\":[]}"));
216 }
217
218 /**
219 * Tests a GET of all applications with data.
220 */
221 @Test
222 public void getAllApplicationsPopulated() {
223 expect(service.getApplications())
224 .andReturn(ImmutableSet.of(app1, app2, app3, app4));
225 replay(service);
226
227 WebResource rs = resource();
228 String response = rs.path("applications").get(String.class);
229 assertThat(response, containsString("{\"applications\":["));
230
Jian Li80cfe452016-01-14 16:04:58 -0800231 JsonObject result = Json.parse(response).asObject();
Ray Milkeyf195b022015-02-03 15:13:11 -0800232 assertThat(result, notNullValue());
233
234 assertThat(result.names(), hasSize(1));
235 assertThat(result.names().get(0), is("applications"));
236
237 JsonArray jsonApps = result.get("applications").asArray();
238 assertThat(jsonApps, notNullValue());
239 assertThat(jsonApps.size(), is(4));
240
241 assertThat(jsonApps.get(0).asObject(), matchesApp(app1));
242 assertThat(jsonApps.get(1).asObject(), matchesApp(app2));
243 assertThat(jsonApps.get(2).asObject(), matchesApp(app3));
244 assertThat(jsonApps.get(3).asObject(), matchesApp(app4));
245 }
246
247 /**
248 * Tests a GET of a single application.
249 */
250 @Test
251 public void getSingleApplication() {
252 replay(service);
253
254 WebResource rs = resource();
255 String response = rs.path("applications/three").get(String.class);
256
Jian Li80cfe452016-01-14 16:04:58 -0800257 JsonObject result = Json.parse(response).asObject();
Ray Milkeyf195b022015-02-03 15:13:11 -0800258 assertThat(result, notNullValue());
259
260 assertThat(result, matchesApp(app3));
261 }
262
263 /**
264 * Tests a DELETE of a single application - this should
265 * attempt to uninstall it.
266 */
267 @Test
268 public void deleteApplication() {
269 service.uninstall(id3);
270 expectLastCall();
271
272 replay(service);
273
274 WebResource rs = resource();
275 rs.path("applications/three").delete();
276 }
277
278 /**
279 * Tests a DELETE of a single active application - this should
280 * attempt to uninstall it.
281 */
282 @Test
283 public void deleteActiveApplication() {
284 service.deactivate(id3);
285 expectLastCall();
286
287 replay(service);
288
289 WebResource rs = resource();
290 rs.path("applications/three/active").delete();
291 }
292
293 /**
294 * Tests a POST operation to the "active" URL. This should attempt to
295 * activate the application.
296 */
297 @Test
298 public void postActiveApplication() {
299 service.activate(id3);
300 expectLastCall();
301
302 replay(service);
303
304 WebResource rs = resource();
305 rs.path("applications/three/active").post();
306 }
307
308 /**
309 * Tests a POST operation. This should attempt to
310 * install the application.
311 */
312 @Test
313 public void postApplication() {
314 expect(service.install(isA(InputStream.class)))
315 .andReturn(app4)
316 .once();
317
318 replay(service);
319
320 ApplicationCodec codec = new ApplicationCodec();
321 String app4Json = codec.encode(app4,
322 new MockCodecContextWithService(service))
323 .asText();
324
325 WebResource rs = resource();
326 String response = rs.path("applications").post(String.class, app4Json);
327
Jian Li80cfe452016-01-14 16:04:58 -0800328 JsonObject result = Json.parse(response).asObject();
Ray Milkeyf195b022015-02-03 15:13:11 -0800329 assertThat(result, notNullValue());
330
331 assertThat(result, matchesApp(app4));
332 }
333}