Minimize and centralize assumptions about build output

Closes gh-15471
pull/15473/head
Andy Wilkinson 6 years ago
parent 7d0a7a65c8
commit 61d04db0d7

@ -141,10 +141,10 @@ public class Neo4jPropertiesTests {
@Test @Test
public void embeddedModeWithRelativeLocation() { public void embeddedModeWithRelativeLocation() {
Neo4jProperties properties = load(true, Neo4jProperties properties = load(true,
"spring.data.neo4j.uri=file:target/neo4j/my.db"); "spring.data.neo4j.uri=file:relative/path/to/my.db");
Configuration configuration = properties.createConfiguration(); Configuration configuration = properties.createConfiguration();
assertDriver(configuration, Neo4jProperties.EMBEDDED_DRIVER, assertDriver(configuration, Neo4jProperties.EMBEDDED_DRIVER,
"file:target/neo4j/my.db"); "file:relative/path/to/my.db");
} }
private static void assertDriver(Configuration actual, String driver, String uri) { private static void assertDriver(Configuration actual, String driver, String uri) {

@ -24,6 +24,7 @@ import org.junit.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.testsupport.BuildOutput;
import org.springframework.boot.testsupport.rule.OutputCapture; import org.springframework.boot.testsupport.rule.OutputCapture;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -36,6 +37,8 @@ import static org.assertj.core.api.Assertions.assertThat;
*/ */
public class FreeMarkerAutoConfigurationTests { public class FreeMarkerAutoConfigurationTests {
private final BuildOutput buildOutput = new BuildOutput(getClass());
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(FreeMarkerAutoConfiguration.class)); .withConfiguration(AutoConfigurations.of(FreeMarkerAutoConfiguration.class));
@ -68,19 +71,24 @@ public class FreeMarkerAutoConfigurationTests {
@Test @Test
public void emptyTemplateLocation() { public void emptyTemplateLocation() {
new File("target/test-classes/templates/empty-directory").mkdir(); File emptyDirectory = new File(this.buildOutput.getTestResourcesLocation(),
this.contextRunner.withPropertyValues("spring.freemarker.templateLoaderPath:" "empty-templates/empty-directory");
+ "classpath:/templates/empty-directory/").run((context) -> { emptyDirectory.mkdirs();
}); this.contextRunner
.withPropertyValues("spring.freemarker.templateLoaderPath:"
+ "classpath:/empty-templates/empty-directory/")
.run((context) -> assertThat(this.output.toString())
.doesNotContain("Cannot find template location"));
} }
@Test @Test
public void nonExistentLocationAndEmptyLocation() { public void nonExistentLocationAndEmptyLocation() {
new File("target/test-classes/templates/empty-directory").mkdir(); new File(this.buildOutput.getTestResourcesLocation(),
"empty-templates/empty-directory").mkdirs();
this.contextRunner.withPropertyValues("spring.freemarker.templateLoaderPath:" this.contextRunner.withPropertyValues("spring.freemarker.templateLoaderPath:"
+ "classpath:/does-not-exist/,classpath:/templates/empty-directory/") + "classpath:/does-not-exist/,classpath:/empty-templates/empty-directory/")
.run((context) -> { .run((context) -> assertThat(this.output.toString())
}); .doesNotContain("Cannot find template location"));
} }
} }

@ -31,6 +31,7 @@ import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.springframework.boot.test.util.TestPropertyValues; import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.boot.testsupport.BuildOutput;
import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.ClassPathResource;
import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletRequest;
@ -53,6 +54,8 @@ import static org.assertj.core.api.Assertions.assertThat;
*/ */
public class GroovyTemplateAutoConfigurationTests { public class GroovyTemplateAutoConfigurationTests {
private final BuildOutput buildOutput = new BuildOutput(getClass());
private AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); private AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
@Before @Before
@ -76,7 +79,8 @@ public class GroovyTemplateAutoConfigurationTests {
@Test @Test
public void emptyTemplateLocation() { public void emptyTemplateLocation() {
new File("target/test-classes/templates/empty-directory").mkdir(); new File(this.buildOutput.getTestResourcesLocation(),
"empty-templates/empty-directory").mkdirs();
registerAndRefreshContext("spring.groovy.template.resource-loader-path:" registerAndRefreshContext("spring.groovy.template.resource-loader-path:"
+ "classpath:/templates/empty-directory/"); + "classpath:/templates/empty-directory/");
} }

@ -244,7 +244,7 @@ public class DataSourceAutoConfigurationTests {
public DataSource dataSource() { public DataSource dataSource() {
this.pool = new BasicDataSource(); this.pool = new BasicDataSource();
this.pool.setDriverClassName("org.hsqldb.jdbcDriver"); this.pool.setDriverClassName("org.hsqldb.jdbcDriver");
this.pool.setUrl("jdbc:hsqldb:target/overridedb"); this.pool.setUrl("jdbc:hsqldb:mem:overridedb");
this.pool.setUsername("sa"); this.pool.setUsername("sa");
return this.pool; return this.pool;
} }

@ -17,6 +17,7 @@
package org.springframework.boot.autoconfigure.mongo.embedded; package org.springframework.boot.autoconfigure.mongo.embedded;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -27,7 +28,9 @@ import de.flapdoodle.embed.mongo.distribution.Feature;
import de.flapdoodle.embed.mongo.distribution.Version; import de.flapdoodle.embed.mongo.distribution.Version;
import org.bson.Document; import org.bson.Document;
import org.junit.After; import org.junit.After;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
@ -52,6 +55,9 @@ import static org.assertj.core.api.Assertions.assertThat;
*/ */
public class EmbeddedMongoAutoConfigurationTests { public class EmbeddedMongoAutoConfigurationTests {
@Rule
public final TemporaryFolder temp = new TemporaryFolder();
private AnnotationConfigApplicationContext context; private AnnotationConfigApplicationContext context;
@After @After
@ -143,8 +149,8 @@ public class EmbeddedMongoAutoConfigurationTests {
} }
@Test @Test
public void mongoWritesToCustomDatabaseDir() { public void mongoWritesToCustomDatabaseDir() throws IOException {
File customDatabaseDir = new File("target/custom-database-dir"); File customDatabaseDir = this.temp.newFolder("custom-database-dir");
FileSystemUtils.deleteRecursively(customDatabaseDir); FileSystemUtils.deleteRecursively(customDatabaseDir);
load("spring.mongodb.embedded.storage.databaseDir=" load("spring.mongodb.embedded.storage.databaseDir="
+ customDatabaseDir.getPath()); + customDatabaseDir.getPath());

@ -39,6 +39,7 @@ import org.thymeleaf.templateresolver.ITemplateResolver;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration; import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.test.util.TestPropertyValues; import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.boot.testsupport.BuildOutput;
import org.springframework.boot.testsupport.rule.OutputCapture; import org.springframework.boot.testsupport.rule.OutputCapture;
import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebApplicationContext; import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@ -61,6 +62,8 @@ import static org.assertj.core.api.Assertions.assertThat;
*/ */
public class ThymeleafReactiveAutoConfigurationTests { public class ThymeleafReactiveAutoConfigurationTests {
private final BuildOutput buildOutput = new BuildOutput(getClass());
@Rule @Rule
public final OutputCapture output = new OutputCapture(); public final OutputCapture output = new OutputCapture();
@ -184,9 +187,10 @@ public class ThymeleafReactiveAutoConfigurationTests {
@Test @Test
public void templateLocationEmpty() { public void templateLocationEmpty() {
new File("target/test-classes/templates/empty-directory").mkdir(); new File(this.buildOutput.getTestResourcesLocation(),
"empty-templates/empty-directory").mkdirs();
load(BaseConfiguration.class, load(BaseConfiguration.class,
"spring.thymeleaf.prefix:classpath:/templates/empty-directory/"); "spring.thymeleaf.prefix:classpath:/empty-templates/empty-directory/");
assertThat(this.output.toString()) assertThat(this.output.toString())
.doesNotContain("Cannot find template location"); .doesNotContain("Cannot find template location");
} }

@ -42,6 +42,7 @@ import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.test.rule.OutputCapture; import org.springframework.boot.test.rule.OutputCapture;
import org.springframework.boot.test.util.TestPropertyValues; import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.boot.testsupport.BuildOutput;
import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.filter.OrderedCharacterEncodingFilter; import org.springframework.boot.web.servlet.filter.OrderedCharacterEncodingFilter;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext;
@ -75,6 +76,8 @@ import static org.hamcrest.Matchers.containsString;
*/ */
public class ThymeleafServletAutoConfigurationTests { public class ThymeleafServletAutoConfigurationTests {
private final BuildOutput buildOutput = new BuildOutput(getClass());
@Rule @Rule
public OutputCapture output = new OutputCapture(); public OutputCapture output = new OutputCapture();
@ -176,9 +179,10 @@ public class ThymeleafServletAutoConfigurationTests {
@Test @Test
public void templateLocationEmpty() { public void templateLocationEmpty() {
new File("target/test-classes/templates/empty-directory").mkdir(); new File(this.buildOutput.getTestResourcesLocation(),
"empty-templates/empty-directory").mkdirs();
load(BaseConfiguration.class, load(BaseConfiguration.class,
"spring.thymeleaf.prefix:classpath:/templates/empty-directory/"); "spring.thymeleaf.prefix:classpath:/empty-templates/empty-directory/");
} }
@Test @Test

@ -17,6 +17,7 @@
package org.springframework.boot.autoconfigure.transaction.jta; package org.springframework.boot.autoconfigure.transaction.jta;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.UnknownHostException; import java.net.UnknownHostException;
@ -35,8 +36,9 @@ import com.atomikos.icatch.config.UserTransactionService;
import com.atomikos.icatch.jta.UserTransactionManager; import com.atomikos.icatch.jta.UserTransactionManager;
import com.atomikos.jms.AtomikosConnectionFactoryBean; import com.atomikos.jms.AtomikosConnectionFactoryBean;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration; import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration;
@ -55,7 +57,6 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.jta.JtaTransactionManager; import org.springframework.transaction.jta.JtaTransactionManager;
import org.springframework.util.FileSystemUtils;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@ -72,12 +73,10 @@ import static org.mockito.Mockito.mock;
*/ */
public class JtaAutoConfigurationTests { public class JtaAutoConfigurationTests {
private AnnotationConfigApplicationContext context; @Rule
public final TemporaryFolder temp = new TemporaryFolder();
@Before private AnnotationConfigApplicationContext context;
public void cleanUpLogs() {
FileSystemUtils.deleteRecursively(new File("target/transaction-logs"));
}
@After @After
public void closeContext() { public void closeContext() {
@ -155,15 +154,16 @@ public class JtaAutoConfigurationTests {
} }
@Test @Test
public void defaultAtomikosTransactionManagerName() { public void defaultAtomikosTransactionManagerName() throws IOException {
this.context = new AnnotationConfigApplicationContext(); this.context = new AnnotationConfigApplicationContext();
TestPropertyValues.of("spring.jta.logDir:target/transaction-logs") File logs = this.temp.newFolder("jta");
TestPropertyValues.of("spring.jta.logDir:" + logs.getAbsolutePath())
.applyTo(this.context); .applyTo(this.context);
this.context.register(JtaPropertiesConfiguration.class, this.context.register(JtaPropertiesConfiguration.class,
AtomikosJtaConfiguration.class); AtomikosJtaConfiguration.class);
this.context.refresh(); this.context.refresh();
File epochFile = new File("target/transaction-logs/tmlog0.log"); File epochFile = new File(logs, "tmlog0.log");
assertThat(epochFile.isFile()).isTrue(); assertThat(epochFile.isFile()).isTrue();
} }

@ -18,7 +18,9 @@ package org.springframework.boot.cli;
import java.io.IOException; import java.io.IOException;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.springframework.boot.cli.infrastructure.CommandLineInvoker; import org.springframework.boot.cli.infrastructure.CommandLineInvoker;
import org.springframework.boot.cli.infrastructure.CommandLineInvoker.Invocation; import org.springframework.boot.cli.infrastructure.CommandLineInvoker.Invocation;
@ -36,7 +38,10 @@ import static org.junit.Assert.assertThat;
*/ */
public class CommandLineIT { public class CommandLineIT {
private final CommandLineInvoker cli = new CommandLineInvoker(); @Rule
public final TemporaryFolder temp = new TemporaryFolder();
private final CommandLineInvoker cli = new CommandLineInvoker(this.temp);
@Test @Test
public void hintProducesListOfValidCommands() public void hintProducesListOfValidCommands()

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2017 the original author or authors. * Copyright 2012-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -18,7 +18,9 @@ package org.springframework.boot.cli;
import java.io.File; import java.io.File;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.springframework.boot.cli.command.archive.JarCommand; import org.springframework.boot.cli.command.archive.JarCommand;
import org.springframework.boot.cli.infrastructure.CommandLineInvoker; import org.springframework.boot.cli.infrastructure.CommandLineInvoker;
@ -43,8 +45,11 @@ public class JarCommandIT {
private static final boolean JAVA_9_OR_LATER = isClassPresent( private static final boolean JAVA_9_OR_LATER = isClassPresent(
"java.security.cert.URICertStoreParameters"); "java.security.cert.URICertStoreParameters");
@Rule
public final TemporaryFolder temp = new TemporaryFolder();
private final CommandLineInvoker cli = new CommandLineInvoker( private final CommandLineInvoker cli = new CommandLineInvoker(
new File("src/it/resources/jar-command")); new File("src/it/resources/jar-command"), this.temp);
@Test @Test
public void noArguments() throws Exception { public void noArguments() throws Exception {
@ -66,7 +71,7 @@ public class JarCommandIT {
@Test @Test
public void jarCreationWithGrabResolver() throws Exception { public void jarCreationWithGrabResolver() throws Exception {
File jar = new File("target/test-app.jar"); File jar = new File(this.temp.getRoot(), "test-app.jar");
Invocation invocation = this.cli.invoke("run", jar.getAbsolutePath(), Invocation invocation = this.cli.invoke("run", jar.getAbsolutePath(),
"bad.groovy"); "bad.groovy");
invocation.await(); invocation.await();
@ -93,7 +98,7 @@ public class JarCommandIT {
@Test @Test
public void jarCreation() throws Exception { public void jarCreation() throws Exception {
File jar = new File("target/test-app.jar"); File jar = new File(this.temp.getRoot(), "test-app.jar");
Invocation invocation = this.cli.invoke("jar", jar.getAbsolutePath(), Invocation invocation = this.cli.invoke("jar", jar.getAbsolutePath(),
"jar.groovy"); "jar.groovy");
invocation.await(); invocation.await();
@ -127,7 +132,7 @@ public class JarCommandIT {
@Test @Test
public void jarCreationWithIncludes() throws Exception { public void jarCreationWithIncludes() throws Exception {
File jar = new File("target/test-app.jar"); File jar = new File(this.temp.getRoot(), "test-app.jar");
Invocation invocation = this.cli.invoke("jar", jar.getAbsolutePath(), "--include", Invocation invocation = this.cli.invoke("jar", jar.getAbsolutePath(), "--include",
"-public/**,-resources/**", "jar.groovy"); "-public/**,-resources/**", "jar.groovy");
invocation.await(); invocation.await();

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2017 the original author or authors. * Copyright 2012-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -18,7 +18,9 @@ package org.springframework.boot.cli;
import java.io.File; import java.io.File;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.springframework.boot.cli.command.archive.WarCommand; import org.springframework.boot.cli.command.archive.WarCommand;
import org.springframework.boot.cli.infrastructure.CommandLineInvoker; import org.springframework.boot.cli.infrastructure.CommandLineInvoker;
@ -35,12 +37,15 @@ import static org.assertj.core.api.Assertions.assertThat;
*/ */
public class WarCommandIT { public class WarCommandIT {
@Rule
public final TemporaryFolder temp = new TemporaryFolder();
private final CommandLineInvoker cli = new CommandLineInvoker( private final CommandLineInvoker cli = new CommandLineInvoker(
new File("src/it/resources/war-command")); new File("src/it/resources/war-command"), this.temp);
@Test @Test
public void warCreation() throws Exception { public void warCreation() throws Exception {
File war = new File("target/test-app.war"); File war = new File(this.temp.getRoot(), "test-app.war");
Invocation invocation = this.cli.invoke("war", war.getAbsolutePath(), Invocation invocation = this.cli.invoke("war", war.getAbsolutePath(),
"war.groovy"); "war.groovy");
invocation.await(); invocation.await();

@ -32,6 +32,9 @@ import java.util.stream.Collectors;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream; import java.util.zip.ZipInputStream;
import org.junit.rules.TemporaryFolder;
import org.springframework.boot.testsupport.BuildOutput;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.StreamUtils; import org.springframework.util.StreamUtils;
@ -46,12 +49,15 @@ public final class CommandLineInvoker {
private final File workingDirectory; private final File workingDirectory;
public CommandLineInvoker() { private final TemporaryFolder temp;
this(new File("."));
public CommandLineInvoker(TemporaryFolder temp) {
this(new File("."), temp);
} }
public CommandLineInvoker(File workingDirectory) { public CommandLineInvoker(File workingDirectory, TemporaryFolder temp) {
this.workingDirectory = workingDirectory; this.workingDirectory = workingDirectory;
this.temp = temp;
} }
public Invocation invoke(String... args) throws IOException { public Invocation invoke(String... args) throws IOException {
@ -69,9 +75,9 @@ public final class CommandLineInvoker {
} }
private File findLaunchScript() throws IOException { private File findLaunchScript() throws IOException {
File unpacked = new File("target/unpacked-cli"); File unpacked = new File(this.temp.getRoot(), "unpacked-cli");
if (!unpacked.isDirectory()) { if (!unpacked.isDirectory()) {
File zip = new File("target") File zip = new BuildOutput(getClass()).getRootLocation()
.listFiles((pathname) -> pathname.getName().endsWith("-bin.zip"))[0]; .listFiles((pathname) -> pathname.getName().endsWith("-bin.zip"))[0];
try (ZipInputStream input = new ZipInputStream(new FileInputStream(zip))) { try (ZipInputStream input = new ZipInputStream(new FileInputStream(zip))) {
ZipEntry entry; ZipEntry entry;

@ -32,6 +32,7 @@ import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.junit.Assume; import org.junit.Assume;
import org.junit.rules.TemporaryFolder;
import org.junit.rules.TestRule; import org.junit.rules.TestRule;
import org.junit.runner.Description; import org.junit.runner.Description;
import org.junit.runners.model.Statement; import org.junit.runners.model.Statement;
@ -42,6 +43,7 @@ import org.springframework.boot.cli.command.archive.JarCommand;
import org.springframework.boot.cli.command.grab.GrabCommand; import org.springframework.boot.cli.command.grab.GrabCommand;
import org.springframework.boot.cli.command.run.RunCommand; import org.springframework.boot.cli.command.run.RunCommand;
import org.springframework.boot.test.rule.OutputCapture; import org.springframework.boot.test.rule.OutputCapture;
import org.springframework.boot.testsupport.BuildOutput;
import org.springframework.util.FileCopyUtils; import org.springframework.util.FileCopyUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
@ -54,6 +56,10 @@ import org.springframework.util.StringUtils;
*/ */
public class CliTester implements TestRule { public class CliTester implements TestRule {
private final TemporaryFolder temp = new TemporaryFolder();
private final BuildOutput buildOutput = new BuildOutput(getClass());
private final OutputCapture outputCapture = new OutputCapture(); private final OutputCapture outputCapture = new OutputCapture();
private long timeout = TimeUnit.MINUTES.toMillis(6); private long timeout = TimeUnit.MINUTES.toMillis(6);
@ -62,6 +68,8 @@ public class CliTester implements TestRule {
private final String prefix; private final String prefix;
private File serverPortFile;
public CliTester(String prefix) { public CliTester(String prefix) {
this.prefix = prefix; this.prefix = prefix;
} }
@ -75,14 +83,15 @@ public class CliTester implements TestRule {
boolean classpathUpdated = false; boolean classpathUpdated = false;
for (String arg : args) { for (String arg : args) {
if (arg.startsWith("--classpath=")) { if (arg.startsWith("--classpath=")) {
arg = arg + ":" + new File("target/test-classes").getAbsolutePath(); arg = arg + ":"
+ this.buildOutput.getTestClassesLocation().getAbsolutePath();
classpathUpdated = true; classpathUpdated = true;
} }
updatedArgs.add(arg); updatedArgs.add(arg);
} }
if (!classpathUpdated) { if (!classpathUpdated) {
updatedArgs.add( updatedArgs.add("--classpath=.:"
"--classpath=.:" + new File("target/test-classes").getAbsolutePath()); + this.buildOutput.getTestClassesLocation().getAbsolutePath());
} }
Future<RunCommand> future = submitCommand(new RunCommand(), Future<RunCommand> future = submitCommand(new RunCommand(),
StringUtils.toStringArray(updatedArgs)); StringUtils.toStringArray(updatedArgs));
@ -111,8 +120,8 @@ public class CliTester implements TestRule {
System.setProperty("server.port", "0"); System.setProperty("server.port", "0");
System.setProperty("spring.application.class.name", System.setProperty("spring.application.class.name",
"org.springframework.boot.cli.CliTesterSpringApplication"); "org.springframework.boot.cli.CliTesterSpringApplication");
System.setProperty("portfile", this.serverPortFile = new File(this.temp.newFolder(), "server.port");
new File("target/server.port").getAbsolutePath()); System.setProperty("portfile", this.serverPortFile.getAbsolutePath());
try { try {
command.run(sources); command.run(sources);
return command; return command;
@ -168,8 +177,9 @@ public class CliTester implements TestRule {
@Override @Override
public Statement apply(Statement base, Description description) { public Statement apply(Statement base, Description description) {
final Statement statement = CliTester.this.outputCapture final Statement statement = this.temp.apply(
.apply(new RunLauncherStatement(base), description); this.outputCapture.apply(new RunLauncherStatement(base), description),
description);
return new Statement() { return new Statement() {
@Override @Override
@ -180,6 +190,7 @@ public class CliTester implements TestRule {
.contains("integration")); .contains("integration"));
statement.evaluate(); statement.evaluate();
} }
}; };
} }
@ -190,7 +201,7 @@ public class CliTester implements TestRule {
public String getHttpOutput(String uri) { public String getHttpOutput(String uri) {
try { try {
int port = Integer.parseInt( int port = Integer.parseInt(
FileCopyUtils.copyToString(new FileReader("target/server.port"))); FileCopyUtils.copyToString(new FileReader(this.serverPortFile)));
InputStream stream = URI.create("http://localhost:" + port + uri).toURL() InputStream stream = URI.create("http://localhost:" + port + uri).toURL()
.openStream(); .openStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); BufferedReader reader = new BufferedReader(new InputStreamReader(stream));

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2017 the original author or authors. * Copyright 2012-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -22,6 +22,7 @@ import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.springframework.boot.cli.command.grab.GrabCommand; import org.springframework.boot.cli.command.grab.GrabCommand;
import org.springframework.util.FileSystemUtils; import org.springframework.util.FileSystemUtils;
@ -37,13 +38,15 @@ import static org.junit.Assert.fail;
*/ */
public class GrabCommandIntegrationTests { public class GrabCommandIntegrationTests {
@Rule
public TemporaryFolder temp = new TemporaryFolder();
@Rule @Rule
public CliTester cli = new CliTester("src/test/resources/grab-samples/"); public CliTester cli = new CliTester("src/test/resources/grab-samples/");
@Before @Before
@After @After
public void deleteLocalRepository() { public void deleteLocalRepository() {
FileSystemUtils.deleteRecursively(new File("target/repository"));
System.clearProperty("grape.root"); System.clearProperty("grape.root");
System.clearProperty("groovy.grape.report.downloads"); System.clearProperty("groovy.grape.report.downloads");
} }
@ -51,13 +54,13 @@ public class GrabCommandIntegrationTests {
@Test @Test
public void grab() throws Exception { public void grab() throws Exception {
System.setProperty("grape.root", "target"); System.setProperty("grape.root", this.temp.getRoot().getAbsolutePath());
System.setProperty("groovy.grape.report.downloads", "true"); System.setProperty("groovy.grape.report.downloads", "true");
// Use --autoconfigure=false to limit the amount of downloaded dependencies // Use --autoconfigure=false to limit the amount of downloaded dependencies
String output = this.cli.grab("grab.groovy", "--autoconfigure=false"); String output = this.cli.grab("grab.groovy", "--autoconfigure=false");
assertThat(new File("target/repository/joda-time/joda-time").isDirectory()) assertThat(new File(this.temp.getRoot(), "repository/joda-time/joda-time"))
.isTrue(); .isDirectory();
// Should be resolved from local repository cache // Should be resolved from local repository cache
assertThat(output.contains("Downloading: file:")).isTrue(); assertThat(output.contains("Downloading: file:")).isTrue();
} }
@ -76,13 +79,12 @@ public class GrabCommandIntegrationTests {
@Test @Test
public void customMetadata() throws Exception { public void customMetadata() throws Exception {
System.setProperty("grape.root", "target"); System.setProperty("grape.root", this.temp.getRoot().getAbsolutePath());
File repository = new File(this.temp.getRoot().getAbsolutePath(), "repository");
FileSystemUtils.copyRecursively( FileSystemUtils.copyRecursively(
new File("src/test/resources/grab-samples/repository"), new File("src/test/resources/grab-samples/repository"), repository);
new File("target/repository"));
this.cli.grab("customDependencyManagement.groovy", "--autoconfigure=false"); this.cli.grab("customDependencyManagement.groovy", "--autoconfigure=false");
assertThat(new File("target/repository/javax/ejb/ejb-api/3.0").isDirectory()) assertThat(new File(repository, "javax/ejb/ejb-api/3.0")).isDirectory();
.isTrue();
} }
} }

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2017 the original author or authors. * Copyright 2012-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -28,8 +28,6 @@ import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.TemporaryFolder; import org.junit.rules.TemporaryFolder;
import org.springframework.util.FileSystemUtils;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
@ -50,9 +48,7 @@ public class InstallerTests {
@Before @Before
public void setUp() throws IOException { public void setUp() throws IOException {
System.setProperty("spring.home", "target"); System.setProperty("spring.home", this.tempFolder.getRoot().getAbsolutePath());
FileSystemUtils.deleteRecursively(new File("target/lib"));
this.installer = new Installer(this.resolver); this.installer = new Installer(this.resolver);
} }
@ -119,7 +115,7 @@ public class InstallerTests {
private Set<String> getNamesOfFilesInLibExt() { private Set<String> getNamesOfFilesInLibExt() {
Set<String> names = new HashSet<>(); Set<String> names = new HashSet<>();
for (File file : new File("target/lib/ext").listFiles()) { for (File file : new File(this.tempFolder.getRoot(), "lib/ext").listFiles()) {
names.add(file.getName()); names.add(file.getName());
} }
return names; return names;

@ -16,6 +16,7 @@
package org.springframework.boot.devtools.autoconfigure; package org.springframework.boot.devtools.autoconfigure;
import java.io.IOException;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
@ -23,7 +24,9 @@ import javax.sql.DataSource;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.ConfigurableApplicationContext;
@ -40,9 +43,13 @@ import static org.mockito.Mockito.verify;
public class DevToolsPooledDataSourceAutoConfigurationTests public class DevToolsPooledDataSourceAutoConfigurationTests
extends AbstractDevToolsDataSourceAutoConfigurationTests { extends AbstractDevToolsDataSourceAutoConfigurationTests {
@Rule
public final TemporaryFolder temp = new TemporaryFolder();
@Before @Before
public void before() { public void before() throws IOException {
System.setProperty("derby.stream.error.file", "target/derby.log"); System.setProperty("derby.stream.error.file",
this.temp.newFile("derby.log").getAbsolutePath());
} }
@After @After

@ -26,6 +26,7 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.context.TestConfiguration; import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.testsupport.BuildOutput;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation; import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation;
import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler; import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler;
@ -55,23 +56,26 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder
@AutoConfigureRestDocs @AutoConfigureRestDocs
public class MockMvcRestDocsAutoConfigurationAdvancedConfigurationIntegrationTests { public class MockMvcRestDocsAutoConfigurationAdvancedConfigurationIntegrationTests {
@Before
public void deleteSnippets() {
FileSystemUtils.deleteRecursively(new File("target/generated-snippets"));
}
@Autowired @Autowired
private MockMvc mvc; private MockMvc mvc;
@Autowired @Autowired
private RestDocumentationResultHandler documentationHandler; private RestDocumentationResultHandler documentationHandler;
private File generatedSnippets;
@Before
public void deleteSnippets() {
this.generatedSnippets = new File(new BuildOutput(getClass()).getRootLocation(),
"generated-snippets");
FileSystemUtils.deleteRecursively(this.generatedSnippets);
}
@Test @Test
public void snippetGeneration() throws Exception { public void snippetGeneration() throws Exception {
this.mvc.perform(get("/")).andDo(this.documentationHandler.document(links( this.mvc.perform(get("/")).andDo(this.documentationHandler.document(links(
linkWithRel("self").description("Canonical location of this resource")))); linkWithRel("self").description("Canonical location of this resource"))));
File defaultSnippetsDir = new File( File defaultSnippetsDir = new File(this.generatedSnippets, "snippet-generation");
"target/generated-snippets/snippet-generation");
assertThat(defaultSnippetsDir).exists(); assertThat(defaultSnippetsDir).exists();
assertThat(new File(defaultSnippetsDir, "curl-request.md")) assertThat(new File(defaultSnippetsDir, "curl-request.md"))
.has(contentContaining("'http://localhost:8080/'")); .has(contentContaining("'http://localhost:8080/'"));

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2017 the original author or authors. * Copyright 2012-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -25,6 +25,7 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.testsupport.BuildOutput;
import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
import org.springframework.util.FileSystemUtils; import org.springframework.util.FileSystemUtils;
@ -43,18 +44,22 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder
@AutoConfigureRestDocs(uriScheme = "https", uriHost = "api.example.com", uriPort = 443) @AutoConfigureRestDocs(uriScheme = "https", uriHost = "api.example.com", uriPort = 443)
public class MockMvcRestDocsAutoConfigurationIntegrationTests { public class MockMvcRestDocsAutoConfigurationIntegrationTests {
@Autowired
private MockMvc mvc;
private File generatedSnippets;
@Before @Before
public void deleteSnippets() { public void deleteSnippets() {
FileSystemUtils.deleteRecursively(new File("target/generated-snippets")); this.generatedSnippets = new File(new BuildOutput(getClass()).getRootLocation(),
"generated-snippets");
FileSystemUtils.deleteRecursively(this.generatedSnippets);
} }
@Autowired
private MockMvc mvc;
@Test @Test
public void defaultSnippetsAreWritten() throws Exception { public void defaultSnippetsAreWritten() throws Exception {
this.mvc.perform(get("/")).andDo(document("default-snippets")); this.mvc.perform(get("/")).andDo(document("default-snippets"));
File defaultSnippetsDir = new File("target/generated-snippets/default-snippets"); File defaultSnippetsDir = new File(this.generatedSnippets, "default-snippets");
assertThat(defaultSnippetsDir).exists(); assertThat(defaultSnippetsDir).exists();
assertThat(new File(defaultSnippetsDir, "curl-request.adoc")) assertThat(new File(defaultSnippetsDir, "curl-request.adoc"))
.has(contentContaining("'https://api.example.com/'")); .has(contentContaining("'https://api.example.com/'"));

@ -28,6 +28,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.context.TestConfiguration; import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.testsupport.BuildOutput;
import org.springframework.boot.web.server.LocalServerPort; import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation; import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation;
@ -59,14 +60,18 @@ public class RestAssuredRestDocsAutoConfigurationAdvancedConfigurationIntegratio
@LocalServerPort @LocalServerPort
private int port; private int port;
@Autowired
private RequestSpecification documentationSpec;
private File generatedSnippets;
@Before @Before
public void deleteSnippets() { public void deleteSnippets() {
FileSystemUtils.deleteRecursively(new File("target/generated-snippets")); this.generatedSnippets = new File(new BuildOutput(getClass()).getRootLocation(),
"generated-snippets");
FileSystemUtils.deleteRecursively(this.generatedSnippets);
} }
@Autowired
private RequestSpecification documentationSpec;
@Test @Test
public void snippetGeneration() { public void snippetGeneration() {
given(this.documentationSpec) given(this.documentationSpec)
@ -74,7 +79,7 @@ public class RestAssuredRestDocsAutoConfigurationAdvancedConfigurationIntegratio
preprocessRequest(modifyUris().scheme("https") preprocessRequest(modifyUris().scheme("https")
.host("api.example.com").removePort()))) .host("api.example.com").removePort())))
.when().port(this.port).get("/").then().assertThat().statusCode(is(200)); .when().port(this.port).get("/").then().assertThat().statusCode(is(200));
File defaultSnippetsDir = new File("target/generated-snippets/default-snippets"); File defaultSnippetsDir = new File(this.generatedSnippets, "default-snippets");
assertThat(defaultSnippetsDir).exists(); assertThat(defaultSnippetsDir).exists();
assertThat(new File(defaultSnippetsDir, "curl-request.md")) assertThat(new File(defaultSnippetsDir, "curl-request.md"))
.has(contentContaining("'https://api.example.com/'")); .has(contentContaining("'https://api.example.com/'"));

@ -27,6 +27,7 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.testsupport.BuildOutput;
import org.springframework.boot.web.server.LocalServerPort; import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.FileSystemUtils; import org.springframework.util.FileSystemUtils;
@ -51,14 +52,18 @@ public class RestAssuredRestDocsAutoConfigurationIntegrationTests {
@LocalServerPort @LocalServerPort
private int port; private int port;
@Autowired
private RequestSpecification documentationSpec;
private File generatedSnippets;
@Before @Before
public void deleteSnippets() { public void deleteSnippets() {
FileSystemUtils.deleteRecursively(new File("target/generated-snippets")); this.generatedSnippets = new File(new BuildOutput(getClass()).getRootLocation(),
"generated-snippets");
FileSystemUtils.deleteRecursively(this.generatedSnippets);
} }
@Autowired
private RequestSpecification documentationSpec;
@Test @Test
public void defaultSnippetsAreWritten() { public void defaultSnippetsAreWritten() {
given(this.documentationSpec) given(this.documentationSpec)
@ -66,7 +71,7 @@ public class RestAssuredRestDocsAutoConfigurationIntegrationTests {
preprocessRequest(modifyUris().scheme("https") preprocessRequest(modifyUris().scheme("https")
.host("api.example.com").removePort()))) .host("api.example.com").removePort())))
.when().port(this.port).get("/").then().assertThat().statusCode(is(200)); .when().port(this.port).get("/").then().assertThat().statusCode(is(200));
File defaultSnippetsDir = new File("target/generated-snippets/default-snippets"); File defaultSnippetsDir = new File(this.generatedSnippets, "default-snippets");
assertThat(defaultSnippetsDir).exists(); assertThat(defaultSnippetsDir).exists();
assertThat(new File(defaultSnippetsDir, "curl-request.adoc")) assertThat(new File(defaultSnippetsDir, "curl-request.adoc"))
.has(contentContaining("'https://api.example.com/'")); .has(contentContaining("'https://api.example.com/'"));

@ -26,6 +26,7 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest; import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
import org.springframework.boot.test.context.TestConfiguration; import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.testsupport.BuildOutput;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation; import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation;
import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler; import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler;
@ -51,19 +52,23 @@ import static org.springframework.restdocs.webtestclient.WebTestClientRestDocume
@AutoConfigureRestDocs(uriScheme = "https", uriHost = "api.example.com", uriPort = 443) @AutoConfigureRestDocs(uriScheme = "https", uriHost = "api.example.com", uriPort = 443)
public class WebTestClientRestDocsAutoConfigurationAdvancedConfigurationIntegrationTests { public class WebTestClientRestDocsAutoConfigurationAdvancedConfigurationIntegrationTests {
@Autowired
private WebTestClient webTestClient;
private File generatedSnippets;
@Before @Before
public void deleteSnippets() { public void deleteSnippets() {
FileSystemUtils.deleteRecursively(new File("target/generated-snippets")); this.generatedSnippets = new File(new BuildOutput(getClass()).getRootLocation(),
"generated-snippets");
FileSystemUtils.deleteRecursively(this.generatedSnippets);
} }
@Autowired
private WebTestClient webTestClient;
@Test @Test
public void defaultSnippetsAreWritten() throws Exception { public void defaultSnippetsAreWritten() throws Exception {
this.webTestClient.get().uri("/").exchange().expectStatus().is2xxSuccessful() this.webTestClient.get().uri("/").exchange().expectStatus().is2xxSuccessful()
.expectBody().consumeWith(document("default-snippets")); .expectBody().consumeWith(document("default-snippets"));
File defaultSnippetsDir = new File("target/generated-snippets/default-snippets"); File defaultSnippetsDir = new File(this.generatedSnippets, "default-snippets");
assertThat(defaultSnippetsDir).exists(); assertThat(defaultSnippetsDir).exists();
assertThat(new File(defaultSnippetsDir, "curl-request.md")) assertThat(new File(defaultSnippetsDir, "curl-request.md"))
.has(contentContaining("'https://api.example.com/'")); .has(contentContaining("'https://api.example.com/'"));

@ -25,6 +25,7 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest; import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
import org.springframework.boot.testsupport.BuildOutput;
import org.springframework.security.test.context.support.WithMockUser; import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient; import org.springframework.test.web.reactive.server.WebTestClient;
@ -44,19 +45,23 @@ import static org.springframework.restdocs.webtestclient.WebTestClientRestDocume
@AutoConfigureRestDocs(uriScheme = "https", uriHost = "api.example.com", uriPort = 443) @AutoConfigureRestDocs(uriScheme = "https", uriHost = "api.example.com", uriPort = 443)
public class WebTestClientRestDocsAutoConfigurationIntegrationTests { public class WebTestClientRestDocsAutoConfigurationIntegrationTests {
@Autowired
private WebTestClient webTestClient;
private File generatedSnippets;
@Before @Before
public void deleteSnippets() { public void deleteSnippets() {
FileSystemUtils.deleteRecursively(new File("target/generated-snippets")); this.generatedSnippets = new File(new BuildOutput(getClass()).getRootLocation(),
"generated-snippets");
FileSystemUtils.deleteRecursively(this.generatedSnippets);
} }
@Autowired
private WebTestClient webTestClient;
@Test @Test
public void defaultSnippetsAreWritten() throws Exception { public void defaultSnippetsAreWritten() throws Exception {
this.webTestClient.get().uri("/").exchange().expectStatus().is2xxSuccessful() this.webTestClient.get().uri("/").exchange().expectStatus().is2xxSuccessful()
.expectBody().consumeWith(document("default-snippets")); .expectBody().consumeWith(document("default-snippets"));
File defaultSnippetsDir = new File("target/generated-snippets/default-snippets"); File defaultSnippetsDir = new File(this.generatedSnippets, "default-snippets");
assertThat(defaultSnippetsDir).exists(); assertThat(defaultSnippetsDir).exists();
assertThat(new File(defaultSnippetsDir, "curl-request.adoc")) assertThat(new File(defaultSnippetsDir, "curl-request.adoc"))
.has(contentContaining("'https://api.example.com/'")); .has(contentContaining("'https://api.example.com/'"));

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2017 the original author or authors. * Copyright 2012-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -46,9 +46,9 @@ public class FileUtilsTests {
private File originDirectory; private File originDirectory;
@Before @Before
public void init() { public void init() throws IOException {
this.outputDirectory = new File("target/test/remove"); this.outputDirectory = this.temporaryFolder.newFolder("remove");
this.originDirectory = new File("target/test/keep"); this.originDirectory = this.temporaryFolder.newFolder("keep");
FileSystemUtils.deleteRecursively(this.outputDirectory); FileSystemUtils.deleteRecursively(this.outputDirectory);
FileSystemUtils.deleteRecursively(this.originDirectory); FileSystemUtils.deleteRecursively(this.originDirectory);
this.outputDirectory.mkdirs(); this.outputDirectory.mkdirs();

@ -0,0 +1,81 @@
/*
* Copyright 2012-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.testsupport;
import java.io.File;
import java.net.URISyntaxException;
/**
* Provides access to build output locations in a build system and IDE agnostic manner.
*
* @author Andy Wilkinson
*/
public class BuildOutput {
private final Class<?> testClass;
public BuildOutput(Class<?> testClass) {
this.testClass = testClass;
}
/**
* Returns the location into which test classes have been built.
* @return test classes location
*/
public File getTestClassesLocation() {
try {
File location = new File(this.testClass.getProtectionDomain().getCodeSource()
.getLocation().toURI());
if (location.getPath().endsWith(path("target", "test-classes"))) {
return location;
}
throw new IllegalStateException(
"Unexpected test classes location '" + location + "'");
}
catch (URISyntaxException ex) {
throw new IllegalStateException("Invalid test class code source location",
ex);
}
}
/**
* Returns the location into which test resources have been built.
* @return test resources location
*/
public File getTestResourcesLocation() {
File testClassesLocation = getTestClassesLocation();
if (testClassesLocation.getPath().endsWith(path("target", "test-classes"))) {
return testClassesLocation;
}
throw new IllegalStateException(
"Cannot determine test resources location from classes location '"
+ testClassesLocation + "'");
}
/**
* Returns the root location into which build output is written.
* @return root location
*/
public File getRootLocation() {
return getTestClassesLocation().getParentFile();
}
private String path(String... components) {
return File.separator + String.join(File.separator, components);
}
}

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2017 the original author or authors. * Copyright 2012-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,7 +16,6 @@
package org.springframework.boot.testsupport.context; package org.springframework.boot.testsupport.context;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
@ -25,6 +24,7 @@ import org.junit.Test;
import org.springframework.asm.Opcodes; import org.springframework.asm.Opcodes;
import org.springframework.beans.DirectFieldAccessor; import org.springframework.beans.DirectFieldAccessor;
import org.springframework.boot.testsupport.BuildOutput;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
@ -44,6 +44,8 @@ import static org.assertj.core.api.Assertions.assertThat;
*/ */
public abstract class AbstractConfigurationClassTests { public abstract class AbstractConfigurationClassTests {
private final BuildOutput buildOutput = new BuildOutput(getClass());
private ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); private ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
@Test @Test
@ -83,7 +85,7 @@ public abstract class AbstractConfigurationClassTests {
private boolean isTestClass(Resource resource) throws IOException { private boolean isTestClass(Resource resource) throws IOException {
return resource.getFile().getAbsolutePath() return resource.getFile().getAbsolutePath()
.contains("target" + File.separator + "test-classes"); .startsWith(this.buildOutput.getTestClassesLocation().getAbsolutePath());
} }
private boolean isPublic(MethodMetadata methodMetadata) { private boolean isPublic(MethodMetadata methodMetadata) {

@ -43,6 +43,7 @@ import org.springframework.boot.WebApplicationType;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.boot.context.event.ApplicationPreparedEvent; import org.springframework.boot.context.event.ApplicationPreparedEvent;
import org.springframework.boot.env.EnvironmentPostProcessor; import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.boot.testsupport.BuildOutput;
import org.springframework.boot.testsupport.rule.OutputCapture; import org.springframework.boot.testsupport.rule.OutputCapture;
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext;
@ -73,6 +74,8 @@ import static org.assertj.core.api.Assertions.assertThat;
*/ */
public class ConfigFileApplicationListenerTests { public class ConfigFileApplicationListenerTests {
private final BuildOutput buildOutput = new BuildOutput(getClass());
private final StandardEnvironment environment = new StandardEnvironment(); private final StandardEnvironment environment = new StandardEnvironment();
private final SpringApplication application = new SpringApplication(); private final SpringApplication application = new SpringApplication();
@ -486,8 +489,9 @@ public class ConfigFileApplicationListenerTests {
String suffix = (profile != null) ? "-" + profile : ""; String suffix = (profile != null) ? "-" + profile : "";
String string = ".properties)"; String string = ".properties)";
return "Loaded config file '" return "Loaded config file '"
+ new File("target/test-classes/application" + suffix + ".properties") + new File(this.buildOutput.getTestResourcesLocation(),
.getAbsoluteFile().toURI().toString() "application" + suffix + ".properties").getAbsoluteFile().toURI()
.toString()
+ "' (classpath:/application" + suffix + string; + "' (classpath:/application" + suffix + string;
} }

@ -33,6 +33,7 @@ import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.slf4j.bridge.SLF4JBridgeHandler; import org.slf4j.bridge.SLF4JBridgeHandler;
import org.slf4j.impl.StaticLoggerBinder; import org.slf4j.impl.StaticLoggerBinder;
@ -88,6 +89,9 @@ public class LoggingApplicationListenerTests {
@Rule @Rule
public OutputCapture outputCapture = new OutputCapture(); public OutputCapture outputCapture = new OutputCapture();
@Rule
public final TemporaryFolder temp = new TemporaryFolder();
private final LoggingApplicationListener initializer = new LoggingApplicationListener(); private final LoggingApplicationListener initializer = new LoggingApplicationListener();
private final LoggerContext loggerContext = (LoggerContext) StaticLoggerBinder private final LoggerContext loggerContext = (LoggerContext) StaticLoggerBinder
@ -100,12 +104,14 @@ public class LoggingApplicationListenerTests {
private final GenericApplicationContext context = new GenericApplicationContext(); private final GenericApplicationContext context = new GenericApplicationContext();
private File logFile;
@Before @Before
public void init() throws SecurityException, IOException { public void init() throws SecurityException, IOException {
LogManager.getLogManager().readConfiguration( LogManager.getLogManager().readConfiguration(
JavaLoggingSystem.class.getResourceAsStream("logging.properties")); JavaLoggingSystem.class.getResourceAsStream("logging.properties"));
multicastEvent(new ApplicationStartingEvent(new SpringApplication(), NO_ARGS)); multicastEvent(new ApplicationStartingEvent(new SpringApplication(), NO_ARGS));
new File("target/foo.log").delete(); this.logFile = new File(this.temp.getRoot(), "foo.log");
new File(tmpDir() + "/spring.log").delete(); new File(tmpDir() + "/spring.log").delete();
ConfigurableEnvironment environment = this.context.getEnvironment(); ConfigurableEnvironment environment = this.context.getEnvironment();
ConfigurationPropertySources.attach(environment); ConfigurationPropertySources.attach(environment);
@ -216,7 +222,7 @@ public class LoggingApplicationListenerTests {
public void addLogFileProperty() { public void addLogFileProperty() {
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context, TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context,
"logging.config=classpath:logback-nondefault.xml", "logging.config=classpath:logback-nondefault.xml",
"logging.file.name=target/foo.log"); "logging.file.name=" + this.logFile);
this.initializer.initialize(this.context.getEnvironment(), this.initializer.initialize(this.context.getEnvironment(),
this.context.getClassLoader()); this.context.getClassLoader());
Log logger = LogFactory.getLog(LoggingApplicationListenerTests.class); Log logger = LogFactory.getLog(LoggingApplicationListenerTests.class);
@ -224,7 +230,7 @@ public class LoggingApplicationListenerTests {
logger.info("Hello world"); logger.info("Hello world");
String output = this.outputCapture.toString().substring(existingOutput.length()) String output = this.outputCapture.toString().substring(existingOutput.length())
.trim(); .trim();
assertThat(output).startsWith("target/foo.log"); assertThat(output).startsWith(this.logFile.getAbsolutePath());
} }
@Test @Test
@ -232,7 +238,7 @@ public class LoggingApplicationListenerTests {
public void addLogFilePropertyWithDeprecatedProperty() { public void addLogFilePropertyWithDeprecatedProperty() {
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context, TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context,
"logging.config=classpath:logback-nondefault.xml", "logging.config=classpath:logback-nondefault.xml",
"logging.file=target/foo.log"); "logging.file=" + this.logFile);
this.initializer.initialize(this.context.getEnvironment(), this.initializer.initialize(this.context.getEnvironment(),
this.context.getClassLoader()); this.context.getClassLoader());
Log logger = LogFactory.getLog(LoggingApplicationListenerTests.class); Log logger = LogFactory.getLog(LoggingApplicationListenerTests.class);
@ -240,39 +246,39 @@ public class LoggingApplicationListenerTests {
logger.info("Hello world"); logger.info("Hello world");
String output = this.outputCapture.toString().substring(existingOutput.length()) String output = this.outputCapture.toString().substring(existingOutput.length())
.trim(); .trim();
assertThat(output).startsWith("target/foo.log"); assertThat(output).startsWith(this.logFile.getAbsolutePath());
} }
@Test @Test
public void addLogFilePropertyWithDefault() { public void addLogFilePropertyWithDefault() {
assertThat(new File("target/foo.log").exists()).isFalse(); assertThat(this.logFile).doesNotExist();
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context, TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context,
"logging.file.name=target/foo.log"); "logging.file.name=" + this.logFile);
this.initializer.initialize(this.context.getEnvironment(), this.initializer.initialize(this.context.getEnvironment(),
this.context.getClassLoader()); this.context.getClassLoader());
Log logger = LogFactory.getLog(LoggingApplicationListenerTests.class); Log logger = LogFactory.getLog(LoggingApplicationListenerTests.class);
logger.info("Hello world"); logger.info("Hello world");
assertThat(new File("target/foo.log").exists()).isTrue(); assertThat(this.logFile).isFile();
} }
@Test @Test
@Deprecated @Deprecated
public void addLogFilePropertyWithDefaultAndDeprecatedProperty() { public void addLogFilePropertyWithDefaultAndDeprecatedProperty() {
assertThat(new File("target/foo.log").exists()).isFalse(); assertThat(this.logFile).doesNotExist();
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context, TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context,
"logging.file=target/foo.log"); "logging.file=" + this.logFile);
this.initializer.initialize(this.context.getEnvironment(), this.initializer.initialize(this.context.getEnvironment(),
this.context.getClassLoader()); this.context.getClassLoader());
Log logger = LogFactory.getLog(LoggingApplicationListenerTests.class); Log logger = LogFactory.getLog(LoggingApplicationListenerTests.class);
logger.info("Hello world"); logger.info("Hello world");
assertThat(new File("target/foo.log").exists()).isTrue(); assertThat(this.logFile).isFile();
} }
@Test @Test
public void addLogPathProperty() { public void addLogPathProperty() {
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context, TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context,
"logging.config=classpath:logback-nondefault.xml", "logging.config=classpath:logback-nondefault.xml",
"logging.file.path=target/foo/"); "logging.file.path=" + this.logFile);
this.initializer.initialize(this.context.getEnvironment(), this.initializer.initialize(this.context.getEnvironment(),
this.context.getClassLoader()); this.context.getClassLoader());
Log logger = LogFactory.getLog(LoggingApplicationListenerTests.class); Log logger = LogFactory.getLog(LoggingApplicationListenerTests.class);
@ -280,14 +286,14 @@ public class LoggingApplicationListenerTests {
logger.info("Hello world"); logger.info("Hello world");
String output = this.outputCapture.toString().substring(existingOutput.length()) String output = this.outputCapture.toString().substring(existingOutput.length())
.trim(); .trim();
assertThat(output).startsWith("target/foo/spring.log"); assertThat(output).startsWith(this.logFile.getAbsolutePath());
} }
@Test @Test
public void addLogPathPropertyWithDeprecatedProperty() { public void addLogPathPropertyWithDeprecatedProperty() {
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context, TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context,
"logging.config=classpath:logback-nondefault.xml", "logging.config=classpath:logback-nondefault.xml",
"logging.path=target/foo/"); "logging.path=" + this.temp.getRoot());
this.initializer.initialize(this.context.getEnvironment(), this.initializer.initialize(this.context.getEnvironment(),
this.context.getClassLoader()); this.context.getClassLoader());
Log logger = LogFactory.getLog(LoggingApplicationListenerTests.class); Log logger = LogFactory.getLog(LoggingApplicationListenerTests.class);
@ -295,7 +301,8 @@ public class LoggingApplicationListenerTests {
logger.info("Hello world"); logger.info("Hello world");
String output = this.outputCapture.toString().substring(existingOutput.length()) String output = this.outputCapture.toString().substring(existingOutput.length())
.trim(); .trim();
assertThat(output).startsWith("target/foo/spring.log"); assertThat(output).startsWith(
new File(this.temp.getRoot(), "spring.log").getAbsolutePath());
} }
@Test @Test
@ -539,7 +546,7 @@ public class LoggingApplicationListenerTests {
public void systemPropertiesAreSetForLoggingConfiguration() { public void systemPropertiesAreSetForLoggingConfiguration() {
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context, TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context,
"logging.exception-conversion-word=conversion", "logging.exception-conversion-word=conversion",
"logging.file.name=target/log", "logging.file.path=path", "logging.file.name=" + this.logFile, "logging.file.path=path",
"logging.pattern.console=console", "logging.pattern.file=file", "logging.pattern.console=console", "logging.pattern.file=file",
"logging.pattern.level=level"); "logging.pattern.level=level");
this.initializer.initialize(this.context.getEnvironment(), this.initializer.initialize(this.context.getEnvironment(),
@ -551,7 +558,7 @@ public class LoggingApplicationListenerTests {
assertThat(System.getProperty(LoggingSystemProperties.EXCEPTION_CONVERSION_WORD)) assertThat(System.getProperty(LoggingSystemProperties.EXCEPTION_CONVERSION_WORD))
.isEqualTo("conversion"); .isEqualTo("conversion");
assertThat(System.getProperty(LoggingSystemProperties.LOG_FILE)) assertThat(System.getProperty(LoggingSystemProperties.LOG_FILE))
.isEqualTo("target/log"); .isEqualTo(this.logFile.getAbsolutePath());
assertThat(System.getProperty(LoggingSystemProperties.LOG_LEVEL_PATTERN)) assertThat(System.getProperty(LoggingSystemProperties.LOG_LEVEL_PATTERN))
.isEqualTo("level"); .isEqualTo("level");
assertThat(System.getProperty(LoggingSystemProperties.LOG_PATH)) assertThat(System.getProperty(LoggingSystemProperties.LOG_PATH))
@ -563,11 +570,11 @@ public class LoggingApplicationListenerTests {
@Deprecated @Deprecated
public void systemPropertiesAreSetForLoggingConfigurationWithDeprecatedProperties() { public void systemPropertiesAreSetForLoggingConfigurationWithDeprecatedProperties() {
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context, TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context,
"logging.file=target/log", "logging.path=path"); "logging.file=" + this.logFile, "logging.path=path");
this.initializer.initialize(this.context.getEnvironment(), this.initializer.initialize(this.context.getEnvironment(),
this.context.getClassLoader()); this.context.getClassLoader());
assertThat(System.getProperty(LoggingSystemProperties.LOG_FILE)) assertThat(System.getProperty(LoggingSystemProperties.LOG_FILE))
.isEqualTo("target/log"); .isEqualTo(this.logFile.getAbsolutePath());
assertThat(System.getProperty(LoggingSystemProperties.LOG_PATH)) assertThat(System.getProperty(LoggingSystemProperties.LOG_PATH))
.isEqualTo("path"); .isEqualTo("path");
} }
@ -597,11 +604,13 @@ public class LoggingApplicationListenerTests {
@Test @Test
public void logFilePropertiesCanReferenceSystemProperties() { public void logFilePropertiesCanReferenceSystemProperties() {
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context, TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context,
"logging.file.name=target/${PID}.log"); "logging.file.name=" + this.temp.getRoot().getAbsolutePath()
+ "${PID}.log");
this.initializer.initialize(this.context.getEnvironment(), this.initializer.initialize(this.context.getEnvironment(),
this.context.getClassLoader()); this.context.getClassLoader());
assertThat(System.getProperty(LoggingSystemProperties.LOG_FILE)) assertThat(System.getProperty(LoggingSystemProperties.LOG_FILE))
.isEqualTo("target/" + new ApplicationPid().toString() + ".log"); .isEqualTo(this.temp.getRoot().getAbsolutePath()
+ new ApplicationPid().toString() + ".log");
} }
@Test @Test

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2016 the original author or authors. * Copyright 2012-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,21 +16,22 @@
package sample.integration; package sample.integration;
import org.springframework.boot.CommandLineRunner; import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@Component @Component
public class SampleCommandLineRunner implements CommandLineRunner { public class SampleApplicationRunner implements ApplicationRunner {
private final SampleMessageGateway gateway; private final SampleMessageGateway gateway;
public SampleCommandLineRunner(SampleMessageGateway gateway) { public SampleApplicationRunner(SampleMessageGateway gateway) {
this.gateway = gateway; this.gateway = gateway;
} }
@Override @Override
public void run(String... args) throws Exception { public void run(ApplicationArguments args) throws Exception {
for (String arg : args) { for (String arg : args.getNonOptionArgs()) {
this.gateway.echo(arg); this.gateway.echo(arg);
} }
} }

@ -16,7 +16,6 @@
package sample.integration; package sample.integration;
import java.io.File;
import java.util.function.Consumer; import java.util.function.Consumer;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
@ -35,10 +34,16 @@ import org.springframework.integration.file.FileWritingMessageHandler;
@EnableConfigurationProperties(ServiceProperties.class) @EnableConfigurationProperties(ServiceProperties.class)
public class SampleIntegrationApplication { public class SampleIntegrationApplication {
private final ServiceProperties serviceProperties;
public SampleIntegrationApplication(ServiceProperties serviceProperties) {
this.serviceProperties = serviceProperties;
}
@Bean @Bean
public FileReadingMessageSource fileReader() { public FileReadingMessageSource fileReader() {
FileReadingMessageSource reader = new FileReadingMessageSource(); FileReadingMessageSource reader = new FileReadingMessageSource();
reader.setDirectory(new File("target/input")); reader.setDirectory(this.serviceProperties.getInputDir());
return reader; return reader;
} }
@ -55,7 +60,7 @@ public class SampleIntegrationApplication {
@Bean @Bean
public FileWritingMessageHandler fileWriter() { public FileWritingMessageHandler fileWriter() {
FileWritingMessageHandler writer = new FileWritingMessageHandler( FileWritingMessageHandler writer = new FileWritingMessageHandler(
new File("target/output")); this.serviceProperties.getOutputDir());
writer.setExpectReply(false); writer.setExpectReply(false);
return writer; return writer;
} }

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2014 the original author or authors. * Copyright 2012-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,6 +16,8 @@
package sample.integration; package sample.integration;
import java.io.File;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.jmx.export.annotation.ManagedAttribute; import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedResource; import org.springframework.jmx.export.annotation.ManagedResource;
@ -26,6 +28,10 @@ public class ServiceProperties {
private String greeting = "Hello"; private String greeting = "Hello";
private File inputDir;
private File outputDir;
@ManagedAttribute @ManagedAttribute
public String getGreeting() { public String getGreeting() {
return this.greeting; return this.greeting;
@ -35,4 +41,20 @@ public class ServiceProperties {
this.greeting = greeting; this.greeting = greeting;
} }
public File getInputDir() {
return this.inputDir;
}
public void setInputDir(File inputDir) {
this.inputDir = inputDir;
}
public File getOutputDir() {
return this.outputDir;
}
public void setOutputDir(File outputDir) {
this.outputDir = outputDir;
}
} }

@ -1,2 +1,4 @@
logging.level.org.springframework.integration.file=DEBUG logging.level.org.springframework.integration.file=DEBUG
service.greeting=Hello service.greeting=Hello
service.input-dir=input
service.output-dir=output

@ -25,9 +25,11 @@ import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import sample.integration.SampleIntegrationApplication; import sample.integration.SampleIntegrationApplication;
import sample.integration.ServiceProperties;
import sample.integration.producer.ProducerApplication; import sample.integration.producer.ProducerApplication;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
@ -35,7 +37,6 @@ import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePatternUtils; import org.springframework.core.io.support.ResourcePatternUtils;
import org.springframework.util.FileSystemUtils;
import org.springframework.util.StreamUtils; import org.springframework.util.StreamUtils;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -48,19 +49,10 @@ import static org.assertj.core.api.Assertions.assertThat;
*/ */
public class SampleIntegrationApplicationTests { public class SampleIntegrationApplicationTests {
private ConfigurableApplicationContext context; @Rule
public final TemporaryFolder temp = new TemporaryFolder();
@Before
public void deleteInputAndOutput() {
deleteIfExists(new File("target/input"));
deleteIfExists(new File("target/output"));
}
private void deleteIfExists(File directory) { private ConfigurableApplicationContext context;
if (directory.exists()) {
assertThat(FileSystemUtils.deleteRecursively(directory)).isTrue();
}
}
@After @After
public void stop() { public void stop() {
@ -71,29 +63,37 @@ public class SampleIntegrationApplicationTests {
@Test @Test
public void testVanillaExchange() throws Exception { public void testVanillaExchange() throws Exception {
this.context = SpringApplication.run(SampleIntegrationApplication.class); File inputDir = new File(this.temp.getRoot(), "input");
SpringApplication.run(ProducerApplication.class, "World"); File outputDir = new File(this.temp.getRoot(), "output");
String output = getOutput(); this.context = SpringApplication.run(SampleIntegrationApplication.class,
"--service.input-dir=" + inputDir, "--service.output-dir=" + outputDir);
SpringApplication.run(ProducerApplication.class, "World",
"--service.input-dir=" + inputDir, "--service.output-dir=" + outputDir);
String output = getOutput(outputDir);
assertThat(output).contains("Hello World"); assertThat(output).contains("Hello World");
} }
@Test @Test
public void testMessageGateway() throws Exception { public void testMessageGateway() throws Exception {
File inputDir = new File(this.temp.getRoot(), "input");
File outputDir = new File(this.temp.getRoot(), "output");
this.context = SpringApplication.run(SampleIntegrationApplication.class, this.context = SpringApplication.run(SampleIntegrationApplication.class,
"testviamg"); "testviamg", "--service.input-dir=" + inputDir,
String output = getOutput(); "--service.output-dir=" + outputDir);
String output = getOutput(
this.context.getBean(ServiceProperties.class).getOutputDir());
assertThat(output).contains("testviamg"); assertThat(output).contains("testviamg");
} }
private String getOutput() throws Exception { private String getOutput(File outputDir) throws Exception {
Future<String> future = Executors.newSingleThreadExecutor() Future<String> future = Executors.newSingleThreadExecutor()
.submit(new Callable<String>() { .submit(new Callable<String>() {
@Override @Override
public String call() throws Exception { public String call() throws Exception {
Resource[] resources = getResourcesWithContent(); Resource[] resources = getResourcesWithContent(outputDir);
while (resources.length == 0) { while (resources.length == 0) {
Thread.sleep(200); Thread.sleep(200);
resources = getResourcesWithContent(); resources = getResourcesWithContent(outputDir);
} }
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
for (Resource resource : resources) { for (Resource resource : resources) {
@ -108,10 +108,10 @@ public class SampleIntegrationApplicationTests {
return future.get(30, TimeUnit.SECONDS); return future.get(30, TimeUnit.SECONDS);
} }
private Resource[] getResourcesWithContent() throws IOException { private Resource[] getResourcesWithContent(File outputDir) throws IOException {
Resource[] candidates = ResourcePatternUtils Resource[] candidates = ResourcePatternUtils
.getResourcePatternResolver(new DefaultResourceLoader()) .getResourcePatternResolver(new DefaultResourceLoader())
.getResources("file:target/output/**"); .getResources("file:" + outputDir.getAbsolutePath() + "/**");
for (Resource candidate : candidates) { for (Resource candidate : candidates) {
if ((candidate.getFilename() != null if ((candidate.getFilename() != null
&& candidate.getFilename().endsWith(".writing")) && candidate.getFilename().endsWith(".writing"))

@ -19,20 +19,32 @@ package sample.integration.producer;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import org.springframework.boot.CommandLineRunner; import sample.integration.ServiceProperties;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@Configuration @Configuration
public class ProducerApplication implements CommandLineRunner { @EnableConfigurationProperties(ServiceProperties.class)
public class ProducerApplication implements ApplicationRunner {
private final ServiceProperties serviceProperties;
public ProducerApplication(ServiceProperties serviceProperties) {
this.serviceProperties = serviceProperties;
}
@Override @Override
public void run(String... args) throws Exception { public void run(ApplicationArguments args) throws Exception {
new File("target/input").mkdirs(); this.serviceProperties.getInputDir().mkdirs();
if (args.length > 0) { if (args.getNonOptionArgs().size() > 0) {
FileOutputStream stream = new FileOutputStream( FileOutputStream stream = new FileOutputStream(
"target/input/data" + System.currentTimeMillis() + ".txt"); new File(this.serviceProperties.getInputDir(),
for (String arg : args) { "data" + System.currentTimeMillis() + ".txt"));
for (String arg : args.getNonOptionArgs()) {
stream.write(arg.getBytes()); stream.write(arg.getBytes());
} }
stream.flush(); stream.flush();

@ -16,7 +16,6 @@
package sample.parent; package sample.parent;
import java.io.File;
import java.util.function.Consumer; import java.util.function.Consumer;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
@ -33,7 +32,6 @@ import org.springframework.integration.file.FileReadingMessageSource;
import org.springframework.integration.file.FileWritingMessageHandler; import org.springframework.integration.file.FileWritingMessageHandler;
@SpringBootApplication @SpringBootApplication
@EnableConfigurationProperties(ServiceProperties.class)
public class SampleParentContextApplication { public class SampleParentContextApplication {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
@ -42,12 +40,19 @@ public class SampleParentContextApplication {
} }
@EnableAutoConfiguration @EnableAutoConfiguration
@EnableConfigurationProperties(ServiceProperties.class)
protected static class Parent { protected static class Parent {
private final ServiceProperties serviceProperties;
public Parent(ServiceProperties serviceProperties) {
this.serviceProperties = serviceProperties;
}
@Bean @Bean
public FileReadingMessageSource fileReader() { public FileReadingMessageSource fileReader() {
FileReadingMessageSource reader = new FileReadingMessageSource(); FileReadingMessageSource reader = new FileReadingMessageSource();
reader.setDirectory(new File("target/input")); reader.setDirectory(this.serviceProperties.getInputDir());
return reader; return reader;
} }
@ -64,7 +69,7 @@ public class SampleParentContextApplication {
@Bean @Bean
public FileWritingMessageHandler fileWriter() { public FileWritingMessageHandler fileWriter() {
FileWritingMessageHandler writer = new FileWritingMessageHandler( FileWritingMessageHandler writer = new FileWritingMessageHandler(
new File("target/output")); this.serviceProperties.getOutputDir());
writer.setExpectReply(false); writer.setExpectReply(false);
return writer; return writer;
} }

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2014 the original author or authors. * Copyright 2012-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,6 +16,8 @@
package sample.parent; package sample.parent;
import java.io.File;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.jmx.export.annotation.ManagedAttribute; import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedResource; import org.springframework.jmx.export.annotation.ManagedResource;
@ -26,6 +28,10 @@ public class ServiceProperties {
private String greeting = "Hello"; private String greeting = "Hello";
private File inputDir;
private File outputDir;
@ManagedAttribute @ManagedAttribute
public String getGreeting() { public String getGreeting() {
return this.greeting; return this.greeting;
@ -35,4 +41,20 @@ public class ServiceProperties {
this.greeting = greeting; this.greeting = greeting;
} }
public File getInputDir() {
return this.inputDir;
}
public void setInputDir(File inputDir) {
this.inputDir = inputDir;
}
public File getOutputDir() {
return this.outputDir;
}
public void setOutputDir(File outputDir) {
this.outputDir = outputDir;
}
} }

@ -1 +1,3 @@
service.greeting=Hello service.greeting=Hello
service.input-dir=input
service.output-dir=output

@ -16,11 +16,12 @@
package sample.parent.consumer; package sample.parent.consumer;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import org.junit.AfterClass; import org.junit.Rule;
import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import sample.parent.SampleParentContextApplication; import sample.parent.SampleParentContextApplication;
import sample.parent.producer.ProducerApplication; import sample.parent.producer.ProducerApplication;
@ -41,34 +42,41 @@ import static org.junit.Assert.fail;
*/ */
public class SampleIntegrationParentApplicationTests { public class SampleIntegrationParentApplicationTests {
private static ConfigurableApplicationContext context; @Rule
public final TemporaryFolder temp = new TemporaryFolder();
@BeforeClass
public static void start() {
context = SpringApplication.run(SampleParentContextApplication.class);
}
@AfterClass
public static void stop() {
if (context != null) {
context.close();
}
}
@Test @Test
public void testVanillaExchange() throws Exception { public void testVanillaExchange() throws Exception {
SpringApplication.run(ProducerApplication.class, "World"); File inputDir = new File(this.temp.getRoot(), "input");
awaitOutputContaining("Hello World"); File outputDir = new File(this.temp.getRoot(), "output");
ConfigurableApplicationContext app = SpringApplication.run(
SampleParentContextApplication.class, "--service.input-dir=" + inputDir,
"--service.output-dir=" + outputDir);
try {
ConfigurableApplicationContext producer = SpringApplication.run(
ProducerApplication.class, "--service.input-dir=" + inputDir,
"--service.output-dir=" + outputDir, "World");
try {
awaitOutputContaining(outputDir, "Hello World");
}
finally {
producer.close();
}
}
finally {
app.close();
}
} }
private void awaitOutputContaining(String requiredContents) throws Exception { private void awaitOutputContaining(File outputDir, String requiredContents)
throws Exception {
long endTime = System.currentTimeMillis() + 30000; long endTime = System.currentTimeMillis() + 30000;
String output = null; String output = null;
while (System.currentTimeMillis() < endTime) { while (System.currentTimeMillis() < endTime) {
Resource[] resources = findResources(); Resource[] resources = findResources(outputDir);
if (resources.length == 0) { if (resources.length == 0) {
Thread.sleep(200); Thread.sleep(200);
resources = findResources(); resources = findResources(outputDir);
} }
else { else {
output = readResources(resources); output = readResources(resources);
@ -85,10 +93,10 @@ public class SampleIntegrationParentApplicationTests {
+ "'. Output was '" + output + "'"); + "'. Output was '" + output + "'");
} }
private Resource[] findResources() throws IOException { private Resource[] findResources(File outputDir) throws IOException {
return ResourcePatternUtils return ResourcePatternUtils
.getResourcePatternResolver(new DefaultResourceLoader()) .getResourcePatternResolver(new DefaultResourceLoader())
.getResources("file:target/output/*.txt"); .getResources("file:" + outputDir.getAbsolutePath() + "/*.txt");
} }
private String readResources(Resource[] resources) throws IOException { private String readResources(Resource[] resources) throws IOException {

@ -19,20 +19,32 @@ package sample.parent.producer;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import org.springframework.boot.CommandLineRunner; import sample.parent.ServiceProperties;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@Configuration @Configuration
public class ProducerApplication implements CommandLineRunner { @EnableConfigurationProperties(ServiceProperties.class)
public class ProducerApplication implements ApplicationRunner {
private final ServiceProperties serviceProperties;
public ProducerApplication(ServiceProperties serviceProperties) {
this.serviceProperties = serviceProperties;
}
@Override @Override
public void run(String... args) throws Exception { public void run(ApplicationArguments args) throws Exception {
new File("target/input").mkdirs(); this.serviceProperties.getInputDir().mkdirs();
if (args.length > 0) { if (args.getNonOptionArgs().size() > 0) {
FileOutputStream stream = new FileOutputStream( FileOutputStream stream = new FileOutputStream(
"target/input/data" + System.currentTimeMillis() + ".txt"); new File(this.serviceProperties.getInputDir(),
for (String arg : args) { "data" + System.currentTimeMillis() + ".txt"));
for (String arg : args.getNonOptionArgs()) {
stream.write(arg.getBytes()); stream.write(arg.getBytes());
} }
stream.flush(); stream.flush();

@ -26,6 +26,11 @@
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test-support</artifactId>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>net.bytebuddy</groupId> <groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId> <artifactId>byte-buddy</artifactId>

@ -25,7 +25,7 @@ public class DevToolsTestApplication {
public static void main(String[] args) { public static void main(String[] args) {
new SpringApplicationBuilder(DevToolsTestApplication.class) new SpringApplicationBuilder(DevToolsTestApplication.class)
.listeners(new WebServerPortFileWriter("target/server.port")).run(args); .listeners(new WebServerPortFileWriter(args[0])).run(args);
} }
} }

@ -0,0 +1,57 @@
/*
* Copyright 2012-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.devtools.tests;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.springframework.util.FileSystemUtils;
/**
* Base class for all {@link ApplicationLauncher} implementations.
*
* @author Andy Wilkinson
*/
abstract class AbstractApplicationLauncher implements ApplicationLauncher {
private final Directories directories;
AbstractApplicationLauncher(Directories directories) {
this.directories = directories;
}
protected final void copyApplicationTo(File location) throws IOException {
FileSystemUtils.deleteRecursively(location);
location.mkdirs();
FileSystemUtils.copyRecursively(
new File(this.directories.getTestClassesDirectory(), "com"),
new File(location, "com"));
}
protected final List<String> getDependencyJarPaths() {
return Stream.of(this.directories.getDependenciesDirectory().listFiles())
.map(File::getAbsolutePath).collect(Collectors.toList());
}
protected final Directories getDirectories() {
return this.directories;
}
}

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2017 the original author or authors. * Copyright 2012-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,6 +16,8 @@
package org.springframework.boot.devtools.tests; package org.springframework.boot.devtools.tests;
import java.io.File;
/** /**
* Launches an application with DevTools. * Launches an application with DevTools.
* *
@ -23,6 +25,7 @@ package org.springframework.boot.devtools.tests;
*/ */
public interface ApplicationLauncher { public interface ApplicationLauncher {
LaunchedApplication launchApplication(JvmLauncher javaLauncher) throws Exception; LaunchedApplication launchApplication(JvmLauncher javaLauncher, File serverPortFile)
throws Exception;
} }

@ -18,6 +18,8 @@ package org.springframework.boot.devtools.tests;
import java.io.File; import java.io.File;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException;
import java.time.Duration;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -28,13 +30,16 @@ import net.bytebuddy.dynamic.DynamicType.Builder;
import net.bytebuddy.implementation.FixedValue; import net.bytebuddy.implementation.FixedValue;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.junit.runners.Parameterized; import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters; import org.junit.runners.Parameterized.Parameters;
import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.testsupport.BuildOutput;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.util.FileCopyUtils; import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
@ -50,9 +55,15 @@ import static org.assertj.core.api.Assertions.assertThat;
@RunWith(Parameterized.class) @RunWith(Parameterized.class)
public class DevToolsIntegrationTests { public class DevToolsIntegrationTests {
@ClassRule
public static final TemporaryFolder temp = new TemporaryFolder();
private static final BuildOutput buildOutput = new BuildOutput(
DevToolsIntegrationTests.class);
private LaunchedApplication launchedApplication; private LaunchedApplication launchedApplication;
private final File serverPortFile = new File("target/server.port"); private final File serverPortFile;
private final ApplicationLauncher applicationLauncher; private final ApplicationLauncher applicationLauncher;
@ -61,14 +72,15 @@ public class DevToolsIntegrationTests {
public DevToolsIntegrationTests(ApplicationLauncher applicationLauncher) { public DevToolsIntegrationTests(ApplicationLauncher applicationLauncher) {
this.applicationLauncher = applicationLauncher; this.applicationLauncher = applicationLauncher;
this.serverPortFile = new File(
DevToolsIntegrationTests.buildOutput.getRootLocation(), "server.port");
} }
@Before @Before
public void launchApplication() throws Exception { public void launchApplication() throws Exception {
this.serverPortFile.delete(); this.serverPortFile.delete();
System.out.println("Launching " + this.javaLauncher.getClass());
this.launchedApplication = this.applicationLauncher this.launchedApplication = this.applicationLauncher
.launchApplication(this.javaLauncher); .launchApplication(this.javaLauncher, this.serverPortFile);
} }
@After @After
@ -205,13 +217,15 @@ public class DevToolsIntegrationTests {
} }
private int awaitServerPort() throws Exception { private int awaitServerPort() throws Exception {
long end = System.currentTimeMillis() + 40000; Duration timeToWait = Duration.ofSeconds(40);
long end = System.currentTimeMillis() + timeToWait.toMillis();
System.out.println("Reading server port from '" + this.serverPortFile + "'");
while (this.serverPortFile.length() == 0) { while (this.serverPortFile.length() == 0) {
System.out.println("Getting server port " + this.serverPortFile.length());
if (System.currentTimeMillis() > end) { if (System.currentTimeMillis() > end) {
throw new IllegalStateException(String.format( throw new IllegalStateException(String.format(
"server.port file was not written within 30 seconds. " "server.port file '" + this.serverPortFile
+ "Application output:%n%s%s", + "' was not written within " + timeToWait.toMillis()
+ "ms. " + "Application output:%n%s%s",
FileCopyUtils.copyToString(new FileReader( FileCopyUtils.copyToString(new FileReader(
this.launchedApplication.getStandardOut())), this.launchedApplication.getStandardOut())),
FileCopyUtils.copyToString(new FileReader( FileCopyUtils.copyToString(new FileReader(
@ -234,10 +248,11 @@ public class DevToolsIntegrationTests {
} }
@Parameters(name = "{0}") @Parameters(name = "{0}")
public static Object[] parameters() { public static Object[] parameters() throws IOException {
return new Object[] { new Object[] { new LocalApplicationLauncher() }, Directories directories = new Directories(buildOutput, temp);
new Object[] { new ExplodedRemoteApplicationLauncher() }, return new Object[] { new Object[] { new LocalApplicationLauncher(directories) },
new Object[] { new JarFileRemoteApplicationLauncher() } }; new Object[] { new ExplodedRemoteApplicationLauncher(directories) },
new Object[] { new JarFileRemoteApplicationLauncher(directories) } };
} }
private static final class ControllerBuilder { private static final class ControllerBuilder {

@ -0,0 +1,57 @@
/*
* Copyright 2012-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.devtools.tests;
import java.io.File;
import org.junit.rules.TemporaryFolder;
import org.springframework.boot.testsupport.BuildOutput;
/**
* Various directories used by the {@link ApplicationLauncher ApplicationLaunchers}.
*
* @author Andy Wilkinson
*/
class Directories {
private final BuildOutput buildOutput;
private final TemporaryFolder temp;
Directories(BuildOutput buildOutput, TemporaryFolder temp) {
this.buildOutput = buildOutput;
this.temp = temp;
}
File getTestClassesDirectory() {
return this.buildOutput.getTestClassesLocation();
}
File getRemoteAppDirectory() {
return new File(this.temp.getRoot(), "remote");
}
File getDependenciesDirectory() {
return new File(this.buildOutput.getRootLocation(), "dependencies");
}
File getAppDirectory() {
return new File(this.temp.getRoot(), "app");
}
}

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2017 the original author or authors. * Copyright 2012-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -20,7 +20,6 @@ import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.springframework.util.FileSystemUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
/** /**
@ -31,18 +30,17 @@ import org.springframework.util.StringUtils;
*/ */
public class ExplodedRemoteApplicationLauncher extends RemoteApplicationLauncher { public class ExplodedRemoteApplicationLauncher extends RemoteApplicationLauncher {
public ExplodedRemoteApplicationLauncher(Directories directories) {
super(directories);
}
@Override @Override
protected String createApplicationClassPath() throws Exception { protected String createApplicationClassPath() throws Exception {
File appDirectory = new File("target/app"); File appDirectory = getDirectories().getAppDirectory();
FileSystemUtils.deleteRecursively(appDirectory); copyApplicationTo(appDirectory);
appDirectory.mkdirs();
FileSystemUtils.copyRecursively(new File("target/test-classes/com"),
new File("target/app/com"));
List<String> entries = new ArrayList<>(); List<String> entries = new ArrayList<>();
entries.add("target/app"); entries.add(appDirectory.getAbsolutePath());
for (File jar : new File("target/dependencies").listFiles()) { entries.addAll(getDependencyJarPaths());
entries.add(jar.getAbsolutePath());
}
return StringUtils.collectionToDelimitedString(entries, File.pathSeparator); return StringUtils.collectionToDelimitedString(entries, File.pathSeparator);
} }

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2017 the original author or authors. * Copyright 2012-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -27,7 +27,6 @@ import java.util.jar.JarOutputStream;
import java.util.jar.Manifest; import java.util.jar.Manifest;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import org.springframework.util.FileSystemUtils;
import org.springframework.util.StreamUtils; import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
@ -39,28 +38,24 @@ import org.springframework.util.StringUtils;
*/ */
public class JarFileRemoteApplicationLauncher extends RemoteApplicationLauncher { public class JarFileRemoteApplicationLauncher extends RemoteApplicationLauncher {
public JarFileRemoteApplicationLauncher(Directories directories) {
super(directories);
}
@Override @Override
protected String createApplicationClassPath() throws Exception { protected String createApplicationClassPath() throws Exception {
File appDirectory = new File("target/app"); File appDirectory = getDirectories().getAppDirectory();
if (appDirectory.isDirectory() copyApplicationTo(appDirectory);
&& !FileSystemUtils.deleteRecursively(appDirectory.toPath())) {
throw new IllegalStateException(
"Failed to delete '" + appDirectory.getAbsolutePath() + "'");
}
appDirectory.mkdirs();
Manifest manifest = new Manifest(); Manifest manifest = new Manifest();
manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0"); manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
JarOutputStream output = new JarOutputStream( File appJar = new File(appDirectory, "app.jar");
new FileOutputStream(new File(appDirectory, "app.jar")), manifest); JarOutputStream output = new JarOutputStream(new FileOutputStream(appJar),
FileSystemUtils.copyRecursively(new File("target/test-classes/com"), manifest);
new File("target/app/com")); addToJar(output, appDirectory, appDirectory);
addToJar(output, new File("target/app/"), new File("target/app/"));
output.close(); output.close();
List<String> entries = new ArrayList<>(); List<String> entries = new ArrayList<>();
entries.add("target/app/app.jar"); entries.add(appJar.getAbsolutePath());
for (File jar : new File("target/dependencies").listFiles()) { entries.addAll(getDependencyJarPaths());
entries.add(jar.getAbsolutePath());
}
String classpath = StringUtils.collectionToDelimitedString(entries, String classpath = StringUtils.collectionToDelimitedString(entries,
File.pathSeparator); File.pathSeparator);
return classpath; return classpath;

@ -27,6 +27,7 @@ import org.junit.rules.TestRule;
import org.junit.runner.Description; import org.junit.runner.Description;
import org.junit.runners.model.Statement; import org.junit.runners.model.Statement;
import org.springframework.boot.testsupport.BuildOutput;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
/** /**
@ -39,12 +40,15 @@ class JvmLauncher implements TestRule {
private static final Pattern NON_ALPHABET_PATTERN = Pattern.compile("[^A-Za-z]+"); private static final Pattern NON_ALPHABET_PATTERN = Pattern.compile("[^A-Za-z]+");
private final BuildOutput buildOutput = new BuildOutput(getClass());
private File outputDirectory; private File outputDirectory;
@Override @Override
public Statement apply(Statement base, Description description) { public Statement apply(Statement base, Description description) {
this.outputDirectory = new File("target/output/" + NON_ALPHABET_PATTERN this.outputDirectory = new File(this.buildOutput.getRootLocation(),
.matcher(description.getMethodName()).replaceAll("")); "output/" + NON_ALPHABET_PATTERN.matcher(description.getMethodName())
.replaceAll(""));
this.outputDirectory.mkdirs(); this.outputDirectory.mkdirs();
return base; return base;
} }

@ -21,7 +21,6 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.springframework.boot.devtools.tests.JvmLauncher.LaunchedJvm; import org.springframework.boot.devtools.tests.JvmLauncher.LaunchedJvm;
import org.springframework.util.FileSystemUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
/** /**
@ -29,28 +28,29 @@ import org.springframework.util.StringUtils;
* *
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
public class LocalApplicationLauncher implements ApplicationLauncher { public class LocalApplicationLauncher extends AbstractApplicationLauncher {
LocalApplicationLauncher(Directories directories) {
super(directories);
}
@Override @Override
public LaunchedApplication launchApplication(JvmLauncher jvmLauncher) public LaunchedApplication launchApplication(JvmLauncher jvmLauncher,
throws Exception { File serverPortFile) throws Exception {
LaunchedJvm jvm = jvmLauncher.launch("local", createApplicationClassPath(), LaunchedJvm jvm = jvmLauncher.launch("local", createApplicationClassPath(),
"com.example.DevToolsTestApplication", "--server.port=0"); "com.example.DevToolsTestApplication", serverPortFile.getAbsolutePath(),
return new LaunchedApplication(new File("target/app"), jvm.getStandardOut(), "--server.port=0");
jvm.getStandardError(), jvm.getProcess(), null, null); return new LaunchedApplication(getDirectories().getAppDirectory(),
jvm.getStandardOut(), jvm.getStandardError(), jvm.getProcess(), null,
null);
} }
protected String createApplicationClassPath() throws Exception { protected String createApplicationClassPath() throws Exception {
File appDirectory = new File("target/app"); File appDirectory = getDirectories().getAppDirectory();
FileSystemUtils.deleteRecursively(appDirectory); copyApplicationTo(appDirectory);
appDirectory.mkdirs();
FileSystemUtils.copyRecursively(new File("target/test-classes/com"),
new File("target/app/com"));
List<String> entries = new ArrayList<>(); List<String> entries = new ArrayList<>();
entries.add("target/app"); entries.add(appDirectory.getAbsolutePath());
for (File jar : new File("target/dependencies").listFiles()) { entries.addAll(getDependencyJarPaths());
entries.add(jar.getAbsolutePath());
}
return StringUtils.collectionToDelimitedString(entries, File.pathSeparator); return StringUtils.collectionToDelimitedString(entries, File.pathSeparator);
} }

@ -25,7 +25,6 @@ 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;
import org.springframework.util.FileCopyUtils; import org.springframework.util.FileCopyUtils;
import org.springframework.util.FileSystemUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
/** /**
@ -34,18 +33,23 @@ import org.springframework.util.StringUtils;
* *
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
abstract class RemoteApplicationLauncher implements ApplicationLauncher { abstract class RemoteApplicationLauncher extends AbstractApplicationLauncher {
RemoteApplicationLauncher(Directories directories) {
super(directories);
}
@Override @Override
public LaunchedApplication launchApplication(JvmLauncher javaLauncher) public LaunchedApplication launchApplication(JvmLauncher javaLauncher,
throws Exception { File serverPortFile) throws Exception {
LaunchedJvm applicationJvm = javaLauncher.launch("app", LaunchedJvm applicationJvm = javaLauncher.launch("app",
createApplicationClassPath(), "com.example.DevToolsTestApplication", createApplicationClassPath(), "com.example.DevToolsTestApplication",
"--server.port=0", "--spring.devtools.remote.secret=secret"); serverPortFile.getAbsolutePath(), "--server.port=0",
int port = awaitServerPort(applicationJvm.getStandardOut()); "--spring.devtools.remote.secret=secret");
int port = awaitServerPort(applicationJvm.getStandardOut(), serverPortFile);
BiFunction<Integer, File, Process> remoteRestarter = getRemoteRestarter( BiFunction<Integer, File, Process> remoteRestarter = getRemoteRestarter(
javaLauncher); javaLauncher);
return new LaunchedApplication(new File("target/remote"), return new LaunchedApplication(getDirectories().getRemoteAppDirectory(),
applicationJvm.getStandardOut(), applicationJvm.getStandardError(), applicationJvm.getStandardOut(), applicationJvm.getStandardError(),
applicationJvm.getProcess(), remoteRestarter.apply(port, null), applicationJvm.getProcess(), remoteRestarter.apply(port, null),
remoteRestarter); remoteRestarter);
@ -74,24 +78,18 @@ abstract class RemoteApplicationLauncher implements ApplicationLauncher {
private String createRemoteSpringApplicationClassPath(File classesDirectory) private String createRemoteSpringApplicationClassPath(File classesDirectory)
throws Exception { throws Exception {
File remoteAppDirectory = getDirectories().getRemoteAppDirectory();
if (classesDirectory == null) { if (classesDirectory == null) {
File remoteDirectory = new File("target/remote"); copyApplicationTo(remoteAppDirectory);
FileSystemUtils.deleteRecursively(remoteDirectory);
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(remoteAppDirectory.getAbsolutePath());
for (File jar : new File("target/dependencies").listFiles()) { entries.addAll(getDependencyJarPaths());
entries.add(jar.getAbsolutePath());
}
return StringUtils.collectionToDelimitedString(entries, File.pathSeparator); return StringUtils.collectionToDelimitedString(entries, File.pathSeparator);
} }
private int awaitServerPort(File standardOut) throws Exception { private int awaitServerPort(File standardOut, File serverPortFile) throws Exception {
long end = System.currentTimeMillis() + 30000; long end = System.currentTimeMillis() + 30000;
File serverPortFile = new File("target/server.port");
while (serverPortFile.length() == 0) { while (serverPortFile.length() == 0) {
if (System.currentTimeMillis() > end) { if (System.currentTimeMillis() > end) {
throw new IllegalStateException(String.format( throw new IllegalStateException(String.format(

@ -24,6 +24,11 @@
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test-support</artifactId>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>com.samskivert</groupId> <groupId>com.samskivert</groupId>
<artifactId>jmustache</artifactId> <artifactId>jmustache</artifactId>

@ -41,7 +41,7 @@ public class ResourceHandlingApplication {
public static void main(String[] args) { public static void main(String[] args) {
new SpringApplicationBuilder(ResourceHandlingApplication.class) new SpringApplicationBuilder(ResourceHandlingApplication.class)
.properties("server.port:0") .properties("server.port:0")
.listeners(new WebServerPortFileWriter("target/server.port")).run(args); .listeners(new WebServerPortFileWriter(args[0])).run(args);
} }
@Bean @Bean

@ -26,6 +26,7 @@ import java.util.List;
import org.junit.rules.ExternalResource; import org.junit.rules.ExternalResource;
import org.springframework.boot.testsupport.BuildOutput;
import org.springframework.util.FileCopyUtils; import org.springframework.util.FileCopyUtils;
import org.springframework.util.StreamUtils; import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
@ -40,12 +41,16 @@ abstract class AbstractApplicationLauncher extends ExternalResource {
private final ApplicationBuilder applicationBuilder; private final ApplicationBuilder applicationBuilder;
private final BuildOutput buildOutput;
private Process process; private Process process;
private int httpPort; private int httpPort;
protected AbstractApplicationLauncher(ApplicationBuilder applicationBuilder) { protected AbstractApplicationLauncher(ApplicationBuilder applicationBuilder,
BuildOutput buildOutput) {
this.applicationBuilder = applicationBuilder; this.applicationBuilder = applicationBuilder;
this.buildOutput = buildOutput;
} }
@Override @Override
@ -62,7 +67,7 @@ abstract class AbstractApplicationLauncher extends ExternalResource {
return this.httpPort; return this.httpPort;
} }
protected abstract List<String> getArguments(File archive); protected abstract List<String> getArguments(File archive, File serverPortFile);
protected abstract File getWorkingDirectory(); protected abstract File getWorkingDirectory();
@ -70,14 +75,12 @@ abstract class AbstractApplicationLauncher extends ExternalResource {
private Process startApplication() throws Exception { private Process startApplication() throws Exception {
File workingDirectory = getWorkingDirectory(); File workingDirectory = getWorkingDirectory();
File serverPortFile = (workingDirectory != null) File serverPortFile = new File(this.buildOutput.getRootLocation(), "server.port");
? new File(workingDirectory, "target/server.port")
: new File("target/server.port");
serverPortFile.delete(); serverPortFile.delete();
File archive = this.applicationBuilder.buildApplication(); File archive = this.applicationBuilder.buildApplication();
List<String> arguments = new ArrayList<>(); List<String> arguments = new ArrayList<>();
arguments.add(System.getProperty("java.home") + "/bin/java"); arguments.add(System.getProperty("java.home") + "/bin/java");
arguments.addAll(getArguments(archive)); arguments.addAll(getArguments(archive, serverPortFile));
ProcessBuilder processBuilder = new ProcessBuilder( ProcessBuilder processBuilder = new ProcessBuilder(
StringUtils.toStringArray(arguments)); StringUtils.toStringArray(arguments));
if (workingDirectory != null) { if (workingDirectory != null) {

@ -26,6 +26,7 @@ import org.junit.ClassRule;
import org.junit.Rule; import org.junit.Rule;
import org.junit.rules.TemporaryFolder; import org.junit.rules.TemporaryFolder;
import org.springframework.boot.testsupport.BuildOutput;
import org.springframework.http.client.ClientHttpResponse; import org.springframework.http.client.ClientHttpResponse;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.web.client.ResponseErrorHandler; import org.springframework.web.client.ResponseErrorHandler;
@ -48,6 +49,9 @@ public abstract class AbstractEmbeddedServletContainerIntegrationTests {
}; };
public static final BuildOutput buildOutput = new BuildOutput(
AbstractEmbeddedServletContainerIntegrationTests.class);
@Rule @Rule
public final AbstractApplicationLauncher launcher; public final AbstractApplicationLauncher launcher;
@ -70,8 +74,9 @@ public abstract class AbstractEmbeddedServletContainerIntegrationTests {
for (Class<? extends AbstractApplicationLauncher> launcherClass : applicationLaunchers) { for (Class<? extends AbstractApplicationLauncher> launcherClass : applicationLaunchers) {
try { try {
AbstractApplicationLauncher launcher = launcherClass AbstractApplicationLauncher launcher = launcherClass
.getDeclaredConstructor(ApplicationBuilder.class) .getDeclaredConstructor(ApplicationBuilder.class,
.newInstance(applicationBuilder); BuildOutput.class)
.newInstance(applicationBuilder, buildOutput);
String name = StringUtils.capitalize(container) + ": " String name = StringUtils.capitalize(container) + ": "
+ launcher.getDescription(packaging); + launcher.getDescription(packaging);
parameters.add(new Object[] { name, launcher }); parameters.add(new Object[] { name, launcher });

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2017 the original author or authors. * Copyright 2012-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -27,6 +27,7 @@ import java.util.List;
import java.util.jar.JarEntry; import java.util.jar.JarEntry;
import java.util.jar.JarFile; import java.util.jar.JarFile;
import org.springframework.boot.testsupport.BuildOutput;
import org.springframework.util.FileCopyUtils; import org.springframework.util.FileCopyUtils;
import org.springframework.util.FileSystemUtils; import org.springframework.util.FileSystemUtils;
import org.springframework.util.StreamUtils; import org.springframework.util.StreamUtils;
@ -40,14 +41,16 @@ import org.springframework.util.StringUtils;
*/ */
class BootRunApplicationLauncher extends AbstractApplicationLauncher { class BootRunApplicationLauncher extends AbstractApplicationLauncher {
private final File exploded = new File("target/run"); private final File exploded;
BootRunApplicationLauncher(ApplicationBuilder applicationBuilder) { BootRunApplicationLauncher(ApplicationBuilder applicationBuilder,
super(applicationBuilder); BuildOutput buildOutput) {
super(applicationBuilder, buildOutput);
this.exploded = new File(buildOutput.getRootLocation(), "run");
} }
@Override @Override
protected List<String> getArguments(File archive) { protected List<String> getArguments(File archive, File serverPortFile) {
try { try {
explodeArchive(archive); explodeArchive(archive);
deleteLauncherClasses(); deleteLauncherClasses();
@ -64,7 +67,8 @@ class BootRunApplicationLauncher extends AbstractApplicationLauncher {
return Arrays.asList("-cp", return Arrays.asList("-cp",
StringUtils.collectionToDelimitedString(classpath, StringUtils.collectionToDelimitedString(classpath,
File.pathSeparator), File.pathSeparator),
"com.example.ResourceHandlingApplication"); "com.example.ResourceHandlingApplication",
serverPortFile.getAbsolutePath());
} }
catch (IOException ex) { catch (IOException ex) {
throw new RuntimeException(ex); throw new RuntimeException(ex);
@ -76,12 +80,12 @@ class BootRunApplicationLauncher extends AbstractApplicationLauncher {
} }
private File populateTargetClasses(File archive) throws IOException { private File populateTargetClasses(File archive) throws IOException {
File targetClasses = new File(this.exploded, "target/classes"); File builtClasses = new File(this.exploded, "built/classes");
targetClasses.mkdirs(); builtClasses.mkdirs();
File source = new File(this.exploded, getClassesPath(archive)); File source = new File(this.exploded, getClassesPath(archive));
FileSystemUtils.copyRecursively(source, targetClasses); FileSystemUtils.copyRecursively(source, builtClasses);
FileSystemUtils.deleteRecursively(source); FileSystemUtils.deleteRecursively(source);
return targetClasses; return builtClasses;
} }
private File populateDependencies(File archive) throws IOException { private File populateDependencies(File archive) throws IOException {

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2017 the original author or authors. * Copyright 2012-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -22,9 +22,11 @@ import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.List; import java.util.List;
import java.util.function.Supplier;
import java.util.jar.JarEntry; import java.util.jar.JarEntry;
import java.util.jar.JarFile; import java.util.jar.JarFile;
import org.springframework.boot.testsupport.BuildOutput;
import org.springframework.util.FileSystemUtils; import org.springframework.util.FileSystemUtils;
import org.springframework.util.StreamUtils; import org.springframework.util.StreamUtils;
@ -36,15 +38,17 @@ import org.springframework.util.StreamUtils;
*/ */
class ExplodedApplicationLauncher extends AbstractApplicationLauncher { class ExplodedApplicationLauncher extends AbstractApplicationLauncher {
private final File exploded = new File("target/exploded"); private final Supplier<File> exploded;
ExplodedApplicationLauncher(ApplicationBuilder applicationBuilder) { ExplodedApplicationLauncher(ApplicationBuilder applicationBuilder,
super(applicationBuilder); BuildOutput buildOutput) {
super(applicationBuilder, buildOutput);
this.exploded = () -> new File(buildOutput.getRootLocation(), "exploded");
} }
@Override @Override
protected File getWorkingDirectory() { protected File getWorkingDirectory() {
return this.exploded; return this.exploded.get();
} }
@Override @Override
@ -53,13 +57,14 @@ class ExplodedApplicationLauncher extends AbstractApplicationLauncher {
} }
@Override @Override
protected List<String> getArguments(File archive) { protected List<String> getArguments(File archive, File serverPortFile) {
String mainClass = (archive.getName().endsWith(".war") String mainClass = (archive.getName().endsWith(".war")
? "org.springframework.boot.loader.WarLauncher" ? "org.springframework.boot.loader.WarLauncher"
: "org.springframework.boot.loader.JarLauncher"); : "org.springframework.boot.loader.JarLauncher");
try { try {
explodeArchive(archive); explodeArchive(archive);
return Arrays.asList("-cp", this.exploded.getAbsolutePath(), mainClass); return Arrays.asList("-cp", this.exploded.get().getAbsolutePath(), mainClass,
serverPortFile.getAbsolutePath());
} }
catch (IOException ex) { catch (IOException ex) {
throw new RuntimeException(ex); throw new RuntimeException(ex);
@ -67,12 +72,12 @@ class ExplodedApplicationLauncher extends AbstractApplicationLauncher {
} }
private void explodeArchive(File archive) throws IOException { private void explodeArchive(File archive) throws IOException {
FileSystemUtils.deleteRecursively(this.exploded); FileSystemUtils.deleteRecursively(this.exploded.get());
JarFile jarFile = new JarFile(archive); JarFile jarFile = new JarFile(archive);
Enumeration<JarEntry> entries = jarFile.entries(); Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) { while (entries.hasMoreElements()) {
JarEntry jarEntry = entries.nextElement(); JarEntry jarEntry = entries.nextElement();
File extracted = new File(this.exploded, jarEntry.getName()); File extracted = new File(this.exploded.get(), jarEntry.getName());
if (jarEntry.isDirectory()) { if (jarEntry.isDirectory()) {
extracted.mkdirs(); extracted.mkdirs();
} }

@ -27,6 +27,7 @@ import java.util.List;
import java.util.jar.JarEntry; import java.util.jar.JarEntry;
import java.util.jar.JarFile; import java.util.jar.JarFile;
import org.springframework.boot.testsupport.BuildOutput;
import org.springframework.util.FileCopyUtils; import org.springframework.util.FileCopyUtils;
import org.springframework.util.FileSystemUtils; import org.springframework.util.FileSystemUtils;
import org.springframework.util.StreamUtils; import org.springframework.util.StreamUtils;
@ -40,10 +41,12 @@ import org.springframework.util.StringUtils;
*/ */
class IdeApplicationLauncher extends AbstractApplicationLauncher { class IdeApplicationLauncher extends AbstractApplicationLauncher {
private final File exploded = new File("target/the+ide application"); private final File exploded;
IdeApplicationLauncher(ApplicationBuilder applicationBuilder) { IdeApplicationLauncher(ApplicationBuilder applicationBuilder,
super(applicationBuilder); BuildOutput buildOutput) {
super(applicationBuilder, buildOutput);
this.exploded = new File(buildOutput.getRootLocation(), "the+ide application");
} }
@Override @Override
@ -57,18 +60,18 @@ class IdeApplicationLauncher extends AbstractApplicationLauncher {
} }
@Override @Override
protected List<String> getArguments(File archive) { protected List<String> getArguments(File archive, File serverPortFile) {
try { try {
explodeArchive(archive, this.exploded); explodeArchive(archive, this.exploded);
deleteLauncherClasses(); deleteLauncherClasses();
File targetClasses = populateTargetClasses(archive); File builtClasses = populateBuiltClasses(archive);
File dependencies = populateDependencies(archive); File dependencies = populateDependencies(archive);
File resourcesProject = explodedResourcesProject(dependencies); File resourcesProject = explodedResourcesProject(dependencies);
if (archive.getName().endsWith(".war")) { if (archive.getName().endsWith(".war")) {
populateSrcMainWebapp(); populateSrcMainWebapp();
} }
List<String> classpath = new ArrayList<>(); List<String> classpath = new ArrayList<>();
classpath.add(targetClasses.getAbsolutePath()); classpath.add(builtClasses.getAbsolutePath());
for (File dependency : dependencies.listFiles()) { for (File dependency : dependencies.listFiles()) {
classpath.add(dependency.getAbsolutePath()); classpath.add(dependency.getAbsolutePath());
} }
@ -76,20 +79,21 @@ class IdeApplicationLauncher extends AbstractApplicationLauncher {
return Arrays.asList("-cp", return Arrays.asList("-cp",
StringUtils.collectionToDelimitedString(classpath, StringUtils.collectionToDelimitedString(classpath,
File.pathSeparator), File.pathSeparator),
"com.example.ResourceHandlingApplication"); "com.example.ResourceHandlingApplication",
serverPortFile.getAbsolutePath());
} }
catch (IOException ex) { catch (IOException ex) {
throw new RuntimeException(ex); throw new RuntimeException(ex);
} }
} }
private File populateTargetClasses(File archive) throws IOException { private File populateBuiltClasses(File archive) throws IOException {
File targetClasses = new File(this.exploded, "target/classes"); File builtClasses = new File(this.exploded, "built/classes");
targetClasses.mkdirs(); builtClasses.mkdirs();
File source = new File(this.exploded, getClassesPath(archive)); File source = new File(this.exploded, getClassesPath(archive));
FileSystemUtils.copyRecursively(source, targetClasses); FileSystemUtils.copyRecursively(source, builtClasses);
FileSystemUtils.deleteRecursively(source); FileSystemUtils.deleteRecursively(source);
return targetClasses; return builtClasses;
} }
private File populateDependencies(File archive) throws IOException { private File populateDependencies(File archive) throws IOException {
@ -108,7 +112,7 @@ class IdeApplicationLauncher extends AbstractApplicationLauncher {
private File explodedResourcesProject(File dependencies) throws IOException { private File explodedResourcesProject(File dependencies) throws IOException {
File resourcesProject = new File(this.exploded, File resourcesProject = new File(this.exploded,
"resources-project/target/classes"); "resources-project/built/classes");
File resourcesJar = new File(dependencies, "resources-1.0.jar"); File resourcesJar = new File(dependencies, "resources-1.0.jar");
explodeArchive(resourcesJar, resourcesProject); explodeArchive(resourcesJar, resourcesProject);
resourcesJar.delete(); resourcesJar.delete();

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2017 the original author or authors. * Copyright 2012-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -20,6 +20,8 @@ import java.io.File;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import org.springframework.boot.testsupport.BuildOutput;
/** /**
* {@link AbstractApplicationLauncher} that launches a packaged Spring Boot application * {@link AbstractApplicationLauncher} that launches a packaged Spring Boot application
* using {@code java -jar}. * using {@code java -jar}.
@ -28,8 +30,9 @@ import java.util.List;
*/ */
class PackagedApplicationLauncher extends AbstractApplicationLauncher { class PackagedApplicationLauncher extends AbstractApplicationLauncher {
PackagedApplicationLauncher(ApplicationBuilder applicationBuilder) { PackagedApplicationLauncher(ApplicationBuilder applicationBuilder,
super(applicationBuilder); BuildOutput buildOutput) {
super(applicationBuilder, buildOutput);
} }
@Override @Override
@ -43,8 +46,9 @@ class PackagedApplicationLauncher extends AbstractApplicationLauncher {
} }
@Override @Override
protected List<String> getArguments(File archive) { protected List<String> getArguments(File archive, File serverPortFile) {
return Arrays.asList("-jar", archive.getAbsolutePath()); return Arrays.asList("-jar", archive.getAbsolutePath(),
serverPortFile.getAbsolutePath());
} }
} }

Loading…
Cancel
Save