| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package tests.util; |
| |
| import java.io.FileNotFoundException; |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.Enumeration; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import javax.xml.parsers.DocumentBuilder; |
| import javax.xml.parsers.DocumentBuilderFactory; |
| import javax.xml.parsers.ParserConfigurationException; |
| import javax.xml.transform.TransformerException; |
| |
| import junit.extensions.TestDecorator; |
| import junit.extensions.TestSetup; |
| import junit.framework.Test; |
| import junit.framework.TestCase; |
| import junit.framework.TestResult; |
| import junit.framework.TestSuite; |
| |
| import org.apache.xpath.XPathAPI; |
| import org.apache.xpath.objects.XObject; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| import org.xml.sax.SAXException; |
| import org.xml.sax.SAXParseException; |
| import org.xml.sax.helpers.DefaultHandler; |
| |
| /** |
| * Decorator for JUnit test suites that we want to run with certain test cases |
| * excluded. The exclusions are captured in a separate XML file. |
| */ |
| public class SomeTests extends TestSetup { |
| |
| private static final String EXCLUDES_SCHEMA_URI_PROP = "excludes.schema.uri"; |
| |
| private static final String EXCLUDES_FILE_URI_PROP = "excludes.file.uri"; |
| |
| private static final String JAXP_SCHEMA_SOURCE_ATTR_NAME = "http://java.sun.com/xml/jaxp/properties/schemaSource"; |
| |
| private static final String JAXP_SCHEMA_LANGUAGE_ATTR_VAL = "http://www.w3.org/2001/XMLSchema"; |
| |
| private static final String JAXP_SCHEMA_LANGUAGE_ATTR_NAME = "http://java.sun.com/xml/jaxp/properties/schemaLanguage"; |
| |
| private static final String DOCUMENT_BUILDER_FACTORY_VAL = "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl"; |
| |
| private static final String DOCUMENT_BUILDER_FACTORY_PROP = "javax.xml.parsers.DocumentBuilderFactory"; |
| |
| private Node excludesDoc; |
| |
| private final List<TestCase> runCases = new ArrayList<TestCase>(); |
| |
| private String excludesListURI; |
| |
| private String excludesSchemaURI; |
| |
| int originalTestCaseCount; |
| |
| private boolean docIsValid = false; |
| |
| /** |
| * @param test |
| * @param excludesListURI |
| * @param excludesSchemaURI |
| */ |
| public SomeTests(Test test) { |
| super(test); |
| initExcludes(); |
| |
| // Drill down into each test case contained in the supplied Test |
| // and, for each one *not* excluded, add the corresponding TestCase |
| // to an ordered collection. The number of TestCase objects in the |
| // collection is the number of test cases that will be run. |
| seekTests(this.getTest()); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see junit.extensions.TestDecorator#basicRun(junit.framework.TestResult) |
| */ |
| @Override |
| public void basicRun(TestResult result) { |
| // The 'basic run' of this decorator is to enumerate through all |
| // of the tests not excluded and run them... |
| Iterator<TestCase> allIncluded = runCases.iterator(); |
| while (allIncluded.hasNext()) { |
| TestCase test = allIncluded.next(); |
| test.run(result); |
| }// end while |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see junit.extensions.TestSetup#setUp() |
| */ |
| @Override |
| protected void setUp() throws Exception { |
| if (docIsValid) { |
| System.out.println("\nExcludes list document " + excludesListURI |
| + " is valid"); |
| } |
| System.out.println("\nRunning " + this.countTestCases() |
| + " out of a total of " + this.originalTestCaseCount |
| + " possible test cases\n"); |
| } |
| |
| @Override |
| protected void tearDown() throws Exception { |
| System.out.println("\nRan " + this.countTestCases() |
| + " out of a total of " + this.originalTestCaseCount |
| + " possible test cases\n"); |
| |
| if (excludesDoc != null) { |
| System.out.println("THE FOLLOWING EXCLUSIONS WERE ENFORCED:"); |
| NodeList allTypes = XPathAPI.selectNodeList(excludesDoc, |
| "/descendant::hy:type"); |
| for (int i = 0; i < allTypes.getLength(); i++) { |
| Node typeNode = allTypes.item(i); |
| String typeName = typeNode.getAttributes().getNamedItem("id") |
| .getNodeValue(); |
| NodeList allExcludesForType = XPathAPI.selectNodeList(typeNode, |
| "descendant::hy:exclude"); |
| for (int j = 0; j < allExcludesForType.getLength(); j++) { |
| Node excludeNode = allExcludesForType.item(j); |
| String excName = excludeNode.getAttributes().getNamedItem( |
| "id").getNodeValue(); |
| if (excName.equalsIgnoreCase("all")) { |
| excName = "!!!!!!!!!!ALL TESTS!!!!!!!!!!"; |
| } |
| System.out.print(typeName + "::" + excName); |
| Node reasonNode = XPathAPI.selectSingleNode(excludeNode, |
| "descendant::hy:reason"); |
| if (reasonNode != null) { |
| XObject reason = XPathAPI.eval(reasonNode, "string()"); |
| System.out.print(" (" + reason.str() + ")"); |
| } |
| System.out.print("\n"); |
| }// end for all excludes |
| }// end for all types |
| System.out.println("\n"); |
| } |
| super.tearDown(); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see junit.framework.Test#countTestCases() |
| */ |
| @Override |
| public int countTestCases() { |
| return runCases.size(); |
| } |
| |
| private void seekTests(TestSuite suite) { |
| Enumeration<?> allTests = suite.tests(); |
| while (allTests.hasMoreElements()) { |
| Test test = (Test) allTests.nextElement(); |
| seekTests(test); |
| }// end while |
| } |
| |
| private void seekTests(Test test) { |
| if (test instanceof TestSuite) { |
| seekTests((TestSuite) test); |
| } else if (test instanceof TestCase) { |
| seekTests((TestCase) test); |
| } else if (test instanceof TestDecorator) { |
| seekTests(((TestDecorator) test).getTest()); |
| } |
| } |
| |
| private void seekTests(TestCase testCase) { |
| // Check the testcase against the excludes structure |
| if (!isTestCaseExcluded(testCase)) { |
| // Add this testcase to the collection of tests to be run. |
| runCases.add(testCase); |
| } |
| } |
| |
| private boolean isTestCaseExcluded(TestCase testCase) { |
| this.originalTestCaseCount++; |
| boolean result = false; |
| String tcType = testCase.getClass().getName(); |
| String tcName = testCase.getName(); |
| |
| if (excludesDoc != null) { |
| try { |
| // Find *the first* element for the type. If there are |
| // more than one "type" elements for a given type then the |
| // first one found is what counts. |
| NodeList typeNodes = XPathAPI.selectNodeList(excludesDoc, |
| "/descendant::hy:type[@id=\"" + tcType + "\"]"); |
| if (typeNodes.getLength() > 0) { |
| Node typeNode = typeNodes.item(0); |
| // Look for a blanket exclusion of this test case type |
| NodeList excludes = XPathAPI.selectNodeList(typeNode, |
| "descendant::hy:exclude[@id=\"all\"]"); |
| if (excludes.getLength() != 0) { |
| result = true; |
| } else { |
| // Look for explicit exclusion |
| excludes = XPathAPI.selectNodeList(typeNode, |
| "descendant::hy:exclude[@id=\"" + tcName |
| + "\"]"); |
| if (excludes.getLength() != 0) { |
| result = true; |
| } |
| }// end else |
| }// end if named type located |
| } catch (TransformerException e) { |
| // Carry on. |
| result = false; |
| } |
| } |
| return result; |
| } |
| |
| /** |
| */ |
| private boolean initExcludes() { |
| boolean result = true; |
| |
| // Look for location of excludes list and (optionally) a schema |
| // location override. |
| readProperties(); |
| if (excludesListURI == null) { |
| System.out.println("No excludes list specified."); |
| result = false; |
| } |
| |
| if (result) { |
| try { |
| System.setProperty(DOCUMENT_BUILDER_FACTORY_PROP, |
| DOCUMENT_BUILDER_FACTORY_VAL); |
| DocumentBuilderFactory factory = DocumentBuilderFactory |
| .newInstance(); |
| factory.setNamespaceAware(true); |
| factory.setValidating(true); |
| factory.setAttribute(JAXP_SCHEMA_LANGUAGE_ATTR_NAME, |
| JAXP_SCHEMA_LANGUAGE_ATTR_VAL); |
| if (excludesSchemaURI != null) { |
| factory.setAttribute(JAXP_SCHEMA_SOURCE_ATTR_NAME, |
| excludesSchemaURI); |
| } |
| |
| DocumentBuilder builder = factory.newDocumentBuilder(); |
| DocValidator handler = new DocValidator(); |
| builder.setErrorHandler(handler); |
| excludesDoc = builder.parse(excludesListURI); |
| if (handler.inError == true) { |
| this.docIsValid = false; |
| System.out.println("Excludes list document " |
| + excludesListURI + " is invalid :" |
| + handler.inError + " " |
| + handler.spException.getMessage()); |
| excludesDoc = null; |
| result = false; |
| } else { |
| this.docIsValid = true; |
| } |
| } catch (FileNotFoundException e) { |
| System.out.println("File not found : " + e.getMessage()); |
| result = false; |
| } catch (ParserConfigurationException e) { |
| System.out.println("Serious error with XML parser : " |
| + e.getMessage()); |
| result = false; |
| } catch (SAXException e) { |
| System.out.println("Serious error occurred parsing document : " |
| + e.getMessage()); |
| result = false; |
| } catch (IOException e) { |
| System.out.println("IO error occurred : " + e.getMessage()); |
| result = false; |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * |
| */ |
| private void readProperties() { |
| excludesListURI = System.getProperty(EXCLUDES_FILE_URI_PROP); |
| excludesSchemaURI = System.getProperty(EXCLUDES_SCHEMA_URI_PROP); |
| } |
| |
| /** |
| */ |
| class DocValidator extends DefaultHandler { |
| private boolean inError = false; |
| |
| private SAXParseException spException = null; |
| |
| @Override |
| public void error(SAXParseException exception) throws SAXException { |
| inError = true; |
| spException = exception; |
| } |
| |
| @Override |
| public void fatalError(SAXParseException exception) throws SAXException { |
| inError = true; |
| spException = exception; |
| } |
| } |
| } |