Clover coverage report - Code Coverage for hivemind release 1.0
Coverage timestamp: Wed Sep 22 2004 08:05:25 EDT
file stats: LOC: 477   Methods: 0
NCLOC: 259   Classes: 1
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover
 
 Source file Conditionals Statements Methods TOTAL
HiveMindTestCase.java - - - -
coverage
 1   
 //  Copyright 2004 The Apache Software Foundation
 2   
 //
 3   
 // Licensed under the Apache License, Version 2.0 (the "License");
 4   
 // you may not use this file except in compliance with the License.
 5   
 // You may obtain a copy of the License at
 6   
 //
 7   
 //     http://www.apache.org/licenses/LICENSE-2.0
 8   
 //
 9   
 // Unless required by applicable law or agreed to in writing, software
 10   
 // distributed under the License is distributed on an "AS IS" BASIS,
 11   
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12   
 // See the License for the specific language governing permissions and
 13   
 // limitations under the License.
 14   
 
 15   
 package org.apache.hivemind.test;
 16   
 
 17   
 import java.net.URL;
 18   
 import java.util.ArrayList;
 19   
 import java.util.Iterator;
 20   
 import java.util.List;
 21   
 import java.util.Locale;
 22   
 
 23   
 import junit.framework.AssertionFailedError;
 24   
 import junit.framework.TestCase;
 25   
 
 26   
 import org.apache.hivemind.ApplicationRuntimeException;
 27   
 import org.apache.hivemind.ClassResolver;
 28   
 import org.apache.hivemind.Location;
 29   
 import org.apache.hivemind.Registry;
 30   
 import org.apache.hivemind.Resource;
 31   
 import org.apache.hivemind.impl.DefaultClassResolver;
 32   
 import org.apache.hivemind.impl.LocationImpl;
 33   
 import org.apache.hivemind.impl.RegistryBuilder;
 34   
 import org.apache.hivemind.util.ClasspathResource;
 35   
 import org.apache.hivemind.util.PropertyUtils;
 36   
 import org.apache.hivemind.util.URLResource;
 37   
 import org.apache.log4j.Level;
 38   
 import org.apache.log4j.LogManager;
 39   
 import org.apache.log4j.Logger;
 40   
 import org.apache.log4j.spi.LoggingEvent;
 41   
 import org.apache.oro.text.regex.Pattern;
 42   
 import org.apache.oro.text.regex.Perl5Compiler;
 43   
 import org.apache.oro.text.regex.Perl5Matcher;
 44   
 import org.easymock.MockControl;
 45   
 
 46   
 /**
 47   
  * Contains some support for creating HiveMind tests; this is useful enough that
 48   
  * has been moved into the main framework, to simplify creation of tests in the dependent
 49   
  * libraries.
 50   
  *
 51   
  * @author Howard Lewis Ship
 52   
  */
 53   
 public abstract class HiveMindTestCase extends TestCase
 54   
 {
 55   
     ///CLOVER:OFF
 56   
 
 57   
     protected String _interceptedLoggerName;
 58   
     protected StoreAppender _appender;
 59   
 
 60   
     private static Perl5Compiler _compiler;
 61   
     private static Perl5Matcher _matcher;
 62   
 
 63   
     /** List of {@link org.easymock.MockControl}. */
 64   
 
 65   
     private List _controls = new ArrayList();
 66   
 
 67   
     /**
 68   
      * Returns the given file as a {@link Resource} from the classpath. Typically,
 69   
      * this is to find files in the same folder as the invoking class.
 70   
      */
 71   
     protected Resource getResource(String file)
 72   
     {
 73   
         URL url = getClass().getResource(file);
 74   
 
 75   
         if (url == null)
 76   
             throw new NullPointerException("No resource named '" + file + "'.");
 77   
 
 78   
         return new URLResource(url);
 79   
     }
 80   
 
 81   
     /**
 82   
      * Converts the actual list to an array and invokes
 83   
      * {@link #assertListsEqual(Object[], Object[])}.
 84   
      */
 85   
     protected static void assertListsEqual(Object[] expected, List actual)
 86   
     {
 87   
         assertListsEqual(expected, actual.toArray());
 88   
     }
 89   
 
 90   
     /**
 91   
      * Asserts that the two arrays are equal; same length and all elements
 92   
      * equal.  Checks the elements first, then the length.
 93   
      */
 94   
     protected static void assertListsEqual(Object[] expected, Object[] actual)
 95   
     {
 96   
         assertNotNull(actual);
 97   
 
 98   
         int min = Math.min(expected.length, actual.length);
 99   
 
 100   
         for (int i = 0; i < min; i++)
 101   
             assertEquals("list[" + i + "]", expected[i], actual[i]);
 102   
 
 103   
         assertEquals("list length", expected.length, actual.length);
 104   
     }
 105   
 
 106   
     /**
 107   
      * Called when code should not be reachable (because a test is expected
 108   
      * to throw an exception); throws
 109   
      * AssertionFailedError always.
 110   
      */
 111   
     protected static void unreachable()
 112   
     {
 113   
         throw new AssertionFailedError("This code should be unreachable.");
 114   
     }
 115   
 
 116   
     /**
 117   
      * Sets up a {@link StoreAppender} to intercept logging for the specified
 118   
      * logger. Captured log events can be recovered via
 119   
      * {@link #getInterceptedLogEvents()}.
 120   
      */
 121   
     protected void interceptLogging(String loggerName)
 122   
     {
 123   
         Logger logger = LogManager.getLogger(loggerName);
 124   
 
 125   
         logger.removeAllAppenders();
 126   
 
 127   
         _interceptedLoggerName = loggerName;
 128   
         _appender = new StoreAppender();
 129   
 
 130   
         logger.setLevel(Level.DEBUG);
 131   
         logger.setAdditivity(false);
 132   
         logger.addAppender(_appender);
 133   
     }
 134   
 
 135   
     /**
 136   
      * Gets the list of events most recently intercepted. This resets
 137   
      * the {@link StoreAppender} (it clears its list of log events).
 138   
      * 
 139   
      * @see #interceptLogging(String)
 140   
      * @see StoreAppender#getEvents()
 141   
      */
 142   
     protected List getInterceptedLogEvents()
 143   
     {
 144   
         return _appender.getEvents();
 145   
     }
 146   
 
 147   
     /**
 148   
      * Removes the {@link StoreAppender} that may have been setup by
 149   
      * {@link #interceptLogging(String)}. Also, invokes
 150   
      * {@link org.apache.hivemind.util.PropertyUtils#clearCache()}.
 151   
      */
 152   
     protected void tearDown() throws Exception
 153   
     {
 154   
         super.tearDown();
 155   
 
 156   
         if (_appender != null)
 157   
         {
 158   
             _appender = null;
 159   
 
 160   
             Logger logger = LogManager.getLogger(_interceptedLoggerName);
 161   
             logger.setLevel(null);
 162   
             logger.setAdditivity(true);
 163   
             logger.removeAllAppenders();
 164   
         }
 165   
 
 166   
         PropertyUtils.clearCache();
 167   
     }
 168   
 
 169   
     /**
 170   
      * Checks that the provided substring exists in the exceptions message.
 171   
      */
 172   
     protected void assertExceptionSubstring(Throwable ex, String substring)
 173   
     {
 174   
         String message = ex.getMessage();
 175   
         assertNotNull(message);
 176   
 
 177   
         int pos = message.indexOf(substring);
 178   
 
 179   
         if (pos < 0)
 180   
             throw new AssertionFailedError(
 181   
                 "Exception message (" + message + ") does not contain [" + substring + "]");
 182   
     }
 183   
 
 184   
     /**
 185   
      * Checks that the message for an exception matches a regular expression.
 186   
      */
 187   
 
 188   
     protected void assertExceptionRegexp(Throwable ex, String pattern) throws Exception
 189   
     {
 190   
         String message = ex.getMessage();
 191   
         assertNotNull(message);
 192   
 
 193   
         setupMatcher();
 194   
 
 195   
         Pattern compiled = _compiler.compile(pattern);
 196   
 
 197   
         if (_matcher.contains(message, compiled))
 198   
             return;
 199   
 
 200   
         throw new AssertionFailedError(
 201   
             "Exception message ("
 202   
                 + message
 203   
                 + ") does not contain regular expression ["
 204   
                 + pattern
 205   
                 + "].");
 206   
     }
 207   
 
 208   
     protected void assertRegexp(String pattern, String actual) throws Exception
 209   
     {
 210   
         setupMatcher();
 211   
 
 212   
         Pattern compiled = _compiler.compile(pattern);
 213   
 
 214   
         if (_matcher.contains(actual, compiled))
 215   
             return;
 216   
 
 217   
         throw new AssertionFailedError(
 218   
             "\"" + actual + "\" does not contain regular expression[" + pattern + "].");
 219   
     }
 220   
 
 221   
     /**
 222   
      * Digs down through (potentially) a stack of ApplicationRuntimeExceptions until it
 223   
      * reaches the originating exception, which is returned.
 224   
      */
 225   
     protected Throwable findNestedException(ApplicationRuntimeException ex)
 226   
     {
 227   
         Throwable cause = ex.getRootCause();
 228   
 
 229   
         if (cause == null || cause == ex)
 230   
             return ex;
 231   
 
 232   
         if (cause instanceof ApplicationRuntimeException)
 233   
             return findNestedException((ApplicationRuntimeException) cause);
 234   
 
 235   
         return cause;
 236   
     }
 237   
 
 238   
     /**
 239   
      * Checks to see if a specific event matches the name and message.
 240   
      * @param message exact message to search for
 241   
      * @param events the list of events {@link #getInterceptedLogEvents()}
 242   
      * @param index the index to check at
 243   
      */
 244   
     private void assertLoggedMessage(String message, List events, int index)
 245   
     {
 246   
         LoggingEvent e = (LoggingEvent) events.get(index);
 247   
 
 248   
         assertEquals("Message", message, e.getMessage());
 249   
     }
 250   
 
 251   
     /**
 252   
      * Checks the messages for all logged events for exact match against
 253   
      * the supplied list.
 254   
      */
 255   
     protected void assertLoggedMessages(String[] messages)
 256   
     {
 257   
         List events = getInterceptedLogEvents();
 258   
 
 259   
         for (int i = 0; i < messages.length; i++)
 260   
         {
 261   
             assertLoggedMessage(messages[i], events, i);
 262   
         }
 263   
     }
 264   
 
 265   
     /**
 266   
      * Asserts that some capture log event matches the given message exactly.
 267   
      */
 268   
     protected void assertLoggedMessage(String message)
 269   
     {
 270   
         assertLoggedMessage(message, getInterceptedLogEvents());
 271   
     }
 272   
 
 273   
     /**
 274   
      * Asserts that some capture log event matches the given message exactly.
 275   
      * @param message to search for; success is finding a logged message contain the parameter as a substring
 276   
      * @param events from {@link #getInterceptedLogEvents()}
 277   
      */
 278   
     protected void assertLoggedMessage(String message, List events)
 279   
     {
 280   
         int count = events.size();
 281   
 
 282   
         for (int i = 0; i < count; i++)
 283   
         {
 284   
             LoggingEvent e = (LoggingEvent) events.get(i);
 285   
 
 286   
             String eventMessage = String.valueOf(e.getMessage());
 287   
 
 288   
             if (eventMessage.indexOf(message) >= 0)
 289   
                 return;
 290   
         }
 291   
 
 292   
         throw new AssertionFailedError("Could not find logged message: " + message);
 293   
     }
 294   
 
 295   
     protected void assertLoggedMessagePattern(String pattern) throws Exception
 296   
     {
 297   
         assertLoggedMessagePattern(pattern, getInterceptedLogEvents());
 298   
     }
 299   
 
 300   
     protected void assertLoggedMessagePattern(String pattern, List events) throws Exception
 301   
     {
 302   
         setupMatcher();
 303   
 
 304   
         Pattern compiled = null;
 305   
 
 306   
         int count = events.size();
 307   
 
 308   
         for (int i = 0; i < count; i++)
 309   
         {
 310   
             LoggingEvent e = (LoggingEvent) events.get(i);
 311   
 
 312   
             String eventMessage = e.getMessage().toString();
 313   
 
 314   
             if (compiled == null)
 315   
                 compiled = _compiler.compile(pattern);
 316   
 
 317   
             if (_matcher.contains(eventMessage, compiled))
 318   
                 return;
 319   
 
 320   
         }
 321   
 
 322   
         throw new AssertionFailedError("Could not find logging event: " + pattern);
 323   
     }
 324   
 
 325   
     private void setupMatcher()
 326   
     {
 327   
         if (_compiler == null)
 328   
             _compiler = new Perl5Compiler();
 329   
 
 330   
         if (_matcher == null)
 331   
             _matcher = new Perl5Matcher();
 332   
     }
 333   
 
 334   
     /**
 335   
      * Convienience method for invoking
 336   
      * {@link #buildFrameworkRegistry(String[])} with only a single file.
 337   
      */
 338   
     protected Registry buildFrameworkRegistry(String file) throws Exception
 339   
     {
 340   
         return buildFrameworkRegistry(new String[] { file });
 341   
     }
 342   
 
 343   
     /**
 344   
      * Builds a minimal registry, containing only the specified files, plus
 345   
      * the master module descriptor (i.e., those visible on the classpath).
 346   
      * Files are resolved using {@link HiveMindTestCase#getResource(String)}.
 347   
      */
 348   
     protected Registry buildFrameworkRegistry(String[] files) throws Exception
 349   
     {
 350   
         ClassResolver resolver = new DefaultClassResolver();
 351   
 
 352   
         RegistryBuilder builder = new RegistryBuilder();
 353   
 
 354   
         for (int i = 0; i < files.length; i++)
 355   
         {
 356   
             Resource resource = getResource(files[i]);
 357   
 
 358   
             builder.processModule(resolver, resource);
 359   
         }
 360   
 
 361   
         builder.processModules(resolver);
 362   
 
 363   
         return builder.constructRegistry(Locale.getDefault());
 364   
     }
 365   
 
 366   
     /**
 367   
      * Builds a registry from exactly the provided resource; this registry
 368   
      * will not include the <code>hivemind</code> module.
 369   
      */
 370   
     protected Registry buildMinimalRegistry(Resource l) throws Exception
 371   
     {
 372   
         RegistryBuilder builder = new RegistryBuilder();
 373   
 
 374   
         builder.processModule(new DefaultClassResolver(), l);
 375   
 
 376   
         return builder.constructRegistry(Locale.getDefault());
 377   
     }
 378   
 
 379   
     /**
 380   
      * Creates a <em>managed</em> control via
 381   
      * {@link MockControl#createStrictControl(java.lang.Class)}.
 382   
      * The created control is remembered, and will be
 383   
      * invoked by {@link #replayControls()},
 384   
      * {@link #verifyControls()}, etc..
 385   
      */
 386   
     protected MockControl newControl(Class mockClass)
 387   
     {
 388   
         MockControl result = MockControl.createStrictControl(mockClass);
 389   
 
 390   
         addControl(result);
 391   
 
 392   
         return result;
 393   
     }
 394   
 
 395   
     /**
 396   
      * Adds the control to the list of managed controls used by
 397   
      * {@link #replayControls()} and {@link #verifyControls()}.
 398   
      */
 399   
     protected void addControl(MockControl control)
 400   
     {
 401   
         _controls.add(control);
 402   
     }
 403   
 
 404   
     /**
 405   
      * Convienience for invoking {@link #newControl(Class)} and then
 406   
      * invoking {@link MockControl#getMock()} on the result.
 407   
      */
 408   
     protected Object newMock(Class mockClass)
 409   
     {
 410   
         return newControl(mockClass).getMock();
 411   
     }
 412   
 
 413   
     /**
 414   
      * Invokes {@link MockControl#replay()} on all controls
 415   
      * created by {@link #newControl(Class)}.
 416   
      */
 417   
     protected void replayControls()
 418   
     {
 419   
         Iterator i = _controls.iterator();
 420   
         while (i.hasNext())
 421   
         {
 422   
             MockControl c = (MockControl) i.next();
 423   
             c.replay();
 424   
         }
 425   
     }
 426   
 
 427   
     /**
 428   
      * Invokes {@link org.easymock.MockControl#verify()} and
 429   
      * {@link MockControl#reset()} on all
 430   
      * controls created by {@link #newControl(Class)}.
 431   
      */
 432   
 
 433   
     protected void verifyControls()
 434   
     {
 435   
         Iterator i = _controls.iterator();
 436   
         while (i.hasNext())
 437   
         {
 438   
             MockControl c = (MockControl) i.next();
 439   
             c.verify();
 440   
             c.reset();
 441   
         }
 442   
     }
 443   
 
 444   
     /**
 445   
      * Invokes {@link org.easymock.MockControl#reset()} on all
 446   
      * controls.
 447   
      */
 448   
 
 449   
     protected void resetControls()
 450   
     {
 451   
         Iterator i = _controls.iterator();
 452   
         while (i.hasNext())
 453   
         {
 454   
             MockControl c = (MockControl) i.next();
 455   
             c.reset();
 456   
         }
 457   
     }
 458   
 
 459   
     protected Location fabricateLocation(int line)
 460   
     {
 461   
         String path = "/" + getClass().getName().replace('.', '/');
 462   
 
 463   
         Resource r = new ClasspathResource(new DefaultClassResolver(), path);
 464   
 
 465   
         return new LocationImpl(r, line);
 466   
     }
 467   
 
 468   
     protected boolean matches(String input, String pattern) throws Exception
 469   
     {
 470   
         setupMatcher();
 471   
 
 472   
         Pattern compiled = _compiler.compile(pattern);
 473   
 
 474   
         return _matcher.matches(input, compiled);
 475   
     }
 476   
 }
 477