NIHVIVO-222 First step at coding the Java-based SeleniumRunner.
This commit is contained in:
parent
a8cfc10b2e
commit
72ee86f0a7
8 changed files with 769 additions and 0 deletions
|
@ -0,0 +1,167 @@
|
||||||
|
/* $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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <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 int returnCode;
|
||||||
|
private String stdOut = "";
|
||||||
|
private String stdErr = "";
|
||||||
|
private File workingDirectory;
|
||||||
|
|
||||||
|
/* Gets informed of output as it arrives. Never null. */
|
||||||
|
private final Logger logger;
|
||||||
|
|
||||||
|
private final Map<String, String> environmentAdditions = new HashMap<String, String>();
|
||||||
|
|
||||||
|
public CommandRunner(SeleniumRunnerParameters parms) {
|
||||||
|
this.logger = parms.getLogger();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 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 {
|
||||||
|
logger.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();
|
||||||
|
this.stdOut = outputEater.getContents();
|
||||||
|
|
||||||
|
errorEater.join();
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
logger.subProcessStop(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getReturnCode() {
|
||||||
|
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 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.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
int howMany = 0;
|
||||||
|
while (true) {
|
||||||
|
howMany = stream.read(buffer);
|
||||||
|
if (howMany > 0) {
|
||||||
|
String string = new String(buffer, 0, howMany);
|
||||||
|
contents.write(string);
|
||||||
|
|
||||||
|
if (isError) {
|
||||||
|
logger.subProcessErrout(string);
|
||||||
|
} else {
|
||||||
|
logger.subProcessStdout(string);
|
||||||
|
}
|
||||||
|
} else if (howMany == 0) {
|
||||||
|
Thread.yield();
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
stream.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContents() {
|
||||||
|
return contents.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.utilities.testrunner;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates a problem with the attempt to run a command in a sub-process.
|
||||||
|
*/
|
||||||
|
public class CommandRunnerException extends Exception {
|
||||||
|
|
||||||
|
public CommandRunnerException() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandRunnerException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandRunnerException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandRunnerException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,117 @@
|
||||||
|
/* $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.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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
public class Logger {
|
||||||
|
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat(
|
||||||
|
"yyyy-MM-dd HH:mm:ss.SSS");
|
||||||
|
|
||||||
|
private final Writer writer;
|
||||||
|
|
||||||
|
public Logger(PrintStream out) {
|
||||||
|
this.writer = new OutputStreamWriter(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Logger(File logFile) throws IOException {
|
||||||
|
this.writer = new FileWriter(logFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void runStarted() {
|
||||||
|
log("Run started.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void runStopped() {
|
||||||
|
log("Run stopped.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void subProcessStart(List<String> command) {
|
||||||
|
log("Subprocess started: " + command);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void subProcessStdout(String string) {
|
||||||
|
logRawText(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void subProcessErrout(String string) {
|
||||||
|
logRawText(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void subProcessStop(List<String> command) {
|
||||||
|
log("Subprocess stopped: " + command);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void suiteStarted(File suiteDir) {
|
||||||
|
log("Suite started: " + suiteDir.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void suiteFailed(File suiteDir, IOException e) {
|
||||||
|
log("Suite failed: " + suiteDir.getName());
|
||||||
|
log(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void suiteStopped(File suiteDir) {
|
||||||
|
log("Suite stopped: " + suiteDir.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cleanUploadStart(File uploadDirectory) {
|
||||||
|
log("Upload cleaning started: " + uploadDirectory.getPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cleanUploadFailed(File uploadDirectory, IOException e) {
|
||||||
|
log("Upload cleaning failed: " + uploadDirectory.getPath());
|
||||||
|
log(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cleanUploadStop(File uploadDirectory) {
|
||||||
|
log("Upload cleaning stopped: " + uploadDirectory.getPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.utilities.testrunner;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
public class ModelCleaner {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param parms
|
||||||
|
*/
|
||||||
|
public ModelCleaner(SeleniumRunnerParameters parms) {
|
||||||
|
// TODO Auto-generated constructor stub
|
||||||
|
throw new RuntimeException("ModelCleaner Constructor not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void clean() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
throw new RuntimeException("ModelCleaner.clean() not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,101 @@
|
||||||
|
/* $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.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the Selenium test suites. Provide the properties file and perhaps an
|
||||||
|
* "interactive" flag.
|
||||||
|
*/
|
||||||
|
public class SeleniumRunner {
|
||||||
|
private final SeleniumRunnerParameters parms;
|
||||||
|
private final Logger logger;
|
||||||
|
private final UploadAreaCleaner uploadCleaner;
|
||||||
|
private final ModelCleaner modelCleaner;
|
||||||
|
private final SuiteRunner suiteRunner;
|
||||||
|
|
||||||
|
public SeleniumRunner(SeleniumRunnerParameters parms) {
|
||||||
|
this.parms = parms;
|
||||||
|
this.logger = parms.getLogger();
|
||||||
|
this.uploadCleaner = new UploadAreaCleaner(parms);
|
||||||
|
this.modelCleaner = new ModelCleaner(parms);
|
||||||
|
this.suiteRunner = new SuiteRunner(parms);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void runSelectedSuites() {
|
||||||
|
logger.runStarted();
|
||||||
|
for (File suiteDir : parms.getSelectedSuites()) {
|
||||||
|
logger.suiteStarted(suiteDir);
|
||||||
|
try {
|
||||||
|
if (parms.isCleanModel()) {
|
||||||
|
modelCleaner.clean();
|
||||||
|
}
|
||||||
|
if (parms.isCleanUploads()) {
|
||||||
|
uploadCleaner.clean();
|
||||||
|
}
|
||||||
|
suiteRunner.runSuite(suiteDir);
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.suiteFailed(suiteDir, e);
|
||||||
|
}
|
||||||
|
logger.suiteStopped(suiteDir);
|
||||||
|
}
|
||||||
|
logger.runStopped();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void selectAllSuites(SeleniumRunnerParameters parms) {
|
||||||
|
List<File> suites = new ArrayList<File>();
|
||||||
|
for (File parentDir : parms.getSuiteParentDirectories()) {
|
||||||
|
suites.addAll(parms.findSuiteDirs(parentDir));
|
||||||
|
}
|
||||||
|
parms.setSelectedSuites(suites);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param args
|
||||||
|
*/
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SeleniumRunnerParameters parms = null;
|
||||||
|
boolean interactive = false;
|
||||||
|
|
||||||
|
if ((args.length != 1) && (args.length != 2)) {
|
||||||
|
usage("Wrong number of arguments.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.length == 2) {
|
||||||
|
if (!"interactive".equalsIgnoreCase(args[1])) {
|
||||||
|
usage("Invalid argument '" + args[1] + "'");
|
||||||
|
}
|
||||||
|
interactive = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
parms = new SeleniumRunnerParameters(args[0]);
|
||||||
|
} catch (IOException e) {
|
||||||
|
usage("Can't read properties file: " + e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interactive) {
|
||||||
|
// TODO hook up the GUI.
|
||||||
|
throw new RuntimeException("interactive mode not implemented.");
|
||||||
|
} else {
|
||||||
|
// Run all of the suites.
|
||||||
|
// For each suite, clean the model and the upload area.
|
||||||
|
selectAllSuites(parms);
|
||||||
|
parms.setCleanModel(true);
|
||||||
|
parms.setCleanUploads(true);
|
||||||
|
SeleniumRunner runner = new SeleniumRunner(parms);
|
||||||
|
runner.runSelectedSuites();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void usage(String message) {
|
||||||
|
System.out.println(message);
|
||||||
|
System.out.println("Usage is: SeleniumRunner <parameters_file> "
|
||||||
|
+ "[\"interactive\"]");
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,205 @@
|
||||||
|
/* $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.FileReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 {
|
||||||
|
private static final String PROP_OUTPUT_DIRECTORY = "output_directory";
|
||||||
|
private static final String PROP_UPLOAD_DIRECTORY = "upload_directory";
|
||||||
|
private static final String PROP_SUITE_DIRECTORIES = "suite_parent_directories";
|
||||||
|
|
||||||
|
private static final String LOGFILE_NAME = "log_file.txt";
|
||||||
|
|
||||||
|
private final File uploadDirectory;
|
||||||
|
private final File outputDirectory;
|
||||||
|
private final File logFile;
|
||||||
|
|
||||||
|
private final Collection<File> suiteParentDirectories;
|
||||||
|
|
||||||
|
private Collection<File> selectedSuites = Collections.emptySet();
|
||||||
|
private boolean cleanModel = true;
|
||||||
|
private boolean cleanUploads = true;
|
||||||
|
private Logger logger = new Logger(System.out);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the required properties from the property file, and do some checks
|
||||||
|
* on them.
|
||||||
|
*/
|
||||||
|
public SeleniumRunnerParameters(String propertiesFilepath)
|
||||||
|
throws IOException {
|
||||||
|
Reader propsReader = null;
|
||||||
|
try {
|
||||||
|
propsReader = new FileReader(new File(propertiesFilepath));
|
||||||
|
Properties props = new Properties();
|
||||||
|
props.load(propsReader);
|
||||||
|
|
||||||
|
this.uploadDirectory = checkReadWriteDirectory(props,
|
||||||
|
PROP_UPLOAD_DIRECTORY);
|
||||||
|
this.outputDirectory = checkReadWriteDirectory(props,
|
||||||
|
PROP_OUTPUT_DIRECTORY);
|
||||||
|
this.logFile = new File(this.outputDirectory, LOGFILE_NAME);
|
||||||
|
this.logger = new Logger(this.logFile);
|
||||||
|
|
||||||
|
this.suiteParentDirectories = checkSuiteParentDirectories(props);
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
if (propsReader != null) {
|
||||||
|
try {
|
||||||
|
propsReader.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that there is a property for the output directory, 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.");
|
||||||
|
}
|
||||||
|
|
||||||
|
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.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dir.canWrite()) {
|
||||||
|
throw new IllegalArgumentException("Directory " + key + " '"
|
||||||
|
+ value + "' is not writeable.");
|
||||||
|
}
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.");
|
||||||
|
}
|
||||||
|
if (!dir.isDirectory()) {
|
||||||
|
throw new IllegalArgumentException("Suite directory '"
|
||||||
|
+ dir.getPath() + "' is not a directory.");
|
||||||
|
}
|
||||||
|
if (!dir.canRead()) {
|
||||||
|
throw new IllegalArgumentException("Suite directory '"
|
||||||
|
+ dir.getPath() + "' is not readable.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Logger getLogger() {
|
||||||
|
return logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLogger(Logger logger) {
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public File getUploadDirectory() {
|
||||||
|
return uploadDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<File> getSuiteParentDirectories() {
|
||||||
|
return suiteParentDirectories;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelectedSuites(Collection<File> selectedSuites) {
|
||||||
|
this.selectedSuites = selectedSuites;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<File> getSelectedSuites() {
|
||||||
|
return new ArrayList<File>(this.selectedSuites);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
File suiteFile = new File(pathname, "Suite.html");
|
||||||
|
if (suiteFile.exists()) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
logger.subProcessErrout("Warning: suite file '" + suiteFile.getPath()
|
||||||
|
+ "' does not exist.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
/* $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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
public class SuiteRunner {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param parms
|
||||||
|
*/
|
||||||
|
public SuiteRunner(SeleniumRunnerParameters parms) {
|
||||||
|
// TODO Auto-generated constructor stub
|
||||||
|
throw new RuntimeException("SuiteRunner Constructor not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param suiteDir
|
||||||
|
*/
|
||||||
|
public void runSuite(File suiteDir) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
throw new RuntimeException("SuiteRunner.runSuite() not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
/* $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.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean out the file upload area, so the next suite will start with no uploads.
|
||||||
|
*/
|
||||||
|
public class UploadAreaCleaner {
|
||||||
|
private final SeleniumRunnerParameters parms;
|
||||||
|
private final Logger logger;
|
||||||
|
|
||||||
|
public UploadAreaCleaner(SeleniumRunnerParameters parms) {
|
||||||
|
this.parms = parms;
|
||||||
|
this.logger = parms.getLogger();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.");
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.cleanUploadStart(uploadDirectory);
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (File file : uploadDirectory.listFiles()) {
|
||||||
|
if (file.isFile()) {
|
||||||
|
deleteFile(file);
|
||||||
|
} else {
|
||||||
|
purgeDirectoryRecursively(uploadDirectory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.cleanUploadFailed(uploadDirectory, e);
|
||||||
|
throw e;
|
||||||
|
} finally {
|
||||||
|
logger.cleanUploadStop(uploadDirectory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete all of the files in a directory, any sub-directories, and the
|
||||||
|
* directory itself.
|
||||||
|
*/
|
||||||
|
protected 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a file, either before or after the test. If it can't be deleted,
|
||||||
|
* complain.
|
||||||
|
*/
|
||||||
|
protected 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()
|
||||||
|
+ "'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue