[bs-62] Add integration tests for CLI samples

[Fixes #48658503]
This commit is contained in:
Dave Syer
2013-04-24 16:09:17 +01:00
parent c91e83c7d2
commit 38f0cf1ed2
14 changed files with 265 additions and 33 deletions

View File

@@ -48,7 +48,9 @@ public class RunCommand extends OptionParsingCommand {
private OptionSpec<Void> verboseOption;
private OptionSpec<Void> quiteOption;
private OptionSpec<Void> quietOption;
private BootstrapRunner runner;
public RunCommand() {
super("run", "Run a spring groovy script");
@@ -59,6 +61,12 @@ public class RunCommand extends OptionParsingCommand {
return "[options] <file>";
}
public void stop() {
if (this.runner != null) {
this.runner.stop();
}
}
@Override
protected OptionParser createOptionParser() {
OptionParser parser = new OptionParser();
@@ -71,7 +79,7 @@ public class RunCommand extends OptionParsingCommand {
this.noGuessDependenciesOption = parser.accepts("no-guess-dependencies",
"Do not attempt to guess dependencies");
this.verboseOption = parser.acceptsAll(asList("verbose", "v"), "Verbose logging");
this.quiteOption = parser.acceptsAll(asList("quiet", "q"), "Quiet logging");
this.quietOption = parser.acceptsAll(asList("quiet", "q"), "Quiet logging");
return parser;
}
@@ -87,8 +95,9 @@ public class RunCommand extends OptionParsingCommand {
BootstrapRunnerConfiguration configuration = new BootstrapRunnerConfigurationAdapter(
options);
new BootstrapRunner(configuration, file, args.toArray(new String[args.size()]))
.compileAndRun();
this.runner = new BootstrapRunner(configuration, file,
args.toArray(new String[args.size()]));
this.runner.compileAndRun();
}
private File getFileArgument(List<String> nonOptionArguments) {
@@ -136,7 +145,7 @@ public class RunCommand extends OptionParsingCommand {
if (this.options.has(RunCommand.this.verboseOption)) {
return Level.FINEST;
}
if (this.options.has(RunCommand.this.quiteOption)) {
if (this.options.has(RunCommand.this.quietOption)) {
return Level.OFF;
}
return Level.INFO;

View File

@@ -60,12 +60,34 @@ public class DependencyCustomizer {
}
/**
* Create a nested {@link DependencyCustomizer} that only applies if the specified
* class names are not on the class path.
* Create a nested {@link DependencyCustomizer} that only applies if any of the
* specified class names are not on the class path.
* @param classNames the class names to test
* @return a nested {@link DependencyCustomizer}
*/
public DependencyCustomizer ifMissingClasses(final String... classNames) {
public DependencyCustomizer ifAnyMissingClasses(final String... classNames) {
return new DependencyCustomizer(this) {
@Override
protected boolean canAdd() {
for (String classname : classNames) {
try {
DependencyCustomizer.this.loader.loadClass(classname);
} catch (Exception e) {
return true;
}
}
return DependencyCustomizer.this.canAdd();
}
};
}
/**
* Create a nested {@link DependencyCustomizer} that only applies if all of the
* specified class names are not on the class path.
* @param classNames the class names to test
* @return a nested {@link DependencyCustomizer}
*/
public DependencyCustomizer ifAllMissingClasses(final String... classNames) {
return new DependencyCustomizer(this) {
@Override
protected boolean canAdd() {
@@ -81,6 +103,86 @@ public class DependencyCustomizer {
};
}
/**
* Create a nested {@link DependencyCustomizer} that only applies if the specified
* paths are on the class path.
* @param paths the paths to test
* @return a nested {@link DependencyCustomizer}
*/
public DependencyCustomizer ifAllResourcesPresent(final String... paths) {
return new DependencyCustomizer(this) {
@Override
protected boolean canAdd() {
for (String path : paths) {
try {
if (DependencyCustomizer.this.loader.getResource(path) == null) {
return false;
}
return true;
} catch (Exception e) {
}
}
return DependencyCustomizer.this.canAdd();
}
};
}
/**
* Create a nested {@link DependencyCustomizer} that only applies at least one of the
* specified paths is on the class path.
* @param paths the paths to test
* @return a nested {@link DependencyCustomizer}
*/
public DependencyCustomizer ifAnyResourcesPresent(final String... paths) {
return new DependencyCustomizer(this) {
@Override
protected boolean canAdd() {
for (String path : paths) {
try {
if (DependencyCustomizer.this.loader.getResource(path) != null) {
return true;
}
return false;
} catch (Exception e) {
}
}
return DependencyCustomizer.this.canAdd();
}
};
}
/**
* Create a nested {@link DependencyCustomizer} that only applies the specified one
* was not yet added.
* @return a nested {@link DependencyCustomizer}
*/
public DependencyCustomizer ifNotAdded(final String group, final String module) {
return new DependencyCustomizer(this) {
@Override
protected boolean canAdd() {
if (DependencyCustomizer.this.contains(group, module)) {
return false;
}
return DependencyCustomizer.this.canAdd();
}
};
}
/**
* @param group the group ID
* @param module the module ID
* @return true if this module is already in the dependencies
*/
protected boolean contains(String group, String module) {
for (Map<String, Object> dependency : this.dependencies) {
if (group.equals(dependency.get("group"))
&& module.equals(dependency.get("module"))) {
return true;
}
}
return false;
}
/**
* Add a single dependencies.
* @param group the group ID
@@ -113,7 +215,7 @@ public class DependencyCustomizer {
/**
* Strategy called to test if dependencies can be added. Subclasses override as
* requred.
* required.
*/
protected boolean canAdd() {
return true;

View File

@@ -37,7 +37,7 @@ public class SpringBatchCompilerAutoConfiguration extends CompilerAutoConfigurat
@Override
public void applyDependencies(DependencyCustomizer dependencies) {
dependencies.ifMissingClasses("org.springframework.batch.core.Job").add(
dependencies.ifAnyMissingClasses("org.springframework.batch.core.Job").add(
"org.springframework.batch", "spring-batch-core", "2.1.9.RELEASE");
}

View File

@@ -38,15 +38,27 @@ public class SpringBootstrapCompilerAutoConfiguration extends CompilerAutoConfig
@Override
public void applyDependencies(DependencyCustomizer dependencies) {
dependencies.ifMissingClasses("org.springframework.bootstrap.SpringApplication")
.add("org.springframework.bootstrap", "spring-bootstrap-application",
"0.0.1-SNAPSHOT");
DependencyCustomizer customizer = dependencies.ifAnyMissingClasses(
"org.springframework.bootstrap.SpringApplication").add(
"org.springframework.bootstrap", "spring-bootstrap", "0.0.1-SNAPSHOT");
customizer = customizer.ifAnyResourcesPresent("logback.xml").add(
"ch.qos.logback", "logback-classic", "1.0.7");
customizer = customizer.ifNotAdded("cg.qos.logback", "logback-classic")
.ifAnyResourcesPresent("log4j.properties", "log4j.xml")
.add("org.slf4j", "slf4j-log4j12", "1.7.1")
.add("log4j", "log4j", "1.2.16");
customizer = customizer.ifNotAdded("ch.qos.logback", "logback-classic")
.ifNotAdded("org.slf4j", "slf4j-log4j12")
.add("org.slf4j", "slf4j-jdk14", "1.7.1");
// FIXME get the version
}
@Override
public void applyImports(ImportCustomizer imports) {
imports.addImports("javax.sql.DataSource",
"org.springframework.stereotype.Controller",
"org.springframework.stereotype.Service",
"org.springframework.stereotype.Component",
"org.springframework.beans.factory.annotation.Autowired",
"org.springframework.beans.factory.annotation.Value",
"org.springframework.context.annotation.Import",

View File

@@ -32,10 +32,10 @@ public class SpringMvcCompilerAutoConfiguration extends CompilerAutoConfiguratio
@Override
public void applyDependencies(DependencyCustomizer dependencies) {
dependencies.ifMissingClasses("org.springframework.web.servlet.mvc.Controller")
dependencies.ifAnyMissingClasses("org.springframework.web.servlet.mvc.Controller")
.add("org.springframework", "spring-webmvc", "4.0.0.BOOTSTRAP-SNAPSHOT");
dependencies.ifMissingClasses("org.apache.catalina.startup.Tomcat",
dependencies.ifAnyMissingClasses("org.apache.catalina.startup.Tomcat",
"org.eclipse.jetty.server.Server").add("org.eclipse.jetty",
"jetty-webapp", "8.1.10.v20130312");

View File

@@ -29,6 +29,7 @@ import org.springframework.bootstrap.cli.compiler.GroovyCompiler;
* changes.
*
* @author Phillip Webb
* @author Dave Syer
*/
public class BootstrapRunner {
@@ -71,11 +72,7 @@ public class BootstrapRunner {
public synchronized void compileAndRun() throws Exception {
try {
// Shutdown gracefully any running container
if (this.runThread != null) {
this.runThread.shutdown();
this.runThread = null;
}
stop();
// Compile
Class<?>[] classes = this.compiler.compile(this.file);
@@ -140,7 +137,7 @@ public class BootstrapRunner {
}
/**
* Shutdown the thread, closing any previously opened appplication context.
* Shutdown the thread, closing any previously opened application context.
*/
public synchronized void shutdown() {
if (this.applicationContext != null) {
@@ -188,4 +185,12 @@ public class BootstrapRunner {
}
}
public void stop() {
if (this.runThread != null) {
this.runThread.shutdown();
this.runThread = null;
}
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright 2012-2013 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.bootstrap.cli;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.junit.After;
import org.junit.BeforeClass;
import org.junit.Test;
/**
* @author Dave Syer
*
*/
public class SampleIntegrationTests {
private RunCommand command;
private void start(final String sample) throws Exception {
Future<RunCommand> future = Executors.newSingleThreadExecutor().submit(
new Callable<RunCommand>() {
@Override
public RunCommand call() throws Exception {
RunCommand command = new RunCommand();
command.run(sample);
return command;
}
});
this.command = future.get(10, TimeUnit.SECONDS);
}
@After
public void stop() {
if (this.command != null) {
this.command.stop();
}
}
@BeforeClass
public static void clean() {
// SpringBootstrapCli.main("clean");
// System.setProperty("ivy.message.logger.level", "4");
}
@Test
public void appSample() throws Exception {
start("samples/app.groovy");
}
@Test
public void webSample() throws Exception {
start("samples/web.groovy");
}
@Test
public void serviceSample() throws Exception {
start("samples/service.groovy");
}
}

View File

@@ -0,0 +1,7 @@
log4j.rootCategory=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n
log4j.category.org.springframework.bootstrap=DEBUG