package org.codehaus.mojo.rspec;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
/**
* Mojo to run Ruby Spec test
*
* @author Michael Ward
* @author Mauro Talevi
* @goal spec
*/
public class RspecRunnerMojo extends AbstractMojo {
/**
* The project base directory
*
* @parameter expression="${basedir}"
* @required
* @readonly
*/
protected String basedir;
/**
* The classpath elements of the project being tested.
*
* @parameter expression="${project.testClasspathElements}"
* @required
* @readonly
*/
protected List<String> classpathElements;
/**
* The directory containing the RSpec source files
*
* @parameter
* @required
*/
protected String sourceDirectory;
/**
* The directory where the RSpec report will be written to
*
* @parameter
* @required
*/
protected String outputDirectory;
/**
* The name of the RSpec report (optional, defaults to "rspec_report.html")
*
* @parameter expression="rspec_report.html"
*/
protected String reportName;
/**
* The directory where JRuby is installed (optional, defaults to
* "${user.home}/.jruby")
*
* @parameter expression="${user.home}/.jruby"
*/
protected String jrubyHome;
/**
* The flag to ignore failures (optional, defaults to "false")
*
* @parameter expression="false"
*/
protected boolean ignoreFailure;
/**
* The flag to skip tests (optional, defaults to "false")
*
* @parameter expression="false"
*/
protected boolean skipTests;
/**
* List of system properties to set for the tests.
*
* @parameter
*/
protected Properties systemProperties;
private RSpecScriptFactory rspecScriptFactory = new RSpecScriptFactory();
private ShellScriptFactory shellScriptFactory = new ShellScriptFactory();
public RspecRunnerMojo() {
}
public void execute() throws MojoExecutionException, MojoFailureException {
if (skipTests) {
getLog().info("Skipping RSpec tests");
return;
}
getLog().info("Running RSpec tests from " + sourceDirectory);
String reportPath = outputDirectory + "/" + reportName;
initScriptFactory( rspecScriptFactory, reportPath);
initScriptFactory( shellScriptFactory, reportPath);
try {
rspecScriptFactory.emit();
} catch (Exception e) {
getLog().error( "error emitting .rb", e );
}
try {
shellScriptFactory.emit();
} catch (Exception e) {
getLog().error( "error emitting .sh", e );
}
try {
runScript(rspecScriptFactory.getScript() );
} catch (MalformedURLException e) {
getLog().error( "error running script", e );
}
}
private void initScriptFactory(ScriptFactory factory, String reportPath) {
factory.setBaseDir(basedir);
factory.setClasspathElements(classpathElements);
factory.setOutputDir(new File(outputDirectory));
factory.setReportPath(reportPath);
factory.setSourceDir(sourceDirectory);
factory.setSystemProperties( systemProperties );
}
private void runScript(String script) {
//getLog().info( "[[\n\n" + script + "\n\n]]" );
List<String> cmdLine = new ArrayList<String>();
cmdLine.add( jrubyHome + "/bin/jruby");
cmdLine.add( "-J-Dbasedir=" + basedir );
for (Object propName : systemProperties.keySet()) {
String propValue = systemProperties.getProperty(propName.toString());
cmdLine.add("-J-D" + propName + "=" + propValue);
}
//getLog().info( "cmdline [" + cmdLine + "]" );
StringBuilder classpath = new StringBuilder();
boolean first = true;
for (String element : classpathElements) {
if (first) {
first = false;
} else {
classpath.append(":");
}
classpath.append(element);
}
ProcessBuilder builder = new ProcessBuilder(cmdLine);
builder.environment().put("JRUBY_HOME", jrubyHome);
builder.environment().put("CLASSPATH", classpath.toString());
try {
Process process = builder.start();
new InputConsumer(process.getInputStream(), System.out).start();
new InputConsumer(process.getErrorStream(), System.err).start();
OutputStream out = process.getOutputStream();
out.write(script.getBytes());
out.close();
process.waitFor();
System.err.println("exit: " + process.exitValue());
} catch (IOException e) {
getLog().error(e);
} catch (InterruptedException e) {
getLog().error(e);
}
}
private class InputConsumer extends Thread {
private InputStream input;
private OutputStream sink;
public InputConsumer(InputStream input, OutputStream sink) {
this.input = input;
this.sink = sink;
}
public void run() {
byte[] buf = new byte[128];
int len = 0;
try {
while ((len = this.input.read(buf)) >= 0) {
this.sink.write(buf, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}