Merge branch '2.0.x'
This commit is contained in:
commit
1bb788f5c2
|
@ -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 {
|
||||||
.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 {
|
||||||
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,15 +131,16 @@ 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");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -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 {
|
||||||
@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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 @@
|
||||||
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 {
|
||||||
|
|
||||||
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 {
|
||||||
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;
|
||||||
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 {
|
||||||
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());
|
||||||
LaunchedJvm remoteSpringApplicationJvm = javaLauncher.launch(
|
BiFunction<Integer, File, Process> remoteRestarter = getRemoteRestarter(
|
||||||
"remote-spring-application", createRemoteSpringApplicationClassPath(),
|
javaLauncher);
|
||||||
RemoteSpringApplication.class.getName(),
|
|
||||||
"--spring.devtools.remote.secret=secret", "http://localhost:12345");
|
|
||||||
awaitRemoteSpringApplication(remoteSpringApplicationJvm.getStandardOut());
|
|
||||||
return new LaunchedApplication(new File("target/remote"),
|
return new LaunchedApplication(new File("target/remote"),
|
||||||
applicationJvm.getStandardOut(), applicationJvm.getStandardError(),
|
applicationJvm.getStandardOut(), applicationJvm.getStandardError(),
|
||||||
applicationJvm.getProcess(), remoteSpringApplicationJvm.getProcess());
|
applicationJvm.getProcess(), remoteRestarter.apply(port, null),
|
||||||
|
remoteRestarter);
|
||||||
|
}
|
||||||
|
|
||||||
|
private BiFunction<Integer, File, Process> getRemoteRestarter(
|
||||||
|
JvmLauncher javaLauncher) {
|
||||||
|
return (port, classesDirectory) -> {
|
||||||
|
try {
|
||||||
|
LaunchedJvm remoteSpringApplicationJvm = javaLauncher.launch(
|
||||||
|
"remote-spring-application",
|
||||||
|
createRemoteSpringApplicationClassPath(classesDirectory),
|
||||||
|
RemoteSpringApplication.class.getName(),
|
||||||
|
"--spring.devtools.remote.secret=secret",
|
||||||
|
"http://localhost:" + port);
|
||||||
|
awaitRemoteSpringApplication(remoteSpringApplicationJvm.getStandardOut());
|
||||||
|
return 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)
|
||||||
File remoteDirectory = new File("target/remote");
|
throws Exception {
|
||||||
FileSystemUtils.deleteRecursively(remoteDirectory);
|
if (classesDirectory == null) {
|
||||||
remoteDirectory.mkdirs();
|
File remoteDirectory = new File("target/remote");
|
||||||
FileSystemUtils.copyRecursively(new File("target/test-classes/com"),
|
FileSystemUtils.deleteRecursively(remoteDirectory);
|
||||||
new File("target/remote/com"));
|
remoteDirectory.mkdirs();
|
||||||
|
FileSystemUtils.copyRecursively(new File("target/test-classes/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()) {
|
||||||
|
|
Loading…
Reference in New Issue