/* * Copyright 2015 Open Networking Laboratory * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.onosproject.rest; import com.eclipsesource.json.JsonArray; import com.eclipsesource.json.JsonObject; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.sun.jersey.api.client.WebResource; import org.hamcrest.Description; import org.hamcrest.TypeSafeMatcher; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.onlab.osgi.ServiceDirectory; import org.onlab.osgi.TestServiceDirectory; import org.onlab.rest.BaseResource; import org.onosproject.app.ApplicationAdminService; import org.onosproject.app.ApplicationService; import org.onosproject.app.ApplicationState; import org.onosproject.codec.CodecService; import org.onosproject.codec.impl.ApplicationCodec; import org.onosproject.codec.impl.CodecManager; import org.onosproject.codec.impl.MockCodecContext; import org.onosproject.core.Application; import org.onosproject.core.ApplicationId; import org.onosproject.core.ApplicationRole; import org.onosproject.core.DefaultApplication; import org.onosproject.core.DefaultApplicationId; import org.onosproject.core.Version; import java.io.InputStream; import java.net.URI; import java.util.Optional; import static org.easymock.EasyMock.*; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; /** * Unit tests for applications REST APIs. */ public class ApplicationsResourceTest extends ResourceTest { private static class MockCodecContextWithService extends MockCodecContext { private ApplicationAdminService service; MockCodecContextWithService(ApplicationAdminService service) { this.service = service; } @Override @SuppressWarnings("unchecked") public T getService(Class serviceClass) { return (T) service; } } private ApplicationAdminService service; private ApplicationId id1 = new DefaultApplicationId(1, "app1"); private ApplicationId id2 = new DefaultApplicationId(2, "app2"); private ApplicationId id3 = new DefaultApplicationId(3, "app3"); private ApplicationId id4 = new DefaultApplicationId(4, "app4"); private static final URI FURL = URI.create("mvn:org.foo-features/1.2a/xml/features"); private static final Version VER = Version.version(1, 2, "a", null); private Application app1 = new DefaultApplication(id1, VER, "app1", "origin1", ApplicationRole.ADMIN, ImmutableSet.of(), Optional.of(FURL), ImmutableList.of("My Feature"), ImmutableList.of()); private Application app2 = new DefaultApplication(id2, VER, "app2", "origin2", ApplicationRole.ADMIN, ImmutableSet.of(), Optional.of(FURL), ImmutableList.of("My Feature"), ImmutableList.of()); private Application app3 = new DefaultApplication(id3, VER, "app3", "origin3", ApplicationRole.ADMIN, ImmutableSet.of(), Optional.of(FURL), ImmutableList.of("My Feature"), ImmutableList.of()); private Application app4 = new DefaultApplication(id4, VER, "app4", "origin4", ApplicationRole.ADMIN, ImmutableSet.of(), Optional.of(FURL), ImmutableList.of("My Feature"), ImmutableList.of()); /** * Hamcrest matcher to check that an application representation in JSON matches * the actual device. */ private static class AppJsonMatcher extends TypeSafeMatcher { private final Application app; private String reason = ""; public AppJsonMatcher(Application appValue) { app = appValue; } @Override public boolean matchesSafely(JsonObject jsonApp) { // check id short jsonId = (short) jsonApp.get("id").asInt(); if (jsonId != app.id().id()) { reason = "id " + app.id().id(); return false; } // check name String jsonName = jsonApp.get("name").asString(); if (!jsonName.equals(app.id().name())) { reason = "name " + app.id().name(); return false; } // check origin String jsonOrigin = jsonApp.get("origin").asString(); if (!jsonOrigin.equals(app.origin())) { reason = "manufacturer " + app.origin(); return false; } return true; } @Override public void describeTo(Description description) { description.appendText(reason); } } /** * Factory to allocate an application matcher. * * @param app application object we are looking for * @return matcher */ private static AppJsonMatcher matchesApp(Application app) { return new AppJsonMatcher(app); } /** * Initializes test mocks and environment. */ @Before public void setUpMocks() { service = createMock(ApplicationAdminService.class); expect(service.getId("one")) .andReturn(id1) .anyTimes(); expect(service.getId("two")) .andReturn(id2) .anyTimes(); expect(service.getId("three")) .andReturn(id3) .anyTimes(); expect(service.getId("four")) .andReturn(id4) .anyTimes(); expect(service.getApplication(id3)) .andReturn(app3) .anyTimes(); expect(service.getState(isA(ApplicationId.class))) .andReturn(ApplicationState.ACTIVE) .anyTimes(); // Register the services needed for the test CodecManager codecService = new CodecManager(); codecService.activate(); ServiceDirectory testDirectory = new TestServiceDirectory() .add(ApplicationAdminService.class, service) .add(ApplicationService.class, service) .add(CodecService.class, codecService); BaseResource.setServiceDirectory(testDirectory); } /** * Verifies test mocks. */ @After public void tearDownMocks() { verify(service); } /** * Tests a GET of all applications when no applications are present. */ @Test public void getAllApplicationsEmpty() { expect(service.getApplications()) .andReturn(ImmutableSet.of()); replay(service); WebResource rs = resource(); String response = rs.path("applications").get(String.class); assertThat(response, is("{\"applications\":[]}")); } /** * Tests a GET of all applications with data. */ @Test public void getAllApplicationsPopulated() { expect(service.getApplications()) .andReturn(ImmutableSet.of(app1, app2, app3, app4)); replay(service); WebResource rs = resource(); String response = rs.path("applications").get(String.class); assertThat(response, containsString("{\"applications\":[")); JsonObject result = JsonObject.readFrom(response); assertThat(result, notNullValue()); assertThat(result.names(), hasSize(1)); assertThat(result.names().get(0), is("applications")); JsonArray jsonApps = result.get("applications").asArray(); assertThat(jsonApps, notNullValue()); assertThat(jsonApps.size(), is(4)); assertThat(jsonApps.get(0).asObject(), matchesApp(app1)); assertThat(jsonApps.get(1).asObject(), matchesApp(app2)); assertThat(jsonApps.get(2).asObject(), matchesApp(app3)); assertThat(jsonApps.get(3).asObject(), matchesApp(app4)); } /** * Tests a GET of a single application. */ @Test public void getSingleApplication() { replay(service); WebResource rs = resource(); String response = rs.path("applications/three").get(String.class); JsonObject result = JsonObject.readFrom(response); assertThat(result, notNullValue()); assertThat(result, matchesApp(app3)); } /** * Tests a DELETE of a single application - this should * attempt to uninstall it. */ @Test public void deleteApplication() { service.uninstall(id3); expectLastCall(); replay(service); WebResource rs = resource(); rs.path("applications/three").delete(); } /** * Tests a DELETE of a single active application - this should * attempt to uninstall it. */ @Test public void deleteActiveApplication() { service.deactivate(id3); expectLastCall(); replay(service); WebResource rs = resource(); rs.path("applications/three/active").delete(); } /** * Tests a POST operation to the "active" URL. This should attempt to * activate the application. */ @Test public void postActiveApplication() { service.activate(id3); expectLastCall(); replay(service); WebResource rs = resource(); rs.path("applications/three/active").post(); } /** * Tests a POST operation. This should attempt to * install the application. */ @Test public void postApplication() { expect(service.install(isA(InputStream.class))) .andReturn(app4) .once(); replay(service); ApplicationCodec codec = new ApplicationCodec(); String app4Json = codec.encode(app4, new MockCodecContextWithService(service)) .asText(); WebResource rs = resource(); String response = rs.path("applications").post(String.class, app4Json); JsonObject result = JsonObject.readFrom(response); assertThat(result, notNullValue()); assertThat(result, matchesApp(app4)); } }