Commit 1bb788f5 authored by Madhura Bhave's avatar Madhura Bhave

Merge branch '2.0.x'

parents bab111b3 657a5347
...@@ -59,13 +59,6 @@ public class DevToolsIntegrationTests { ...@@ -59,13 +59,6 @@ public class DevToolsIntegrationTests {
@Rule @Rule
public JvmLauncher javaLauncher = new JvmLauncher(); public JvmLauncher javaLauncher = new JvmLauncher();
@Parameters(name = "{0}")
public static Object[] parameters() {
return new Object[] { new Object[] { new LocalApplicationLauncher() },
new Object[] { new ExplodedRemoteApplicationLauncher() },
new Object[] { new JarFileRemoteApplicationLauncher() } };
}
public DevToolsIntegrationTests(ApplicationLauncher applicationLauncher) { public DevToolsIntegrationTests(ApplicationLauncher applicationLauncher) {
this.applicationLauncher = applicationLauncher; this.applicationLauncher = applicationLauncher;
} }
...@@ -93,20 +86,23 @@ public class DevToolsIntegrationTests { ...@@ -93,20 +86,23 @@ public class DevToolsIntegrationTests {
.isEqualTo(HttpStatus.NOT_FOUND); .isEqualTo(HttpStatus.NOT_FOUND);
controller("com.example.ControllerOne").withRequestMapping("one") controller("com.example.ControllerOne").withRequestMapping("one")
.withRequestMapping("two").build(); .withRequestMapping("two").build();
urlBase = "http://localhost:" + awaitServerPort();
assertThat(template.getForObject(urlBase + "/one", String.class)) assertThat(template.getForObject(urlBase + "/one", String.class))
.isEqualTo("one"); .isEqualTo("one");
assertThat(template.getForObject("http://localhost:" + awaitServerPort() + "/two", assertThat(template.getForObject(urlBase + "/two", String.class))
String.class)).isEqualTo("two"); .isEqualTo("two");
} }
@Test @Test
public void removeARequestMappingFromAnExistingController() throws Exception { public void removeARequestMappingFromAnExistingController() throws Exception {
TestRestTemplate template = new TestRestTemplate(); TestRestTemplate template = new TestRestTemplate();
assertThat(template.getForObject("http://localhost:" + awaitServerPort() + "/one", String urlBase = "http://localhost:" + awaitServerPort();
String.class)).isEqualTo("one"); assertThat(template.getForObject(urlBase + "/one", String.class))
.isEqualTo("one");
controller("com.example.ControllerOne").build(); controller("com.example.ControllerOne").build();
assertThat(template.getForEntity("http://localhost:" + awaitServerPort() + "/one", urlBase = "http://localhost:" + awaitServerPort();
String.class).getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); assertThat(template.getForEntity(urlBase + "/one", String.class).getStatusCode())
.isEqualTo(HttpStatus.NOT_FOUND);
} }
@Test @Test
...@@ -118,10 +114,11 @@ public class DevToolsIntegrationTests { ...@@ -118,10 +114,11 @@ public class DevToolsIntegrationTests {
assertThat(template.getForEntity(urlBase + "/two", String.class).getStatusCode()) assertThat(template.getForEntity(urlBase + "/two", String.class).getStatusCode())
.isEqualTo(HttpStatus.NOT_FOUND); .isEqualTo(HttpStatus.NOT_FOUND);
controller("com.example.ControllerTwo").withRequestMapping("two").build(); controller("com.example.ControllerTwo").withRequestMapping("two").build();
urlBase = "http://localhost:" + awaitServerPort();
assertThat(template.getForObject(urlBase + "/one", String.class)) assertThat(template.getForObject(urlBase + "/one", String.class))
.isEqualTo("one"); .isEqualTo("one");
assertThat(template.getForObject("http://localhost:" + awaitServerPort() + "/two", assertThat(template.getForObject(urlBase + "/two", String.class))
String.class)).isEqualTo("two"); .isEqualTo("two");
} }
...@@ -134,14 +131,15 @@ public class DevToolsIntegrationTests { ...@@ -134,14 +131,15 @@ public class DevToolsIntegrationTests {
assertThat(template.getForEntity(urlBase + "/two", String.class).getStatusCode()) assertThat(template.getForEntity(urlBase + "/two", String.class).getStatusCode())
.isEqualTo(HttpStatus.NOT_FOUND); .isEqualTo(HttpStatus.NOT_FOUND);
controller("com.example.ControllerTwo").withRequestMapping("two").build(); controller("com.example.ControllerTwo").withRequestMapping("two").build();
urlBase = "http://localhost:" + awaitServerPort();
assertThat(template.getForObject(urlBase + "/one", String.class)) assertThat(template.getForObject(urlBase + "/one", String.class))
.isEqualTo("one"); .isEqualTo("one");
assertThat(template.getForObject("http://localhost:" + awaitServerPort() + "/two", assertThat(template.getForObject(urlBase + "/two", String.class))
String.class)).isEqualTo("two"); .isEqualTo("two");
controller("com.example.ControllerTwo").withRequestMapping("two") controller("com.example.ControllerTwo").withRequestMapping("two")
.withRequestMapping("three").build(); .withRequestMapping("three").build();
assertThat(template.getForObject( urlBase = "http://localhost:" + awaitServerPort();
"http://localhost:" + awaitServerPort() + "/three", String.class)) assertThat(template.getForObject(urlBase + "/three", String.class))
.isEqualTo("three"); .isEqualTo("three");
} }
...@@ -155,10 +153,11 @@ public class DevToolsIntegrationTests { ...@@ -155,10 +153,11 @@ public class DevToolsIntegrationTests {
assertThat(template.getForEntity(urlBase + "/two", String.class).getStatusCode()) assertThat(template.getForEntity(urlBase + "/two", String.class).getStatusCode())
.isEqualTo(HttpStatus.NOT_FOUND); .isEqualTo(HttpStatus.NOT_FOUND);
controller("com.example.ControllerTwo").withRequestMapping("two").build(); controller("com.example.ControllerTwo").withRequestMapping("two").build();
urlBase = "http://localhost:" + awaitServerPort();
assertThat(template.getForObject(urlBase + "/one", String.class)) assertThat(template.getForObject(urlBase + "/one", String.class))
.isEqualTo("one"); .isEqualTo("one");
assertThat(template.getForObject("http://localhost:" + awaitServerPort() + "/two", assertThat(template.getForObject(urlBase + "/two", String.class))
String.class)).isEqualTo("two"); .isEqualTo("two");
controller("com.example.ControllerOne").withRequestMapping("one") controller("com.example.ControllerOne").withRequestMapping("one")
.withRequestMapping("three").build(); .withRequestMapping("three").build();
urlBase = "http://localhost:" + awaitServerPort(); urlBase = "http://localhost:" + awaitServerPort();
...@@ -173,12 +172,14 @@ public class DevToolsIntegrationTests { ...@@ -173,12 +172,14 @@ public class DevToolsIntegrationTests {
@Test @Test
public void deleteAController() throws Exception { public void deleteAController() throws Exception {
TestRestTemplate template = new TestRestTemplate(); TestRestTemplate template = new TestRestTemplate();
assertThat(template.getForObject("http://localhost:" + awaitServerPort() + "/one", String urlBase = "http://localhost:" + awaitServerPort();
String.class)).isEqualTo("one"); assertThat(template.getForObject(urlBase + "/one", String.class))
.isEqualTo("one");
assertThat(new File(this.launchedApplication.getClassesDirectory(), assertThat(new File(this.launchedApplication.getClassesDirectory(),
"com/example/ControllerOne.class").delete()).isTrue(); "com/example/ControllerOne.class").delete()).isTrue();
assertThat(template.getForEntity("http://localhost:" + awaitServerPort() + "/one", urlBase = "http://localhost:" + awaitServerPort();
String.class).getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); assertThat(template.getForEntity(urlBase + "/one", String.class).getStatusCode())
.isEqualTo(HttpStatus.NOT_FOUND);
} }
...@@ -191,18 +192,20 @@ public class DevToolsIntegrationTests { ...@@ -191,18 +192,20 @@ public class DevToolsIntegrationTests {
assertThat(template.getForEntity(urlBase + "/two", String.class).getStatusCode()) assertThat(template.getForEntity(urlBase + "/two", String.class).getStatusCode())
.isEqualTo(HttpStatus.NOT_FOUND); .isEqualTo(HttpStatus.NOT_FOUND);
controller("com.example.ControllerTwo").withRequestMapping("two").build(); controller("com.example.ControllerTwo").withRequestMapping("two").build();
urlBase = "http://localhost:" + awaitServerPort();
assertThat(template.getForObject(urlBase + "/one", String.class)) assertThat(template.getForObject(urlBase + "/one", String.class))
.isEqualTo("one"); .isEqualTo("one");
assertThat(template.getForObject("http://localhost:" + awaitServerPort() + "/two", assertThat(template.getForObject(urlBase + "/two", String.class))
String.class)).isEqualTo("two"); .isEqualTo("two");
assertThat(new File(this.launchedApplication.getClassesDirectory(), assertThat(new File(this.launchedApplication.getClassesDirectory(),
"com/example/ControllerTwo.class").delete()).isTrue(); "com/example/ControllerTwo.class").delete()).isTrue();
assertThat(template.getForEntity("http://localhost:" + awaitServerPort() + "/two", urlBase = "http://localhost:" + awaitServerPort();
String.class).getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); assertThat(template.getForEntity(urlBase + "/two", String.class).getStatusCode())
.isEqualTo(HttpStatus.NOT_FOUND);
} }
private int awaitServerPort() throws Exception { private int awaitServerPort() throws Exception {
long end = System.currentTimeMillis() + 30000; long end = System.currentTimeMillis() + 40000;
while (this.serverPortFile.length() == 0) { while (this.serverPortFile.length() == 0) {
System.out.println("Getting server port " + this.serverPortFile.length()); System.out.println("Getting server port " + this.serverPortFile.length());
if (System.currentTimeMillis() > end) { if (System.currentTimeMillis() > end) {
...@@ -220,6 +223,8 @@ public class DevToolsIntegrationTests { ...@@ -220,6 +223,8 @@ public class DevToolsIntegrationTests {
int port = Integer.valueOf(FileCopyUtils.copyToString(portReader)); int port = Integer.valueOf(FileCopyUtils.copyToString(portReader));
this.serverPortFile.delete(); this.serverPortFile.delete();
System.out.println("Got port " + port); System.out.println("Got port " + port);
this.launchedApplication.restartRemote(port);
Thread.sleep(1000);
return port; return port;
} }
...@@ -228,6 +233,13 @@ public class DevToolsIntegrationTests { ...@@ -228,6 +233,13 @@ public class DevToolsIntegrationTests {
this.launchedApplication.getClassesDirectory()); this.launchedApplication.getClassesDirectory());
} }
@Parameters(name = "{0}")
public static Object[] parameters() {
return new Object[] { new Object[] { new LocalApplicationLauncher() },
new Object[] { new ExplodedRemoteApplicationLauncher() },
new Object[] { new JarFileRemoteApplicationLauncher() } };
}
private static final class ControllerBuilder { private static final class ControllerBuilder {
private final List<String> mappings = new ArrayList<>(); private final List<String> mappings = new ArrayList<>();
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
package org.springframework.boot.devtools.tests; package org.springframework.boot.devtools.tests;
import java.io.File; import java.io.File;
import java.util.function.BiFunction;
/** /**
* An application launched by {@link ApplicationLauncher}. * An application launched by {@link ApplicationLauncher}.
...@@ -31,18 +32,38 @@ class LaunchedApplication { ...@@ -31,18 +32,38 @@ class LaunchedApplication {
private final File standardError; private final File standardError;
private final Process[] processes; private final Process localProcess;
private Process remoteProcess;
private final BiFunction<Integer, File, Process> remoteProcessRestarter;
LaunchedApplication(File classesDirectory, File standardOut, File standardError, LaunchedApplication(File classesDirectory, File standardOut, File standardError,
Process... processes) { Process localProcess, Process remoteProcess,
BiFunction<Integer, File, Process> remoteProcessRestarter) {
this.classesDirectory = classesDirectory; this.classesDirectory = classesDirectory;
this.standardOut = standardOut; this.standardOut = standardOut;
this.standardError = standardError; this.standardError = standardError;
this.processes = processes; this.localProcess = localProcess;
this.remoteProcess = remoteProcess;
this.remoteProcessRestarter = remoteProcessRestarter;
}
public void restartRemote(int port) throws InterruptedException {
if (this.remoteProcessRestarter != null) {
stop(this.remoteProcess);
this.remoteProcess = this.remoteProcessRestarter.apply(port,
this.classesDirectory);
}
} }
void stop() throws InterruptedException { void stop() throws InterruptedException {
for (Process process : this.processes) { stop(this.localProcess);
stop(this.remoteProcess);
}
private void stop(Process process) throws InterruptedException {
if (process != null) {
process.destroy(); process.destroy();
process.waitFor(); process.waitFor();
} }
......
...@@ -37,7 +37,7 @@ public class LocalApplicationLauncher implements ApplicationLauncher { ...@@ -37,7 +37,7 @@ public class LocalApplicationLauncher implements ApplicationLauncher {
LaunchedJvm jvm = jvmLauncher.launch("local", createApplicationClassPath(), LaunchedJvm jvm = jvmLauncher.launch("local", createApplicationClassPath(),
"com.example.DevToolsTestApplication", "--server.port=0"); "com.example.DevToolsTestApplication", "--server.port=0");
return new LaunchedApplication(new File("target/app"), jvm.getStandardOut(), return new LaunchedApplication(new File("target/app"), jvm.getStandardOut(),
jvm.getStandardError(), jvm.getProcess()); jvm.getStandardError(), jvm.getProcess(), null, null);
} }
protected String createApplicationClassPath() throws Exception { protected String createApplicationClassPath() throws Exception {
......
...@@ -20,6 +20,7 @@ import java.io.File; ...@@ -20,6 +20,7 @@ import java.io.File;
import java.io.FileReader; import java.io.FileReader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.function.BiFunction;
import org.springframework.boot.devtools.RemoteSpringApplication; import org.springframework.boot.devtools.RemoteSpringApplication;
import org.springframework.boot.devtools.tests.JvmLauncher.LaunchedJvm; import org.springframework.boot.devtools.tests.JvmLauncher.LaunchedJvm;
...@@ -40,26 +41,46 @@ abstract class RemoteApplicationLauncher implements ApplicationLauncher { ...@@ -40,26 +41,46 @@ abstract class RemoteApplicationLauncher implements ApplicationLauncher {
throws Exception { throws Exception {
LaunchedJvm applicationJvm = javaLauncher.launch("app", LaunchedJvm applicationJvm = javaLauncher.launch("app",
createApplicationClassPath(), "com.example.DevToolsTestApplication", createApplicationClassPath(), "com.example.DevToolsTestApplication",
"--server.port=12345", "--spring.devtools.remote.secret=secret"); "--server.port=0", "--spring.devtools.remote.secret=secret");
awaitServerPort(applicationJvm.getStandardOut()); int port = awaitServerPort(applicationJvm.getStandardOut());
BiFunction<Integer, File, Process> remoteRestarter = getRemoteRestarter(
javaLauncher);
return new LaunchedApplication(new File("target/remote"),
applicationJvm.getStandardOut(), applicationJvm.getStandardError(),
applicationJvm.getProcess(), remoteRestarter.apply(port, null),
remoteRestarter);
}
private BiFunction<Integer, File, Process> getRemoteRestarter(
JvmLauncher javaLauncher) {
return (port, classesDirectory) -> {
try {
LaunchedJvm remoteSpringApplicationJvm = javaLauncher.launch( LaunchedJvm remoteSpringApplicationJvm = javaLauncher.launch(
"remote-spring-application", createRemoteSpringApplicationClassPath(), "remote-spring-application",
createRemoteSpringApplicationClassPath(classesDirectory),
RemoteSpringApplication.class.getName(), RemoteSpringApplication.class.getName(),
"--spring.devtools.remote.secret=secret", "http://localhost:12345"); "--spring.devtools.remote.secret=secret",
"http://localhost:" + port);
awaitRemoteSpringApplication(remoteSpringApplicationJvm.getStandardOut()); awaitRemoteSpringApplication(remoteSpringApplicationJvm.getStandardOut());
return new LaunchedApplication(new File("target/remote"), return remoteSpringApplicationJvm.getProcess();
applicationJvm.getStandardOut(), applicationJvm.getStandardError(), }
applicationJvm.getProcess(), remoteSpringApplicationJvm.getProcess()); catch (Exception ex) {
throw new IllegalStateException(ex);
}
};
} }
protected abstract String createApplicationClassPath() throws Exception; protected abstract String createApplicationClassPath() throws Exception;
private String createRemoteSpringApplicationClassPath() throws Exception { private String createRemoteSpringApplicationClassPath(File classesDirectory)
throws Exception {
if (classesDirectory == null) {
File remoteDirectory = new File("target/remote"); File remoteDirectory = new File("target/remote");
FileSystemUtils.deleteRecursively(remoteDirectory); FileSystemUtils.deleteRecursively(remoteDirectory);
remoteDirectory.mkdirs(); remoteDirectory.mkdirs();
FileSystemUtils.copyRecursively(new File("target/test-classes/com"), FileSystemUtils.copyRecursively(new File("target/test-classes/com"),
new File("target/remote/com")); new File("target/remote/com"));
}
List<String> entries = new ArrayList<>(); List<String> entries = new ArrayList<>();
entries.add("target/remote"); entries.add("target/remote");
for (File jar : new File("target/dependencies").listFiles()) { for (File jar : new File("target/dependencies").listFiles()) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment