package org.jsystemtest.plugin; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.project.MavenProject; import org.apache.tools.ant.DefaultLogger; import org.apache.tools.ant.Project; import org.apache.tools.ant.ProjectHelper; import org.jsystemtest.plugin.MultipleScenarioSuitExecutionFileParser.Execution; import jsystem.framework.FrameworkOptions; import jsystem.framework.JSystemProperties; import jsystem.framework.scenario.RunningProperties; import jsystem.runner.AntExecutionListener; import jsystem.utils.StringUtils; /** * * This plug in purpose is to execute JSystem scenarios * * @author Itai Agmon * * @goal run * @requiresProject true * * @phase integration-test */ public class JSystemMojo extends AbstractMojo { private static final String SCENARIO_PATH = "target/classes/scenarios"; private static final String SUT_PATH = "target/classes/sut"; private static final String TEST_PROPERTIES_FILE_EMPTY = ".testPropertiesFile_Empty"; private static final String DEFAULT_REPORTERS = "jsystem.extensions.report.difido.HtmlReporter;jsystem.framework.report.SystemOutTestReporter;jsystem.extensions.report.xml.XmlReporter;jsystem.extensions.report.junit.JUnitReporter"; private static final String DELIMITER = ","; /** * The current project representation. * * @parameter expression="${project}" * @required * @readonly */ private MavenProject mavenProject; /** * @parameter expression="${scenario}" */ private String scenario; /** * @parameter expression="${sut}" */ private String sut; /** * @parameter expression="${xmlFile}" */ private String xmlFile; /** */ public void execute() throws MojoExecutionException, MojoFailureException { if (null == scenario) { getLog().error("Please specify a valid scenario name. Scenario can't be " + scenario); throw new MojoExecutionException("Please specify a valid scenario name. Scenario can't be " + scenario); } if (null == sut) { getLog().error("Please specify a valid sut name. Sut can't be " + sut); throw new MojoExecutionException("Please specify a valid sut name. Sut can't be " + sut); } getLog().info("Changing user working dir to: " + mavenProject.getBasedir().getAbsolutePath()); // This line is for setting the current folder to the project root // folder. This is very important if we want to run the plug-in from the // parent folder. System.setProperty("user.dir", mavenProject.getBasedir().getAbsolutePath()); final File scenariosPath = new File(mavenProject.getBasedir(), SCENARIO_PATH); // Collect parameters that are required for the execution if (!StringUtils.isEmpty(xmlFile)) { xmlFileToParameters(); } final File[] sutFilesArr = sutParameterToFileArray(); final File[] scenarioFilesArr = scenarioParameterToFileArray(scenariosPath); // Check input correction if (sutFilesArr == null || sutFilesArr.length == 0 || scenarioFilesArr == null || scenarioFilesArr.length == 0) { throw new MojoFailureException("Sut or scenario parameters was not specified"); } if (sutFilesArr.length != scenarioFilesArr.length) { throw new MojoFailureException("Number of scenarios must be equals to the number of sut files"); } try { // This file is mandatory for scenario execution createEmptyTestPropertiesFile(scenariosPath); } catch (IOException e) { getLog().error("Failed to create new empty scenario properties file"); getLog().error(e); throw new MojoFailureException("Failed to create new empty scenario properties file"); } getLog().info("--------------------------Jsystem Maven Plugin--------------------------"); getLog().info("About to execute scenarios " + scenario + " with sut files " + sut); getLog().info("of project=" + mavenProject.getBasedir()); getLog().info("------------------------------------------------------------------------"); for (int i = 0; i < scenarioFilesArr.length; i++) { if (!scenarioFilesArr[i].exists()) { throw new MojoFailureException("Scenario file " + scenarioFilesArr[i] + " is not exist"); } if (!sutFilesArr[i].exists()) { throw new MojoFailureException("Sut file " + sutFilesArr[i] + " is not exist"); } String scenarioName = scenario.split(DELIMITER)[i]; if (!scenarioName.startsWith("scenarios/")) { scenarioName = "scenarios/" + scenarioName; } final Project p = createNewAntProject(scenariosPath, scenarioFilesArr[i], scenarioName, sut.split(DELIMITER)[i]); updateJSystemProperties(sutFilesArr[i], sut.split(DELIMITER)[i], scenarioFilesArr[i], scenarioName); executeSingleScenario(scenarioFilesArr[i], p); } getLog().info("------------------------------------------------------------------------"); getLog().info("Execution of scenarios " + scenario + " ended "); getLog().info("Reports can be found in " + mavenProject.getBasedir().getAbsolutePath() + File.separator + "log" + File.separator + "current"); } private void xmlFileToParameters() throws MojoFailureException { try { MultipleScenarioSuitExecutionFileParser parser = new MultipleScenarioSuitExecutionFileParser( new File(xmlFile)); parser.parse(); StringBuilder scenarioSb = new StringBuilder(); StringBuilder sutSb = new StringBuilder(); for (Execution execution : parser.getExecutions()) { scenarioSb.append(execution.getScenario().replaceFirst("\\.xml", "")).append(","); sutSb.append(execution.getSut().replaceFirst("sut\\\\", "")).append(","); } scenario = scenarioSb.toString(); sut = sutSb.toString(); } catch (IOException e) { throw new MojoFailureException(e.getMessage()); } } private void executeSingleScenario(final File scenarioFile, final Project p) { getLog().info("Executing scenario " + scenarioFile.getName() + " with sut " + p.getProperty("sutFile")); try { p.fireBuildStarted(); p.init(); ProjectHelper helper = ProjectHelper.getProjectHelper(); p.addReference("ant.projectHelper", helper); helper.parse(p, scenarioFile); p.executeTarget(p.getDefaultTarget()); } catch (Exception e) { getLog().error("Failed to execute scenario " + scenarioFile.getName()); getLog().error(e); } finally { p.fireBuildFinished(null); } getLog().info("Execution of scenario " + scenarioFile.getName() + " with sut " + p.getProperty("sutFile") + " has ended"); getLog().info("------------------------------------------------------------------------"); } private File[] scenarioParameterToFileArray(File scenariosPath) { final List<File> filesList = new ArrayList<File>(); for (String scenarioName : scenario.split(DELIMITER)) { filesList.add(new File(scenariosPath, scenarioName.replaceFirst("scenarios", "") + ".xml")); } return filesList.toArray(new File[] {}); } private File[] sutParameterToFileArray() { final List<File> filesList = new ArrayList<File>(); for (String sutFileName : sut.split(DELIMITER)) { filesList.add(new File(mavenProject.getBasedir() + File.separator + SUT_PATH, sutFileName)); } return filesList.toArray(new File[] {}); } /** * Updates the JSystem properties file with all the data required for the * execution * * @param sutFile * - The SUT file to use * @param scenarioFile * - The scenario to use */ private void updateJSystemProperties(final File sutFile, final String sutName, final File scenarioFile, final String scenarioName) { JSystemProperties.getInstance().setPreference(FrameworkOptions.LOG_FOLDER, mavenProject.getBasedir().getAbsolutePath() + File.separator + "log"); String reporters = JSystemProperties.getInstance().getPreference(FrameworkOptions.REPORTERS_CLASSES); // Making sure that there are reporters configured in the properties // file. if (null == reporters) { JSystemProperties.getInstance().setPreference(FrameworkOptions.REPORTERS_CLASSES, DEFAULT_REPORTERS); } // Configure all other required parameters: // Scenario JSystemProperties.getInstance().setPreference(FrameworkOptions.CURRENT_SCENARIO, scenarioName); // SUT JSystemProperties.getInstance().setPreference(FrameworkOptions.USED_SUT_FILE, sutName); // Class Folder JSystemProperties.getInstance().setPreference(FrameworkOptions.TESTS_CLASS_FOLDER, mavenProject.getBasedir().getAbsolutePath() + File.separator + "target" + File.separator + "classes"); // Test Source JSystemProperties.getInstance().setPreference(FrameworkOptions.TESTS_SOURCE_FOLDER, mavenProject.getBasedir().getAbsolutePath() + File.separator + "src" + File.separator + "main" + File.separator + "java"); // resources folder. JSystemProperties.getInstance().setPreference(FrameworkOptions.RESOURCES_SOURCE_FOLDER, mavenProject.getBasedir().getAbsolutePath() + File.separator + "src" + File.separator + "main" + File.separator + "resources"); } /** * Create ANT project that can be executed programatically * * @param scenariosPath * @param scenarioFile * @param sutFile * @return */ private Project createNewAntProject(File scenariosPath, File scenarioFile, String scenarioName, String sutName) { System.setProperty(RunningProperties.CURRENT_SCENARIO_NAME, scenarioName); System.setProperty(RunningProperties.CURRENT_SUT, sutName); Project p = new Project(); p.setName("JSystem Maven Plugin Project"); p.setBaseDir(mavenProject.getBasedir()); p.addBuildListener(new AntExecutionListener()); p.setProperty("basedir", scenariosPath.getAbsolutePath()); p.setProperty("scenarios.base", scenariosPath.getParentFile().getAbsolutePath()); p.setProperty("sutFile", sutName); p.setProperty("ant.file", scenarioFile.getAbsolutePath()); DefaultLogger consoleLogger = new DefaultLogger(); consoleLogger.setErrorPrintStream(System.err); consoleLogger.setOutputPrintStream(System.out); consoleLogger.setMessageOutputLevel(Project.MSG_INFO); p.addBuildListener(consoleLogger); return p; } /** * This is required for executing scenarios * * @param scenariosPath * @throws IOException */ private void createEmptyTestPropertiesFile(final File scenariosPath) throws IOException { File testPropFile = new File(scenariosPath, TEST_PROPERTIES_FILE_EMPTY); getLog().debug("About to create file " + testPropFile.getAbsolutePath()); if (!testPropFile.exists()) { if (!testPropFile.createNewFile()) { throw new IOException("Failed to create new empty properties file"); } } if (!testPropFile.exists()) { throw new IOException("Failed to create " + testPropFile.getAbsolutePath()); } getLog().debug("Created file " + testPropFile.getAbsolutePath()); } }