/** * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2015-2019) * * contact.vitam@culture.gouv.fr * * This software is a computer program whose purpose is to implement a digital archiving back-office system managing * high volumetry securely and efficiently. * * This software is governed by the CeCILL 2.1 license under French law and abiding by the rules of distribution of free * software. You can use, modify and/ or redistribute the software under the terms of the CeCILL 2.1 license as * circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". * * As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, * users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the * successive licensors have only limited liability. * * In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or * developing or reproducing the software by the user in light of its specific status of free software, that may mean * that it is complicated to manipulate, and that also therefore means that it is reserved for developers and * experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the * software's suitability as regards their requirements in conditions enabling the security of their systems and/or data * to be ensured and, more generally, to use and operate it in the same conditions as regards security. * * The fact that you are presently reading this means that you have had knowledge of the CeCILL 2.1 license and that you * accept its terms. */ package fr.gouv.vitam.common.server.application.junit; import static org.mockito.Mockito.mock; import javax.ws.rs.core.Response; import org.junit.After; import org.junit.Before; import fr.gouv.vitam.common.client.MockOrRestClient; import fr.gouv.vitam.common.client.VitamClientFactoryInterface; import fr.gouv.vitam.common.client.configuration.ClientConfiguration; import fr.gouv.vitam.common.exception.VitamApplicationServerException; import fr.gouv.vitam.common.junit.JunitHelper; import fr.gouv.vitam.common.junit.VitamApplicationTestFactory; import fr.gouv.vitam.common.server.application.VitamApplicationInterface; /** * Class to extend for Junit as JerseyTest. </br> * * @param <A> Application class </br> * <P> * What is already implemented: * <ul> * <li>A mocked ExpectedResults interface</li> * <li>The start and stop of the application at each run</li> * <li>_client containing MockOrRestClient interface that will be closed at each run</li> * <li>The reservation and free of network port through JunitHelper used to start the application (the port is * accessible through getServerPort() method)</li> * </ul> * </br> * You must implement the following: * <ul> * <li>_getClient() method that returns the client to use and close at each run</li> * <li>setup() method (for instance to set your own mock if default one is not enough)</li> * <li>startVitamApplication(int reservedPort) to create the application and starting it (method * application.start()) using the reserved port</li> * <li>Define your own Application class (to register your own Resource) based on AbstractVitamApplication</li> * <li>Define your own ApplicationConfiguration (or simply extend DefaultVitamApplicationConfiguration)</li> * </ul> * You may implement: * <ul> * <li>Your own Mock</li> * </ul> * Example: * * <pre> * <code> * public class MyClientTest extends VitamJerseyTest { * private static final String RESOURCE_PATH = "..."; * // You own factory * TestVitamClientFactory<TestClient> factory = * new TestVitamClientFactory<TestClient>(8080, RESOURCE_PATH); * // Store your own client * TestClient client; * * // ************************************** // * // Start of VitamJerseyTest configuration // * // ************************************** // * // Override the beforeTest if necessary (not mandatory) * @Override * public void beforeTest() throws VitamApplicationServerException { * // anything before test * } * * // Override the afterTest if necessary (not mandatory) * @Override * public void afterTest() throws VitamApplicationServerException { * // anything after test * } * * // This method MUST be created. Assign your own client (keep it) and returns it. * @Override * protected MockOrRestClient _getClient() throws VitamApplicationServerException { * try { * // Fix your factory * factory.changeServerPort(getServerPort()); * client = factory.getClient(); * return client; * } catch (final VitamClientException e) { * throw new VitamApplicationServerException(e); * } * } * * // Setup test to setup anything if necessary (not mandatory) * @Override * public void setup() { * // nothing * } * * // Define the getApplication to return your Application using the correct Configuration * @Override * public StartApplicationResponse<AbstractApplication> startVitamApplication(int reservedPort) { * // Use your own ApplicationConfiguration if necessary, or just copy the following * final TestVitamApplicationConfiguration configuration = * new TestVitamApplicationConfiguration(); * * // DEFAULT_XML_CONFIGURATION_FILE could be used as default XML file, but you can specify another * configuration.setJettyConfig(DEFAULT_XML_CONFIGURATION_FILE); * * // Use your own application or just copy the following * final AbstractApplication application = new AbstractApplication(configuration); * // Start the application (mandatory) * try { * application.start(); * } catch (final VitamApplicationServerException e) { * SysErrLogger.FAKE_LOGGER.ignoreLog(e); * throw new IllegalStateException("Cannot start the application", e); * } * // Return the response as follow * return new StartApplicationResponse<AbstractApplication>() * .setServerPort(application.getVitamServer().getPort()) * .setApplication(application); * } * * // Define your Application class (or reuse it), in particular set your own MockResources or just copy the following * public final class AbstractApplication * extends AbstractVitamApplication<AbstractApplication, TestVitamApplicationConfiguration> { * protected AbstractApplication(TestVitamApplicationConfiguration configuration) { * super(TestVitamApplicationConfiguration.class, configuration); * } * * @Override * protected void registerInResourceConfig(ResourceConfig resourceConfig) { * resourceConfig.registerInstances(new MockResource(mock)); * } * } * * // Define your Configuration class (or reuse it) or just copy the following * public static class TestVitamApplicationConfiguration extends DefaultVitamApplicationConfiguration { * // Empty for this example * } * * // Define your Resource class * @Path(RESOURCE_PATH) * public static class MockResource extends ApplicationStatusResource { * private final ExpectedResults expectedResponse; * * public MockResource(ExpectedResults expectedResponse) { * this.expectedResponse = expectedResponse; * } * ... * } * // ************************************ // * // End of VitamJerseyTest configuration // * // ************************************ // * * // Use client to act on AbstractApplication * * }</code> * </pre> * </P> */ public abstract class VitamJerseyTest<A> implements VitamApplicationTestFactory<A> { /** * Default XML Configuration to use (from JunitHelper) */ public static final String DEFAULT_XML_CONFIGURATION_FILE = "jetty-config-base-test.xml"; /** * Localhost */ public static final String HOSTNAME = "localhost"; private final StartApplicationResponse<A> response; final MockOrRestClient _client; final VitamClientFactoryInterface<?> factory; protected ExpectedResults mock; /** * Default ExpectedResults */ public interface ExpectedResults { /** * * @return Mock Response */ Response post(); /** * * @return Mock Response */ Response get(); /** * * @return Mock Response */ Response put(); /** * * @return Mock Response */ Response delete(); /** * * @return Mock Response */ Response head(); /** * * @return Mock Response */ Response options(); } /** * Create the VitamJerseyTest, calling setup first.</br> * Note: will call factory.changeServerPort(getServerPort()) automatically before creating the client. * * @param factory the Client Factory to use * * @throws VitamApplicationServerException * * @throws IllegalStateException if the start is incorrect */ @SuppressWarnings("unchecked") public VitamJerseyTest(VitamClientFactoryInterface<?> factory) { mock = mock(ExpectedResults.class); this.factory = factory; final ClientConfiguration clientConfiguration = this.factory.getClientConfiguration(); if (clientConfiguration != null) { clientConfiguration.setServerHost(HOSTNAME); } setup(); response = (StartApplicationResponse<A>) JunitHelper.getInstance().findAvailablePortSetToApplication(this); factory.changeServerPort(getServerPort()); _client = factory.getClient(); } /** * * @return the factory to use */ public VitamClientFactoryInterface<?> getFactory() { return factory; } /** * * @return the client using the factory */ public MockOrRestClient getClient() { return _client; } /** * Do anything necessary before starting the application and before getting the server port. Called before * startVitamApplication and _getClient() */ public void setup() { // Default do nothing more } /** * * @return the current port */ public final int getServerPort() { return response.getServerPort(); } /** * * @return the current application */ public final VitamApplicationInterface<?, ?> getApplication() { return (VitamApplicationInterface<?, ?>) response.getApplication(); } /** * Start the Application. * * @throws VitamApplicationServerException */ @Before public final void startTest() throws VitamApplicationServerException { beforeTest(); } /** * To be extended if necessary (equivalent to @Before) * * @throws VitamApplicationServerException */ public void beforeTest() throws VitamApplicationServerException { // Empty } /** * End the application only * @throws VitamApplicationServerException */ public final void endApplication() throws VitamApplicationServerException { if (response.getApplication() != null) { ((VitamApplicationInterface<?, ?>) response.getApplication()).stop(); } } /** * End the Application. * * @throws VitamApplicationServerException */ @After public final void endTest() throws VitamApplicationServerException { endApplication(); JunitHelper.getInstance().releasePort(response.getServerPort()); if (_client != null) { _client.close(); } afterTest(); } /** * To be extended if necessary (equivalent to @After) * * @throws VitamApplicationServerException */ public void afterTest() throws VitamApplicationServerException { // Empty } }