Skip to content

Commit 93202d1

Browse files
authored
Try to stabilize tests (docker-java#1285)
- perform cleanup after each test - Remove `RegistryUtils`, introduce `PrivateRegistryRule` - Do not trim stacktraces - Fix the OkHttp SSL support - Improve `attachContainerClosesStdoutWhenContainerExits` - Close DockerClient to avoid leaks
1 parent 217c14b commit 93202d1

File tree

13 files changed

+754
-218
lines changed

13 files changed

+754
-218
lines changed

docker-java-transport-okhttp/src/main/java/com/github/dockerjava/okhttp/FramedSink.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.github.dockerjava.api.model.StreamType;
66
import okio.BufferedSource;
77

8+
import java.io.IOException;
89
import java.nio.ByteBuffer;
910
import java.util.Arrays;
1011
import java.util.function.Consumer;
@@ -22,7 +23,14 @@ class FramedSink implements Consumer<BufferedSource> {
2223
@Override
2324
public void accept(BufferedSource source) {
2425
try {
25-
while (!source.exhausted()) {
26+
while (true) {
27+
try {
28+
if (source.exhausted()) {
29+
break;
30+
}
31+
} catch (IOException e) {
32+
break;
33+
}
2634
// See https://docs.docker.com/engine/api/v1.37/#operation/ContainerAttach
2735
// [8]byte{STREAM_TYPE, 0, 0, 0, SIZE1, SIZE2, SIZE3, SIZE4}[]byte{OUTPUT}
2836

docker-java-transport-okhttp/src/main/java/com/github/dockerjava/okhttp/OkHttpDockerCmdExecFactory.java

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,6 @@
2020
import java.io.IOException;
2121
import java.net.InetAddress;
2222
import java.net.URI;
23-
import java.security.KeyManagementException;
24-
import java.security.KeyStoreException;
25-
import java.security.NoSuchAlgorithmException;
26-
import java.security.UnrecoverableKeyException;
2723
import java.security.cert.X509Certificate;
2824
import java.util.Collections;
2925
import java.util.concurrent.TimeUnit;
@@ -74,10 +70,12 @@ public void init(DockerClientConfig dockerClientConfig) {
7470
}
7571

7672
SSLConfig sslConfig = dockerClientConfig.getSSLConfig();
73+
boolean isSSL = false;
7774
if (sslConfig != null) {
7875
try {
7976
SSLContext sslContext = sslConfig.getSSLContext();
8077
if (sslContext != null) {
78+
isSSL = true;
8179
clientBuilder
8280
.sslSocketFactory(sslContext.getSocketFactory(), new TrustAllX509TrustManager());
8381
}
@@ -94,20 +92,14 @@ public void init(DockerClientConfig dockerClientConfig) {
9492
case "unix":
9593
case "npipe":
9694
baseUrlBuilder = new HttpUrl.Builder()
97-
.scheme("http")
98-
.host("docker" + SOCKET_SUFFIX);
95+
.scheme("http")
96+
.host("docker" + SOCKET_SUFFIX);
9997
break;
10098
case "tcp":
101-
SSLContext sslContext;
102-
try {
103-
sslContext = sslConfig.getSSLContext();
104-
} catch (KeyManagementException | UnrecoverableKeyException | NoSuchAlgorithmException | KeyStoreException e) {
105-
throw new RuntimeException(e);
106-
}
10799
baseUrlBuilder = new HttpUrl.Builder()
108-
.scheme(sslConfig != null && sslContext != null ? "https" : "http")
109-
.host(dockerHost.getHost())
110-
.port(dockerHost.getPort());
100+
.scheme(isSSL ? "https" : "http")
101+
.host(dockerHost.getHost())
102+
.port(dockerHost.getPort());
111103
break;
112104
default:
113105
baseUrlBuilder = HttpUrl.get(dockerHost.toString()).newBuilder();

docker-java/pom.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@
115115
<artifactId>maven-surefire-plugin</artifactId>
116116
<version>${maven-surefire-plugin.version}</version>
117117
<configuration>
118+
<trimStackTrace>false</trimStackTrace>
118119
<rerunFailingTestsCount>3</rerunFailingTestsCount>
119120
<excludedGroups>com.github.dockerjava.junit.category.Integration</excludedGroups>
120121
</configuration>
@@ -133,6 +134,7 @@
133134
</execution>
134135
</executions>
135136
<configuration>
137+
<trimStackTrace>false</trimStackTrace>
136138
<rerunFailingTestsCount>5</rerunFailingTestsCount>
137139
<groups>com.github.dockerjava.junit.category.Integration</groups>
138140
<excludedGroups>com.github.dockerjava.junit.category.AuthIntegration,com.github.dockerjava.junit.category.SwarmModeIntegration</excludedGroups>

docker-java/src/test/java/com/github/dockerjava/cmd/AttachContainerCmdIT.java

Lines changed: 27 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,12 @@
1414
import org.slf4j.LoggerFactory;
1515

1616
import java.io.ByteArrayInputStream;
17-
import java.io.Closeable;
1817
import java.io.File;
1918
import java.io.InputStream;
2019
import java.io.PipedInputStream;
2120
import java.io.PipedOutputStream;
2221
import java.util.concurrent.CountDownLatch;
2322
import java.util.concurrent.TimeUnit;
24-
import java.util.concurrent.atomic.AtomicLong;
2523

2624
import static com.github.dockerjava.junit.DockerRule.DEFAULT_IMAGE;
2725
import static java.util.concurrent.TimeUnit.SECONDS;
@@ -222,58 +220,38 @@ public void attachContainerClosesStdoutWhenContainerExits() throws Exception {
222220
.exec();
223221
LOG.info("Created container: {}", container.toString());
224222

225-
final CountDownLatch started = new CountDownLatch(1);
226-
final AtomicLong startedAtNanos = new AtomicLong();
227-
final CountDownLatch gotLine = new CountDownLatch(1);
228-
final CountDownLatch completed = new CountDownLatch(1);
229-
final AtomicLong gotLineAtNanos = new AtomicLong();
230-
AttachContainerTestCallback callback = new AttachContainerTestCallback() {
231-
@Override
232-
public void onStart(Closeable stream) {
233-
startedAtNanos.set(System.nanoTime());
234-
started.countDown();
235-
super.onStart(stream);
236-
}
237-
238-
@Override
239-
public void onNext(Frame item) {
240-
LOG.info("Got frame: {}", item);
241-
if (item.getStreamType() == StreamType.STDOUT) {
242-
gotLineAtNanos.set(System.nanoTime());
243-
gotLine.countDown();
244-
}
245-
super.onNext(item);
246-
}
247-
248-
@Override
249-
public void onError(Throwable throwable) {
250-
LOG.info("Got error: ", throwable);
251-
super.onError(throwable);
252-
}
253-
254-
@Override
255-
public void onComplete() {
256-
completed.countDown();
257-
super.onComplete();
258-
}
259-
};
260-
261-
try (Closeable ignored = callback) {
262-
dockerClient.attachContainerCmd(container.getId())
263-
.withStdOut(true)
264-
.withFollowStream(true)
265-
.exec(callback);
223+
CountDownLatch gotLine = new CountDownLatch(1);
224+
try (
225+
AttachContainerResultCallback resultCallback = dockerClient.attachContainerCmd(container.getId())
226+
.withStdOut(true)
227+
.withStdErr(true)
228+
.withFollowStream(true)
229+
.exec(new AttachContainerTestCallback() {
230+
@Override
231+
public void onNext(Frame item) {
232+
LOG.info("Got frame: {}", item);
233+
if (item.getStreamType() == StreamType.STDOUT) {
234+
gotLine.countDown();
235+
}
236+
super.onNext(item);
237+
}
238+
239+
@Override
240+
public void onComplete() {
241+
LOG.info("On complete");
242+
super.onComplete();
243+
}
244+
})
245+
) {
246+
resultCallback.awaitStarted(5, SECONDS);
247+
LOG.info("Attach started");
266248

267249
dockerClient.startContainerCmd(container.getId()).exec();
250+
LOG.info("Container started");
268251

269-
assertTrue("Should start in a reasonable time", started.await(30, SECONDS));
270252
assertTrue("Should get first line quickly after the start", gotLine.await(15, SECONDS));
271253

272-
long gotLineDurationSeconds = (gotLineAtNanos.get() - startedAtNanos.get()) / 1_000_000_000L;
273-
LOG.info("Got line from {} for {} seconds", container.getId(), gotLineDurationSeconds);
274-
275-
boolean finished = completed.await(1L + gotLineDurationSeconds, SECONDS);
276-
assertTrue("Should get EOF in a time close to time of getting the first line", finished);
254+
resultCallback.awaitCompletion(5, SECONDS);
277255
}
278256
}
279257

docker-java/src/test/java/com/github/dockerjava/cmd/BuildImageCmdIT.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@
1010
import com.github.dockerjava.core.command.PushImageResultCallback;
1111
import com.github.dockerjava.core.command.WaitContainerResultCallback;
1212
import com.github.dockerjava.core.util.CompressArchiveUtil;
13-
import com.github.dockerjava.utils.RegistryUtils;
13+
import com.github.dockerjava.junit.PrivateRegistryRule;
1414
import net.jcip.annotations.NotThreadSafe;
1515
import org.apache.commons.io.FileUtils;
1616
import org.apache.commons.io.filefilter.TrueFileFilter;
17+
import org.junit.ClassRule;
1718
import org.junit.Rule;
1819
import org.junit.Test;
1920
import org.junit.rules.TemporaryFolder;
@@ -51,6 +52,9 @@
5152
public class BuildImageCmdIT extends CmdIT {
5253
public static final Logger LOG = LoggerFactory.getLogger(BuildImageCmd.class);
5354

55+
@ClassRule
56+
public static PrivateRegistryRule REGISTRY = new PrivateRegistryRule();
57+
5458
@Rule
5559
public TemporaryFolder folder = new TemporaryFolder(new File("target/"));
5660

@@ -195,7 +199,7 @@ public void env() throws Exception {
195199

196200
@Test
197201
public void fromPrivateRegistry() throws Exception {
198-
AuthConfig authConfig = RegistryUtils.runPrivateRegistry(dockerRule.getClient());
202+
AuthConfig authConfig = REGISTRY.getAuthConfig();
199203
String imgName = authConfig.getRegistryAddress() + "/testuser/busybox";
200204

201205
File dockerfile = folder.newFile("Dockerfile");

docker-java/src/test/java/com/github/dockerjava/cmd/CmdIT.java

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,6 @@
1313

1414
import java.util.Arrays;
1515

16-
import static com.github.dockerjava.cmd.CmdIT.FactoryType.JERSEY;
17-
import static com.github.dockerjava.cmd.CmdIT.FactoryType.NETTY;
18-
import static com.github.dockerjava.cmd.CmdIT.FactoryType.OKHTTP;
19-
2016
/**
2117
* @author Kanstantsin Shautsou
2218
*/
@@ -64,9 +60,7 @@ public boolean supportsStdinAttach() {
6460

6561
@Parameterized.Parameters(name = "{index}:{0}")
6662
public static Iterable<FactoryType> data() {
67-
return Arrays.asList(
68-
NETTY, JERSEY, OKHTTP
69-
);
63+
return Arrays.asList(FactoryType.values());
7064
}
7165

7266
@Parameterized.Parameter

docker-java/src/test/java/com/github/dockerjava/cmd/CreateContainerCmdIT.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,11 @@
2626
import com.github.dockerjava.api.model.VolumesFrom;
2727
import com.github.dockerjava.core.command.LogContainerResultCallback;
2828
import com.github.dockerjava.junit.DockerAssume;
29-
import com.github.dockerjava.utils.RegistryUtils;
29+
import com.github.dockerjava.junit.PrivateRegistryRule;
3030
import com.github.dockerjava.utils.TestUtils;
3131
import net.jcip.annotations.NotThreadSafe;
3232
import org.apache.commons.io.FileUtils;
33+
import org.junit.ClassRule;
3334
import org.junit.Rule;
3435
import org.junit.Test;
3536
import org.junit.rules.ExpectedException;
@@ -77,6 +78,9 @@
7778
public class CreateContainerCmdIT extends CmdIT {
7879
public static final Logger LOG = LoggerFactory.getLogger(CreateContainerCmdIT.class);
7980

81+
@ClassRule
82+
public static PrivateRegistryRule REGISTRY = new PrivateRegistryRule();
83+
8084
@Rule
8185
public TemporaryFolder tempDir = new TemporaryFolder(new File("target/"));
8286

@@ -1002,9 +1006,9 @@ public void createContainerWithNetworkID() {
10021006
public void createContainerFromPrivateRegistryWithValidAuth() throws Exception {
10031007
DockerAssume.assumeSwarm(dockerRule.getClient());
10041008

1005-
AuthConfig authConfig = RegistryUtils.runPrivateRegistry(dockerRule.getClient());
1009+
AuthConfig authConfig = REGISTRY.getAuthConfig();
10061010

1007-
String imgName = RegistryUtils.createPrivateImage(dockerRule, "create-container-with-valid-auth");
1011+
String imgName = REGISTRY.createPrivateImage("create-container-with-valid-auth");
10081012

10091013
CreateContainerResponse container = dockerRule.getClient().createContainerCmd(imgName)
10101014
.withAuthConfig(authConfig)
@@ -1015,9 +1019,9 @@ public void createContainerFromPrivateRegistryWithValidAuth() throws Exception {
10151019

10161020
@Test
10171021
public void createContainerFromPrivateRegistryWithNoAuth() throws Exception {
1018-
RegistryUtils.runPrivateRegistry(dockerRule.getClient());
1022+
AuthConfig authConfig = REGISTRY.getAuthConfig();
10191023

1020-
String imgName = RegistryUtils.createPrivateImage(dockerRule, "create-container-with-no-auth");
1024+
String imgName = REGISTRY.createPrivateImage("create-container-with-no-auth");
10211025

10221026
if (TestUtils.isSwarm(dockerRule.getClient())) {
10231027
exception.expect(instanceOf(InternalServerErrorException.class));

docker-java/src/test/java/com/github/dockerjava/cmd/PullImageCmdIT.java

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
import com.github.dockerjava.api.model.Info;
99
import com.github.dockerjava.core.RemoteApiVersion;
1010
import com.github.dockerjava.core.command.PullImageResultCallback;
11-
import com.github.dockerjava.utils.RegistryUtils;
11+
import com.github.dockerjava.junit.PrivateRegistryRule;
12+
import org.junit.ClassRule;
1213
import org.junit.Rule;
1314
import org.junit.Test;
1415
import org.junit.rules.ExpectedException;
@@ -26,6 +27,9 @@
2627
public class PullImageCmdIT extends CmdIT {
2728
private static final Logger LOG = LoggerFactory.getLogger(PullImageCmdIT.class);
2829

30+
@ClassRule
31+
public static PrivateRegistryRule REGISTRY = new PrivateRegistryRule();
32+
2933
@Rule
3034
public ExpectedException exception = ExpectedException.none();
3135

@@ -91,9 +95,9 @@ public void testPullNonExistingImage() throws Exception {
9195

9296
@Test
9397
public void testPullImageWithValidAuth() throws Exception {
94-
AuthConfig authConfig = RegistryUtils.runPrivateRegistry(dockerRule.getClient());
98+
AuthConfig authConfig = REGISTRY.getAuthConfig();
9599

96-
String imgName = RegistryUtils.createPrivateImage(dockerRule, "pull-image-with-valid-auth");
100+
String imgName = REGISTRY.createPrivateImage("pull-image-with-valid-auth");
97101

98102
// stream needs to be fully read in order to close the underlying connection
99103
dockerRule.getClient().pullImageCmd(imgName)
@@ -104,10 +108,9 @@ public void testPullImageWithValidAuth() throws Exception {
104108

105109
@Test
106110
public void testPullImageWithValidAuthAndEmail() throws Exception {
107-
AuthConfig authConfig = RegistryUtils.runPrivateRegistry(dockerRule.getClient())
108-
.withEmail("foo@bar.de");
111+
AuthConfig authConfig = REGISTRY.getAuthConfig().withEmail("foo@bar.de");
109112

110-
String imgName = RegistryUtils.createPrivateImage(dockerRule, "pull-image-with-valid-auth");
113+
String imgName = REGISTRY.createPrivateImage("pull-image-with-valid-auth");
111114

112115
// stream needs to be fully read in order to close the underlying connection
113116
dockerRule.getClient().pullImageCmd(imgName)
@@ -118,9 +121,9 @@ public void testPullImageWithValidAuthAndEmail() throws Exception {
118121

119122
@Test
120123
public void testPullImageWithNoAuth() throws Exception {
121-
RegistryUtils.runPrivateRegistry(dockerRule.getClient());
124+
AuthConfig authConfig = REGISTRY.getAuthConfig();
122125

123-
String imgName = RegistryUtils.createPrivateImage(dockerRule, "pull-image-with-no-auth");
126+
String imgName = REGISTRY.createPrivateImage("pull-image-with-no-auth");
124127

125128
if (isNotSwarm(dockerRule.getClient()) && getVersion(dockerRule.getClient())
126129
.isGreaterOrEqual(RemoteApiVersion.VERSION_1_30)) {
@@ -138,15 +141,14 @@ public void testPullImageWithNoAuth() throws Exception {
138141

139142
@Test
140143
public void testPullImageWithInvalidAuth() throws Exception {
141-
AuthConfig validAuthConfig = RegistryUtils.runPrivateRegistry(dockerRule.getClient());
142-
143-
AuthConfig authConfig = new AuthConfig()
144+
AuthConfig authConfig = REGISTRY.getAuthConfig();
145+
AuthConfig invalidAuthConfig = new AuthConfig()
144146
.withUsername("testuser")
145147
.withPassword("testwrongpassword")
146148
.withEmail("foo@bar.de")
147-
.withRegistryAddress(validAuthConfig.getRegistryAddress());
149+
.withRegistryAddress(authConfig.getRegistryAddress());
148150

149-
String imgName = RegistryUtils.createPrivateImage(dockerRule, "pull-image-with-invalid-auth");
151+
String imgName = REGISTRY.createPrivateImage("pull-image-with-invalid-auth");
150152

151153
if (isNotSwarm(dockerRule.getClient()) && getVersion(dockerRule.getClient())
152154
.isGreaterOrEqual(RemoteApiVersion.VERSION_1_30)) {
@@ -157,7 +159,7 @@ public void testPullImageWithInvalidAuth() throws Exception {
157159

158160
// stream needs to be fully read in order to close the underlying connection
159161
dockerRule.getClient().pullImageCmd(imgName)
160-
.withAuthConfig(authConfig)
162+
.withAuthConfig(invalidAuthConfig)
161163
.exec(new PullImageResultCallback())
162164
.awaitCompletion(30, TimeUnit.SECONDS);
163165
}

0 commit comments

Comments
 (0)