diff --git a/.baseline/findbugs/excludeFilter.xml b/.baseline/findbugs/excludeFilter.xml index 1887223f2..d96c8a012 100644 --- a/.baseline/findbugs/excludeFilter.xml +++ b/.baseline/findbugs/excludeFilter.xml @@ -9,13 +9,14 @@ - + + diff --git a/appveyor.yml b/appveyor.yml index d31b56062..212ec6633 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -7,7 +7,8 @@ build_script: - gradlew.bat compileJava compileTestJava --info --no-daemon test_script: - - gradlew.bat dependencies --info --no-daemon + - cinst -y docker docker-compose + - gradlew.bat test windowsSmokeTest --info --no-daemon branches: only: diff --git a/build.gradle b/build.gradle index 43a25c96b..934aa4a75 100644 --- a/build.gradle +++ b/build.gradle @@ -36,6 +36,7 @@ subprojects { apply plugin: 'com.palantir.baseline-eclipse' apply plugin: 'com.palantir.baseline-findbugs' apply plugin: 'com.palantir.baseline-idea' + apply from: "${rootDir}/gradle/integTest.gradle" apply from: "${rootDir}/gradle/publish.gradle" apply plugin: 'org.inferred.processors' diff --git a/circle.yml b/circle.yml index 995af171f..6433cc320 100644 --- a/circle.yml +++ b/circle.yml @@ -18,7 +18,7 @@ test: override: - ? > case $CIRCLE_NODE_INDEX in - 0) ./gradlew test --info ;; + 0) ./gradlew test integTest --info ;; 1) ./gradlew findbugsMain findbugsTest checkstyleMain checkstyleTest javadoc --info ;; esac : diff --git a/docker-compose-rule-core/build.gradle b/docker-compose-rule-core/build.gradle index 7159dad63..660c561be 100644 --- a/docker-compose-rule-core/build.gradle +++ b/docker-compose-rule-core/build.gradle @@ -5,6 +5,7 @@ dependencies { compile "com.google.guava:guava:$guavaVersion" compile "joda-time:joda-time:$jodaVersion" compile "com.github.zafarkhaja:java-semver:$javaSemverVersion" + compile "com.google.code.findbugs:jsr305:3.0.0" compile 'com.jayway.awaitility:awaitility:1.6.5' @@ -18,7 +19,6 @@ dependencies { testCompile "org.hamcrest:hamcrest-all:$hamcrestVersion" testCompile "org.mockito:mockito-core:$mockitoVersion" testCompile "com.github.tomakehurst:wiremock:2.0.6-beta" - testCompile "com.google.code.findbugs:jsr305:3.0.0" testCompile "com.github.stefanbirkner:system-rules:1.16.1" } diff --git a/docker-compose-rule-core/src/test/java/com/palantir/docker/compose/connection/ContainerIntegrationTests.java b/docker-compose-rule-core/src/integTest/java/com/palantir/docker/compose/connection/ContainerIntegrationTests.java similarity index 95% rename from docker-compose-rule-core/src/test/java/com/palantir/docker/compose/connection/ContainerIntegrationTests.java rename to docker-compose-rule-core/src/integTest/java/com/palantir/docker/compose/connection/ContainerIntegrationTests.java index e2ecfa8aa..d4892c551 100644 --- a/docker-compose-rule-core/src/test/java/com/palantir/docker/compose/connection/ContainerIntegrationTests.java +++ b/docker-compose-rule-core/src/integTest/java/com/palantir/docker/compose/connection/ContainerIntegrationTests.java @@ -36,7 +36,7 @@ public class ContainerIntegrationTests { @Test public void testStateChanges_withoutHealthCheck() throws IOException, InterruptedException { DockerCompose dockerCompose = new DefaultDockerCompose( - DockerComposeFiles.from("src/test/resources/no-healthcheck.yaml"), + DockerComposeFiles.from("src/integTest/resources/no-healthcheck.yaml"), dockerMachine, ProjectName.random()); @@ -60,7 +60,7 @@ public void testStateChanges_withHealthCheck() throws IOException, InterruptedEx assumeThat("docker-compose version", DockerCompose.version(), new GreaterOrEqual<>(Version.forIntegers(1, 10, 0))); DockerCompose dockerCompose = new DefaultDockerCompose( - DockerComposeFiles.from("src/test/resources/native-healthcheck.yaml"), + DockerComposeFiles.from("src/integTest/resources/native-healthcheck.yaml"), dockerMachine, ProjectName.random()); diff --git a/docker-compose-rule-core/src/test/resources/native-healthcheck.yaml b/docker-compose-rule-core/src/integTest/resources/native-healthcheck.yaml similarity index 100% rename from docker-compose-rule-core/src/test/resources/native-healthcheck.yaml rename to docker-compose-rule-core/src/integTest/resources/native-healthcheck.yaml diff --git a/docker-compose-rule-core/src/test/resources/no-healthcheck.yaml b/docker-compose-rule-core/src/integTest/resources/no-healthcheck.yaml similarity index 100% rename from docker-compose-rule-core/src/test/resources/no-healthcheck.yaml rename to docker-compose-rule-core/src/integTest/resources/no-healthcheck.yaml diff --git a/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/Docker.java b/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/Docker.java index c7ec8aa4c..94c27f407 100644 --- a/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/Docker.java +++ b/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/Docker.java @@ -25,7 +25,6 @@ import java.util.Collection; import java.util.regex.Matcher; import java.util.regex.Pattern; - import org.apache.commons.lang3.SystemUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -35,7 +34,7 @@ public class Docker { private static final Logger log = LoggerFactory.getLogger(Docker.class); // Without java escape characters: ^(\d+)\.(\d+)\.(\d+)(?:-.*)?$ - private static final Pattern VERSION_PATTERN = Pattern.compile("^Docker version (\\d+)\\.(\\d+)\\.(\\d+)(?:-.*)?$"); + private static final Pattern VERSION_PATTERN = Pattern.compile("^Docker version (\\d+)\\.(\\d+)\\.(\\d+)(?:(-|,).*)?$"); private static final String HEALTH_STATUS_FORMAT = "--format=" + "{{if not .State.Running}}DOWN" diff --git a/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DockerCommandLocations.java b/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DockerCommandLocations.java deleted file mode 100644 index a1e0c0a06..000000000 --- a/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DockerCommandLocations.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2016 Palantir Technologies, Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.palantir.docker.compose.execution; - -import static java.util.Arrays.asList; - -import java.io.File; -import java.util.List; -import java.util.Optional; -import java.util.function.Predicate; - -public class DockerCommandLocations { - private static final Predicate IS_NOT_NULL = path -> path != null; - private static final Predicate FILE_EXISTS = path -> new File(path).exists(); - - private final List possiblePaths; - - public DockerCommandLocations(String... possiblePaths) { - this.possiblePaths = asList(possiblePaths); - } - - public Optional preferredLocation() { - - return possiblePaths.stream() - .filter(IS_NOT_NULL) - .filter(FILE_EXISTS) - .findFirst(); - } - - @Override - public String toString() { - return "DockerCommandLocations{possiblePaths=" + possiblePaths + "}"; - } -} diff --git a/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DockerCommandLocator.java b/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DockerCommandLocator.java new file mode 100644 index 000000000..402d9c8a2 --- /dev/null +++ b/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DockerCommandLocator.java @@ -0,0 +1,73 @@ +/* + * Copyright 2016 Palantir Technologies, Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.palantir.docker.compose.execution; + +import com.google.common.collect.ImmutableList; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import javax.annotation.Nullable; +import org.apache.commons.lang3.SystemUtils; +import org.immutables.value.Value; + +@Value.Immutable +public abstract class DockerCommandLocator { + + private static final List MAC_SEARCH_LOCATIONS = ImmutableList.of("/usr/local/bin", "/usr/bin"); + + protected abstract String command(); + + @Value.Default + protected boolean isWindows() { + return SystemUtils.IS_OS_WINDOWS; + } + + @Value.Default + protected List macSearchLocations() { + return MAC_SEARCH_LOCATIONS; + } + + @Value.Derived + protected String executableName() { + if (isWindows()) { + return command() + ".exe"; + } + return command(); + } + + @Nullable + protected abstract String locationOverride(); + + public String getLocation() { + if (locationOverride() != null) { + return locationOverride(); + } + return macSearchLocations() + .stream() + .map(p -> Paths.get(p, executableName())) + .filter(Files::exists) + .findFirst() + .map(Path::toString) + .orElse(executableName()); + } + + public static ImmutableDockerCommandLocator.Builder forCommand(String command) { + return ImmutableDockerCommandLocator.builder() + .command(command); + } + +} diff --git a/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DockerComposeExecutable.java b/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DockerComposeExecutable.java index 9c2daed21..48a54697e 100644 --- a/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DockerComposeExecutable.java +++ b/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DockerComposeExecutable.java @@ -29,19 +29,12 @@ public abstract class DockerComposeExecutable implements Executable { private static final Logger log = LoggerFactory.getLogger(DockerComposeExecutable.class); - private static final DockerCommandLocations DOCKER_COMPOSE_LOCATIONS = new DockerCommandLocations( - System.getenv("DOCKER_COMPOSE_LOCATION"), - "/usr/local/bin/docker-compose", - "/usr/bin/docker-compose" - ); - private static String defaultDockerComposePath() { - String pathToUse = DOCKER_COMPOSE_LOCATIONS.preferredLocation() - .orElseThrow(() -> new IllegalStateException( - "Could not find docker-compose, looked in: " + DOCKER_COMPOSE_LOCATIONS)); - + DockerCommandLocator commandLocator = DockerCommandLocator.forCommand("docker-compose") + .locationOverride(System.getenv("DOCKER_COMPOSE_LOCATION")) + .build(); + String pathToUse = commandLocator.getLocation(); log.debug("Using docker-compose found at " + pathToUse); - return pathToUse; } diff --git a/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DockerExecutable.java b/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DockerExecutable.java index 1ff5cf01e..5dc9cf755 100644 --- a/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DockerExecutable.java +++ b/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DockerExecutable.java @@ -26,12 +26,6 @@ public abstract class DockerExecutable implements Executable { private static final Logger log = LoggerFactory.getLogger(DockerExecutable.class); - private static final DockerCommandLocations DOCKER_LOCATIONS = new DockerCommandLocations( - System.getenv("DOCKER_LOCATION"), - "/usr/local/bin/docker", - "/usr/bin/docker" - ); - @Value.Parameter protected abstract DockerConfiguration dockerConfiguration(); @Override @@ -41,12 +35,11 @@ public final String commandName() { @Value.Derived protected String dockerPath() { - String pathToUse = DOCKER_LOCATIONS.preferredLocation() - .orElseThrow(() -> new IllegalStateException( - "Could not find docker, looked in: " + DOCKER_LOCATIONS)); - + DockerCommandLocator commandLocator = DockerCommandLocator.forCommand("docker") + .locationOverride(System.getenv("DOCKER_LOCATION")) + .build(); + String pathToUse = commandLocator.getLocation(); log.debug("Using docker found at " + pathToUse); - return pathToUse; } @@ -66,4 +59,5 @@ public Process execute(String... commands) throws IOException { public static ImmutableDockerExecutable.Builder builder() { return ImmutableDockerExecutable.builder(); } + } diff --git a/docker-compose-rule-core/src/test/java/com/palantir/docker/compose/execution/DockerCommandLocationsShould.java b/docker-compose-rule-core/src/test/java/com/palantir/docker/compose/execution/DockerCommandLocationsShould.java deleted file mode 100644 index f5b2e44eb..000000000 --- a/docker-compose-rule-core/src/test/java/com/palantir/docker/compose/execution/DockerCommandLocationsShould.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2016 Palantir Technologies, Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.palantir.docker.compose.execution; - -import static java.util.Optional.empty; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.core.Is.is; - -import java.io.IOException; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; - -public class DockerCommandLocationsShould { - private static final String badLocation = "file/that/does/not/exist"; - private static final String otherBadLocation = "another/file/that/does/not/exist"; - - @Rule public TemporaryFolder folder = new TemporaryFolder(); - - private String goodLocation; - - @Before - public void setup() throws IOException { - goodLocation = folder.newFile("docker-compose.yml").getAbsolutePath(); - } - - @Test public void - provide_the_first_docker_command_location_if_it_exists() { - DockerCommandLocations dockerCommandLocations = new DockerCommandLocations( - badLocation, - goodLocation, - otherBadLocation); - - assertThat(dockerCommandLocations.preferredLocation().get(), - is(goodLocation)); - } - - @Test public void - skip_paths_from_environment_variables_that_are_unset() { - DockerCommandLocations dockerCommandLocations = new DockerCommandLocations( - System.getenv("AN_UNSET_DOCKER_COMPOSE_PATH"), - goodLocation); - - assertThat(dockerCommandLocations.preferredLocation().get(), - is(goodLocation)); - } - - @Test public void - have_no_preferred_path_when_all_possible_paths_are_all_invalid() { - DockerCommandLocations dockerCommandLocations = new DockerCommandLocations( - badLocation); - - assertThat(dockerCommandLocations.preferredLocation(), - is(empty())); - } -} diff --git a/docker-compose-rule-core/src/test/java/com/palantir/docker/compose/execution/DockerCommandLocatorShould.java b/docker-compose-rule-core/src/test/java/com/palantir/docker/compose/execution/DockerCommandLocatorShould.java new file mode 100644 index 000000000..d32348db3 --- /dev/null +++ b/docker-compose-rule-core/src/test/java/com/palantir/docker/compose/execution/DockerCommandLocatorShould.java @@ -0,0 +1,82 @@ +/* + * Copyright 2016 Palantir Technologies, Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.palantir.docker.compose.execution; + +import static java.util.Collections.singletonList; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.rules.TemporaryFolder; + +public class DockerCommandLocatorShould { + private static final String command = "not-a-real-command!"; + private static final String windowsCommand = command + ".exe"; + + @Rule public TemporaryFolder folder = new TemporaryFolder(); + + @Rule public ExpectedException exception = ExpectedException.none(); + + @Test public void + returns_the_command_name_when_no_other_paths_contain_command() { + DockerCommandLocator locator = DockerCommandLocator.forCommand(command) + .isWindows(false) + .build(); + + assertThat(locator.getLocation(), is(command)); + } + + @Test public void + returns_the_command_name_with_exe_on_windows_when_no_other_paths_contain_command() { + DockerCommandLocator locator = DockerCommandLocator.forCommand(command) + .isWindows(true) + .build(); + + assertThat(locator.getLocation(), is(windowsCommand)); + } + + @Test public void + allow_the_path_to_be_overriden() throws IOException { + Path overrideFolder = folder.newFolder("override").toPath(); + String overridenCommand = Files.createFile(overrideFolder.resolve(command)).toString(); + + DockerCommandLocator locator = DockerCommandLocator.forCommand(command) + .locationOverride(overridenCommand) + .isWindows(false) + .build(); + + assertThat(locator.getLocation(), is(overridenCommand)); + } + + @Test public void + search_in_known_mac_install_locations_for_the_command() throws IOException { + Path macSearchFolder = folder.newFolder("override").toPath(); + String commandLocation = Files.createFile(macSearchFolder.resolve(command)).toString(); + + DockerCommandLocator locator = DockerCommandLocator.forCommand(command) + .macSearchLocations(singletonList(macSearchFolder.toString())) + .isWindows(false) + .build(); + + assertThat(locator.getLocation(), is(commandLocation)); + } + +} diff --git a/docker-compose-rule-core/src/test/java/com/palantir/docker/compose/execution/DockerShould.java b/docker-compose-rule-core/src/test/java/com/palantir/docker/compose/execution/DockerShould.java index a55fbd2aa..73d427533 100644 --- a/docker-compose-rule-core/src/test/java/com/palantir/docker/compose/execution/DockerShould.java +++ b/docker-compose-rule-core/src/test/java/com/palantir/docker/compose/execution/DockerShould.java @@ -62,7 +62,7 @@ public void call_docker_network_ls() throws IOException, InterruptedException { @Test public void understand_old_version_format() throws IOException, InterruptedException { - when(executedProcess.getInputStream()).thenReturn(toInputStream("Docker version 1.7.2")); + when(executedProcess.getInputStream()).thenReturn(toInputStream("Docker version 1.7.2, build abcdef")); Version version = docker.configuredVersion(); assertThat(version, is(Version.valueOf("1.7.2"))); diff --git a/docker-compose-rule-core/src/test/java/com/palantir/docker/compose/execution/RetryerShould.java b/docker-compose-rule-core/src/test/java/com/palantir/docker/compose/execution/RetryerShould.java index 1a2764677..0f60b83d6 100644 --- a/docker-compose-rule-core/src/test/java/com/palantir/docker/compose/execution/RetryerShould.java +++ b/docker-compose-rule-core/src/test/java/com/palantir/docker/compose/execution/RetryerShould.java @@ -20,6 +20,7 @@ import static org.hamcrest.Matchers.lessThan; import static org.hamcrest.core.Is.is; import static org.junit.Assert.fail; +import static org.junit.Assume.assumeTrue; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -27,6 +28,7 @@ import com.google.common.base.Stopwatch; import com.palantir.docker.compose.utils.MockitoMultiAnswer; import java.util.concurrent.TimeUnit; +import org.apache.commons.lang3.SystemUtils; import org.joda.time.Duration; import org.junit.Test; import org.junit.runner.RunWith; @@ -61,11 +63,13 @@ public void should_not_pause_after_last_failure() throws Exception { @Test public void retryer_should_wait_after_failure_before_trying_again() throws Exception { + assumeTrue("Not running on Windows as Thread.sleep isn't accurate there", !SystemUtils.IS_OS_WINDOWS); + Retryer timeRetryer = new Retryer(1, Duration.millis(100)); Stopwatch stopwatch = Stopwatch.createStarted(); when(operation.call()).thenThrow(new DockerExecutionException()).thenAnswer(i -> { - assertThat(stopwatch.elapsed(TimeUnit.MILLISECONDS), greaterThan(100L)); + assertThat(stopwatch.elapsed(TimeUnit.MILLISECONDS), greaterThan(98L)); return "success"; }); diff --git a/docker-compose-rule-junit4/build.gradle b/docker-compose-rule-junit4/build.gradle index f9f2fe3a2..f4eec86fc 100644 --- a/docker-compose-rule-junit4/build.gradle +++ b/docker-compose-rule-junit4/build.gradle @@ -23,3 +23,15 @@ dependencies { if (System.env.CIRCLE_TEST_REPORTS) { test.reports.junitXml.destination = file(System.env.CIRCLE_TEST_REPORTS) } + +task windowsSmokeTest(type: Test) { + testClassesDir = sourceSets.integTest.output.classesDir + classpath = sourceSets.integTest.runtimeClasspath + + reports.html.destination = "${project.buildDir}/reports/integTest" + reports.junitXml.destination = "${project.buildDir}/integTest-results" + binResultsDir = file("${project.buildDir}/integTest-results/binary/integTest") + + include '**/windows/**' +} + diff --git a/docker-compose-rule-junit4/src/test/java/com/palantir/docker/compose/AggressiveShutdownStrategyIntegrationTest.java b/docker-compose-rule-junit4/src/integTest/java/com/palantir/docker/compose/AggressiveShutdownStrategyIntegrationTest.java similarity index 93% rename from docker-compose-rule-junit4/src/test/java/com/palantir/docker/compose/AggressiveShutdownStrategyIntegrationTest.java rename to docker-compose-rule-junit4/src/integTest/java/com/palantir/docker/compose/AggressiveShutdownStrategyIntegrationTest.java index 058e15e0d..e5cda5646 100644 --- a/docker-compose-rule-junit4/src/test/java/com/palantir/docker/compose/AggressiveShutdownStrategyIntegrationTest.java +++ b/docker-compose-rule-junit4/src/integTest/java/com/palantir/docker/compose/AggressiveShutdownStrategyIntegrationTest.java @@ -16,7 +16,7 @@ public class AggressiveShutdownStrategyIntegrationTest { @Test public void shut_down_multiple_containers_immediately() throws Exception { DockerComposeRule rule = DockerComposeRule.builder() - .file("src/test/resources/shutdown-strategy.yaml") + .file("src/integTest/resources/shutdown-strategy.yaml") .logCollector(new DoNothingLogCollector()) .retryAttempts(0) .shutdownStrategy(ShutdownStrategy.AGGRESSIVE) diff --git a/docker-compose-rule-junit4/src/test/java/com/palantir/docker/compose/AggressiveShutdownWithNetworkCleanupStrategyIntegrationTest.java b/docker-compose-rule-junit4/src/integTest/java/com/palantir/docker/compose/AggressiveShutdownWithNetworkCleanupStrategyIntegrationTest.java similarity index 95% rename from docker-compose-rule-junit4/src/test/java/com/palantir/docker/compose/AggressiveShutdownWithNetworkCleanupStrategyIntegrationTest.java rename to docker-compose-rule-junit4/src/integTest/java/com/palantir/docker/compose/AggressiveShutdownWithNetworkCleanupStrategyIntegrationTest.java index 35eacafa7..41613ce1f 100644 --- a/docker-compose-rule-junit4/src/test/java/com/palantir/docker/compose/AggressiveShutdownWithNetworkCleanupStrategyIntegrationTest.java +++ b/docker-compose-rule-junit4/src/integTest/java/com/palantir/docker/compose/AggressiveShutdownWithNetworkCleanupStrategyIntegrationTest.java @@ -18,7 +18,7 @@ public class AggressiveShutdownWithNetworkCleanupStrategyIntegrationTest { private final DockerComposeRule rule = DockerComposeRule.builder() - .file("src/test/resources/shutdown-strategy-with-network.yaml") + .file("src/integTest/resources/shutdown-strategy-with-network.yaml") .logCollector(new DoNothingLogCollector()) .retryAttempts(0) .shutdownStrategy(ShutdownStrategy.AGGRESSIVE_WITH_NETWORK_CLEANUP) diff --git a/docker-compose-rule-junit4/src/test/java/com/palantir/docker/compose/DockerComposeRuleIntegrationTest.java b/docker-compose-rule-junit4/src/integTest/java/com/palantir/docker/compose/DockerComposeRuleIntegrationTest.java similarity index 98% rename from docker-compose-rule-junit4/src/test/java/com/palantir/docker/compose/DockerComposeRuleIntegrationTest.java rename to docker-compose-rule-junit4/src/integTest/java/com/palantir/docker/compose/DockerComposeRuleIntegrationTest.java index 8162b087e..17dca78e5 100644 --- a/docker-compose-rule-junit4/src/test/java/com/palantir/docker/compose/DockerComposeRuleIntegrationTest.java +++ b/docker-compose-rule-junit4/src/integTest/java/com/palantir/docker/compose/DockerComposeRuleIntegrationTest.java @@ -45,7 +45,7 @@ public class DockerComposeRuleIntegrationTest { @Rule public final DockerComposeRule docker = DockerComposeRule.builder() - .files(DockerComposeFiles.from("src/test/resources/docker-compose.yaml")) + .files(DockerComposeFiles.from("src/integTest/resources/docker-compose.yaml")) .waitingForService("db", toHaveAllPortsOpen()) .waitingForService("db2", toHaveAllPortsOpen()) .waitingForServices(ImmutableList.of("db3", "db4"), toAllHaveAllPortsOpen()) diff --git a/docker-compose-rule-junit4/src/test/java/com/palantir/docker/compose/DockerComposeRuleNativeHealthcheckIntegrationTest.java b/docker-compose-rule-junit4/src/integTest/java/com/palantir/docker/compose/DockerComposeRuleNativeHealthcheckIntegrationTest.java similarity index 97% rename from docker-compose-rule-junit4/src/test/java/com/palantir/docker/compose/DockerComposeRuleNativeHealthcheckIntegrationTest.java rename to docker-compose-rule-junit4/src/integTest/java/com/palantir/docker/compose/DockerComposeRuleNativeHealthcheckIntegrationTest.java index 6ad62740f..fad8f15fe 100644 --- a/docker-compose-rule-junit4/src/test/java/com/palantir/docker/compose/DockerComposeRuleNativeHealthcheckIntegrationTest.java +++ b/docker-compose-rule-junit4/src/integTest/java/com/palantir/docker/compose/DockerComposeRuleNativeHealthcheckIntegrationTest.java @@ -53,7 +53,7 @@ public void dockerComposeRuleWaitsUntilHealthcheckPasses() assumeThat("docker-compose version", DockerCompose.version(), new GreaterOrEqual<>(Version.forIntegers(1, 10, 0))); rule = DockerComposeRule.builder() - .file("src/test/resources/native-healthcheck.yaml") + .file("src/integTest/resources/native-healthcheck.yaml") .build(); Future beforeFuture = pool.submit(() -> { rule.before(); diff --git a/docker-compose-rule-junit4/src/test/java/com/palantir/docker/compose/DockerComposeRuleUpContainerIntegrationTest.java b/docker-compose-rule-junit4/src/integTest/java/com/palantir/docker/compose/DockerComposeRuleUpContainerIntegrationTest.java similarity index 97% rename from docker-compose-rule-junit4/src/test/java/com/palantir/docker/compose/DockerComposeRuleUpContainerIntegrationTest.java rename to docker-compose-rule-junit4/src/integTest/java/com/palantir/docker/compose/DockerComposeRuleUpContainerIntegrationTest.java index 488a2b949..45f96b8ad 100644 --- a/docker-compose-rule-junit4/src/test/java/com/palantir/docker/compose/DockerComposeRuleUpContainerIntegrationTest.java +++ b/docker-compose-rule-junit4/src/integTest/java/com/palantir/docker/compose/DockerComposeRuleUpContainerIntegrationTest.java @@ -37,7 +37,7 @@ public class DockerComposeRuleUpContainerIntegrationTest { public final DockerComposeRule dockerComposeRule = DockerComposeRule .builder() .shutdownStrategy(AGGRESSIVE) - .file("src/test/resources/up-integration-test.yaml") + .file("src/integTest/resources/up-integration-test.yaml") .build(); @Test diff --git a/docker-compose-rule-junit4/src/test/java/com/palantir/docker/compose/HostNetworkedPortsIntegrationTest.java b/docker-compose-rule-junit4/src/integTest/java/com/palantir/docker/compose/HostNetworkedPortsIntegrationTest.java similarity index 96% rename from docker-compose-rule-junit4/src/test/java/com/palantir/docker/compose/HostNetworkedPortsIntegrationTest.java rename to docker-compose-rule-junit4/src/integTest/java/com/palantir/docker/compose/HostNetworkedPortsIntegrationTest.java index baf59ed37..64f2f117b 100644 --- a/docker-compose-rule-junit4/src/test/java/com/palantir/docker/compose/HostNetworkedPortsIntegrationTest.java +++ b/docker-compose-rule-junit4/src/integTest/java/com/palantir/docker/compose/HostNetworkedPortsIntegrationTest.java @@ -22,7 +22,6 @@ import com.palantir.docker.compose.connection.DockerPort; import com.palantir.docker.compose.connection.waiting.HealthCheck; import com.palantir.docker.compose.connection.waiting.SuccessOrFailure; - import org.apache.commons.lang3.SystemUtils; import org.junit.Test; @@ -40,7 +39,7 @@ private static HealthCheck toBeOpen() { assumeTrue("Host ports are only accessible on linux", SystemUtils.IS_OS_LINUX); DockerComposeRule docker = DockerComposeRule.builder() - .file("src/test/resources/host-networked-docker-compose.yaml") + .file("src/integTest/resources/host-networked-docker-compose.yaml") .waitingForHostNetworkedPort(5432, toBeOpen()) .build(); try { diff --git a/docker-compose-rule-junit4/src/test/java/com/palantir/docker/compose/RemoveConflictingContainersIntegrationTest.java b/docker-compose-rule-junit4/src/integTest/java/com/palantir/docker/compose/RemoveConflictingContainersIntegrationTest.java similarity index 97% rename from docker-compose-rule-junit4/src/test/java/com/palantir/docker/compose/RemoveConflictingContainersIntegrationTest.java rename to docker-compose-rule-junit4/src/integTest/java/com/palantir/docker/compose/RemoveConflictingContainersIntegrationTest.java index 84961cc78..800e8f149 100644 --- a/docker-compose-rule-junit4/src/test/java/com/palantir/docker/compose/RemoveConflictingContainersIntegrationTest.java +++ b/docker-compose-rule-junit4/src/integTest/java/com/palantir/docker/compose/RemoveConflictingContainersIntegrationTest.java @@ -25,7 +25,7 @@ public class RemoveConflictingContainersIntegrationTest { - private static final String DOCKER_COMPOSE_YAML_PATH = "src/test/resources/named-containers-docker-compose.yaml"; + private static final String DOCKER_COMPOSE_YAML_PATH = "src/integTest/resources/named-containers-docker-compose.yaml"; @Rule public ExpectedException exception = ExpectedException.none(); diff --git a/docker-compose-rule-junit4/src/test/java/com/palantir/docker/compose/execution/EnvironmentVariableIntegrationTest.java b/docker-compose-rule-junit4/src/integTest/java/com/palantir/docker/compose/execution/EnvironmentVariableIntegrationTest.java similarity index 96% rename from docker-compose-rule-junit4/src/test/java/com/palantir/docker/compose/execution/EnvironmentVariableIntegrationTest.java rename to docker-compose-rule-junit4/src/integTest/java/com/palantir/docker/compose/execution/EnvironmentVariableIntegrationTest.java index 304ba7dcd..25ddfa1ff 100644 --- a/docker-compose-rule-junit4/src/test/java/com/palantir/docker/compose/execution/EnvironmentVariableIntegrationTest.java +++ b/docker-compose-rule-junit4/src/integTest/java/com/palantir/docker/compose/execution/EnvironmentVariableIntegrationTest.java @@ -39,7 +39,7 @@ public void docker_compose_gets_environment_variables_from_docker_machine_and_pa .build(); DockerComposeRule dockerComposition = DockerComposeRule.builder() - .file("src/test/resources/environment/docker-compose.yaml") + .file("src/integTest/resources/environment/docker-compose.yaml") .machine(dockerMachine) .waitingForService("env-test", toHaveAllPortsOpen()) .saveLogsTo(temporaryFolder.getRoot().getAbsolutePath()) diff --git a/docker-compose-rule-junit4/src/test/java/com/palantir/docker/compose/logging/LoggingIntegrationTest.java b/docker-compose-rule-junit4/src/integTest/java/com/palantir/docker/compose/logging/LoggingIntegrationTest.java similarity index 97% rename from docker-compose-rule-junit4/src/test/java/com/palantir/docker/compose/logging/LoggingIntegrationTest.java rename to docker-compose-rule-junit4/src/integTest/java/com/palantir/docker/compose/logging/LoggingIntegrationTest.java index f227e0bbe..94a569a5d 100644 --- a/docker-compose-rule-junit4/src/test/java/com/palantir/docker/compose/logging/LoggingIntegrationTest.java +++ b/docker-compose-rule-junit4/src/integTest/java/com/palantir/docker/compose/logging/LoggingIntegrationTest.java @@ -39,7 +39,7 @@ public class LoggingIntegrationTest { @Before public void setUp() { dockerComposeRule = DockerComposeRule.builder() - .file("src/test/resources/docker-compose.yaml") + .file("src/integTest/resources/docker-compose.yaml") .waitingForService("db", toHaveAllPortsOpen()) .waitingForService("db2", toHaveAllPortsOpen()) .saveLogsTo(logFolder.getRoot().getAbsolutePath()) diff --git a/docker-compose-rule-junit4/src/integTest/java/com/palantir/docker/compose/windows/WindowsIntegrationTest.java b/docker-compose-rule-junit4/src/integTest/java/com/palantir/docker/compose/windows/WindowsIntegrationTest.java new file mode 100644 index 000000000..394004ee9 --- /dev/null +++ b/docker-compose-rule-junit4/src/integTest/java/com/palantir/docker/compose/windows/WindowsIntegrationTest.java @@ -0,0 +1,36 @@ +/* + * Copyright 2016 Palantir Technologies, Inc. All rights reserved. + */ + +package com.palantir.docker.compose.windows; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; +import static org.junit.Assume.assumeTrue; + +import com.palantir.docker.compose.DockerComposeRule; +import com.palantir.docker.compose.configuration.DockerComposeFiles; +import com.palantir.docker.compose.connection.State; +import java.io.IOException; +import org.apache.commons.lang3.SystemUtils; +import org.junit.Test; + +public class WindowsIntegrationTest { + + @Test + public void can_execute_docker_commands() throws IOException, InterruptedException { + assumeTrue("Running on Windows", SystemUtils.IS_OS_WINDOWS); + + DockerComposeRule docker = DockerComposeRule.builder() + .files(DockerComposeFiles.from("src/integTest/resources/windows-docker-compose.yaml")) + .build(); + docker.before(); + + try { + assertThat(docker.containers().container("hello-world").state(), is(State.DOWN)); + } finally { + docker.after(); + } + } + +} diff --git a/docker-compose-rule-junit4/src/test/resources/docker-compose.yaml b/docker-compose-rule-junit4/src/integTest/resources/docker-compose.yaml similarity index 100% rename from docker-compose-rule-junit4/src/test/resources/docker-compose.yaml rename to docker-compose-rule-junit4/src/integTest/resources/docker-compose.yaml diff --git a/docker-compose-rule-junit4/src/test/resources/environment/docker-compose.yaml b/docker-compose-rule-junit4/src/integTest/resources/environment/docker-compose.yaml similarity index 100% rename from docker-compose-rule-junit4/src/test/resources/environment/docker-compose.yaml rename to docker-compose-rule-junit4/src/integTest/resources/environment/docker-compose.yaml diff --git a/docker-compose-rule-junit4/src/test/resources/host-networked-docker-compose.yaml b/docker-compose-rule-junit4/src/integTest/resources/host-networked-docker-compose.yaml similarity index 100% rename from docker-compose-rule-junit4/src/test/resources/host-networked-docker-compose.yaml rename to docker-compose-rule-junit4/src/integTest/resources/host-networked-docker-compose.yaml diff --git a/docker-compose-rule-junit4/src/test/resources/named-containers-docker-compose.yaml b/docker-compose-rule-junit4/src/integTest/resources/named-containers-docker-compose.yaml similarity index 100% rename from docker-compose-rule-junit4/src/test/resources/named-containers-docker-compose.yaml rename to docker-compose-rule-junit4/src/integTest/resources/named-containers-docker-compose.yaml diff --git a/docker-compose-rule-junit4/src/test/resources/native-healthcheck.yaml b/docker-compose-rule-junit4/src/integTest/resources/native-healthcheck.yaml similarity index 100% rename from docker-compose-rule-junit4/src/test/resources/native-healthcheck.yaml rename to docker-compose-rule-junit4/src/integTest/resources/native-healthcheck.yaml diff --git a/docker-compose-rule-junit4/src/test/resources/shutdown-strategy-with-network.yaml b/docker-compose-rule-junit4/src/integTest/resources/shutdown-strategy-with-network.yaml similarity index 100% rename from docker-compose-rule-junit4/src/test/resources/shutdown-strategy-with-network.yaml rename to docker-compose-rule-junit4/src/integTest/resources/shutdown-strategy-with-network.yaml diff --git a/docker-compose-rule-junit4/src/test/resources/shutdown-strategy.yaml b/docker-compose-rule-junit4/src/integTest/resources/shutdown-strategy.yaml similarity index 100% rename from docker-compose-rule-junit4/src/test/resources/shutdown-strategy.yaml rename to docker-compose-rule-junit4/src/integTest/resources/shutdown-strategy.yaml diff --git a/docker-compose-rule-junit4/src/test/resources/up-integration-test.yaml b/docker-compose-rule-junit4/src/integTest/resources/up-integration-test.yaml similarity index 100% rename from docker-compose-rule-junit4/src/test/resources/up-integration-test.yaml rename to docker-compose-rule-junit4/src/integTest/resources/up-integration-test.yaml diff --git a/docker-compose-rule-junit4/src/integTest/resources/windows-docker-compose.yaml b/docker-compose-rule-junit4/src/integTest/resources/windows-docker-compose.yaml new file mode 100644 index 000000000..d1e98b7bc --- /dev/null +++ b/docker-compose-rule-junit4/src/integTest/resources/windows-docker-compose.yaml @@ -0,0 +1,4 @@ +hello-world: + image: microsoft/windowsservercore + command: echo "Server started" + diff --git a/gradle/integTest.gradle b/gradle/integTest.gradle new file mode 100644 index 000000000..bf1dcea1c --- /dev/null +++ b/gradle/integTest.gradle @@ -0,0 +1,67 @@ +// From https://raw.githubusercontent.com/spring-io/sagan/master/gradle/integTest.gradle +import org.gradle.api.tasks.testing.Test + +/** + * This script adds a dedicated integration testing source set (src/integTest) and task + * (integTest) when applied to any Java project. + * + * Configuration: + * apply from: path/to/integTest.gradle + * + * Usage: + * gradle integTest + * - or - + * gradle check + */ + +sourceSets { + integTest { + java.srcDir 'src/integTest/java' + resources.srcDir 'src/integTest/resources' + } +} + +task integTest(type: Test) { + description = "Runs integration tests." + + testClassesDir = sourceSets.integTest.output.classesDir + classpath = sourceSets.integTest.runtimeClasspath + + maxHeapSize = '1024m' + + // ensure we don't overwrite default report directories used by 'test' task + reports.html.destination = "${project.buildDir}/reports/integTest" + reports.junitXml.destination = "${project.buildDir}/integTest-results" + binResultsDir = file("${project.buildDir}/integTest-results/binary/integTest") + + // always run integration tests after unit tests in order to fail fast + mustRunAfter test +} + +dependencies { + integTestCompile sourceSets.main.output + integTestCompile sourceSets.test.output + integTestCompile configurations.compile + integTestCompile configurations.testCompile + integTestRuntime configurations.runtime + integTestRuntime configurations.testRuntime +} + +// Ensure unit test tasks (named 'test') always run before integration tests in +// order to fail as fast as possible +gradle.projectsEvaluated { + def unitTestTasks = [] + gradle.rootProject.allprojects { project -> + unitTestTasks.addAll(project.tasks.findAll { it.name == 'test' }) + } + unitTestTasks.each { unitTestTask -> + project.integTest.mustRunAfter unitTestTask + } +} + +// Add integration test source directories to IDEA .iml files +if (project.plugins.hasPlugin('idea')) { + idea.module { + testSourceDirs += (sourceSets.integTest.java.srcDirs + sourceSets.integTest.resources.srcDirs) + } +}