NIHVIVO-222 Use the OWL file of the test user model instead of a MySQL dump.

Embed the OWL file in the source, so we don't need to configure it. 
Break out a separate TomcatController class.
This commit is contained in:
jeb228 2010-08-18 16:38:01 +00:00
parent 60444bb7f8
commit 99c70b5d66
7 changed files with 294 additions and 161 deletions

View file

@ -193,6 +193,10 @@ public class Listener {
log("Upload cleaning stopped: " + uploadDirectory.getPath()); log("Upload cleaning stopped: " + uploadDirectory.getPath());
} }
public void logWarning(String message) {
log("WARNING: " + message);
}
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// Helper methods // Helper methods
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------

View file

@ -3,6 +3,8 @@
package edu.cornell.mannlib.vitro.utilities.testrunner; package edu.cornell.mannlib.vitro.utilities.testrunner;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -11,14 +13,18 @@ import java.util.List;
* test suite. * test suite.
*/ */
public class ModelCleaner { public class ModelCleaner {
public static final String TEST_USER_ONTOLOGY_FILENAME = "test-user-model.owl";
private final ModelCleanerProperties properties; private final ModelCleanerProperties properties;
private final TomcatController tomcatController;
private final CommandRunner runner; private final CommandRunner runner;
private final Listener listener; private final Listener listener;
public ModelCleaner(SeleniumRunnerParameters parms) { public ModelCleaner(SeleniumRunnerParameters parms,
TomcatController tomcatController) {
this.properties = parms.getModelCleanerProperties(); this.properties = parms.getModelCleanerProperties();
this.listener = parms.getListener(); this.listener = parms.getListener();
this.runner = new CommandRunner(parms); this.runner = new CommandRunner(parms);
this.tomcatController = tomcatController;
sanityCheck(); sanityCheck();
} }
@ -42,42 +48,39 @@ public class ModelCleaner {
* if a problem occurs in a sub-process. * if a problem occurs in a sub-process.
*/ */
public void clean() throws CommandRunnerException { public void clean() throws CommandRunnerException {
stopTheWebapp(); tomcatController.stopTheWebapp();
dropDatabase(); insertTheUserFile();
createAndLoadDatabase(); recreateTheDatabase();
startTheWebapp(); tomcatController.startTheWebapp();
removeTheUserFile();
} }
/** /**
* Stop Tomcat and wait the prescribed number of seconds for it to clean up. * Copy the test data ontology file into the auth area, so we get our
* pre-defined admin user.
*/ */
public void stopTheWebapp() throws CommandRunnerException { private void insertTheUserFile() {
String tomcatStopCommand = properties.getTomcatStopCommand(); InputStream userOntologyStream = this.getClass().getResourceAsStream(
int tomcatStopDelay = properties.getTomcatStopDelay(); TEST_USER_ONTOLOGY_FILENAME);
if (userOntologyStream == null) {
listener.webappStopping(tomcatStopCommand); throw new FatalException(
runner.run(parseCommandLine(tomcatStopCommand)); "Couldn't find the Test User Ontology file: '"
+ TEST_USER_ONTOLOGY_FILENAME + "'");
int returnCode = runner.getReturnCode();
if (returnCode != 0) {
listener.webappStopFailed(returnCode);
// Throw no exception - this can happen if Tomcat isn't running.
} }
listener.webappWaitingForStop(tomcatStopDelay); File userOntologyTarget = figureUserOntologyTarget();
try { try {
Thread.sleep(tomcatStopDelay * 1000L); FileHelper.copy(userOntologyStream, userOntologyTarget);
} catch (InterruptedException e) { userOntologyStream.close();
// Just continue. } catch (IOException e) {
e.printStackTrace();
} }
listener.webappStopped();
} }
/** /**
* Delete the database. * Drop the database and create it again, empty.
*/ */
private void dropDatabase() { private void recreateTheDatabase() {
String mysqlStatement = "drop database " + properties.getMysqlDbName() String mysqlStatement = "drop database " + properties.getMysqlDbName()
+ "; create database " + properties.getMysqlDbName() + "; create database " + properties.getMysqlDbName()
+ " character set utf8;"; + " character set utf8;";
@ -96,54 +99,15 @@ public class ModelCleaner {
} }
/** /**
* Rebuild the database. * Remove the test data ontology file, so we leave no trace.
*/ */
private void createAndLoadDatabase() { private void removeTheUserFile() {
String mysqlStatement = "source " File userOntologyTarget = figureUserOntologyTarget();
+ convertBackslashes(properties.getMysqlDumpfile()) + ";"; userOntologyTarget.delete();
if (userOntologyTarget.exists()) {
listener.loadDatabaseStarting(mysqlStatement); listener.logWarning("Failed to delete the test data ontology "
executeMysqlStatement(mysqlStatement); + "file: '" + TEST_USER_ONTOLOGY_FILENAME + "'");
int returnCode = runner.getReturnCode();
if (returnCode != 0) {
listener.loadDatabaseFailed(returnCode);
throw new FatalException("loadDatabase() failed: return code="
+ returnCode);
} }
listener.loadDatabaseComplete();
}
/**
* Start Tomcat and wait for it to initialize.
*/
private void startTheWebapp() {
String tomcatStartCommand = properties.getTomcatStartCommand();
int tomcatStartDelay = properties.getTomcatStartDelay();
listener.webappStarting(tomcatStartCommand);
try {
runner.runAsBackground(parseCommandLine(tomcatStartCommand));
} catch (CommandRunnerException e) {
throw new FatalException(e);
}
int returnCode = runner.getReturnCode();
if (returnCode != 0) {
listener.webappStartFailed(returnCode);
throw new FatalException("startTheWebapp() failed: return code="
+ returnCode);
}
listener.webappWaitingForStart(tomcatStartDelay);
try {
Thread.sleep(tomcatStartDelay * 1000L);
} catch (InterruptedException e) {
// Just continue.
}
listener.webappStarted();
} }
/** /**
@ -166,48 +130,23 @@ public class ModelCleaner {
} }
/** /**
* A command line must be broken into separate arguments, where arguments * Figure out where the test data ontology file should go. C:\Program
* are delimited by blanks unless the blank (and the argument) is enclosed * Files\Apache Software Foundation\Tomcat
* in quotes. * 6.0\webapps\vivo\WEB-INF\ontologies\auth
*/ */
static List<String> parseCommandLine(String commandLine) { private File figureUserOntologyTarget() {
List<String> pieces = new ArrayList<String>(); File webappDirectory = properties.getWebappDirectory();
StringBuilder piece = null; File authDirectory = new File(webappDirectory,
boolean inDelimiter = true; "WEB-INF/ontologies/auth");
boolean inQuotes = false;
for (int i = 0; i < commandLine.length(); i++) { if (!authDirectory.exists()) {
char thisChar = commandLine.charAt(i); throw new FatalException("Target directory for the test data "
if ((thisChar == ' ') && !inQuotes) { + "ontology file doesn't exist. Webapp directory is '"
if (inDelimiter) { + webappDirectory + "', target directory is '"
// No effect. + authDirectory + "'");
} 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. return new File(authDirectory, TEST_USER_ONTOLOGY_FILENAME);
if (!inDelimiter) {
pieces.add(piece.toString());
}
// Quotes must appear in pairs
if (inQuotes) {
throw new IllegalArgumentException(
"Command line contains mismatched quotes: " + commandLine);
}
return pieces;
} }
static String convertBackslashes(File file) { static String convertBackslashes(File file) {

View file

@ -17,7 +17,7 @@ public class ModelCleanerProperties {
public static final String PROP_MYSQL_USERNAME = "mysql_username"; public static final String PROP_MYSQL_USERNAME = "mysql_username";
public static final String PROP_MYSQL_PASSWORD = "mysql_password"; 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_MYSQL_DB_NAME = "mysql_db_name";
public static final String PROP_MYSQL_DUMPFILE = "mysql_dumpfile"; public static final String PROP_WEBAPP_DIRECTORY = "vivo_webapp_directory";
private final String tomcatStartCommand; private final String tomcatStartCommand;
private final int tomcatStartDelay; private final int tomcatStartDelay;
@ -26,7 +26,7 @@ public class ModelCleanerProperties {
private final String mysqlUsername; private final String mysqlUsername;
private final String mysqlPassword; private final String mysqlPassword;
private final String mysqlDbName; private final String mysqlDbName;
private final File mysqlDumpfile; private final File webappDirectory;
/** /**
* Confirm that we have the expected properties, and that their values seem * Confirm that we have the expected properties, and that their values seem
@ -47,7 +47,7 @@ public class ModelCleanerProperties {
this.mysqlPassword = getRequiredProperty(props, PROP_MYSQL_PASSWORD); this.mysqlPassword = getRequiredProperty(props, PROP_MYSQL_PASSWORD);
this.mysqlDbName = getRequiredProperty(props, PROP_MYSQL_DB_NAME); this.mysqlDbName = getRequiredProperty(props, PROP_MYSQL_DB_NAME);
this.mysqlDumpfile = confirmDumpfile(props); this.webappDirectory = confirmWebappDirectory(props);
} }
public String getTomcatStartCommand() { public String getTomcatStartCommand() {
@ -78,8 +78,8 @@ public class ModelCleanerProperties {
return mysqlDbName; return mysqlDbName;
} }
public File getMysqlDumpfile() { public File getWebappDirectory() {
return mysqlDumpfile; return webappDirectory;
} }
/** /**
@ -106,33 +106,38 @@ public class ModelCleanerProperties {
} }
/** /**
* The dumpfile parameter must point to an existing file. * The dumpfile parameter must point to an existing directory.
*/ */
private File confirmDumpfile(Properties props) { private File confirmWebappDirectory(Properties props) {
String filename = getRequiredProperty(props, PROP_MYSQL_DUMPFILE); String filename = getRequiredProperty(props, PROP_WEBAPP_DIRECTORY);
File dumpfile = new File(filename); File webappDirectory = new File(filename);
if (!dumpfile.exists()) { if (!webappDirectory.exists()) {
throw new IllegalArgumentException("Invalid value for '" throw new IllegalArgumentException("Invalid value for '"
+ PROP_MYSQL_DUMPFILE + "': file '" + filename + PROP_WEBAPP_DIRECTORY + "': directory '" + filename
+ "' does not exist."); + "' does not exist.");
} }
if (!dumpfile.isFile()) { if (!webappDirectory.isDirectory()) {
throw new IllegalArgumentException("Invalid value for '" throw new IllegalArgumentException("Invalid value for '"
+ PROP_MYSQL_DUMPFILE + "': '" + filename + PROP_WEBAPP_DIRECTORY + "': '" + filename
+ "' is not a file."); + "' is not a directory.");
} }
if (!dumpfile.canRead()) { if (!webappDirectory.canWrite()) {
throw new IllegalArgumentException("Invalid value for '" throw new IllegalArgumentException("Invalid value for '"
+ PROP_MYSQL_DUMPFILE + "': file '" + filename + PROP_WEBAPP_DIRECTORY + "': directory '" + filename
+ "' is not readable."); + "' is not writeable.");
} }
return dumpfile; return webappDirectory;
} }
public String toString() { public String toString() {
return "\n tomcatStartCommand: " + tomcatStartCommand return "\n tomcatStartCommand: " + tomcatStartCommand
+ "\n tomcatStartDelay: " + tomcatStartDelay + "\n tomcatStartDelay: " + tomcatStartDelay
+ "\n tomcatStopCommand: " + tomcatStopCommand + "\n tomcatStopCommand: " + tomcatStopCommand
+ "\n tomcatStopDelay: " + tomcatStopDelay; + "\n tomcatStopDelay: " + tomcatStopDelay
+ "\n mysqlUsername: " + mysqlUsername
+ "\n mysqlPassword: " + mysqlPassword
+ "\n mysqlDbName: " + mysqlDbName
+ "\n webappDirectory: " + webappDirectory;
} }
} }

View file

@ -17,6 +17,7 @@ public class SeleniumRunner {
private final SeleniumRunnerParameters parms; private final SeleniumRunnerParameters parms;
private final Listener listener; private final Listener listener;
private final UploadAreaCleaner uploadCleaner; private final UploadAreaCleaner uploadCleaner;
private final TomcatController tomcatController;
private final ModelCleaner modelCleaner; private final ModelCleaner modelCleaner;
private final SuiteRunner suiteRunner; private final SuiteRunner suiteRunner;
private final OutputManager outputManager; private final OutputManager outputManager;
@ -25,43 +26,27 @@ public class SeleniumRunner {
this.parms = parms; this.parms = parms;
this.listener = parms.getListener(); this.listener = parms.getListener();
this.uploadCleaner = new UploadAreaCleaner(parms); this.uploadCleaner = new UploadAreaCleaner(parms);
this.modelCleaner = new ModelCleaner(parms); this.tomcatController = new TomcatController(parms);
this.modelCleaner = new ModelCleaner(parms, this.tomcatController);
this.suiteRunner = new SuiteRunner(parms); this.suiteRunner = new SuiteRunner(parms);
this.outputManager = new OutputManager(parms); this.outputManager = new OutputManager(parms);
} }
public boolean runSelectedSuites() { /**
* 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; boolean success;
try { try {
listener.runStarted(); listener.runStarted();
outputManager.cleanOutputDirectory(); outputManager.cleanOutputDirectory();
for (File suiteDir : parms.getSelectedSuites()) {
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);
}
// If we've been starting and stopping Tomcat, runSelectedSuites();
// stop it one more time. tomcatController.cleanup();
if (parms.isCleanModel()) {
try {
modelCleaner.stopTheWebapp();
} catch (CommandRunnerException e) {
throw new FatalException(e);
}
}
listener.runEndTime(); listener.runEndTime();
Status status = outputManager.summarizeOutput(); Status status = outputManager.summarizeOutput();
@ -79,6 +64,26 @@ public class SeleniumRunner {
return success; return success;
} }
public void runSelectedSuites() {
for (File suiteDir : parms.getSelectedSuites()) {
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 selectAllSuites(SeleniumRunnerParameters parms) { private static void selectAllSuites(SeleniumRunnerParameters parms) {
Listener listener = parms.getListener(); Listener listener = parms.getListener();
IgnoredTests ignored = parms.getIgnoredTests(); IgnoredTests ignored = parms.getIgnoredTests();
@ -145,7 +150,7 @@ public class SeleniumRunner {
System.out.println(parms); System.out.println(parms);
SeleniumRunner runner = new SeleniumRunner(parms); SeleniumRunner runner = new SeleniumRunner(parms);
success = runner.runSelectedSuites(); success = runner.run();
} }
System.out.println("Exiting SeleniumRunner"); System.out.println("Exiting SeleniumRunner");
System.exit(success ? 0 : -1); System.exit(success ? 0 : -1);

View file

@ -0,0 +1,139 @@
/* $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;
/**
* 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();
}
/**
* Stop Tomcat and wait the prescribed number of seconds for it to clean up.
*/
public void stopTheWebapp() throws CommandRunnerException {
String tomcatStopCommand = properties.getTomcatStopCommand();
int tomcatStopDelay = properties.getTomcatStopDelay();
CommandRunner runner = new CommandRunner(parms);
listener.webappStopping(tomcatStopCommand);
runner.run(parseCommandLine(tomcatStopCommand));
int returnCode = runner.getReturnCode();
if (returnCode != 0) {
listener.webappStopFailed(returnCode);
// Throw no exception - this can happen if Tomcat isn't running.
}
listener.webappWaitingForStop(tomcatStopDelay);
try {
Thread.sleep(tomcatStopDelay * 1000L);
} catch (InterruptedException e) {
// Just continue.
}
listener.webappStopped();
}
/**
* Start Tomcat and wait for it to initialize.
*/
public void startTheWebapp() {
String tomcatStartCommand = properties.getTomcatStartCommand();
int tomcatStartDelay = properties.getTomcatStartDelay();
CommandRunner runner = new CommandRunner(parms);
listener.webappStarting(tomcatStartCommand);
try {
runner.runAsBackground(parseCommandLine(tomcatStartCommand));
} catch (CommandRunnerException e) {
throw new FatalException(e);
}
// Can't check the return code because the process shouldn't end.
listener.webappWaitingForStart(tomcatStartDelay);
try {
Thread.sleep(tomcatStartDelay * 1000L);
} catch (InterruptedException e) {
// Just continue.
}
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() {
// 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);
}
}
}
}

View file

@ -0,0 +1,41 @@
<?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="http://vitro.mannlib.cornell.edu/ns/vitro/default#"
xml:base="http://vitro.mannlib.cornell.edu/ns/vitro/default">
<vitro:User rdf:about="#defaultAdminUser">
<vitro:username rdf:datatype="http://www.w3.org/2001/XMLSchema#string">testAdmin</vitro:username>
<vitro:md5password rdf:datatype="http://www.w3.org/2001/XMLSchema#string">DC647EB65E6711E155375218212B3964</vitro:md5password>
<vitro:roleURI rdf:datatype="http://www.w3.org/2001/XMLSchema#string">role:/50</vitro:roleURI>
<vitro:firstTime rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2010-03-09T16:06:45</vitro:firstTime>
<vitro:loginCount rdf:datatype="http://www.w3.org/2001/XMLSchema#int">1</vitro:loginCount>
</vitro:User>
<vitro:User rdf:about="http://vivo.mydomain.edu/individual/JoeUser">
<vitro:username rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Joe User</vitro:username>
<vitro:md5password rdf:datatype="http://www.w3.org/2001/XMLSchema#string">8A1A62B7B58B8B95564483BEA60CD99A</vitro:md5password>
<vitro:roleURI rdf:datatype="http://www.w3.org/2001/XMLSchema#string">role:/1</vitro:roleURI>
<vitro:firstTime rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2010-03-09T16:06:45</vitro:firstTime>
<vitro:loginCount rdf:datatype="http://www.w3.org/2001/XMLSchema#int">1</vitro:loginCount>
</vitro:User>
<vitro:User rdf:about="http://vivo.mydomain.edu/individual/SallyEditor">
<vitro:username rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Sally Editor</vitro:username>
<vitro:md5password rdf:datatype="http://www.w3.org/2001/XMLSchema#string">8A1A62B7B58B8B95564483BEA60CD99A</vitro:md5password>
<vitro:roleURI rdf:datatype="http://www.w3.org/2001/XMLSchema#string">role:/4</vitro:roleURI>
<vitro:firstTime rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2010-03-09T16:06:45</vitro:firstTime>
<vitro:loginCount rdf:datatype="http://www.w3.org/2001/XMLSchema#int">1</vitro:loginCount>
</vitro:User>
<vitro:User rdf:about="http://vivo.mydomain.edu/individual/JohnCurator">
<vitro:username rdf:datatype="http://www.w3.org/2001/XMLSchema#string">John Curator</vitro:username>
<vitro:md5password rdf:datatype="http://www.w3.org/2001/XMLSchema#string">8A1A62B7B58B8B95564483BEA60CD99A</vitro:md5password>
<vitro:roleURI rdf:datatype="http://www.w3.org/2001/XMLSchema#string">role:/5</vitro:roleURI>
<vitro:firstTime rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2010-03-09T16:06:45</vitro:firstTime>
<vitro:loginCount rdf:datatype="http://www.w3.org/2001/XMLSchema#int">1</vitro:loginCount>
</vitro:User>
</rdf:RDF>

View file

@ -11,7 +11,7 @@ import org.junit.Test;
/** /**
* TODO * TODO
*/ */
public class ModelCleanerTest { public class TomcatControllerTest {
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// Tests for parseCommandLine() // Tests for parseCommandLine()
@ -45,7 +45,7 @@ public class ModelCleanerTest {
private void assertExpectedParsing(String commandLine, private void assertExpectedParsing(String commandLine,
String... expectedPieces) { String... expectedPieces) {
assertEquals("parse", Arrays.asList(expectedPieces), ModelCleaner assertEquals("parse", Arrays.asList(expectedPieces),
.parseCommandLine(commandLine)); TomcatController.parseCommandLine(commandLine));
} }
} }