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.xml;
020:
021: import java.io.File;
022:
023: import java.net.URL;
024:
025: import java.util.HashSet;
026: import java.util.Set;
027: import java.util.StringTokenizer;
028:
029: import javax.xml.parsers.DocumentBuilderFactory;
030: import javax.xml.parsers.DocumentBuilder;
031:
032: import org.w3c.dom.Document;
033:
034: import org.apache.batik.test.DefaultTestReport;
035: import org.apache.batik.test.DefaultTestSuite;
036: import org.apache.batik.test.AbstractTest;
037: import org.apache.batik.test.TestReport;
038: import org.apache.batik.test.TestSuiteReport;
039:
040: /**
041: * Validates the operation of the <tt>XMLTestSuireRunner</tt> by checking
042: * that it runs the tests specified by the command line parameter and
043: * only these tests. <br />
044: * The test uses an dummy <testRun> which contains: <br />
045: * - testRun, id="all"
046: * - testSuite, href="testSuiteA.xml" <br />
047: * - testSuite, href="testSuiteB.xml" <br />
048: * Where: <br />
049: * - testSuite, id="A" <br />
050: * - test, id="A1" <br />
051: * - test, id="A2" <br />
052: * - test, id="duplicateId" <br />
053: * - testGroup, id="AG" <br />
054: * - test, id="AG1" <br />
055: * - test, id="AG2" <br />
056: *
057: * and: <br />
058: * - testSuite, id="B" <br />
059: * - test, id="B1" <br />
060: * - test, id="B2" <br />
061: * - test, id="B3" <br />
062: * - test, id="duplicateId" <br />
063: *
064: * where all the leaf test pass. <br />
065: *
066: * @author <a href="mailto:vhardy@apache.org">Vincent Hardy</a>
067: * @version $Id: XMLTestSuiteRunnerValidator.java 482121 2006-12-04 10:00:39Z dvholten $
068: */
069: public class XMLTestSuiteRunnerValidator extends DefaultTestSuite {
070: public static final String ERROR_TEST_NOT_RUN = "error.test.not.run";
071:
072: public static final String ERROR_EXTRA_TEST_RUN = "error.extra.test.run";
073:
074: public static final String ENTRY_KEY_CONFIGURATION = "entry.key.configuration";
075:
076: public static final String ENTRY_KEY_EXPECTED_RESULT = "entry.key.expected.result";
077:
078: public static final String ENTRY_KEY_ACTUAL_RESULT = "entry.key.actual.result";
079:
080: public static final String ENTRY_KEY_TEST_IDS_NOT_RUN = "entry.key.test.ids.not.run";
081:
082: public static final String ENTRY_KEY_TEST_ID_NOT_EXPECTED = "entry.key.test.id.not.expected";
083:
084: /**
085: * Dummy test-suite used to run the test
086: */
087: static final String dummyTestRun = "test-resources/org/apache/batik/test/xml/dummyTestRun.xml";
088:
089: /**
090: * This suite is made of elementary tests which validate that
091: * the XML result for a given input contains a list of
092: * report ids and no more (i.e., that the expected test reports
093: * were generated and no more). <br />
094: * Specificaly, with fully qualified ids: <br />
095: * - no arguments. All tests-reports should be produced. <br />
096: * - 1 target test: "all.B.B3". A single test-report should be produced
097: * for B3. <br />
098: * - 1 target test-suite: "all.A". A test-report with
099: * "A1", "A2", "duplicatedId", "AG", "AG.AG1" and "AG.AG2" should be produced.<br />
100: * - 1 target test-suite and 2 tests: "all.B and
101: * all.A.A1 and all.A.A2. A test-report for "all.B.B1", "all.B.B2",
102: * "all.B.B3", "all.B.duplicatedId", "all.A.A1" and "all.A.A2"
103: * should be produced. <br />
104: * - 1 target testGroup: "AG". A test-report with
105: * "A.AG", "A.AG.AG1" and "A.AG.AG2" should be produced.<br />
106: * <br />
107: * In addition, the following test with non-qualified ids: <br />
108: * - 1 target test id: "duplicatedId" should be produced and
109: * pass for "all.A.duplicatedId" and "all.B.duplicatedId".
110: */
111: public XMLTestSuiteRunnerValidator() {
112: Object[][] config = {
113: {
114: "",
115: new String[] { "all", "all.A", "all.A.A1",
116: "all.A.A2", "all.A.duplicatedId",
117: "all.A.duplicatedId.1",
118: "all.A.duplicatedId.2", "all.A.AG",
119: "all.A.AG.AG1", "all.A.AG.AG2",
120: "all.B", "all.B.B1", "all.B.B2",
121: "all.B.B3", "all.B.duplicatedId" } },
122:
123: { "all.B.B3",
124: new String[] { "all", "all.B", "all.B.B3" } },
125:
126: {
127: "all.A",
128: new String[] { "all", "all.A", "all.A.A1",
129: "all.A.A2", "all.A.duplicatedId",
130: "all.A.duplicatedId.1",
131: "all.A.duplicatedId.2", "all.A.AG",
132: "all.A.AG.AG1", "all.A.AG.AG2" } },
133:
134: {
135: "all.B all.A.A1 all.A.A2",
136: new String[] { "all", "all.B", "all.B.B1",
137: "all.B.B2", "all.B.B3",
138: "all.B.duplicatedId", "all.A",
139: "all.A.A1", "all.A.A2" } },
140:
141: {
142: "duplicatedId",
143: new String[] { "all", "all.A",
144: "all.A.duplicatedId",
145: "all.A.duplicatedId.1",
146: "all.A.duplicatedId.2", "all.B",
147: "all.B.duplicatedId" } },
148:
149: {
150: "AG",
151: new String[] { "all", "all.A", "all.A.AG",
152: "all.A.AG.AG1", "all.A.AG.AG2" } } };
153:
154: for (int i = 0; i < config.length; i++) {
155: addTest(new XMLTestSuiteRunnerTest(config[i]));
156: }
157:
158: }
159:
160: static class XMLTestSuiteRunnerTest extends AbstractTest {
161: /**
162: * Argument to feed into the XMLTestSuiteRunner
163: */
164: protected String[] args;
165:
166: /**
167: * Expected ids in the report generated by the
168: * XMLTestSuiteRunner
169: */
170: protected HashSet ids;
171: protected String[] idsArray;
172:
173: /**
174: * @param config an array of two objects: a String containing
175: * the "config" to pass to the XMLTestSuiteRunner and
176: * an array of Strings containing the expected ids
177: * from the XMLTestSuiteRunner operation.
178: */
179: public XMLTestSuiteRunnerTest(Object[] config) {
180: StringTokenizer st = new StringTokenizer(
181: (String) config[0], " ");
182: int nArgs = st.countTokens();
183: args = new String[nArgs];
184: for (int i = 0; i < nArgs; i++) {
185: args[i] = st.nextToken();
186: }
187:
188: ids = new HashSet();
189: for (int i = 0; i < (config[1] != null ? ((Object[]) config[1]).length
190: : 0); i++) {
191: ids.add(((Object[]) config[1])[i]);
192: }
193: idsArray = (String[]) config[1];
194: }
195:
196: /**
197: * <tt>AbstractTest</tt>'s template method implementation.
198: */
199: public TestReport runImpl() throws Exception {
200: //
201: // Load the template dummy testRun file.
202: //
203: Document doc = loadDummyTestRun();
204:
205: //
206: // Now run the test.
207: //
208: XMLTestSuiteRunner runner = new XMLTestSuiteRunner();
209:
210: TestReport runReport = runner.run(doc, args);
211:
212: //
213: // Analyse TestReport
214: //
215: Set idSet = (Set) (ids.clone());
216: String idNotExpected = checkTestReport(runReport, idSet);
217:
218: if (idNotExpected == null) {
219: if (idSet.isEmpty()) {
220: return reportSuccess();
221: } else {
222: DefaultTestReport report = new DefaultTestReport(
223: this );
224: report.setErrorCode(ERROR_TEST_NOT_RUN);
225: report.addDescriptionEntry(ENTRY_KEY_CONFIGURATION,
226: arrayToString(args));
227: report.addDescriptionEntry(
228: ENTRY_KEY_EXPECTED_RESULT,
229: arrayToString(idsArray));
230: report.addDescriptionEntry(ENTRY_KEY_ACTUAL_RESULT,
231: reportIdsToString(runReport));
232: report.addDescriptionEntry(
233: ENTRY_KEY_TEST_IDS_NOT_RUN,
234: arrayToString(idSet.toArray()));
235: report.setPassed(false);
236: return report;
237: }
238: } else {
239: DefaultTestReport report = new DefaultTestReport(this );
240: report.setErrorCode(ERROR_EXTRA_TEST_RUN);
241: report.addDescriptionEntry(ENTRY_KEY_CONFIGURATION,
242: arrayToString(args));
243: report.addDescriptionEntry(ENTRY_KEY_EXPECTED_RESULT,
244: arrayToString(idsArray));
245: report.addDescriptionEntry(ENTRY_KEY_ACTUAL_RESULT,
246: reportIdsToString(runReport));
247: report.addDescriptionEntry(
248: ENTRY_KEY_TEST_ID_NOT_EXPECTED, idNotExpected);
249: report.setPassed(false);
250: return report;
251: }
252: }
253:
254: protected String arrayToString(Object[] array) {
255: StringBuffer sb = new StringBuffer();
256: if (array != null) {
257: if (array.length > 0) {
258: sb.append(array[0]);
259: }
260: for (int i = 1; i < array.length; i++) {
261: sb.append(", ");
262: sb.append(array[i].toString());
263: }
264: }
265: return sb.toString();
266: }
267:
268: protected String reportIdsToString(TestReport r) {
269: StringBuffer sb = new StringBuffer();
270: if (r != null) {
271: sb.append(r.getTest().getQualifiedId());
272: if (r instanceof TestSuiteReport) {
273: TestReport[] c = ((TestSuiteReport) r)
274: .getChildrenReports();
275: if (c != null) {
276: for (int i = 0; i < c.length; i++) {
277: appendReportIds(c[i], sb);
278: }
279: }
280: }
281: } else {
282: sb.append("null");
283: }
284:
285: return sb.toString();
286: }
287:
288: protected void appendReportIds(TestReport r, StringBuffer sb) {
289: if (r != null) {
290: sb.append(", ");
291: sb.append(r.getTest().getQualifiedId());
292:
293: if (r instanceof TestSuiteReport) {
294: TestReport[] c = ((TestSuiteReport) r)
295: .getChildrenReports();
296: if (c != null) {
297: for (int i = 0; i < c.length; i++) {
298: appendReportIds(c[i], sb);
299: }
300: }
301: }
302: }
303: }
304:
305: /**
306: * Loads the dummy testRun description
307: */
308: protected Document loadDummyTestRun() throws Exception {
309: DocumentBuilder docBuilder = DocumentBuilderFactory
310: .newInstance().newDocumentBuilder();
311:
312: URL url = (new File(
313: XMLTestSuiteRunnerValidator.dummyTestRun)).toURL();
314: return docBuilder.parse(url.toString());
315:
316: }
317:
318: /**
319: * Validates that the input <tt>TestReport</tt>
320: * contains only the expected identifiers.
321: * The following code is by no means optimized,
322: * but it gets the job done.
323: */
324: protected String checkTestReport(TestReport report, Set idSet) {
325: String id = report.getTest().getQualifiedId();
326: if (!(idSet.contains(id))) {
327: return id;
328: }
329:
330: idSet.remove(id);
331:
332: //
333: // Now, process children reports if any.
334: //
335: if (report instanceof TestSuiteReport) {
336: TestReport[] childReports = ((TestSuiteReport) report)
337: .getChildrenReports();
338: if (childReports != null) {
339: for (int i = 0; i < childReports.length; i++) {
340: String idNotExpected = checkTestReport(
341: childReports[i], idSet);
342: if (idNotExpected != null) {
343: return idNotExpected;
344: }
345: }
346: }
347: }
348:
349: return null;
350: }
351:
352: }
353:
354: }
|