/******************************************************************************* * Copyright (c) 2012-2016 Codenvy, S.A. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Codenvy, S.A. - initial API and implementation *******************************************************************************/ package org.everrest.core.impl; import org.everrest.core.ApplicationContext; import org.everrest.core.DependencySupplier; import org.everrest.core.RequestHandler; import org.everrest.core.ResourceBinder; import org.everrest.core.impl.method.MethodInvokerDecorator; import org.everrest.core.impl.method.MethodInvokerDecoratorFactory; import org.everrest.core.method.MethodInvoker; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; import javax.annotation.PreDestroy; import javax.ws.rs.core.Application; import javax.ws.rs.core.MultivaluedHashMap; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.Response; import java.net.URI; import java.util.concurrent.atomic.AtomicInteger; import static com.google.common.collect.Sets.newHashSet; import static org.everrest.core.ExtHttpHeaders.X_HTTP_METHOD_OVERRIDE; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.mockito.Mockito.RETURNS_DEEP_STUBS; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; public class EverrestProcessorTest { private String httpMethod = "POST"; private URI requestUri = URI.create("http://localhost:8080/servlet/a/b/c"); private URI baseUri = URI.create("http://localhost:8080/servlet"); private MultivaluedMap<String, String> requestHeaders = new MultivaluedHashMap<>(); private RequestHandler requestHandler; private DependencySupplier dependencySupplier; private EverrestConfiguration configuration; private EverrestProcessor everrestProcessor; @Before public void setUp() throws Exception { requestHandler = mock(RequestHandler.class); dependencySupplier = mock(DependencySupplier.class); configuration = mock(EverrestConfiguration.class, RETURNS_DEEP_STUBS); when(configuration.getProperty("org.everrest.core.impl.method.MethodInvokerDecoratorFactory")) .thenReturn(TestMethodInvokerDecoratorFactory.class.getName()); everrestProcessor = new EverrestProcessor(configuration, dependencySupplier, requestHandler, null); } @After public void tearDown() throws Exception { requestHeaders.clear(); } @Test public void processesRequest() throws Exception { ContainerRequest containerRequest = mockContainerRequest(); ContainerResponse containerResponse = mockContainerResponse(); EnvironmentContext environmentContext = mock(EnvironmentContext.class); doAnswer(invocation -> { Response response = mock(Response.class); when(response.getStatus()).thenReturn(200); when(response.getEntity()).thenReturn("foo"); containerResponse.setResponse(response); return null; }).when(requestHandler).handleRequest(containerRequest, containerResponse); everrestProcessor.process(containerRequest, containerResponse, environmentContext); ArgumentCaptor<Response> argumentCaptor = ArgumentCaptor.forClass(Response.class); verify(containerResponse).setResponse(argumentCaptor.capture()); assertEquals(200, argumentCaptor.getValue().getStatus()); assertEquals("foo", argumentCaptor.getValue().getEntity()); } @Test public void setsUpApplicationContextBeforeCallToRequestHandler() throws Exception { ContainerRequest containerRequest = mockContainerRequest(); ContainerResponse containerResponse = mockContainerResponse(); EnvironmentContext environmentContext = mock(EnvironmentContext.class); ApplicationContext[] applicationContextThatRequestHandlerCalledWith = new ApplicationContext[1]; doAnswer(invocation -> { applicationContextThatRequestHandlerCalledWith[0] = ApplicationContext.getCurrent(); return null; }).when(requestHandler).handleRequest(containerRequest, containerResponse); everrestProcessor.process(containerRequest, containerResponse, environmentContext); assertNotNull(applicationContextThatRequestHandlerCalledWith[0]); assertSame(containerRequest, applicationContextThatRequestHandlerCalledWith[0].getContainerRequest()); assertSame(containerResponse, applicationContextThatRequestHandlerCalledWith[0].getContainerResponse()); assertSame(dependencySupplier, applicationContextThatRequestHandlerCalledWith[0].getDependencySupplier()); } @Test public void resetsApplicationContextAlterCallToRequestHandler() throws Exception { ContainerRequest containerRequest = mockContainerRequest(); ContainerResponse containerResponse = mockContainerResponse(); EnvironmentContext environmentContext = mock(EnvironmentContext.class); everrestProcessor.process(containerRequest, containerResponse, environmentContext); ApplicationContext applicationContextAfterCall = ApplicationContext.getCurrent(); assertNull(applicationContextAfterCall); } @Test public void setsUpEnvironmentContextBeforeCallToRequestHandler() throws Exception { ContainerRequest containerRequest = mockContainerRequest(); ContainerResponse containerResponse = mockContainerResponse(); EnvironmentContext environmentContext = mock(EnvironmentContext.class); EnvironmentContext[] environmentContextThatRequestHandlerCalledWith = new EnvironmentContext[1]; doAnswer(invocation -> { environmentContextThatRequestHandlerCalledWith[0] = EnvironmentContext.getCurrent(); return null; }).when(requestHandler).handleRequest(containerRequest, containerResponse); everrestProcessor.process(containerRequest, containerResponse, environmentContext); assertNotNull(environmentContextThatRequestHandlerCalledWith[0]); assertSame(environmentContext, environmentContextThatRequestHandlerCalledWith[0]); } @Test public void resetsEnvironmentContextAlterCallToRequestHandler() throws Exception { ContainerRequest containerRequest = mockContainerRequest(); ContainerResponse containerResponse = mockContainerResponse(); EnvironmentContext environmentContext = mock(EnvironmentContext.class); everrestProcessor.process(containerRequest, containerResponse, environmentContext); EnvironmentContext environmentContextAfterCall = EnvironmentContext.getCurrent(); assertNull(environmentContextAfterCall); } @Test public void overridesHttpMethodWhenXHTTPMethodOverrideHeaderIsSet() throws Exception { when(configuration.isHttpMethodOverride()).thenReturn(true); requestHeaders.putSingle(X_HTTP_METHOD_OVERRIDE, "PUT"); ContainerRequest containerRequest = mockContainerRequest(); ContainerResponse containerResponse = mockContainerResponse(); EnvironmentContext environmentContext = mock(EnvironmentContext.class); everrestProcessor.process(containerRequest, containerResponse, environmentContext); verify(containerRequest).setMethod("PUT"); } @Test public void callsPreDestroyMethodsForSingletonComponentsOnStop() throws Exception { EchoResource resource = new EchoResource(); Application application = mock(Application.class); when(application.getSingletons()).thenReturn(newHashSet(resource)); when(requestHandler.getResources()).thenReturn(mock(ResourceBinder.class)); everrestProcessor.addApplication(application); everrestProcessor.stop(); assertEquals(1, resource.preDestroyActionInvocationsCounter.get()); } private ContainerRequest mockContainerRequest() { ContainerRequest containerRequest = mock(ContainerRequest.class); when(containerRequest.getBaseUri()).thenReturn(baseUri); when(containerRequest.getRequestUri()).thenReturn(requestUri); when(containerRequest.getMethod()).thenReturn(httpMethod); when(containerRequest.getRequestHeaders()).thenReturn(requestHeaders); return containerRequest; } private ContainerResponse mockContainerResponse() { ContainerResponse containerResponse = mock(ContainerResponse.class); when(containerResponse.getHttpHeaders()).thenReturn(new MultivaluedHashMap<>()); return containerResponse; } public static class TestMethodInvokerDecoratorFactory implements MethodInvokerDecoratorFactory { @Override public MethodInvokerDecorator makeDecorator(MethodInvoker invoker) { return mock(MethodInvokerDecorator.class); } } public static class EchoResource { public String echo(String phrase) { return phrase; } private AtomicInteger preDestroyActionInvocationsCounter = new AtomicInteger(); @PreDestroy private void preDestroyAction() { preDestroyActionInvocationsCounter.incrementAndGet(); } } }