summaryrefslogtreecommitdiff
path: root/qpid/java/systests/src/test/java/org/apache/qpid/util
diff options
context:
space:
mode:
Diffstat (limited to 'qpid/java/systests/src/test/java/org/apache/qpid/util')
-rw-r--r--qpid/java/systests/src/test/java/org/apache/qpid/util/ClasspathScanner.java239
-rw-r--r--qpid/java/systests/src/test/java/org/apache/qpid/util/LogMonitor.java336
-rw-r--r--qpid/java/systests/src/test/java/org/apache/qpid/util/LogMonitorTest.java274
3 files changed, 849 insertions, 0 deletions
diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/util/ClasspathScanner.java b/qpid/java/systests/src/test/java/org/apache/qpid/util/ClasspathScanner.java
new file mode 100644
index 0000000000..151d1473ac
--- /dev/null
+++ b/qpid/java/systests/src/test/java/org/apache/qpid/util/ClasspathScanner.java
@@ -0,0 +1,239 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.util;
+
+import org.apache.log4j.Logger;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * An ClasspathScanner scans the classpath for classes that implement an interface or extend a base class and have names
+ * that match a regular expression.
+ *
+ * <p/>In order to test whether a class implements an interface or extends a class, the class must be loaded (unless
+ * the class files were to be scanned directly). Using this collector can cause problems when it scans the classpath,
+ * because loading classes will initialize their statics, which in turn may cause undesired side effects. For this
+ * reason, the collector should always be used with a regular expression, through which the class file names are
+ * filtered, and only those that pass this filter will be tested. For example, if you define tests in classes that
+ * end with the keyword "Test" then use the regular expression "Test$" to match this.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Find all classes matching type and name pattern on the classpath.
+ * </table>
+ *
+ * @todo Add logic to scan jars as well as directories.
+ */
+public class ClasspathScanner
+{
+ private static final Logger log = Logger.getLogger(ClasspathScanner.class);
+
+ /**
+ * Scans the classpath and returns all classes that extend a specified class and match a specified name.
+ * There is an flag that can be used to indicate that only Java Beans will be matched (that is, only those classes
+ * that have a default constructor).
+ *
+ * @param matchingClass The class or interface to match.
+ * @param matchingRegexp The regular expression to match against the class name.
+ * @param beanOnly Flag to indicate that onyl classes with default constructors should be matched.
+ *
+ * @return All the classes that match this collector.
+ */
+ public static <T> Collection<Class<? extends T>> getMatches(Class<T> matchingClass, String matchingRegexp,
+ boolean beanOnly)
+ {
+ log.debug("public static <T> Collection<Class<? extends T>> getMatches(Class<T> matchingClass = " + matchingClass
+ + ", String matchingRegexp = " + matchingRegexp + ", boolean beanOnly = " + beanOnly + "): called");
+
+ // Build a compiled regular expression from the pattern to match.
+ Pattern matchPattern = Pattern.compile(matchingRegexp);
+
+ String classPath = System.getProperty("java.class.path");
+ Map<String, Class<? extends T>> result = new HashMap<String, Class<? extends T>>();
+
+ log.debug("classPath = " + classPath);
+
+ // Find matching classes starting from all roots in the classpath.
+ for (String path : splitClassPath(classPath))
+ {
+ gatherFiles(new File(path), "", result, matchPattern, matchingClass);
+ }
+
+ return result.values();
+ }
+
+ /**
+ * Finds all matching classes rooted at a given location in the file system. If location is a directory it
+ * is recursively examined.
+ *
+ * @param classRoot The root of the current point in the file system being examined.
+ * @param classFileName The name of the current file or directory to examine.
+ * @param result The accumulated mapping from class names to classes that match the scan.
+ *
+ * @todo Recursion ok as file system depth is not likely to exhaust the stack. Might be better to replace with
+ * iteration.
+ */
+ private static <T> void gatherFiles(File classRoot, String classFileName, Map<String, Class<? extends T>> result,
+ Pattern matchPattern, Class<? extends T> matchClass)
+ {
+ log.debug("private static <T> void gatherFiles(File classRoot = " + classRoot + ", String classFileName = "
+ + classFileName + ", Map<String, Class<? extends T>> result, Pattern matchPattern = " + matchPattern
+ + ", Class<? extends T> matchClass = " + matchClass + "): called");
+
+ File thisRoot = new File(classRoot, classFileName);
+
+ // If the current location is a file, check if it is a matching class.
+ if (thisRoot.isFile())
+ {
+ // Check that the file has a matching name.
+ if (matchesName(thisRoot.getName(), matchPattern))
+ {
+ String className = classNameFromFile(thisRoot.getName());
+
+ // Check that the class has matching type.
+ try
+ {
+ Class<?> candidateClass = Class.forName(className);
+
+ Class matchedClass = matchesClass(candidateClass, matchClass);
+
+ if (matchedClass != null)
+ {
+ result.put(className, matchedClass);
+ }
+ }
+ catch (ClassNotFoundException e)
+ {
+ // Ignore this. The matching class could not be loaded.
+ log.debug("Got ClassNotFoundException, ignoring.", e);
+ }
+ }
+
+ return;
+ }
+ // Otherwise the current location is a directory, so examine all of its contents.
+ else
+ {
+ String[] contents = thisRoot.list();
+
+ if (contents != null)
+ {
+ for (String content : contents)
+ {
+ gatherFiles(classRoot, classFileName + File.separatorChar + content, result, matchPattern, matchClass);
+ }
+ }
+ }
+ }
+
+ /**
+ * Checks if the specified class file name corresponds to a class with name matching the specified regular expression.
+ *
+ * @param classFileName The class file name.
+ * @param matchPattern The regular expression pattern to match.
+ *
+ * @return <tt>true</tt> if the class name matches, <tt>false</tt> otherwise.
+ */
+ private static boolean matchesName(String classFileName, Pattern matchPattern)
+ {
+ String className = classNameFromFile(classFileName);
+ Matcher matcher = matchPattern.matcher(className);
+
+ return matcher.matches();
+ }
+
+ /**
+ * Checks if the specified class to compare extends the base class being scanned for.
+ *
+ * @param matchingClass The base class to match against.
+ * @param toMatch The class to match against the base class.
+ *
+ * @return The class to check, cast as an instance of the class to match if the class extends the base class, or
+ * <tt>null</tt> otherwise.
+ */
+ private static <T> Class<? extends T> matchesClass(Class<?> matchingClass, Class<? extends T> toMatch)
+ {
+ try
+ {
+ return matchingClass.asSubclass(toMatch);
+ }
+ catch (ClassCastException e)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Takes a classpath (which is a series of paths) and splits it into its component paths.
+ *
+ * @param classPath The classpath to split.
+ *
+ * @return A list of the component paths that make up the class path.
+ */
+ private static List<String> splitClassPath(String classPath)
+ {
+ List<String> result = new LinkedList<String>();
+ String separator = System.getProperty("path.separator");
+ StringTokenizer tokenizer = new StringTokenizer(classPath, separator);
+
+ while (tokenizer.hasMoreTokens())
+ {
+ result.add(tokenizer.nextToken());
+ }
+
+ return result;
+ }
+
+ /**
+ * Translates from the filename of a class to its fully qualified classname. Files are named using forward slash
+ * seperators and end in ".class", whereas fully qualified class names use "." sperators and no ".class" ending.
+ *
+ * @param classFileName The filename of the class to translate to a class name.
+ *
+ * @return The fully qualified class name.
+ */
+ private static String classNameFromFile(String classFileName)
+ {
+ log.debug("private static String classNameFromFile(String classFileName = " + classFileName + "): called");
+
+ // Remove the .class ending.
+ String s = classFileName.substring(0, classFileName.length() - ".class".length());
+
+ // Turn / seperators in . seperators.
+ String s2 = s.replace(File.separatorChar, '.');
+
+ // Knock off any leading . caused by a leading /.
+ if (s2.startsWith("."))
+ {
+ return s2.substring(1);
+ }
+
+ return s2;
+ }
+}
diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/util/LogMonitor.java b/qpid/java/systests/src/test/java/org/apache/qpid/util/LogMonitor.java
new file mode 100644
index 0000000000..d77731d09f
--- /dev/null
+++ b/qpid/java/systests/src/test/java/org/apache/qpid/util/LogMonitor.java
@@ -0,0 +1,336 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.util;
+
+import org.apache.log4j.FileAppender;
+import org.apache.log4j.Logger;
+import org.apache.log4j.SimpleLayout;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.LineNumberReader;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Utility to simplify the monitoring of Log4j file output
+ *
+ * Monitoring of a given log file can be done alternatively the Monitor will
+ * add a new log4j FileAppender to the root Logger to gather all the available
+ * logging for monitoring
+ */
+public class LogMonitor
+{
+ private static final Logger _logger = Logger.getLogger(LogMonitor.class);
+
+ // The file that the log statements will be written to.
+ private final File _logfile;
+
+ // The appender we added to the get messages
+ private final FileAppender _appender;
+
+ private int _linesToSkip = 0;
+
+ /**
+ * Create a new LogMonitor that creates a new Log4j Appender and monitors
+ * all log4j output via the current configuration.
+ *
+ * @throws IOException if there is a problem creating the temporary file.
+ */
+ public LogMonitor() throws IOException
+ {
+ this(null);
+ }
+
+ /**
+ * Create a new LogMonitor on the specified file if the file does not exist
+ * or the value is null then a new Log4j appender will be added and
+ * monitoring set up on that appender.
+ *
+ * NOTE: for the appender to receive any value the RootLogger will need to
+ * have the level correctly configured.ng
+ *
+ * @param file the file to monitor
+ *
+ * @throws IOException if there is a problem creating a temporary file
+ */
+ public LogMonitor(File file) throws IOException
+ {
+ if (file != null && file.exists())
+ {
+ _logfile = file;
+ _appender = null;
+ }
+ else
+ {
+ // This is mostly for running the test outside of the ant setup
+ _logfile = File.createTempFile("LogMonitor", ".log");
+ _appender = new FileAppender(new SimpleLayout(),
+ _logfile.getAbsolutePath());
+ _appender.setFile(_logfile.getAbsolutePath());
+ _appender.setImmediateFlush(true);
+ Logger.getRootLogger().addAppender(_appender);
+ }
+
+ _logger.info("Created LogMonitor. Monitoring file: " + _logfile.getAbsolutePath());
+ }
+
+ /**
+ * Checks the log file for a given message to appear and returns all
+ * instances of that appearance.
+ *
+ * @param message the message to wait for in the log
+ * @param wait the time in ms to wait for the message to occur
+ * @return true if the message was found
+ *
+ * @throws java.io.FileNotFoundException if the Log file can no longer be found
+ * @throws IOException thrown when reading the log file
+ */
+ public List<String> waitAndFindMatches(String message, long wait)
+ throws FileNotFoundException, IOException
+ {
+ if (waitForMessage(message, wait))
+ {
+ return findMatches(message);
+ }
+ else
+ {
+ return new LinkedList<String>();
+ }
+ }
+
+ /**
+ * Checks the log for instances of the search string. If the caller
+ * has previously called {@link #markDiscardPoint()}, lines up until the discard
+ * point are not considered.
+ *
+ * The pattern parameter can take any valid argument used in String.contains()
+ *
+ * {@see String.contains(CharSequences)}
+ *
+ * @param pattern the search string
+ *
+ * @return a list of matching lines from the log
+ *
+ * @throws IOException if there is a problem with the file
+ */
+ public List<String> findMatches(String pattern) throws IOException
+ {
+
+ List<String> results = new LinkedList<String>();
+
+ LineNumberReader reader = new LineNumberReader(new FileReader(_logfile));
+ try
+ {
+ while (reader.ready())
+ {
+ String line = reader.readLine();
+ if (reader.getLineNumber() > _linesToSkip && line.contains(pattern))
+ {
+ results.add(line);
+ }
+ }
+ }
+ finally
+ {
+ reader.close();
+ }
+
+ return results;
+ }
+
+ public Map<String, List<String>> findMatches(String... pattern) throws IOException
+ {
+
+ Map<String, List<String>> results= new HashMap<String, List<String>>();
+ for (String p : pattern)
+ {
+ results.put(p, new LinkedList<String>());
+ }
+ LineNumberReader reader = new LineNumberReader(new FileReader(_logfile));
+ try
+ {
+ while (reader.ready())
+ {
+ String line = reader.readLine();
+ if (reader.getLineNumber() > _linesToSkip)
+ {
+ for (String p : pattern)
+ {
+ if (line.contains(p))
+ {
+ results.get(p).add(line);
+ }
+ }
+ }
+ }
+ }
+ finally
+ {
+ reader.close();
+ }
+
+ return results;
+ }
+ /**
+ * Checks the log file for a given message to appear. If the caller
+ * has previously called {@link #markDiscardPoint()}, lines up until the discard
+ * point are not considered.
+ *
+ * @param message the message to wait for in the log
+ * @param wait the time in ms to wait for the message to occur
+ * @return true if the message was found
+ *
+ * @throws java.io.FileNotFoundException if the Log file can no longer be found
+ * @throws IOException thrown when reading the log file
+ */
+ public boolean waitForMessage(String message, long wait)
+ throws FileNotFoundException, IOException
+ {
+ // Loop through alerts until we're done or wait ms seconds have passed,
+ // just in case the logfile takes a while to flush.
+ LineNumberReader reader = null;
+ try
+ {
+ reader = new LineNumberReader(new FileReader(_logfile));
+
+ boolean found = false;
+ long endtime = System.currentTimeMillis() + wait;
+ while (!found && System.currentTimeMillis() < endtime)
+ {
+ boolean ready = true;
+ while (ready = reader.ready())
+ {
+ String line = reader.readLine();
+
+ if (reader.getLineNumber() > _linesToSkip)
+ {
+ if (line.contains(message))
+ {
+ found = true;
+ break;
+ }
+ }
+ }
+ if (!ready)
+ {
+ try
+ {
+ Thread.sleep(50);
+ }
+ catch (InterruptedException ie)
+ {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+ return found;
+
+ }
+ finally
+ {
+ if (reader != null)
+ {
+ reader.close();
+ }
+ }
+ }
+
+ /**
+ * Read the log file in to memory as a String
+ *
+ * @return the current contents of the log file
+ *
+ * @throws java.io.FileNotFoundException if the Log file can no longer be found
+ * @throws IOException thrown when reading the log file
+ */
+ public String readFile() throws FileNotFoundException, IOException
+ {
+ return FileUtils.readFileAsString(_logfile);
+ }
+
+ /**
+ * Return a File reference to the monitored file
+ *
+ * @return the file being monitored
+ */
+ public File getMonitoredFile()
+ {
+ return _logfile;
+ }
+
+ /**
+ * Marks the discard point in the log file.
+ *
+ * @throws java.io.FileNotFoundException if the Log file can no longer be found
+ * @throws IOException thrown if there is a problem with the log file
+ */
+ public void markDiscardPoint() throws FileNotFoundException, IOException
+ {
+ _linesToSkip = countLinesInFile();
+ }
+
+ private int countLinesInFile() throws IOException
+ {
+ int lineCount = 0;
+ BufferedReader br = null;
+ try
+ {
+ br = new BufferedReader(new FileReader(_logfile));
+ while(br.readLine() != null)
+ {
+ lineCount++;
+ }
+
+ return lineCount;
+ }
+ finally
+ {
+ if (br != null)
+ {
+ br.close();
+ }
+ }
+ }
+
+ /**
+ * Stop monitoring this file.
+ *
+ * This is required to be called incase we added a new logger.
+ *
+ * If we don't call close then the new logger will continue to get log entries
+ * after our desired test has finished.
+ */
+ public void close()
+ {
+ //Remove the custom appender we added for this logger
+ if (_appender != null)
+ {
+ Logger.getRootLogger().removeAppender(_appender);
+ }
+ }
+
+}
diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/util/LogMonitorTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/util/LogMonitorTest.java
new file mode 100644
index 0000000000..89f707fbef
--- /dev/null
+++ b/qpid/java/systests/src/test/java/org/apache/qpid/util/LogMonitorTest.java
@@ -0,0 +1,274 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.util;
+
+import junit.framework.TestCase;
+import org.apache.log4j.Logger;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+public class LogMonitorTest extends TestCase
+{
+
+ private LogMonitor _monitor;
+
+ @Override
+ public void setUp() throws Exception
+ {
+ _monitor = new LogMonitor();
+ _monitor.getMonitoredFile().deleteOnExit(); // Make sure we clean up
+ }
+
+ /**
+ * Test that a new file is created when attempting to set up a monitor with
+ * the default constructor.
+ */
+ public void testMonitor()
+ {
+ //Validate that the monitor is now running on a new file
+ assertTrue("New file does not have correct name:" + _monitor.
+ getMonitoredFile().getName(),
+ _monitor.getMonitoredFile().getName().contains("LogMonitor"));
+ }
+
+ /**
+ * Test that creation of a monitor on an existing file is possible
+ *
+ * This also tests taht getMonitoredFile works
+ *
+ * @throws IOException if there is a problem creating the temporary file
+ */
+ public void testMonitorNormalFile() throws IOException
+ {
+ File testFile = File.createTempFile("testMonitorFile", ".log");
+ testFile.deleteOnExit();
+
+ //Ensure that we can create a monitor on a file
+ try
+ {
+ _monitor = new LogMonitor(testFile);
+ assertEquals(testFile, _monitor.getMonitoredFile());
+ }
+ catch (IOException ioe)
+ {
+ fail("IOE thrown:" + ioe);
+ }
+
+ }
+
+ /**
+ * Test that a new file is created when attempting to set up a monitor on
+ * a null input value.
+ */
+ public void testMonitorNullFile()
+ {
+ // Validate that a NPE is thrown with null input
+ try
+ {
+ LogMonitor montior = new LogMonitor(null);
+ //Validte that the monitor is now running on a new file
+ assertTrue("New file does not have correct name:" + montior.
+ getMonitoredFile().getName(),
+ montior.getMonitoredFile().getName().contains("LogMonitor"));
+ }
+ catch (IOException ioe)
+ {
+ fail("IOE thrown:" + ioe);
+ }
+ }
+
+ /**
+ * Test that a new file is created when attempting to set up a monitor on
+ * a non existing file.
+ *
+ * @throws IOException if there is a problem setting up the nonexistent file
+ */
+ public void testMonitorNonExistentFile() throws IOException
+ {
+ //Validate that we get a FileNotFound if the file does not exist
+
+ File nonexist = File.createTempFile("nonexist", ".out");
+
+ assertTrue("Unable to delete file for our test", nonexist.delete());
+
+ assertFalse("Unable to test as our test file exists.", nonexist.exists());
+
+ try
+ {
+ LogMonitor montior = new LogMonitor(nonexist);
+ //Validte that the monitor is now running on a new file
+ assertTrue("New file does not have correct name:" + montior.
+ getMonitoredFile().getName(),
+ montior.getMonitoredFile().getName().contains("LogMonitor"));
+ }
+ catch (IOException ioe)
+ {
+ fail("IOE thrown:" + ioe);
+ }
+ }
+
+ /**
+ * Test that Log file matches logged messages.
+ *
+ * @throws java.io.IOException if there is a problem creating LogMontior
+ */
+ public void testFindMatches_Match() throws IOException
+ {
+
+ String message = getName() + ": Test Message";
+
+ Logger.getRootLogger().warn(message);
+
+ validateLogContainsMessage(_monitor, message);
+ }
+
+ /**
+ * Test that Log file does not match a message not logged.
+ *
+ * @throws java.io.IOException if there is a problem creating LogMontior
+ */
+ public void testFindMatches_NoMatch() throws IOException
+ {
+ String message = getName() + ": Test Message";
+
+ Logger.getRootLogger().warn(message);
+
+ String notLogged = "This text was not logged";
+
+ validateLogDoesNotContainMessage(_monitor, notLogged);
+ }
+
+ public void testWaitForMessage_Timeout() throws IOException
+ {
+ String message = getName() + ": Test Message";
+
+ long TIME_OUT = 2000;
+
+ logMessageWithDelay(message, TIME_OUT);
+
+ // Verify that we can time out waiting for a message
+ assertFalse("Message was logged ",
+ _monitor.waitForMessage(message, TIME_OUT / 2));
+
+ // Verify that the message did eventually get logged.
+ assertTrue("Message was never logged.",
+ _monitor.waitForMessage(message, TIME_OUT));
+ }
+
+ public void testDiscardPoint() throws IOException
+ {
+ String firstMessage = getName() + ": Test Message1";
+ Logger.getRootLogger().warn(firstMessage);
+
+ validateLogContainsMessage(_monitor, firstMessage);
+
+ _monitor.markDiscardPoint();
+
+ validateLogDoesNotContainMessage(_monitor, firstMessage);
+
+ String secondMessage = getName() + ": Test Message2";
+ Logger.getRootLogger().warn(secondMessage);
+ validateLogContainsMessage(_monitor, secondMessage);
+ }
+
+ public void testRead() throws IOException
+ {
+ String message = getName() + ": Test Message";
+
+ Logger.getRootLogger().warn(message);
+
+ String fileContents = _monitor.readFile();
+
+ assertTrue("Logged message not found when reading file.",
+ fileContents.contains(message));
+ }
+
+ /****************** Helpers ******************/
+
+ /**
+ * Validate that the LogMonitor does not match the given string in the log
+ *
+ * @param log The LogMonitor to check
+ * @param message The message to check for
+ *
+ * @throws IOException if a problems occurs
+ */
+ protected void validateLogDoesNotContainMessage(LogMonitor log, String message)
+ throws IOException
+ {
+ List<String> results = log.findMatches(message);
+
+ assertNotNull("Null results returned.", results);
+
+ assertEquals("Incorrect result set size", 0, results.size());
+ }
+
+ /**
+ * Validate that the LogMonitor can match the given string in the log
+ *
+ * @param log The LogMonitor to check
+ * @param message The message to check for
+ *
+ * @throws IOException if a problems occurs
+ */
+ protected void validateLogContainsMessage(LogMonitor log, String message)
+ throws IOException
+ {
+ List<String> results = log.findMatches(message);
+
+ assertNotNull("Null results returned.", results);
+
+ assertEquals("Incorrect result set size", 1, results.size());
+
+ assertTrue("Logged Message'" + message + "' not present in results:"
+ + results.get(0), results.get(0).contains(message));
+ }
+
+ /**
+ * Create a new thread to log the given message after the set delay
+ *
+ * @param message the messasge to log
+ * @param delay the delay (ms) to wait before logging
+ */
+ private void logMessageWithDelay(final String message, final long delay)
+ {
+ new Thread(new Runnable()
+ {
+
+ public void run()
+ {
+ try
+ {
+ Thread.sleep(delay);
+ }
+ catch (InterruptedException e)
+ {
+ //ignore
+ }
+
+ Logger.getRootLogger().warn(message);
+ }
+ }).start();
+ }
+
+}