3434import javax .xml .transform .TransformerFactory ;
3535import javax .xml .transform .dom .DOMSource ;
3636import javax .xml .transform .stream .StreamResult ;
37+ import java .io .BufferedOutputStream ;
3738import java .io .File ;
39+ import java .io .FilterOutputStream ;
3840import java .io .IOException ;
41+ import java .io .PrintStream ;
3942import java .lang .reflect .Method ;
4043import java .net .InetAddress ;
4144import java .net .ServerSocket ;
4245import java .net .URL ;
4346import java .net .URLClassLoader ;
4447import java .net .UnknownHostException ;
48+ import java .nio .charset .StandardCharsets ;
4549import java .util .Collections ;
4650import java .util .HashSet ;
4751import 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