blob: 3e72f18db7ab298dec8ee72f1fd3a3af88652e9e [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
Thomas Vachuskaebf5e542015-02-03 19:38:13 -080018import com.eclipsesource.json.JsonArray;
19import com.eclipsesource.json.JsonObject;
20import com.google.common.collect.ImmutableList;
21import com.google.common.collect.ImmutableSet;
22import com.sun.jersey.api.client.WebResource;
Ray Milkeyf195b022015-02-03 15:13:11 -080023import org.hamcrest.Description;
24import org.hamcrest.TypeSafeMatcher;
25import org.junit.After;
26import org.junit.Before;
27import org.junit.Test;
28import org.onlab.osgi.ServiceDirectory;
29import org.onlab.osgi.TestServiceDirectory;
30import org.onlab.rest.BaseResource;
31import org.onosproject.app.ApplicationAdminService;
32import org.onosproject.app.ApplicationService;
33import org.onosproject.app.ApplicationState;
34import org.onosproject.codec.CodecService;
35import org.onosproject.codec.impl.ApplicationCodec;
36import org.onosproject.codec.impl.CodecManager;
37import org.onosproject.codec.impl.MockCodecContext;
38import org.onosproject.core.Application;
39import org.onosproject.core.ApplicationId;
Changhoon Yoonbdeb88a2015-05-12 20:35:31 +090040import org.onosproject.core.ApplicationRole;
Ray Milkeyf195b022015-02-03 15:13:11 -080041import org.onosproject.core.DefaultApplication;
42import org.onosproject.core.DefaultApplicationId;
43import org.onosproject.core.Version;
44
Thomas Vachuskaebf5e542015-02-03 19:38:13 -080045import java.io.InputStream;
46import java.net.URI;
47import java.util.Optional;
Ray Milkeyf195b022015-02-03 15:13:11 -080048
Thomas Vachuskaebf5e542015-02-03 19:38:13 -080049import static org.easymock.EasyMock.*;
Ray Milkeyf195b022015-02-03 15:13:11 -080050import static org.hamcrest.MatcherAssert.assertThat;
Yuta HIGUCHI293ede02015-02-05 00:08:41 -080051import static org.hamcrest.Matchers.containsString;
52import static org.hamcrest.Matchers.hasSize;
53import static org.hamcrest.Matchers.is;
54import static org.hamcrest.Matchers.notNullValue;
Ray Milkeyf195b022015-02-03 15:13:11 -080055
56/**
57 * Unit tests for applications REST APIs.
58 */
59
60public class ApplicationsResourceTest extends ResourceTest {
61
62 private static class MockCodecContextWithService extends MockCodecContext {
63 private ApplicationAdminService service;
64
65 MockCodecContextWithService(ApplicationAdminService service) {
66 this.service = service;
67 }
68
69 @Override
70 @SuppressWarnings("unchecked")
Ray Milkey3078fc02015-05-06 16:14:14 -070071 public <T> T getService(Class<T> serviceClass) {
Ray Milkeyf195b022015-02-03 15:13:11 -080072 return (T) service;
73 }
74 }
75
76 private ApplicationAdminService service;
77 private ApplicationId id1 = new DefaultApplicationId(1, "app1");
78 private ApplicationId id2 = new DefaultApplicationId(2, "app2");
79 private ApplicationId id3 = new DefaultApplicationId(3, "app3");
80 private ApplicationId id4 = new DefaultApplicationId(4, "app4");
81
82 private static final URI FURL = URI.create("mvn:org.foo-features/1.2a/xml/features");
83 private static final Version VER = Version.version(1, 2, "a", null);
84
85 private Application app1 =
86 new DefaultApplication(id1, VER,
Changhoon Yoonbdeb88a2015-05-12 20:35:31 +090087 "app1", "origin1", ApplicationRole.ADMIN, ImmutableSet.of(), Optional.of(FURL),
Thomas Vachuska761f0042015-11-11 19:10:17 -080088 ImmutableList.of("My Feature"), ImmutableList.of());
Ray Milkeyf195b022015-02-03 15:13:11 -080089 private Application app2 =
90 new DefaultApplication(id2, VER,
Changhoon Yoonbdeb88a2015-05-12 20:35:31 +090091 "app2", "origin2", ApplicationRole.ADMIN, ImmutableSet.of(), Optional.of(FURL),
Thomas Vachuska761f0042015-11-11 19:10:17 -080092 ImmutableList.of("My Feature"), ImmutableList.of());
Ray Milkeyf195b022015-02-03 15:13:11 -080093 private Application app3 =
94 new DefaultApplication(id3, VER,
Changhoon Yoonbdeb88a2015-05-12 20:35:31 +090095 "app3", "origin3", ApplicationRole.ADMIN, ImmutableSet.of(), Optional.of(FURL),
Thomas Vachuska761f0042015-11-11 19:10:17 -080096 ImmutableList.of("My Feature"), ImmutableList.of());
Ray Milkeyf195b022015-02-03 15:13:11 -080097 private Application app4 =
98 new DefaultApplication(id4, VER,
Changhoon Yoonbdeb88a2015-05-12 20:35:31 +090099 "app4", "origin4", ApplicationRole.ADMIN, ImmutableSet.of(), Optional.of(FURL),
Thomas Vachuska761f0042015-11-11 19:10:17 -0800100 ImmutableList.of("My Feature"), ImmutableList.of());
Ray Milkeyf195b022015-02-03 15:13:11 -0800101
102 /**
Ray Milkeyed0b1662015-02-05 09:34:29 -0800103 * Hamcrest matcher to check that an application representation in JSON matches
Ray Milkeyf195b022015-02-03 15:13:11 -0800104 * the actual device.
105 */
106 private static class AppJsonMatcher extends TypeSafeMatcher<JsonObject> {
107 private final Application app;
108 private String reason = "";
109
110 public AppJsonMatcher(Application appValue) {
111 app = appValue;
112 }
113
114 @Override
115 public boolean matchesSafely(JsonObject jsonApp) {
116 // check id
117 short jsonId = (short) jsonApp.get("id").asInt();
118 if (jsonId != app.id().id()) {
119 reason = "id " + app.id().id();
120 return false;
121 }
122
123 // check name
124 String jsonName = jsonApp.get("name").asString();
125 if (!jsonName.equals(app.id().name())) {
126 reason = "name " + app.id().name();
127 return false;
128 }
129
130 // check origin
131 String jsonOrigin = jsonApp.get("origin").asString();
132 if (!jsonOrigin.equals(app.origin())) {
133 reason = "manufacturer " + app.origin();
134 return false;
135 }
136
137 return true;
138 }
139
140 @Override
141 public void describeTo(Description description) {
142 description.appendText(reason);
143 }
144 }
145
146 /**
Ray Milkeyed0b1662015-02-05 09:34:29 -0800147 * Factory to allocate an application matcher.
Ray Milkeyf195b022015-02-03 15:13:11 -0800148 *
149 * @param app application object we are looking for
150 * @return matcher
151 */
152 private static AppJsonMatcher matchesApp(Application app) {
153 return new AppJsonMatcher(app);
154 }
155
Ray Milkeyed0b1662015-02-05 09:34:29 -0800156 /**
157 * Initializes test mocks and environment.
158 */
Ray Milkeyf195b022015-02-03 15:13:11 -0800159 @Before
Ray Milkeyed0b1662015-02-05 09:34:29 -0800160 public void setUpMocks() {
Ray Milkeyf195b022015-02-03 15:13:11 -0800161 service = createMock(ApplicationAdminService.class);
162
163 expect(service.getId("one"))
164 .andReturn(id1)
165 .anyTimes();
166 expect(service.getId("two"))
167 .andReturn(id2)
168 .anyTimes();
169 expect(service.getId("three"))
170 .andReturn(id3)
171 .anyTimes();
172 expect(service.getId("four"))
173 .andReturn(id4)
174 .anyTimes();
175
176 expect(service.getApplication(id3))
177 .andReturn(app3)
178 .anyTimes();
179 expect(service.getState(isA(ApplicationId.class)))
180 .andReturn(ApplicationState.ACTIVE)
181 .anyTimes();
182
183 // Register the services needed for the test
184 CodecManager codecService = new CodecManager();
185 codecService.activate();
186 ServiceDirectory testDirectory =
187 new TestServiceDirectory()
188 .add(ApplicationAdminService.class, service)
189 .add(ApplicationService.class, service)
190 .add(CodecService.class, codecService);
191
192 BaseResource.setServiceDirectory(testDirectory);
193 }
194
Ray Milkeyed0b1662015-02-05 09:34:29 -0800195 /**
196 * Verifies test mocks.
197 */
Ray Milkeyf195b022015-02-03 15:13:11 -0800198 @After
Ray Milkeyed0b1662015-02-05 09:34:29 -0800199 public void tearDownMocks() {
Ray Milkeyf195b022015-02-03 15:13:11 -0800200 verify(service);
201 }
202
203 /**
204 * Tests a GET of all applications when no applications are present.
205 */
206 @Test
207 public void getAllApplicationsEmpty() {
208 expect(service.getApplications())
209 .andReturn(ImmutableSet.of());
210 replay(service);
211
212 WebResource rs = resource();
213 String response = rs.path("applications").get(String.class);
214 assertThat(response, is("{\"applications\":[]}"));
215 }
216
217 /**
218 * Tests a GET of all applications with data.
219 */
220 @Test
221 public void getAllApplicationsPopulated() {
222 expect(service.getApplications())
223 .andReturn(ImmutableSet.of(app1, app2, app3, app4));
224 replay(service);
225
226 WebResource rs = resource();
227 String response = rs.path("applications").get(String.class);
228 assertThat(response, containsString("{\"applications\":["));
229
230 JsonObject result = JsonObject.readFrom(response);
231 assertThat(result, notNullValue());
232
233 assertThat(result.names(), hasSize(1));
234 assertThat(result.names().get(0), is("applications"));
235
236 JsonArray jsonApps = result.get("applications").asArray();
237 assertThat(jsonApps, notNullValue());
238 assertThat(jsonApps.size(), is(4));
239
240 assertThat(jsonApps.get(0).asObject(), matchesApp(app1));
241 assertThat(jsonApps.get(1).asObject(), matchesApp(app2));
242 assertThat(jsonApps.get(2).asObject(), matchesApp(app3));
243 assertThat(jsonApps.get(3).asObject(), matchesApp(app4));
244 }
245
246 /**
247 * Tests a GET of a single application.
248 */
249 @Test
250 public void getSingleApplication() {
251 replay(service);
252
253 WebResource rs = resource();
254 String response = rs.path("applications/three").get(String.class);
255
256 JsonObject result = JsonObject.readFrom(response);
257 assertThat(result, notNullValue());
258
259 assertThat(result, matchesApp(app3));
260 }
261
262 /**
263 * Tests a DELETE of a single application - this should
264 * attempt to uninstall it.
265 */
266 @Test
267 public void deleteApplication() {
268 service.uninstall(id3);
269 expectLastCall();
270
271 replay(service);
272
273 WebResource rs = resource();
274 rs.path("applications/three").delete();
275 }
276
277 /**
278 * Tests a DELETE of a single active application - this should
279 * attempt to uninstall it.
280 */
281 @Test
282 public void deleteActiveApplication() {
283 service.deactivate(id3);
284 expectLastCall();
285
286 replay(service);
287
288 WebResource rs = resource();
289 rs.path("applications/three/active").delete();
290 }
291
292 /**
293 * Tests a POST operation to the "active" URL. This should attempt to
294 * activate the application.
295 */
296 @Test
297 public void postActiveApplication() {
298 service.activate(id3);
299 expectLastCall();
300
301 replay(service);
302
303 WebResource rs = resource();
304 rs.path("applications/three/active").post();
305 }
306
307 /**
308 * Tests a POST operation. This should attempt to
309 * install the application.
310 */
311 @Test
312 public void postApplication() {
313 expect(service.install(isA(InputStream.class)))
314 .andReturn(app4)
315 .once();
316
317 replay(service);
318
319 ApplicationCodec codec = new ApplicationCodec();
320 String app4Json = codec.encode(app4,
321 new MockCodecContextWithService(service))
322 .asText();
323
324 WebResource rs = resource();
325 String response = rs.path("applications").post(String.class, app4Json);
326
327 JsonObject result = JsonObject.readFrom(response);
328 assertThat(result, notNullValue());
329
330 assertThat(result, matchesApp(app4));
331 }
332}