Skip to content

Commit f10c9b5

Browse files
committed
Avoid race between file creation and its contents being written
Previously, SampleIntegrationParentApplicationTests assumed that when an output file existed on disk its contents would have been written in their entirety. This assumption does not hold true and causes the test to fail intermittently as it incorrectly determines that the test has produced no output. This commit updates the test to wait for up to 30 seconds for the output files to appear on disk and for the expected content to be found in one of those files. If the files exist but do not contain the expected content the test will keep trying until it does or until too much time as elapsed. Fixes gh-2380
1 parent b359710 commit f10c9b5

File tree

1 file changed

+41
-29
lines changed

1 file changed

+41
-29
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2013 the original author or authors.
2+
* Copyright 2012-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,10 +16,7 @@
1616

1717
package sample.parent.consumer;
1818

19-
import java.util.concurrent.Callable;
20-
import java.util.concurrent.Executors;
21-
import java.util.concurrent.Future;
22-
import java.util.concurrent.TimeUnit;
19+
import java.io.IOException;
2320

2421
import org.junit.AfterClass;
2522
import org.junit.BeforeClass;
@@ -34,12 +31,13 @@
3431
import sample.parent.SampleParentContextApplication;
3532
import sample.parent.producer.ProducerApplication;
3633

37-
import static org.junit.Assert.assertTrue;
34+
import static org.junit.Assert.fail;
3835

3936
/**
4037
* Basic integration tests for service demo application.
4138
*
4239
* @author Dave Syer
40+
* @author Andy Wilkinson
4341
*/
4442
public class SampleIntegrationParentApplicationTests {
4543

@@ -60,30 +58,44 @@ public static void stop() {
6058
@Test
6159
public void testVanillaExchange() throws Exception {
6260
SpringApplication.run(ProducerApplication.class, "World");
63-
String output = getOutput();
64-
assertTrue("Wrong output: " + output, output.contains("Hello World"));
61+
awaitOutputContaining("Hello World");
6562
}
6663

67-
private String getOutput() throws Exception {
68-
Future<String> future = Executors.newSingleThreadExecutor().submit(
69-
new Callable<String>() {
70-
@Override
71-
public String call() throws Exception {
72-
Resource[] resources = new Resource[0];
73-
while (resources.length == 0) {
74-
Thread.sleep(200);
75-
resources = ResourcePatternUtils.getResourcePatternResolver(
76-
new DefaultResourceLoader()).getResources(
77-
"file:target/output/**");
78-
}
79-
StringBuilder builder = new StringBuilder();
80-
for (Resource resource : resources) {
81-
builder.append(new String(StreamUtils
82-
.copyToByteArray(resource.getInputStream())));
83-
}
84-
return builder.toString();
85-
}
86-
});
87-
return future.get(30, TimeUnit.SECONDS);
64+
private void awaitOutputContaining(final String requiredContents) throws Exception {
65+
long endTime = System.currentTimeMillis() + 30000;
66+
String output = null;
67+
while (System.currentTimeMillis() < endTime) {
68+
Resource[] resources = findResources();
69+
if (resources.length == 0) {
70+
Thread.sleep(200);
71+
resources = findResources();
72+
}
73+
else {
74+
output = readResources(resources);
75+
if (output != null && output.contains(requiredContents)) {
76+
return;
77+
}
78+
else {
79+
Thread.sleep(200);
80+
output = readResources(resources);
81+
}
82+
}
83+
}
84+
fail("Timed out awaiting output containing '" + requiredContents
85+
+ "'. Output was '" + output + "'");
86+
}
87+
88+
private Resource[] findResources() throws IOException {
89+
return ResourcePatternUtils.getResourcePatternResolver(
90+
new DefaultResourceLoader()).getResources("file:target/output/**");
91+
}
92+
93+
private String readResources(Resource[] resources) throws IOException {
94+
StringBuilder builder = new StringBuilder();
95+
for (Resource resource : resources) {
96+
builder.append(new String(StreamUtils.copyToByteArray(resource
97+
.getInputStream())));
98+
}
99+
return builder.toString();
88100
}
89101
}

0 commit comments

Comments
 (0)