Source code: org/apache/batik/test/svg/SelfContainedSVGOnLoadTest.java
1 /*
2
3 Copyright 2002-2003 The Apache Software Foundation
4
5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 */
18 package org.apache.batik.test.svg;
19
20 import java.io.File;
21 import java.io.IOException;
22 import java.net.MalformedURLException;
23 import java.net.URL;
24
25 import org.w3c.dom.Document;
26 import org.w3c.dom.Element;
27 import org.w3c.dom.NodeList;
28
29 import org.apache.batik.bridge.BaseScriptingEnvironment;
30 import org.apache.batik.bridge.BridgeContext;
31 import org.apache.batik.bridge.BridgeException;
32 import org.apache.batik.bridge.GVTBuilder;
33 import org.apache.batik.bridge.UserAgent;
34 import org.apache.batik.bridge.UserAgentAdapter;
35 import org.apache.batik.dom.svg.SAXSVGDocumentFactory;
36 import org.apache.batik.test.AbstractTest;
37 import org.apache.batik.test.DefaultTestReport;
38 import org.apache.batik.test.TestReport;
39 import org.apache.batik.util.XMLResourceDescriptor;
40
41 /**
42 * This test takes an SVG file as an input. It processes the input SVG
43 * (meaning it turns it into a GVT tree) and then dispatches the 'onload'
44 * event.
45 *
46 * The SVG input file should contain script that will position the
47 * result of the test in the DOM using the following namespace: <br />
48 * xmlns:test="http://xml.apache.org/batik/test" <br />
49 *
50 * The result should be set in the <code>result</code> attribute of the
51 * <testResult> element by the script embeded in the input SVG
52 * test file. <br />
53 *
54 * Sample input SVG file:<br /><code>
55 * <svg ... onload="runTest(evt)" xmlns:test="http://xml.apache.org/batik/test" >
56 * <script type="text/ecmascript">
57 * function runTest(evt) {
58 * ...; // do some test
59 * var rootSvg = document.getDocumentElement();
60 * var result = document.createElementNS("http://xml.apache.org/batik/test",
61 * "testResult");
62 * result.setAttributeNS(null, "result", "failed");
63 * result.setAttributeNS(null, "errorCode", "org.apache.batik.css.dom.wrong.computed.value");
64 * rootSvg.appendChild(result);
65 * }
66 * </script>
67 * </svg></code>
68 *
69 * @author <a href="mailto:vhardy@apache.org">Vincent Hardy</a>
70 * @version $Id: SelfContainedSVGOnLoadTest.java,v 1.6 2004/08/18 07:17:03 vhardy Exp $
71 */
72 public class SelfContainedSVGOnLoadTest extends AbstractTest {
73 /**
74 * Error when the input file cannot be loaded into a
75 * Document object
76 * {0} = IOException message
77 */
78 public static final String ERROR_CANNOT_LOAD_SVG_DOCUMENT
79 = "SelfContainedSVGOnLoadTest.error.cannot.load.svg.document";
80
81 /**
82 * Error while building the GVT tree or dispatching the
83 * 'onload' event.
84 */
85 public static final String ERROR_WHILE_PROCESSING_SVG_DOCUMENT
86 = "SelfContainedSVGOnLoadTest.error.while.processing.svg.document";
87
88 /**
89 * There is either 0 or more than one <testResult> elements in
90 * the document after dispatching the onload event.
91 */
92 public static final String ERROR_UNEXPECTED_NUMBER_OF_TEST_RESULT_ELEMENTS
93 = "SelfContainedSVGOnLoadTest.error.unexpected.number.of.test.result.elements";
94
95 /**
96 * The 'result' attribute value is neither 'passed' nor 'failed'
97 */
98 public static final String ERROR_UNEXPECTED_RESULT_VALUE
99 = "SelfContainedSVGOnLoadTest.error.unexpected.result.value";
100
101 /**
102 * The result was 'failed' but there was no 'errorCode' attribute or
103 * it was the empty string
104 */
105 public static final String ERROR_MISSING_OR_EMPTY_ERROR_CODE_ON_FAILED_TEST
106 = "SelfContainedSVGOnLoadTest.error.missing.or.empty.error.code.on.failed.test";
107
108 /**
109 * Entry describing the error
110 */
111 public static final String ENTRY_KEY_ERROR_DESCRIPTION
112 = "SelfContainedSVGOnLoadTest.entry.key.error.description";
113
114 /**
115 * Entry describing the number of testResult elements found in the
116 * document after dispatching onload.
117 */
118 public static final String ENTRY_KEY_NUMBER_OF_TEST_RESULT_ELEMENTS
119 = "SelfContainedSVGOnLoadTest.entry.key.number.of.test.result.elements";
120
121 /**
122 * Entry describing the result value (different from 'passed' or 'failed'
123 * found in the 'result' attribute.
124 */
125 public static final String ENTRY_KEY_RESULT_VALUE
126 = "SelfContainedSVGOnLoadTest.entry.key.result.value";
127
128 /**
129 * Test Namespace
130 */
131 public static final String testNS = "http://xml.apache.org/batik/test";
132
133 /**
134 * Test Constants
135 */
136 public static final String TAG_TEST_RESULT = "testResult";
137 public static final String TAG_ERROR_DESCRIPTION_ENTRY = "errorDescriptionEntry";
138 public static final String ATTRIBUTE_RESULT = "result";
139 public static final String ATTRIBUTE_KEY = "id";
140 public static final String ATTRIBUTE_VALUE = "value";
141 public static final String TEST_RESULT_PASSED = "passed";
142 public static final String TEST_RESULT_FAILED = "failed";
143
144 /**
145 * The URL for the input SVG document to be tested
146 */
147 protected String svgURL;
148
149 /**
150 * @param svgURL the URL string for the SVG document being tested
151 */
152 public SelfContainedSVGOnLoadTest(String svgURL){
153 this.svgURL = resolveURL(svgURL);
154 }
155
156 /**
157 * Default constructor
158 */
159 protected SelfContainedSVGOnLoadTest(){
160 }
161
162 /**
163 * Resolves the input string as follows.
164 * + First, the string is interpreted as a file description.
165 * If the file exists, then the file name is turned into
166 * a URL.
167 * + Otherwise, the string is supposed to be a URL. If it
168 * is an invalid URL, an IllegalArgumentException is thrown.
169 */
170 protected String resolveURL(String url){
171 // Is url a file?
172 File f = (new File(url)).getAbsoluteFile();
173 if(f.getParentFile().exists()){
174 try{
175 return f.toURL().toString();
176 }catch(MalformedURLException e){
177 throw new IllegalArgumentException();
178 }
179 }
180
181 // url is not a file. It must be a regular URL...
182 try{
183 return (new URL(url)).toString();
184 }catch(MalformedURLException e){
185 throw new IllegalArgumentException(url);
186 }
187 }
188
189
190 /**
191 * Run this test and produce a report.
192 * The test goes through the following steps: <ul>
193 * <li>load the input SVG into a Document</li>
194 * <li>build the GVT tree corresponding to the
195 * Document and dispatch the 'onload' event</li>
196 * <li>looks for one and only one <testResult> element in
197 * the Document. This is used to build the returned
198 * TestReport</li>
199 * </ul>
200 *
201 */
202 public TestReport runImpl() throws Exception{
203 DefaultTestReport report
204 = new DefaultTestReport(this);
205
206 //
207 // First step:
208 //
209 // Load the input SVG into a Document object
210 //
211 String parserClassName = XMLResourceDescriptor.getXMLParserClassName();
212 SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(parserClassName);
213 Document doc = null;
214
215 try {
216 doc = f.createDocument(svgURL);
217 } catch(IOException e){
218 report.setErrorCode(ERROR_CANNOT_LOAD_SVG_DOCUMENT);
219 report.addDescriptionEntry(ENTRY_KEY_ERROR_DESCRIPTION,
220 e.getMessage());
221 report.setPassed(false);
222 return report;
223 } catch(Exception e){
224 report.setErrorCode(ERROR_CANNOT_LOAD_SVG_DOCUMENT);
225 report.addDescriptionEntry(ENTRY_KEY_ERROR_DESCRIPTION,
226 e.getMessage());
227 report.setPassed(false);
228 return report;
229 }
230
231 //
232 // Second step:
233 //
234 // Now that the SVG file has been loaded, build
235 // a GVT Tree from it
236 //
237 UserAgent userAgent = buildUserAgent();
238 GVTBuilder builder = new GVTBuilder();
239 BridgeContext ctx = new BridgeContext(userAgent);
240 ctx.setDynamic(true);
241
242 try {
243 builder.build(ctx, doc);
244 BaseScriptingEnvironment scriptEnvironment
245 = new BaseScriptingEnvironment(ctx);
246 scriptEnvironment.loadScripts();
247 scriptEnvironment.dispatchSVGLoadEvent();
248 } catch (BridgeException e){
249 e.printStackTrace();
250 report.setErrorCode(ERROR_WHILE_PROCESSING_SVG_DOCUMENT);
251 report.addDescriptionEntry(ENTRY_KEY_ERROR_DESCRIPTION,
252 e.getMessage());
253 report.setPassed(false);
254 return report;
255 } catch(Exception e){
256 e.printStackTrace();
257 report.setErrorCode(ERROR_WHILE_PROCESSING_SVG_DOCUMENT);
258 report.addDescriptionEntry(ENTRY_KEY_ERROR_DESCRIPTION,
259 e.getMessage());
260 report.setPassed(false);
261 return report;
262 }
263
264 //
265 // Final step:
266 //
267 // Look for one and only one <testResult> element
268 //
269 NodeList testResultList = doc.getElementsByTagNameNS(testNS,
270 TAG_TEST_RESULT);
271
272 // Check that there is one and only one testResult element
273 if(testResultList.getLength() != 1){
274 report.setErrorCode(ERROR_UNEXPECTED_NUMBER_OF_TEST_RESULT_ELEMENTS);
275 report.addDescriptionEntry(ENTRY_KEY_NUMBER_OF_TEST_RESULT_ELEMENTS,
276 "" + testResultList.getLength());
277 report.setPassed(false);
278 return report;
279 }
280
281 Element testResult = (Element)testResultList.item(0);
282
283 // Now, get the result attribute. Whould be either "passed" or "failed"
284 String result = testResult.getAttributeNS(null, ATTRIBUTE_RESULT);
285 boolean passed = true;
286 if(TEST_RESULT_PASSED.equals(result)){
287 // OK
288 } else if (TEST_RESULT_FAILED.equals(result)){
289 passed = false;
290 } else {
291 report.setErrorCode(ERROR_UNEXPECTED_RESULT_VALUE);
292 report.addDescriptionEntry(ENTRY_KEY_RESULT_VALUE, result);
293 report.setPassed(false);
294 return report;
295 }
296
297 // If the test failed, then there should be an error code
298 if( !passed ){
299 String errorCode = testResult.getAttributeNS(null, "errorCode");
300 if("".equals(errorCode)){
301 report.setErrorCode(ERROR_MISSING_OR_EMPTY_ERROR_CODE_ON_FAILED_TEST);
302 report.setPassed(false);
303 return report;
304 }
305
306 // We got an error code, set it on the report object
307 report.setErrorCode(errorCode);
308
309 // Now, add descriptions from children <errorDescriptionEntry> elements
310 NodeList desc = testResult.getElementsByTagNameNS(testNS,
311 TAG_ERROR_DESCRIPTION_ENTRY);
312 int nDesc = desc.getLength();
313 for (int i=0; i<nDesc; i++){
314 Element entry = (Element)desc.item(i);
315 String key = entry.getAttributeNS(null, ATTRIBUTE_KEY);
316 String value = entry.getAttributeNS(null, ATTRIBUTE_VALUE);
317 report.addDescriptionEntry(key, value);
318 }
319 report.setPassed(false);
320 return report;
321 }
322
323 return report;
324 }
325
326 /**
327 * Give subclasses a chance to build their own UserAgent
328 */
329 protected UserAgent buildUserAgent(){
330 return new UserAgentAdapter();
331 }
332
333 }