001: /*
002:
003: Licensed to the Apache Software Foundation (ASF) under one or more
004: contributor license agreements. See the NOTICE file distributed with
005: this work for additional information regarding copyright ownership.
006: The ASF licenses this file to You under the Apache License, Version 2.0
007: (the "License"); you may not use this file except in compliance with
008: the License. You may obtain a copy of the License at
009:
010: http://www.apache.org/licenses/LICENSE-2.0
011:
012: Unless required by applicable law or agreed to in writing, software
013: distributed under the License is distributed on an "AS IS" BASIS,
014: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: See the License for the specific language governing permissions and
016: limitations under the License.
017:
018: */
019: package org.apache.batik.test.svg;
020:
021: import java.io.File;
022: import java.io.IOException;
023: import java.net.MalformedURLException;
024: import java.net.URL;
025:
026: import org.w3c.dom.Document;
027: import org.w3c.dom.Element;
028: import org.w3c.dom.NodeList;
029:
030: import org.apache.batik.bridge.BaseScriptingEnvironment;
031: import org.apache.batik.bridge.BridgeContext;
032: import org.apache.batik.bridge.BridgeException;
033: import org.apache.batik.bridge.GVTBuilder;
034: import org.apache.batik.bridge.UserAgent;
035: import org.apache.batik.bridge.UserAgentAdapter;
036: import org.apache.batik.dom.svg.SAXSVGDocumentFactory;
037: import org.apache.batik.test.AbstractTest;
038: import org.apache.batik.test.DefaultTestReport;
039: import org.apache.batik.test.TestReport;
040: import org.apache.batik.util.XMLResourceDescriptor;
041:
042: /**
043: * This test takes an SVG file as an input. It processes the input SVG
044: * (meaning it turns it into a GVT tree) and then dispatches the 'onload'
045: * event.
046: *
047: * The SVG input file should contain script that will position the
048: * result of the test in the DOM using the following namespace: <br />
049: * xmlns:test="http://xml.apache.org/batik/test" <br />
050: *
051: * The result should be set in the <code>result</code> attribute of the
052: * <testResult> element by the script embeded in the input SVG
053: * test file. <br />
054: *
055: * Sample input SVG file:<br /><code>
056: * <svg ... onload="runTest(evt)" xmlns:test="http://xml.apache.org/batik/test" >
057: * <script type="text/ecmascript">
058: * function runTest(evt) {
059: * ...; // do some test
060: * var rootSvg = document.getDocumentElement();
061: * var result = document.createElementNS("http://xml.apache.org/batik/test",
062: * "testResult");
063: * result.setAttributeNS(null, "result", "failed");
064: * result.setAttributeNS(null, "errorCode", "org.apache.batik.css.dom.wrong.computed.value");
065: * rootSvg.appendChild(result);
066: * }
067: * </script>
068: * </svg></code>
069: *
070: * @author <a href="mailto:vhardy@apache.org">Vincent Hardy</a>
071: * @version $Id: SelfContainedSVGOnLoadTest.java 475477 2006-11-15 22:44:28Z cam $
072: */
073: public class SelfContainedSVGOnLoadTest extends AbstractTest {
074: /**
075: * Error when the input file cannot be loaded into a
076: * Document object
077: * {0} = IOException message
078: */
079: public static final String ERROR_CANNOT_LOAD_SVG_DOCUMENT = "SelfContainedSVGOnLoadTest.error.cannot.load.svg.document";
080:
081: /**
082: * Error while building the GVT tree or dispatching the
083: * 'onload' event.
084: */
085: public static final String ERROR_WHILE_PROCESSING_SVG_DOCUMENT = "SelfContainedSVGOnLoadTest.error.while.processing.svg.document";
086:
087: /**
088: * There is either 0 or more than one <testResult> elements in
089: * the document after dispatching the onload event.
090: */
091: public static final String ERROR_UNEXPECTED_NUMBER_OF_TEST_RESULT_ELEMENTS = "SelfContainedSVGOnLoadTest.error.unexpected.number.of.test.result.elements";
092:
093: /**
094: * The 'result' attribute value is neither 'passed' nor 'failed'
095: */
096: public static final String ERROR_UNEXPECTED_RESULT_VALUE = "SelfContainedSVGOnLoadTest.error.unexpected.result.value";
097:
098: /**
099: * The result was 'failed' but there was no 'errorCode' attribute or
100: * it was the empty string
101: */
102: public static final String ERROR_MISSING_OR_EMPTY_ERROR_CODE_ON_FAILED_TEST = "SelfContainedSVGOnLoadTest.error.missing.or.empty.error.code.on.failed.test";
103:
104: /**
105: * Entry describing the error
106: */
107: public static final String ENTRY_KEY_ERROR_DESCRIPTION = "SelfContainedSVGOnLoadTest.entry.key.error.description";
108:
109: /**
110: * Entry describing the number of testResult elements found in the
111: * document after dispatching onload.
112: */
113: public static final String ENTRY_KEY_NUMBER_OF_TEST_RESULT_ELEMENTS = "SelfContainedSVGOnLoadTest.entry.key.number.of.test.result.elements";
114:
115: /**
116: * Entry describing the result value (different from 'passed' or 'failed'
117: * found in the 'result' attribute.
118: */
119: public static final String ENTRY_KEY_RESULT_VALUE = "SelfContainedSVGOnLoadTest.entry.key.result.value";
120:
121: /**
122: * Test Namespace
123: */
124: public static final String testNS = "http://xml.apache.org/batik/test";
125:
126: /**
127: * Test Constants
128: */
129: public static final String TAG_TEST_RESULT = "testResult";
130: public static final String TAG_ERROR_DESCRIPTION_ENTRY = "errorDescriptionEntry";
131: public static final String ATTRIBUTE_RESULT = "result";
132: public static final String ATTRIBUTE_KEY = "id";
133: public static final String ATTRIBUTE_VALUE = "value";
134: public static final String TEST_RESULT_PASSED = "passed";
135: public static final String TEST_RESULT_FAILED = "failed";
136:
137: /**
138: * The URL for the input SVG document to be tested
139: */
140: protected String svgURL;
141:
142: /**
143: * @param svgURL the URL string for the SVG document being tested
144: */
145: public SelfContainedSVGOnLoadTest(String svgURL) {
146: this .svgURL = resolveURL(svgURL);
147: }
148:
149: /**
150: * Default constructor
151: */
152: protected SelfContainedSVGOnLoadTest() {
153: }
154:
155: /**
156: * Resolves the input string as follows.
157: * + First, the string is interpreted as a file description.
158: * If the file exists, then the file name is turned into
159: * a URL.
160: * + Otherwise, the string is supposed to be a URL. If it
161: * is an invalid URL, an IllegalArgumentException is thrown.
162: */
163: protected String resolveURL(String url) {
164: // Is url a file?
165: File f = (new File(url)).getAbsoluteFile();
166: if (f.getParentFile().exists()) {
167: try {
168: return f.toURL().toString();
169: } catch (MalformedURLException e) {
170: throw new IllegalArgumentException();
171: }
172: }
173:
174: // url is not a file. It must be a regular URL...
175: try {
176: return (new URL(url)).toString();
177: } catch (MalformedURLException e) {
178: throw new IllegalArgumentException(url);
179: }
180: }
181:
182: /**
183: * Run this test and produce a report.
184: * The test goes through the following steps: <ul>
185: * <li>load the input SVG into a Document</li>
186: * <li>build the GVT tree corresponding to the
187: * Document and dispatch the 'onload' event</li>
188: * <li>looks for one and only one <testResult> element in
189: * the Document. This is used to build the returned
190: * TestReport</li>
191: * </ul>
192: *
193: */
194: public TestReport runImpl() throws Exception {
195: DefaultTestReport report = new DefaultTestReport(this );
196:
197: //
198: // First step:
199: //
200: // Load the input SVG into a Document object
201: //
202: String parserClassName = XMLResourceDescriptor
203: .getXMLParserClassName();
204: SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(
205: parserClassName);
206: Document doc = null;
207:
208: try {
209: doc = f.createDocument(svgURL);
210: } catch (IOException e) {
211: report.setErrorCode(ERROR_CANNOT_LOAD_SVG_DOCUMENT);
212: report.addDescriptionEntry(ENTRY_KEY_ERROR_DESCRIPTION, e
213: .getMessage());
214: report.setPassed(false);
215: return report;
216: } catch (Exception e) {
217: report.setErrorCode(ERROR_CANNOT_LOAD_SVG_DOCUMENT);
218: report.addDescriptionEntry(ENTRY_KEY_ERROR_DESCRIPTION, e
219: .getMessage());
220: report.setPassed(false);
221: return report;
222: }
223:
224: //
225: // Second step:
226: //
227: // Now that the SVG file has been loaded, build
228: // a GVT Tree from it
229: //
230: UserAgent userAgent = buildUserAgent();
231: GVTBuilder builder = new GVTBuilder();
232: BridgeContext ctx = new BridgeContext(userAgent);
233: ctx.setDynamic(true);
234:
235: try {
236: builder.build(ctx, doc);
237: BaseScriptingEnvironment scriptEnvironment = new BaseScriptingEnvironment(
238: ctx);
239: scriptEnvironment.loadScripts();
240: scriptEnvironment.dispatchSVGLoadEvent();
241: } catch (BridgeException e) {
242: e.printStackTrace();
243: report.setErrorCode(ERROR_WHILE_PROCESSING_SVG_DOCUMENT);
244: report.addDescriptionEntry(ENTRY_KEY_ERROR_DESCRIPTION, e
245: .getMessage());
246: report.setPassed(false);
247: return report;
248: } catch (Exception e) {
249: e.printStackTrace();
250: report.setErrorCode(ERROR_WHILE_PROCESSING_SVG_DOCUMENT);
251: report.addDescriptionEntry(ENTRY_KEY_ERROR_DESCRIPTION, e
252: .getMessage());
253: report.setPassed(false);
254: return report;
255: }
256:
257: //
258: // Final step:
259: //
260: // Look for one and only one <testResult> element
261: //
262: NodeList testResultList = doc.getElementsByTagNameNS(testNS,
263: TAG_TEST_RESULT);
264:
265: // Check that there is one and only one testResult element
266: if (testResultList.getLength() != 1) {
267: report
268: .setErrorCode(ERROR_UNEXPECTED_NUMBER_OF_TEST_RESULT_ELEMENTS);
269: report.addDescriptionEntry(
270: ENTRY_KEY_NUMBER_OF_TEST_RESULT_ELEMENTS, ""
271: + testResultList.getLength());
272: report.setPassed(false);
273: return report;
274: }
275:
276: Element testResult = (Element) testResultList.item(0);
277:
278: // Now, get the result attribute. Whould be either "passed" or "failed"
279: String result = testResult.getAttributeNS(null,
280: ATTRIBUTE_RESULT);
281: boolean passed = true;
282: if (TEST_RESULT_PASSED.equals(result)) {
283: // OK
284: } else if (TEST_RESULT_FAILED.equals(result)) {
285: passed = false;
286: } else {
287: report.setErrorCode(ERROR_UNEXPECTED_RESULT_VALUE);
288: report.addDescriptionEntry(ENTRY_KEY_RESULT_VALUE, result);
289: report.setPassed(false);
290: return report;
291: }
292:
293: // If the test failed, then there should be an error code
294: if (!passed) {
295: String errorCode = testResult.getAttributeNS(null,
296: "errorCode");
297: if ("".equals(errorCode)) {
298: report
299: .setErrorCode(ERROR_MISSING_OR_EMPTY_ERROR_CODE_ON_FAILED_TEST);
300: report.setPassed(false);
301: return report;
302: }
303:
304: // We got an error code, set it on the report object
305: report.setErrorCode(errorCode);
306:
307: // Now, add descriptions from children <errorDescriptionEntry> elements
308: NodeList desc = testResult.getElementsByTagNameNS(testNS,
309: TAG_ERROR_DESCRIPTION_ENTRY);
310: int nDesc = desc.getLength();
311: for (int i = 0; i < nDesc; i++) {
312: Element entry = (Element) desc.item(i);
313: String key = entry.getAttributeNS(null, ATTRIBUTE_KEY);
314: String value = entry.getAttributeNS(null,
315: ATTRIBUTE_VALUE);
316: report.addDescriptionEntry(key, value);
317: }
318: report.setPassed(false);
319: return report;
320: }
321:
322: return report;
323: }
324:
325: /**
326: * Give subclasses a chance to build their own UserAgent
327: */
328: protected UserAgent buildUserAgent() {
329: return new UserAgentAdapter();
330: }
331:
332: }
|