/*
* Sonar PHP Plugin
* Copyright (C) 2010 Sonar PHP Plugin
* dev@sonar.codehaus.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.plugins.php.phpunit;
import static org.sonar.plugins.php.api.Php.PHP;
import static org.sonar.plugins.php.phpunit.PhpUnitConfiguration.PHPUNIT_ANALYZE_TEST_DIRECTORY_KEY;
import static org.sonar.plugins.php.phpunit.PhpUnitConfiguration.PHPUNIT_ARGUMENT_LINE_KEY;
import static org.sonar.plugins.php.phpunit.PhpUnitConfiguration.PHPUNIT_BOOTSTRAP_OPTION;
import static org.sonar.plugins.php.phpunit.PhpUnitConfiguration.PHPUNIT_BOOTSTRAP_PROPERTY_KEY;
import static org.sonar.plugins.php.phpunit.PhpUnitConfiguration.PHPUNIT_CONFIGURATION_OPTION;
import static org.sonar.plugins.php.phpunit.PhpUnitConfiguration.PHPUNIT_CONFIGURATION_PROPERTY_KEY;
import static org.sonar.plugins.php.phpunit.PhpUnitConfiguration.PHPUNIT_FILTER_OPTION;
import static org.sonar.plugins.php.phpunit.PhpUnitConfiguration.PHPUNIT_FILTER_PROPERTY_KEY;
import static org.sonar.plugins.php.phpunit.PhpUnitConfiguration.PHPUNIT_GROUP_OPTION;
import static org.sonar.plugins.php.phpunit.PhpUnitConfiguration.PHPUNIT_GROUP_PROPERTY_KEY;
import static org.sonar.plugins.php.phpunit.PhpUnitConfiguration.PHPUNIT_IGNORE_CONFIGURATION_OPTION;
import static org.sonar.plugins.php.phpunit.PhpUnitConfiguration.PHPUNIT_IGNORE_CONFIGURATION_PROPERTY_KEY;
import static org.sonar.plugins.php.phpunit.PhpUnitConfiguration.PHPUNIT_LOADER_OPTION;
import static org.sonar.plugins.php.phpunit.PhpUnitConfiguration.PHPUNIT_LOADER_PROPERTY_KEY;
import static org.sonar.plugins.php.phpunit.PhpUnitConfiguration.PHPUNIT_MAIN_TEST_FILE_PROPERTY_KEY;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.resources.Project;
import org.sonar.plugins.php.core.PhpPluginAbstractExecutor;
/**
* The Class PhpUnitExecutor.
*/
public class PhpUnitExecutor extends PhpPluginAbstractExecutor {
/** The logger. */
private static final Logger LOG = LoggerFactory.getLogger(PhpUnitExecutor.class);
private static final String PHPUNIT_COVERAGE_CLOVER_OPTION = "--coverage-clover=";
private static final String PHPUNIT_LOG_JUNIT_OPTION = "--log-junit=";
private static final String PHPUNIT_PREFIX = "phpunit";
private static final String XML_SUFFIX = ".xml";
/** The configuration. */
private final PhpUnitConfiguration configuration;
/** The project. */
private final Project project;
/**
* Instantiates a new php unit executor.
*
* @param configuration
* the configuration
* @param project
* the project
*/
public PhpUnitExecutor(PhpUnitConfiguration config, Project project) {
super();
this.configuration = config;
this.project = project;
PHP.setConfiguration(configuration.getProject().getConfiguration());
}
/**
* @see org.sonar.plugins.php.core.PhpPluginAbstractExecutor#getCommandLine()
*/
@Override
protected List<String> getCommandLine() {
List<String> result = new ArrayList<String>();
result.add(configuration.getOsDependentToolScriptName());
Configuration c = configuration.getProject().getConfiguration();
addBasicOptions(result);
boolean useMaintTestClass = true;
if (configuration.isStringPropertySet(PHPUNIT_CONFIGURATION_PROPERTY_KEY)) {
result.add(PHPUNIT_CONFIGURATION_OPTION + configuration.getConfiguration());
useMaintTestClass = false;
}
addExtendedOptions(result, c);
if (useMaintTestClass && configuration.isStringPropertySet(PHPUNIT_MAIN_TEST_FILE_PROPERTY_KEY)) {
result.add(project.getName());
result.add(configuration.getMainTestClass());
}
// source directory is appended phpunit.
if ( !useMaintTestClass || !c.containsKey(PHPUNIT_ANALYZE_TEST_DIRECTORY_KEY) || c.getBoolean(PHPUNIT_ANALYZE_TEST_DIRECTORY_KEY)) {
result.add(getTestDirectoryOrFiles());
}
return result;
}
/**
* @param result
* @param c
*/
private void addExtendedOptions(List<String> result, Configuration c) {
if (configuration.isStringPropertySet(PHPUNIT_LOADER_PROPERTY_KEY)) {
result.add(PHPUNIT_LOADER_OPTION + configuration.getLoader());
}
if (configuration.isStringPropertySet(PHPUNIT_GROUP_PROPERTY_KEY)) {
result.add(PHPUNIT_GROUP_OPTION + configuration.getGroup());
}
if (configuration.isStringPropertySet(PHPUNIT_ARGUMENT_LINE_KEY)) {
result.add(configuration.getArgumentLine());
}
if (c.containsKey(PHPUNIT_IGNORE_CONFIGURATION_PROPERTY_KEY) && c.getBoolean(PHPUNIT_IGNORE_CONFIGURATION_PROPERTY_KEY)) {
result.add(PHPUNIT_IGNORE_CONFIGURATION_OPTION);
}
result.add(PHPUNIT_LOG_JUNIT_OPTION + configuration.getReportFile());
if (configuration.shouldRunCoverage()) {
result.add(PHPUNIT_COVERAGE_CLOVER_OPTION + configuration.getCoverageReportFile());
}
}
/**
* @param result
*/
private void addBasicOptions(List<String> result) {
if (configuration.isStringPropertySet(PHPUNIT_FILTER_PROPERTY_KEY)) {
result.add(PHPUNIT_FILTER_OPTION + configuration.getFilter());
}
if (configuration.isStringPropertySet(PHPUNIT_BOOTSTRAP_PROPERTY_KEY)) {
result.add(PHPUNIT_BOOTSTRAP_OPTION + configuration.getBootstrap());
}
}
/**
* @param result
* @return phpunit configuration option followed by the generated phpunit.xml launcher file. Or the test directory if only one.
*/
private String getTestDirectoryOrFiles() {
List<File> testDirs = project.getFileSystem().getTestDirs();
String directoryOrFiles = null;
if (testDirs.size() == 1) {
directoryOrFiles = testDirs.get(0).toString();
} else {
// in case of multiple source directories, phpunit.xml file is generated and passed to phpunit.
LOG.warn("Phpunit does not support multiple source directories for the moment.");
LOG.warn("Group your tests folder under the same directory or use phpunit.xml file");
List<File> testFiles = project.getFileSystem().getTestFiles(PHP);
LOG.info("Generating phpunit.xml file containing all your test files...");
File phpunitXml = createPhpunitConfigurationFile(testFiles);
LOG.warn(phpunitXml + " file generated.");
directoryOrFiles = PHPUNIT_CONFIGURATION_OPTION + phpunitXml.toString();
}
return directoryOrFiles;
}
/**
* @param testFiles
* @return
*/
private File createPhpunitConfigurationFile(List<File> testFiles) {
File workingDir = configuration.createWorkingDirectory();
File ruleset = null;
try {
ruleset = File.createTempFile(PHPUNIT_PREFIX, XML_SUFFIX, workingDir);
StringBuilder xml = new StringBuilder("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
xml.append("<phpunit><testsuites><testsuite name=\"Generated\">\n");
for (File f : testFiles) {
xml.append("<file>").append(f.getAbsolutePath()).append("</file>\n");
}
xml.append("</testsuite></testsuites></phpunit>");
FileUtils.writeStringToFile(ruleset, xml.toString());
} catch (IOException e) {
String msg = "Error while creating temporary phpunit.xml from files: " + testFiles + " to file : " + ruleset + " in dir "
+ workingDir;
LOG.error(msg);
}
return ruleset.length() > 0 ? ruleset : null;
}
/**
* @see org.sonar.plugins.php.core.PhpPluginAbstractExecutor#getExecutedTool()
*/
@Override
protected String getExecutedTool() {
return "Phpunit";
}
/**
* @return the configuration
*/
public PhpUnitConfiguration getConfiguration() {
return configuration;
}
}