Skip to content
This repository has been archived by the owner on Sep 6, 2024. It is now read-only.

Commit

Permalink
Fix checkstyle errors
Browse files Browse the repository at this point in the history
  • Loading branch information
Tomas Hanley committed Jan 26, 2018
1 parent 463c6ac commit 9054d60
Show file tree
Hide file tree
Showing 11 changed files with 174 additions and 124 deletions.
9 changes: 5 additions & 4 deletions src/main/java/com/github/junit5docker/ContainerInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,22 @@
import static java.util.Collections.emptySet;
import static java.util.Collections.unmodifiableCollection;

public class ContainerInfo {
class ContainerInfo {

private final String containerId;

private final Collection<String> networkIds;

public ContainerInfo(String containerId, Collection<String> networkIds) {
ContainerInfo(String containerId, Collection<String> networkIds) {
this.containerId = containerId;
this.networkIds = networkIds == null ? emptySet() : unmodifiableCollection(networkIds);
}

public String getContainerId() {
String getContainerId() {
return containerId;
}

public Collection<String> getNetworkIds() {
Collection<String> getNetworkIds() {
return networkIds;
}
}
18 changes: 13 additions & 5 deletions src/main/java/com/github/junit5docker/DefaultDockerClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ class DefaultDockerClient implements DockerClientAdapter {
}

@Override
public ContainerInfo startContainer(String wantedImage, Map<String, String> environment, String[] networkNames, PortBinding... portBinding) {
public ContainerInfo startContainer(String wantedImage,
Map<String, String> environment,
String[] networkNames,
PortBinding... portBinding) {
Ports bindings = createPortBindings(portBinding);
List<String> environmentStrings = createEnvironmentList(environment);
String containerId = createContainer(wantedImage, bindings, environmentStrings);
Expand Down Expand Up @@ -62,10 +65,15 @@ private String getNetworkId(String networkName) {
}

private Optional<String> getExistingNetworkId(String networkName) {
return dockerClient.listNetworksCmd().exec().stream()
.filter(n -> n.getName().equals(networkName))
.reduce((a, b) -> {
throw new IllegalStateException("Multiple networks found with the same name: " + a + ", " + b);
return dockerClient.listNetworksCmd()
.exec()
.stream()
.filter(name -> name.getName().equals(networkName))
.reduce((name1, name2) -> {
String msg = String.format("Multiple networks found with the same name: %s and %s",
name1,
name2);
throw new IllegalStateException(msg);
})
.map(Network::getId);
}
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/com/github/junit5docker/Docker.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import static com.github.junit5docker.WaitFor.NOTHING;

/**
* <p>This annotation is the junit-docker entry point.</p>
* <p>This annotation is a junit-docker entry point.</p>
*
* <p>Adding this annotation to a test's class will start a docker container before running the tests and will be stop
* at the end of the tests. This is done once per class.</p>
Expand Down Expand Up @@ -55,7 +55,8 @@
boolean newForEachCase() default true;

/**
* The names of the networks for the container to join.
* @return the names of the networks for the container to join.
* Empty if the container has no networks to join.
*/
String[] networks() default {};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@

interface DockerClientAdapter {

ContainerInfo startContainer(String wantedImage, Map<String, String> environment, String[] networkNames, PortBinding... portBinding);
ContainerInfo startContainer(String wantedImage,
Map<String, String> environment,
String[] networkNames,
PortBinding... portBinding);

void disconnectFromNetwork(String containerId, String networkId);

/**
* Remove the specified network if no containers are connected to it.
* @param networkId
*
* @param networkId The id of the network to try remove
*/
void maybeRemoveNetwork(String networkId);

Expand Down
63 changes: 18 additions & 45 deletions src/main/java/com/github/junit5docker/DockerExtension.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,42 +9,40 @@
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Stream;

import static java.util.concurrent.CompletableFuture.supplyAsync;

class DockerExtension implements BeforeAllCallback, AfterAllCallback, BeforeEachCallback, AfterEachCallback {

private final DockerClientAdapter dockerClient;

private final DockerLogChecker dockerLogChecker;

DockerExtension() {
this(new DefaultDockerClient());
}

DockerExtension(DockerClientAdapter dockerClient) {
this.dockerClient = dockerClient;
this.dockerLogChecker = new DockerLogChecker(dockerClient);
}

@Override
public void beforeAll(ExtensionContext context) {
forEachDocker(context, d -> !d.newForEachCase(), this::startContainer);
forEachDocker(context, docker -> !docker.newForEachCase(), this::startContainer);
}

@Override
public void beforeEach(ExtensionContext context) {
forEachDocker(context, Docker::newForEachCase, this::startContainer);
}

private static void forEachDocker(ExtensionContext context, Predicate<Docker> predicate, BiConsumer<ExtensionContext, Docker> action){
Arrays.stream(findDockerAnnotations(context)).filter(predicate).forEach(d -> action.accept(context, d));
private static void forEachDocker(ExtensionContext context,
Predicate<Docker> predicate,
BiConsumer<ExtensionContext, Docker> action) {
Arrays.stream(findDockerAnnotations(context))
.filter(predicate)
.forEach(docker -> action.accept(context, docker));
}

private void startContainer(ExtensionContext context, Docker dockerAnnotation) {
Expand All @@ -53,39 +51,14 @@ private void startContainer(ExtensionContext context, Docker dockerAnnotation) {
String imageReference = findImageName(dockerAnnotation);
WaitFor waitFor = dockerAnnotation.waitFor();
String[] networkNames = dockerAnnotation.networks();
ContainerInfo containerInfo = dockerClient.startContainer(imageReference, environmentMap, networkNames, portBindings);
waitForLogAccordingTo(waitFor, containerInfo.getContainerId());
ContainerInfo containerInfo = dockerClient.startContainer(imageReference,
environmentMap,
networkNames,
portBindings);
dockerLogChecker.waitForLogAccordingTo(waitFor, containerInfo.getContainerId());
getStore(context).put(dockerAnnotation, containerInfo);
}

private void waitForLogAccordingTo(WaitFor waitFor, String containerId) {
String expectedLog = waitFor.value();
if (!WaitFor.NOTHING.equals(expectedLog)) {
ExecutorService executor = Executors.newSingleThreadExecutor();
CompletableFuture<Boolean> logFound = supplyAsync(findFirstLogContaining(expectedLog, containerId), executor);
executor.shutdown();
try {
boolean termination = executor.awaitTermination(waitFor.timeoutInMillis(), TimeUnit.MILLISECONDS);
if (!termination) {
throw new AssertionError("Timeout while waiting for log : \"" + expectedLog + "\"");
}
if (!logFound.getNow(false)) {
throw new AssertionError("\"" + expectedLog + "\" not found in logs and container stopped");
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}

private Supplier<Boolean> findFirstLogContaining(String logToFind, String containerId) {
return () -> {
try (Stream<String> logs = dockerClient.logs(containerId)) {
return logs.anyMatch(log -> log.contains(logToFind));
}
};
}

private static Docker[] findDockerAnnotations(ExtensionContext extensionContext) {
Class<?> testClass = extensionContext.getTestClass().get();
return testClass.getAnnotationsByType(Docker.class);
Expand Down Expand Up @@ -116,7 +89,7 @@ private static PortBinding[] createPortBindings(Docker dockerAnnotation) {

@Override
public void afterAll(ExtensionContext context) {
forEachDocker(context, d -> !d.newForEachCase(), this::stopAndRemove);
forEachDocker(context, docker -> !docker.newForEachCase(), this::stopAndRemove);
}

@Override
Expand All @@ -129,9 +102,9 @@ private void stopAndRemove(ExtensionContext context, Docker docker) {

String containerId = containerInfo.getContainerId();

containerInfo.getNetworkIds().forEach(c -> {
dockerClient.disconnectFromNetwork(containerId, c);
dockerClient.maybeRemoveNetwork(c);
containerInfo.getNetworkIds().forEach(networkId -> {
dockerClient.disconnectFromNetwork(containerId, networkId);
dockerClient.maybeRemoveNetwork(networkId);
});
dockerClient.stopAndRemoveContainer(containerId);
}
Expand Down
48 changes: 48 additions & 0 deletions src/main/java/com/github/junit5docker/DockerLogChecker.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.github.junit5docker;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import java.util.stream.Stream;

import static java.util.concurrent.CompletableFuture.supplyAsync;

class DockerLogChecker {

private final DockerClientAdapter dockerClient;

DockerLogChecker(DockerClientAdapter dockerClient) {
this.dockerClient = dockerClient;
}

void waitForLogAccordingTo(WaitFor waitFor, String containerId) {
String expectedLog = waitFor.value();
if (!WaitFor.NOTHING.equals(expectedLog)) {
ExecutorService executor = Executors.newSingleThreadExecutor();
CompletableFuture<Boolean> logFound = supplyAsync(findFirstLogContaining(expectedLog, containerId),
executor);
executor.shutdown();
try {
boolean termination = executor.awaitTermination(waitFor.timeoutInMillis(), TimeUnit.MILLISECONDS);
if (!termination) {
throw new AssertionError("Timeout while waiting for log : \"" + expectedLog + "\"");
}
if (!logFound.getNow(false)) {
throw new AssertionError("\"" + expectedLog + "\" not found in logs and container stopped");
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}

private Supplier<Boolean> findFirstLogContaining(String logToFind, String containerId) {
return () -> {
try (Stream<String> logs = dockerClient.logs(containerId)) {
return logs.anyMatch(log -> log.contains(logToFind));
}
};
}
}
12 changes: 10 additions & 2 deletions src/main/java/com/github/junit5docker/Dockers.java
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
package com.github.junit5docker;


import org.junit.jupiter.api.extension.ExtendWith;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* <p>This annotation is a junit-docker entry point.</p>
* <p>It can be used to start multiple docker containers per test.</p>
* <p>
* <p>It must contain one or more {@link com.github.junit5docker.Docker} annotations.</p>
*
* @see Docker
*/

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@ExtendWith(DockerExtension.class)
public @interface Dockers {

/**
* @return the list of Docker containers to start
* @return the list of Docker containers to start.
* @see Docker
*/
Docker[] value();
Expand Down
16 changes: 10 additions & 6 deletions src/test/java/com/github/junit5docker/DefaultDockerClientIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ public void ensureImageIsPulled() {
@Test
@DisplayName("start a container without ports")
public void shouldStartContainer() {
String containerId = defaultDockerClient.startContainer(WANTED_IMAGE, emptyMap(), null).getContainerId();
String containerId = defaultDockerClient.startContainer(WANTED_IMAGE, emptyMap(), null)
.getContainerId();
assertThat(dockerClient.listContainersCmd().exec()).hasSize(existingContainers.size() + 1);
InspectContainerResponse startedContainer = dockerClient.inspectContainerCmd(containerId).exec();
assertThat(startedContainer.getConfig().getImage()).isEqualTo(WANTED_IMAGE);
Expand Down Expand Up @@ -117,11 +118,11 @@ public void shouldStartContainerWithEnvironmentVariables() {
Map<String, String> environments = new HashMap<>();
environments.put("khaled", "souf");
environments.put("abdellah", "stagiaire");
String containerId = defaultDockerClient.startContainer(WANTED_IMAGE, environments, null).getContainerId();
String containerId = defaultDockerClient.startContainer(WANTED_IMAGE, environments, null)
.getContainerId();
InspectContainerResponse startedContainer = dockerClient.inspectContainerCmd(containerId).exec();
List<String> envs = Arrays.asList(startedContainer.getConfig().getEnv());
assertThat(envs).hasSize(2 + DEFAULT_DOCKER_ENV_NUMBER)
.contains("khaled=souf", "abdellah=stagiaire");
assertThat(envs).hasSize(2 + DEFAULT_DOCKER_ENV_NUMBER).contains("khaled=souf", "abdellah=stagiaire");
}
}

Expand All @@ -144,7 +145,8 @@ public void ensureContainerIsNotPresent() {
@Test
@DisplayName("start a container after pulling the image")
public void shouldStartContainer() {
String containerId = defaultDockerClient.startContainer(WANTED_IMAGE, emptyMap(), null).getContainerId();
String containerId = defaultDockerClient.startContainer(WANTED_IMAGE, emptyMap(), null)
.getContainerId();
assertThat(dockerClient.listContainersCmd().exec()).hasSize(existingContainers.size() + 1);
InspectContainerResponse startedContainer = dockerClient.inspectContainerCmd(containerId).exec();
assertThat(startedContainer.getConfig().getImage()).isEqualTo(WANTED_IMAGE);
Expand All @@ -157,7 +159,9 @@ class WithABugInDockerJava {
@Test
@DisplayName("add latest to the image name if none is given")
public void shouldStartLatestContainer() {
String containerId = defaultDockerClient.startContainer("faustxvi/simple-two-ports", emptyMap(), null).getContainerId();
String containerId = defaultDockerClient.startContainer("faustxvi/simple-two-ports",
emptyMap(),
null).getContainerId();
List<Container> currentContainers = dockerClient.listContainersCmd().exec();
assertThat(currentContainers).hasSize(existingContainers.size() + 1);
InspectContainerResponse startedContainer = dockerClient.inspectContainerCmd(containerId).exec();
Expand Down
Loading

0 comments on commit 9054d60

Please sign in to comment.