/* * Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com * The software in this package is published under the terms of the CPAL v1.0 * license, a copy of which has been included with this distribution in the * LICENSE.txt file. */ package org.mule.runtime.module.embedded; import static com.mashape.unirest.http.Unirest.post; import static java.lang.String.valueOf; import static java.lang.Thread.sleep; import static java.nio.file.Files.delete; import static java.util.Collections.emptyMap; import static java.util.Collections.singletonList; import static java.util.Optional.empty; import static java.util.Optional.of; import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertThat; import static org.mule.maven.client.api.model.MavenConfiguration.newMavenConfigurationBuilder; import static org.mule.maven.client.api.model.RemoteRepository.newRemoteRepositoryBuilder; import static org.mule.runtime.api.deployment.management.ComponentInitialStateManager.DISABLE_SCHEDULER_SOURCES_PROPERTY; import static org.mule.runtime.core.util.UUID.getUUID; import static org.mule.runtime.module.embedded.api.EmbeddedContainer.builder; import static org.mule.tck.MuleTestUtils.testWithSystemProperty; import static org.mule.test.allure.AllureConstants.DeploymentTypeFeature.DEPLOYMENT_TYPE; import static org.mule.test.allure.AllureConstants.DeploymentTypeFeature.DeploymentTypeStory.EMBEDDED; import static org.mule.test.allure.AllureConstants.EmbeddedApiFeature.EMBEDDED_API; import static org.mule.test.allure.AllureConstants.EmbeddedApiFeature.EmbeddedApiStory.CONFIGURATION; import static org.slf4j.LoggerFactory.getLogger; import org.mule.maven.client.api.MavenClientProvider; import org.mule.runtime.module.embedded.api.Application; import org.mule.runtime.module.embedded.api.ApplicationConfiguration; import org.mule.runtime.module.embedded.api.DeploymentConfiguration; import org.mule.runtime.module.embedded.api.EmbeddedContainer; import org.mule.tck.junit4.AbstractMuleTestCase; import org.mule.tck.junit4.rule.FreePortFinder; import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.exceptions.UnirestException; import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.nio.file.Paths; import java.util.HashMap; import java.util.Map; import java.util.Optional; import java.util.function.Consumer; import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.slf4j.Logger; import ru.yandex.qatools.allure.annotations.Description; import ru.yandex.qatools.allure.annotations.Features; import ru.yandex.qatools.allure.annotations.Stories; @Features({EMBEDDED_API, DEPLOYMENT_TYPE}) @Stories({CONFIGURATION, EMBEDDED}) public class EmbeddedContainerTestCase extends AbstractMuleTestCase { private static final String LOGGING_FILE = "app.log"; private static final Logger LOGGER = getLogger(EmbeddedContainerTestCase.class); @ClassRule public static TemporaryFolder localRepositoryFolder = new TemporaryFolder(); @Rule public TemporaryFolder containerFolder = new TemporaryFolder(); @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder(); @Description("Embedded runs an application depending on a connector") @Test public void applicationWithConnector() throws Exception { doWithinApplication("http-echo", port -> { try { String httpBody = "test-message"; HttpResponse<String> response = post(String.format("http://localhost:%s/", port)).body(httpBody).asString(); assertThat(response.getBody(), is(httpBody)); } catch (UnirestException e) { throw new RuntimeException(e); } }, emptyMap()); } @Description("Embedded runs an application using test dependencies") @Test public void applicationWithTestDependency() throws Exception { doWithinApplication("http-test-dependency", port -> { try { String httpBody = "org.mobicents.xcap.client.impl.XcapClientImpl"; HttpResponse<String> response = post(String.format("http://localhost:%s/", port)).body(httpBody).asString(); assertThat(response.getBody(), is(httpBody)); } catch (UnirestException e) { throw new RuntimeException(e); } }, true, emptyMap(), empty()); } @Description("Embedded runs an application with scheduler not started by using the " + DISABLE_SCHEDULER_SOURCES_PROPERTY + " property in the mule-artifact.properties file") @Test public void applicationWithSchedulersStoppedByDefaultUsingApplicationProperties() throws Exception { HashMap<String, String> applicationProperties = new HashMap<>(); File fileWriteFolder = temporaryFolder.newFolder(); File fileWriteDestination = new File(fileWriteFolder, getUUID()); applicationProperties.put("file.path", fileWriteDestination.getAbsolutePath()); applicationProperties.put(DISABLE_SCHEDULER_SOURCES_PROPERTY, "true"); // start and stops the application, the scheduler within it should have been run if started doWithinApplication("scheduler-stopped", port -> { waitForPollToBeExecuted(); }, applicationProperties); assertThat(fileWriteDestination.exists(), is(false)); } @Description("Embedded runs an application with scheduler not started by using the " + DISABLE_SCHEDULER_SOURCES_PROPERTY + " property as system property") @Test public void applicationWithSchedulersStoppedByDefaultUsingSystemProperties() throws Exception { HashMap<String, String> applicationProperties = new HashMap<>(); File fileWriteFolder = temporaryFolder.newFolder(); File fileWriteDestination = new File(fileWriteFolder, getUUID()); applicationProperties.put("file.path", fileWriteDestination.getAbsolutePath()); // start and stops the application, the scheduler within it should have been run if started testWithSystemProperty(DISABLE_SCHEDULER_SOURCES_PROPERTY, "true", () -> { doWithinApplication("scheduler-stopped", port -> { waitForPollToBeExecuted(); }, applicationProperties); }); assertThat(fileWriteDestination.exists(), is(false)); } @Description("Embedded runs an application using a custom log4j configuration file") @Test public void applicationWithCustomLogger() throws Exception { doWithinApplication("http-echo", port -> { try { String httpBody = "test-message"; HttpResponse<String> response = post(String.format("http://localhost:%s/", port)).body(httpBody).asString(); assertThat(response.getBody(), is(httpBody)); } catch (UnirestException e) { throw new RuntimeException(e); } }, false, emptyMap(), of(getClass().getClassLoader().getResource("log4j2-custom-file.xml").getFile())); try { File expectedLoggingFile = new File(LOGGING_FILE); assertThat(expectedLoggingFile.exists(), is(true)); assertThat(expectedLoggingFile.length(), greaterThan(0l)); } finally { delete(Paths.get(LOGGING_FILE)); } } private void waitForPollToBeExecuted() { try { sleep(200); } catch (InterruptedException e) { // do nothing } } private void doWithinApplication(String applicaitonFolder, Consumer<Integer> portConsumer, Map<String, String> applicationProperties) throws URISyntaxException, IOException { doWithinApplication(applicaitonFolder, portConsumer, false, applicationProperties, empty()); } private void doWithinApplication(String applicaitonFolder, Consumer<Integer> portConsumer, boolean enableTestDependencies, Map<String, String> applicationProperties, Optional<String> log4JConfigurationFileOptional) throws URISyntaxException, IOException { Map<String, String> customizedApplicationProperties = new HashMap<>(applicationProperties); Integer httpListenerPort = new FreePortFinder(6000, 9000).find(); customizedApplicationProperties.put("httpPort", valueOf(httpListenerPort)); Application application = new Application( singletonList(getClasspathResourceAsUri(applicaitonFolder + File.separator + "mule-config.xml")), null, getClasspathResourceAsUri(applicaitonFolder + File.separator + "pom.xml").toURL(), getClasspathResourceAsUri(applicaitonFolder + File.separator + "mule-application.json").toURL()); File localRepositoryLocation = localRepositoryFolder.getRoot(); localRepositoryLocation = MavenClientProvider.discoverProvider(getClass().getClassLoader()) .getLocalRepositorySuppliers().environmentMavenRepositorySupplier().get(); LOGGER.info("Using folder as local repository: " + localRepositoryLocation.getAbsolutePath()); EmbeddedContainer embeddedContainer = builder() .withMuleVersion("4.0.0-SNAPSHOT") .withContainerBaseFolder(containerFolder.newFolder().toURI().toURL()) .withMavenConfiguration(newMavenConfigurationBuilder() .withLocalMavenRepositoryLocation(localRepositoryLocation) .withRemoteRepository(newRemoteRepositoryBuilder().withId("mulesoft-public") .withUrl(new URL("https://repository.mulesoft.org/nexus/content/repositories/public")) .build()) .build()) .withLog4jConfigurationFile(log4JConfigurationFileOptional .orElse(getClass().getClassLoader().getResource("log4j2-default.xml").getFile())) .withApplicationConfiguration(ApplicationConfiguration.builder() .withApplication(application) .withDeploymentConfiguration(DeploymentConfiguration.builder() .withTestDependenciesEnabled(enableTestDependencies) .withArtifactProperties(customizedApplicationProperties) .build()) .build()) .build(); embeddedContainer.start(); try { portConsumer.accept(httpListenerPort); } finally { embeddedContainer.stop(); } } private URI getClasspathResourceAsUri(String resource) throws URISyntaxException { return getClass().getClassLoader().getResource(resource).toURI(); } @Override public int getTestTimeoutSecs() { return 20 * super.getTestTimeoutSecs(); } }