View Javadoc
1   /*
2    * Redistribution and use of this software and associated documentation
3    * ("Software"), with or without modification, are permitted provided
4    * that the following conditions are met:
5    *
6    * 1. Redistributions of source code must retain copyright
7    *    statements and notices.  Redistributions must also contain a
8    *    copy of this document.
9    *
10   * 2. Redistributions in binary form must reproduce the
11   *    above copyright notice, this list of conditions and the
12   *    following disclaimer in the documentation and/or other
13   *    materials provided with the distribution.
14   *
15   * 3. The name "Exolab" must not be used to endorse or promote
16   *    products derived from this Software without prior written
17   *    permission of Intalio, Inc.  For written permission,
18   *    please contact info@exolab.org.
19   *
20   * 4. Products derived from this Software may not be called "Exolab"
21   *    nor may "Exolab" appear in their names without prior written
22   *    permission of Intalio, Inc. Exolab is a registered
23   *    trademark of Intalio, Inc.
24   *
25   * 5. Due credit should be given to the Exolab Project
26   *    (http://www.exolab.org/).
27   *
28   * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS
29   * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30   * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31   * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
32   * INTALIO, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33   * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39   * OF THE POSSIBILITY OF SUCH DAMAGE.
40   *
41   * Copyright 2001-2003 (C) Intalio, Inc. All Rights Reserved.
42   *
43   * $Id: MarshallingFrameworkTestCase.java 6787 2007-01-29 06:00:49Z ekuns $
44   */
45  package org.castor.xmlctf;
46  
47  import java.io.FileNotFoundException;
48  import java.io.InputStream;
49  import java.net.URL;
50  import java.net.URLClassLoader;
51  
52  import junit.framework.Test;
53  import junit.framework.TestSuite;
54  
55  import org.castor.xmlctf.compiler.CompilationException;
56  import org.castor.xmlctf.compiler.Compiler;
57  import org.castor.xmlctf.compiler.SunJavaCompiler;
58  import org.castor.xmlctf.util.FileServices;
59  import org.exolab.castor.mapping.Mapping;
60  import org.exolab.castor.tests.framework.testDescriptor.ListenerType;
61  import org.exolab.castor.tests.framework.testDescriptor.MarshallingTest;
62  import org.exolab.castor.tests.framework.testDescriptor.RootType;
63  import org.exolab.castor.tests.framework.testDescriptor.UnitTestCase;
64  import org.xml.sax.InputSource;
65  
66  /**
67   * This class encapsulates all the logic to run the test patterns for the Castor
68   * marshalling framework. This include introspection and mapping.
69   *
70   * @author <a href="mailto:gignoux@kernelcenter.com">Sebastien Gignoux</a>
71   * @author <a href="mailto:blandin@intalio.com">Arnaud Blandin</a>
72   * @version $Revision: 6787 $ $Date: 2004-09-10 18:23:03 -0600 (Fri, 10 Sep 2004) $
73   */
74  public class MarshallingFrameworkTestCase extends XMLTestCase {
75  
76      /**
77       * Contains the configuration for this test case. The configuration is
78       * directly read for the test descriptor file located in a jar or in a
79       * directory.
80       */
81      protected final MarshallingTest _marshallingConf;
82      /** If true, the randomize() function has been implemented in the root class. */
83      protected final boolean         _hasRandom;
84  
85      /**
86       * Creates a CTF test case for the Marshalling framework.
87       *
88       * @param test A Test Case
89       * @param unit A configuration element for a test case from a TestDescriptor
90       *            configuration file
91       * @param marshalling a Marshalling test definition from a TestDescriptor
92       *            configuration file
93       */
94      public MarshallingFrameworkTestCase(final CastorTestCase test, final UnitTestCase unit,
95                                          final MarshallingTest marshalling) {
96          super(test, unit);
97          _marshallingConf = marshalling;
98  
99          RootType rootType = _marshallingConf.getRoot_Object();
100         if (rootType == null) {
101             throw new IllegalArgumentException("You must give a root object for a Marshaling Test: "
102                     + _outputRootFile + ", " +  getName());
103         }
104 
105         _rootClassName = rootType.getContent();
106         if (_rootClassName == null) {
107             throw new IllegalArgumentException("You must give a root object for a Marshaling Test:"
108                     + _outputRootFile + ", " +  getName());
109         }
110 
111         _hasRandom = rootType.getRandom();
112         _hasDump   = rootType.getDump();
113     }
114 
115     /**
116      * Create a new MarshallingFrameworkTestCase with the given name and a null
117      * marshalling configuration.  This constructor should not be used!
118      *
119      * @param name Name for the MarshallingFrameworkTestCase
120      */
121     public MarshallingFrameworkTestCase(final String name) {
122         super(name);
123         throw new IllegalArgumentException("You cannot use the name-only constructor");
124     }
125 
126     /**
127      * Returns the test suite for this given test setup.
128      * @return the test suite for this given test setup.
129      */
130     public Test suite() {
131         TestSuite suite = new TestSuite(_name);
132 
133         String name = getTestSuiteName();
134         name = (name != null) ? name + "#" + _name : _name;
135 
136         if (_unitTest.getCustomTest() != null) {
137             suite.addTest(new TestWithCustomTest(name, this));
138         } else {
139             suite.addTest(new TestWithReferenceDocument(name, this));
140             if (_hasRandom) {
141                 suite.addTest(new TestWithRandomObject(name, this));
142             }
143         }
144         return suite;
145     }
146 
147     /**
148      * Sets up this test suite. Loads the mapping file if any.
149      * <p>
150      * Nothing in this setUp() method should ever be expected to fail. Thus,
151      * there are no checks against _failure. If anything goes wrong here, there
152      * is a problem with the individual test case configuration.
153      *
154      * @throws Exception
155      *             if anything goes wrong
156      */
157     protected void setUp() throws java.lang.Exception {
158         verbose("\n================================================");
159         verbose("Test suite '" + _test.getName() + "': setting up test '" + _name + "'");
160         verbose("================================================\n");
161 
162         FileServices.copySupportFiles(_test.getTestFile(), _outputRootFile);
163 
164         // Compile the source directory for this test, if not already done
165         if (!_test.isDirectoryCompiled()) {
166             verbose("-->Compiling any necessary source files in " + _outputRootFile);
167             Compiler compiler = new SunJavaCompiler(_outputRootFile);
168             if (_unitTest.hasJavaSourceVersion()) {
169                 compiler.setJavaSourceVersion(_unitTest.getJavaSourceVersion());
170             }
171             try {
172                 compiler.compileDirectory();
173                 _test.setDirectoryCompiled(true);
174             } catch (CompilationException e) {
175                 if (_printStack) {
176                     e.printStackTrace(System.out);
177                 }
178                 fail("Build Failed: " + e.getMessage());
179             }
180         }
181 
182         //-- Add outputRoot to classpath
183         ClassLoader loader = _test.getClassLoader();
184         loader = new URLClassLoader(new URL[] {_outputRootFile.toURL()}, loader);
185         _test.setClassLoader(loader);
186         getXMLContext().getInternalContext().setClassLoader(loader);
187 
188         verbose("Root class specified in TestDescriptor...");
189         verbose("Loading class: " + _rootClassName);
190         _rootClass = loader.loadClass(_rootClassName);
191 
192         // Try to load the mapping file if any, else we will use the introspector
193         String mappingFilePath = null;
194         if (_unitTest.getUnitTestCaseChoice() != null) {
195             mappingFilePath = _unitTest.getUnitTestCaseChoice().getMapping_File();
196         }
197 
198         if (mappingFilePath != null) {
199             configureMapping(loader, mappingFilePath);
200         } else {
201             verbose("##### TESTING INTROSPECTION #####");
202             _mapping = null;
203         }
204     }
205 
206     /**
207      * Clean up after a test -- nothing to do except display output.
208      * @throws Exception if anything goes wrong
209      */
210     protected void tearDown() throws java.lang.Exception {
211         verbose("\n================================================");
212         verbose("Test suite '" + _test.getName() + "': test '" + _name + "' complete.");
213         verbose("================================================\n");
214     }
215 
216     /**
217      * For a test case with a mapping, load the mapping. If there is a listener,
218      * initialize it.
219      *
220      * @param loader ClassLoader for this test case
221      * @param mappingFilePath Path to the mapping file
222      * @throws Exception if anything goes wrong during the test
223      */
224     private void configureMapping(final ClassLoader loader, final String mappingFilePath) throws Exception {
225         verbose("##### TESTING MAPPING #####");
226         verbose("Mapping file: " + mappingFilePath);
227         InputStream mappingFile = loader.getResourceAsStream(mappingFilePath);
228 
229         if (mappingFile == null) {
230             throw new FileNotFoundException("Unable to locate the mapping file '"
231                      + mappingFilePath + "' for the test '" + _test.getName() + "'");
232         }
233 
234         _mapping = new Mapping(loader);
235         InputSource source = new InputSource(mappingFile);
236         source.setSystemId(mappingFilePath);
237         _mapping.loadMapping(source);
238 
239         ListenerType listener = _unitTest.getListener();
240         if (listener != null) {
241             String listenerName = listener.getClassName();
242             try {
243                 // See if we can load the class...
244                 initializeListeners(listener);
245             } catch (ClassNotFoundException cnfex) {
246                 //Class#forName
247                 fail("The listener '" + listenerName + "' cannot be found in the CLASSPATH");
248             } catch (InstantiationException iex) {
249                 fail("The listener '" + listenerName + "' cannot be instantiated");
250             } catch (IllegalAccessException iaex) {
251                 fail("Constructing a '" + listenerName + "' failed: " + iaex);
252             }
253             verbose("##### TESTING LISTENER CLASS " + listenerName + " #####");
254         } // listener != null;
255     }
256 
257 }