Skip to content

Commit

Permalink
Avoid connection leaks in LogUtils (#2834)
Browse files Browse the repository at this point in the history
  • Loading branch information
bsideup committed Jun 6, 2020
1 parent ddae79c commit 0035c31
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -1,34 +1,53 @@
package org.testcontainers.containers.wait.strategy;

import com.github.dockerjava.api.command.LogContainerCmd;
import lombok.SneakyThrows;
import org.testcontainers.DockerClientFactory;
import org.testcontainers.containers.ContainerLaunchException;
import org.testcontainers.containers.output.FrameConsumerResultCallback;
import org.testcontainers.containers.output.OutputFrame;
import org.testcontainers.containers.output.WaitingConsumer;
import org.testcontainers.utility.LogUtils;

import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Predicate;

import static org.testcontainers.containers.output.OutputFrame.OutputType.STDERR;
import static org.testcontainers.containers.output.OutputFrame.OutputType.STDOUT;

public class LogMessageWaitStrategy extends AbstractWaitStrategy {

private String regEx;

private int times = 1;

@Override
@SneakyThrows(IOException.class)
protected void waitUntilReady() {
WaitingConsumer waitingConsumer = new WaitingConsumer();
LogUtils.followOutput(DockerClientFactory.instance().client(), waitStrategyTarget.getContainerId(), waitingConsumer);

Predicate<OutputFrame> waitPredicate = outputFrame ->
// (?s) enables line terminator matching (equivalent to Pattern.DOTALL)
outputFrame.getUtf8String().matches("(?s)" + regEx);
LogContainerCmd cmd = DockerClientFactory.instance().client().logContainerCmd(waitStrategyTarget.getContainerId())
.withFollowStream(true)
.withSince(0)
.withStdOut(true)
.withStdErr(true);

try (FrameConsumerResultCallback callback = new FrameConsumerResultCallback()) {
callback.addConsumer(STDOUT, waitingConsumer);
callback.addConsumer(STDERR, waitingConsumer);

cmd.exec(callback);

Predicate<OutputFrame> waitPredicate = outputFrame ->
// (?s) enables line terminator matching (equivalent to Pattern.DOTALL)
outputFrame.getUtf8String().matches("(?s)" + regEx);

try {
waitingConsumer.waitUntil(waitPredicate, startupTimeout.getSeconds(), TimeUnit.SECONDS, times);
} catch (TimeoutException e) {
throw new ContainerLaunchException("Timed out waiting for log output matching '" + regEx + "'");
try {
waitingConsumer.waitUntil(waitPredicate, startupTimeout.getSeconds(), TimeUnit.SECONDS, times);
} catch (TimeoutException e) {
throw new ContainerLaunchException("Timed out waiting for log output matching '" + regEx + "'");
}
}
}

Expand Down
26 changes: 16 additions & 10 deletions core/src/main/java/org/testcontainers/utility/LogUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@

import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.command.LogContainerCmd;
import lombok.SneakyThrows;
import lombok.experimental.UtilityClass;
import org.testcontainers.containers.output.FrameConsumerResultCallback;
import org.testcontainers.containers.output.OutputFrame;
import org.testcontainers.containers.output.ToStringConsumer;
import org.testcontainers.containers.output.WaitingConsumer;

import java.io.Closeable;
import java.io.IOException;
import java.util.function.Consumer;

import static org.testcontainers.containers.output.OutputFrame.OutputType.STDERR;
Expand Down Expand Up @@ -59,6 +62,7 @@ public void followOutput(DockerClient dockerClient,
* @param types types of {@link OutputFrame} to receive
* @return all previous output frames (stdout/stderr being separated by newline characters)
*/
@SneakyThrows(IOException.class)
public String getOutput(DockerClient dockerClient,
String containerId,
OutputFrame.OutputType... types) {
Expand All @@ -73,17 +77,19 @@ public String getOutput(DockerClient dockerClient,

final ToStringConsumer consumer = new ToStringConsumer();
final WaitingConsumer wait = new WaitingConsumer();
attachConsumer(dockerClient, containerId, consumer.andThen(wait), false, types);

wait.waitUntilEnd();
return consumer.toUtf8String();
try (Closeable closeable = attachConsumer(dockerClient, containerId, consumer.andThen(wait), false, types)) {
wait.waitUntilEnd();
return consumer.toUtf8String();
}
}

private static void attachConsumer(DockerClient dockerClient,
String containerId,
Consumer<OutputFrame> consumer,
boolean followStream,
OutputFrame.OutputType... types) {
private static Closeable attachConsumer(
DockerClient dockerClient,
String containerId,
Consumer<OutputFrame> consumer,
boolean followStream,
OutputFrame.OutputType... types
) {

final LogContainerCmd cmd = dockerClient.logContainerCmd(containerId)
.withFollowStream(followStream)
Expand All @@ -96,6 +102,6 @@ private static void attachConsumer(DockerClient dockerClient,
if (type == STDERR) cmd.withStdErr(true);
}

cmd.exec(callback);
return cmd.exec(callback);
}
}

0 comments on commit 0035c31

Please sign in to comment.