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

View file

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

View file

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

View file

@ -1,294 +1,294 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.utilities.testrunner.datamodel;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import edu.cornell.mannlib.vitro.utilities.testrunner.IgnoredTests;
import edu.cornell.mannlib.vitro.utilities.testrunner.IgnoredTests.IgnoredTestInfo;
import edu.cornell.mannlib.vitro.utilities.testrunner.LogStats;
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.output.OutputDataListener;
import edu.cornell.mannlib.vitro.utilities.testrunner.output.OutputDataListener.ProcessOutput;
import edu.cornell.mannlib.vitro.utilities.testrunner.output.SuiteResults;
/**
* Collect all that we know about suites, tests, and their current status.
*/
public class DataModel {
/* base data */
private Collection<SuiteContents> suiteContents = Collections.emptyList();
private Collection<File> selectedSuites = Collections.emptyList();
private Collection<SuiteResults> suiteResults = Collections.emptyList();
private OutputDataListener.Info dataListenerInfo = OutputDataListener.Info.EMPTY_INFO;
private IgnoredTests ignoredTestList = IgnoredTests.EMPTY_LIST;
private LogStats logStats = LogStats.EMPTY_LOG_STATS; // TODO
/* derived data */
private Status runStatus = Status.PENDING;
private final SortedMap<String, SuiteData> suiteDataMap = new TreeMap<String, SuiteData>();
private final EnumMap<Status, List<SuiteData>> suiteMapByStatus = new EnumMap<Status, List<SuiteData>>(
Status.class);
private final List<TestData> allTests = new ArrayList<TestData>();
private final EnumMap<Status, List<TestData>> testMapByStatus = new EnumMap<Status, List<TestData>>(
Status.class);
// ----------------------------------------------------------------------
// Constructor
// ----------------------------------------------------------------------
public DataModel() {
calculate();
}
// ----------------------------------------------------------------------
// Update the base data.
// ----------------------------------------------------------------------
public void setSuiteContents(Collection<SuiteContents> suiteContents) {
this.suiteContents = new ArrayList<SuiteContents>(suiteContents);
calculate();
}
public void setSelectedSuites(Collection<File> selectedSuites) {
this.selectedSuites = new ArrayList<File>(selectedSuites);
calculate();
}
public Collection<File> getSelectedSuites() {
return new ArrayList<File>(selectedSuites);
}
public void setSuiteResults(Collection<SuiteResults> suiteResults) {
this.suiteResults = new ArrayList<SuiteResults>(suiteResults);
calculate();
}
public void captureDataListener(OutputDataListener dataListener) {
this.dataListenerInfo = dataListener.getInfo();
calculate();
}
public void setIgnoredTestList(IgnoredTests ignoredTestList) {
this.ignoredTestList = ignoredTestList;
calculate();
}
public void setLogStats(LogStats logStats) { // TODO
this.logStats = logStats;
calculate();
}
// ----------------------------------------------------------------------
// Keep the derived data current.
// ----------------------------------------------------------------------
/**
* Data in the model has been updated. Refresh all derived data.
*/
private void calculate() {
// Clear all derived data.
runStatus = Status.OK;
suiteDataMap.clear();
suiteMapByStatus.clear();
for (Status s : Status.values()) {
suiteMapByStatus.put(s, new ArrayList<SuiteData>());
}
allTests.clear();
testMapByStatus.clear();
for (Status s : Status.values()) {
testMapByStatus.put(s, new ArrayList<TestData>());
}
/*
* Populate the Suite map with all Suites.
*/
Map<String, SuiteResults> resultsMap = new HashMap<String, SuiteResults>();
for (SuiteResults result : suiteResults) {
resultsMap.put(result.getName(), result);
}
Map<String, SuiteContents> contentsMap = new HashMap<String, SuiteContents>();
for (SuiteContents contents : suiteContents) {
contentsMap.put(contents.getName(), contents);
}
for (SuiteContents contents : suiteContents) {
String name = contents.getName();
SuiteResults result = resultsMap.get(name);
boolean ignored = ignoredTestList.isIgnored(name);
ProcessOutput failureMessages = dataListenerInfo
.getFailureMessages().get(name);
suiteDataMap.put(name, new SuiteData(name, ignored, contents,
result, failureMessages));
}
/*
* Map the Suites by status.
*/
for (SuiteData s : suiteDataMap.values()) {
getSuites(s.getStatus()).add(s);
}
/**
* Populate the Test map with all Tests, and map by status.
*/
for (SuiteData s : suiteDataMap.values()) {
for (TestData t : s.getTestMap().values()) {
allTests.add(t);
getTests(t.getStatus()).add(t);
}
}
if (logStats.hasErrors() || !getSuites(Status.ERROR).isEmpty()) {
runStatus = Status.ERROR;
} else if (!getSuites(Status.PENDING).isEmpty()) {
runStatus = Status.PENDING;
} else {
runStatus = Status.OK;
}
}
// ----------------------------------------------------------------------
// Access the derived data.
// ----------------------------------------------------------------------
public Status getRunStatus() {
return runStatus;
}
public long getStartTime() {
return dataListenerInfo.getStartTime();
}
public long getEndTime() {
return dataListenerInfo.getEndTime();
}
public long getElapsedTime() {
return dataListenerInfo.getElapsedTime();
}
public boolean isAnyPasses() {
return !getTests(Status.OK).isEmpty();
}
public boolean isAnyFailures() {
return !getTests(Status.ERROR).isEmpty();
}
public boolean isAnyIgnores() {
return !getTests(Status.IGNORED).isEmpty();
}
public boolean isAnyPending() {
return !getTests(Status.PENDING).isEmpty();
}
public int getTotalSuiteCount() {
return suiteDataMap.size();
}
public int getPassingSuiteCount() {
return getSuites(Status.OK).size();
}
public int getFailingSuiteCount() {
return getSuites(Status.ERROR).size();
}
public int getIgnoredSuiteCount() {
return getSuites(Status.IGNORED).size();
}
public int getPendingSuiteCount() {
return getSuites(Status.PENDING).size();
}
public Collection<SuiteData> getAllSuites() {
return suiteDataMap.values();
}
public Map<String, SuiteData> getSuitesWithFailureMessages() {
Map<String, SuiteData> map = new TreeMap<String, SuiteData>();
for (SuiteData s : suiteDataMap.values()) {
if (s.getFailureMessages() != null) {
map.put(s.getName(), s);
}
}
return map;
}
public int getTotalTestCount() {
return allTests.size();
}
public int getPassingTestCount() {
return getTests(Status.OK).size();
}
public int getFailingTestCount() {
return getTests(Status.ERROR).size();
}
public int getIgnoredTestCount() {
return getTests(Status.IGNORED).size();
}
public int getPendingTestCount() {
return getTests(Status.PENDING).size();
}
public Collection<TestData> getAllTests() {
return Collections.unmodifiableCollection(allTests);
}
public Collection<TestData> getFailingTests() {
return Collections.unmodifiableCollection(getTests(Status.ERROR));
}
public Collection<TestData> getIgnoredTests() {
return Collections.unmodifiableCollection(getTests(Status.IGNORED));
}
public Collection<IgnoredTestInfo> getIgnoredTestInfo() {
return ignoredTestList.getList();
}
public String getReasonForIgnoring(String suiteName, String testName) {
return ignoredTestList.getReasonForIgnoring(suiteName, testName);
}
// ----------------------------------------------------------------------
// Helper methods
// ----------------------------------------------------------------------
/**
* Get the list of suites that have this status.
*/
private List<SuiteData> getSuites(Status st) {
return suiteMapByStatus.get(st);
}
/**
* Get the list of tests that have this status.
*/
private List<TestData> getTests(Status st) {
return testMapByStatus.get(st);
}
}
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.utilities.testrunner.datamodel;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import edu.cornell.mannlib.vitro.utilities.testrunner.IgnoredTests;
import edu.cornell.mannlib.vitro.utilities.testrunner.IgnoredTests.IgnoredTestInfo;
import edu.cornell.mannlib.vitro.utilities.testrunner.LogStats;
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.output.OutputDataListener;
import edu.cornell.mannlib.vitro.utilities.testrunner.output.OutputDataListener.ProcessOutput;
import edu.cornell.mannlib.vitro.utilities.testrunner.output.SuiteResults;
/**
* Collect all that we know about suites, tests, and their current status.
*/
public class DataModel {
/* base data */
private Collection<SuiteContents> suiteContents = Collections.emptyList();
private Collection<File> selectedSuites = Collections.emptyList();
private Collection<SuiteResults> suiteResults = Collections.emptyList();
private OutputDataListener.Info dataListenerInfo = OutputDataListener.Info.EMPTY_INFO;
private IgnoredTests ignoredTestList = IgnoredTests.EMPTY_LIST;
private LogStats logStats = LogStats.EMPTY_LOG_STATS; // TODO
/* derived data */
private Status runStatus = Status.PENDING;
private final SortedMap<String, SuiteData> suiteDataMap = new TreeMap<String, SuiteData>();
private final EnumMap<Status, List<SuiteData>> suiteMapByStatus = new EnumMap<Status, List<SuiteData>>(
Status.class);
private final List<TestData> allTests = new ArrayList<TestData>();
private final EnumMap<Status, List<TestData>> testMapByStatus = new EnumMap<Status, List<TestData>>(
Status.class);
// ----------------------------------------------------------------------
// Constructor
// ----------------------------------------------------------------------
public DataModel() {
calculate();
}
// ----------------------------------------------------------------------
// Update the base data.
// ----------------------------------------------------------------------
public void setSuiteContents(Collection<SuiteContents> suiteContents) {
this.suiteContents = new ArrayList<SuiteContents>(suiteContents);
calculate();
}
public void setSelectedSuites(Collection<File> selectedSuites) {
this.selectedSuites = new ArrayList<File>(selectedSuites);
calculate();
}
public Collection<File> getSelectedSuites() {
return new ArrayList<File>(selectedSuites);
}
public void setSuiteResults(Collection<SuiteResults> suiteResults) {
this.suiteResults = new ArrayList<SuiteResults>(suiteResults);
calculate();
}
public void captureDataListener(OutputDataListener dataListener) {
this.dataListenerInfo = dataListener.getInfo();
calculate();
}
public void setIgnoredTestList(IgnoredTests ignoredTestList) {
this.ignoredTestList = ignoredTestList;
calculate();
}
public void setLogStats(LogStats logStats) { // TODO
this.logStats = logStats;
calculate();
}
// ----------------------------------------------------------------------
// Keep the derived data current.
// ----------------------------------------------------------------------
/**
* Data in the model has been updated. Refresh all derived data.
*/
private void calculate() {
// Clear all derived data.
runStatus = Status.OK;
suiteDataMap.clear();
suiteMapByStatus.clear();
for (Status s : Status.values()) {
suiteMapByStatus.put(s, new ArrayList<SuiteData>());
}
allTests.clear();
testMapByStatus.clear();
for (Status s : Status.values()) {
testMapByStatus.put(s, new ArrayList<TestData>());
}
/*
* Populate the Suite map with all Suites.
*/
Map<String, SuiteResults> resultsMap = new HashMap<String, SuiteResults>();
for (SuiteResults result : suiteResults) {
resultsMap.put(result.getName(), result);
}
Map<String, SuiteContents> contentsMap = new HashMap<String, SuiteContents>();
for (SuiteContents contents : suiteContents) {
contentsMap.put(contents.getName(), contents);
}
for (SuiteContents contents : suiteContents) {
String name = contents.getName();
SuiteResults result = resultsMap.get(name);
boolean ignored = ignoredTestList.isIgnored(name);
ProcessOutput failureMessages = dataListenerInfo
.getFailureMessages().get(name);
suiteDataMap.put(name, new SuiteData(name, ignored, contents,
result, failureMessages));
}
/*
* Map the Suites by status.
*/
for (SuiteData s : suiteDataMap.values()) {
getSuites(s.getStatus()).add(s);
}
/**
* Populate the Test map with all Tests, and map by status.
*/
for (SuiteData s : suiteDataMap.values()) {
for (TestData t : s.getTestMap().values()) {
allTests.add(t);
getTests(t.getStatus()).add(t);
}
}
if (logStats.hasErrors() || !getSuites(Status.ERROR).isEmpty()) {
runStatus = Status.ERROR;
} else if (!getSuites(Status.PENDING).isEmpty()) {
runStatus = Status.PENDING;
} else {
runStatus = Status.OK;
}
}
// ----------------------------------------------------------------------
// Access the derived data.
// ----------------------------------------------------------------------
public Status getRunStatus() {
return runStatus;
}
public long getStartTime() {
return dataListenerInfo.getStartTime();
}
public long getEndTime() {
return dataListenerInfo.getEndTime();
}
public long getElapsedTime() {
return dataListenerInfo.getElapsedTime();
}
public boolean isAnyPasses() {
return !getTests(Status.OK).isEmpty();
}
public boolean isAnyFailures() {
return !getTests(Status.ERROR).isEmpty();
}
public boolean isAnyIgnores() {
return !getTests(Status.IGNORED).isEmpty();
}
public boolean isAnyPending() {
return !getTests(Status.PENDING).isEmpty();
}
public int getTotalSuiteCount() {
return suiteDataMap.size();
}
public int getPassingSuiteCount() {
return getSuites(Status.OK).size();
}
public int getFailingSuiteCount() {
return getSuites(Status.ERROR).size();
}
public int getIgnoredSuiteCount() {
return getSuites(Status.IGNORED).size();
}
public int getPendingSuiteCount() {
return getSuites(Status.PENDING).size();
}
public Collection<SuiteData> getAllSuites() {
return suiteDataMap.values();
}
public Map<String, SuiteData> getSuitesWithFailureMessages() {
Map<String, SuiteData> map = new TreeMap<String, SuiteData>();
for (SuiteData s : suiteDataMap.values()) {
if (s.getFailureMessages() != null) {
map.put(s.getName(), s);
}
}
return map;
}
public int getTotalTestCount() {
return allTests.size();
}
public int getPassingTestCount() {
return getTests(Status.OK).size();
}
public int getFailingTestCount() {
return getTests(Status.ERROR).size();
}
public int getIgnoredTestCount() {
return getTests(Status.IGNORED).size();
}
public int getPendingTestCount() {
return getTests(Status.PENDING).size();
}
public Collection<TestData> getAllTests() {
return Collections.unmodifiableCollection(allTests);
}
public Collection<TestData> getFailingTests() {
return Collections.unmodifiableCollection(getTests(Status.ERROR));
}
public Collection<TestData> getIgnoredTests() {
return Collections.unmodifiableCollection(getTests(Status.IGNORED));
}
public Collection<IgnoredTestInfo> getIgnoredTestInfo() {
return ignoredTestList.getList();
}
public String getReasonForIgnoring(String suiteName, String testName) {
return ignoredTestList.getReasonForIgnoring(suiteName, testName);
}
// ----------------------------------------------------------------------
// Helper methods
// ----------------------------------------------------------------------
/**
* Get the list of suites that have this status.
*/
private List<SuiteData> getSuites(Status st) {
return suiteMapByStatus.get(st);
}
/**
* Get the list of tests that have this status.
*/
private List<TestData> getTests(Status 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$ */
package edu.cornell.mannlib.vitro.utilities.testrunner.output;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.Reader;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.Map;
import edu.cornell.mannlib.vitro.utilities.testrunner.FileHelper;
import edu.cornell.mannlib.vitro.utilities.testrunner.IgnoredTests.IgnoredTestInfo;
import edu.cornell.mannlib.vitro.utilities.testrunner.LogStats;
import edu.cornell.mannlib.vitro.utilities.testrunner.SeleniumRunnerParameters;
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.SuiteData;
import edu.cornell.mannlib.vitro.utilities.testrunner.datamodel.SuiteData.TestData;
import edu.cornell.mannlib.vitro.utilities.testrunner.output.OutputDataListener.ProcessOutput;
/**
* Creates the summary HTML file.
*/
public class OutputSummaryFormatter {
public static final String SUMMARY_HTML_FILENAME = "summary.html";
public static final String SUMMARY_CSS_FILENAME = "summary.css";
private final SimpleDateFormat dateFormat = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss");
private final SeleniumRunnerParameters parms;
private LogStats logStats;
private DataModel dataModel;
public OutputSummaryFormatter(SeleniumRunnerParameters parms) {
this.parms = parms;
}
/**
* Create a summary HTML file from the info contained in this log file and
* these suite outputs.
*/
public void format(LogStats logStats, DataModel dataModel) {
this.logStats = logStats;
this.dataModel = dataModel;
PrintWriter writer = null;
try {
copyCssFile();
File outputFile = new File(parms.getOutputDirectory(),
SUMMARY_HTML_FILENAME);
writer = new PrintWriter(outputFile);
writeHeader(writer);
writeStatsSection(writer);
writeErrorMessagesSection(writer);
writeCondensedTable(writer);
writeIgnoreSection(writer);
writeSuiteErrorMessagesSection(writer);
writeFooter(writer);
} catch (IOException e) {
// There is no appeal for any problems here. Just report them.
e.printStackTrace();
} finally {
if (writer != null) {
writer.close();
}
}
}
/**
* Copy the CSS file into the output directory.
*/
private void copyCssFile() {
InputStream cssStream = this.getClass().getResourceAsStream(
SUMMARY_CSS_FILENAME);
if (cssStream == null) {
System.out.println("Couldn't find the CSS file: '"
+ SUMMARY_CSS_FILENAME + "'");
} else {
File cssTarget = new File(parms.getOutputDirectory(),
SUMMARY_CSS_FILENAME);
try {
FileHelper.copy(cssStream, cssTarget);
cssStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void writeHeader(PrintWriter w) {
Status runStatus = dataModel.getRunStatus();
String statusString = (runStatus == Status.PENDING) ? "IN PROGRESS"
: runStatus.toString();
String startString = formatDateTime(dataModel.getStartTime());
w.println("<html>");
w.println("<head>");
w.println(" <title>Summary of Acceptance Tests " + startString
+ "</title>");
w.println(" <link rel=\"stylesheet\" type=\"text/css\" "
+ "href=\"summary.css\">");
w.println("</head>");
w.println("<body>");
w.println();
w.println(" <div class=\"heading\">");
w.println(" Acceptance test results: " + startString);
w.println(" <div class=\"" + runStatus.getHtmlClass()
+ " one-word\">" + statusString + "</div>");
w.println(" </div>");
}
private void writeStatsSection(PrintWriter w) {
String passClass = dataModel.isAnyPasses() ? Status.OK.getHtmlClass()
: "";
String failClass = dataModel.isAnyFailures() ? Status.ERROR
.getHtmlClass() : "";
String ignoreClass = dataModel.isAnyIgnores() ? Status.IGNORED
.getHtmlClass() : "";
String start = formatDateTime(dataModel.getStartTime());
String end = formatDateTime(dataModel.getEndTime());
String elapsed = formatElapsedTime(dataModel.getElapsedTime());
w.println(" <div class=\"section\">Summary</div>");
w.println();
w.println(" <table class=\"summary\" cellspacing=\"0\">");
w.println(" <tr>");
w.println(" <td>");
w.println(" <table cellspacing=\"0\">");
w.println(" <tr><td>Start time:</td><td>" + start
+ "</td></tr>");
w.println(" <tr><td>End time:</td><td>" + end + "</td></tr>");
w.println(" <tr><td>Elapsed time</td><td>" + elapsed
+ "</td></tr>");
w.println(" </table>");
w.println(" </td>");
w.println(" <td>");
w.println(" <table class=\"tallys\" cellspacing=\"0\">");
w.println(" <tr><th>&nbsp;</th><th>Suites</th><th>Tests</th>");
w.println(" <tr class=\"" + passClass
+ "\"><td>Passed</td><td>" + dataModel.getPassingSuiteCount()
+ "</td><td>" + dataModel.getPassingTestCount() + "</td>");
w.println(" <tr class=\"" + failClass
+ "\"><td>Failed</td><td>" + dataModel.getFailingSuiteCount()
+ "</td><td>" + dataModel.getFailingTestCount() + "</td>");
w.println(" <tr class=\"" + ignoreClass
+ "\"><td>Ignored</td><td>" + dataModel.getIgnoredSuiteCount()
+ "</td><td>" + dataModel.getIgnoredTestCount() + "</td>");
if (dataModel.isAnyPending()) {
w.println(" <tr class=\"" + Status.PENDING.getHtmlClass()
+ "\"><td>Pending</td><td>"
+ dataModel.getPendingSuiteCount() + "</td><td>"
+ dataModel.getPendingTestCount() + "</td>");
}
w.println(" <tr><td class=\"total\">Total</td><td>"
+ dataModel.getTotalSuiteCount() + "</td><td>"
+ dataModel.getTotalTestCount() + "</td>");
w.println(" </table>");
w.println(" </td>");
w.println(" </tr>");
w.println(" </table>");
w.println();
}
private void writeErrorMessagesSection(PrintWriter w) {
String errorClass = Status.ERROR.getHtmlClass();
w.println(" <div class=section>Errors and warnings</div>");
w.println();
w.println(" <table cellspacing=\"0\">");
if ((!logStats.hasErrors()) && (!logStats.hasWarnings())) {
w.println(" <tr><td colspan=\"2\">No errors or warnings</td></tr>");
} else {
for (String e : logStats.getErrors()) {
w.println(" <tr class=\"" + errorClass
+ "\"><td>ERROR</td><td>" + e + "</td></tr>");
}
}
w.println(" </table>");
w.println();
}
private void writeCondensedTable(PrintWriter w) {
w.println(" <div class=section>Condensed List</div>");
w.println();
w.println(" <table class=\"condensed\" cellspacing=\"0\">");
for (SuiteData s : dataModel.getAllSuites()) {
String sReason = "";
if (s.getStatus() == Status.IGNORED) {
sReason = dataModel.getReasonForIgnoring(s.getName(), "*");
} else if (s.getFailureMessages() != null) {
sReason = s.getFailureMessages().getErrout();
} else if (s.getStatus() == Status.PENDING) {
sReason = Status.PENDING.toString();
}
w.println(" <tr>");
w.println(" <td class=\"" + s.getStatus().getHtmlClass()
+ "\">");
w.println(" <div class=\"suite\">" + outputLink(s)
+ "</div>");
if (!sReason.isEmpty()) {
// The entire class is either failed or pending or ignored.
w.println(" <div class=\"reason\">" + sReason + "</div>");
} else {
// Show the individual tests.
for (TestData t : s.getTestMap().values()) {
String tClass = t.getStatus().getHtmlClass();
String tReason = dataModel.getReasonForIgnoring(
s.getName(), t.getTestName());
w.println(" <div class=\"test " + tClass + "\">");
w.println(" " + outputLink(t));
if (!tReason.isEmpty()) {
w.println(" <div class=\"tReason\">" + tReason
+ "</div>");
}
w.println(" </div>");
}
}
w.println(" </td>");
w.println(" </tr>");
}
w.println(" </table>");
w.println();
}
private void writeSuiteErrorMessagesSection(PrintWriter w) {
Map<String, SuiteData> failedSuiteMap = dataModel
.getSuitesWithFailureMessages();
if (failedSuiteMap.isEmpty()) {
return;
}
w.println(" <div class=section>All tests</div>");
w.println();
for (SuiteData s : failedSuiteMap.values()) {
ProcessOutput output = s.getFailureMessages();
w.println(" <a name=\"" + SuiteData.failureMessageAnchor(s)
+ "\">");
w.println(" <table cellspacing=\"0\">");
w.println(" <tr><th>Standard Output</th></tr>\n");
w.println(" <tr><td><pre>" + output.getStdout()
+ "</pre></td></tr>\n");
w.println(" </table>");
w.println("<br/>&nbsp;<br/>");
w.println(" <table cellspacing=\"0\">");
w.println(" <tr><th>Error Output</th></tr>\n");
w.println(" <tr><td><pre>" + output.getErrout()
+ "</pre></td></tr>\n");
w.println(" </table>");
w.println("<br/>&nbsp;<br/>");
w.println();
}
}
private void writeIgnoreSection(PrintWriter w) {
String warnClass = Status.IGNORED.getHtmlClass();
Collection<IgnoredTestInfo> ignoredTests = dataModel
.getIgnoredTestInfo();
w.println(" <div class=section>Ignored</div>");
w.println();
w.println(" <table class=\"ignored\" cellspacing=\"0\">");
w.println(" <tr><th>Suite name</th><th>Test name</th>"
+ "<th>Reason for ignoring</th></tr>\n");
if (ignoredTests.isEmpty()) {
w.println(" <tr><td colspan=\"3\">No tests ignored.</td>"
+ "</tr>");
} else {
for (IgnoredTestInfo info : ignoredTests) {
String suiteName = info.suiteName;
String testName = info.testName;
String reason = dataModel.getReasonForIgnoring(suiteName,
testName);
w.println(" <tr class=\"" + warnClass + "\">");
w.println(" <td>" + suiteName + "</td>");
w.println(" <td>" + testName + "</td>");
w.println(" <td>" + reason + "</td>");
w.println(" </tr>");
}
}
w.println(" </table>");
w.println();
}
private void writeFooter(PrintWriter w) {
w.println(" <div class=section>Log</div>");
w.println(" <pre class=\"log\">");
Reader reader = null;
try {
reader = new FileReader(parms.getLogFile());
char[] buffer = new char[4096];
int howMany;
while (-1 != (howMany = reader.read(buffer))) {
w.write(buffer, 0, howMany);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
w.println(" </pre>");
w.println("</body>");
w.println("</html>");
}
private String formatElapsedTime(long elapsed) {
if (elapsed == 0) {
return "---";
}
long elapsedSeconds = elapsed / 1000L;
long seconds = elapsedSeconds % 60L;
long elapsedMinutes = elapsedSeconds / 60L;
long minutes = elapsedMinutes % 60L;
long hours = elapsedMinutes / 60L;
String elapsedTime = "";
if (hours > 0) {
elapsedTime += hours + "h ";
}
if (minutes > 0 || hours > 0) {
elapsedTime += minutes + "m ";
}
elapsedTime += seconds + "s";
return elapsedTime;
}
private String formatDateTime(long dateTime) {
if (dateTime == 0) {
return "---";
}
return dateFormat.format(new Date(dateTime));
}
private String outputLink(SuiteData s) {
if (s.getOutputLink() == null) {
return s.getName();
} else {
return "<a href=\"" + s.getOutputLink() + "\">" + s.getName()
+ "</a>";
}
}
private String outputLink(TestData t) {
if (t.getOutputLink() == null) {
return t.getTestName();
} else {
return "<a href=\"" + t.getOutputLink() + "\">" + t.getTestName()
+ "</a>";
}
}
}
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.utilities.testrunner.output;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.Reader;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.Map;
import edu.cornell.mannlib.vitro.utilities.testrunner.FileHelper;
import edu.cornell.mannlib.vitro.utilities.testrunner.IgnoredTests.IgnoredTestInfo;
import edu.cornell.mannlib.vitro.utilities.testrunner.LogStats;
import edu.cornell.mannlib.vitro.utilities.testrunner.SeleniumRunnerParameters;
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.SuiteData;
import edu.cornell.mannlib.vitro.utilities.testrunner.datamodel.SuiteData.TestData;
import edu.cornell.mannlib.vitro.utilities.testrunner.output.OutputDataListener.ProcessOutput;
/**
* Creates the summary HTML file.
*/
public class OutputSummaryFormatter {
public static final String SUMMARY_HTML_FILENAME = "summary.html";
public static final String SUMMARY_CSS_FILENAME = "summary.css";
private final SimpleDateFormat dateFormat = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss");
private final SeleniumRunnerParameters parms;
private LogStats logStats;
private DataModel dataModel;
public OutputSummaryFormatter(SeleniumRunnerParameters parms) {
this.parms = parms;
}
/**
* Create a summary HTML file from the info contained in this log file and
* these suite outputs.
*/
public void format(LogStats logStats, DataModel dataModel) {
this.logStats = logStats;
this.dataModel = dataModel;
PrintWriter writer = null;
try {
copyCssFile();
File outputFile = new File(parms.getOutputDirectory(),
SUMMARY_HTML_FILENAME);
writer = new PrintWriter(outputFile);
writeHeader(writer);
writeStatsSection(writer);
writeErrorMessagesSection(writer);
writeCondensedTable(writer);
writeIgnoreSection(writer);
writeSuiteErrorMessagesSection(writer);
writeFooter(writer);
} catch (IOException e) {
// There is no appeal for any problems here. Just report them.
e.printStackTrace();
} finally {
if (writer != null) {
writer.close();
}
}
}
/**
* Copy the CSS file into the output directory.
*/
private void copyCssFile() {
InputStream cssStream = this.getClass().getResourceAsStream(
SUMMARY_CSS_FILENAME);
if (cssStream == null) {
System.out.println("Couldn't find the CSS file: '"
+ SUMMARY_CSS_FILENAME + "'");
} else {
File cssTarget = new File(parms.getOutputDirectory(),
SUMMARY_CSS_FILENAME);
try {
FileHelper.copy(cssStream, cssTarget);
cssStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void writeHeader(PrintWriter w) {
Status runStatus = dataModel.getRunStatus();
String statusString = (runStatus == Status.PENDING) ? "IN PROGRESS"
: runStatus.toString();
String startString = formatDateTime(dataModel.getStartTime());
w.println("<html>");
w.println("<head>");
w.println(" <title>Summary of Acceptance Tests " + startString
+ "</title>");
w.println(" <link rel=\"stylesheet\" type=\"text/css\" "
+ "href=\"summary.css\">");
w.println("</head>");
w.println("<body>");
w.println();
w.println(" <div class=\"heading\">");
w.println(" Acceptance test results: " + startString);
w.println(" <div class=\"" + runStatus.getHtmlClass()
+ " one-word\">" + statusString + "</div>");
w.println(" </div>");
}
private void writeStatsSection(PrintWriter w) {
String passClass = dataModel.isAnyPasses() ? Status.OK.getHtmlClass()
: "";
String failClass = dataModel.isAnyFailures() ? Status.ERROR
.getHtmlClass() : "";
String ignoreClass = dataModel.isAnyIgnores() ? Status.IGNORED
.getHtmlClass() : "";
String start = formatDateTime(dataModel.getStartTime());
String end = formatDateTime(dataModel.getEndTime());
String elapsed = formatElapsedTime(dataModel.getElapsedTime());
w.println(" <div class=\"section\">Summary</div>");
w.println();
w.println(" <table class=\"summary\" cellspacing=\"0\">");
w.println(" <tr>");
w.println(" <td>");
w.println(" <table cellspacing=\"0\">");
w.println(" <tr><td>Start time:</td><td>" + start
+ "</td></tr>");
w.println(" <tr><td>End time:</td><td>" + end + "</td></tr>");
w.println(" <tr><td>Elapsed time</td><td>" + elapsed
+ "</td></tr>");
w.println(" </table>");
w.println(" </td>");
w.println(" <td>");
w.println(" <table class=\"tallys\" cellspacing=\"0\">");
w.println(" <tr><th>&nbsp;</th><th>Suites</th><th>Tests</th>");
w.println(" <tr class=\"" + passClass
+ "\"><td>Passed</td><td>" + dataModel.getPassingSuiteCount()
+ "</td><td>" + dataModel.getPassingTestCount() + "</td>");
w.println(" <tr class=\"" + failClass
+ "\"><td>Failed</td><td>" + dataModel.getFailingSuiteCount()
+ "</td><td>" + dataModel.getFailingTestCount() + "</td>");
w.println(" <tr class=\"" + ignoreClass
+ "\"><td>Ignored</td><td>" + dataModel.getIgnoredSuiteCount()
+ "</td><td>" + dataModel.getIgnoredTestCount() + "</td>");
if (dataModel.isAnyPending()) {
w.println(" <tr class=\"" + Status.PENDING.getHtmlClass()
+ "\"><td>Pending</td><td>"
+ dataModel.getPendingSuiteCount() + "</td><td>"
+ dataModel.getPendingTestCount() + "</td>");
}
w.println(" <tr><td class=\"total\">Total</td><td>"
+ dataModel.getTotalSuiteCount() + "</td><td>"
+ dataModel.getTotalTestCount() + "</td>");
w.println(" </table>");
w.println(" </td>");
w.println(" </tr>");
w.println(" </table>");
w.println();
}
private void writeErrorMessagesSection(PrintWriter w) {
String errorClass = Status.ERROR.getHtmlClass();
w.println(" <div class=section>Errors and warnings</div>");
w.println();
w.println(" <table cellspacing=\"0\">");
if ((!logStats.hasErrors()) && (!logStats.hasWarnings())) {
w.println(" <tr><td colspan=\"2\">No errors or warnings</td></tr>");
} else {
for (String e : logStats.getErrors()) {
w.println(" <tr class=\"" + errorClass
+ "\"><td>ERROR</td><td>" + e + "</td></tr>");
}
}
w.println(" </table>");
w.println();
}
private void writeCondensedTable(PrintWriter w) {
w.println(" <div class=section>Condensed List</div>");
w.println();
w.println(" <table class=\"condensed\" cellspacing=\"0\">");
for (SuiteData s : dataModel.getAllSuites()) {
String sReason = "";
if (s.getStatus() == Status.IGNORED) {
sReason = dataModel.getReasonForIgnoring(s.getName(), "*");
} else if (s.getFailureMessages() != null) {
sReason = s.getFailureMessages().getErrout();
} else if (s.getStatus() == Status.PENDING) {
sReason = Status.PENDING.toString();
}
w.println(" <tr>");
w.println(" <td class=\"" + s.getStatus().getHtmlClass()
+ "\">");
w.println(" <div class=\"suite\">" + outputLink(s)
+ "</div>");
if (!sReason.isEmpty()) {
// The entire class is either failed or pending or ignored.
w.println(" <div class=\"reason\">" + sReason + "</div>");
} else {
// Show the individual tests.
for (TestData t : s.getTestMap().values()) {
String tClass = t.getStatus().getHtmlClass();
String tReason = dataModel.getReasonForIgnoring(
s.getName(), t.getTestName());
w.println(" <div class=\"test " + tClass + "\">");
w.println(" " + outputLink(t));
if (!tReason.isEmpty()) {
w.println(" <div class=\"tReason\">" + tReason
+ "</div>");
}
w.println(" </div>");
}
}
w.println(" </td>");
w.println(" </tr>");
}
w.println(" </table>");
w.println();
}
private void writeSuiteErrorMessagesSection(PrintWriter w) {
Map<String, SuiteData> failedSuiteMap = dataModel
.getSuitesWithFailureMessages();
if (failedSuiteMap.isEmpty()) {
return;
}
w.println(" <div class=section>All tests</div>");
w.println();
for (SuiteData s : failedSuiteMap.values()) {
ProcessOutput output = s.getFailureMessages();
w.println(" <a name=\"" + SuiteData.failureMessageAnchor(s)
+ "\">");
w.println(" <table cellspacing=\"0\">");
w.println(" <tr><th>Standard Output</th></tr>\n");
w.println(" <tr><td><pre>" + output.getStdout()
+ "</pre></td></tr>\n");
w.println(" </table>");
w.println("<br/>&nbsp;<br/>");
w.println(" <table cellspacing=\"0\">");
w.println(" <tr><th>Error Output</th></tr>\n");
w.println(" <tr><td><pre>" + output.getErrout()
+ "</pre></td></tr>\n");
w.println(" </table>");
w.println("<br/>&nbsp;<br/>");
w.println();
}
}
private void writeIgnoreSection(PrintWriter w) {
String warnClass = Status.IGNORED.getHtmlClass();
Collection<IgnoredTestInfo> ignoredTests = dataModel
.getIgnoredTestInfo();
w.println(" <div class=section>Ignored</div>");
w.println();
w.println(" <table class=\"ignored\" cellspacing=\"0\">");
w.println(" <tr><th>Suite name</th><th>Test name</th>"
+ "<th>Reason for ignoring</th></tr>\n");
if (ignoredTests.isEmpty()) {
w.println(" <tr><td colspan=\"3\">No tests ignored.</td>"
+ "</tr>");
} else {
for (IgnoredTestInfo info : ignoredTests) {
String suiteName = info.suiteName;
String testName = info.testName;
String reason = dataModel.getReasonForIgnoring(suiteName,
testName);
w.println(" <tr class=\"" + warnClass + "\">");
w.println(" <td>" + suiteName + "</td>");
w.println(" <td>" + testName + "</td>");
w.println(" <td>" + reason + "</td>");
w.println(" </tr>");
}
}
w.println(" </table>");
w.println();
}
private void writeFooter(PrintWriter w) {
w.println(" <div class=section>Log</div>");
w.println(" <pre class=\"log\">");
Reader reader = null;
try {
reader = new FileReader(parms.getLogFile());
char[] buffer = new char[4096];
int howMany;
while (-1 != (howMany = reader.read(buffer))) {
w.write(buffer, 0, howMany);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
w.println(" </pre>");
w.println("</body>");
w.println("</html>");
}
private String formatElapsedTime(long elapsed) {
if (elapsed == 0) {
return "---";
}
long elapsedSeconds = elapsed / 1000L;
long seconds = elapsedSeconds % 60L;
long elapsedMinutes = elapsedSeconds / 60L;
long minutes = elapsedMinutes % 60L;
long hours = elapsedMinutes / 60L;
String elapsedTime = "";
if (hours > 0) {
elapsedTime += hours + "h ";
}
if (minutes > 0 || hours > 0) {
elapsedTime += minutes + "m ";
}
elapsedTime += seconds + "s";
return elapsedTime;
}
private String formatDateTime(long dateTime) {
if (dateTime == 0) {
return "---";
}
return dateFormat.format(new Date(dateTime));
}
private String outputLink(SuiteData s) {
if (s.getOutputLink() == null) {
return s.getName();
} else {
return "<a href=\"" + s.getOutputLink() + "\">" + s.getName()
+ "</a>";
}
}
private String outputLink(TestData t) {
if (t.getOutputLink() == null) {
return t.getTestName();
} else {
return "<a href=\"" + t.getOutputLink() + "\">" + t.getTestName()
+ "</a>";
}
}
}