Remove this failed experiment that is causing so much problem with the repository!
This commit is contained in:
parent
824848323c
commit
80a23bb848
35 changed files with 0 additions and 4729 deletions
|
@ -1,137 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||
|
||||
<!-- ======================================================================
|
||||
Build script for the Selenium test runner.
|
||||
====================================================================== -->
|
||||
|
||||
<project name="acceptanceTests" default="describe" basedir=".">
|
||||
|
||||
<property name="source.dir" location="${basedir}/src" />
|
||||
<property name="lib.dir" location="${basedir}/lib" />
|
||||
<property name="test.dir" location="${basedir}/test" />
|
||||
<property name="build.dir" value="${basedir}/.build" />
|
||||
|
||||
<!-- =================================
|
||||
target: describe
|
||||
================================= -->
|
||||
<target name="describe" description="--> Describe the targets (this is the default).">
|
||||
<echo>
|
||||
all - Runs "clean", then "run".
|
||||
clean - Delete all artifacts so the next build will be from scratch.
|
||||
compile - Compile the Java source files.
|
||||
test - Compile and run the JUnit tests.
|
||||
run - Run the tester.
|
||||
</echo>
|
||||
</target>
|
||||
|
||||
|
||||
<!-- =================================
|
||||
target: all
|
||||
================================= -->
|
||||
<target name="all"
|
||||
depends="clean, run"
|
||||
description="--> Do a clean build and execute the selenium runner.">
|
||||
|
||||
</target>
|
||||
|
||||
<!-- =================================
|
||||
target: clean
|
||||
================================= -->
|
||||
<target name="clean" description="--> Remove any artifacts from previous builds.">
|
||||
<delete dir="${build.dir}" />
|
||||
</target>
|
||||
|
||||
<!-- - - - - - - - - - - - - - - - - -
|
||||
target: prepare
|
||||
- - - - - - - - - - - - - - - - - -->
|
||||
<target name="prepare">
|
||||
<mkdir dir="${build.dir}" />
|
||||
</target>
|
||||
|
||||
<!-- =================================
|
||||
target: compile
|
||||
================================= -->
|
||||
<target name="compile" depends="prepare" description="--> Compile the selenium runner.">
|
||||
<javac srcdir="${source.dir}"
|
||||
destdir="${build.dir}"
|
||||
debug="true"
|
||||
deprecation="true"
|
||||
encoding="UTF8"
|
||||
optimize="true"
|
||||
source="1.6">
|
||||
<classpath>
|
||||
<pathelement location="${lib.dir}/commons-httpclient-3.1.jar" />
|
||||
</classpath>
|
||||
</javac>
|
||||
|
||||
</target>
|
||||
|
||||
<!-- =================================
|
||||
target: test
|
||||
================================= -->
|
||||
<target name="test"
|
||||
depends="compile"
|
||||
description="--> Run unit tests against the selenium runner code.">
|
||||
<javac srcdir="${test.dir}"
|
||||
destdir="${build.dir}"
|
||||
debug="true"
|
||||
deprecation="true"
|
||||
encoding="UTF8"
|
||||
optimize="false"
|
||||
source="1.6">
|
||||
<classpath>
|
||||
<pathelement location="${build.dir}" />
|
||||
<pathelement location="${lib.dir}/junit-4.8.1.jar" />
|
||||
</classpath>
|
||||
</javac>
|
||||
|
||||
<junit printsummary="no" haltonfailure="yes">
|
||||
<classpath>
|
||||
<pathelement location="${build.dir}" />
|
||||
<pathelement location="${lib.dir}/junit-4.8.1.jar" />
|
||||
</classpath>
|
||||
|
||||
<formatter type="brief" />
|
||||
|
||||
<batchtest fork="yes" todir="${build.dir}">
|
||||
<fileset dir="test">
|
||||
<include name="**/*Test*.java" />
|
||||
</fileset>
|
||||
</batchtest>
|
||||
</junit>
|
||||
</target>
|
||||
|
||||
<!-- =================================
|
||||
target: run
|
||||
================================= -->
|
||||
<target name="run" depends="test" description="--> Execute the selenium runner.">
|
||||
<property name="acceptance.dir" location="${basedir}" />
|
||||
|
||||
<property name="acceptance.properties.file"
|
||||
location="${acceptance.dir}/acceptance_tests.properties" />
|
||||
|
||||
<condition property="acceptance.interactive.arg" value="interactive" else="">
|
||||
<not>
|
||||
<istrue value="${acceptance.batch}" />
|
||||
</not>
|
||||
</condition>
|
||||
|
||||
<java classname="edu.cornell.mannlib.vitro.utilities.testrunner.SeleniumRunner"
|
||||
fork="yes"
|
||||
dir="${acceptance.dir}"
|
||||
failonerror="true">
|
||||
<classpath>
|
||||
<pathelement location="${build.dir}" />
|
||||
<pathelement location="${source.dir}" />
|
||||
<pathelement location="${lib.dir}/commons-httpclient-3.1.jar" />
|
||||
<pathelement location="${lib.dir}/commons-logging-1.1.1.jar" />
|
||||
<pathelement location="${lib.dir}/commons-codec-1.3.jar" />
|
||||
</classpath>
|
||||
<arg file="${acceptance.properties.file}" />
|
||||
<arg value="${acceptance.interactive.arg}" />
|
||||
</java>
|
||||
</target>
|
||||
|
||||
</project>
|
|
@ -1,36 +0,0 @@
|
|||
#
|
||||
# These properties tell how to set up Selenium to run a test suite.
|
||||
#
|
||||
website_url = http://localhost:8080/vivo/
|
||||
suite_parent_directories = suites
|
||||
output_directory = output
|
||||
user_extensions_path = selenium/user-extensions.js
|
||||
firefox_profile_template_path =
|
||||
suite_timeout_limit = 240
|
||||
selenium_jar_path = selenium/selenium-server.jar
|
||||
|
||||
#
|
||||
# These properties are needed to cleanse the data model between test suites.
|
||||
#
|
||||
# -- Windows commands for Tomcat - require startup.bat and shutdown.bat, which may not be part of the installation.
|
||||
#tomcat_stop_command = "C:\\Program Files\\Apache Software Foundation\\Tomcat 6.0\\bin\\shutdown.bat"
|
||||
#tomcat_start_command = "C:\\Program Files\\Apache Software Foundation\\Tomcat 6.0\\bin\\startup.bat"
|
||||
#
|
||||
# -- Linux commands for Tomcat
|
||||
#tomcat_stop_command = /usr/local/tomcat/bin/shutdown.sh
|
||||
#tomcat_start_command = /usr/local/tomcat/bin/startup.bat
|
||||
|
||||
tomcat_stop_command = "C:\\Program Files\\Apache Software Foundation\\Tomcat 6.0\\bin\\shutdown.bat"
|
||||
tomcat_start_command = "C:\\Program Files\\Apache Software Foundation\\Tomcat 6.0\\bin\\startup.bat"
|
||||
tomcat_stop_delay = 10
|
||||
tomcat_start_delay = 30
|
||||
mysql_username = vivoUser
|
||||
mysql_password = vivoPass
|
||||
mysql_dumpfile = /eclipseVitroWorkspace/vivo/utilities/acceptance-tests/test-model/testmodeldump.sql
|
||||
mysql_db_name = vivo
|
||||
upload_directory = /Vivoweb_Stuff/test_deploy/uploads
|
||||
|
||||
#
|
||||
# These properties control the output formatting of the tests.
|
||||
#
|
||||
ignored_tests_file = /eclipseVitroWorkspace/vivo/utilities/acceptance-tests/suites/ignored_tests.txt
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,3 +0,0 @@
|
|||
Here is an excellent description of how to create a Firefox profile for use when running Selenium tests.
|
||||
|
||||
http://girliemangalo.wordpress.com/2009/02/05/creating-firefox-profile-for-your-selenium-rc-tests/
|
Binary file not shown.
|
@ -1,184 +0,0 @@
|
|||
/* $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.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.StringWriter;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import edu.cornell.mannlib.vitro.utilities.testrunner.listener.Listener;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* A harness that runs a system-level command.
|
||||
* </p>
|
||||
* <p>
|
||||
* No provision is made for standard input.
|
||||
* </p>
|
||||
* <p>
|
||||
* The standard output and standard error streams are asynchronously read, so
|
||||
* the sub-process will not block on full buffers. Warning: if either of these
|
||||
* streams contain more data than can fit into a String, then we will have a
|
||||
* problem.
|
||||
* </p>
|
||||
*
|
||||
* @author jblake
|
||||
*/
|
||||
public class CommandRunner {
|
||||
|
||||
private Integer returnCode;
|
||||
private String stdOut = "";
|
||||
private String stdErr = "";
|
||||
private File workingDirectory;
|
||||
|
||||
/* Gets informed of output as it arrives. Never null. */
|
||||
private final Listener listener;
|
||||
|
||||
private final Map<String, String> environmentAdditions = new HashMap<String, String>();
|
||||
|
||||
public CommandRunner(SeleniumRunnerParameters parms) {
|
||||
this.listener = parms.getListener();
|
||||
}
|
||||
|
||||
/** Set the directory that the command will run in. */
|
||||
public void setWorkingDirectory(File workingDirectory) {
|
||||
this.workingDirectory = workingDirectory;
|
||||
}
|
||||
|
||||
/** Add (or replace) any environment variable. */
|
||||
public void setEnvironmentVariable(String key, String value) {
|
||||
this.environmentAdditions.put(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the command.
|
||||
*
|
||||
* @param command
|
||||
* a list containing the operating system program and its
|
||||
* arguments. See
|
||||
* {@link java.lang.ProcessBuilder#ProcessBuilder(List)}.
|
||||
*/
|
||||
public void run(List<String> command) throws CommandRunnerException {
|
||||
listener.subProcessStart(command);
|
||||
try {
|
||||
ProcessBuilder builder = new ProcessBuilder(command);
|
||||
|
||||
if (workingDirectory != null) {
|
||||
builder.directory(workingDirectory);
|
||||
}
|
||||
|
||||
if (!environmentAdditions.isEmpty()) {
|
||||
builder.environment().putAll(this.environmentAdditions);
|
||||
}
|
||||
|
||||
Process process = builder.start();
|
||||
StreamEater outputEater = new StreamEater(process.getInputStream(),
|
||||
false);
|
||||
StreamEater errorEater = new StreamEater(process.getErrorStream(),
|
||||
true);
|
||||
|
||||
this.returnCode = process.waitFor();
|
||||
|
||||
outputEater.join(1000);
|
||||
outputEater.stopRunning();
|
||||
this.stdOut = outputEater.getContents();
|
||||
|
||||
errorEater.join(1000);
|
||||
errorEater.stopRunning();
|
||||
this.stdErr = errorEater.getContents();
|
||||
} catch (IOException e) {
|
||||
throw new CommandRunnerException(
|
||||
"Exception when handling sub-process:", e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new CommandRunnerException(
|
||||
"Exception when handling sub-process:", e);
|
||||
}
|
||||
listener.subProcessStop(command);
|
||||
}
|
||||
|
||||
public int getReturnCode() {
|
||||
if (returnCode == null) {
|
||||
throw new IllegalStateException("Return code is not available.");
|
||||
}
|
||||
return returnCode;
|
||||
}
|
||||
|
||||
public String getStdErr() {
|
||||
return stdErr;
|
||||
}
|
||||
|
||||
public String getStdOut() {
|
||||
return stdOut;
|
||||
}
|
||||
|
||||
/**
|
||||
* A thread that reads an InputStream until it reaches end of file, then
|
||||
* closes the stream. Designated as error stream or not, so it can tell the
|
||||
* logger.
|
||||
*/
|
||||
private class StreamEater extends Thread {
|
||||
private final InputStream stream;
|
||||
private final boolean isError;
|
||||
private volatile boolean running;
|
||||
|
||||
private final StringWriter contents = new StringWriter();
|
||||
|
||||
private final byte[] buffer = new byte[4096];
|
||||
|
||||
public StreamEater(InputStream stream, boolean isError) {
|
||||
this.stream = stream;
|
||||
this.isError = isError;
|
||||
this.running = true;
|
||||
this.start();
|
||||
}
|
||||
|
||||
public void stopRunning() {
|
||||
this.running = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
int howMany = 0;
|
||||
while (running) {
|
||||
howMany = stream.read(buffer);
|
||||
if (howMany > 0) {
|
||||
String string = new String(buffer, 0, howMany);
|
||||
contents.write(string);
|
||||
|
||||
if (isError) {
|
||||
listener.subProcessErrout(string);
|
||||
} else {
|
||||
listener.subProcessStdout(string);
|
||||
}
|
||||
} else if (howMany == 0) {
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
stream.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getContents() {
|
||||
return contents.toString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
/* $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);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
/* $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);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,167 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.utilities.testrunner;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Reader;
|
||||
|
||||
/**
|
||||
* Some utility methods for dealing with files and directories.
|
||||
*/
|
||||
public class FileHelper {
|
||||
|
||||
/**
|
||||
* Delete a file. If it can't be deleted, complain.
|
||||
*/
|
||||
public static void deleteFile(File file) throws IOException {
|
||||
if (file.exists()) {
|
||||
file.delete();
|
||||
}
|
||||
if (!file.exists()) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we were unable to delete the file, is it because it's a non-empty
|
||||
* directory?
|
||||
*/
|
||||
if (file.isDirectory()) {
|
||||
final StringBuffer message = new StringBuffer(
|
||||
"Can't delete directory '" + file.getPath() + "'\n");
|
||||
file.listFiles(new FileFilter() {
|
||||
public boolean accept(File pathname) {
|
||||
message.append(" contains file '" + pathname + "'\n");
|
||||
return true;
|
||||
}
|
||||
});
|
||||
throw new IOException(message.toString().trim());
|
||||
} else {
|
||||
throw new IOException("Unable to delete file '" + file.getPath()
|
||||
+ "'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all of the files in a directory, any sub-directories, and the
|
||||
* directory itself.
|
||||
*/
|
||||
public static void purgeDirectoryRecursively(File directory)
|
||||
throws IOException {
|
||||
File[] files = directory.listFiles();
|
||||
for (File file : files) {
|
||||
if (file.isDirectory()) {
|
||||
purgeDirectoryRecursively(file);
|
||||
} else {
|
||||
deleteFile(file);
|
||||
}
|
||||
}
|
||||
deleteFile(directory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm that this is an existing, readable file.
|
||||
*/
|
||||
public static void checkReadableFile(File file, String label) {
|
||||
if (!file.exists()) {
|
||||
throw new IllegalArgumentException(label + " does not exist.");
|
||||
}
|
||||
if (!file.isFile()) {
|
||||
throw new IllegalArgumentException(label + " is not a file.");
|
||||
}
|
||||
if (!file.canRead()) {
|
||||
throw new IllegalArgumentException(label + " is not readable.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of this file, without the extension.
|
||||
*/
|
||||
public static String baseName(File file) {
|
||||
String name = file.getName();
|
||||
int periodHere = name.indexOf('.');
|
||||
if (periodHere == -1) {
|
||||
return name;
|
||||
} else {
|
||||
return name.substring(0, periodHere);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the contents of a file to a new location. If the target file already
|
||||
* exists, it will be over-written.
|
||||
*/
|
||||
public static void copy(File source, File target) throws IOException {
|
||||
InputStream input = null;
|
||||
|
||||
try {
|
||||
input = new FileInputStream(source);
|
||||
copy(input, target);
|
||||
} finally {
|
||||
if (input != null) {
|
||||
try {
|
||||
input.close();
|
||||
} catch (IOException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the contents of an InputStream to a file. If the target file already
|
||||
* exists, it will be over-written. Doesn't close the input stream.
|
||||
*/
|
||||
public static void copy(InputStream input, File target) throws IOException {
|
||||
OutputStream output = null;
|
||||
|
||||
try {
|
||||
output = new FileOutputStream(target);
|
||||
int howMany;
|
||||
byte[] buffer = new byte[4096];
|
||||
while (-1 != (howMany = input.read(buffer))) {
|
||||
output.write(buffer, 0, howMany);
|
||||
}
|
||||
} finally {
|
||||
if (output != null) {
|
||||
try {
|
||||
output.close();
|
||||
} catch (IOException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Suck all the data from a {@link Reader} into a {@link String}.
|
||||
*/
|
||||
public static String readAll(Reader reader) throws IOException {
|
||||
StringBuilder result = new StringBuilder();
|
||||
BufferedReader buffered = new BufferedReader(reader);
|
||||
char[] chunk = new char[4096];
|
||||
int howMany;
|
||||
|
||||
try {
|
||||
while (-1 != (howMany = buffered.read(chunk))) {
|
||||
result.append(chunk, 0, howMany);
|
||||
}
|
||||
} finally {
|
||||
reader.close();
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/** No need to instantiate this, since all methods are static. */
|
||||
private FileHelper() {
|
||||
// Nothing to initialize.
|
||||
}
|
||||
|
||||
}
|
|
@ -1,216 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.utilities.testrunner;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* A list of tests to be ignored - they are expected to fail, and their failure
|
||||
* is logged with a warning, not an error.
|
||||
*/
|
||||
public class IgnoredTests {
|
||||
public static final IgnoredTests EMPTY_LIST = new IgnoredTests();
|
||||
|
||||
private final String filePath;
|
||||
private final List<IgnoredTestInfo> tests;
|
||||
|
||||
/**
|
||||
* Create an empty instance.
|
||||
*/
|
||||
private IgnoredTests() {
|
||||
this.filePath = "NO FILE";
|
||||
this.tests = Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Parse the file of ignored tests.
|
||||
* </p>
|
||||
* <p>
|
||||
* Ignore any blank line, or any line starting with '#' or '!'
|
||||
* </p>
|
||||
* <p>
|
||||
* Each other line describes an ignored test. The line contains the suite
|
||||
* name, a comma (with optional space), the test name (with optional space)
|
||||
* and optionally a comment, starting with a '#'.
|
||||
* </p>
|
||||
* If the test name is an asterisk '*', then the entire suite will be
|
||||
* ignored.
|
||||
* <p>
|
||||
* </p>
|
||||
*/
|
||||
public IgnoredTests(File file) {
|
||||
this.filePath = file.getAbsolutePath();
|
||||
|
||||
List<IgnoredTestInfo> tests = new ArrayList<IgnoredTestInfo>();
|
||||
|
||||
BufferedReader reader = null;
|
||||
try {
|
||||
reader = new BufferedReader(new FileReader(file));
|
||||
String line;
|
||||
while (null != (line = reader.readLine())) {
|
||||
line = line.trim();
|
||||
if ((line.length() == 0) || (line.charAt(0) == '#')
|
||||
|| (line.charAt(0) == '!')) {
|
||||
continue;
|
||||
}
|
||||
Pattern p = Pattern.compile("([^,#]+),([^,#]+)(#(.*))?");
|
||||
Matcher m = p.matcher(line);
|
||||
if (m.matches()) {
|
||||
tests.add(new IgnoredTestInfo(m.group(1), m.group(2), m
|
||||
.group(4)));
|
||||
} else {
|
||||
throw new FatalException(
|
||||
"Bad format on ignored test description: '" + line
|
||||
+ "', should be "
|
||||
+ "<suite name>, <test name> [# comment]");
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new FatalException(
|
||||
"Failed to parse the list of ignored tests: '"
|
||||
+ file.getPath() + "'", e);
|
||||
} finally {
|
||||
if (reader != null) {
|
||||
try {
|
||||
reader.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.tests = Collections.unmodifiableList(tests);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a copy of the whole list.
|
||||
*/
|
||||
public List<IgnoredTestInfo> getList() {
|
||||
return new ArrayList<IgnoredTestInfo>(tests);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this test ignored or not?
|
||||
*/
|
||||
public boolean isIgnored(String suiteName, String testName) {
|
||||
for (IgnoredTestInfo test : tests) {
|
||||
if (test.matches(suiteName, testName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this entire suite ignored?
|
||||
*/
|
||||
public boolean isIgnored(String suiteName) {
|
||||
for (IgnoredTestInfo test : tests) {
|
||||
if (test.matchesEntireSuite(suiteName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this test is ignored, what is the reason? If not, return an empty
|
||||
* string.
|
||||
*/
|
||||
public String getReasonForIgnoring(String suiteName, String testName) {
|
||||
for (IgnoredTestInfo test : tests) {
|
||||
if (test.matches(suiteName, testName)) {
|
||||
return test.comment;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* If this suite is ignored, what is the reason? If not, return an empty
|
||||
* string.
|
||||
*/
|
||||
public String getReasonForIgnoring(String suiteName) {
|
||||
for (IgnoredTestInfo test : tests) {
|
||||
if (test.matchesEntireSuite(suiteName)) {
|
||||
return test.comment;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String s = " ignored tests from " + this.filePath + "\n";
|
||||
for (IgnoredTestInfo test : tests) {
|
||||
s += " " + test.suiteName + ", " + test.testName + "\n";
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encapsulates a line from the file with suite name, test name, and
|
||||
* comment.
|
||||
*/
|
||||
public static class IgnoredTestInfo {
|
||||
public final String suiteName;
|
||||
public final String testName;
|
||||
public final String comment;
|
||||
|
||||
public IgnoredTestInfo(String suiteName, String testName, String comment) {
|
||||
this.suiteName = suiteName.trim();
|
||||
this.testName = testName.trim();
|
||||
this.comment = (comment == null) ? "" : comment.trim();
|
||||
}
|
||||
|
||||
public boolean matches(String suiteName, String testName) {
|
||||
return this.suiteName.equals(suiteName)
|
||||
&& (this.testName.equals(testName) || this.testName
|
||||
.equals("*"));
|
||||
}
|
||||
|
||||
public boolean matchesEntireSuite(String suiteName) {
|
||||
return this.suiteName.equals(suiteName)
|
||||
&& this.testName.equals("*");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (!obj.getClass().equals(this.getClass())) {
|
||||
return false;
|
||||
}
|
||||
IgnoredTestInfo that = (IgnoredTestInfo) obj;
|
||||
return this.suiteName.equals(that.suiteName)
|
||||
&& this.testName.equals(that.testName)
|
||||
&& this.comment.equals(that.comment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return suiteName.hashCode() ^ testName.hashCode()
|
||||
^ comment.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "IgnoredTestInfo['" + suiteName + "', '" + testName + "', '"
|
||||
+ comment + "']";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.utilities.testrunner;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Extract any summary information from the log file.
|
||||
*/
|
||||
public class LogStats {
|
||||
public static LogStats EMPTY_LOG_STATS = new LogStats();
|
||||
|
||||
private static final Pattern SUITE_NAME_PATTERN = Pattern
|
||||
.compile("Running suite (.*)");
|
||||
private static final Pattern ERROR_PATTERN = Pattern
|
||||
.compile("ERROR\\s+(.*)");
|
||||
private static final Pattern WARNING_PATTERN = Pattern
|
||||
.compile("WARN\\s+(.*)");
|
||||
|
||||
/**
|
||||
* Factory method.
|
||||
*/
|
||||
public static LogStats parse(File logFile) {
|
||||
return new LogStats(logFile);
|
||||
}
|
||||
|
||||
private final List<String> suiteNames = new ArrayList<String>();
|
||||
private final List<String> errors = new ArrayList<String>();
|
||||
private final List<String> warnings = new ArrayList<String>();
|
||||
|
||||
private LogStats() {
|
||||
// Nothing to initialize for empty instance.
|
||||
}
|
||||
|
||||
private LogStats(File logFile) {
|
||||
|
||||
BufferedReader reader = null;
|
||||
String line;
|
||||
try {
|
||||
reader = new BufferedReader(new FileReader(logFile));
|
||||
while (null != (line = reader.readLine())) {
|
||||
Matcher m;
|
||||
m = SUITE_NAME_PATTERN.matcher(line);
|
||||
if (m.matches()) {
|
||||
suiteNames.add(m.group(1));
|
||||
} else {
|
||||
m = ERROR_PATTERN.matcher(line);
|
||||
if (m.matches()) {
|
||||
errors.add(m.group(1));
|
||||
} else {
|
||||
m = WARNING_PATTERN.matcher(line);
|
||||
if (m.matches()) {
|
||||
warnings.add(m.group(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
// Can't give up - I need to create as much output as I can.
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (reader != null) {
|
||||
try {
|
||||
reader.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasErrors() {
|
||||
return !errors.isEmpty();
|
||||
}
|
||||
|
||||
public Collection<String> getErrors() {
|
||||
return Collections.unmodifiableCollection(errors);
|
||||
}
|
||||
|
||||
public boolean hasWarnings() {
|
||||
return !warnings.isEmpty();
|
||||
}
|
||||
|
||||
public Collection<String> getWarnings() {
|
||||
return Collections.unmodifiableCollection(warnings);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,157 +0,0 @@
|
|||
/* $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.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import edu.cornell.mannlib.vitro.utilities.testrunner.listener.Listener;
|
||||
|
||||
/**
|
||||
* Resets the RDF-Model to a known state, in preparation for the next Selenium
|
||||
* test suite.
|
||||
*/
|
||||
public class ModelCleaner {
|
||||
public static final String TEST_USER_ONTOLOGY_FILENAME = "test-user-model.owl";
|
||||
private final ModelCleanerProperties properties;
|
||||
private final TomcatController tomcatController;
|
||||
private final CommandRunner runner;
|
||||
private final Listener listener;
|
||||
|
||||
public ModelCleaner(SeleniumRunnerParameters parms,
|
||||
TomcatController tomcatController) {
|
||||
this.properties = parms.getModelCleanerProperties();
|
||||
this.listener = parms.getListener();
|
||||
this.runner = new CommandRunner(parms);
|
||||
this.tomcatController = tomcatController;
|
||||
|
||||
sanityCheck();
|
||||
}
|
||||
|
||||
private void sanityCheck() {
|
||||
executeMysqlStatement("show databases;");
|
||||
|
||||
int returnCode = runner.getReturnCode();
|
||||
if (returnCode != 0) {
|
||||
throw new FatalException(
|
||||
"sanityCheck: Failed to execute a MySQL statement: "
|
||||
+ "return code=" + returnCode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the RDF-Model to a known state, according to the parameters in the
|
||||
* properties file.
|
||||
*
|
||||
* @throws CommandRunnerException
|
||||
* if a problem occurs in a sub-process.
|
||||
*/
|
||||
public void clean() throws CommandRunnerException {
|
||||
tomcatController.stopTheWebapp();
|
||||
insertTheUserFile();
|
||||
recreateTheDatabase();
|
||||
tomcatController.startTheWebapp();
|
||||
removeTheUserFile();
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the test data ontology file into the auth area, so we get our
|
||||
* pre-defined admin user.
|
||||
*/
|
||||
private void insertTheUserFile() {
|
||||
InputStream userOntologyStream = this.getClass().getResourceAsStream(
|
||||
TEST_USER_ONTOLOGY_FILENAME);
|
||||
if (userOntologyStream == null) {
|
||||
throw new FatalException(
|
||||
"Couldn't find the Test User Ontology file: '"
|
||||
+ TEST_USER_ONTOLOGY_FILENAME + "'");
|
||||
}
|
||||
|
||||
File userOntologyTarget = figureUserOntologyTarget();
|
||||
try {
|
||||
FileHelper.copy(userOntologyStream, userOntologyTarget);
|
||||
userOntologyStream.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop the database and create it again, empty.
|
||||
*/
|
||||
private void recreateTheDatabase() {
|
||||
String mysqlStatement = "drop database " + properties.getMysqlDbName()
|
||||
+ "; create database " + properties.getMysqlDbName()
|
||||
+ " character set utf8;";
|
||||
|
||||
listener.dropDatabaseStarting(mysqlStatement);
|
||||
executeMysqlStatement(mysqlStatement);
|
||||
|
||||
int returnCode = runner.getReturnCode();
|
||||
if (returnCode != 0) {
|
||||
listener.dropDatabaseFailed(returnCode);
|
||||
throw new FatalException("dropDatabase() failed: return code="
|
||||
+ returnCode);
|
||||
}
|
||||
|
||||
listener.dropDatabaseComplete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the test data ontology file, so we leave no trace.
|
||||
*/
|
||||
private void removeTheUserFile() {
|
||||
File userOntologyTarget = figureUserOntologyTarget();
|
||||
userOntologyTarget.delete();
|
||||
if (userOntologyTarget.exists()) {
|
||||
listener.logWarning("Failed to delete the test data ontology "
|
||||
+ "file: '" + TEST_USER_ONTOLOGY_FILENAME + "'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell MySQL to execute this statement. If it fails, throw a fatal
|
||||
* exception.
|
||||
*/
|
||||
private void executeMysqlStatement(String mysqlStatement) {
|
||||
List<String> cmd = new ArrayList<String>();
|
||||
cmd.add("mysql");
|
||||
cmd.add("--user=" + properties.getMysqlUsername());
|
||||
cmd.add("--password=" + properties.getMysqlPassword());
|
||||
cmd.add("--database=" + properties.getMysqlDbName());
|
||||
cmd.add("--execute=" + mysqlStatement);
|
||||
|
||||
try {
|
||||
runner.run(cmd);
|
||||
} catch (CommandRunnerException e) {
|
||||
throw new FatalException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Figure out where the test data ontology file should go. C:\Program
|
||||
* Files\Apache Software Foundation\Tomcat
|
||||
* 6.0\webapps\vivo\WEB-INF\ontologies\auth
|
||||
*/
|
||||
private File figureUserOntologyTarget() {
|
||||
File webappDirectory = properties.getWebappDirectory();
|
||||
File authDirectory = new File(webappDirectory,
|
||||
"WEB-INF/ontologies/auth");
|
||||
|
||||
if (!authDirectory.exists()) {
|
||||
throw new FatalException("Target directory for the test data "
|
||||
+ "ontology file doesn't exist. Webapp directory is '"
|
||||
+ webappDirectory + "', target directory is '"
|
||||
+ authDirectory + "'");
|
||||
}
|
||||
|
||||
return new File(authDirectory, TEST_USER_ONTOLOGY_FILENAME);
|
||||
}
|
||||
|
||||
static String convertBackslashes(File file) {
|
||||
return file.getPath().replace("\\", "/");
|
||||
}
|
||||
}
|
|
@ -1,120 +0,0 @@
|
|||
/* $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.util.Properties;
|
||||
|
||||
/**
|
||||
* Hold the runtime properties that pertain specifically to cleaning the data
|
||||
* model.
|
||||
*/
|
||||
public class ModelCleanerProperties {
|
||||
public static final String PROP_MYSQL_USERNAME = "mysql_username";
|
||||
public static final String PROP_MYSQL_PASSWORD = "mysql_password";
|
||||
public static final String PROP_MYSQL_DB_NAME = "mysql_db_name";
|
||||
public static final String PROP_WEBAPP_DIRECTORY = "vivo_webapp_directory";
|
||||
public static final String PROP_TOMCAT_CHECK_READY_COMMAND = "tomcat_check_ready_command";
|
||||
public static final String PROP_TOMCAT_STOP_COMMAND = "tomcat_stop_command";
|
||||
public static final String PROP_TOMCAT_START_COMMAND = "tomcat_start_command";
|
||||
|
||||
private final String mysqlUsername;
|
||||
private final String mysqlPassword;
|
||||
private final String mysqlDbName;
|
||||
private final File webappDirectory;
|
||||
private final String tomcatCheckReadyCommand;
|
||||
private final String tomcatStopCommand;
|
||||
private final String tomcatStartCommand;
|
||||
|
||||
/**
|
||||
* Confirm that we have the expected properties, and that their values seem
|
||||
* reasonable.
|
||||
*/
|
||||
public ModelCleanerProperties(Properties props) {
|
||||
this.mysqlUsername = getRequiredProperty(props, PROP_MYSQL_USERNAME);
|
||||
this.mysqlPassword = getRequiredProperty(props, PROP_MYSQL_PASSWORD);
|
||||
this.mysqlDbName = getRequiredProperty(props, PROP_MYSQL_DB_NAME);
|
||||
|
||||
this.webappDirectory = confirmWebappDirectory(props);
|
||||
|
||||
this.tomcatCheckReadyCommand = getRequiredProperty(props,
|
||||
PROP_TOMCAT_CHECK_READY_COMMAND);
|
||||
this.tomcatStopCommand = getRequiredProperty(props,
|
||||
PROP_TOMCAT_STOP_COMMAND);
|
||||
this.tomcatStartCommand = getRequiredProperty(props,
|
||||
PROP_TOMCAT_START_COMMAND);
|
||||
}
|
||||
|
||||
public String getMysqlUsername() {
|
||||
return mysqlUsername;
|
||||
}
|
||||
|
||||
public String getMysqlPassword() {
|
||||
return mysqlPassword;
|
||||
}
|
||||
|
||||
public String getMysqlDbName() {
|
||||
return mysqlDbName;
|
||||
}
|
||||
|
||||
public File getWebappDirectory() {
|
||||
return webappDirectory;
|
||||
}
|
||||
|
||||
public String getTomcatCheckReadyCommand() {
|
||||
return tomcatCheckReadyCommand;
|
||||
}
|
||||
|
||||
public String getTomcatStopCommand() {
|
||||
return tomcatStopCommand;
|
||||
}
|
||||
|
||||
public String getTomcatStartCommand() {
|
||||
return tomcatStartCommand;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* The dumpfile parameter must point to an existing directory.
|
||||
*/
|
||||
private File confirmWebappDirectory(Properties props) {
|
||||
String filename = getRequiredProperty(props, PROP_WEBAPP_DIRECTORY);
|
||||
File webappDirectory = new File(filename);
|
||||
if (!webappDirectory.exists()) {
|
||||
throw new IllegalArgumentException("Invalid value for '"
|
||||
+ PROP_WEBAPP_DIRECTORY + "': directory '" + filename
|
||||
+ "' does not exist.");
|
||||
}
|
||||
if (!webappDirectory.isDirectory()) {
|
||||
throw new IllegalArgumentException("Invalid value for '"
|
||||
+ PROP_WEBAPP_DIRECTORY + "': '" + filename
|
||||
+ "' is not a directory.");
|
||||
}
|
||||
if (!webappDirectory.canWrite()) {
|
||||
throw new IllegalArgumentException("Invalid value for '"
|
||||
+ PROP_WEBAPP_DIRECTORY + "': directory '" + filename
|
||||
+ "' is not writeable.");
|
||||
}
|
||||
return webappDirectory;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "\n mysqlUsername: " + mysqlUsername
|
||||
+ "\n mysqlPassword: " + mysqlPassword
|
||||
+ "\n mysqlDbName: " + mysqlDbName
|
||||
+ "\n webappDirectory: " + webappDirectory;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,205 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.utilities.testrunner;
|
||||
|
||||
import static edu.cornell.mannlib.vitro.utilities.testrunner.SeleniumRunnerParameters.LOGFILE_NAME;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import edu.cornell.mannlib.vitro.utilities.testrunner.datamodel.DataModel;
|
||||
import edu.cornell.mannlib.vitro.utilities.testrunner.datamodel.SuiteContents;
|
||||
import edu.cornell.mannlib.vitro.utilities.testrunner.listener.Listener;
|
||||
import edu.cornell.mannlib.vitro.utilities.testrunner.output.OutputManager;
|
||||
|
||||
/**
|
||||
* Run the Selenium test suites. Provide the properties file and perhaps an
|
||||
* "interactive" flag.
|
||||
*/
|
||||
public class SeleniumRunner {
|
||||
private final SeleniumRunnerParameters parms;
|
||||
private final Listener listener;
|
||||
private final UploadAreaCleaner uploadCleaner;
|
||||
private final TomcatController tomcatController;
|
||||
private final ModelCleaner modelCleaner;
|
||||
private final SuiteRunner suiteRunner;
|
||||
private final OutputManager outputManager;
|
||||
private final DataModel dataModel;
|
||||
|
||||
public SeleniumRunner(SeleniumRunnerParameters parms) {
|
||||
this.parms = parms;
|
||||
this.listener = parms.getListener();
|
||||
this.uploadCleaner = new UploadAreaCleaner(parms);
|
||||
this.tomcatController = new TomcatController(parms);
|
||||
this.modelCleaner = new ModelCleaner(parms, this.tomcatController);
|
||||
this.suiteRunner = new SuiteRunner(parms);
|
||||
this.outputManager = new OutputManager(parms);
|
||||
|
||||
this.dataModel = new DataModel();
|
||||
this.dataModel.setIgnoredTestList(parms.getIgnoredTests());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up the run, run the selected suites, summarize the output, and clean
|
||||
* up afterwards.
|
||||
*
|
||||
* @return <code>true</code> iff all tests passed.
|
||||
*/
|
||||
public boolean run() {
|
||||
boolean success;
|
||||
try {
|
||||
listener.runStarted();
|
||||
outputManager.cleanOutputDirectory();
|
||||
|
||||
parseSuites();
|
||||
selectSuites();
|
||||
|
||||
runSelectedSuites();
|
||||
tomcatController.cleanup();
|
||||
|
||||
listener.runEndTime();
|
||||
outputManager.summarizeOutput(dataModel);
|
||||
success = Status.isSuccess(dataModel.getRunStatus());
|
||||
} catch (IOException e) {
|
||||
listener.runFailed(e);
|
||||
success = false;
|
||||
throw new FatalException(e);
|
||||
} catch (FatalException e) {
|
||||
listener.runFailed(e);
|
||||
success = false;
|
||||
throw e;
|
||||
} finally {
|
||||
listener.runStopped();
|
||||
outputManager.summarizeOutput(dataModel);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan the suite directories in the suite files.
|
||||
*/
|
||||
public void parseSuites() {
|
||||
List<SuiteContents> allContents = new ArrayList<SuiteContents>();
|
||||
for (File parentDir : parms.getSuiteParentDirectories()) {
|
||||
for (File suiteDir : parms.findSuiteDirs(parentDir)) {
|
||||
SuiteContents contents = SuiteContents.parse(suiteDir);
|
||||
if (contents != null) {
|
||||
allContents.add(contents);
|
||||
}
|
||||
}
|
||||
}
|
||||
dataModel.setSuiteContents(allContents);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select all test suites which aren't explicitly ignored.
|
||||
*/
|
||||
public void selectSuites() {
|
||||
Listener listener = parms.getListener();
|
||||
IgnoredTests ignored = parms.getIgnoredTests();
|
||||
|
||||
List<File> suites = new ArrayList<File>();
|
||||
|
||||
for (File parentDir : parms.getSuiteParentDirectories()) {
|
||||
for (File suite : parms.findSuiteDirs(parentDir)) {
|
||||
String suiteName = suite.getName();
|
||||
if (ignored.isIgnored(suiteName)) {
|
||||
listener.suiteIgnored(suite);
|
||||
} else {
|
||||
listener.suiteAdded(suite);
|
||||
suites.add(suite);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dataModel.setSelectedSuites(suites);
|
||||
}
|
||||
|
||||
public void runSelectedSuites() {
|
||||
for (File suiteDir : dataModel.getSelectedSuites()) {
|
||||
outputManager.summarizeOutput(dataModel);
|
||||
listener.suiteStarted(suiteDir);
|
||||
try {
|
||||
if (parms.isCleanModel()) {
|
||||
modelCleaner.clean();
|
||||
}
|
||||
if (parms.isCleanUploads()) {
|
||||
uploadCleaner.clean();
|
||||
}
|
||||
suiteRunner.runSuite(suiteDir);
|
||||
} catch (IOException e) {
|
||||
listener.suiteFailed(suiteDir, e);
|
||||
} catch (CommandRunnerException e) {
|
||||
listener.suiteFailed(suiteDir, e);
|
||||
}
|
||||
listener.suiteStopped(suiteDir);
|
||||
}
|
||||
}
|
||||
|
||||
private static void usage(String message) {
|
||||
System.out.println(message);
|
||||
System.out.println("Usage is: SeleniumRunner <parameters_file> "
|
||||
+ "[\"interactive\"]");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
SeleniumRunnerParameters parms = null;
|
||||
boolean interactive = false;
|
||||
boolean success = false;
|
||||
|
||||
if ((args.length != 1) && (args.length != 2)) {
|
||||
usage("Wrong number of arguments.");
|
||||
}
|
||||
|
||||
if (args.length == 2) {
|
||||
String option = args[1].trim();
|
||||
if (option.length() > 0) {
|
||||
if (!"interactive".equalsIgnoreCase(args[1])) {
|
||||
usage("Invalid argument '" + args[1] + "'");
|
||||
}
|
||||
interactive = true;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
try {
|
||||
parms = new SeleniumRunnerParameters(args[0]);
|
||||
} catch (IOException e) {
|
||||
usage("Can't read properties file: " + e.getMessage());
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new FatalException(e);
|
||||
}
|
||||
|
||||
if (interactive) {
|
||||
// TODO hook up the GUI.
|
||||
throw new FatalException("interactive mode not implemented. "
|
||||
+ "use 'ant acceptance -Dacceptance.batch=true'");
|
||||
} else {
|
||||
File logFile = new File(parms.getOutputDirectory(),
|
||||
LOGFILE_NAME);
|
||||
System.out.println("Log file is '" + logFile.getPath() + "'");
|
||||
|
||||
// Run all of the suites.
|
||||
// For each suite, clean the model and the upload area.
|
||||
parms.setCleanModel(true);
|
||||
parms.setCleanUploads(true);
|
||||
|
||||
System.out.println(parms);
|
||||
|
||||
success = new SeleniumRunner(parms).run();
|
||||
}
|
||||
} catch (FatalException e) {
|
||||
System.err.println("\n\n-----------------\n"
|
||||
+ "| FATAL ERROR | " + e.getMessage()
|
||||
+ "\n-----------------\n\n");
|
||||
e.printStackTrace();
|
||||
}
|
||||
System.out.println("Exiting SeleniumRunner");
|
||||
System.exit(success ? 0 : -1);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,434 +0,0 @@
|
|||
/* $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;
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.utilities.testrunner;
|
||||
|
||||
/**
|
||||
* Status for each test, each suite, and the entire run.
|
||||
*/
|
||||
public enum Status {
|
||||
/** All tests passed, and there were no warnings or errors. */
|
||||
OK("good"),
|
||||
|
||||
/**
|
||||
* One or more tests have not been run yet.
|
||||
*/
|
||||
PENDING("pending"),
|
||||
|
||||
/**
|
||||
* Will not run because it is ignored, or has run and failed but the failure
|
||||
* is ignored.
|
||||
*/
|
||||
IGNORED("fair"),
|
||||
|
||||
/**
|
||||
* A test failed and could not be ignored, or an error message was
|
||||
* generated.
|
||||
*/
|
||||
ERROR("bad");
|
||||
|
||||
private final String htmlClass;
|
||||
|
||||
private Status(String htmlClass) {
|
||||
this.htmlClass = htmlClass;
|
||||
}
|
||||
|
||||
public String getHtmlClass() {
|
||||
return this.htmlClass;
|
||||
}
|
||||
|
||||
/** When combined, the more severe status (defined later) takes precedence. */
|
||||
public static Status combine(Status s1, Status s2) {
|
||||
if (s1.compareTo(s2) > 0) {
|
||||
return s1;
|
||||
} else {
|
||||
return s2;
|
||||
}
|
||||
}
|
||||
|
||||
/** Anything except ERROR is considered to be a success. */
|
||||
public static boolean isSuccess(Status status) {
|
||||
return status != Status.ERROR;
|
||||
}
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
/* $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.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import edu.cornell.mannlib.vitro.utilities.testrunner.listener.Listener;
|
||||
|
||||
/**
|
||||
* Run a Selenium TestSuite in a sub-process.
|
||||
*/
|
||||
public class SuiteRunner {
|
||||
|
||||
private final SeleniumRunnerParameters parms;
|
||||
private final CommandRunner runner;
|
||||
private final Listener listener;
|
||||
|
||||
public SuiteRunner(SeleniumRunnerParameters parms) {
|
||||
this.parms = parms;
|
||||
this.runner = new CommandRunner(parms);
|
||||
this.listener = parms.getListener();
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the suite.
|
||||
*/
|
||||
public void runSuite(File suiteDir) {
|
||||
listener.suiteTestingStarted(suiteDir);
|
||||
|
||||
List<String> cmd = new ArrayList<String>();
|
||||
cmd.add("java");
|
||||
cmd.add("-jar");
|
||||
cmd.add(parms.getSeleniumJarPath().getPath());
|
||||
cmd.add("-singleWindow");
|
||||
cmd.add("-timeout");
|
||||
cmd.add(String.valueOf(parms.getSuiteTimeoutLimit()));
|
||||
cmd.add("-userExtensions");
|
||||
cmd.add(parms.getUserExtensionsFile().getPath());
|
||||
|
||||
// TODO - figure out why the use of a template means running the test
|
||||
// twice in simultaneous tabs.
|
||||
// if (parms.hasFirefoxProfileDir()) {
|
||||
// cmd.add("-firefoxProfileTemplate");
|
||||
// cmd.add(parms.getFirefoxProfileDir().getPath());
|
||||
// }
|
||||
|
||||
String suiteName = suiteDir.getName();
|
||||
File outputFile = new File(parms.getOutputDirectory(), suiteName
|
||||
+ ".html");
|
||||
File suiteFile = new File(suiteDir, "Suite.html");
|
||||
|
||||
cmd.add("-htmlSuite");
|
||||
cmd.add("*firefox");
|
||||
cmd.add(parms.getWebsiteUrl());
|
||||
cmd.add(suiteFile.getPath());
|
||||
cmd.add(outputFile.getPath());
|
||||
|
||||
try {
|
||||
runner.run(cmd);
|
||||
} catch (CommandRunnerException e) {
|
||||
throw new FatalException(e);
|
||||
}
|
||||
|
||||
int returnCode = runner.getReturnCode();
|
||||
if (returnCode != 0) {
|
||||
listener.suiteFailed(suiteDir, returnCode);
|
||||
}
|
||||
|
||||
listener.suiteTestingStopped(suiteDir);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,160 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.utilities.testrunner;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import edu.cornell.mannlib.vitro.utilities.testrunner.listener.Listener;
|
||||
|
||||
/**
|
||||
* Start and stop the webapp, so we can clean the database.
|
||||
*/
|
||||
public class TomcatController {
|
||||
private final SeleniumRunnerParameters parms;
|
||||
private final ModelCleanerProperties properties;
|
||||
private final Listener listener;
|
||||
|
||||
public TomcatController(SeleniumRunnerParameters parms) {
|
||||
this.parms = parms;
|
||||
this.properties = parms.getModelCleanerProperties();
|
||||
this.listener = parms.getListener();
|
||||
|
||||
try {
|
||||
checkThatTomcatIsReady();
|
||||
} catch (CommandRunnerException e) {
|
||||
throw new FatalException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Insure that Tomcat is ready and that we can start and stop VIVO.
|
||||
*/
|
||||
private void checkThatTomcatIsReady() throws CommandRunnerException {
|
||||
String tomcatCheckReadyCommand = properties
|
||||
.getTomcatCheckReadyCommand();
|
||||
|
||||
CommandRunner runner = new CommandRunner(parms);
|
||||
|
||||
listener.webappCheckingReady(tomcatCheckReadyCommand);
|
||||
runner.run(parseCommandLine(tomcatCheckReadyCommand));
|
||||
|
||||
int returnCode = runner.getReturnCode();
|
||||
if (returnCode != 0) {
|
||||
listener.webappCheckReadyFailed(returnCode);
|
||||
throw new CommandRunnerException("Tomcat is not ready: code="
|
||||
+ returnCode);
|
||||
}
|
||||
|
||||
listener.webappCheckedReady();
|
||||
}
|
||||
|
||||
public void stopTheWebapp() throws CommandRunnerException {
|
||||
String tomcatStopCommand = properties.getTomcatStopCommand();
|
||||
|
||||
CommandRunner runner = new CommandRunner(parms);
|
||||
|
||||
listener.webappStopping(tomcatStopCommand);
|
||||
runner.run(parseCommandLine(tomcatStopCommand));
|
||||
|
||||
int returnCode = runner.getReturnCode();
|
||||
if (returnCode != 0) {
|
||||
listener.webappStopFailed(returnCode);
|
||||
throw new CommandRunnerException("Failed to stop Tomcat: code="
|
||||
+ returnCode);
|
||||
}
|
||||
|
||||
listener.webappStopped();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start Tomcat and wait for it to initialize.
|
||||
*/
|
||||
public void startTheWebapp() throws CommandRunnerException {
|
||||
String tomcatStartCommand = properties.getTomcatStartCommand();
|
||||
|
||||
CommandRunner runner = new CommandRunner(parms);
|
||||
|
||||
listener.webappStarting(tomcatStartCommand);
|
||||
try {
|
||||
// Stupid Windows won't allow us to start Tomcat as an independent
|
||||
// process (except if its installed as a service).
|
||||
runner.run(parseCommandLine(tomcatStartCommand));
|
||||
} catch (CommandRunnerException e) {
|
||||
throw new FatalException(e);
|
||||
}
|
||||
|
||||
int returnCode = runner.getReturnCode();
|
||||
if (returnCode != 0) {
|
||||
listener.webappStartFailed(returnCode);
|
||||
throw new CommandRunnerException("Failed to start Tomcat: code="
|
||||
+ returnCode);
|
||||
}
|
||||
|
||||
listener.webappStarted();
|
||||
}
|
||||
|
||||
/**
|
||||
* A command line must be broken into separate arguments, where arguments
|
||||
* are delimited by blanks unless the blank (and the argument) is enclosed
|
||||
* in quotes.
|
||||
*/
|
||||
static List<String> parseCommandLine(String commandLine) {
|
||||
List<String> pieces = new ArrayList<String>();
|
||||
StringBuilder piece = null;
|
||||
boolean inDelimiter = true;
|
||||
boolean inQuotes = false;
|
||||
for (int i = 0; i < commandLine.length(); i++) {
|
||||
char thisChar = commandLine.charAt(i);
|
||||
if ((thisChar == ' ') && !inQuotes) {
|
||||
if (inDelimiter) {
|
||||
// No effect.
|
||||
} else {
|
||||
inDelimiter = true;
|
||||
pieces.add(piece.toString());
|
||||
}
|
||||
} else if (thisChar == '"') {
|
||||
// Quotes are not carried into the parsed strings.
|
||||
inQuotes = !inQuotes;
|
||||
} else { // Not a blank or a quote.
|
||||
if (inDelimiter) {
|
||||
inDelimiter = false;
|
||||
piece = new StringBuilder();
|
||||
}
|
||||
piece.append(thisChar);
|
||||
}
|
||||
}
|
||||
|
||||
// There is an implied delimiter at the end of the command line.
|
||||
if (!inDelimiter) {
|
||||
pieces.add(piece.toString());
|
||||
}
|
||||
|
||||
// Quotes must appear in pairs
|
||||
if (inQuotes) {
|
||||
throw new IllegalArgumentException(
|
||||
"Command line contains mismatched quotes: " + commandLine);
|
||||
}
|
||||
|
||||
return pieces;
|
||||
}
|
||||
|
||||
/**
|
||||
* The run is finished. Do we need to do anything?
|
||||
*/
|
||||
public void cleanup() {
|
||||
// Don't need to do anything.
|
||||
|
||||
// If we've been starting and stopping Tomcat,
|
||||
// stop it one more time.
|
||||
if (parms.isCleanModel()) {
|
||||
try {
|
||||
stopTheWebapp();
|
||||
} catch (CommandRunnerException e) {
|
||||
throw new FatalException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
/* $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.IOException;
|
||||
|
||||
import edu.cornell.mannlib.vitro.utilities.testrunner.listener.Listener;
|
||||
|
||||
/**
|
||||
* Clean out the file upload area, so the next suite will start with no uploads.
|
||||
*/
|
||||
public class UploadAreaCleaner {
|
||||
private final SeleniumRunnerParameters parms;
|
||||
private final Listener listener;
|
||||
|
||||
public UploadAreaCleaner(SeleniumRunnerParameters parms) {
|
||||
this.parms = parms;
|
||||
this.listener = parms.getListener();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all of the directories and files in the upload directory. Don't
|
||||
* delete the upload directory itself.
|
||||
*/
|
||||
public void clean() throws IOException {
|
||||
File uploadDirectory = parms.getUploadDirectory();
|
||||
if (!uploadDirectory.isDirectory()) {
|
||||
throw new IllegalArgumentException("'" + uploadDirectory.getPath()
|
||||
+ "' is not a directory.");
|
||||
}
|
||||
|
||||
listener.cleanUploadStart(uploadDirectory);
|
||||
|
||||
try {
|
||||
for (File file : uploadDirectory.listFiles()) {
|
||||
if (file.isFile()) {
|
||||
FileHelper.deleteFile(file);
|
||||
} else {
|
||||
FileHelper.purgeDirectoryRecursively(file);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
listener.cleanUploadFailed(uploadDirectory, e);
|
||||
throw e;
|
||||
} finally {
|
||||
listener.cleanUploadStop(uploadDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,294 +0,0 @@
|
|||
/* $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);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
/* $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.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import edu.cornell.mannlib.vitro.utilities.testrunner.FileHelper;
|
||||
|
||||
/**
|
||||
* Parses the actual HTML test suite file, and holds the results.
|
||||
*/
|
||||
public class SuiteContents {
|
||||
/**
|
||||
* If the file doesn't contain a line that includes this pattern, it is not
|
||||
* a suite contents file.
|
||||
*/
|
||||
private static final Pattern TITLE_LINE_PATTERN = Pattern
|
||||
.compile("<title>Test Suite</title>");
|
||||
private static final Pattern TEST_PATTERN = Pattern
|
||||
.compile("<tr><td><a\\s+href=[^>]*>([^<]+)</a></td></tr>(?m)");
|
||||
|
||||
private static final String SUITE_FILE_NAME = "Suite.html";
|
||||
|
||||
/**
|
||||
* Parse the test names fields from this file and attempt to produce a
|
||||
* {@link SuiteContents} object. If this is not an appropriate file, just
|
||||
* return null.
|
||||
*/
|
||||
public static SuiteContents parse(File suiteDirectory) {
|
||||
StringBuilder fileContents = new StringBuilder();
|
||||
BufferedReader reader = null;
|
||||
try {
|
||||
File suiteFile = new File(suiteDirectory, SUITE_FILE_NAME);
|
||||
if (!suiteFile.exists()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
reader = new BufferedReader(new FileReader(suiteFile));
|
||||
String line;
|
||||
while (null != (line = reader.readLine())) {
|
||||
fileContents.append(line).append('\n');
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
} finally {
|
||||
if (reader != null) {
|
||||
try {
|
||||
reader.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If it doesn't contain the title line, it's not a suite file.
|
||||
if (!TITLE_LINE_PATTERN.matcher(fileContents).find()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Accumulate all of the test names.
|
||||
List<String> testNames = new ArrayList<String>();
|
||||
Matcher m = TEST_PATTERN.matcher(fileContents);
|
||||
int lookHere = 0;
|
||||
while (m.find(lookHere)) {
|
||||
testNames.add(m.group(1));
|
||||
lookHere = m.end();
|
||||
}
|
||||
|
||||
return new SuiteContents(FileHelper.baseName(suiteDirectory), testNames);
|
||||
}
|
||||
|
||||
private final String name;
|
||||
private final Collection<String> testNames;
|
||||
|
||||
public SuiteContents(String name, Collection<String> testNames) {
|
||||
this.name = name;
|
||||
this.testNames = Collections
|
||||
.unmodifiableCollection(new ArrayList<String>(testNames));
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Collection<String> getTestNames() {
|
||||
return testNames;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,181 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.utilities.testrunner.datamodel;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import edu.cornell.mannlib.vitro.utilities.testrunner.Status;
|
||||
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.TestResults;
|
||||
|
||||
/**
|
||||
* What do we know about this suite, both before it runs and after it has run?
|
||||
*/
|
||||
public class SuiteData {
|
||||
/**
|
||||
* If this suite has failure messages, the output link is to an anchor on
|
||||
* the same page.
|
||||
*/
|
||||
public static String failureMessageAnchor(SuiteData s) {
|
||||
return "suiteFailure_" + s.getName();
|
||||
}
|
||||
|
||||
private final String name;
|
||||
private final Status status;
|
||||
private final String outputLink;
|
||||
private final ProcessOutput failureMessages;
|
||||
|
||||
/**
|
||||
* This map iterates according to the order that the tests were specified in
|
||||
* the suite file.
|
||||
*/
|
||||
private final Map<String, TestData> testMap;
|
||||
|
||||
public SuiteData(String name, boolean ignored, SuiteContents contents,
|
||||
SuiteResults results, ProcessOutput failureMessages) {
|
||||
this.name = name;
|
||||
this.failureMessages = failureMessages;
|
||||
|
||||
if (ignored) {
|
||||
this.status = Status.IGNORED;
|
||||
this.outputLink = null;
|
||||
this.testMap = buildTestMap(contents, results);
|
||||
} else if (failureMessages != null) {
|
||||
this.status = Status.ERROR;
|
||||
this.outputLink = "#" + failureMessageAnchor(this);
|
||||
this.testMap = buildTestMap(contents, results);
|
||||
} else if (results != null) {
|
||||
this.testMap = buildTestMap(contents, results);
|
||||
this.status = buildStatusFromTestMap();
|
||||
this.outputLink = results.getOutputLink();
|
||||
} else {
|
||||
this.status = Status.PENDING;
|
||||
this.outputLink = null;
|
||||
this.testMap = buildTestMap(contents, results);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the test map. Do we have test results, or only the advance list of
|
||||
* tests?
|
||||
*/
|
||||
private Map<String, TestData> buildTestMap(SuiteContents contents,
|
||||
SuiteResults results) {
|
||||
if (results == null) {
|
||||
return buildTestMapFromContents(contents);
|
||||
} else {
|
||||
return buildTestMapFromResults(contents, results);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* All we have to build from is the contents of the Suite HTML file.
|
||||
*/
|
||||
private Map<String, TestData> buildTestMapFromContents(
|
||||
SuiteContents contents) {
|
||||
Map<String, TestData> map = new LinkedHashMap<String, TestData>();
|
||||
for (String testName : contents.getTestNames()) {
|
||||
map.put(testName, new TestData(testName, this.name, this.status,
|
||||
null));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* We can build from both the contents of the Suite HTML file and from the
|
||||
* test results output file.
|
||||
*/
|
||||
private Map<String, TestData> buildTestMapFromResults(
|
||||
SuiteContents contents, SuiteResults results) {
|
||||
Map<String, TestData> map = new LinkedHashMap<String, TestData>();
|
||||
for (String testName : contents.getTestNames()) {
|
||||
TestResults testResult = results.getTest(testName);
|
||||
if (testResult == null) {
|
||||
// This shouldn't happen. How do we show it?
|
||||
map.put(testName, new TestData(testName, this.name,
|
||||
Status.PENDING, null));
|
||||
} else {
|
||||
map.put(testName,
|
||||
new TestData(testName, this.name, testResult
|
||||
.getStatus(), testResult.getOutputLink()));
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* The suite ran to completion, so its status is the worst of the individual
|
||||
* test statuses.
|
||||
*/
|
||||
private Status buildStatusFromTestMap() {
|
||||
Status status = Status.OK;
|
||||
for (TestData t : this.testMap.values()) {
|
||||
status = Status.combine(status, t.getStatus());
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Status getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public String getOutputLink() {
|
||||
return outputLink;
|
||||
}
|
||||
|
||||
public ProcessOutput getFailureMessages() {
|
||||
return failureMessages;
|
||||
}
|
||||
|
||||
public Map<String, TestData> getTestMap() {
|
||||
return testMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* What do we know about this test, both before it runs and after it has
|
||||
* run?
|
||||
*/
|
||||
public static class TestData {
|
||||
private final String testName;
|
||||
private final String suiteName;
|
||||
private final Status status;
|
||||
private final String outputLink;
|
||||
|
||||
public TestData(String testName, String suiteName, Status status,
|
||||
String outputLink) {
|
||||
this.testName = testName;
|
||||
this.suiteName = suiteName;
|
||||
this.status = status;
|
||||
this.outputLink = outputLink;
|
||||
}
|
||||
|
||||
public String getTestName() {
|
||||
return testName;
|
||||
}
|
||||
|
||||
public String getSuiteName() {
|
||||
return suiteName;
|
||||
}
|
||||
|
||||
public Status getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public String getOutputLink() {
|
||||
return outputLink;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TestData[testName=" + testName + ", suiteName=" + suiteName
|
||||
+ ", status=" + status + ", outputLink=" + outputLink + "]";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,92 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.utilities.testrunner.listener;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A listener for all events that occur during the run.
|
||||
*/
|
||||
public interface Listener {
|
||||
|
||||
void suiteIgnored(File suite);
|
||||
|
||||
void suiteAdded(File suite);
|
||||
|
||||
void runStarted();
|
||||
|
||||
void runFailed(Exception e);
|
||||
|
||||
void runEndTime();
|
||||
|
||||
void runStopped();
|
||||
|
||||
void cleanOutputStart(File outputDirectory);
|
||||
|
||||
void cleanOutputFailed(File outputDirectory, IOException e);
|
||||
|
||||
void cleanOutputStop(File outputDirectory);
|
||||
|
||||
void webappStopping(String tomcatStopCommand);
|
||||
|
||||
void webappStopFailed(int returnCode);
|
||||
|
||||
void webappStopped();
|
||||
|
||||
void dropDatabaseStarting(String statement);
|
||||
|
||||
void dropDatabaseFailed(int returnCode);
|
||||
|
||||
void dropDatabaseComplete();
|
||||
|
||||
void loadDatabaseStarting(String statement);
|
||||
|
||||
void loadDatabaseFailed(int returnCode);
|
||||
|
||||
void loadDatabaseComplete();
|
||||
|
||||
void webappCheckingReady(String command);
|
||||
|
||||
void webappCheckReadyFailed(int returnCode);
|
||||
|
||||
void webappCheckedReady();
|
||||
|
||||
void webappStarting(String command);
|
||||
|
||||
void webappStartFailed(int returnCode);
|
||||
|
||||
void webappStarted();
|
||||
|
||||
void subProcessStart(List<String> command);
|
||||
|
||||
void subProcessStartInBackground(List<String> command);
|
||||
|
||||
void subProcessStdout(String string);
|
||||
|
||||
void subProcessErrout(String string);
|
||||
|
||||
void subProcessStop(List<String> command);
|
||||
|
||||
void suiteStarted(File suiteDir);
|
||||
|
||||
void suiteTestingStarted(File suiteDir);
|
||||
|
||||
void suiteFailed(File suiteDir, int returnCode);
|
||||
|
||||
void suiteFailed(File suiteDir, Exception e);
|
||||
|
||||
void suiteTestingStopped(File suiteDir);
|
||||
|
||||
void suiteStopped(File suiteDir);
|
||||
|
||||
void cleanUploadStart(File uploadDirectory);
|
||||
|
||||
void cleanUploadFailed(File uploadDirectory, IOException e);
|
||||
|
||||
void cleanUploadStop(File uploadDirectory);
|
||||
|
||||
void logWarning(String message);
|
||||
|
||||
}
|
|
@ -1,281 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.utilities.testrunner.listener;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.Writer;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A listener for all events that occur during the run. In this basic
|
||||
* implementation, each event is simply formatted and written to a log file or
|
||||
* {@link PrintStream}.
|
||||
*/
|
||||
public class LoggingListener implements Listener {
|
||||
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat(
|
||||
"yyyy-MM-dd HH:mm:ss.SSS");
|
||||
|
||||
private final Writer writer;
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Constructors
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
public LoggingListener(PrintStream out) {
|
||||
this.writer = new OutputStreamWriter(out);
|
||||
}
|
||||
|
||||
public LoggingListener(File logFile) throws IOException {
|
||||
this.writer = new FileWriter(logFile);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Listener methods
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public void suiteIgnored(File suite) {
|
||||
log("Suite '" + suite.getName() + "' ignored.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suiteAdded(File suite) {
|
||||
log("Suite '" + suite.getName() + "' added.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runStarted() {
|
||||
log("Run started.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runFailed(Exception e) {
|
||||
log("Run failed - fatal error");
|
||||
log(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runEndTime() {
|
||||
log("Testing complete.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runStopped() {
|
||||
log("Run stopped.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanOutputStart(File outputDirectory) {
|
||||
log("Output area cleaning started: " + outputDirectory.getPath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanOutputFailed(File outputDirectory, IOException e) {
|
||||
log("Output area cleaning failed: " + outputDirectory.getPath());
|
||||
log(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanOutputStop(File outputDirectory) {
|
||||
log("Output area cleaning stopped: " + outputDirectory.getPath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void webappCheckingReady(String command) {
|
||||
log("Checking if Tomcat is ready: " + command);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void webappCheckReadyFailed(int returnCode) {
|
||||
log("Tomcat is not ready: " + returnCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void webappCheckedReady() {
|
||||
log("Checked that Tomcat is ready.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void webappStopping(String command) {
|
||||
log("Stopping tomcat: " + command);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void webappStopFailed(int returnCode) {
|
||||
log("Failed to stop tomcat; return code was " + returnCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void webappStopped() {
|
||||
log("Tomcat stopped.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dropDatabaseStarting(String statement) {
|
||||
log("Dropping database: " + statement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dropDatabaseFailed(int returnCode) {
|
||||
log("Failed to drop the database; return code was " + returnCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dropDatabaseComplete() {
|
||||
log("Dropped database.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadDatabaseStarting(String statement) {
|
||||
log("Loading the database: " + statement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadDatabaseFailed(int returnCode) {
|
||||
log("Failed to load the database; return code was " + returnCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadDatabaseComplete() {
|
||||
log("Loaded the database.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void webappStarting(String tomcatStartCommand) {
|
||||
log("Starting tomcat: " + tomcatStartCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void webappStartFailed(int returnCode) {
|
||||
log("Failed to start tomcat; return code was " + returnCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void webappStarted() {
|
||||
log("Tomcat started.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subProcessStart(List<String> command) {
|
||||
log("Subprocess started: " + command);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subProcessStartInBackground(List<String> command) {
|
||||
log("Subprocess started in background: " + command);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subProcessStdout(String string) {
|
||||
logRawText(string);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subProcessErrout(String string) {
|
||||
logRawText(string);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subProcessStop(List<String> command) {
|
||||
log("Subprocess stopped: " + command);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suiteStarted(File suiteDir) {
|
||||
log("Suite started: " + suiteDir.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suiteTestingStarted(File suiteDir) {
|
||||
log("Suite testing started: " + suiteDir.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suiteFailed(File suiteDir, int returnCode) {
|
||||
log("Suite failed: " + suiteDir.getName() + ", returnCode="
|
||||
+ returnCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suiteFailed(File suiteDir, Exception e) {
|
||||
log("Suite failed: " + suiteDir.getName());
|
||||
log(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suiteTestingStopped(File suiteDir) {
|
||||
log("Suite testing stopped: " + suiteDir.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suiteStopped(File suiteDir) {
|
||||
log("Suite stopped: " + suiteDir.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanUploadStart(File uploadDirectory) {
|
||||
log("Upload cleaning started: " + uploadDirectory.getPath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanUploadFailed(File uploadDirectory, IOException e) {
|
||||
log("Upload cleaning failed: " + uploadDirectory.getPath());
|
||||
log(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanUploadStop(File uploadDirectory) {
|
||||
log("Upload cleaning stopped: " + uploadDirectory.getPath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logWarning(String message) {
|
||||
log("WARNING: " + message);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Helper methods
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
private void logRawText(String rawText) {
|
||||
try {
|
||||
writer.write(rawText);
|
||||
writer.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void log(String message) {
|
||||
try {
|
||||
writer.write(timeStamp() + " " + message + "\n");
|
||||
writer.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void log(Throwable t) {
|
||||
try {
|
||||
t.printStackTrace(new PrintWriter(writer));
|
||||
writer.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the current date and time to a string for the log.
|
||||
*/
|
||||
private String timeStamp() {
|
||||
return DATE_FORMAT.format(new Date());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,298 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.utilities.testrunner.listener;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A {@link Listener} implementation that holds a list of {@link Listener}s and
|
||||
* sends each message to all of them.
|
||||
*/
|
||||
public class MulticastListener implements Listener {
|
||||
private final List<Listener> listeners = new ArrayList<Listener>();
|
||||
|
||||
public void addListener(Listener l) {
|
||||
listeners.add(l);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Listener methods
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public void suiteIgnored(File suite) {
|
||||
for (Listener l : listeners) {
|
||||
l.suiteIgnored(suite);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suiteAdded(File suite) {
|
||||
for (Listener l : listeners) {
|
||||
l.suiteAdded(suite);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runStarted() {
|
||||
for (Listener l : listeners) {
|
||||
l.runStarted();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runFailed(Exception e) {
|
||||
for (Listener l : listeners) {
|
||||
l.runFailed(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runEndTime() {
|
||||
for (Listener l : listeners) {
|
||||
l.runEndTime();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runStopped() {
|
||||
for (Listener l : listeners) {
|
||||
l.runStopped();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanOutputStart(File outputDirectory) {
|
||||
for (Listener l : listeners) {
|
||||
l.cleanOutputStart(outputDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanOutputFailed(File outputDirectory, IOException e) {
|
||||
for (Listener l : listeners) {
|
||||
l.cleanOutputFailed(outputDirectory, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanOutputStop(File outputDirectory) {
|
||||
for (Listener l : listeners) {
|
||||
l.cleanOutputStop(outputDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void webappStopping(String tomcatStopCommand) {
|
||||
for (Listener l : listeners) {
|
||||
l.webappStopping(tomcatStopCommand);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void webappStopFailed(int returnCode) {
|
||||
for (Listener l : listeners) {
|
||||
l.webappStopFailed(returnCode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void webappStopped() {
|
||||
for (Listener l : listeners) {
|
||||
l.webappStopped();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dropDatabaseStarting(String statement) {
|
||||
for (Listener l : listeners) {
|
||||
l.dropDatabaseStarting(statement);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dropDatabaseFailed(int returnCode) {
|
||||
for (Listener l : listeners) {
|
||||
l.dropDatabaseFailed(returnCode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dropDatabaseComplete() {
|
||||
for (Listener l : listeners) {
|
||||
l.dropDatabaseComplete();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadDatabaseStarting(String statement) {
|
||||
for (Listener l : listeners) {
|
||||
l.loadDatabaseStarting(statement);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadDatabaseFailed(int returnCode) {
|
||||
for (Listener l : listeners) {
|
||||
l.loadDatabaseFailed(returnCode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadDatabaseComplete() {
|
||||
for (Listener l : listeners) {
|
||||
l.loadDatabaseComplete();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void webappCheckingReady(String command) {
|
||||
for (Listener l : listeners) {
|
||||
l.webappCheckingReady(command);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void webappCheckReadyFailed(int returnCode) {
|
||||
for (Listener l : listeners) {
|
||||
l.webappCheckReadyFailed(returnCode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void webappCheckedReady() {
|
||||
for (Listener l : listeners) {
|
||||
l.webappCheckedReady();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void webappStarting(String tomcatStartCommand) {
|
||||
for (Listener l : listeners) {
|
||||
l.webappStarting(tomcatStartCommand);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void webappStartFailed(int returnCode) {
|
||||
for (Listener l : listeners) {
|
||||
l.webappStartFailed(returnCode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void webappStarted() {
|
||||
for (Listener l : listeners) {
|
||||
l.webappStarted();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subProcessStart(List<String> command) {
|
||||
for (Listener l : listeners) {
|
||||
l.subProcessStart(command);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subProcessStartInBackground(List<String> command) {
|
||||
for (Listener l : listeners) {
|
||||
l.subProcessStartInBackground(command);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subProcessStdout(String string) {
|
||||
for (Listener l : listeners) {
|
||||
l.subProcessStdout(string);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subProcessErrout(String string) {
|
||||
for (Listener l : listeners) {
|
||||
l.subProcessErrout(string);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subProcessStop(List<String> command) {
|
||||
for (Listener l : listeners) {
|
||||
l.subProcessStop(command);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suiteStarted(File suiteDir) {
|
||||
for (Listener l : listeners) {
|
||||
l.suiteStarted(suiteDir);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suiteTestingStarted(File suiteDir) {
|
||||
for (Listener l : listeners) {
|
||||
l.suiteTestingStarted(suiteDir);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suiteFailed(File suiteDir, int returnCode) {
|
||||
for (Listener l : listeners) {
|
||||
l.suiteFailed(suiteDir, returnCode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suiteFailed(File suiteDir, Exception e) {
|
||||
for (Listener l : listeners) {
|
||||
l.suiteFailed(suiteDir, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suiteTestingStopped(File suiteDir) {
|
||||
for (Listener l : listeners) {
|
||||
l.suiteTestingStopped(suiteDir);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suiteStopped(File suiteDir) {
|
||||
for (Listener l : listeners) {
|
||||
l.suiteStopped(suiteDir);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanUploadStart(File uploadDirectory) {
|
||||
for (Listener l : listeners) {
|
||||
l.cleanUploadStart(uploadDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanUploadFailed(File uploadDirectory, IOException e) {
|
||||
for (Listener l : listeners) {
|
||||
l.cleanUploadFailed(uploadDirectory, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanUploadStop(File uploadDirectory) {
|
||||
for (Listener l : listeners) {
|
||||
l.cleanUploadStop(uploadDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logWarning(String message) {
|
||||
for (Listener l : listeners) {
|
||||
l.logWarning(message);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,312 +0,0 @@
|
|||
/* $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.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import edu.cornell.mannlib.vitro.utilities.testrunner.FileHelper;
|
||||
import edu.cornell.mannlib.vitro.utilities.testrunner.listener.Listener;
|
||||
|
||||
public class OutputDataListener implements Listener {
|
||||
private boolean runCompleted;
|
||||
private long startTime;
|
||||
private long endTime;
|
||||
|
||||
private ProcessOutput currentSuiteOutput = new ProcessOutput("");
|
||||
private Map<String, ProcessOutput> failureMessages = new HashMap<String, ProcessOutput>();
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Listener methods that affect the data model
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public void runStarted() {
|
||||
System.out.println("run started");
|
||||
startTime = new Date().getTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runEndTime() {
|
||||
endTime = new Date().getTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runStopped() {
|
||||
runCompleted = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suiteStarted(File suiteDir) {
|
||||
currentSuiteOutput = new ProcessOutput(FileHelper.baseName(suiteDir));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suiteStopped(File suiteDir) {
|
||||
if (currentSuiteOutput.isSuiteFailure()) {
|
||||
failureMessages.put(currentSuiteOutput.suiteName,
|
||||
currentSuiteOutput);
|
||||
}
|
||||
currentSuiteOutput = new ProcessOutput("");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subProcessStdout(String string) {
|
||||
currentSuiteOutput.addStdout(string);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subProcessErrout(String string) {
|
||||
currentSuiteOutput.addErrout(string);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// A class that holds a snapshot of the data.
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* A snapshot of the data that the listener has accumulated so far.
|
||||
*/
|
||||
public static class Info {
|
||||
public static Info EMPTY_INFO = new Info();
|
||||
|
||||
private final boolean runCompleted;
|
||||
private final long startTime;
|
||||
private final long endTime;
|
||||
private final Map<String, ProcessOutput> failureMessages;
|
||||
|
||||
Info() {
|
||||
this.runCompleted = false;
|
||||
this.startTime = 0;
|
||||
this.endTime = 0;
|
||||
this.failureMessages = Collections.emptyMap();
|
||||
}
|
||||
|
||||
Info(OutputDataListener parent) {
|
||||
this.runCompleted = parent.runCompleted;
|
||||
this.startTime = parent.startTime;
|
||||
this.endTime = parent.endTime;
|
||||
this.failureMessages = Collections
|
||||
.unmodifiableMap(new HashMap<String, ProcessOutput>(
|
||||
parent.failureMessages));
|
||||
}
|
||||
|
||||
public boolean isRunCompleted() {
|
||||
return runCompleted;
|
||||
}
|
||||
|
||||
public long getStartTime() {
|
||||
return startTime;
|
||||
}
|
||||
|
||||
public long getEndTime() {
|
||||
return endTime;
|
||||
}
|
||||
|
||||
public long getElapsedTime() {
|
||||
if ((startTime == 0) || (endTime == 0)) {
|
||||
return 0;
|
||||
} else {
|
||||
return endTime - startTime;
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, ProcessOutput> getFailureMessages() {
|
||||
return failureMessages;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a snapshot of the data.
|
||||
*/
|
||||
public Info getInfo() {
|
||||
return new Info(this);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// A class that summarized the sub-process output from a test suite.
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* The output from a subprocess that runs a test suite. It's only
|
||||
* interesting if it indicates a suite failure.
|
||||
*/
|
||||
public static class ProcessOutput {
|
||||
private static final String SUITE_FAILURE_PATTERN = "exception|error(?i)";
|
||||
private final String suiteName;
|
||||
private final StringBuilder stdout = new StringBuilder();
|
||||
private final StringBuilder errout = new StringBuilder();
|
||||
|
||||
public ProcessOutput(String suiteName) {
|
||||
this.suiteName = suiteName;
|
||||
}
|
||||
|
||||
public void addStdout(String string) {
|
||||
stdout.append(string);
|
||||
}
|
||||
|
||||
public void addErrout(String string) {
|
||||
errout.append(string);
|
||||
}
|
||||
|
||||
public String getSuiteName() {
|
||||
return suiteName;
|
||||
}
|
||||
|
||||
public String getStdout() {
|
||||
return stdout.toString();
|
||||
}
|
||||
|
||||
public String getErrout() {
|
||||
return errout.toString();
|
||||
}
|
||||
|
||||
public boolean isSuiteFailure() {
|
||||
Pattern p = Pattern.compile(SUITE_FAILURE_PATTERN);
|
||||
Matcher m = p.matcher(errout);
|
||||
return m.find();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Listener methods that don't affect the data model
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public void suiteAdded(File suite) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suiteIgnored(File suite) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runFailed(Exception e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanOutputStart(File outputDirectory) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanOutputFailed(File outputDirectory, IOException e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanOutputStop(File outputDirectory) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void webappCheckingReady(String command) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void webappCheckReadyFailed(int returnCode) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void webappCheckedReady() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void webappStopping(String tomcatStopCommand) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void webappStopFailed(int returnCode) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void webappStopped() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dropDatabaseStarting(String statement) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dropDatabaseFailed(int returnCode) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dropDatabaseComplete() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadDatabaseStarting(String statement) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadDatabaseFailed(int returnCode) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadDatabaseComplete() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void webappStarting(String tomcatStartCommand) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void webappStartFailed(int returnCode) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void webappStarted() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subProcessStart(List<String> command) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subProcessStartInBackground(List<String> command) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subProcessStop(List<String> command) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suiteTestingStarted(File suiteDir) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suiteFailed(File suiteDir, int returnCode) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suiteFailed(File suiteDir, Exception e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suiteTestingStopped(File suiteDir) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanUploadStart(File uploadDirectory) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanUploadFailed(File uploadDirectory, IOException e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanUploadStop(File uploadDirectory) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logWarning(String message) {
|
||||
}
|
||||
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
/* $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.FileFilter;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import edu.cornell.mannlib.vitro.utilities.testrunner.FileHelper;
|
||||
import edu.cornell.mannlib.vitro.utilities.testrunner.LogStats;
|
||||
import edu.cornell.mannlib.vitro.utilities.testrunner.SeleniumRunnerParameters;
|
||||
import edu.cornell.mannlib.vitro.utilities.testrunner.datamodel.DataModel;
|
||||
|
||||
/**
|
||||
* Manages the contents of the output area. Removes old files prior to a run.
|
||||
* Creates a unified summary of the test suite outputs.
|
||||
*/
|
||||
public class OutputManager {
|
||||
private final SeleniumRunnerParameters parms;
|
||||
private final OutputDataListener dataListener;
|
||||
|
||||
public OutputManager(SeleniumRunnerParameters parms) {
|
||||
this.parms = parms;
|
||||
this.dataListener = new OutputDataListener();
|
||||
parms.addListener(this.dataListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete any output files from previous runs.
|
||||
*/
|
||||
public void cleanOutputDirectory() throws IOException {
|
||||
File outputDirectory = parms.getOutputDirectory();
|
||||
parms.getListener().cleanOutputStart(outputDirectory);
|
||||
|
||||
try {
|
||||
for (File file : outputDirectory.listFiles()) {
|
||||
// Skip the log file, since we are already over-writing it.
|
||||
if (file.equals(parms.getLogFile())) {
|
||||
continue;
|
||||
}
|
||||
// Skip any hidden files (like .svn)
|
||||
if (file.getPath().startsWith(".")) {
|
||||
continue;
|
||||
}
|
||||
// Delete all of the others.
|
||||
if (file.isFile()) {
|
||||
FileHelper.deleteFile(file);
|
||||
} else {
|
||||
FileHelper.purgeDirectoryRecursively(file);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
parms.getListener().cleanOutputFailed(outputDirectory, e);
|
||||
throw e;
|
||||
} finally {
|
||||
parms.getListener().cleanOutputStop(outputDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse each of the output files from the test suites, and create a unified
|
||||
* output file.
|
||||
*/
|
||||
public void summarizeOutput(DataModel dataModel) {
|
||||
try {
|
||||
LogStats log = LogStats.parse(parms.getLogFile());
|
||||
|
||||
List<SuiteResults> suiteResults = new ArrayList<SuiteResults>();
|
||||
for (File outputFile : parms.getOutputDirectory().listFiles(
|
||||
new HtmlFileFilter())) {
|
||||
SuiteResults suite = SuiteResults.parse(parms, outputFile);
|
||||
if (suite != null) {
|
||||
suiteResults.add(suite);
|
||||
}
|
||||
}
|
||||
|
||||
dataModel.setSuiteResults(suiteResults);
|
||||
dataModel.captureDataListener(dataListener);
|
||||
|
||||
OutputSummaryFormatter formatter = new OutputSummaryFormatter(parms);
|
||||
formatter.format(log, dataModel);
|
||||
} catch (Exception e) {
|
||||
// It must be impossible to throw an exception from here, so just
|
||||
// print it to sysout.
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static class HtmlFileFilter implements FileFilter {
|
||||
public boolean accept(File path) {
|
||||
return path.getName().endsWith(".html")
|
||||
|| path.getName().endsWith(".htm");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,375 +0,0 @@
|
|||
/* $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> </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/> <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/> <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>";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,188 +0,0 @@
|
|||
/* $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.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import edu.cornell.mannlib.vitro.utilities.testrunner.FileHelper;
|
||||
import edu.cornell.mannlib.vitro.utilities.testrunner.IgnoredTests;
|
||||
import edu.cornell.mannlib.vitro.utilities.testrunner.SeleniumRunnerParameters;
|
||||
import edu.cornell.mannlib.vitro.utilities.testrunner.Status;
|
||||
|
||||
/**
|
||||
* Extract any summary information from an HTML output file, produced by a test
|
||||
* suite.
|
||||
*/
|
||||
public class SuiteResults {
|
||||
/**
|
||||
* If the file doesn't contain a line that includes this pattern, it is not
|
||||
* a suite output file.
|
||||
*/
|
||||
private static final Pattern TITLE_LINE_PATTERN = Pattern
|
||||
.compile("<title>Test suite results</title>");
|
||||
|
||||
/**
|
||||
* A test line looks something like this example:
|
||||
*/
|
||||
public static final String EXAMPLE_TEST_LINE = ""
|
||||
+ "<pre><tr class=\" status_passed\"><td><a href=\"#testresult0\">MyTest</a></td></tr></pre>";
|
||||
|
||||
/**
|
||||
* So here is the pattern to match it:
|
||||
*/
|
||||
private static final Pattern TEST_LINE_PATTERN = Pattern
|
||||
.compile("<tr class=\"\\s*(\\w+)\"><td><a href=\"(#\\w+)\">([^<]*)</a></td></tr>");
|
||||
|
||||
/**
|
||||
* Parse the fields from this file and attempt to produce a
|
||||
* {@link SuiteResults} object. If this is not an appropriate file, just
|
||||
* return null.
|
||||
*/
|
||||
public static SuiteResults parse(SeleniumRunnerParameters parms,
|
||||
File outputFile) {
|
||||
IgnoredTests ignoredTests = parms.getIgnoredTests();
|
||||
|
||||
boolean isSuiteOutputFile = false;
|
||||
Status status = Status.ERROR;
|
||||
|
||||
List<TestResults> tests = new ArrayList<TestResults>();
|
||||
String suiteName = FileHelper.baseName(outputFile);
|
||||
String outputLink = outputFile.getName();
|
||||
|
||||
BufferedReader reader = null;
|
||||
String line;
|
||||
try {
|
||||
reader = new BufferedReader(new FileReader(outputFile));
|
||||
while (null != (line = reader.readLine())) {
|
||||
if (TITLE_LINE_PATTERN.matcher(line).find()) {
|
||||
isSuiteOutputFile = true;
|
||||
}
|
||||
|
||||
Matcher m;
|
||||
m = TEST_LINE_PATTERN.matcher(line);
|
||||
if (m.matches()) {
|
||||
String testName = m.group(3);
|
||||
String testLink = outputLink + m.group(2);
|
||||
|
||||
Status testStatus;
|
||||
if ("status_passed".equals(m.group(1))) {
|
||||
testStatus = Status.OK;
|
||||
} else if (ignoredTests.isIgnored(suiteName, testName)) {
|
||||
testStatus = Status.IGNORED;
|
||||
} else {
|
||||
testStatus = Status.ERROR;
|
||||
}
|
||||
|
||||
tests.add(new TestResults(testName, suiteName, testLink,
|
||||
testStatus));
|
||||
}
|
||||
}
|
||||
|
||||
status = Status.OK;
|
||||
for (TestResults t : tests) {
|
||||
status = Status.combine(status, t.status);
|
||||
}
|
||||
|
||||
if (isSuiteOutputFile) {
|
||||
return new SuiteResults(suiteName, outputLink, tests, status);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
// Can't give up - I need to create as much output as I can.
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
} finally {
|
||||
if (reader != null) {
|
||||
try {
|
||||
reader.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final String suiteName;
|
||||
private final String outputLink;
|
||||
private final Map<String, TestResults> testMap;
|
||||
private final Status status;
|
||||
|
||||
public SuiteResults(String suiteName, String outputLink,
|
||||
List<TestResults> tests, Status status) {
|
||||
this.suiteName = suiteName;
|
||||
this.outputLink = outputLink;
|
||||
this.status = status;
|
||||
|
||||
Map<String, TestResults> map = new HashMap<String, TestResults>();
|
||||
for (TestResults t : tests) {
|
||||
map.put(t.getTestName(), t);
|
||||
}
|
||||
testMap = Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return suiteName;
|
||||
}
|
||||
|
||||
public Status getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public String getOutputLink() {
|
||||
return outputLink;
|
||||
}
|
||||
|
||||
public Collection<TestResults> getTests() {
|
||||
return Collections.unmodifiableCollection(testMap.values());
|
||||
}
|
||||
|
||||
public TestResults getTest(String testName) {
|
||||
return testMap.get(testName);
|
||||
}
|
||||
|
||||
public static class TestResults {
|
||||
private final String name;
|
||||
private final String suite;
|
||||
private final String outputLink;
|
||||
private final Status status;
|
||||
|
||||
public TestResults(String name, String suite, String outputLink,
|
||||
Status status) {
|
||||
this.name = name;
|
||||
this.suite = suite;
|
||||
this.outputLink = outputLink;
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public Status getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public String getSuiteName() {
|
||||
return suite;
|
||||
}
|
||||
|
||||
public String getTestName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getOutputLink() {
|
||||
return outputLink;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,115 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
/*
|
||||
Formats for the output summary from the acceptance tests.
|
||||
*/
|
||||
body {
|
||||
background: rgb(95%, 95%, 95%);
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
.heading {
|
||||
border: groove;
|
||||
background: white;
|
||||
padding: 10px 20px 8px 20px;
|
||||
margin-top: 50px;
|
||||
font-size: large;
|
||||
}
|
||||
|
||||
table {
|
||||
border: thin double gray;
|
||||
background: white;
|
||||
}
|
||||
|
||||
td,th {
|
||||
padding: 4px 12px 2px 12px;
|
||||
}
|
||||
|
||||
th {
|
||||
border-bottom: 1px solid black;
|
||||
}
|
||||
|
||||
table.summary {
|
||||
border: none;
|
||||
background: inherit;
|
||||
}
|
||||
|
||||
table.summary td {
|
||||
padding-right: 30;
|
||||
border: none;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
table.tallys td {
|
||||
align: right;
|
||||
}
|
||||
|
||||
table.tallys td.total {
|
||||
font.weight: bold;
|
||||
}
|
||||
|
||||
.section {
|
||||
background: rgb(70%, 85%, 85%);
|
||||
font-size: larger;
|
||||
margin: 50px 0px 15px 0px;
|
||||
padding: 4px 12px 2px 12px;
|
||||
}
|
||||
|
||||
.good {
|
||||
background: rgb(60%, 100%, 60%);
|
||||
}
|
||||
|
||||
.bad {
|
||||
background: rgb(100%, 60%, 60%);
|
||||
}
|
||||
|
||||
.fair {
|
||||
background: rgb(100%, 100%, 60%);
|
||||
}
|
||||
|
||||
.pending {
|
||||
background: rgb(90%, 90%, 100%);
|
||||
}
|
||||
|
||||
.one-word {
|
||||
width: 20%;
|
||||
text-align: center;
|
||||
margin: 15px 0px 0px 0px;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
table.condensed td {
|
||||
border: 1px solid grey;
|
||||
padding: 10px 5px 10px 5px;
|
||||
}
|
||||
|
||||
table.condensed div.suite {
|
||||
font-size: 85%;
|
||||
font-weight: bold;
|
||||
padding: 3px 3px 3px 3px;
|
||||
}
|
||||
|
||||
table.condensed div.reason {
|
||||
font-size: 70%;
|
||||
font-style: italic;
|
||||
padding: 3px 3px 3px 30px;
|
||||
}
|
||||
|
||||
table.condensed div.test {
|
||||
font-size: 70%;
|
||||
padding: 3px 3px 3px 15px;
|
||||
}
|
||||
|
||||
table.condensed div.test div.tReason{
|
||||
font-style: italic;
|
||||
padding: 3px 3px 3px 10px;
|
||||
}
|
||||
|
||||
table.ignored td {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
pre.log {
|
||||
font-family: monospace;
|
||||
font-size: 80%;
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
|
||||
xmlns:owl="http://www.w3.org/2002/07/owl#"
|
||||
xmlns:vitro="http://vitro.mannlib.cornell.edu/ns/vitro/0.7#"
|
||||
xmlns:auth="http://vitro.mannlib.cornell.edu/ns/vitro/authorization#"
|
||||
xmlns="http://vitro.mannlib.cornell.edu/ns/vitro/default#"
|
||||
xml:base="http://vitro.mannlib.cornell.edu/ns/vitro/default">
|
||||
|
||||
<auth:UserAccount rdf:about="http://vivo.mydomain.edu/individual/TestAdmin">
|
||||
<auth:emailAddress rdf:datatype="http://www.w3.org/2001/XMLSchema#string">testAdmin@cornell.edu</auth:emailAddress>
|
||||
<auth:externalAuthId rdf:datatype="http://www.w3.org/2001/XMLSchema#string">testAdmin</auth:externalAuthId>
|
||||
<auth:firstName rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Test</auth:firstName>
|
||||
<auth:lastName rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Admin</auth:lastName>
|
||||
<auth:md5password rdf:datatype="http://www.w3.org/2001/XMLSchema#string">DC647EB65E6711E155375218212B3964</auth:md5password>
|
||||
<auth:status rdf:datatype="http://www.w3.org/2001/XMLSchema#string">ACTIVE</auth:status>
|
||||
<auth:loginCount rdf:datatype="http://www.w3.org/2001/XMLSchema#int">1</auth:loginCount>
|
||||
<auth:passwordLinkExpires rdf:datatype="http://www.w3.org/2001/XMLSchema#long">0</auth:passwordLinkExpires>
|
||||
<auth:hasPermissionSet rdf:resource="http://vitro.mannlib.cornell.edu/ns/vitro/authorization#ADMIN"/>
|
||||
</auth:UserAccount>
|
||||
|
||||
<auth:UserAccount rdf:about="http://vivo.mydomain.edu/individual/JohnCurator">
|
||||
<auth:emailAddress rdf:datatype="http://www.w3.org/2001/XMLSchema#string">johnCurator@cornell.edu</auth:emailAddress>
|
||||
<auth:externalAuthId rdf:datatype="http://www.w3.org/2001/XMLSchema#string">johnCurator</auth:externalAuthId>
|
||||
<auth:firstName rdf:datatype="http://www.w3.org/2001/XMLSchema#string">John</auth:firstName>
|
||||
<auth:lastName rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Curator</auth:lastName>
|
||||
<auth:md5password rdf:datatype="http://www.w3.org/2001/XMLSchema#string">DC647EB65E6711E155375218212B3964</auth:md5password>
|
||||
<auth:status rdf:datatype="http://www.w3.org/2001/XMLSchema#string">ACTIVE</auth:status>
|
||||
<auth:loginCount rdf:datatype="http://www.w3.org/2001/XMLSchema#int">1</auth:loginCount>
|
||||
<auth:passwordLinkExpires rdf:datatype="http://www.w3.org/2001/XMLSchema#long">0</auth:passwordLinkExpires>
|
||||
<auth:hasPermissionSet rdf:resource="http://vitro.mannlib.cornell.edu/ns/vitro/authorization#CURATOR"/>
|
||||
</auth:UserAccount>
|
||||
|
||||
<auth:UserAccount rdf:about="http://vivo.mydomain.edu/individual/SallyEditor">
|
||||
<auth:emailAddress rdf:datatype="http://www.w3.org/2001/XMLSchema#string">sallyEditor@cornell.edu</auth:emailAddress>
|
||||
<auth:externalAuthId rdf:datatype="http://www.w3.org/2001/XMLSchema#string">sallyEditor</auth:externalAuthId>
|
||||
<auth:firstName rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Sally</auth:firstName>
|
||||
<auth:lastName rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Editor</auth:lastName>
|
||||
<auth:md5password rdf:datatype="http://www.w3.org/2001/XMLSchema#string">DC647EB65E6711E155375218212B3964</auth:md5password>
|
||||
<auth:status rdf:datatype="http://www.w3.org/2001/XMLSchema#string">ACTIVE</auth:status>
|
||||
<auth:loginCount rdf:datatype="http://www.w3.org/2001/XMLSchema#int">1</auth:loginCount>
|
||||
<auth:passwordLinkExpires rdf:datatype="http://www.w3.org/2001/XMLSchema#long">0</auth:passwordLinkExpires>
|
||||
<auth:hasPermissionSet rdf:resource="http://vitro.mannlib.cornell.edu/ns/vitro/authorization#EDITOR"/>
|
||||
</auth:UserAccount>
|
||||
|
||||
<auth:UserAccount rdf:about="http://vivo.mydomain.edu/individual/JoeUser">
|
||||
<auth:emailAddress rdf:datatype="http://www.w3.org/2001/XMLSchema#string">joeUser@cornell.edu</auth:emailAddress>
|
||||
<auth:externalAuthId rdf:datatype="http://www.w3.org/2001/XMLSchema#string">joeUser</auth:externalAuthId>
|
||||
<auth:firstName rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Joe</auth:firstName>
|
||||
<auth:lastName rdf:datatype="http://www.w3.org/2001/XMLSchema#string">User</auth:lastName>
|
||||
<auth:md5password rdf:datatype="http://www.w3.org/2001/XMLSchema#string">DC647EB65E6711E155375218212B3964</auth:md5password>
|
||||
<auth:status rdf:datatype="http://www.w3.org/2001/XMLSchema#string">ACTIVE</auth:status>
|
||||
<auth:loginCount rdf:datatype="http://www.w3.org/2001/XMLSchema#int">1</auth:loginCount>
|
||||
<auth:passwordLinkExpires rdf:datatype="http://www.w3.org/2001/XMLSchema#long">0</auth:passwordLinkExpires>
|
||||
<auth:hasPermissionSet rdf:resource="http://vitro.mannlib.cornell.edu/ns/vitro/authorization#SELF_EDITOR"/>
|
||||
</auth:UserAccount>
|
||||
|
||||
</rdf:RDF>
|
|
@ -1,191 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.utilities.testrunner;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertFalse;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import edu.cornell.mannlib.vitro.utilities.testrunner.IgnoredTests.IgnoredTestInfo;
|
||||
|
||||
/**
|
||||
* Check that the ignored_tests.txt file is being parsed correctly.
|
||||
*/
|
||||
public class IgnoredTestsTest {
|
||||
private static final String TEST_WITH_REASON = "test with reason";
|
||||
private static final String TEST_NO_REASON = "test with no reason";
|
||||
private static final String TEST_NOT_IGNORED = "test not ignored";
|
||||
private static final String TEST_FROM_IGNORED_SUITE = "test from ignored suite";
|
||||
private static final String SUITE_WITH_TESTS = "suite with tests";
|
||||
private static final String SUITE_WITH_REASON = "entire suite with reason";
|
||||
private static final String SUITE_NO_REASON = "entire suite with no reason";
|
||||
private static final String SUITE_NOT_IGNORED = "entire suite not ignored";
|
||||
private static final String REASON_FOR_TEST = "the reason for the test";
|
||||
private static final String REASON_FOR_SUITE = "the reason for the suite";
|
||||
private static final String NO_REASON = "";
|
||||
|
||||
private static final String FILE_CONTENTS = "# This line is a comment \n"
|
||||
+ "! This line is also, and so is the blank one\n"
|
||||
+ "\n"
|
||||
+ (SUITE_WITH_TESTS + ", " + TEST_NO_REASON + "\n")
|
||||
+ (SUITE_WITH_TESTS + ", " + TEST_WITH_REASON + " # "
|
||||
+ REASON_FOR_TEST + "\n") + (SUITE_NO_REASON + ", *\n")
|
||||
+ (SUITE_WITH_REASON + ", * # " + REASON_FOR_SUITE + "\n");
|
||||
|
||||
private static final String BAD_CONTENTS = "suite but no test # doesn't match.";
|
||||
|
||||
/*
|
||||
* Ignore any blank line, or any line starting with '#' or '!' </p> <p> Each
|
||||
* other line describes an ignored test. The line contains the suite name, a
|
||||
* comma (with optional space), the test name (with optional space) and
|
||||
* optionally a comment, starting with a '#'. </p> If the test name is an
|
||||
* asterisk '*', then the entire suite will be ignored. <p>
|
||||
*/
|
||||
|
||||
private static File ignoreFile;
|
||||
private static File badFile;
|
||||
|
||||
@BeforeClass
|
||||
public static void initializeTheFile() throws IOException {
|
||||
ignoreFile = File.createTempFile("IgnoredTestsTest", "");
|
||||
|
||||
Writer writer = new FileWriter(ignoreFile);
|
||||
try {
|
||||
writer.write(FILE_CONTENTS);
|
||||
} finally {
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void initializeBadFile() throws IOException {
|
||||
badFile = File.createTempFile("IgnoredTestsTest", "");
|
||||
|
||||
Writer writer = new FileWriter(badFile);
|
||||
try {
|
||||
writer.write(BAD_CONTENTS);
|
||||
} finally {
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void cleanup() throws IOException {
|
||||
ignoreFile.delete();
|
||||
badFile.delete();
|
||||
}
|
||||
|
||||
private IgnoredTests ignored;
|
||||
|
||||
@Before
|
||||
public void readTheFile() {
|
||||
ignored = new IgnoredTests(ignoreFile);
|
||||
}
|
||||
|
||||
@Test(expected = FatalException.class)
|
||||
public void readBadFile() {
|
||||
new IgnoredTests(badFile);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getList() {
|
||||
Set<IgnoredTestInfo> expected = new HashSet<IgnoredTestInfo>();
|
||||
expected.add(new IgnoredTestInfo(SUITE_WITH_TESTS, TEST_NO_REASON,
|
||||
NO_REASON));
|
||||
expected.add(new IgnoredTestInfo(SUITE_WITH_TESTS, TEST_WITH_REASON,
|
||||
REASON_FOR_TEST));
|
||||
expected.add(new IgnoredTestInfo(SUITE_NO_REASON, "*", NO_REASON));
|
||||
expected.add(new IgnoredTestInfo(SUITE_WITH_REASON, "*",
|
||||
REASON_FOR_SUITE));
|
||||
Set<IgnoredTestInfo> actual = new HashSet<IgnoredTestInfo>(
|
||||
ignored.getList());
|
||||
assertEquals("list of tests", expected, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isIgnoredTestYes() {
|
||||
assertTrue("ignored test",
|
||||
ignored.isIgnored(SUITE_WITH_TESTS, TEST_NO_REASON));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isIgnoredTestNo() {
|
||||
assertFalse("not ignored test",
|
||||
ignored.isIgnored(SUITE_WITH_TESTS, TEST_NOT_IGNORED));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isIgnoredTestFromSuite() {
|
||||
assertTrue("test from ignored suite",
|
||||
ignored.isIgnored(SUITE_WITH_REASON, TEST_FROM_IGNORED_SUITE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getReasonTestYes() {
|
||||
assertEquals(
|
||||
"test with reason",
|
||||
REASON_FOR_TEST,
|
||||
ignored.getReasonForIgnoring(SUITE_WITH_TESTS, TEST_WITH_REASON));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getReasonTestNo() {
|
||||
assertEquals(
|
||||
"test not ignored",
|
||||
NO_REASON,
|
||||
ignored.getReasonForIgnoring(SUITE_WITH_TESTS, TEST_NOT_IGNORED));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getReasonTestNoReason() {
|
||||
assertEquals("test with no reason", NO_REASON,
|
||||
ignored.getReasonForIgnoring(SUITE_WITH_TESTS, TEST_NO_REASON));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getReasonTestFromSuite() {
|
||||
assertEquals("test from ignored suite", REASON_FOR_SUITE,
|
||||
ignored.getReasonForIgnoring(SUITE_WITH_REASON,
|
||||
TEST_FROM_IGNORED_SUITE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isIgnoredSuiteYes() {
|
||||
assertTrue("ignored suite", ignored.isIgnored(SUITE_WITH_REASON));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isIgnoredSuiteNo() {
|
||||
assertFalse("not ignored suite", ignored.isIgnored(SUITE_NOT_IGNORED));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getReasonSuiteYes() {
|
||||
assertEquals("suite with reason", REASON_FOR_SUITE,
|
||||
ignored.getReasonForIgnoring(SUITE_WITH_REASON));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getReasonSuiteNo() {
|
||||
assertEquals("suite not ignored", NO_REASON,
|
||||
ignored.getReasonForIgnoring(SUITE_NOT_IGNORED));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getReasonSuiteNoReason() {
|
||||
assertEquals("suite with no reason", NO_REASON,
|
||||
ignored.getReasonForIgnoring(SUITE_NO_REASON));
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue