From 99c70b5d663880bf9136a733a159fab0ddddc88d Mon Sep 17 00:00:00 2001 From: jeb228 Date: Wed, 18 Aug 2010 16:38:01 +0000 Subject: [PATCH] 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. --- .../vitro/utilities/testrunner/Listener.java | 4 + .../utilities/testrunner/ModelCleaner.java | 159 ++++++------------ .../testrunner/ModelCleanerProperties.java | 43 ++--- .../utilities/testrunner/SeleniumRunner.java | 63 +++---- .../testrunner/TomcatController.java | 139 +++++++++++++++ .../utilities/testrunner/test-user-model.owl | 41 +++++ ...nerTest.java => TomcatControllerTest.java} | 6 +- 7 files changed, 294 insertions(+), 161 deletions(-) create mode 100644 utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/TomcatController.java create mode 100644 utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/test-user-model.owl rename utilities/testrunner/test/edu/cornell/mannlib/vitro/utilities/testrunner/{ModelCleanerTest.java => TomcatControllerTest.java} (84%) diff --git a/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/Listener.java b/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/Listener.java index 904965a78..1adca197e 100644 --- a/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/Listener.java +++ b/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/Listener.java @@ -192,6 +192,10 @@ public class Listener { public void cleanUploadStop(File uploadDirectory) { log("Upload cleaning stopped: " + uploadDirectory.getPath()); } + + public void logWarning(String message) { + log("WARNING: " + message); + } // ---------------------------------------------------------------------- // Helper methods diff --git a/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/ModelCleaner.java b/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/ModelCleaner.java index ed8ac4c3e..586ad5f6b 100644 --- a/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/ModelCleaner.java +++ b/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/ModelCleaner.java @@ -3,6 +3,8 @@ 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; @@ -11,14 +13,18 @@ import java.util.List; * 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) { + public ModelCleaner(SeleniumRunnerParameters parms, + TomcatController tomcatController) { this.properties = parms.getModelCleanerProperties(); this.listener = parms.getListener(); this.runner = new CommandRunner(parms); + this.tomcatController = tomcatController; sanityCheck(); } @@ -42,42 +48,39 @@ public class ModelCleaner { * if a problem occurs in a sub-process. */ public void clean() throws CommandRunnerException { - stopTheWebapp(); - dropDatabase(); - createAndLoadDatabase(); - startTheWebapp(); + tomcatController.stopTheWebapp(); + insertTheUserFile(); + recreateTheDatabase(); + 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 { - String tomcatStopCommand = properties.getTomcatStopCommand(); - int tomcatStopDelay = properties.getTomcatStopDelay(); - - 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. + 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 + "'"); } - listener.webappWaitingForStop(tomcatStopDelay); + File userOntologyTarget = figureUserOntologyTarget(); try { - Thread.sleep(tomcatStopDelay * 1000L); - } catch (InterruptedException e) { - // Just continue. + FileHelper.copy(userOntologyStream, userOntologyTarget); + userOntologyStream.close(); + } 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() + "; create database " + properties.getMysqlDbName() + " 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() { - String mysqlStatement = "source " - + convertBackslashes(properties.getMysqlDumpfile()) + ";"; - - listener.loadDatabaseStarting(mysqlStatement); - executeMysqlStatement(mysqlStatement); - - int returnCode = runner.getReturnCode(); - if (returnCode != 0) { - listener.loadDatabaseFailed(returnCode); - throw new FatalException("loadDatabase() failed: return code=" - + returnCode); + 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 + "'"); } - - 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 - * are delimited by blanks unless the blank (and the argument) is enclosed - * in quotes. + * 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 */ - static List parseCommandLine(String commandLine) { - List pieces = new ArrayList(); - 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); - } + 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 + "'"); } - // 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; + return new File(authDirectory, TEST_USER_ONTOLOGY_FILENAME); } static String convertBackslashes(File file) { diff --git a/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/ModelCleanerProperties.java b/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/ModelCleanerProperties.java index 310051905..285b4fd5d 100644 --- a/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/ModelCleanerProperties.java +++ b/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/ModelCleanerProperties.java @@ -17,7 +17,7 @@ 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_MYSQL_DUMPFILE = "mysql_dumpfile"; + public static final String PROP_WEBAPP_DIRECTORY = "vivo_webapp_directory"; private final String tomcatStartCommand; private final int tomcatStartDelay; @@ -26,7 +26,7 @@ public class ModelCleanerProperties { private final String mysqlUsername; private final String mysqlPassword; private final String mysqlDbName; - private final File mysqlDumpfile; + private final File webappDirectory; /** * 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.mysqlDbName = getRequiredProperty(props, PROP_MYSQL_DB_NAME); - this.mysqlDumpfile = confirmDumpfile(props); + this.webappDirectory = confirmWebappDirectory(props); } public String getTomcatStartCommand() { @@ -78,8 +78,8 @@ public class ModelCleanerProperties { return mysqlDbName; } - public File getMysqlDumpfile() { - return mysqlDumpfile; + public File getWebappDirectory() { + 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) { - String filename = getRequiredProperty(props, PROP_MYSQL_DUMPFILE); - File dumpfile = new File(filename); - if (!dumpfile.exists()) { + 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_MYSQL_DUMPFILE + "': file '" + filename + + PROP_WEBAPP_DIRECTORY + "': directory '" + filename + "' does not exist."); } - if (!dumpfile.isFile()) { + if (!webappDirectory.isDirectory()) { throw new IllegalArgumentException("Invalid value for '" - + PROP_MYSQL_DUMPFILE + "': '" + filename - + "' is not a file."); + + PROP_WEBAPP_DIRECTORY + "': '" + filename + + "' is not a directory."); } - if (!dumpfile.canRead()) { + if (!webappDirectory.canWrite()) { throw new IllegalArgumentException("Invalid value for '" - + PROP_MYSQL_DUMPFILE + "': file '" + filename - + "' is not readable."); + + PROP_WEBAPP_DIRECTORY + "': directory '" + filename + + "' is not writeable."); } - return dumpfile; + return webappDirectory; } public String toString() { return "\n tomcatStartCommand: " + tomcatStartCommand + "\n tomcatStartDelay: " + tomcatStartDelay + "\n tomcatStopCommand: " + tomcatStopCommand - + "\n tomcatStopDelay: " + tomcatStopDelay; + + "\n tomcatStopDelay: " + tomcatStopDelay + + "\n mysqlUsername: " + mysqlUsername + + "\n mysqlPassword: " + mysqlPassword + + "\n mysqlDbName: " + mysqlDbName + + "\n webappDirectory: " + webappDirectory; } + } diff --git a/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/SeleniumRunner.java b/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/SeleniumRunner.java index c252121a2..41e3c9ff3 100644 --- a/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/SeleniumRunner.java +++ b/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/SeleniumRunner.java @@ -17,6 +17,7 @@ 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; @@ -25,43 +26,27 @@ public class SeleniumRunner { this.parms = parms; this.listener = parms.getListener(); 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.outputManager = new OutputManager(parms); + } - public boolean runSelectedSuites() { + /** + * Set up the run, run the selected suites, summarize the output, and clean + * up afterwards. + * + * @return true iff all tests passed. + */ + public boolean run() { boolean success; try { listener.runStarted(); 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, - // stop it one more time. - if (parms.isCleanModel()) { - try { - modelCleaner.stopTheWebapp(); - } catch (CommandRunnerException e) { - throw new FatalException(e); - } - } + runSelectedSuites(); + tomcatController.cleanup(); listener.runEndTime(); Status status = outputManager.summarizeOutput(); @@ -79,6 +64,26 @@ public class SeleniumRunner { 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) { Listener listener = parms.getListener(); IgnoredTests ignored = parms.getIgnoredTests(); @@ -145,7 +150,7 @@ public class SeleniumRunner { System.out.println(parms); SeleniumRunner runner = new SeleniumRunner(parms); - success = runner.runSelectedSuites(); + success = runner.run(); } System.out.println("Exiting SeleniumRunner"); System.exit(success ? 0 : -1); diff --git a/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/TomcatController.java b/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/TomcatController.java new file mode 100644 index 000000000..a7c2a8ecd --- /dev/null +++ b/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/TomcatController.java @@ -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 parseCommandLine(String commandLine) { + List pieces = new ArrayList(); + 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); + } + } + + } + +} diff --git a/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/test-user-model.owl b/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/test-user-model.owl new file mode 100644 index 000000000..494058cab --- /dev/null +++ b/utilities/testrunner/src/edu/cornell/mannlib/vitro/utilities/testrunner/test-user-model.owl @@ -0,0 +1,41 @@ + + + + + testAdmin + DC647EB65E6711E155375218212B3964 + role:/50 + 2010-03-09T16:06:45 + 1 + + + + Joe User + 8A1A62B7B58B8B95564483BEA60CD99A + role:/1 + 2010-03-09T16:06:45 + 1 + + + + Sally Editor + 8A1A62B7B58B8B95564483BEA60CD99A + role:/4 + 2010-03-09T16:06:45 + 1 + + + + John Curator + 8A1A62B7B58B8B95564483BEA60CD99A + role:/5 + 2010-03-09T16:06:45 + 1 + + + diff --git a/utilities/testrunner/test/edu/cornell/mannlib/vitro/utilities/testrunner/ModelCleanerTest.java b/utilities/testrunner/test/edu/cornell/mannlib/vitro/utilities/testrunner/TomcatControllerTest.java similarity index 84% rename from utilities/testrunner/test/edu/cornell/mannlib/vitro/utilities/testrunner/ModelCleanerTest.java rename to utilities/testrunner/test/edu/cornell/mannlib/vitro/utilities/testrunner/TomcatControllerTest.java index c626a280d..8db9b5b9b 100644 --- a/utilities/testrunner/test/edu/cornell/mannlib/vitro/utilities/testrunner/ModelCleanerTest.java +++ b/utilities/testrunner/test/edu/cornell/mannlib/vitro/utilities/testrunner/TomcatControllerTest.java @@ -11,7 +11,7 @@ import org.junit.Test; /** * TODO */ -public class ModelCleanerTest { +public class TomcatControllerTest { // ---------------------------------------------------------------------- // Tests for parseCommandLine() @@ -45,7 +45,7 @@ public class ModelCleanerTest { private void assertExpectedParsing(String commandLine, String... expectedPieces) { - assertEquals("parse", Arrays.asList(expectedPieces), ModelCleaner - .parseCommandLine(commandLine)); + assertEquals("parse", Arrays.asList(expectedPieces), + TomcatController.parseCommandLine(commandLine)); } }