    1   /*
    2    * $Id: TestActionServlet.java 471754 2006-11-06 14:55:09Z husted $
    3    *
    4    * Licensed to the Apache Software Foundation (ASF) under one
    5    * or more contributor license agreements.  See the NOTICE file
    6    * distributed with this work for additional information
    7    * regarding copyright ownership.  The ASF licenses this file
    8    * to you under the Apache License, Version 2.0 (the
    9    * "License"); you may not use this file except in compliance
    10   * with the License.  You may obtain a copy of the License at
    11   *
    12   *  http://www.apache.org/licenses/LICENSE-2.0
    13   *
    14   * Unless required by applicable law or agreed to in writing,
    15   * software distributed under the License is distributed on an
    16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    17   * KIND, either express or implied.  See the License for the
    18   * specific language governing permissions and limitations
    19   * under the License.
    20   */
    21  package org.apache.struts.action;
    22
    23  import junit.framework.Test;
    24  import junit.framework.TestCase;
    25  import junit.framework.TestSuite;
    26
    27  import org.apache.struts.config.ActionConfig;
    28  import org.apache.struts.config.ExceptionConfig;
    29  import org.apache.struts.config.FormBeanConfig;
    30  import org.apache.struts.config.FormPropertyConfig;
    31  import org.apache.struts.config.ForwardConfig;
    32  import org.apache.struts.config.ModuleConfig;
    33  import org.apache.struts.config.ModuleConfigFactory;
    34  import org.apache.struts.util.MessageResources;
    35
    36  import javax.servlet.ServletException;
    37  import javax.servlet.UnavailableException;
    38
    39  import java.util.List;
    40
    41  /**
    42   * Suite of unit tests for the <code>org.apache.struts.action.ActionServlet</code>
    43   * class.
    44   */
    45  public class TestActionServlet extends TestCase {
    46      // ----------------------------------------------------- Instance Variables
    47
    48      /**
    49       * The ModuleConfig we'll use.
    50       */
    51      protected ModuleConfig moduleConfig = null;
    52
    53      /**
    54       * The common form bean we'll use.
    55       */
    56      protected FormBeanConfig baseFormBean = null;
    57
    58      /**
    59       * The common exception config we'll use.
    60       */
    61      protected ExceptionConfig baseException = null;
    62
    63      /**
    64       * The common action config we'll use.
    65       */
    66      protected ActionMapping baseAction = null;
    67
    68      /**
    69       * The common action forward we'll use.
    70       */
    71      protected ActionForward baseForward = null;
    72
    73      /**
    74       * The ActionServlet we'll test.
    75       */
    76      protected ActionServlet actionServlet = null;
    77
    78      // ------------------------------------------ Constructors, suite, and main
    79
    80      /**
    81       * Defines the testcase name for JUnit.
    82       *
    83       * @param theName the testcase's name.
    84       */
    85      public TestActionServlet(String theName) {
    86          super(theName);
    87      }
    88
    89      /**
    90       * Start the tests.
    91       *
    92       * @param theArgs the arguments. Not used
    93       */
    94      public static void main(String[] theArgs) {
    95          junit.awtui.TestRunner.main(new String[] {
    96                  TestActionServlet.class.getName()
    97              });
    98      }
    99
    100     /**
    101      * @return a test suite (<code>TestSuite</code>) that includes all methods
    102      *         starting with "test"
    103      */
    104     public static Test suite() {
    105         // All methods starting with "test" will be executed in the test suite.
    106         return new TestSuite(TestActionServlet.class);
    107     }
    108
    109     // ------------------------------------------------- setUp() and tearDown()
    110
    111     /**
    112      * Set up instance variables required by this test case.
    113      */
    114     public void setUp() throws Exception {
    115         actionServlet = new ActionServlet();
    116         actionServlet.initInternal();
    117
    118         ModuleConfigFactory factoryObject = ModuleConfigFactory.createFactory();
    119
    120         moduleConfig = factoryObject.createModuleConfig("");
    121
    122         // Setup the base form
    123         baseFormBean = new FormBeanConfig();
    124         baseFormBean.setName("baseForm");
    125         baseFormBean.setType("org.apache.struts.action.DynaActionForm");
    126
    127         // Set up id, name, and score
    128         FormPropertyConfig property = new FormPropertyConfig();
    129
    130         property.setName("id");
    131         property.setType("java.lang.String");
    132         baseFormBean.addFormPropertyConfig(property);
    133
    134         property = new FormPropertyConfig();
    135         property.setName("name");
    136         property.setType("java.lang.String");
    137         baseFormBean.addFormPropertyConfig(property);
    138
    139         property = new FormPropertyConfig();
    140         property.setName("score");
    141         property.setType("java.lang.String");
    142         baseFormBean.addFormPropertyConfig(property);
    143
    144         // Setup the exception handler
    145         baseException = new ExceptionConfig();
    146         baseException.setType("java.lang.NullPointerException");
    147         baseException.setKey("msg.exception.npe");
    148
    149         // Setup the forward config
    150         baseForward = new ActionForward("success", "/succes.jsp", false);
    151
    152         // Setup the action config
    153         baseAction = new ActionMapping();
    154         baseAction.setPath("/index");
    155         baseAction.setType("org.apache.struts.actions.DummyAction");
    156         baseAction.setName("someForm");
    157         baseAction.setInput("/input.jsp");
    158         baseAction.addForwardConfig(new ActionForward("next", "/next.jsp", false));
    159         baseAction.addForwardConfig(new ActionForward("prev", "/prev.jsp", false));
    160
    161         ExceptionConfig exceptionConfig = new ExceptionConfig();
    162
    163         exceptionConfig.setType("java.sql.SQLException");
    164         exceptionConfig.setKey("msg.exception.sql");
    165         baseAction.addExceptionConfig(exceptionConfig);
    166
    167         // Nothing is registered to our module config until they are needed
    168     }
    169
    170     /**
    171      * Tear down instance variables required by this test case.
    172      */
    173     public void tearDown() {
    174         moduleConfig = null;
    175     }
    176
    177     // ----------------------------- initInternal() and destroyInternal() tests
    178
    179     /**
    180      * Verify that we can initialize and destroy our internal message
    181      * resources object.
    182      */
    183     public void testInitDestroyInternal() {
    184         ActionServlet servlet = new ActionServlet();
    185
    186         try {
    187             servlet.initInternal();
    188         } catch (ServletException e) {
    189             fail("initInternal() threw exception: " + e);
    190         }
    191
    192         assertTrue("internal was initialized", servlet.getInternal() != null);
    193         assertTrue("internal of correct type",
    194             servlet.getInternal() instanceof MessageResources);
    195         servlet.destroyInternal();
    196         assertTrue("internal was destroyed", servlet.getInternal() == null);
    197     }
    198
    199     /**
    200      * Test class loader resolution and splitting.
    201      */
    202     public void notestSplitAndResolvePaths()
    203         throws Exception {
    204         ActionServlet servlet = new ActionServlet();
    205         List list =
    206             servlet.splitAndResolvePaths(
    207                 "org/apache/struts/config/struts-config.xml");
    208
    209         assertNotNull(list);
    210         assertTrue("List size should be 1", list.size() == 1);
    211
    212         list =
    213             servlet.splitAndResolvePaths(
    214                 "org/apache/struts/config/struts-config.xml, "
    215                 + "org/apache/struts/config/struts-config-1.1.xml");
    216         assertNotNull(list);
    217         assertTrue("List size should be 2, was " + list.size(), list.size() == 2);
    218
    219         list = servlet.splitAndResolvePaths("META-INF/MANIFEST.MF");
    220         assertNotNull(list);
    221         assertTrue("Number of manifests should be more than 5, was "
    222             + list.size(), list.size() > 5);
    223
    224         // test invalid path
    225         try {
    226             list =
    227                 servlet.splitAndResolvePaths(
    228                     "org/apache/struts/config/struts-asdfasdfconfig.xml");
    229             fail("Should have thrown an exception on bad path");
    230         } catch (NullPointerException ex) {
    231             // correct behavior since internal error resources aren't loaded
    232         }
    233     }
    234
    235     //----- Test initApplication() method --------------------------------------
    236
    237     /**
    238      * Verify that nothing happens if no "application" property is defined in
    239      * the servlet configuration.
    240      */
    241
    242     /*
    243     public void testInitApplicationNull() throws ServletException
    244     {
    245         ActionServlet servlet = new ActionServlet();
    246         servlet.init(config);
    247
    248         // Test the initApplication() method
    249         servlet.initApplication();
    250
    251         // As no "application" object is found in the servlet config, no
    252         // attribute should be set in the context
    253         assertTrue(config.getServletContext().getAttribute(Action.MESSAGES_KEY) == null);
    254     }
    255     */
    256
    257     /**
    258      * Verify that eveything is fine when only a "application" parameter is
    259      * defined in the servlet configuration.
    260      */
    261
    262     /*
    263     public void testInitApplicationOk1() throws ServletException
    264     {
    265         // initialize config
    266         config.setInitParameter("application", "org.apache.struts.webapp.example.ApplicationResources");
    267
    268         ActionServlet servlet = new ActionServlet();
    269         servlet.init(config);
    270
    271         // Test the initApplication() method
    272         servlet.initApplication();
    273
    274         assertTrue(servlet.application != null);
    275         assertTrue(servlet.application.getReturnNull() == true);
    276
    277         assertTrue(config.getServletContext().getAttribute(Action.MESSAGES_KEY) != null);
    278         assertEquals(servlet.application, config.getServletContext().getAttribute(Action.MESSAGES_KEY));
    279
    280     }
    281     */
    282
    283     // --------------------------------------------------- FormBeanConfig Tests
    284
    285     /**
    286      * Test that nothing fails if there are no extensions.
    287      */
    288     public void testInitModuleFormBeansNoExtends()
    289         throws ServletException {
    290         moduleConfig.addFormBeanConfig(baseFormBean);
    291
    292         try {
    293             actionServlet.initModuleExceptionConfigs(moduleConfig);
    294         } catch (Exception e) {
    295             fail("Unexpected exception caught.");
    296         }
    297     }
    298
    299     /**
    300      * Test that initModuleFormBeans throws an exception when a form with a
    301      * null type is present.
    302      */
    303     public void testInitModuleFormBeansNullFormType()
    304         throws ServletException {
    305         FormBeanConfig formBean = new FormBeanConfig();
    306
    307         formBean.setName("noTypeForm");
    308         moduleConfig.addFormBeanConfig(formBean);
    309
    310         try {
    311             actionServlet.initModuleFormBeans(moduleConfig);
    312             fail("An exception should've been thrown here.");
    313         } catch (UnavailableException e) {
    314             // success
    315         } catch (Exception e) {
    316             fail("Unrecognized exception thrown: " + e);
    317         }
    318     }
    319
    320     /**
    321      * Test that initModuleFormBeans throws an exception when a form whose
    322      * prop type is null is present.
    323      */
    324     public void testInitModuleFormBeansNullPropType()
    325         throws ServletException {
    326         moduleConfig.addFormBeanConfig(baseFormBean);
    327         baseFormBean.findFormPropertyConfig("name").setType(null);
    328
    329         try {
    330             actionServlet.initModuleFormBeans(moduleConfig);
    331             fail("An exception should've been thrown here.");
    332         } catch (UnavailableException e) {
    333             // success
    334         } catch (Exception e) {
    335             fail("Unrecognized exception thrown: " + e);
    336         }
    337     }
    338
    339     /**
    340      * Test that processFormBeanExtension() calls processExtends()
    341      */
    342     public void testProcessFormBeanExtension()
    343         throws ServletException {
    344         CustomFormBeanConfig form = new CustomFormBeanConfig();
    345
    346         actionServlet.processFormBeanExtension(form, moduleConfig);
    347
    348         assertTrue("processExtends() was not called", form.processExtendsCalled);
    349     }
    350
    351     /**
    352      * Make sure processFormBeanConfigClass() returns an instance of the
    353      * correct class if the base config is using a custom class.
    354      */
    355     public void testProcessFormBeanConfigClass()
    356         throws Exception {
    357         CustomFormBeanConfig customBase = new CustomFormBeanConfig();
    358
    359         customBase.setName("customBase");
    360         moduleConfig.addFormBeanConfig(customBase);
    361
    362         FormBeanConfig customSub = new FormBeanConfig();
    363
    364         customSub.setName("customSub");
    365         customSub.setExtends("customBase");
    366         customSub.setType("org.apache.struts.action.DynaActionForm");
    367         moduleConfig.addFormBeanConfig(customSub);
    368
    369         FormBeanConfig result =
    370             actionServlet.processFormBeanConfigClass(customSub, moduleConfig);
    371
    372         assertTrue("Incorrect class of form bean config",
    373             result instanceof CustomFormBeanConfig);
    374         assertEquals("Incorrect name", customSub.getName(), result.getName());
    375         assertEquals("Incorrect type", customSub.getType(), result.getType());
    376         assertEquals("Incorrect extends", customSub.getExtends(),
    377             result.getExtends());
    378         assertEquals("Incorrect 'restricted' value", customSub.isRestricted(),
    379             result.isRestricted());
    380
    381         assertSame("Result was not registered in the module config", result,
    382             moduleConfig.findFormBeanConfig("customSub"));
    383     }
    384
    385     /**
    386      * Make sure processFormBeanConfigClass() returns what it was given if the
    387      * form passed to it doesn't extend anything.
    388      */
    389     public void testProcessFormBeanConfigClassNoExtends()
    390         throws Exception {
    391         moduleConfig.addFormBeanConfig(baseFormBean);
    392
    393         FormBeanConfig result = null;
    394
    395         try {
    396             result =
    397                 actionServlet.processFormBeanConfigClass(baseFormBean,
    398                     moduleConfig);
    399         } catch (UnavailableException e) {
    400             fail("An exception should not be thrown when there's nothing to do");
    401         }
    402
    403         assertSame("Result should be the same as the input.", baseFormBean,
    404             result);
    405     }
    406
    407     /**
    408      * Make sure processFormBeanConfigClass() returns the same class instance
    409      * if the base config isn't using a custom class.
    410      */
    411     public void testProcessFormBeanConfigClassSubFormCustomClass()
    412         throws Exception {
    413         moduleConfig.addFormBeanConfig(baseFormBean);
    414
    415         FormBeanConfig customSub = new FormBeanConfig();
    416
    417         customSub.setName("customSub");
    418         customSub.setExtends("baseForm");
    419         moduleConfig.addFormBeanConfig(customSub);
    420
    421         FormBeanConfig result =
    422             actionServlet.processFormBeanConfigClass(customSub, moduleConfig);
    423
    424         assertSame("The instance returned should be the param given it.",
    425             customSub, result);
    426     }
    427
    428     /**
    429      * Make sure the code throws the correct exception when it can't create an
    430      * instance of the base config's custom class.
    431      */
    432     public void notestProcessFormBeanConfigClassError()
    433         throws Exception {
    434         CustomFormBeanConfigArg customBase =
    435             new CustomFormBeanConfigArg("customBase");
    436
    437         moduleConfig.addFormBeanConfig(customBase);
    438
    439         FormBeanConfig customSub = new FormBeanConfig();
    440
    441         customSub.setName("customSub");
    442         customSub.setExtends("customBase");
    443         moduleConfig.addFormBeanConfig(customSub);
    444
    445         try {
    446             actionServlet.processFormBeanConfigClass(customSub, moduleConfig);
    447             fail("Exception should be thrown");
    448         } catch (UnavailableException e) {
    449             // success
    450         } catch (Exception e) {
    451             fail("Unexpected exception thrown.");
    452         }
    453     }
    454
    455     /**
    456      * Test the case where the subform has already specified its own form bean
    457      * config class.  If the code still attempts to create a new instance, an
    458      * error will be thrown.
    459      */
    460     public void testProcessFormBeanConfigClassOverriddenSubFormClass()
    461         throws Exception {
    462         CustomFormBeanConfigArg customBase =
    463             new CustomFormBeanConfigArg("customBase");
    464
    465         moduleConfig.addFormBeanConfig(customBase);
    466
    467         FormBeanConfig customSub = new CustomFormBeanConfigArg("customSub");
    468
    469         customSub.setExtends("customBase");
    470         moduleConfig.addFormBeanConfig(customSub);
    471
    472         try {
    473             actionServlet.processFormBeanConfigClass(customSub, moduleConfig);
    474         } catch (Exception e) {
    475             fail("Exception should not be thrown");
    476         }
    477     }
    478
    479     // -------------------------------------------------- ExceptionConfig Tests
    480
    481     /**
    482      * Test that nothing fails if there are no extensions.
    483      */
    484     public void testInitModuleExceptionConfigsNoExtends()
    485         throws ServletException {
    486         moduleConfig.addExceptionConfig(baseException);
    487
    488         try {
    489             actionServlet.initModuleExceptionConfigs(moduleConfig);
    490         } catch (Exception e) {
    491             fail("Unexpected exception caught.");
    492         }
    493     }
    494
    495     /**
    496      * Test that initModuleExceptionConfigs throws an exception when a handler
    497      * with a null key is present.
    498      */
    499     public void testInitModuleExceptionConfigsNullFormType()
    500         throws ServletException {
    501         ExceptionConfig handler = new ExceptionConfig();
    502
    503         handler.setType("java.lang.NullPointerException");
    504         moduleConfig.addExceptionConfig(handler);
    505
    506         try {
    507             actionServlet.initModuleExceptionConfigs(moduleConfig);
    508             fail("An exception should've been thrown here.");
    509         } catch (UnavailableException e) {
    510             // success
    511         } catch (Exception e) {
    512             fail("Unrecognized exception thrown: " + e);
    513         }
    514     }
    515
    516     /**
    517      * Test that processExceptionExtension() calls processExtends()
    518      */
    519     public void testProcessExceptionExtension()
    520         throws ServletException {
    521         CustomExceptionConfig handler = new CustomExceptionConfig();
    522
    523         handler.setType("java.lang.NullPointerException");
    524         moduleConfig.addExceptionConfig(handler);
    525         actionServlet.processExceptionExtension(handler, moduleConfig, null);
    526
    527         assertTrue("processExtends() was not called",
    528             handler.processExtendsCalled);
    529     }
    530
    531     /**
    532      * Make sure processExceptionConfigClass() returns an instance of the
    533      * correct class if the base config is using a custom class.
    534      */
    535     public void testProcessExceptionConfigClass()
    536         throws Exception {
    537         CustomExceptionConfig customBase = new CustomExceptionConfig();
    538
    539         customBase.setType("java.lang.NullPointerException");
    540         customBase.setKey("msg.exception.npe");
    541         moduleConfig.addExceptionConfig(customBase);
    542
    543         ExceptionConfig customSub = new ExceptionConfig();
    544
    545         customSub.setType("java.lang.IllegalStateException");
    546         customSub.setExtends("java.lang.NullPointerException");
    547         moduleConfig.addExceptionConfig(customSub);
    548
    549         ExceptionConfig result =
    550             actionServlet.processExceptionConfigClass(customSub, moduleConfig,
    551                 null);
    552
    553         assertTrue("Incorrect class of exception config",
    554             result instanceof CustomExceptionConfig);
    555         assertEquals("Incorrect type", customSub.getType(), result.getType());
    556         assertEquals("Incorrect key", customSub.getKey(), result.getKey());
    557         assertEquals("Incorrect extends", customSub.getExtends(),
    558             result.getExtends());
    559
    560         assertSame("Result was not registered in the module config", result,
    561             moduleConfig.findExceptionConfig("java.lang.IllegalStateException"));
    562     }
    563
    564     /**
    565      * Make sure processExceptionConfigClass() returns what it was given if
    566      * the handler passed to it doesn't extend anything.
    567      */
    568     public void testProcessExceptionConfigClassNoExtends()
    569         throws Exception {
    570         moduleConfig.addExceptionConfig(baseException);
    571
    572         ExceptionConfig result = null;
    573
    574         try {
    575             result =
    576                 actionServlet.processExceptionConfigClass(baseException,
    577                     moduleConfig, null);
    578         } catch (UnavailableException e) {
    579             fail("An exception should not be thrown when there's nothing to do");
    580         }
    581
    582         assertSame("Result should be the same as the input.", baseException,
    583             result);
    584     }
    585
    586     /**
    587      * Make sure processExceptionConfigClass() returns the same class instance
    588      * if the base config isn't using a custom class.
    589      */
    590     public void testProcessExceptionConfigClassSubConfigCustomClass()
    591         throws Exception {
    592         moduleConfig.addExceptionConfig(baseException);
    593
    594         ExceptionConfig customSub = new ExceptionConfig();
    595
    596         customSub.setType("java.lang.IllegalStateException");
    597         customSub.setExtends("java.lang.NullPointerException");
    598         moduleConfig.addExceptionConfig(customSub);
    599
    600         ExceptionConfig result =
    601             actionServlet.processExceptionConfigClass(customSub, moduleConfig,
    602                 null);
    603
    604         assertSame("The instance returned should be the param given it.",
    605             customSub, result);
    606     }
    607
    608     /**
    609      * Make sure the code throws the correct exception when it can't create an
    610      * instance of the base config's custom class.
    611      */
    612     public void notestProcessExceptionConfigClassError()
    613         throws Exception {
    614         ExceptionConfig customBase =
    615             new CustomExceptionConfigArg("java.lang.NullPointerException");
    616
    617         moduleConfig.addExceptionConfig(customBase);
    618
    619         ExceptionConfig customSub = new ExceptionConfig();
    620
    621         customSub.setType("java.lang.IllegalStateException");
    622         customSub.setExtends("java.lang.NullPointerException");
    623         moduleConfig.addExceptionConfig(customSub);
    624
    625         try {
    626             actionServlet.processExceptionConfigClass(customSub, moduleConfig,
    627                 null);
    628             fail("Exception should be thrown");
    629         } catch (UnavailableException e) {
    630             // success
    631         } catch (Exception e) {
    632             fail("Unexpected exception thrown.");
    633         }
    634     }
    635
    636     /**
    637      * Test the case where the subconfig has already specified its own config
    638      * class.  If the code still attempts to create a new instance, an error
    639      * will be thrown.
    640      */
    641     public void testProcessExceptionConfigClassOverriddenSubFormClass()
    642         throws Exception {
    643         moduleConfig.addExceptionConfig(baseException);
    644
    645         ExceptionConfig customSub =
    646             new CustomExceptionConfigArg("java.lang.IllegalStateException");
    647
    648         customSub.setExtends("java.lang.NullPointerException");
    649         moduleConfig.addExceptionConfig(customSub);
    650
    651         try {
    652             actionServlet.processExceptionConfigClass(customSub, moduleConfig,
    653                 null);
    654         } catch (Exception e) {
    655             fail("Exception should not be thrown");
    656         }
    657     }
    658
    659     // ---------------------------------------------------- ForwardConfig Tests
    660
    661     /**
    662      * Test that nothing fails if there are no extensions.
    663      */
    664     public void testInitModuleForwardConfigsNoExtends()
    665         throws ServletException {
    666         moduleConfig.addForwardConfig(baseForward);
    667
    668         try {
    669             actionServlet.initModuleForwards(moduleConfig);
    670         } catch (Exception e) {
    671             fail("Unexpected exception caught.");
    672         }
    673     }
    674
    675     /**
    676      * Test that initModuleForwards throws an exception when a forward with a
    677      * null path is present.
    678      */
    679     public void testInitModuleForwardsNullFormType()
    680         throws ServletException {
    681         ActionForward forward = new ActionForward("success", null, false);
    682
    683         moduleConfig.addForwardConfig(forward);
    684
    685         try {
    686             actionServlet.initModuleForwards(moduleConfig);
    687             fail("An exception should've been thrown here.");
    688         } catch (UnavailableException e) {
    689             // success
    690         } catch (Exception e) {
    691             fail("Unrecognized exception thrown: " + e);
    692         }
    693     }
    694
    695     /**
    696      * Test that processForwardExtension() calls processExtends()
    697      */
    698     public void testProcessForwardExtension()
    699         throws ServletException {
    700         CustomForwardConfig forward =
    701             new CustomForwardConfig("forward", "/forward.jsp");
    702
    703         moduleConfig.addForwardConfig(forward);
    704         actionServlet.processForwardExtension(forward, moduleConfig, null);
    705
    706         assertTrue("processExtends() was not called",
    707             forward.processExtendsCalled);
    708     }
    709
    710     /**
    711      * Make sure processForwardConfigClass() returns an instance of the
    712      * correct class if the base config is using a custom class.
    713      */
    714     public void testProcessForwardConfigClass()
    715         throws Exception {
    716         CustomForwardConfig customBase =
    717             new CustomForwardConfig("success", "/success.jsp");
    718
    719         moduleConfig.addForwardConfig(customBase);
    720
    721         ActionForward customSub = new ActionForward();
    722
    723         customSub.setName("failure");
    724         customSub.setExtends("success");
    725         moduleConfig.addForwardConfig(customSub);
    726
    727         ForwardConfig result =
    728             actionServlet.processForwardConfigClass(customSub, moduleConfig,
    729                 null);
    730
    731         assertTrue("Incorrect class of forward config",
    732             result instanceof CustomForwardConfig);
    733         assertEquals("Incorrect name", customSub.getName(), result.getName());
    734         assertEquals("Incorrect path", customSub.getPath(), result.getPath());
    735         assertEquals("Incorrect extends", customSub.getExtends(),
    736             result.getExtends());
    737
    738         assertSame("Result was not registered in the module config", result,
    739             moduleConfig.findForwardConfig("failure"));
    740     }
    741
    742     /**
    743      * Make sure processForwardConfigClass() returns what it was given if the
    744      * forward passed to it doesn't extend anything.
    745      */
    746     public void testProcessForwardConfigClassNoExtends()
    747         throws Exception {
    748         moduleConfig.addForwardConfig(baseForward);
    749
    750         ForwardConfig result = null;
    751
    752         try {
    753             result =
    754                 actionServlet.processForwardConfigClass(baseForward,
    755                     moduleConfig, null);
    756         } catch (UnavailableException e) {
    757             fail("An exception should not be thrown when there's nothing to do");
    758         }
    759
    760         assertSame("Result should be the same as the input.", baseForward,
    761             result);
    762     }
    763
    764     /**
    765      * Make sure processForwardConfigClass() returns the same class instance
    766      * if the base config isn't using a custom class.
    767      */
    768     public void testProcessForwardConfigClassSubConfigCustomClass()
    769         throws Exception {
    770         moduleConfig.addForwardConfig(baseForward);
    771
    772         ForwardConfig customSub = new ActionForward();
    773
    774         customSub.setName("failure");
    775         customSub.setExtends("success");
    776         moduleConfig.addForwardConfig(customSub);
    777
    778         ForwardConfig result =
    779             actionServlet.processForwardConfigClass(customSub, moduleConfig,
    780                 null);
    781
    782         assertSame("The instance returned should be the param given it.",
    783             customSub, result);
    784     }
    785
    786     /**
    787      * Make sure the code throws the correct exception when it can't create an
    788      * instance of the base config's custom class.
    789      */
    790     public void notestProcessForwardConfigClassError()
    791         throws Exception {
    792         ForwardConfig customBase =
    793             new CustomForwardConfigArg("success", "/success.jsp");
    794
    795         moduleConfig.addForwardConfig(customBase);
    796
    797         ForwardConfig customSub = new ActionForward();
    798
    799         customSub.setName("failure");
    800         customSub.setExtends("success");
    801         moduleConfig.addForwardConfig(customSub);
    802
    803         try {
    804             actionServlet.processForwardConfigClass(customSub, moduleConfig,
    805                 null);
    806             fail("Exception should be thrown");
    807         } catch (UnavailableException e) {
    808             // success
    809         } catch (Exception e) {
    810             fail("Unexpected exception thrown.");
    811         }
    812     }
    813
    814     /**
    815      * Test the case where the subconfig has already specified its own config
    816      * class.  If the code still attempts to create a new instance, an error
    817      * will be thrown.
    818      */
    819     public void testProcessForwardConfigClassOverriddenSubConfigClass()
    820         throws Exception {
    821         moduleConfig.addForwardConfig(baseForward);
    822
    823         ForwardConfig customSub =
    824             new CustomForwardConfigArg("failure", "/failure.jsp");
    825
    826         customSub.setExtends("success");
    827         moduleConfig.addForwardConfig(customSub);
    828
    829         try {
    830             actionServlet.processForwardConfigClass(customSub, moduleConfig,
    831                 null);
    832         } catch (Exception e) {
    833             fail("Exception should not be thrown");
    834         }
    835     }
    836
    837     // --------------------------------------------------- ActionConfig Tests
    838
    839     /**
    840      * Test that nothing fails if there are no extensions.
    841      */
    842     public void testInitModuleActionConfigsNoExtends()
    843         throws ServletException {
    844         moduleConfig.addActionConfig(baseAction);
    845
    846         try {
    847             actionServlet.initModuleActions(moduleConfig);
    848         } catch (Exception e) {
    849             fail("Unexpected exception caught.");
    850         }
    851     }
    852
    853     /**
    854      * Test that processActionConfigExtension() calls processExtends()
    855      */
    856     public void testProcessActionExtension()
    857         throws ServletException {
    858         CustomActionConfig action = new CustomActionConfig("/action");
    859
    860         moduleConfig.addActionConfig(action);
    861         actionServlet.processActionConfigExtension(action, moduleConfig);
    862
    863         assertTrue("processExtends() was not called",
    864             action.processExtendsCalled);
    865     }
    866
    867     /**
    868      * Test that an ActionConfig's ForwardConfig can inherit from a
    869      * global ForwardConfig.
    870      */
    871     public void testProcessActionExtensionWithForwardConfig()
    872         throws ServletException {
    873         ForwardConfig forwardConfig = new ForwardConfig();
    874         forwardConfig.setName("sub");
    875         forwardConfig.setExtends("success");
    876         baseAction.addForwardConfig(forwardConfig);
    877
    878         moduleConfig.addActionConfig(baseAction);
    879         moduleConfig.addForwardConfig(baseForward);
    880         actionServlet.processActionConfigExtension(baseAction, moduleConfig);
    881
    882         forwardConfig = baseAction.findForwardConfig("sub");
    883
    884         assertEquals("'sub' forward's inheritance was not processed.",
    885             baseForward.getPath(), forwardConfig.getPath());
    886     }
    887
    888     /**
    889      * Test that an ActionConfig's ExceptionConfig can inherit from a
    890      * global ExceptionConfig.
    891      */
    892     public void testProcessActionExtensionWithExceptionConfig()
    893         throws ServletException {
    894         ExceptionConfig exceptionConfig = new ExceptionConfig();
    895         exceptionConfig.setType("SomeException");
    896         exceptionConfig.setExtends("java.lang.NullPointerException");
    897         baseAction.addExceptionConfig(exceptionConfig);
    898
    899         moduleConfig.addActionConfig(baseAction);
    900         moduleConfig.addExceptionConfig(baseException);
    901         actionServlet.processActionConfigExtension(baseAction, moduleConfig);
    902
    903         exceptionConfig = baseAction.findExceptionConfig("SomeException");
    904
    905         assertEquals("SomeException's inheritance was not processed.",
    906             baseException.getKey(), exceptionConfig.getKey());
    907     }
    908
    909     /**
    910      * Make sure processActionConfigClass() returns an instance of the correct
    911      * class if the base config is using a custom class.
    912      */
    913     public void testProcessActionConfigClass()
    914         throws Exception {
    915         CustomActionConfig customBase = new CustomActionConfig("/base");
    916
    917         moduleConfig.addActionConfig(customBase);
    918
    919         ActionMapping customSub = new ActionMapping();
    920
    921         customSub.setPath("/sub");
    922         customSub.setExtends("/base");
    923         moduleConfig.addActionConfig(customSub);
    924
    925         ActionConfig result =
    926             actionServlet.processActionConfigClass(customSub, moduleConfig);
    927
    928         assertTrue("Incorrect class of action config",
    929             result instanceof CustomActionConfig);
    930         assertEquals("Incorrect path", customSub.getPath(), result.getPath());
    931         assertEquals("Incorrect extends", customSub.getExtends(),
    932             result.getExtends());
    933
    934         assertSame("Result was not registered in the module config", result,
    935             moduleConfig.findActionConfig("/sub"));
    936     }
    937
    938     /**
    939      * Make sure processActionConfigClass() returns what it was given if the
    940      * action passed to it doesn't extend anything.
    941      */
    942     public void testProcessActionConfigClassNoExtends()
    943         throws Exception {
    944         moduleConfig.addActionConfig(baseAction);
    945
    946         ActionConfig result = null;
    947
    948         try {
    949             result =
    950                 actionServlet.processActionConfigClass(baseAction, moduleConfig);
    951         } catch (UnavailableException e) {
    952             fail("An exception should not be thrown here");
    953         }
    954
    955         assertSame("Result should be the same as the input.", baseAction, result);
    956     }
    957
    958     /**
    959      * Make sure processActionConfigClass() returns the same class instance if
    960      * the base config isn't using a custom class.
    961      */
    962     public void testProcessActionConfigClassSubConfigCustomClass()
    963         throws Exception {
    964         moduleConfig.addActionConfig(baseAction);
    965
    966         ActionConfig customSub = new ActionMapping();
    967
    968         customSub.setPath("/sub");
    969         customSub.setExtends("/index");
    970         moduleConfig.addActionConfig(customSub);
    971
    972         ActionConfig result =
    973             actionServlet.processActionConfigClass(customSub, moduleConfig);
    974
    975         assertSame("The instance returned should be the param given it.",
    976             customSub, result);
    977     }
    978
    979     /**
    980      * Make sure the code throws the correct exception when it can't create an
    981      * instance of the base config's custom class.
    982      */
    983     public void notestProcessActionConfigClassError()
    984         throws Exception {
    985         ActionConfig customBase = new CustomActionConfigArg("/index");
    986
    987         moduleConfig.addActionConfig(customBase);
    988
    989         ActionConfig customSub = new ActionMapping();
    990
    991         customSub.setPath("/sub");
    992         customSub.setExtends("/index");
    993         moduleConfig.addActionConfig(customSub);
    994
    995         try {
    996             actionServlet.processActionConfigClass(customSub, moduleConfig);
    997             fail("Exception should be thrown");
    998         } catch (UnavailableException e) {
    999             // success
    1000         } catch (Exception e) {
    1001             fail("Unexpected exception thrown.");
    1002         }
    1003     }
    1004
    1005     /**
    1006      * Test the case where the subconfig has already specified its own config
    1007      * class.  If the code still attempts to create a new instance, an error
    1008      * will be thrown.
    1009      */
    1010     public void testProcessActionConfigClassOverriddenSubConfigClass()
    1011         throws Exception {
    1012         moduleConfig.addActionConfig(baseAction);
    1013
    1014         ActionConfig customSub = new CustomActionConfigArg("/sub");
    1015
    1016         customSub.setExtends("/index");
    1017         moduleConfig.addActionConfig(customSub);
    1018
    1019         try {
    1020             actionServlet.processActionConfigClass(customSub, moduleConfig);
    1021         } catch (Exception e) {
    1022             fail("Exception should not be thrown");
    1023         }
    1024     }
    1025
    1026     /**
    1027      * Used for testing custom FormBeanConfig classes.
    1028      */
    1029     public static class CustomFormBeanConfig extends FormBeanConfig {
    1030         public boolean processExtendsCalled = false;
    1031
    1032         public CustomFormBeanConfig() {
    1033             super();
    1034         }
    1035
    1036         /**
    1037          * Set a flag so we know this method was called.
    1038          */
    1039         public void processExtends(ModuleConfig moduleConfig)
    1040             throws ClassNotFoundException, IllegalAccessException,
    1041                 InstantiationException {
    1042             processExtendsCalled = true;
    1043         }
    1044     }
    1045
    1046     /**
    1047      * Used to test cases where the subclass cannot be created with a no-arg
    1048      * constructor.
    1049      */
    1050     private class CustomFormBeanConfigArg extends FormBeanConfig {
    1051         CustomFormBeanConfigArg(String name) {
    1052             super();
    1053             setName(name);
    1054         }
    1055     }
    1056
    1057     /**
    1058      * Used for testing custom ExceptionConfig classes.
    1059      */
    1060     public static class CustomExceptionConfig extends ExceptionConfig {
    1061         public boolean processExtendsCalled = false;
    1062
    1063         public CustomExceptionConfig() {
    1064             super();
    1065         }
    1066
    1067         /**
    1068          * Set a flag so we know this method was called.
    1069          */
    1070         public void processExtends(ModuleConfig moduleConfig,
    1071             ActionConfig actionConfig)
    1072             throws ClassNotFoundException, IllegalAccessException,
    1073                 InstantiationException {
    1074             processExtendsCalled = true;
    1075         }
    1076     }
    1077
    1078     /**
    1079      * Used to test cases where the subclass cannot be created with a no-arg
    1080      * constructor.
    1081      */
    1082     private class CustomExceptionConfigArg extends ExceptionConfig {
    1083         CustomExceptionConfigArg(String type) {
    1084             super();
    1085             setType(type);
    1086         }
    1087     }
    1088
    1089     /**
    1090      * Used for testing custom ForwardConfig classes.
    1091      */
    1092     public static class CustomForwardConfig extends ForwardConfig {
    1093         public boolean processExtendsCalled = false;
    1094
    1095         public CustomForwardConfig() {
    1096             super();
    1097         }
    1098
    1099         public CustomForwardConfig(String name, String path) {
    1100             super(name, path, false);
    1101         }
    1102
    1103         /**
    1104          * Set a flag so we know this method was called.
    1105          */
    1106         public void processExtends(ModuleConfig moduleConfig,
    1107             ActionConfig actionConfig)
    1108             throws ClassNotFoundException, IllegalAccessException,
    1109                 InstantiationException {
    1110             processExtendsCalled = true;
    1111         }
    1112     }
    1113
    1114     /**
    1115      * Used to test cases where the subclass cannot be created with a no-arg
    1116      * constructor.
    1117      */
    1118     private class CustomForwardConfigArg extends ForwardConfig {
    1119         CustomForwardConfigArg(String name, String path) {
    1120             super();
    1121             setName(name);
    1122             setPath(path);
    1123         }
    1124     }
    1125
    1126     /**
    1127      * Used for testing custom ActionConfig classes.
    1128      */
    1129     public static class CustomActionConfig extends ActionConfig {
    1130         public boolean processExtendsCalled = false;
    1131
    1132         public CustomActionConfig() {
    1133             super();
    1134         }
    1135
    1136         public CustomActionConfig(String path) {
    1137             super();
    1138             setPath(path);
    1139         }
    1140
    1141         /**
    1142          * Set a flag so we know this method was called.
    1143          */
    1144         public void processExtends(ModuleConfig moduleConfig)
    1145             throws ClassNotFoundException, IllegalAccessException,
    1146                 InstantiationException {
    1147             processExtendsCalled = true;
    1148         }
    1149     }
    1150
    1151     /**
    1152      * Used to test cases where the subclass cannot be created with a no-arg
    1153      * constructor.
    1154      */
    1155     private class CustomActionConfigArg extends ActionConfig {
    1156         CustomActionConfigArg(String path) {
    1157             super();
    1158             setPath(path);
    1159         }
    1160     }
    1161
    1162     // [...]
    1163 }