/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library 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 Lesser General Public License for more * details. */ package com.liferay.portal.kernel.resiliency.spi.agent; import com.liferay.portal.kernel.process.local.LocalProcessLauncher; import com.liferay.portal.kernel.resiliency.spi.MockSPI; import com.liferay.portal.kernel.resiliency.spi.SPI; import com.liferay.portal.kernel.resiliency.spi.SPIUtil; import com.liferay.portal.kernel.test.CaptureHandler; import com.liferay.portal.kernel.test.JDKLoggerTestUtil; import com.liferay.portal.kernel.test.rule.CodeCoverageAssertor; import com.liferay.portal.kernel.util.PortalUtil; import com.liferay.portal.kernel.util.StringPool; import com.liferay.portal.util.PortalImpl; import java.io.IOException; import java.util.List; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import java.util.logging.Level; import java.util.logging.LogRecord; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.junit.Assert; import org.junit.Before; import org.junit.ClassRule; import org.junit.Test; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.mock.web.MockHttpSession; import org.springframework.mock.web.MockServletConfig; import org.springframework.mock.web.MockServletContext; /** * @author Shuyang Zhou */ public class AcceptorServletTest { @ClassRule public static final CodeCoverageAssertor codeCoverageAssertor = CodeCoverageAssertor.INSTANCE; @Before public void setUp() { PortalUtil portalUtil = new PortalUtil(); portalUtil.setPortal( new PortalImpl() { @Override public String getPathContext() { return _pathContext; } }); ConcurrentMap<String, Object> attributes = LocalProcessLauncher.ProcessContext.getAttributes(); SPI spi = new MockSPI() { @Override public SPIAgent getSPIAgent() { return _recordSPIAgent; } }; attributes.put(SPI.SPI_INSTANCE_PUBLICATION_KEY, spi); Assert.assertSame(spi, SPIUtil.getSPI()); } @Test public void testService() throws IOException, ServletException { // Successfully forward final AtomicBoolean failOnForward = new AtomicBoolean(); final AtomicReference<String> forwardPathReference = new AtomicReference<>(); final IOException ioException = new IOException("Unable to forward"); MockServletContext mockServletContext = new MockServletContext() { @Override public RequestDispatcher getRequestDispatcher(final String path) { return new RequestDispatcher() { @Override public void forward( ServletRequest servletRequest, ServletResponse servletResponse) throws IOException { forwardPathReference.set(path); if (failOnForward.get()) { throw ioException; } } @Override public void include( ServletRequest servletRequest, ServletResponse servletResponse) { } }; } }; mockServletContext.setContextPath("/"); AcceptorServlet acceptorServlet = new AcceptorServlet(); acceptorServlet.init(new MockServletConfig(mockServletContext)); MockHttpServletRequest mockHttpServletRequest = new MockHttpServletRequest(); mockHttpServletRequest.setServerPort(1234); MockHttpServletResponse mockHttpServletResponse = new MockHttpServletResponse(); acceptorServlet.service( mockHttpServletRequest, mockHttpServletResponse); Assert.assertEquals("/c/portal/resiliency", forwardPathReference.get()); Assert.assertSame( mockHttpServletRequest, _recordSPIAgent._originalRequest1); Assert.assertSame( mockHttpServletRequest, _recordSPIAgent._originalRequest2); Assert.assertSame( mockHttpServletResponse, _recordSPIAgent._originalResponse); Assert.assertNull(_recordSPIAgent._exception); Assert.assertTrue(_mockHttpSession.isInvalid()); _pathContext = "/liferay-portal"; mockServletContext.registerContext(_pathContext, mockServletContext); acceptorServlet.service( mockHttpServletRequest, mockHttpServletResponse); Assert.assertEquals("/c/portal/resiliency", forwardPathReference.get()); Assert.assertSame( mockHttpServletRequest, _recordSPIAgent._originalRequest1); Assert.assertSame( mockHttpServletRequest, _recordSPIAgent._originalRequest2); Assert.assertSame( mockHttpServletResponse, _recordSPIAgent._originalResponse); Assert.assertNull(_recordSPIAgent._exception); Assert.assertTrue(_mockHttpSession.isInvalid()); try (CaptureHandler captureHandler = JDKLoggerTestUtil.configureJDKLogger( AcceptorServlet.class.getName(), Level.SEVERE)) { // IOException on prepare request _recordSPIAgent.setIOExceptionOnPrepareRequest(true); List<LogRecord> logRecords = captureHandler.getLogRecords(); try { acceptorServlet.service( mockHttpServletRequest, mockHttpServletResponse); Assert.fail(); } catch (IOException ioe) { Assert.assertEquals( "IOException on prepare request", ioe.getMessage()); } Assert.assertEquals(logRecords.toString(), 1, logRecords.size()); LogRecord logRecord = logRecords.get(0); Throwable throwable = logRecord.getThrown(); Assert.assertSame(IOException.class, throwable.getClass()); Assert.assertEquals( "IOException on prepare request", throwable.getMessage()); // RuntimeException on prepare request _recordSPIAgent.setIOExceptionOnPrepareRequest(false); _recordSPIAgent.setRuntimeExceptionOnPrepareRequest(true); logRecords = captureHandler.resetLogLevel(Level.SEVERE); try { acceptorServlet.service( mockHttpServletRequest, mockHttpServletResponse); Assert.fail(); } catch (RuntimeException re) { Assert.assertEquals( "RuntimeException on prepare request", re.getMessage()); } Assert.assertEquals(logRecords.toString(), 1, logRecords.size()); logRecord = logRecords.get(0); throwable = logRecord.getThrown(); Assert.assertSame(RuntimeException.class, throwable.getClass()); Assert.assertEquals( "RuntimeException on prepare request", throwable.getMessage()); } // Unable to forward _recordSPIAgent.setRuntimeExceptionOnPrepareRequest(false); failOnForward.set(true); acceptorServlet.service( mockHttpServletRequest, mockHttpServletResponse); Assert.assertEquals("/c/portal/resiliency", forwardPathReference.get()); Assert.assertSame( mockHttpServletRequest, _recordSPIAgent._originalRequest1); Assert.assertSame( mockHttpServletRequest, _recordSPIAgent._originalRequest2); Assert.assertSame( mockHttpServletResponse, _recordSPIAgent._originalResponse); Assert.assertSame(ioException, _recordSPIAgent._exception); Assert.assertTrue(_mockHttpSession.isInvalid()); } private final MockHttpSession _mockHttpSession = new MockHttpSession(); private String _pathContext = StringPool.BLANK; private final RecordSPIAgent _recordSPIAgent = new RecordSPIAgent(); private class RecordSPIAgent extends MockSPIAgent { public RecordSPIAgent() { super(null, null); } @Override public HttpServletRequest prepareRequest(HttpServletRequest request) throws IOException { if (_ioExceptionOnPrepareRequest) { throw new IOException("IOException on prepare request"); } if (_runtimeExceptionOnPrepareRequest) { throw new RuntimeException( "RuntimeException on prepare request"); } _originalRequest1 = request; _preparedRequest = new MockHttpServletRequest(); _preparedRequest.setSession(_mockHttpSession); return _preparedRequest; } @Override public HttpServletResponse prepareResponse( HttpServletRequest request, HttpServletResponse response) { _originalRequest2 = request; _originalResponse = response; _preparedResponse = new MockHttpServletResponse(); return _preparedResponse; } public void setIOExceptionOnPrepareRequest( boolean ioExceptionOnPrepareRequest) { _ioExceptionOnPrepareRequest = ioExceptionOnPrepareRequest; } public void setRuntimeExceptionOnPrepareRequest( boolean runtimeExceptionOnPrepareRequest) { _runtimeExceptionOnPrepareRequest = runtimeExceptionOnPrepareRequest; } @Override public void transferResponse( HttpServletRequest request, HttpServletResponse response, Exception e) { Assert.assertSame(_preparedRequest, request); Assert.assertSame(_preparedResponse, response); _exception = e; } private Exception _exception; private boolean _ioExceptionOnPrepareRequest; private HttpServletRequest _originalRequest1; private HttpServletRequest _originalRequest2; private HttpServletResponse _originalResponse; private MockHttpServletRequest _preparedRequest; private MockHttpServletResponse _preparedResponse; private boolean _runtimeExceptionOnPrepareRequest; } }