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 2002-2003 (C) Intalio, Inc. All Rights Reserved.
32   *
33   * Portions of this file developed by Keith Visco after Jan 19 2005 are Copyright (C) 2005 Keith
34   * Visco. All Rights Reserverd.
35   *
36   * $Id: SchemaTestCase.java 6787 2007-01-29 06:00:49Z ekuns $
37   *
38   * Date Author Changes ----------------------------------------- 01/23/2002 Keith Visco Created
39   * 03/25/2002 Arnaud Blandin Ported to CTF 10/15/2003 Arnaud Blandin Improved reporting
40   */
41  package org.castor.xmlctf;
42  
43  import java.io.File;
44  import java.io.FileWriter;
45  import java.io.IOException;
46  import java.io.PrintWriter;
47  
48  import junit.framework.Test;
49  import junit.framework.TestSuite;
50  
51  import org.castor.xmlctf.util.CTFUtils;
52  import org.castor.xmlctf.util.FileServices;
53  import org.exolab.castor.tests.framework.testDescriptor.SchemaDifferences;
54  import org.exolab.castor.tests.framework.testDescriptor.UnitTestCase;
55  import org.exolab.castor.tests.framework.testDescriptor.types.FailureStepType;
56  import org.exolab.castor.xml.XMLContext;
57  import org.exolab.castor.xml.schema.Schema;
58  import org.exolab.castor.xml.schema.SchemaContextImpl;
59  import org.exolab.castor.xml.schema.reader.SchemaReader;
60  import org.exolab.castor.xml.schema.writer.SchemaWriter;
61  import org.xml.sax.InputSource;
62  
63  /**
64   * A JUnit test case for testing the Castor Schema Object Model.
65   *
66   * @author <a href="mailto:keith AT kvisco DOT com">Keith Visco</a>
67   * @author <a href="mailto:blandin@intalio.com">Arnaud Blandin</a>
68   * @version $Revision: 6787 $ $Date: 2006-04-26 15:14:53 -0600 (Wed, 26 Apr 2006) $
69   */
70  public class SchemaTestCase extends XMLTestCase {
71  
72    /** The name of the schema to test. */
73    private String _schemaName;
74    /** The count of differences expected for the file-reference comparison. */
75    private final int _differenceCountReference;
76    /**
77     * Gold file to compare a schema against. Optional. Only needed if schema changes during parsing,
78     * i.e., due to redefine element.
79     */
80    protected final String _goldFileName;
81  
82    /**
83     * Default constructor
84     * 
85     * @param name the name of the test
86     */
87    public SchemaTestCase(final String name) {
88      super(name);
89      throw new IllegalArgumentException("You cannot use the name-only constructor");
90    } // -- SchemaTest
91  
92    /**
93     * Creates a new SchemaTest with the given name
94     * 
95     * @param castorTc the reference to the jar/directory
96     * @param tc the UnitTestCase that wraps the configuration for this XML Test case.
97     */
98    public SchemaTestCase(final CastorTestCase castorTc, final UnitTestCase tc) {
99      super(castorTc, tc);
100     _differenceCountReference = getSchemaDifferenceCount(tc, FailureStepType.COMPARE_TO_REFERENCE);
101     _goldFileName = tc.getGoldFile();
102   } // -- SchemaTest
103 
104   /**
105    * Looks for and returns the difference count for the given step
106    * 
107    * @param tc the UnitTestCase that wraps the configuration for this XML Test case.
108    * @param step the step to look for
109    * @return the difference count for the given step
110    */
111   private int getSchemaDifferenceCount(final UnitTestCase tc, final FailureStepType step) {
112     SchemaDifferences[] diff = tc.getSchemaDifferences();
113     for (int i = 0; i < diff.length; i++) {
114       if (diff[i].getFailureStep().equals(step)) {
115         return diff[i].getContent();
116       }
117     }
118     return 0;
119   }
120 
121   /**
122    * Sets the name of the XML schema file to test.
123    *
124    * @param name the name of the XML schema file to test.
125    */
126   public void setSchemaName(final String name) {
127     _schemaName = name;
128   }
129 
130   public static Test suite() {
131     return new TestSuite();
132   } // -- suite
133 
134   protected void setUp() throws Exception {
135     verbose("\n================================================");
136     verbose("Test suite '" + _test.getName() + "': setting up test '" + _name + "'");
137     verbose("================================================\n");
138 
139     try {
140       FileServices.copySupportFiles(_test.getTestFile(), _outputRootFile);
141     } catch (IOException e) {
142       fail("IOException copying support files " + e);
143     }
144     if (getXMLContext() == null) {
145       // not wrapped inside a TestWithXy test!
146       setXMLContext(new XMLContext());
147     }
148   }
149 
150   /**
151    * Cleans up after this unit test (nothing to do except provide output).
152    * 
153    * @throws java.lang.Exception never
154    */
155   protected void tearDown() throws Exception {
156     verbose("\n================================================");
157     verbose("Test suite '" + _test.getName() + "': test '" + _name + "' complete.");
158     verbose("================================================\n");
159   }
160 
161   /**
162    * Override this method to run the test and assert its state.
163    *
164    * @throws Throwable if any exception is thrown
165    */
166   public void runTest() throws Throwable {
167     if (_skip) {
168       verbose("-->Skipping the test");
169       return;
170     }
171 
172     File schemaFile = new File(_test.getTestFile() + "/" + _schemaName);
173     String schemaURL = schemaFile.toURL().toString();
174 
175     Schema schema = testReadingSchema(schemaURL);
176     if (schema == null) {
177       return;
178     }
179     testWritingSchema(schemaURL, schema);
180 
181     // Compare marshaled schema to gold file if provided, otherwise to input file
182     compareSchemaFiles(schemaFile);
183 
184     if (_failure != null && _failure.getContent()) {
185       fail("The schema test was expected to fail, but passed");
186     }
187   } // -- runTest
188 
189   private void compareSchemaFiles(final File schemaFile) throws IOException {
190     File file = new File(_outputRootFile,
191         _schemaName.substring(0, _schemaName.lastIndexOf('.')) + "-output" + FileServices.XSD);
192 
193     String goldFileName = (_goldFileName != null) ? _outputRootFile + "/" + _goldFileName
194         : schemaFile.getAbsolutePath();
195 
196     int result = CTFUtils.compare(goldFileName, file.getAbsolutePath());
197     verbose("----> Compare marshaled schema to gold file '" + _goldFileName + "': "
198         + ((result == 0) ? "OK" : "### Failed ### "));
199 
200     final FailureStepType step = _failure != null ? _failure.getFailureStep() : null;
201     final boolean expectedToFail = _failure != null && _failure.getContent()
202         && (step == null || step.equals(FailureStepType.COMPARE_TO_REFERENCE));
203 
204     if (_failure == null || !_failure.getContent()) {
205       assertEquals("The Marshaled schema differs from the gold file", _differenceCountReference,
206           result);
207     } else if (expectedToFail) {
208       assertTrue("The Marshaled schema was expected to differ from the" + " gold file, but did not",
209           result != _differenceCountReference);
210     }
211   }
212 
213   /**
214    * Reads and returns the provided XML schema.
215    *
216    * @param url the schema URL
217    * @return the Schema that was read in
218    */
219   private Schema testReadingSchema(final String url) {
220     verbose("--> Reading XML Schema: " + url);
221     try {
222       SchemaReader reader = new SchemaReader();
223 
224       reader.setSchemaContext(new SchemaContextImpl());
225       reader.setInputSource(new InputSource(url));
226 
227       Schema returnValue = reader.read();
228       if (_failure != null && _failure.getContent() && _failure.getFailureStep() != null
229           && _failure.getFailureStep().equals(FailureStepType.PARSE_SCHEMA)) {
230         fail("Reading/Parsing the schema was expected to fail, but succeeded");
231       }
232       return returnValue;
233     } catch (Exception e) {
234       if (!checkExceptionWasExpected(e, FailureStepType.PARSE_SCHEMA)) {
235         fail("Unable to read Schema '" + url + "': " + e.toString());
236       }
237     }
238 
239     return null;
240   }
241 
242   /**
243    * Writes the provided schema to disk.
244    *
245    * @param url schema url, used only in diagnostic output
246    * @param schema the schema to write
247    */
248   private void testWritingSchema(final String url, final Schema schema) {
249     // First write the schema to disk
250     try {
251       String fileName =
252           _schemaName.substring(0, _schemaName.lastIndexOf('.')) + "-output" + FileServices.XSD;
253       verbose("--> Writing XML Schema: " + fileName);
254 
255       File output = new File(_outputRootFile, fileName);
256       FileWriter writer = new FileWriter(output);
257 
258       SchemaWriter schemaWriter = new SchemaWriter();
259       schemaWriter.setSchemaContext(new SchemaContextImpl());
260       schemaWriter.setDocumentHandler(new PrintWriter(writer, true));
261 
262       schemaWriter.write(schema);
263       writer.close();
264     } catch (Exception e) {
265       if (!checkExceptionWasExpected(e, FailureStepType.WRITE_SCHEMA)) {
266         fail("Failed to write Schema '" + url + "' to disk: " + e.toString());
267       }
268       return;
269     }
270 
271     if (_failure != null && _failure.getContent() && _failure.getFailureStep() != null
272         && _failure.getFailureStep().equals(FailureStepType.WRITE_SCHEMA)) {
273       fail("Writing the schema was expected to fail, but succeeded");
274     }
275   }
276 
277 } // -- SchemaTest