diff --git a/spring-boot-integration-tests/spring-boot-devtools-tests/src/test/java/org/springframework/boot/devtools/tests/ApplicationLauncher.java b/spring-boot-integration-tests/spring-boot-devtools-tests/src/test/java/org/springframework/boot/devtools/tests/ApplicationLauncher.java index 7b9c05b0b8..02c5b20414 100644 --- a/spring-boot-integration-tests/spring-boot-devtools-tests/src/test/java/org/springframework/boot/devtools/tests/ApplicationLauncher.java +++ b/spring-boot-integration-tests/spring-boot-devtools-tests/src/test/java/org/springframework/boot/devtools/tests/ApplicationLauncher.java @@ -23,6 +23,6 @@ package org.springframework.boot.devtools.tests; */ public interface ApplicationLauncher { - LaunchedApplication launchApplication(JavaLauncher javaLauncher) throws Exception; + LaunchedApplication launchApplication(JvmLauncher javaLauncher) throws Exception; } diff --git a/spring-boot-integration-tests/spring-boot-devtools-tests/src/test/java/org/springframework/boot/devtools/tests/DevToolsIntegrationTests.java b/spring-boot-integration-tests/spring-boot-devtools-tests/src/test/java/org/springframework/boot/devtools/tests/DevToolsIntegrationTests.java index 34ae3f8eb4..648b39cc5a 100644 --- a/spring-boot-integration-tests/spring-boot-devtools-tests/src/test/java/org/springframework/boot/devtools/tests/DevToolsIntegrationTests.java +++ b/spring-boot-integration-tests/spring-boot-devtools-tests/src/test/java/org/springframework/boot/devtools/tests/DevToolsIntegrationTests.java @@ -57,7 +57,7 @@ public class DevToolsIntegrationTests { private final ApplicationLauncher applicationLauncher; @Rule - public JavaLauncher javaLauncher = new JavaLauncher(); + public JvmLauncher javaLauncher = new JvmLauncher(); @Parameters(name = "{0}") public static Object[] parameters() { @@ -106,7 +106,6 @@ public class DevToolsIntegrationTests { controller("com.example.ControllerOne").build(); assertThat(template.getForEntity("http://localhost:" + awaitServerPort() + "/one", String.class).getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); - } @Test @@ -138,11 +137,14 @@ public class DevToolsIntegrationTests { } private int awaitServerPort() throws Exception { - long end = System.currentTimeMillis() + 20000; + long end = System.currentTimeMillis() + 30000; while (this.serverPortFile.length() == 0) { if (System.currentTimeMillis() > end) { - throw new IllegalStateException( - "server.port file was not written within 20 seconds"); + throw new IllegalStateException(String.format( + "server.port file was not written within 30 seconds. " + + "Application output:%n%s", + FileCopyUtils.copyToString(new FileReader( + this.launchedApplication.getStandardOut())))); } Thread.sleep(100); } diff --git a/spring-boot-integration-tests/spring-boot-devtools-tests/src/test/java/org/springframework/boot/devtools/tests/JavaLauncher.java b/spring-boot-integration-tests/spring-boot-devtools-tests/src/test/java/org/springframework/boot/devtools/tests/JvmLauncher.java similarity index 63% rename from spring-boot-integration-tests/spring-boot-devtools-tests/src/test/java/org/springframework/boot/devtools/tests/JavaLauncher.java rename to spring-boot-integration-tests/spring-boot-devtools-tests/src/test/java/org/springframework/boot/devtools/tests/JvmLauncher.java index 114cf4bf18..a21206d788 100644 --- a/spring-boot-integration-tests/spring-boot-devtools-tests/src/test/java/org/springframework/boot/devtools/tests/JavaLauncher.java +++ b/spring-boot-integration-tests/spring-boot-devtools-tests/src/test/java/org/springframework/boot/devtools/tests/JvmLauncher.java @@ -27,9 +27,12 @@ import org.junit.runner.Description; import org.junit.runners.model.Statement; /** - * @author awilkinson + * JUnit {@link TestRule} that launched a JVM and redirects its output to a test + * method-specific location. + * + * @author Andy Wilkinson */ -public class JavaLauncher implements TestRule { +class JvmLauncher implements TestRule { private File outputDirectory; @@ -41,13 +44,36 @@ public class JavaLauncher implements TestRule { return base; } - Process launch(String name, String classpath, String... args) throws IOException { + LaunchedJvm launch(String name, String classpath, String... args) throws IOException { List command = new ArrayList(Arrays .asList(System.getProperty("java.home") + "/bin/java", "-cp", classpath)); command.addAll(Arrays.asList(args)); - return new ProcessBuilder(command.toArray(new String[command.size()])) + File standardOut = new File(this.outputDirectory, name + ".out"); + Process process = new ProcessBuilder(command.toArray(new String[command.size()])) .redirectError(new File(this.outputDirectory, name + ".err")) - .redirectOutput(new File(this.outputDirectory, name + ".out")).start(); + .redirectOutput(standardOut).start(); + return new LaunchedJvm(process, standardOut); + } + + static class LaunchedJvm { + + private final Process process; + + private final File standardOut; + + LaunchedJvm(Process process, File standardOut) { + this.process = process; + this.standardOut = standardOut; + } + + Process getProcess() { + return this.process; + } + + File getStandardOut() { + return this.standardOut; + } + } } diff --git a/spring-boot-integration-tests/spring-boot-devtools-tests/src/test/java/org/springframework/boot/devtools/tests/LaunchedApplication.java b/spring-boot-integration-tests/spring-boot-devtools-tests/src/test/java/org/springframework/boot/devtools/tests/LaunchedApplication.java index 3848fb2a05..bc360fa406 100644 --- a/spring-boot-integration-tests/spring-boot-devtools-tests/src/test/java/org/springframework/boot/devtools/tests/LaunchedApplication.java +++ b/spring-boot-integration-tests/spring-boot-devtools-tests/src/test/java/org/springframework/boot/devtools/tests/LaunchedApplication.java @@ -27,10 +27,13 @@ class LaunchedApplication { private final File classesDirectory; + private final File standardOut; + private final Process[] processes; - LaunchedApplication(File classesDirectory, Process... processes) { + LaunchedApplication(File classesDirectory, File standardOut, Process... processes) { this.classesDirectory = classesDirectory; + this.standardOut = standardOut; this.processes = processes; } @@ -40,6 +43,10 @@ class LaunchedApplication { } } + File getStandardOut() { + return this.standardOut; + } + File getClassesDirectory() { return this.classesDirectory; } diff --git a/spring-boot-integration-tests/spring-boot-devtools-tests/src/test/java/org/springframework/boot/devtools/tests/LocalApplicationLauncher.java b/spring-boot-integration-tests/spring-boot-devtools-tests/src/test/java/org/springframework/boot/devtools/tests/LocalApplicationLauncher.java index debb41dbb6..d76191247d 100644 --- a/spring-boot-integration-tests/spring-boot-devtools-tests/src/test/java/org/springframework/boot/devtools/tests/LocalApplicationLauncher.java +++ b/spring-boot-integration-tests/spring-boot-devtools-tests/src/test/java/org/springframework/boot/devtools/tests/LocalApplicationLauncher.java @@ -20,6 +20,7 @@ import java.io.File; import java.util.ArrayList; import java.util.List; +import org.springframework.boot.devtools.tests.JvmLauncher.LaunchedJvm; import org.springframework.util.FileSystemUtils; import org.springframework.util.StringUtils; @@ -31,11 +32,12 @@ import org.springframework.util.StringUtils; public class LocalApplicationLauncher implements ApplicationLauncher { @Override - public LaunchedApplication launchApplication(JavaLauncher javaLauncher) + public LaunchedApplication launchApplication(JvmLauncher jvmLauncher) throws Exception { - Process process = javaLauncher.launch("local", createApplicationClassPath(), + LaunchedJvm jvm = jvmLauncher.launch("local", createApplicationClassPath(), "com.example.DevToolsTestApplication", "--server.port=0"); - return new LaunchedApplication(new File("target/app"), process); + return new LaunchedApplication(new File("target/app"), jvm.getStandardOut(), + jvm.getProcess()); } protected String createApplicationClassPath() throws Exception { diff --git a/spring-boot-integration-tests/spring-boot-devtools-tests/src/test/java/org/springframework/boot/devtools/tests/RemoteApplicationLauncher.java b/spring-boot-integration-tests/spring-boot-devtools-tests/src/test/java/org/springframework/boot/devtools/tests/RemoteApplicationLauncher.java index c5ff5e5442..1e8ee18b21 100644 --- a/spring-boot-integration-tests/spring-boot-devtools-tests/src/test/java/org/springframework/boot/devtools/tests/RemoteApplicationLauncher.java +++ b/spring-boot-integration-tests/spring-boot-devtools-tests/src/test/java/org/springframework/boot/devtools/tests/RemoteApplicationLauncher.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.List; import org.springframework.boot.devtools.RemoteSpringApplication; +import org.springframework.boot.devtools.tests.JvmLauncher.LaunchedJvm; import org.springframework.util.FileSystemUtils; import org.springframework.util.SocketUtils; import org.springframework.util.StringUtils; @@ -34,18 +35,19 @@ import org.springframework.util.StringUtils; abstract class RemoteApplicationLauncher implements ApplicationLauncher { @Override - public LaunchedApplication launchApplication(JavaLauncher javaLauncher) + public LaunchedApplication launchApplication(JvmLauncher javaLauncher) throws Exception { int port = SocketUtils.findAvailableTcpPort(); - Process application = javaLauncher.launch("app", createApplicationClassPath(), - "com.example.DevToolsTestApplication", "--server.port=" + port, - "--spring.devtools.remote.secret=secret"); - Process remoteSpringApplication = javaLauncher.launch("remote-spring-application", - createRemoteSpringApplicationClassPath(), + LaunchedJvm applicationJvm = javaLauncher.launch("app", + createApplicationClassPath(), "com.example.DevToolsTestApplication", + "--server.port=" + port, "--spring.devtools.remote.secret=secret"); + LaunchedJvm remoteSpringApplicationJvm = javaLauncher.launch( + "remote-spring-application", createRemoteSpringApplicationClassPath(), RemoteSpringApplication.class.getName(), "--spring.devtools.remote.secret=secret", "http://localhost:" + port); - return new LaunchedApplication(new File("target/remote"), application, - remoteSpringApplication); + return new LaunchedApplication(new File("target/remote"), + applicationJvm.getStandardOut(), applicationJvm.getProcess(), + remoteSpringApplicationJvm.getProcess()); } protected abstract String createApplicationClassPath() throws Exception;