/* * R Service Bus * * Copyright (c) Copyright of Open Analytics NV, 2010-2015 * * =========================================================================== * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package eu.openanalytics.rsb.component; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.junit.Assert.assertThat; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import java.io.InputStream; import java.net.UnknownHostException; import java.util.Arrays; import java.util.Collections; import java.util.List; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.UriInfo; import org.apache.cxf.jaxrs.ext.multipart.Attachment; import org.apache.cxf.jaxrs.ext.multipart.ContentDisposition; import org.apache.cxf.jaxrs.impl.MetadataMap; import org.apache.cxf.jaxrs.impl.UriBuilderImpl; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.internal.matchers.StartsWith; import org.mockito.runners.MockitoJUnitRunner; import eu.openanalytics.rsb.Constants; import eu.openanalytics.rsb.config.Configuration; import eu.openanalytics.rsb.message.AbstractJob; import eu.openanalytics.rsb.message.MessageDispatcher; import eu.openanalytics.rsb.rest.types.JobToken; /** * @author "OpenAnalytics <rsb.development@openanalytics.eu>" */ @RunWith(MockitoJUnitRunner.class) public class JobsResourceTestCase { private static final String TEST_APP_NAME = "appName"; private JobsResource jobsResource; @Mock private Configuration configuration; @Mock private MessageDispatcher messageDispatcher; @Mock private HttpHeaders httpHeaders; @Mock private UriInfo uriInfo; @Before public void prepareTest() throws UnknownHostException { jobsResource = new JobsResource(); jobsResource.setConfiguration(configuration); jobsResource.setMessageDispatcher(messageDispatcher); } @Test(expected = IllegalArgumentException.class) public void handleBadApplicationName() throws Exception { when(httpHeaders.getRequestHeader(Constants.APPLICATION_NAME_HTTP_HEADER)).thenReturn( Collections.singletonList("_bad:app!$name")); jobsResource.handleXmlFunctionCallJob("fake_xml", httpHeaders, uriInfo); verifyZeroInteractions(messageDispatcher); } @Test public void handleJobWithProtocolOverride() throws Exception { when(httpHeaders.getRequestHeader(Constants.APPLICATION_NAME_HTTP_HEADER)).thenReturn( Collections.singletonList(TEST_APP_NAME)); when(httpHeaders.getRequestHeader(Constants.FORWARDED_PROTOCOL_HTTP_HEADER)).thenReturn( Collections.singletonList("foo")); when(uriInfo.getBaseUriBuilder()).thenReturn(new UriBuilderImpl()); final JobToken jobToken = assertSuccessfullHandling(jobsResource.handleXmlFunctionCallJob("fake_xml", httpHeaders, uriInfo)); assertThat(jobToken.getResultUri(), is(new StartsWith("foo:/"))); } @Test public void handleJsonFunctionCallJob() throws Exception { when(httpHeaders.getRequestHeader(Constants.APPLICATION_NAME_HTTP_HEADER)).thenReturn( Collections.singletonList(TEST_APP_NAME)); when(uriInfo.getBaseUriBuilder()).thenReturn(new UriBuilderImpl()); assertSuccessfullHandling(jobsResource.handleJsonFunctionCallJob("fake_json", httpHeaders, uriInfo)); } @Test public void handleXmlFunctionCallJob() throws Exception { when(httpHeaders.getRequestHeader(Constants.APPLICATION_NAME_HTTP_HEADER)).thenReturn( Collections.singletonList(TEST_APP_NAME)); when(uriInfo.getBaseUriBuilder()).thenReturn(new UriBuilderImpl()); assertSuccessfullHandling(jobsResource.handleXmlFunctionCallJob("fake_xml", httpHeaders, uriInfo)); } @Test(expected = IllegalArgumentException.class) public void handleInvalidZipJob() throws Exception { when(httpHeaders.getRequestHeader(Constants.APPLICATION_NAME_HTTP_HEADER)).thenReturn( Collections.singletonList(TEST_APP_NAME)); when(httpHeaders.getRequestHeaders()).thenReturn(new MetadataMap<String, String>()); when(uriInfo.getBaseUriBuilder()).thenReturn(new UriBuilderImpl()); assertSuccessfullHandling(jobsResource.handleZipJob(getTestDataAsStream("invalid-job-subdir.zip"), httpHeaders, uriInfo)); } @Test public void handleZipJob() throws Exception { when(httpHeaders.getRequestHeader(Constants.APPLICATION_NAME_HTTP_HEADER)).thenReturn( Collections.singletonList(TEST_APP_NAME)); when(httpHeaders.getRequestHeaders()).thenReturn(new MetadataMap<String, String>()); when(uriInfo.getBaseUriBuilder()).thenReturn(new UriBuilderImpl()); assertSuccessfullHandling(jobsResource.handleZipJob(getTestDataAsStream("r-job-sample.zip"), httpHeaders, uriInfo)); } @Test public void handleMultipartFormJob() throws Exception { final Attachment applicationNamePart = mock(Attachment.class); final ContentDisposition applicationContentDisposition = mock(ContentDisposition.class); when(applicationNamePart.getContentDisposition()).thenReturn(applicationContentDisposition); when(applicationContentDisposition.getParameter(eq("name"))).thenReturn( Constants.APPLICATION_NAME_HTTP_HEADER); when(applicationNamePart.getObject(eq(String.class))).thenReturn(TEST_APP_NAME); when(uriInfo.getBaseUriBuilder()).thenReturn(new UriBuilderImpl()); final List<Attachment> parts = Arrays.asList(applicationNamePart); assertSuccessfullHandling(jobsResource.handleMultipartFormJob(parts, httpHeaders, uriInfo)); } private JobToken assertSuccessfullHandling(final Response response) { assertThat(response.getStatus(), is(Status.ACCEPTED.getStatusCode())); final JobToken jobToken = (JobToken) response.getEntity(); assertThat(jobToken, notNullValue()); assertThat(jobToken.getApplicationName(), is(TEST_APP_NAME)); assertThat(jobToken.getJobId(), notNullValue()); assertThat(jobToken.getSubmissionTime(), notNullValue()); assertThat(jobToken.getResultUri(), notNullValue()); assertThat(jobToken.getApplicationResultsUri(), notNullValue()); final ArgumentCaptor<AbstractJob> jobCaptor = ArgumentCaptor.forClass(AbstractJob.class); verify(messageDispatcher).dispatch(jobCaptor.capture()); jobCaptor.getValue().destroy(); return jobToken; } public static InputStream getTestDataAsStream(final String payloadResourceFile) { return Thread.currentThread() .getContextClassLoader() .getResourceAsStream("data/" + payloadResourceFile); } }