Skip to content

Commit 299890e

Browse files
authored
Add option to wait for a ready message before running h3spec test (#14)
Motivation: The millisecond delay might not be sufficiently reliable in some environments, and can also be wasteful in how long builds will wait to ensure reliable execution. Modification: Make it possible for the test to snoop on the System.out stream and look for a readiness message instead, as the signal to start running the test. Result: This should produce more reliable build executions.
1 parent 5adc4f8 commit 299890e

File tree

1 file changed

+37
-0
lines changed

1 file changed

+37
-0
lines changed

src/main/java/io/netty/incubating/maven/h3spec/H3SpecMojo.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,18 @@
3434
import javax.xml.transform.TransformerFactory;
3535
import javax.xml.transform.dom.DOMSource;
3636
import javax.xml.transform.stream.StreamResult;
37+
import java.io.BufferedOutputStream;
3738
import java.io.File;
39+
import java.io.FilterOutputStream;
3840
import java.io.IOException;
41+
import java.io.PrintStream;
3942
import java.lang.reflect.Method;
4043
import java.net.InetAddress;
4144
import java.net.ServerSocket;
4245
import java.net.URL;
4346
import java.net.URLClassLoader;
4447
import java.net.UnknownHostException;
48+
import java.nio.charset.StandardCharsets;
4549
import java.util.Collections;
4650
import java.util.HashSet;
4751
import java.util.List;
@@ -83,6 +87,12 @@ public class H3SpecMojo extends AbstractMojo {
8387
@Parameter(property = "delay", defaultValue = "1000", required = true)
8488
private long delay;
8589

90+
/**
91+
* Wait for the test server to print this ready message before running the test
92+
*/
93+
@Parameter(property = "readyMessage")
94+
private String readyMessage;
95+
8696
/**
8797
* Timeout in milliseconds for each test.
8898
*/
@@ -136,7 +146,27 @@ public void execute() throws MojoExecutionException {
136146
port = findRandomOpenPortOnAllLocalInterfaces();
137147
}
138148
CountDownLatch latch = new CountDownLatch(1);
149+
boolean hasReadyMessage = !readyMessage.isEmpty();
150+
CountDownLatch readyMessageLatch = new CountDownLatch(hasReadyMessage ? 1 : 0);
139151
runner = new Thread(() -> {
152+
PrintStream oldOut = hasReadyMessage ? System.out : null;
153+
if (oldOut != null) {
154+
// Filtering stream looking for the ready message
155+
FilterOutputStream filterOut = new FilterOutputStream(oldOut) {
156+
@Override
157+
public void write(byte[] b, int off, int len) throws IOException {
158+
if (new String(b, off, len).contains(readyMessage)) {
159+
readyMessageLatch.countDown();
160+
}
161+
super.write(b, off, len);
162+
}
163+
};
164+
// Buffering stream ensuring that output always goes through the `write(byte[], int, int)` method
165+
BufferedOutputStream bufOut = new BufferedOutputStream(filterOut);
166+
// Finally, Auto-flushing print stream as required for System.out.
167+
PrintStream printStream = new PrintStream(bufOut, true);
168+
System.setOut(printStream);
169+
}
140170
try {
141171
Thread.currentThread().setContextClassLoader(getClassLoader());
142172
Class<?> clazz = Thread.currentThread().getContextClassLoader().loadClass(mainClass);
@@ -146,6 +176,10 @@ public void execute() throws MojoExecutionException {
146176
} catch (Throwable e) {
147177
error.set(e);
148178
latch.countDown();
179+
} finally {
180+
if (oldOut != null) {
181+
System.setOut(oldOut);
182+
}
149183
}
150184
});
151185
runner.setDaemon(true);
@@ -165,6 +199,9 @@ public void execute() throws MojoExecutionException {
165199
Thread.currentThread().interrupt();
166200
}
167201

202+
// Wait for the ready message, if any
203+
readyMessageLatch.await();
204+
168205
if (excludeSpecs == null) {
169206
excludeSpecs = Collections.emptyList();
170207
}

0 commit comments

Comments
 (0)