2011/08/05 - Jakarta Cactus has been retired.

For more information, please explore the Attic.

Clover coverage report - Cactus 1.8dev for J2EE API 1.3
Coverage timestamp: Sun Mar 26 2006 18:50:18 BRT
file stats: LOC: 468   Methods: 19
NCLOC: 219   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
ClientTestCaseCaller.java 75% 80.9% 100% 83.2%
coverage coverage
 1   
 /* 
 2   
  * ========================================================================
 3   
  * 
 4   
  * Copyright 2001-2004 The Apache Software Foundation.
 5   
  *
 6   
  * Licensed under the Apache License, Version 2.0 (the "License");
 7   
  * you may not use this file except in compliance with the License.
 8   
  * You may obtain a copy of the License at
 9   
  * 
 10   
  *   http://www.apache.org/licenses/LICENSE-2.0
 11   
  * 
 12   
  * Unless required by applicable law or agreed to in writing, software
 13   
  * distributed under the License is distributed on an "AS IS" BASIS,
 14   
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15   
  * See the License for the specific language governing permissions and
 16   
  * limitations under the License.
 17   
  * 
 18   
  * ========================================================================
 19   
  */
 20   
 package org.apache.cactus.internal.client;
 21   
 
 22   
 import java.lang.reflect.InvocationTargetException;
 23   
 import java.lang.reflect.Method;
 24   
 
 25   
 import junit.framework.Assert;
 26   
 import junit.framework.Test;
 27   
 
 28   
 import org.apache.cactus.Request;
 29   
 import org.apache.cactus.internal.util.JUnitVersionHelper;
 30   
 import org.apache.cactus.internal.util.TestCaseImplementChecker;
 31   
 import org.apache.cactus.spi.client.ResponseObjectFactory;
 32   
 import org.apache.cactus.spi.client.connector.ProtocolHandler;
 33   
 import org.apache.cactus.spi.client.connector.ProtocolState;
 34   
 import org.apache.commons.logging.Log;
 35   
 import org.apache.commons.logging.LogFactory;
 36   
 
 37   
 /**
 38   
  * Provides the ability to run common code before and after each test on the 
 39   
  * client side. All the methods provided are independent of any communication 
 40   
  * protocol between client side and server side (HTTP, JMS, etc). Any protocol 
 41   
  * dependent methods must be provided and implemented in the 
 42   
  * {@link ProtocolHandler} implementation class.
 43   
  *  
 44   
  * @version $Id: ClientTestCaseCaller.java 238991 2004-05-22 11:34:50Z vmassol $
 45   
  */
 46   
 public class ClientTestCaseCaller extends Assert
 47   
 {
 48   
     /**
 49   
      * The prefix of a test method.
 50   
      */
 51   
     protected static final String TEST_METHOD_PREFIX = "test";
 52   
 
 53   
     /**
 54   
      * The prefix of a begin test method.
 55   
      */
 56   
     protected static final String BEGIN_METHOD_PREFIX = "begin";
 57   
 
 58   
     /**
 59   
      * The prefix of an end test method.
 60   
      */
 61   
     protected static final String END_METHOD_PREFIX = "end";
 62   
 
 63   
     /**
 64   
      * The name of the method that is called before each test on the client
 65   
      * side (if it exists).
 66   
      */
 67   
     protected static final String CLIENT_GLOBAL_BEGIN_METHOD = "begin";
 68   
 
 69   
     /**
 70   
      * The name of the method that is called after each test on the client
 71   
      * side (if it exists).
 72   
      */
 73   
     protected static final String CLIENT_GLOBAL_END_METHOD = "end";
 74   
 
 75   
     /**
 76   
      * The logger (only used on the client side).
 77   
      */
 78   
     private Log logger;
 79   
 
 80   
     /**
 81   
      * Pure JUnit Test Case that we are wrapping (if any)
 82   
      */
 83   
     private Test wrappedTest;
 84   
 
 85   
     /**
 86   
      * The test we are delegating for.
 87   
      */
 88   
     private Test delegatedTest;   
 89   
 
 90   
     /**
 91   
      * The protocol handler to use to execute the tests on the server side.
 92   
      */
 93   
     private ProtocolHandler protocolHandler;
 94   
 
 95   
     // Constructors ---------------------------------------------------------
 96   
     
 97   
     /**
 98   
      * @param theDelegatedTest the test we are delegating for
 99   
      * @param theWrappedTest the test being wrapped by this delegate (or null 
 100   
      *        if none)
 101   
      * @param theProtocolHandler the protocol handler to use to execute the 
 102   
      *        tests on the server side 
 103   
      */
 104  48
     public ClientTestCaseCaller(Test theDelegatedTest, 
 105   
         Test theWrappedTest, ProtocolHandler theProtocolHandler)
 106   
     {        
 107  48
         if (theDelegatedTest == null)
 108   
         {
 109  0
             throw new IllegalStateException(
 110   
                 "The test object passed must not be null");
 111   
         }
 112   
 
 113  48
         setDelegatedTest(theDelegatedTest); 
 114  48
         setWrappedTest(theWrappedTest);
 115  48
         this.protocolHandler = theProtocolHandler;
 116   
     }
 117   
 
 118   
     // Public methods -------------------------------------------------------
 119   
     
 120   
     /**
 121   
      * Execute begin and end methods and calls the different 
 122   
      * {@link ProtocolHandler} lifecycle methods to execute the test
 123   
      * on the server side.
 124   
      * 
 125   
      * Note that this method is overriden from the JUnit 
 126   
      * {@link junit.framework.TestCase} class in order to prevent JUnit from 
 127   
      * calling the {@link junit.framework.TestCase#setUp()} and
 128   
      * {@link junit.framework.TestCase#tearDown()} methods on the client side.
 129   
      * instead we are calling the server redirector proxy and the setup and
 130   
      * teardown methods will be executed on the server side.
 131   
      *
 132   
      * @exception Throwable if any error happens during the execution of
 133   
      *            the test
 134   
      */
 135  24
     public void runTest() throws Throwable
 136   
     {
 137  24
         Request request = this.protocolHandler.createRequest();
 138   
         
 139   
         // Call the set up and begin methods to fill the request object
 140  24
         callGlobalBeginMethod(request);
 141  24
         callBeginMethod(request);
 142   
 
 143   
         // Run the server test
 144  24
         ProtocolState state = this.protocolHandler.runTest(
 145   
             getDelegatedTest(), getWrappedTest(), request);
 146   
         
 147   
         // Call the end method
 148  24
         Object response = callEndMethod(request, 
 149   
             this.protocolHandler.createResponseObjectFactory(state));
 150   
 
 151   
         // call the tear down method
 152  24
         callGlobalEndMethod(request, 
 153   
             this.protocolHandler.createResponseObjectFactory(state), 
 154   
             response);
 155   
 
 156  24
         this.protocolHandler.afterTest(state);
 157   
     }
 158   
 
 159   
     /**
 160   
      * @return The logger used by the <code>TestCase</code> class and
 161   
      *         subclasses to perform logging.
 162   
      */
 163  24
     public final Log getLogger()
 164   
     {
 165  24
         return this.logger;
 166   
     }
 167   
 
 168   
     /**
 169   
      * Perform client side initializations before each test, such as
 170   
      * re-initializating the logger and printing some logging information.
 171   
      */
 172  24
     public void runBareInit()
 173   
     {
 174   
         // We make sure we reinitialize The logger with the name of the
 175   
         // current extending class so that log statements will contain the
 176   
         // actual class name (that's why the logged instance is not static).
 177  24
         this.logger = LogFactory.getLog(this.getClass());
 178   
 
 179   
         // Mark beginning of test on client side
 180  24
         getLogger().debug("------------- Test: " + this.getCurrentTestName());
 181   
     }
 182   
 
 183   
     /**
 184   
      * Call the test case begin method.
 185   
      *
 186   
      * @param theRequest the request object to pass to the begin method.
 187   
      * @exception Throwable any error that occurred when calling the begin
 188   
      *            method for the current test case.
 189   
      */
 190  24
     public void callBeginMethod(Request theRequest) throws Throwable
 191   
     {
 192  24
         callGenericBeginMethod(theRequest, getBeginMethodName());
 193   
     }
 194   
 
 195   
     /**
 196   
      * Call the test case end method
 197   
      *
 198   
      * @param theRequest the request data that were used to open the
 199   
      *                   connection.
 200   
      * @param theResponseFactory the factory to use to return response objects.
 201   
      * @return the created Reponse object
 202   
      * @exception Throwable any error that occurred when calling the end method
 203   
      *         for the current test case.
 204   
      */
 205  24
     public Object callEndMethod(Request theRequest, 
 206   
         ResponseObjectFactory theResponseFactory) throws Throwable
 207   
     {
 208  24
         return callGenericEndMethod(theRequest, theResponseFactory,
 209   
             getEndMethodName(), null);
 210   
     }
 211   
 
 212   
     /**
 213   
      * Call the global begin method. This is the method that is called before
 214   
      * each test if it exists. It is called on the client side only.
 215   
      *
 216   
      * @param theRequest the request object which will contain data that will
 217   
      *        be used to connect to the Cactus server side redirectors.
 218   
      * @exception Throwable any error that occurred when calling the method
 219   
      */
 220  24
     public void callGlobalBeginMethod(Request theRequest) throws Throwable
 221   
     {
 222  24
         callGenericBeginMethod(theRequest, CLIENT_GLOBAL_BEGIN_METHOD);
 223   
     }
 224   
 
 225   
     /**
 226   
      * Call the client tear down up method if it exists.
 227   
      *
 228   
      * @param theRequest the request data that were used to open the
 229   
      *                   connection.
 230   
      * @param theResponseFactory the factory to use to return response objects.
 231   
      * @param theResponse the Response object if it exists. Can be null in
 232   
      *        which case it is created from the response object factory
 233   
      * @exception Throwable any error that occurred when calling the method
 234   
      */
 235  24
     private void callGlobalEndMethod(Request theRequest, 
 236   
         ResponseObjectFactory theResponseFactory, Object theResponse) 
 237   
         throws Throwable
 238   
     {
 239  24
         callGenericEndMethod(theRequest, theResponseFactory,
 240   
             CLIENT_GLOBAL_END_METHOD, theResponse);
 241   
     }
 242   
     
 243   
     // Private methods ------------------------------------------------------
 244   
     
 245   
     /**
 246   
      * @param theWrappedTest the pure JUnit test that we need to wrap 
 247   
      */
 248  48
     private void setWrappedTest(Test theWrappedTest)
 249   
     {
 250  48
         this.wrappedTest = theWrappedTest;
 251   
     }
 252   
 
 253   
     /**
 254   
      * @param theDelegatedTest the test we are delegating for
 255   
      */
 256  48
     private void setDelegatedTest(Test theDelegatedTest)
 257   
     {
 258  48
         this.delegatedTest = theDelegatedTest;
 259   
     }
 260   
 
 261   
     /**
 262   
      * @return the wrapped JUnit test
 263   
      */
 264  137
     private Test getWrappedTest()
 265   
     {
 266  137
         return this.wrappedTest;
 267   
     }
 268   
 
 269   
     /**
 270   
      * @return the test we are delegating for
 271   
      */
 272  257
     private Test getDelegatedTest()
 273   
     {
 274  257
         return this.delegatedTest;
 275   
     }
 276   
 
 277   
     /**
 278   
      * @return the test on which we will operate. If there is a wrapped
 279   
      *         test then the returned test is the wrapped test. Otherwise we
 280   
      *         return the delegated test.
 281   
      */
 282  113
     private Test getTest()
 283   
     {
 284  113
         Test activeTest;
 285  113
         if (getWrappedTest() != null)
 286   
         {
 287  0
             activeTest = getWrappedTest();
 288   
         }
 289   
         else
 290   
         {
 291  113
             activeTest = getDelegatedTest();
 292   
         }
 293  113
         return activeTest;
 294   
     }
 295   
 
 296   
     /**
 297   
      * @return the name of the test method to call without the
 298   
      *         TEST_METHOD_PREFIX prefix
 299   
      */
 300  48
     private String getBaseMethodName()
 301   
     {
 302   
         // Sanity check
 303  48
         if (!getCurrentTestName().startsWith(TEST_METHOD_PREFIX))
 304   
         {
 305  0
             throw new RuntimeException("bad name ["
 306   
                 + getCurrentTestName()
 307   
                 + "]. It should start with ["
 308   
                 + TEST_METHOD_PREFIX + "].");
 309   
         }
 310   
 
 311  48
         return getCurrentTestName().substring(
 312   
             TEST_METHOD_PREFIX.length());
 313   
     }
 314   
 
 315   
     /**
 316   
      * @return the name of the test begin method to call that initialize the
 317   
      *         test by initializing the <code>WebRequest</code> object
 318   
      *         for the test case.
 319   
      */
 320  24
     private String getBeginMethodName()
 321   
     {
 322  24
         return BEGIN_METHOD_PREFIX + getBaseMethodName();
 323   
     }
 324   
 
 325   
     /**
 326   
      * @return the name of the test end method to call when the test has been
 327   
      *         run on the server. It can be used to verify returned headers,
 328   
      *         cookies, ...
 329   
      */
 330  24
     private String getEndMethodName()
 331   
     {
 332  24
         return END_METHOD_PREFIX + getBaseMethodName();
 333   
     }
 334   
 
 335   
     /**
 336   
      * Call a begin method which takes Cactus WebRequest as parameter
 337   
      *
 338   
      * @param theRequest the request object which will contain data that will
 339   
      *        be used to connect to the Cactus server side redirectors.
 340   
      * @param theMethodName the name of the begin method to call
 341   
      * @exception Throwable any error that occurred when calling the method
 342   
      */
 343  48
     private void callGenericBeginMethod(Request theRequest, 
 344   
         String theMethodName) throws Throwable
 345   
     {
 346   
         // First, verify if a begin method exist. If one is found, verify if
 347   
         // it has the correct signature. If not, send a warning.
 348  48
         Method[] methods = getTest().getClass().getMethods();
 349   
 
 350  48
         for (int i = 0; i < methods.length; i++)
 351   
         {
 352  2795
             if (methods[i].getName().equals(theMethodName))
 353   
             {
 354  6
                 TestCaseImplementChecker.checkAsBeginMethod(methods[i]);
 355   
 
 356  6
                 try
 357   
                 {
 358  6
                     methods[i].invoke(getTest(), new Object[] {theRequest});
 359   
 
 360  6
                     break;
 361   
                 }
 362   
                 catch (InvocationTargetException e)
 363   
                 {
 364  0
                     e.fillInStackTrace();
 365  0
                     throw e.getTargetException();
 366   
                 }
 367   
                 catch (IllegalAccessException e)
 368   
                 {
 369  0
                     e.fillInStackTrace();
 370  0
                     throw e;
 371   
                 }
 372   
             }
 373   
         }
 374   
     }
 375   
 
 376   
     /**
 377   
      * Call the global end method. This is the method that is called after
 378   
      * each test if it exists. It is called on the client side only.
 379   
      *
 380   
      * @param theRequest the request data that were used to open the
 381   
      *        connection.
 382   
      * @param theResponseFactory the factory to use to return response objects.
 383   
      * @param theMethodName the name of the end method to call
 384   
      * @param theResponse the Response object if it exists. Can be null in
 385   
      *        which case it is created from the response object factory
 386   
      * @return the created Reponse object
 387   
      * @exception Throwable any error that occurred when calling the end method
 388   
      *            for the current test case.
 389   
      */
 390  48
     private Object callGenericEndMethod(Request theRequest,
 391   
         ResponseObjectFactory theResponseFactory, String theMethodName, 
 392   
         Object theResponse) throws Throwable
 393   
     {
 394  48
         Method methodToCall = null;
 395  48
         Object paramObject = null;
 396   
 
 397  48
         Method[] methods = getTest().getClass().getMethods();
 398   
 
 399  48
         for (int i = 0; i < methods.length; i++)
 400   
         {
 401  3174
             if (methods[i].getName().equals(theMethodName))
 402   
             {
 403  11
                 TestCaseImplementChecker.checkAsEndMethod(methods[i]);
 404   
 
 405  11
                 paramObject = theResponse;
 406   
 
 407  11
                 if (paramObject == null)
 408   
                 {
 409  11
                     Class[] parameters = methods[i].getParameterTypes();
 410  11
                     try
 411   
                     {
 412  11
                         paramObject = theResponseFactory.getResponseObject(
 413   
                             parameters[0].getName(), theRequest);
 414   
                     }
 415   
                     catch (ClientException e)
 416   
                     {
 417  0
                         throw new ClientException("The method ["
 418   
                             + methods[i].getName() 
 419   
                             + "] has a bad parameter of type ["
 420   
                             + parameters[0].getName() + "]", e);
 421   
                     }
 422   
                 }
 423   
 
 424   
                 // Has a method to call already been found ?
 425  11
                 if (methodToCall != null)
 426   
                 {
 427  0
                     fail("There can only be one method ["
 428   
                        + methods[i].getName() + "] per test case. "
 429   
                        + "Test case [" + this.getCurrentTestName()
 430   
                        + "] has two at least !");
 431   
                 }
 432   
 
 433  11
                 methodToCall = methods[i];
 434   
             }
 435   
         }
 436   
 
 437  48
         if (methodToCall != null)
 438   
         {
 439  11
             try
 440   
             {
 441  11
                 methodToCall.invoke(getTest(), new Object[] {paramObject});
 442   
             }
 443   
             catch (InvocationTargetException e)
 444   
             {
 445  0
                 e.fillInStackTrace();
 446  0
                 throw e.getTargetException();
 447   
             }
 448   
             catch (IllegalAccessException e)
 449   
             {
 450  0
                 e.fillInStackTrace();
 451  0
                 throw e;
 452   
             }
 453   
         }
 454   
 
 455  48
         return paramObject;
 456   
     }
 457   
     
 458   
     /**
 459   
      * @return the name of the current test case being executed (it corresponds
 460   
      *         to the name of the test method with the "test" prefix removed.
 461   
      *         For example, for "testSomeTestOk" would return "someTestOk".
 462   
      */
 463  120
     private String getCurrentTestName()
 464   
     {
 465  120
         return JUnitVersionHelper.getTestCaseName(getDelegatedTest());        
 466   
     }
 467   
 }
 468