package de.saumya.mojo.tests;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.apache.maven.artifact.DependencyResolutionRequiredException;
import org.apache.maven.plugin.MojoExecutionException;
import de.saumya.mojo.gem.AbstractGemMojo;
import de.saumya.mojo.jruby.JRubyVersion;
import de.saumya.mojo.jruby.JRubyVersion.Mode;
import de.saumya.mojo.ruby.gems.GemException;
import de.saumya.mojo.ruby.script.ScriptException;
import de.saumya.mojo.ruby.script.ScriptFactory;
import de.saumya.mojo.tests.JRubyRun.Result;
/**
* maven wrapper around some test command.
*
* @phase test
* @requiresDependencyResolution test
*/
public abstract class AbstractTestMojo extends AbstractGemMojo {
/**
* @parameter expression="${project.build.directory}/surefire-reports"
*/
protected File testReportDirectory;
/**
* skip all tests
* <br/>
* Command line -DskipTests=...
* @parameter expression="${skipTests}" default-value="false"
*/
protected boolean skipTests;
/**
* skip all tests
* <br/>
* Command line -Dmaven.test.skip=...
* @parameter expression="${maven.test.skip}" default-value="false"
*/
protected boolean skip;
/**
* run tests for both ruby 1.8 and 1.9
* <br/>
* Command line -Djruby.18and19=...
* @deprecated
*
* @parameter expression="${jruby.18and19}"
*/
protected Boolean use18and19;
/**
* run tests with list of ruby modes 1.8, 1.9, 2.0
* <br/>
* Command line -Djruby.modes=1.9,2.0
*
* @parameter expression="${jruby.modes}"
*/
protected String modes;
/**
* run tests with a several versions of jruby
* <br/>
* Command line -Djruby.versions=...
*
* @parameter expression="${jruby.versions}"
*/
protected String versions;
/**
* The name of the summary (xml-)report which can be used by TeamCity and Co.
*
* @parameter
*/
protected File summaryReport;
private Mode[] calculateModes( Mode defaultMode )
{
List<Mode> result = new ArrayList<Mode>();
if( use18and19 != null && use18and19 == true )
{
getLog().warn( "use18and19 is deprecated - use modes instead" );
result.add( Mode._18 );
result.add( Mode._19 );
}
else if (jrubySwitches != null )
{
for ( Mode m: Mode.values() )
{
if ( jrubySwitches.contains( m.flag ) )
{
result.add( m );
}
}
}
if (this.modes != null )
{
String[] modes = this.modes.split( "[\\ ,;]+" );
for( String m : modes )
{
Mode mode = Mode.valueOf( "_" + m.replace( ".", "" ) );
if ( ! result.contains( mode ) )
{
result.add( mode );
}
}
}
if ( result.size() == 0)
{
result.add( defaultMode );
}
return result.toArray( new Mode[ result.size() ] );
}
private JRubyVersion[] calculateVersions()
{
if ( versions == null )
{
return new JRubyVersion[] { getJrubyVersion() };
}
else
{
String[] jrubyVersions = versions.split("[\\ ,;]+");
JRubyVersion[] result = new JRubyVersion[ jrubyVersions.length ];
int i = 0;
for( String version: jrubyVersions ){
result[ i++ ] = new JRubyVersion( version );
}
return result;
}
}
protected void executeWithGems() throws MojoExecutionException, IOException, ScriptException, GemException {
testReportDirectory = new File(testReportDirectory.getAbsolutePath().replace("${project.basedir}/",""));
List<JRubyRun> runs = new ArrayList<JRubyRun>();
JRubyVersion[] versions = calculateVersions();
Mode[] modes = calculateModes( getJrubyVersion().defaultMode() );
if ( versions.length == 1 && versions[ 0 ].equals( getJrubyVersion() ) &&
modes.length == 1 && modes[0] == getJrubyVersion().defaultMode() )
{
runs.add( new JRubyRun( getJrubyVersion() ) );
}
else
{
for( JRubyVersion version : versions )
{
runs.add( new JRubyRun( version, modes ) );
}
}
final File outputDir = new File(this.project.getBuild().getDirectory()
.replace("${project.basedir}/", ""));
TestScriptFactory scriptFactory = null;
for( JRubyRun run: runs){
scriptFactory = newTestScriptFactory();
scriptFactory.setBaseDir(project.getBasedir());
scriptFactory.setGemHome(gemsConfig.getGemHome());
scriptFactory.setGemPaths(gemsConfig.getGemPath());
scriptFactory.setOutputDir(outputDir);
scriptFactory.setSystemProperties(project.getProperties());
scriptFactory.setSummaryReport(summaryReport);
scriptFactory.setReportPath(testReportDirectory);
try {
scriptFactory.setClasspathElements(project
.getTestClasspathElements());
}
catch (DependencyResolutionRequiredException e) {
throw new MojoExecutionException("error getting classpath", e);
}
runIt(run, scriptFactory);
if (run.modes.length == 0)
{
getLog().warn( "JRuby version " + run.version + " can not run any of the given modes: " +
( this.modes == null ? Arrays.toString( modes ) : this.modes ) );
}
else
{
scriptFactory.emit();
}
}
boolean hasOverview = this.versions != null || modes != null || (use18and19 != null && use18and19);
if(hasOverview){
getLog().info("");
getLog().info("\tOverall Summary");
getLog().info("\t===============");
}
boolean failure = false;
for( JRubyRun run: runs){
for(Mode mode: run.modes){
if(hasOverview){
getLog().info("\t" + run.toString(mode));
}
failure |= !run.result(mode).success;
}
}
if(hasOverview){
getLog().info("");
getLog().info("use '" + scriptFactory.getScriptFile() +
"' for faster command line execution.");
}
if(failure){
throw new MojoExecutionException("There were test failures");
}
}
protected void runIt(JRubyRun run, TestScriptFactory testScriptFactory) throws MojoExecutionException, IOException, ScriptException {
final de.saumya.mojo.ruby.script.ScriptFactory factory;
if (getJrubyVersion().equals(run.version) ){//|| run.isDefaultModeOnly()){
factory = this.factory;
}
else {
try {
factory = newScriptFactory(resolveJRubyCompleteArtifact(run.version.toString()));
// TODO remove this - it should have been already taken care of :(
if( env != null ){
for( Map.Entry<String, String> entry: env.entrySet() ){
factory.addEnv( entry.getKey(), entry.getValue() );
}
}
} catch (DependencyResolutionRequiredException e) {
throw new MojoExecutionException("could not resolve jruby", e);
}
}
for (Mode mode : run.modes) {
JRubyVersion version = null;
getLog().info("");
if ( !run.isDefaultModeOnly ) {
factory.addSwitch(mode.flag);
getLog().info("\trun with jruby " + run.version + " in mode " + mode);
version = run.version;
}
else {
getLog().info("\trun with jruby " + run.version);
mode = null;
version = null;
}
getLog().info("");
run.setResult(mode, runIt(factory, mode, version, testScriptFactory));
}
}
protected abstract TestScriptFactory newTestScriptFactory();//Mode mode);
protected abstract Result runIt(ScriptFactory factory, Mode mode, JRubyVersion version, TestScriptFactory testScriptFactory)
throws IOException, ScriptException, MojoExecutionException;
}