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