Line-ending characters

This commit is contained in:
j2blake 2013-12-19 11:44:10 -05:00
parent 0192edbd67
commit 2e8ef62bb1
5 changed files with 1155 additions and 1155 deletions

View file

@ -1,26 +1,26 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */ /* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.utilities.testrunner; package edu.cornell.mannlib.vitro.utilities.testrunner;
/** /**
* Indicates a problem with the attempt to run a command in a sub-process. * Indicates a problem with the attempt to run a command in a sub-process.
*/ */
public class CommandRunnerException extends Exception { public class CommandRunnerException extends Exception {
public CommandRunnerException() { public CommandRunnerException() {
super(); super();
} }
public CommandRunnerException(String message) { public CommandRunnerException(String message) {
super(message); super(message);
} }
public CommandRunnerException(Throwable cause) { public CommandRunnerException(Throwable cause) {
super(cause); super(cause);
} }
public CommandRunnerException(String message, Throwable cause) { public CommandRunnerException(String message, Throwable cause) {
super(message, cause); super(message, cause);
} }
} }

View file

@ -1,26 +1,26 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */ /* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.utilities.testrunner; package edu.cornell.mannlib.vitro.utilities.testrunner;
/** /**
* Indicates a problem so severe that we might as well stop now. * Indicates a problem so severe that we might as well stop now.
*/ */
public class FatalException extends RuntimeException { public class FatalException extends RuntimeException {
public FatalException() { public FatalException() {
super(); super();
} }
public FatalException(String message) { public FatalException(String message) {
super(message); super(message);
} }
public FatalException(Throwable cause) { public FatalException(Throwable cause) {
super(cause); super(cause);
} }
public FatalException(String message, Throwable cause) { public FatalException(String message, Throwable cause) {
super(message, cause); super(message, cause);
} }
} }

View file

@ -1,434 +1,434 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */ /* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.utilities.testrunner; package edu.cornell.mannlib.vitro.utilities.testrunner;
import java.io.File; import java.io.File;
import java.io.FileFilter; import java.io.FileFilter;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.io.Reader; import java.io.Reader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Properties; import java.util.Properties;
import edu.cornell.mannlib.vitro.utilities.testrunner.listener.Listener; import edu.cornell.mannlib.vitro.utilities.testrunner.listener.Listener;
import edu.cornell.mannlib.vitro.utilities.testrunner.listener.LoggingListener; import edu.cornell.mannlib.vitro.utilities.testrunner.listener.LoggingListener;
import edu.cornell.mannlib.vitro.utilities.testrunner.listener.MulticastListener; import edu.cornell.mannlib.vitro.utilities.testrunner.listener.MulticastListener;
/** /**
* Holds the runtime parameters that are read from the properties file, perhaps * Holds the runtime parameters that are read from the properties file, perhaps
* with modifications from the GUI if we are running interactively. * with modifications from the GUI if we are running interactively.
*/ */
public class SeleniumRunnerParameters { public class SeleniumRunnerParameters {
public static final String PROP_OUTPUT_DIRECTORY = "output_directory"; public static final String PROP_OUTPUT_DIRECTORY = "output_directory";
public static final String PROP_UPLOAD_DIRECTORY = "upload_directory"; public static final String PROP_UPLOAD_DIRECTORY = "upload_directory";
public static final String PROP_SUITE_DIRECTORIES = "suite_parent_directories"; public static final String PROP_SUITE_DIRECTORIES = "suite_parent_directories";
public static final String PROP_WEBSITE_URL = "website_url"; public static final String PROP_WEBSITE_URL = "website_url";
public static final String PROP_USER_EXTENSIONS_PATH = "user_extensions_path"; public static final String PROP_USER_EXTENSIONS_PATH = "user_extensions_path";
public static final String PROP_FIREFOX_PROFILE_PATH = "firefox_profile_template_path"; public static final String PROP_FIREFOX_PROFILE_PATH = "firefox_profile_template_path";
public static final String PROP_SUITE_TIMEOUT_LIMIT = "suite_timeout_limit"; public static final String PROP_SUITE_TIMEOUT_LIMIT = "suite_timeout_limit";
public static final String PROP_SELENIUM_JAR_PATH = "selenium_jar_path"; public static final String PROP_SELENIUM_JAR_PATH = "selenium_jar_path";
public static final String PROP_IGNORED_TESTS = "ignored_tests_file"; public static final String PROP_IGNORED_TESTS = "ignored_tests_file";
public static final String PROP_SUMMARY_CSS = "summary_css_file"; public static final String PROP_SUMMARY_CSS = "summary_css_file";
public static final String LOGFILE_NAME = "log_file.txt"; public static final String LOGFILE_NAME = "log_file.txt";
private final String websiteUrl; private final String websiteUrl;
private final File userExtensionsFile; private final File userExtensionsFile;
private final File firefoxProfileDir; private final File firefoxProfileDir;
private final int suiteTimeoutLimit; private final int suiteTimeoutLimit;
private final File seleniumJarPath; private final File seleniumJarPath;
private final File uploadDirectory; private final File uploadDirectory;
private final File outputDirectory; private final File outputDirectory;
private final File logFile; private final File logFile;
private final Collection<File> suiteParentDirectories; private final Collection<File> suiteParentDirectories;
private final ModelCleanerProperties modelCleanerProperties; private final ModelCleanerProperties modelCleanerProperties;
private final IgnoredTests ignoredTests; private final IgnoredTests ignoredTests;
private boolean cleanModel = true; private boolean cleanModel = true;
private boolean cleanUploads = true; private boolean cleanUploads = true;
// If we fail during the parameter parsing, we'll still write the log // If we fail during the parameter parsing, we'll still write the log
// somewhere. // somewhere.
private Listener listener = new LoggingListener(System.out); private Listener listener = new LoggingListener(System.out);
/** /**
* Read the required properties from the property file, and do some checks * Read the required properties from the property file, and do some checks
* on them. * on them.
*/ */
public SeleniumRunnerParameters(String propertiesFilepath) public SeleniumRunnerParameters(String propertiesFilepath)
throws IOException { throws IOException {
Properties props = loadPropertiesFile(propertiesFilepath); Properties props = loadPropertiesFile(propertiesFilepath);
this.websiteUrl = getRequiredProperty(props, PROP_WEBSITE_URL); this.websiteUrl = getRequiredProperty(props, PROP_WEBSITE_URL);
this.userExtensionsFile = checkReadableFile(props, this.userExtensionsFile = checkReadableFile(props,
PROP_USER_EXTENSIONS_PATH); PROP_USER_EXTENSIONS_PATH);
this.firefoxProfileDir = checkOptionalReadableDirectory(props, this.firefoxProfileDir = checkOptionalReadableDirectory(props,
PROP_FIREFOX_PROFILE_PATH); PROP_FIREFOX_PROFILE_PATH);
this.suiteTimeoutLimit = getRequiredIntegerProperty(props, this.suiteTimeoutLimit = getRequiredIntegerProperty(props,
PROP_SUITE_TIMEOUT_LIMIT); PROP_SUITE_TIMEOUT_LIMIT);
this.seleniumJarPath = checkReadableFile(props, PROP_SELENIUM_JAR_PATH); this.seleniumJarPath = checkReadableFile(props, PROP_SELENIUM_JAR_PATH);
this.uploadDirectory = checkReadWriteDirectory(props, this.uploadDirectory = checkReadWriteDirectory(props,
PROP_UPLOAD_DIRECTORY); PROP_UPLOAD_DIRECTORY);
this.outputDirectory = checkOutputDirectory(props); this.outputDirectory = checkOutputDirectory(props);
this.logFile = new File(this.outputDirectory, LOGFILE_NAME); this.logFile = new File(this.outputDirectory, LOGFILE_NAME);
this.listener = new MulticastListener(); this.listener = new MulticastListener();
addListener(new LoggingListener(this.logFile)); addListener(new LoggingListener(this.logFile));
this.suiteParentDirectories = checkSuiteParentDirectories(props); this.suiteParentDirectories = checkSuiteParentDirectories(props);
this.modelCleanerProperties = new ModelCleanerProperties(props); this.modelCleanerProperties = new ModelCleanerProperties(props);
// Get the list of ignored tests. // Get the list of ignored tests.
String ignoredFilesPath = getRequiredProperty(props, PROP_IGNORED_TESTS); String ignoredFilesPath = getRequiredProperty(props, PROP_IGNORED_TESTS);
File ignoredFilesFile = new File(ignoredFilesPath); File ignoredFilesFile = new File(ignoredFilesPath);
FileHelper.checkReadableFile(ignoredFilesFile, "File '" FileHelper.checkReadableFile(ignoredFilesFile, "File '"
+ ignoredFilesPath + "'"); + ignoredFilesPath + "'");
this.ignoredTests = new IgnoredTests(ignoredFilesFile); this.ignoredTests = new IgnoredTests(ignoredFilesFile);
} }
/** /**
* Load the properties from the properties file. * Load the properties from the properties file.
*/ */
private Properties loadPropertiesFile(String propertiesFilepath) private Properties loadPropertiesFile(String propertiesFilepath)
throws FileNotFoundException, IOException { throws FileNotFoundException, IOException {
File propsFile = new File(propertiesFilepath); File propsFile = new File(propertiesFilepath);
if (!propsFile.exists()) { if (!propsFile.exists()) {
throw new FileNotFoundException("Property file does not exist: '" throw new FileNotFoundException("Property file does not exist: '"
+ propsFile + "'"); + propsFile + "'");
} }
Reader propsReader = null; Reader propsReader = null;
try { try {
propsReader = new FileReader(propsFile); propsReader = new FileReader(propsFile);
Properties props = new Properties(); Properties props = new Properties();
props.load(propsReader); props.load(propsReader);
return props; return props;
} finally { } finally {
if (propsReader != null) { if (propsReader != null) {
try { try {
propsReader.close(); propsReader.close();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
} }
} }
/** /**
* If there is a parameter for this key, it should point to a readable * If there is a parameter for this key, it should point to a readable
* directory. * directory.
*/ */
private File checkOptionalReadableDirectory(Properties props, String key) { private File checkOptionalReadableDirectory(Properties props, String key) {
String value = props.getProperty(key); String value = props.getProperty(key);
if (value == null) { if (value == null) {
return null; return null;
} }
value = value.trim(); value = value.trim();
if (value.trim().length() == 0) { if (value.trim().length() == 0) {
return null; return null;
} }
File dir = new File(value); File dir = new File(value);
if (!dir.exists()) { if (!dir.exists()) {
throw new IllegalArgumentException("Directory " + key + " '" throw new IllegalArgumentException("Directory " + key + " '"
+ value + "' does not exist."); + value + "' does not exist.");
} }
if (!dir.isDirectory()) { if (!dir.isDirectory()) {
throw new IllegalArgumentException("Directory " + key + " '" throw new IllegalArgumentException("Directory " + key + " '"
+ value + "' is not a directory."); + value + "' is not a directory.");
} }
if (!dir.canRead()) { if (!dir.canRead()) {
throw new IllegalArgumentException("Directory " + key + " '" throw new IllegalArgumentException("Directory " + key + " '"
+ value + "' is not readable."); + value + "' is not readable.");
} }
return dir; return dir;
} }
/** /**
* Check that there is a property for the required directory path, and that * Check that there is a property for the required directory path, and that
* it points to a valid directory. * it points to a valid directory.
*/ */
private File checkReadWriteDirectory(Properties props, String key) { private File checkReadWriteDirectory(Properties props, String key) {
String value = getRequiredProperty(props, key); String value = getRequiredProperty(props, key);
File dir = new File(value); File dir = new File(value);
if (!dir.exists()) { if (!dir.exists()) {
throw new IllegalArgumentException("Directory " + key + " '" throw new IllegalArgumentException("Directory " + key + " '"
+ value + "' does not exist. (" + dir.getAbsolutePath() + value + "' does not exist. (" + dir.getAbsolutePath()
+ ")"); + ")");
} }
if (!dir.isDirectory()) { if (!dir.isDirectory()) {
throw new IllegalArgumentException("Directory " + key + " '" throw new IllegalArgumentException("Directory " + key + " '"
+ value + "' is not a directory. (" + dir.getAbsolutePath() + value + "' is not a directory. (" + dir.getAbsolutePath()
+ ")"); + ")");
} }
if (!dir.canRead()) { if (!dir.canRead()) {
throw new IllegalArgumentException("Directory " + key + " '" throw new IllegalArgumentException("Directory " + key + " '"
+ value + "' is not readable. (" + dir.getAbsolutePath() + value + "' is not readable. (" + dir.getAbsolutePath()
+ ")"); + ")");
} }
if (!dir.canWrite()) { if (!dir.canWrite()) {
throw new IllegalArgumentException("Directory " + key + " '" throw new IllegalArgumentException("Directory " + key + " '"
+ value + "' is not writeable. (" + dir.getAbsolutePath() + value + "' is not writeable. (" + dir.getAbsolutePath()
+ ")"); + ")");
} }
return dir; return dir;
} }
private File checkReadableFile(Properties props, String key) { private File checkReadableFile(Properties props, String key) {
String value = getRequiredProperty(props, key); String value = getRequiredProperty(props, key);
File file = new File(value); File file = new File(value);
if (!file.exists()) { if (!file.exists()) {
throw new IllegalArgumentException("File " + key + ": '" + value throw new IllegalArgumentException("File " + key + ": '" + value
+ "' does not exist. (" + file.getAbsolutePath() + ")"); + "' does not exist. (" + file.getAbsolutePath() + ")");
} }
if (!file.isFile()) { if (!file.isFile()) {
throw new IllegalArgumentException("File " + key + ": '" + value throw new IllegalArgumentException("File " + key + ": '" + value
+ "' is not a file. (" + file.getAbsolutePath() + ")"); + "' is not a file. (" + file.getAbsolutePath() + ")");
} }
if (!file.canRead()) { if (!file.canRead()) {
throw new IllegalArgumentException("File " + key + ": '" + value throw new IllegalArgumentException("File " + key + ": '" + value
+ "' is not readable. (" + file.getAbsolutePath() + ")"); + "' is not readable. (" + file.getAbsolutePath() + ")");
} }
return file; return file;
} }
/** /**
* Get the property for the output directory. If it does not exist, create * Get the property for the output directory. If it does not exist, create
* it (the parent must exist). Ensure that it is writeable. * it (the parent must exist). Ensure that it is writeable.
*/ */
private File checkOutputDirectory(Properties props) throws IOException { private File checkOutputDirectory(Properties props) throws IOException {
String value = getRequiredProperty(props, PROP_OUTPUT_DIRECTORY); String value = getRequiredProperty(props, PROP_OUTPUT_DIRECTORY);
File outputDirectory = new File(value); File outputDirectory = new File(value);
File outputParent = outputDirectory.getParentFile(); File outputParent = outputDirectory.getParentFile();
if (!outputDirectory.exists()) { if (!outputDirectory.exists()) {
if (!outputParent.exists()) { if (!outputParent.exists()) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Output directory does not exist, nor does its parent. '" "Output directory does not exist, nor does its parent. '"
+ outputDirectory + "' (" + outputDirectory + "' ("
+ outputDirectory.getAbsolutePath() + ")"); + outputDirectory.getAbsolutePath() + ")");
} }
outputDirectory.mkdir(); outputDirectory.mkdir();
if (!outputDirectory.exists()) { if (!outputDirectory.exists()) {
throw new IOException("Failed to create output directory: '" throw new IOException("Failed to create output directory: '"
+ outputDirectory + "' (" + outputDirectory + "' ("
+ outputDirectory.getAbsolutePath() + ")"); + outputDirectory.getAbsolutePath() + ")");
} }
} }
if (!outputDirectory.isDirectory()) { if (!outputDirectory.isDirectory()) {
throw new IllegalArgumentException("Suite directory '" throw new IllegalArgumentException("Suite directory '"
+ outputDirectory.getPath() + "' is not a directory. (" + outputDirectory.getPath() + "' is not a directory. ("
+ outputDirectory.getAbsolutePath() + ")"); + outputDirectory.getAbsolutePath() + ")");
} }
if (!outputDirectory.canRead()) { if (!outputDirectory.canRead()) {
throw new IllegalArgumentException("Suite directory '" throw new IllegalArgumentException("Suite directory '"
+ outputDirectory.getPath() + "' is not readable. (" + outputDirectory.getPath() + "' is not readable. ("
+ outputDirectory.getAbsolutePath() + ")"); + outputDirectory.getAbsolutePath() + ")");
} }
if (!outputDirectory.canWrite()) { if (!outputDirectory.canWrite()) {
throw new IllegalArgumentException("Suite directory '" throw new IllegalArgumentException("Suite directory '"
+ outputDirectory.getPath() + "' is not writeable. (" + outputDirectory.getPath() + "' is not writeable. ("
+ outputDirectory.getAbsolutePath() + ")"); + outputDirectory.getAbsolutePath() + ")");
} }
return outputDirectory; return outputDirectory;
} }
/** /**
* Get the property for the suite directories and ensure that each one is * Get the property for the suite directories and ensure that each one is
* indeed a readable directory. * indeed a readable directory.
*/ */
private Collection<File> checkSuiteParentDirectories(Properties props) { private Collection<File> checkSuiteParentDirectories(Properties props) {
String value = getRequiredProperty(props, PROP_SUITE_DIRECTORIES); String value = getRequiredProperty(props, PROP_SUITE_DIRECTORIES);
List<File> dirs = new ArrayList<File>(); List<File> dirs = new ArrayList<File>();
String[] paths = value.split("[:;]"); String[] paths = value.split("[:;]");
for (String path : paths) { for (String path : paths) {
File dir = new File(path.trim()); File dir = new File(path.trim());
if (!dir.exists()) { if (!dir.exists()) {
throw new IllegalArgumentException("Suite directory '" throw new IllegalArgumentException("Suite directory '"
+ dir.getPath() + "' does not exist. (" + dir.getPath() + "' does not exist. ("
+ dir.getAbsolutePath() + ")"); + dir.getAbsolutePath() + ")");
} }
if (!dir.isDirectory()) { if (!dir.isDirectory()) {
throw new IllegalArgumentException("Suite directory '" throw new IllegalArgumentException("Suite directory '"
+ dir.getPath() + "' is not a directory. (" + dir.getPath() + "' is not a directory. ("
+ dir.getAbsolutePath() + ")"); + dir.getAbsolutePath() + ")");
} }
if (!dir.canRead()) { if (!dir.canRead()) {
throw new IllegalArgumentException("Suite directory '" throw new IllegalArgumentException("Suite directory '"
+ dir.getPath() + "' is not readable. (" + dir.getPath() + "' is not readable. ("
+ dir.getAbsolutePath() + ")"); + dir.getAbsolutePath() + ")");
} }
dirs.add(dir); dirs.add(dir);
} }
return dirs; return dirs;
} }
/** /**
* Get the value for this property. If there isn't one, or if it's empty, * Get the value for this property. If there isn't one, or if it's empty,
* complain. * complain.
*/ */
private String getRequiredProperty(Properties props, String key) { private String getRequiredProperty(Properties props, String key) {
String value = props.getProperty(key); String value = props.getProperty(key);
if ((value == null) || (value.trim().length() == 0)) { if ((value == null) || (value.trim().length() == 0)) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Property file must provide a value for '" + key + "'"); "Property file must provide a value for '" + key + "'");
} }
return value; return value;
} }
/** /**
* This required property must be a valid integer. * This required property must be a valid integer.
*/ */
private int getRequiredIntegerProperty(Properties props, String key) { private int getRequiredIntegerProperty(Properties props, String key) {
String value = getRequiredProperty(props, key); String value = getRequiredProperty(props, key);
try { try {
return Integer.parseInt(value.trim()); return Integer.parseInt(value.trim());
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw new IllegalArgumentException("Property value for '" + key throw new IllegalArgumentException("Property value for '" + key
+ "' is not a valid integer: " + value); + "' is not a valid integer: " + value);
} }
} }
public String getWebsiteUrl() { public String getWebsiteUrl() {
return websiteUrl; return websiteUrl;
} }
public File getUserExtensionsFile() { public File getUserExtensionsFile() {
return userExtensionsFile; return userExtensionsFile;
} }
public boolean hasFirefoxProfileDir() { public boolean hasFirefoxProfileDir() {
return firefoxProfileDir != null; return firefoxProfileDir != null;
} }
public File getFirefoxProfileDir() { public File getFirefoxProfileDir() {
return firefoxProfileDir; return firefoxProfileDir;
} }
public int getSuiteTimeoutLimit() { public int getSuiteTimeoutLimit() {
return suiteTimeoutLimit; return suiteTimeoutLimit;
} }
public File getSeleniumJarPath() { public File getSeleniumJarPath() {
return seleniumJarPath; return seleniumJarPath;
} }
public void addListener(Listener l) { public void addListener(Listener l) {
if (listener instanceof MulticastListener) { if (listener instanceof MulticastListener) {
((MulticastListener) listener).addListener(l); ((MulticastListener) listener).addListener(l);
} else { } else {
throw new IllegalStateException("Listener is not a multi-cast -- " throw new IllegalStateException("Listener is not a multi-cast -- "
+ "can't add new listeners."); + "can't add new listeners.");
} }
} }
public Listener getListener() { public Listener getListener() {
return listener; return listener;
} }
public void setListener(Listener logger) { public void setListener(Listener logger) {
this.listener = logger; this.listener = logger;
} }
public File getUploadDirectory() { public File getUploadDirectory() {
return uploadDirectory; return uploadDirectory;
} }
public File getOutputDirectory() { public File getOutputDirectory() {
return outputDirectory; return outputDirectory;
} }
public File getLogFile() { public File getLogFile() {
return logFile; return logFile;
} }
public Collection<File> getSuiteParentDirectories() { public Collection<File> getSuiteParentDirectories() {
return suiteParentDirectories; return suiteParentDirectories;
} }
public ModelCleanerProperties getModelCleanerProperties() { public ModelCleanerProperties getModelCleanerProperties() {
return modelCleanerProperties; return modelCleanerProperties;
} }
public IgnoredTests getIgnoredTests() { public IgnoredTests getIgnoredTests() {
return ignoredTests; return ignoredTests;
} }
public boolean isCleanModel() { public boolean isCleanModel() {
return cleanModel; return cleanModel;
} }
public void setCleanModel(boolean cleanModel) { public void setCleanModel(boolean cleanModel) {
this.cleanModel = cleanModel; this.cleanModel = cleanModel;
} }
public boolean isCleanUploads() { public boolean isCleanUploads() {
return cleanUploads; return cleanUploads;
} }
public void setCleanUploads(boolean cleanUploads) { public void setCleanUploads(boolean cleanUploads) {
this.cleanUploads = cleanUploads; this.cleanUploads = cleanUploads;
} }
public String toString() { public String toString() {
return "Parameters:" + "\n websiteUrl: " + websiteUrl return "Parameters:" + "\n websiteUrl: " + websiteUrl
+ "\n userExtensionsFile: " + userExtensionsFile + "\n userExtensionsFile: " + userExtensionsFile
+ "\n firefoxProfileDir: " + firefoxProfileDir + "\n firefoxProfileDir: " + firefoxProfileDir
+ "\n suiteTimeoutLimit: " + suiteTimeoutLimit + "\n suiteTimeoutLimit: " + suiteTimeoutLimit
+ "\n seleniumJarPath: " + seleniumJarPath + "\n seleniumJarPath: " + seleniumJarPath
+ "\n uploadDirectory: " + uploadDirectory + "\n uploadDirectory: " + uploadDirectory
+ "\n outputDirectory: " + outputDirectory + "\n outputDirectory: " + outputDirectory
+ "\n suiteParentDirectories: " + suiteParentDirectories + "\n suiteParentDirectories: " + suiteParentDirectories
+ "\n modelCleanerProperties: " + modelCleanerProperties + "\n modelCleanerProperties: " + modelCleanerProperties
+ "\n" + ignoredTests + "\n cleanModel: " + cleanModel + "\n" + ignoredTests + "\n cleanModel: " + cleanModel
+ "\n cleanUploads: " + cleanUploads; + "\n cleanUploads: " + cleanUploads;
} }
/** /**
* Look inside this parent directory and find any suite directories. You can * Look inside this parent directory and find any suite directories. You can
* recognize a suite directory because it contains a file named Suite.html. * recognize a suite directory because it contains a file named Suite.html.
*/ */
public Collection<File> findSuiteDirs(File parentDir) { public Collection<File> findSuiteDirs(File parentDir) {
return Arrays.asList(parentDir.listFiles(new FileFilter() { return Arrays.asList(parentDir.listFiles(new FileFilter() {
public boolean accept(File pathname) { public boolean accept(File pathname) {
if (!pathname.isDirectory()) { if (!pathname.isDirectory()) {
return false; return false;
} }
if (pathname.getName().charAt(0) == '.') { if (pathname.getName().charAt(0) == '.') {
return false; return false;
} }
File suiteFile = new File(pathname, "Suite.html"); File suiteFile = new File(pathname, "Suite.html");
if (suiteFile.exists()) { if (suiteFile.exists()) {
return true; return true;
} else { } else {
listener.subProcessErrout("Warning: suite file '" listener.subProcessErrout("Warning: suite file '"
+ suiteFile.getPath() + "' does not exist.\n"); + suiteFile.getPath() + "' does not exist.\n");
return false; return false;
} }
} }
})); }));
} }
} }

View file

@ -1,294 +1,294 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */ /* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.utilities.testrunner.datamodel; package edu.cornell.mannlib.vitro.utilities.testrunner.datamodel;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.SortedMap; import java.util.SortedMap;
import java.util.TreeMap; import java.util.TreeMap;
import edu.cornell.mannlib.vitro.utilities.testrunner.IgnoredTests; import edu.cornell.mannlib.vitro.utilities.testrunner.IgnoredTests;
import edu.cornell.mannlib.vitro.utilities.testrunner.IgnoredTests.IgnoredTestInfo; import edu.cornell.mannlib.vitro.utilities.testrunner.IgnoredTests.IgnoredTestInfo;
import edu.cornell.mannlib.vitro.utilities.testrunner.LogStats; import edu.cornell.mannlib.vitro.utilities.testrunner.LogStats;
import edu.cornell.mannlib.vitro.utilities.testrunner.Status; import edu.cornell.mannlib.vitro.utilities.testrunner.Status;
import edu.cornell.mannlib.vitro.utilities.testrunner.datamodel.SuiteData.TestData; import edu.cornell.mannlib.vitro.utilities.testrunner.datamodel.SuiteData.TestData;
import edu.cornell.mannlib.vitro.utilities.testrunner.output.OutputDataListener; import edu.cornell.mannlib.vitro.utilities.testrunner.output.OutputDataListener;
import edu.cornell.mannlib.vitro.utilities.testrunner.output.OutputDataListener.ProcessOutput; import edu.cornell.mannlib.vitro.utilities.testrunner.output.OutputDataListener.ProcessOutput;
import edu.cornell.mannlib.vitro.utilities.testrunner.output.SuiteResults; import edu.cornell.mannlib.vitro.utilities.testrunner.output.SuiteResults;
/** /**
* Collect all that we know about suites, tests, and their current status. * Collect all that we know about suites, tests, and their current status.
*/ */
public class DataModel { public class DataModel {
/* base data */ /* base data */
private Collection<SuiteContents> suiteContents = Collections.emptyList(); private Collection<SuiteContents> suiteContents = Collections.emptyList();
private Collection<File> selectedSuites = Collections.emptyList(); private Collection<File> selectedSuites = Collections.emptyList();
private Collection<SuiteResults> suiteResults = Collections.emptyList(); private Collection<SuiteResults> suiteResults = Collections.emptyList();
private OutputDataListener.Info dataListenerInfo = OutputDataListener.Info.EMPTY_INFO; private OutputDataListener.Info dataListenerInfo = OutputDataListener.Info.EMPTY_INFO;
private IgnoredTests ignoredTestList = IgnoredTests.EMPTY_LIST; private IgnoredTests ignoredTestList = IgnoredTests.EMPTY_LIST;
private LogStats logStats = LogStats.EMPTY_LOG_STATS; // TODO private LogStats logStats = LogStats.EMPTY_LOG_STATS; // TODO
/* derived data */ /* derived data */
private Status runStatus = Status.PENDING; private Status runStatus = Status.PENDING;
private final SortedMap<String, SuiteData> suiteDataMap = new TreeMap<String, SuiteData>(); private final SortedMap<String, SuiteData> suiteDataMap = new TreeMap<String, SuiteData>();
private final EnumMap<Status, List<SuiteData>> suiteMapByStatus = new EnumMap<Status, List<SuiteData>>( private final EnumMap<Status, List<SuiteData>> suiteMapByStatus = new EnumMap<Status, List<SuiteData>>(
Status.class); Status.class);
private final List<TestData> allTests = new ArrayList<TestData>(); private final List<TestData> allTests = new ArrayList<TestData>();
private final EnumMap<Status, List<TestData>> testMapByStatus = new EnumMap<Status, List<TestData>>( private final EnumMap<Status, List<TestData>> testMapByStatus = new EnumMap<Status, List<TestData>>(
Status.class); Status.class);
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// Constructor // Constructor
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
public DataModel() { public DataModel() {
calculate(); calculate();
} }
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// Update the base data. // Update the base data.
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
public void setSuiteContents(Collection<SuiteContents> suiteContents) { public void setSuiteContents(Collection<SuiteContents> suiteContents) {
this.suiteContents = new ArrayList<SuiteContents>(suiteContents); this.suiteContents = new ArrayList<SuiteContents>(suiteContents);
calculate(); calculate();
} }
public void setSelectedSuites(Collection<File> selectedSuites) { public void setSelectedSuites(Collection<File> selectedSuites) {
this.selectedSuites = new ArrayList<File>(selectedSuites); this.selectedSuites = new ArrayList<File>(selectedSuites);
calculate(); calculate();
} }
public Collection<File> getSelectedSuites() { public Collection<File> getSelectedSuites() {
return new ArrayList<File>(selectedSuites); return new ArrayList<File>(selectedSuites);
} }
public void setSuiteResults(Collection<SuiteResults> suiteResults) { public void setSuiteResults(Collection<SuiteResults> suiteResults) {
this.suiteResults = new ArrayList<SuiteResults>(suiteResults); this.suiteResults = new ArrayList<SuiteResults>(suiteResults);
calculate(); calculate();
} }
public void captureDataListener(OutputDataListener dataListener) { public void captureDataListener(OutputDataListener dataListener) {
this.dataListenerInfo = dataListener.getInfo(); this.dataListenerInfo = dataListener.getInfo();
calculate(); calculate();
} }
public void setIgnoredTestList(IgnoredTests ignoredTestList) { public void setIgnoredTestList(IgnoredTests ignoredTestList) {
this.ignoredTestList = ignoredTestList; this.ignoredTestList = ignoredTestList;
calculate(); calculate();
} }
public void setLogStats(LogStats logStats) { // TODO public void setLogStats(LogStats logStats) { // TODO
this.logStats = logStats; this.logStats = logStats;
calculate(); calculate();
} }
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// Keep the derived data current. // Keep the derived data current.
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
/** /**
* Data in the model has been updated. Refresh all derived data. * Data in the model has been updated. Refresh all derived data.
*/ */
private void calculate() { private void calculate() {
// Clear all derived data. // Clear all derived data.
runStatus = Status.OK; runStatus = Status.OK;
suiteDataMap.clear(); suiteDataMap.clear();
suiteMapByStatus.clear(); suiteMapByStatus.clear();
for (Status s : Status.values()) { for (Status s : Status.values()) {
suiteMapByStatus.put(s, new ArrayList<SuiteData>()); suiteMapByStatus.put(s, new ArrayList<SuiteData>());
} }
allTests.clear(); allTests.clear();
testMapByStatus.clear(); testMapByStatus.clear();
for (Status s : Status.values()) { for (Status s : Status.values()) {
testMapByStatus.put(s, new ArrayList<TestData>()); testMapByStatus.put(s, new ArrayList<TestData>());
} }
/* /*
* Populate the Suite map with all Suites. * Populate the Suite map with all Suites.
*/ */
Map<String, SuiteResults> resultsMap = new HashMap<String, SuiteResults>(); Map<String, SuiteResults> resultsMap = new HashMap<String, SuiteResults>();
for (SuiteResults result : suiteResults) { for (SuiteResults result : suiteResults) {
resultsMap.put(result.getName(), result); resultsMap.put(result.getName(), result);
} }
Map<String, SuiteContents> contentsMap = new HashMap<String, SuiteContents>(); Map<String, SuiteContents> contentsMap = new HashMap<String, SuiteContents>();
for (SuiteContents contents : suiteContents) { for (SuiteContents contents : suiteContents) {
contentsMap.put(contents.getName(), contents); contentsMap.put(contents.getName(), contents);
} }
for (SuiteContents contents : suiteContents) { for (SuiteContents contents : suiteContents) {
String name = contents.getName(); String name = contents.getName();
SuiteResults result = resultsMap.get(name); SuiteResults result = resultsMap.get(name);
boolean ignored = ignoredTestList.isIgnored(name); boolean ignored = ignoredTestList.isIgnored(name);
ProcessOutput failureMessages = dataListenerInfo ProcessOutput failureMessages = dataListenerInfo
.getFailureMessages().get(name); .getFailureMessages().get(name);
suiteDataMap.put(name, new SuiteData(name, ignored, contents, suiteDataMap.put(name, new SuiteData(name, ignored, contents,
result, failureMessages)); result, failureMessages));
} }
/* /*
* Map the Suites by status. * Map the Suites by status.
*/ */
for (SuiteData s : suiteDataMap.values()) { for (SuiteData s : suiteDataMap.values()) {
getSuites(s.getStatus()).add(s); getSuites(s.getStatus()).add(s);
} }
/** /**
* Populate the Test map with all Tests, and map by status. * Populate the Test map with all Tests, and map by status.
*/ */
for (SuiteData s : suiteDataMap.values()) { for (SuiteData s : suiteDataMap.values()) {
for (TestData t : s.getTestMap().values()) { for (TestData t : s.getTestMap().values()) {
allTests.add(t); allTests.add(t);
getTests(t.getStatus()).add(t); getTests(t.getStatus()).add(t);
} }
} }
if (logStats.hasErrors() || !getSuites(Status.ERROR).isEmpty()) { if (logStats.hasErrors() || !getSuites(Status.ERROR).isEmpty()) {
runStatus = Status.ERROR; runStatus = Status.ERROR;
} else if (!getSuites(Status.PENDING).isEmpty()) { } else if (!getSuites(Status.PENDING).isEmpty()) {
runStatus = Status.PENDING; runStatus = Status.PENDING;
} else { } else {
runStatus = Status.OK; runStatus = Status.OK;
} }
} }
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// Access the derived data. // Access the derived data.
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
public Status getRunStatus() { public Status getRunStatus() {
return runStatus; return runStatus;
} }
public long getStartTime() { public long getStartTime() {
return dataListenerInfo.getStartTime(); return dataListenerInfo.getStartTime();
} }
public long getEndTime() { public long getEndTime() {
return dataListenerInfo.getEndTime(); return dataListenerInfo.getEndTime();
} }
public long getElapsedTime() { public long getElapsedTime() {
return dataListenerInfo.getElapsedTime(); return dataListenerInfo.getElapsedTime();
} }
public boolean isAnyPasses() { public boolean isAnyPasses() {
return !getTests(Status.OK).isEmpty(); return !getTests(Status.OK).isEmpty();
} }
public boolean isAnyFailures() { public boolean isAnyFailures() {
return !getTests(Status.ERROR).isEmpty(); return !getTests(Status.ERROR).isEmpty();
} }
public boolean isAnyIgnores() { public boolean isAnyIgnores() {
return !getTests(Status.IGNORED).isEmpty(); return !getTests(Status.IGNORED).isEmpty();
} }
public boolean isAnyPending() { public boolean isAnyPending() {
return !getTests(Status.PENDING).isEmpty(); return !getTests(Status.PENDING).isEmpty();
} }
public int getTotalSuiteCount() { public int getTotalSuiteCount() {
return suiteDataMap.size(); return suiteDataMap.size();
} }
public int getPassingSuiteCount() { public int getPassingSuiteCount() {
return getSuites(Status.OK).size(); return getSuites(Status.OK).size();
} }
public int getFailingSuiteCount() { public int getFailingSuiteCount() {
return getSuites(Status.ERROR).size(); return getSuites(Status.ERROR).size();
} }
public int getIgnoredSuiteCount() { public int getIgnoredSuiteCount() {
return getSuites(Status.IGNORED).size(); return getSuites(Status.IGNORED).size();
} }
public int getPendingSuiteCount() { public int getPendingSuiteCount() {
return getSuites(Status.PENDING).size(); return getSuites(Status.PENDING).size();
} }
public Collection<SuiteData> getAllSuites() { public Collection<SuiteData> getAllSuites() {
return suiteDataMap.values(); return suiteDataMap.values();
} }
public Map<String, SuiteData> getSuitesWithFailureMessages() { public Map<String, SuiteData> getSuitesWithFailureMessages() {
Map<String, SuiteData> map = new TreeMap<String, SuiteData>(); Map<String, SuiteData> map = new TreeMap<String, SuiteData>();
for (SuiteData s : suiteDataMap.values()) { for (SuiteData s : suiteDataMap.values()) {
if (s.getFailureMessages() != null) { if (s.getFailureMessages() != null) {
map.put(s.getName(), s); map.put(s.getName(), s);
} }
} }
return map; return map;
} }
public int getTotalTestCount() { public int getTotalTestCount() {
return allTests.size(); return allTests.size();
} }
public int getPassingTestCount() { public int getPassingTestCount() {
return getTests(Status.OK).size(); return getTests(Status.OK).size();
} }
public int getFailingTestCount() { public int getFailingTestCount() {
return getTests(Status.ERROR).size(); return getTests(Status.ERROR).size();
} }
public int getIgnoredTestCount() { public int getIgnoredTestCount() {
return getTests(Status.IGNORED).size(); return getTests(Status.IGNORED).size();
} }
public int getPendingTestCount() { public int getPendingTestCount() {
return getTests(Status.PENDING).size(); return getTests(Status.PENDING).size();
} }
public Collection<TestData> getAllTests() { public Collection<TestData> getAllTests() {
return Collections.unmodifiableCollection(allTests); return Collections.unmodifiableCollection(allTests);
} }
public Collection<TestData> getFailingTests() { public Collection<TestData> getFailingTests() {
return Collections.unmodifiableCollection(getTests(Status.ERROR)); return Collections.unmodifiableCollection(getTests(Status.ERROR));
} }
public Collection<TestData> getIgnoredTests() { public Collection<TestData> getIgnoredTests() {
return Collections.unmodifiableCollection(getTests(Status.IGNORED)); return Collections.unmodifiableCollection(getTests(Status.IGNORED));
} }
public Collection<IgnoredTestInfo> getIgnoredTestInfo() { public Collection<IgnoredTestInfo> getIgnoredTestInfo() {
return ignoredTestList.getList(); return ignoredTestList.getList();
} }
public String getReasonForIgnoring(String suiteName, String testName) { public String getReasonForIgnoring(String suiteName, String testName) {
return ignoredTestList.getReasonForIgnoring(suiteName, testName); return ignoredTestList.getReasonForIgnoring(suiteName, testName);
} }
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// Helper methods // Helper methods
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
/** /**
* Get the list of suites that have this status. * Get the list of suites that have this status.
*/ */
private List<SuiteData> getSuites(Status st) { private List<SuiteData> getSuites(Status st) {
return suiteMapByStatus.get(st); return suiteMapByStatus.get(st);
} }
/** /**
* Get the list of tests that have this status. * Get the list of tests that have this status.
*/ */
private List<TestData> getTests(Status st) { private List<TestData> getTests(Status st) {
return testMapByStatus.get(st); return testMapByStatus.get(st);
} }
} }

View file

@ -1,375 +1,375 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */ /* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.utilities.testrunner.output; package edu.cornell.mannlib.vitro.utilities.testrunner.output;
import java.io.File; import java.io.File;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.Reader; import java.io.Reader;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Collection; import java.util.Collection;
import java.util.Date; import java.util.Date;
import java.util.Map; import java.util.Map;
import edu.cornell.mannlib.vitro.utilities.testrunner.FileHelper; import edu.cornell.mannlib.vitro.utilities.testrunner.FileHelper;
import edu.cornell.mannlib.vitro.utilities.testrunner.IgnoredTests.IgnoredTestInfo; import edu.cornell.mannlib.vitro.utilities.testrunner.IgnoredTests.IgnoredTestInfo;
import edu.cornell.mannlib.vitro.utilities.testrunner.LogStats; import edu.cornell.mannlib.vitro.utilities.testrunner.LogStats;
import edu.cornell.mannlib.vitro.utilities.testrunner.SeleniumRunnerParameters; import edu.cornell.mannlib.vitro.utilities.testrunner.SeleniumRunnerParameters;
import edu.cornell.mannlib.vitro.utilities.testrunner.Status; import edu.cornell.mannlib.vitro.utilities.testrunner.Status;
import edu.cornell.mannlib.vitro.utilities.testrunner.datamodel.DataModel; import edu.cornell.mannlib.vitro.utilities.testrunner.datamodel.DataModel;
import edu.cornell.mannlib.vitro.utilities.testrunner.datamodel.SuiteData; import edu.cornell.mannlib.vitro.utilities.testrunner.datamodel.SuiteData;
import edu.cornell.mannlib.vitro.utilities.testrunner.datamodel.SuiteData.TestData; import edu.cornell.mannlib.vitro.utilities.testrunner.datamodel.SuiteData.TestData;
import edu.cornell.mannlib.vitro.utilities.testrunner.output.OutputDataListener.ProcessOutput; import edu.cornell.mannlib.vitro.utilities.testrunner.output.OutputDataListener.ProcessOutput;
/** /**
* Creates the summary HTML file. * Creates the summary HTML file.
*/ */
public class OutputSummaryFormatter { public class OutputSummaryFormatter {
public static final String SUMMARY_HTML_FILENAME = "summary.html"; public static final String SUMMARY_HTML_FILENAME = "summary.html";
public static final String SUMMARY_CSS_FILENAME = "summary.css"; public static final String SUMMARY_CSS_FILENAME = "summary.css";
private final SimpleDateFormat dateFormat = new SimpleDateFormat( private final SimpleDateFormat dateFormat = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss"); "yyyy-MM-dd HH:mm:ss");
private final SeleniumRunnerParameters parms; private final SeleniumRunnerParameters parms;
private LogStats logStats; private LogStats logStats;
private DataModel dataModel; private DataModel dataModel;
public OutputSummaryFormatter(SeleniumRunnerParameters parms) { public OutputSummaryFormatter(SeleniumRunnerParameters parms) {
this.parms = parms; this.parms = parms;
} }
/** /**
* Create a summary HTML file from the info contained in this log file and * Create a summary HTML file from the info contained in this log file and
* these suite outputs. * these suite outputs.
*/ */
public void format(LogStats logStats, DataModel dataModel) { public void format(LogStats logStats, DataModel dataModel) {
this.logStats = logStats; this.logStats = logStats;
this.dataModel = dataModel; this.dataModel = dataModel;
PrintWriter writer = null; PrintWriter writer = null;
try { try {
copyCssFile(); copyCssFile();
File outputFile = new File(parms.getOutputDirectory(), File outputFile = new File(parms.getOutputDirectory(),
SUMMARY_HTML_FILENAME); SUMMARY_HTML_FILENAME);
writer = new PrintWriter(outputFile); writer = new PrintWriter(outputFile);
writeHeader(writer); writeHeader(writer);
writeStatsSection(writer); writeStatsSection(writer);
writeErrorMessagesSection(writer); writeErrorMessagesSection(writer);
writeCondensedTable(writer); writeCondensedTable(writer);
writeIgnoreSection(writer); writeIgnoreSection(writer);
writeSuiteErrorMessagesSection(writer); writeSuiteErrorMessagesSection(writer);
writeFooter(writer); writeFooter(writer);
} catch (IOException e) { } catch (IOException e) {
// There is no appeal for any problems here. Just report them. // There is no appeal for any problems here. Just report them.
e.printStackTrace(); e.printStackTrace();
} finally { } finally {
if (writer != null) { if (writer != null) {
writer.close(); writer.close();
} }
} }
} }
/** /**
* Copy the CSS file into the output directory. * Copy the CSS file into the output directory.
*/ */
private void copyCssFile() { private void copyCssFile() {
InputStream cssStream = this.getClass().getResourceAsStream( InputStream cssStream = this.getClass().getResourceAsStream(
SUMMARY_CSS_FILENAME); SUMMARY_CSS_FILENAME);
if (cssStream == null) { if (cssStream == null) {
System.out.println("Couldn't find the CSS file: '" System.out.println("Couldn't find the CSS file: '"
+ SUMMARY_CSS_FILENAME + "'"); + SUMMARY_CSS_FILENAME + "'");
} else { } else {
File cssTarget = new File(parms.getOutputDirectory(), File cssTarget = new File(parms.getOutputDirectory(),
SUMMARY_CSS_FILENAME); SUMMARY_CSS_FILENAME);
try { try {
FileHelper.copy(cssStream, cssTarget); FileHelper.copy(cssStream, cssTarget);
cssStream.close(); cssStream.close();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
} }
private void writeHeader(PrintWriter w) { private void writeHeader(PrintWriter w) {
Status runStatus = dataModel.getRunStatus(); Status runStatus = dataModel.getRunStatus();
String statusString = (runStatus == Status.PENDING) ? "IN PROGRESS" String statusString = (runStatus == Status.PENDING) ? "IN PROGRESS"
: runStatus.toString(); : runStatus.toString();
String startString = formatDateTime(dataModel.getStartTime()); String startString = formatDateTime(dataModel.getStartTime());
w.println("<html>"); w.println("<html>");
w.println("<head>"); w.println("<head>");
w.println(" <title>Summary of Acceptance Tests " + startString w.println(" <title>Summary of Acceptance Tests " + startString
+ "</title>"); + "</title>");
w.println(" <link rel=\"stylesheet\" type=\"text/css\" " w.println(" <link rel=\"stylesheet\" type=\"text/css\" "
+ "href=\"summary.css\">"); + "href=\"summary.css\">");
w.println("</head>"); w.println("</head>");
w.println("<body>"); w.println("<body>");
w.println(); w.println();
w.println(" <div class=\"heading\">"); w.println(" <div class=\"heading\">");
w.println(" Acceptance test results: " + startString); w.println(" Acceptance test results: " + startString);
w.println(" <div class=\"" + runStatus.getHtmlClass() w.println(" <div class=\"" + runStatus.getHtmlClass()
+ " one-word\">" + statusString + "</div>"); + " one-word\">" + statusString + "</div>");
w.println(" </div>"); w.println(" </div>");
} }
private void writeStatsSection(PrintWriter w) { private void writeStatsSection(PrintWriter w) {
String passClass = dataModel.isAnyPasses() ? Status.OK.getHtmlClass() String passClass = dataModel.isAnyPasses() ? Status.OK.getHtmlClass()
: ""; : "";
String failClass = dataModel.isAnyFailures() ? Status.ERROR String failClass = dataModel.isAnyFailures() ? Status.ERROR
.getHtmlClass() : ""; .getHtmlClass() : "";
String ignoreClass = dataModel.isAnyIgnores() ? Status.IGNORED String ignoreClass = dataModel.isAnyIgnores() ? Status.IGNORED
.getHtmlClass() : ""; .getHtmlClass() : "";
String start = formatDateTime(dataModel.getStartTime()); String start = formatDateTime(dataModel.getStartTime());
String end = formatDateTime(dataModel.getEndTime()); String end = formatDateTime(dataModel.getEndTime());
String elapsed = formatElapsedTime(dataModel.getElapsedTime()); String elapsed = formatElapsedTime(dataModel.getElapsedTime());
w.println(" <div class=\"section\">Summary</div>"); w.println(" <div class=\"section\">Summary</div>");
w.println(); w.println();
w.println(" <table class=\"summary\" cellspacing=\"0\">"); w.println(" <table class=\"summary\" cellspacing=\"0\">");
w.println(" <tr>"); w.println(" <tr>");
w.println(" <td>"); w.println(" <td>");
w.println(" <table cellspacing=\"0\">"); w.println(" <table cellspacing=\"0\">");
w.println(" <tr><td>Start time:</td><td>" + start w.println(" <tr><td>Start time:</td><td>" + start
+ "</td></tr>"); + "</td></tr>");
w.println(" <tr><td>End time:</td><td>" + end + "</td></tr>"); w.println(" <tr><td>End time:</td><td>" + end + "</td></tr>");
w.println(" <tr><td>Elapsed time</td><td>" + elapsed w.println(" <tr><td>Elapsed time</td><td>" + elapsed
+ "</td></tr>"); + "</td></tr>");
w.println(" </table>"); w.println(" </table>");
w.println(" </td>"); w.println(" </td>");
w.println(" <td>"); w.println(" <td>");
w.println(" <table class=\"tallys\" cellspacing=\"0\">"); w.println(" <table class=\"tallys\" cellspacing=\"0\">");
w.println(" <tr><th>&nbsp;</th><th>Suites</th><th>Tests</th>"); w.println(" <tr><th>&nbsp;</th><th>Suites</th><th>Tests</th>");
w.println(" <tr class=\"" + passClass w.println(" <tr class=\"" + passClass
+ "\"><td>Passed</td><td>" + dataModel.getPassingSuiteCount() + "\"><td>Passed</td><td>" + dataModel.getPassingSuiteCount()
+ "</td><td>" + dataModel.getPassingTestCount() + "</td>"); + "</td><td>" + dataModel.getPassingTestCount() + "</td>");
w.println(" <tr class=\"" + failClass w.println(" <tr class=\"" + failClass
+ "\"><td>Failed</td><td>" + dataModel.getFailingSuiteCount() + "\"><td>Failed</td><td>" + dataModel.getFailingSuiteCount()
+ "</td><td>" + dataModel.getFailingTestCount() + "</td>"); + "</td><td>" + dataModel.getFailingTestCount() + "</td>");
w.println(" <tr class=\"" + ignoreClass w.println(" <tr class=\"" + ignoreClass
+ "\"><td>Ignored</td><td>" + dataModel.getIgnoredSuiteCount() + "\"><td>Ignored</td><td>" + dataModel.getIgnoredSuiteCount()
+ "</td><td>" + dataModel.getIgnoredTestCount() + "</td>"); + "</td><td>" + dataModel.getIgnoredTestCount() + "</td>");
if (dataModel.isAnyPending()) { if (dataModel.isAnyPending()) {
w.println(" <tr class=\"" + Status.PENDING.getHtmlClass() w.println(" <tr class=\"" + Status.PENDING.getHtmlClass()
+ "\"><td>Pending</td><td>" + "\"><td>Pending</td><td>"
+ dataModel.getPendingSuiteCount() + "</td><td>" + dataModel.getPendingSuiteCount() + "</td><td>"
+ dataModel.getPendingTestCount() + "</td>"); + dataModel.getPendingTestCount() + "</td>");
} }
w.println(" <tr><td class=\"total\">Total</td><td>" w.println(" <tr><td class=\"total\">Total</td><td>"
+ dataModel.getTotalSuiteCount() + "</td><td>" + dataModel.getTotalSuiteCount() + "</td><td>"
+ dataModel.getTotalTestCount() + "</td>"); + dataModel.getTotalTestCount() + "</td>");
w.println(" </table>"); w.println(" </table>");
w.println(" </td>"); w.println(" </td>");
w.println(" </tr>"); w.println(" </tr>");
w.println(" </table>"); w.println(" </table>");
w.println(); w.println();
} }
private void writeErrorMessagesSection(PrintWriter w) { private void writeErrorMessagesSection(PrintWriter w) {
String errorClass = Status.ERROR.getHtmlClass(); String errorClass = Status.ERROR.getHtmlClass();
w.println(" <div class=section>Errors and warnings</div>"); w.println(" <div class=section>Errors and warnings</div>");
w.println(); w.println();
w.println(" <table cellspacing=\"0\">"); w.println(" <table cellspacing=\"0\">");
if ((!logStats.hasErrors()) && (!logStats.hasWarnings())) { if ((!logStats.hasErrors()) && (!logStats.hasWarnings())) {
w.println(" <tr><td colspan=\"2\">No errors or warnings</td></tr>"); w.println(" <tr><td colspan=\"2\">No errors or warnings</td></tr>");
} else { } else {
for (String e : logStats.getErrors()) { for (String e : logStats.getErrors()) {
w.println(" <tr class=\"" + errorClass w.println(" <tr class=\"" + errorClass
+ "\"><td>ERROR</td><td>" + e + "</td></tr>"); + "\"><td>ERROR</td><td>" + e + "</td></tr>");
} }
} }
w.println(" </table>"); w.println(" </table>");
w.println(); w.println();
} }
private void writeCondensedTable(PrintWriter w) { private void writeCondensedTable(PrintWriter w) {
w.println(" <div class=section>Condensed List</div>"); w.println(" <div class=section>Condensed List</div>");
w.println(); w.println();
w.println(" <table class=\"condensed\" cellspacing=\"0\">"); w.println(" <table class=\"condensed\" cellspacing=\"0\">");
for (SuiteData s : dataModel.getAllSuites()) { for (SuiteData s : dataModel.getAllSuites()) {
String sReason = ""; String sReason = "";
if (s.getStatus() == Status.IGNORED) { if (s.getStatus() == Status.IGNORED) {
sReason = dataModel.getReasonForIgnoring(s.getName(), "*"); sReason = dataModel.getReasonForIgnoring(s.getName(), "*");
} else if (s.getFailureMessages() != null) { } else if (s.getFailureMessages() != null) {
sReason = s.getFailureMessages().getErrout(); sReason = s.getFailureMessages().getErrout();
} else if (s.getStatus() == Status.PENDING) { } else if (s.getStatus() == Status.PENDING) {
sReason = Status.PENDING.toString(); sReason = Status.PENDING.toString();
} }
w.println(" <tr>"); w.println(" <tr>");
w.println(" <td class=\"" + s.getStatus().getHtmlClass() w.println(" <td class=\"" + s.getStatus().getHtmlClass()
+ "\">"); + "\">");
w.println(" <div class=\"suite\">" + outputLink(s) w.println(" <div class=\"suite\">" + outputLink(s)
+ "</div>"); + "</div>");
if (!sReason.isEmpty()) { if (!sReason.isEmpty()) {
// The entire class is either failed or pending or ignored. // The entire class is either failed or pending or ignored.
w.println(" <div class=\"reason\">" + sReason + "</div>"); w.println(" <div class=\"reason\">" + sReason + "</div>");
} else { } else {
// Show the individual tests. // Show the individual tests.
for (TestData t : s.getTestMap().values()) { for (TestData t : s.getTestMap().values()) {
String tClass = t.getStatus().getHtmlClass(); String tClass = t.getStatus().getHtmlClass();
String tReason = dataModel.getReasonForIgnoring( String tReason = dataModel.getReasonForIgnoring(
s.getName(), t.getTestName()); s.getName(), t.getTestName());
w.println(" <div class=\"test " + tClass + "\">"); w.println(" <div class=\"test " + tClass + "\">");
w.println(" " + outputLink(t)); w.println(" " + outputLink(t));
if (!tReason.isEmpty()) { if (!tReason.isEmpty()) {
w.println(" <div class=\"tReason\">" + tReason w.println(" <div class=\"tReason\">" + tReason
+ "</div>"); + "</div>");
} }
w.println(" </div>"); w.println(" </div>");
} }
} }
w.println(" </td>"); w.println(" </td>");
w.println(" </tr>"); w.println(" </tr>");
} }
w.println(" </table>"); w.println(" </table>");
w.println(); w.println();
} }
private void writeSuiteErrorMessagesSection(PrintWriter w) { private void writeSuiteErrorMessagesSection(PrintWriter w) {
Map<String, SuiteData> failedSuiteMap = dataModel Map<String, SuiteData> failedSuiteMap = dataModel
.getSuitesWithFailureMessages(); .getSuitesWithFailureMessages();
if (failedSuiteMap.isEmpty()) { if (failedSuiteMap.isEmpty()) {
return; return;
} }
w.println(" <div class=section>All tests</div>"); w.println(" <div class=section>All tests</div>");
w.println(); w.println();
for (SuiteData s : failedSuiteMap.values()) { for (SuiteData s : failedSuiteMap.values()) {
ProcessOutput output = s.getFailureMessages(); ProcessOutput output = s.getFailureMessages();
w.println(" <a name=\"" + SuiteData.failureMessageAnchor(s) w.println(" <a name=\"" + SuiteData.failureMessageAnchor(s)
+ "\">"); + "\">");
w.println(" <table cellspacing=\"0\">"); w.println(" <table cellspacing=\"0\">");
w.println(" <tr><th>Standard Output</th></tr>\n"); w.println(" <tr><th>Standard Output</th></tr>\n");
w.println(" <tr><td><pre>" + output.getStdout() w.println(" <tr><td><pre>" + output.getStdout()
+ "</pre></td></tr>\n"); + "</pre></td></tr>\n");
w.println(" </table>"); w.println(" </table>");
w.println("<br/>&nbsp;<br/>"); w.println("<br/>&nbsp;<br/>");
w.println(" <table cellspacing=\"0\">"); w.println(" <table cellspacing=\"0\">");
w.println(" <tr><th>Error Output</th></tr>\n"); w.println(" <tr><th>Error Output</th></tr>\n");
w.println(" <tr><td><pre>" + output.getErrout() w.println(" <tr><td><pre>" + output.getErrout()
+ "</pre></td></tr>\n"); + "</pre></td></tr>\n");
w.println(" </table>"); w.println(" </table>");
w.println("<br/>&nbsp;<br/>"); w.println("<br/>&nbsp;<br/>");
w.println(); w.println();
} }
} }
private void writeIgnoreSection(PrintWriter w) { private void writeIgnoreSection(PrintWriter w) {
String warnClass = Status.IGNORED.getHtmlClass(); String warnClass = Status.IGNORED.getHtmlClass();
Collection<IgnoredTestInfo> ignoredTests = dataModel Collection<IgnoredTestInfo> ignoredTests = dataModel
.getIgnoredTestInfo(); .getIgnoredTestInfo();
w.println(" <div class=section>Ignored</div>"); w.println(" <div class=section>Ignored</div>");
w.println(); w.println();
w.println(" <table class=\"ignored\" cellspacing=\"0\">"); w.println(" <table class=\"ignored\" cellspacing=\"0\">");
w.println(" <tr><th>Suite name</th><th>Test name</th>" w.println(" <tr><th>Suite name</th><th>Test name</th>"
+ "<th>Reason for ignoring</th></tr>\n"); + "<th>Reason for ignoring</th></tr>\n");
if (ignoredTests.isEmpty()) { if (ignoredTests.isEmpty()) {
w.println(" <tr><td colspan=\"3\">No tests ignored.</td>" w.println(" <tr><td colspan=\"3\">No tests ignored.</td>"
+ "</tr>"); + "</tr>");
} else { } else {
for (IgnoredTestInfo info : ignoredTests) { for (IgnoredTestInfo info : ignoredTests) {
String suiteName = info.suiteName; String suiteName = info.suiteName;
String testName = info.testName; String testName = info.testName;
String reason = dataModel.getReasonForIgnoring(suiteName, String reason = dataModel.getReasonForIgnoring(suiteName,
testName); testName);
w.println(" <tr class=\"" + warnClass + "\">"); w.println(" <tr class=\"" + warnClass + "\">");
w.println(" <td>" + suiteName + "</td>"); w.println(" <td>" + suiteName + "</td>");
w.println(" <td>" + testName + "</td>"); w.println(" <td>" + testName + "</td>");
w.println(" <td>" + reason + "</td>"); w.println(" <td>" + reason + "</td>");
w.println(" </tr>"); w.println(" </tr>");
} }
} }
w.println(" </table>"); w.println(" </table>");
w.println(); w.println();
} }
private void writeFooter(PrintWriter w) { private void writeFooter(PrintWriter w) {
w.println(" <div class=section>Log</div>"); w.println(" <div class=section>Log</div>");
w.println(" <pre class=\"log\">"); w.println(" <pre class=\"log\">");
Reader reader = null; Reader reader = null;
try { try {
reader = new FileReader(parms.getLogFile()); reader = new FileReader(parms.getLogFile());
char[] buffer = new char[4096]; char[] buffer = new char[4096];
int howMany; int howMany;
while (-1 != (howMany = reader.read(buffer))) { while (-1 != (howMany = reader.read(buffer))) {
w.write(buffer, 0, howMany); w.write(buffer, 0, howMany);
} }
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} finally { } finally {
if (reader != null) { if (reader != null) {
try { try {
reader.close(); reader.close();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
} }
w.println(" </pre>"); w.println(" </pre>");
w.println("</body>"); w.println("</body>");
w.println("</html>"); w.println("</html>");
} }
private String formatElapsedTime(long elapsed) { private String formatElapsedTime(long elapsed) {
if (elapsed == 0) { if (elapsed == 0) {
return "---"; return "---";
} }
long elapsedSeconds = elapsed / 1000L; long elapsedSeconds = elapsed / 1000L;
long seconds = elapsedSeconds % 60L; long seconds = elapsedSeconds % 60L;
long elapsedMinutes = elapsedSeconds / 60L; long elapsedMinutes = elapsedSeconds / 60L;
long minutes = elapsedMinutes % 60L; long minutes = elapsedMinutes % 60L;
long hours = elapsedMinutes / 60L; long hours = elapsedMinutes / 60L;
String elapsedTime = ""; String elapsedTime = "";
if (hours > 0) { if (hours > 0) {
elapsedTime += hours + "h "; elapsedTime += hours + "h ";
} }
if (minutes > 0 || hours > 0) { if (minutes > 0 || hours > 0) {
elapsedTime += minutes + "m "; elapsedTime += minutes + "m ";
} }
elapsedTime += seconds + "s"; elapsedTime += seconds + "s";
return elapsedTime; return elapsedTime;
} }
private String formatDateTime(long dateTime) { private String formatDateTime(long dateTime) {
if (dateTime == 0) { if (dateTime == 0) {
return "---"; return "---";
} }
return dateFormat.format(new Date(dateTime)); return dateFormat.format(new Date(dateTime));
} }
private String outputLink(SuiteData s) { private String outputLink(SuiteData s) {
if (s.getOutputLink() == null) { if (s.getOutputLink() == null) {
return s.getName(); return s.getName();
} else { } else {
return "<a href=\"" + s.getOutputLink() + "\">" + s.getName() return "<a href=\"" + s.getOutputLink() + "\">" + s.getName()
+ "</a>"; + "</a>";
} }
} }
private String outputLink(TestData t) { private String outputLink(TestData t) {
if (t.getOutputLink() == null) { if (t.getOutputLink() == null) {
return t.getTestName(); return t.getTestName();
} else { } else {
return "<a href=\"" + t.getOutputLink() + "\">" + t.getTestName() return "<a href=\"" + t.getOutputLink() + "\">" + t.getTestName()
+ "</a>"; + "</a>";
} }
} }
} }