blob: 132a739554a6f1df64b88d078eae3b3b76c1aad5 [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
18import java.io.InputStream;
19import java.net.URI;
20import java.util.Optional;
21
22import org.hamcrest.Description;
23import org.hamcrest.TypeSafeMatcher;
24import org.junit.After;
25import org.junit.Before;
26import org.junit.Test;
27import org.onlab.osgi.ServiceDirectory;
28import org.onlab.osgi.TestServiceDirectory;
29import org.onlab.rest.BaseResource;
30import org.onosproject.app.ApplicationAdminService;
31import org.onosproject.app.ApplicationService;
32import org.onosproject.app.ApplicationState;
33import org.onosproject.codec.CodecService;
34import org.onosproject.codec.impl.ApplicationCodec;
35import org.onosproject.codec.impl.CodecManager;
36import org.onosproject.codec.impl.MockCodecContext;
37import org.onosproject.core.Application;
38import org.onosproject.core.ApplicationId;
39import org.onosproject.core.DefaultApplication;
40import org.onosproject.core.DefaultApplicationId;
41import org.onosproject.core.Version;
42
43import com.eclipsesource.json.JsonArray;
44import com.eclipsesource.json.JsonObject;
45import com.google.common.collect.ImmutableSet;
46import com.sun.jersey.api.client.WebResource;
47
48import static org.easymock.EasyMock.createMock;
49import static org.easymock.EasyMock.expect;
50import static org.easymock.EasyMock.expectLastCall;
51import static org.easymock.EasyMock.isA;
52import static org.easymock.EasyMock.replay;
53import static org.easymock.EasyMock.verify;
54import static org.hamcrest.MatcherAssert.assertThat;
55import static org.hamcrest.Matchers.containsString;
56import static org.hamcrest.Matchers.hasSize;
57import static org.hamcrest.Matchers.is;
58import static org.hamcrest.Matchers.notNullValue;
59
60/**
61 * Unit tests for applications REST APIs.
62 */
63
64public 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}