Adding JUnit tests for org.apache.xerces.parsers.SecureProcessingConfiguration.

git-svn-id: https://svn.apache.org/repos/asf/xerces/java/trunk@1556029 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/tests/jaxp/AllTests.java b/tests/jaxp/AllTests.java
new file mode 100644
index 0000000..6f65ab6
--- /dev/null
+++ b/tests/jaxp/AllTests.java
@@ -0,0 +1,41 @@
+/*
+ * 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 jaxp;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * All JAXP JUnit Tests
+ * 
+ * @author Michael Glavassevich, IBM
+ * @version $Id$
+ */
+public class AllTests {
+    
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(AllTests.suite());
+    }
+    
+    public static Test suite() {
+        TestSuite suite = new TestSuite("Tests for JAXP");
+        suite.addTestSuite(JAXP12Tests.class);
+        suite.addTestSuite(JAXPSecureProcessingTest.class);
+        return suite;
+    }
+}
diff --git a/tests/jaxp/JAXPSecureProcessingTest.java b/tests/jaxp/JAXPSecureProcessingTest.java
new file mode 100644
index 0000000..1e664a1
--- /dev/null
+++ b/tests/jaxp/JAXPSecureProcessingTest.java
@@ -0,0 +1,421 @@
+/*
+ * 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 jaxp;
+
+import javax.xml.XMLConstants;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.validation.SchemaFactory;
+
+import junit.framework.TestCase;
+
+import org.xml.sax.SAXParseException;
+import org.xml.sax.XMLReader;
+
+/**
+ * Tests for JAXP secure processing features.
+ * 
+ * @author Michael Glavassevich, IBM
+ * @version $Id$
+ */
+public class JAXPSecureProcessingTest extends TestCase {
+    
+    private static final String ENTITY_EXPANSION_LIMIT_PROPERTY_NAME = "jdk.xml.entityExpansionLimit";
+    private static final String MAX_OCCUR_LIMIT_PROPERTY_NAME = "jdk.xml.maxOccur";
+    private static final String TOTAL_ENTITY_SIZE_LIMIT_PROPERTY_NAME = "jdk.xml.totalEntitySizeLimit";
+    private static final String MAX_GENERAL_ENTITY_SIZE_LIMIT_PROPERTY_NAME = "jdk.xml.maxGeneralEntitySizeLimit";
+    private static final String MAX_PARAMETER_ENTITY_SIZE_LIMIT_PROPERTY_NAME = "jdk.xml.maxParameterEntitySizeLimit";
+    
+    protected void setUp() throws Exception {
+        super.setUp();
+        System.setProperty("javax.xml.parsers.SAXParserFactory", "org.apache.xerces.jaxp.SAXParserFactoryImpl");
+        System.setProperty("javax.xml.parsers.DocumentBuilderFactory", "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl");
+        System.setProperty("javax.xml.validation.SchemaFactory:" + XMLConstants.W3C_XML_SCHEMA_NS_URI, 
+                "org.apache.xerces.jaxp.validation.XMLSchemaFactory");
+        System.setProperty("org.apache.xerces.xni.parser.XMLParserConfiguration", 
+                "org.apache.xerces.parsers.SecureProcessingConfiguration");
+        System.setProperty(ENTITY_EXPANSION_LIMIT_PROPERTY_NAME, "0");
+        System.setProperty(MAX_OCCUR_LIMIT_PROPERTY_NAME, "0");
+        System.setProperty(TOTAL_ENTITY_SIZE_LIMIT_PROPERTY_NAME, "0");
+        System.setProperty(MAX_GENERAL_ENTITY_SIZE_LIMIT_PROPERTY_NAME, "0");
+        System.setProperty(MAX_PARAMETER_ENTITY_SIZE_LIMIT_PROPERTY_NAME, "0");
+    }
+    
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+    
+    public void testSAXEntityExpansionLimitSG() throws Exception {
+        System.setProperty(ENTITY_EXPANSION_LIMIT_PROPERTY_NAME, "10000");
+        XMLReader reader = newSecureXMLReader();
+        try {
+            reader.parse(new InputData("gEntitySP.xml"));
+            fail("Expected SAXParseException");
+        }
+        catch (SAXParseException se) {
+            assertTrue(se.getMessage().indexOf("\"10,000\"") != -1);
+        }
+    }
+    
+    public void testSAXEntityExpansionLimitSP() throws Exception {
+        System.setProperty(ENTITY_EXPANSION_LIMIT_PROPERTY_NAME, "20000");
+        XMLReader reader = newSecureXMLReader();
+        try {
+            reader.parse(new InputData("pEntitySP.xml"));
+            fail("Expected SAXParseException");
+        }
+        catch (SAXParseException se) {
+            assertTrue(se.getMessage().indexOf("\"20,000\"") != -1);
+        }
+    }
+    
+    public void testSAXEntityExpansionLimitDG() throws Exception {
+        System.setProperty(ENTITY_EXPANSION_LIMIT_PROPERTY_NAME, "30000");
+        XMLReader reader = newDefaultXMLReader();
+        try {
+            reader.parse(new InputData("gEntitySP.xml"));
+            fail("Expected SAXParseException");
+        }
+        catch (SAXParseException se) {
+            assertTrue(se.getMessage().indexOf("\"30,000\"") != -1);
+        }
+    }
+    
+    public void testSAXEntityExpansionLimitDP() throws Exception {
+        System.setProperty(ENTITY_EXPANSION_LIMIT_PROPERTY_NAME, "40000");
+        XMLReader reader = newDefaultXMLReader();
+        try {
+            reader.parse(new InputData("pEntitySP.xml"));
+            fail("Expected SAXParseException");
+        }
+        catch (SAXParseException se) {
+            assertTrue(se.getMessage().indexOf("\"40,000\"") != -1);
+        }
+    }
+    
+    public void testDOMEntityExpansionLimitSG() throws Exception {
+        System.setProperty(ENTITY_EXPANSION_LIMIT_PROPERTY_NAME, "50000");
+        DocumentBuilder reader = newSecureDocumentBuilder();
+        try {
+            reader.parse(new InputData("gEntitySP.xml"));
+            fail("Expected SAXParseException");
+        }
+        catch (SAXParseException se) {
+            assertTrue(se.getMessage().indexOf("\"50,000\"") != -1);
+        }
+    }
+    
+    public void testDOMEntityExpansionLimitSP() throws Exception {
+        System.setProperty(ENTITY_EXPANSION_LIMIT_PROPERTY_NAME, "60000");
+        DocumentBuilder reader = newSecureDocumentBuilder();
+        try {
+            reader.parse(new InputData("pEntitySP.xml"));
+            fail("Expected SAXParseException");
+        }
+        catch (SAXParseException se) {
+            assertTrue(se.getMessage().indexOf("\"60,000\"") != -1);
+        }
+    }
+    
+    public void testDOMEntityExpansionLimitDG() throws Exception {
+        System.setProperty(ENTITY_EXPANSION_LIMIT_PROPERTY_NAME, "70000");
+        DocumentBuilder reader = newDefaultDocumentBuilder();
+        try {
+            reader.parse(new InputData("gEntitySP.xml"));
+            fail("Expected SAXParseException");
+        }
+        catch (SAXParseException se) {
+            assertTrue(se.getMessage().indexOf("\"70,000\"") != -1);
+        }
+    }
+    
+    public void testDOMEntityExpansionLimitDP() throws Exception {
+        System.setProperty(ENTITY_EXPANSION_LIMIT_PROPERTY_NAME, "80000");
+        DocumentBuilder reader = newDefaultDocumentBuilder();
+        try {
+            reader.parse(new InputData("pEntitySP.xml"));
+            fail("Expected SAXParseException");
+        }
+        catch (SAXParseException se) {
+            assertTrue(se.getMessage().indexOf("\"80,000\"") != -1);
+        }
+    }
+    
+    public void testSAXTotalEntitySizeLimitSG() throws Exception {
+        System.setProperty(TOTAL_ENTITY_SIZE_LIMIT_PROPERTY_NAME, "1");
+        XMLReader reader = newSecureXMLReader();
+        try {
+            reader.parse(new InputData("gEntitySP.xml"));
+            fail("Expected SAXParseException");
+        }
+        catch (SAXParseException se) {
+            assertTrue(se.getMessage().indexOf("\"1\"") != -1);
+        }
+    }
+    
+    public void testSAXTotalEntitySizeLimitSP() throws Exception {
+        System.setProperty(TOTAL_ENTITY_SIZE_LIMIT_PROPERTY_NAME, "10000");
+        XMLReader reader = newSecureXMLReader();
+        try {
+            reader.parse(new InputData("pEntitySP.xml"));
+            fail("Expected SAXParseException");
+        }
+        catch (SAXParseException se) {
+            assertTrue(se.getMessage().indexOf("\"10,000\"") != -1);
+        }
+    }
+    
+    public void testSAXTotalEntitySizeLimitDG() throws Exception {
+        System.setProperty(TOTAL_ENTITY_SIZE_LIMIT_PROPERTY_NAME, "2");
+        XMLReader reader = newDefaultXMLReader();
+        try {
+            reader.parse(new InputData("gEntitySP.xml"));
+            fail("Expected SAXParseException");
+        }
+        catch (SAXParseException se) {
+            assertTrue(se.getMessage().indexOf("\"2\"") != -1);
+        }
+    }
+    
+    public void testSAXTotalEntitySizeLimitDP() throws Exception {
+        System.setProperty(TOTAL_ENTITY_SIZE_LIMIT_PROPERTY_NAME, "20000");
+        XMLReader reader = newDefaultXMLReader();
+        try {
+            reader.parse(new InputData("pEntitySP.xml"));
+            fail("Expected SAXParseException");
+        }
+        catch (SAXParseException se) {
+            assertTrue(se.getMessage().indexOf("\"20,000\"") != -1);
+        }
+    }
+    
+    public void testDOMTotalEntitySizeLimitSG() throws Exception {
+        System.setProperty(TOTAL_ENTITY_SIZE_LIMIT_PROPERTY_NAME, "3");
+        DocumentBuilder reader = newSecureDocumentBuilder();
+        try {
+            reader.parse(new InputData("gEntitySP.xml"));
+            fail("Expected SAXParseException");
+        }
+        catch (SAXParseException se) {
+            assertTrue(se.getMessage().indexOf("\"3\"") != -1);
+        }
+    }
+    
+    public void testDOMTotalEntitySizeLimitSP() throws Exception {
+        System.setProperty(TOTAL_ENTITY_SIZE_LIMIT_PROPERTY_NAME, "30000");
+        DocumentBuilder reader = newSecureDocumentBuilder();
+        try {
+            reader.parse(new InputData("pEntitySP.xml"));
+            fail("Expected SAXParseException");
+        }
+        catch (SAXParseException se) {
+            assertTrue(se.getMessage().indexOf("\"30,000\"") != -1);
+        }
+    }
+    
+    public void testDOMTotalEntitySizeLimitDG() throws Exception {
+        System.setProperty(TOTAL_ENTITY_SIZE_LIMIT_PROPERTY_NAME, "4");
+        DocumentBuilder reader = newDefaultDocumentBuilder();
+        try {
+            reader.parse(new InputData("gEntitySP.xml"));
+            fail("Expected SAXParseException");
+        }
+        catch (SAXParseException se) {
+            assertTrue(se.getMessage().indexOf("\"4\"") != -1);
+        }
+    }
+    
+    public void testDOMTotalEntitySizeLimitDP() throws Exception {
+        System.setProperty(TOTAL_ENTITY_SIZE_LIMIT_PROPERTY_NAME, "40000");
+        DocumentBuilder reader = newDefaultDocumentBuilder();
+        try {
+            reader.parse(new InputData("pEntitySP.xml"));
+            fail("Expected SAXParseException");
+        }
+        catch (SAXParseException se) {
+            assertTrue(se.getMessage().indexOf("\"40,000\"") != -1);
+        }
+    }
+    
+    public void testSAXEntitySizeLimitSG() throws Exception {
+        System.setProperty(MAX_GENERAL_ENTITY_SIZE_LIMIT_PROPERTY_NAME, "1");
+        XMLReader reader = newSecureXMLReader();
+        try {
+            reader.parse(new InputData("gEntitySP.xml"));
+            fail("Expected SAXParseException");
+        }
+        catch (SAXParseException se) {
+            assertTrue(se.getMessage().indexOf("\"1\"") != -1);
+        }
+    }
+    
+    public void testSAXEntitySizeLimitSP() throws Exception {
+        System.setProperty(MAX_PARAMETER_ENTITY_SIZE_LIMIT_PROPERTY_NAME, "10000");
+        XMLReader reader = newSecureXMLReader();
+        try {
+            reader.parse(new InputData("pEntitySP.xml"));
+            fail("Expected SAXParseException");
+        }
+        catch (SAXParseException se) {
+            assertTrue(se.getMessage().indexOf("\"10,000\"") != -1);
+        }
+    }
+    
+    public void testSAXEntitySizeLimitDG() throws Exception {
+        System.setProperty(MAX_GENERAL_ENTITY_SIZE_LIMIT_PROPERTY_NAME, "2");
+        XMLReader reader = newDefaultXMLReader();
+        try {
+            reader.parse(new InputData("gEntitySP.xml"));
+            fail("Expected SAXParseException");
+        }
+        catch (SAXParseException se) {
+            assertTrue(se.getMessage().indexOf("\"2\"") != -1);
+        }
+    }
+    
+    public void testSAXEntitySizeLimitDP() throws Exception {
+        System.setProperty(MAX_PARAMETER_ENTITY_SIZE_LIMIT_PROPERTY_NAME, "20000");
+        XMLReader reader = newDefaultXMLReader();
+        try {
+            reader.parse(new InputData("pEntitySP.xml"));
+            fail("Expected SAXParseException");
+        }
+        catch (SAXParseException se) {
+            assertTrue(se.getMessage().indexOf("\"20,000\"") != -1);
+        }
+    }
+    
+    public void testDOMEntitySizeLimitSG() throws Exception {
+        System.setProperty(MAX_GENERAL_ENTITY_SIZE_LIMIT_PROPERTY_NAME, "3");
+        DocumentBuilder reader = newSecureDocumentBuilder();
+        try {
+            reader.parse(new InputData("gEntitySP.xml"));
+            fail("Expected SAXParseException");
+        }
+        catch (SAXParseException se) {
+            assertTrue(se.getMessage().indexOf("\"3\"") != -1);
+        }
+    }
+    
+    public void testDOMEntitySizeLimitSP() throws Exception {
+        System.setProperty(MAX_PARAMETER_ENTITY_SIZE_LIMIT_PROPERTY_NAME, "30000");
+        DocumentBuilder reader = newSecureDocumentBuilder();
+        try {
+            reader.parse(new InputData("pEntitySP.xml"));
+            fail("Expected SAXParseException");
+        }
+        catch (SAXParseException se) {
+            assertTrue(se.getMessage().indexOf("\"30,000\"") != -1);
+        }
+    }
+    
+    public void testDOMEntitySizeLimitDG() throws Exception {
+        System.setProperty(MAX_GENERAL_ENTITY_SIZE_LIMIT_PROPERTY_NAME, "4");
+        DocumentBuilder reader = newDefaultDocumentBuilder();
+        try {
+            reader.parse(new InputData("gEntitySP.xml"));
+            fail("Expected SAXParseException");
+        }
+        catch (SAXParseException se) {
+            assertTrue(se.getMessage().indexOf("\"4\"") != -1);
+        }
+    }
+    
+    public void testDOMEntitySizeLimitDP() throws Exception {
+        System.setProperty(MAX_PARAMETER_ENTITY_SIZE_LIMIT_PROPERTY_NAME, "40000");
+        DocumentBuilder reader = newDefaultDocumentBuilder();
+        try {
+            reader.parse(new InputData("pEntitySP.xml"));
+            fail("Expected SAXParseException");
+        }
+        catch (SAXParseException se) {
+            assertTrue(se.getMessage().indexOf("\"40,000\"") != -1);
+        }
+    }
+    
+    public void testSAXMaxOccursLimit() throws Exception {
+        System.setProperty(MAX_OCCUR_LIMIT_PROPERTY_NAME, "2500");
+        XMLReader reader = newSecureSchemaAwareXMLReader();
+        try {
+            reader.parse(new InputData("maxOccursSP.xml"));
+            fail("Expected SAXParseException");
+        }
+        catch (SAXParseException se) {
+            assertTrue(se.getMessage().indexOf("2,500") != -1);
+        }
+    }
+    
+    public void testDOMMaxOccursLimit() throws Exception {
+        System.setProperty(MAX_OCCUR_LIMIT_PROPERTY_NAME, "3500");
+        DocumentBuilder reader = newSecureSchemaAwareDocumentBuilder();
+        try {
+            reader.parse(new InputData("maxOccursSP.xml"));
+            fail("Expected SAXParseException");
+        }
+        catch (SAXParseException se) {
+            assertTrue(se.getMessage().indexOf("3,500") != -1);
+        }
+    } 
+    
+    private static XMLReader newSecureXMLReader() throws Exception {
+        SAXParserFactory spf = SAXParserFactory.newInstance();
+        spf.setNamespaceAware(true);
+        spf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+        return spf.newSAXParser().getXMLReader();
+    }
+    
+    private static XMLReader newSecureSchemaAwareXMLReader() throws Exception {
+        SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+        sf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+        SAXParserFactory spf = SAXParserFactory.newInstance();
+        spf.setNamespaceAware(true);
+        spf.setSchema(sf.newSchema());
+        spf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+        return spf.newSAXParser().getXMLReader();
+    }
+    
+    private static XMLReader newDefaultXMLReader() throws Exception {
+        SAXParserFactory spf = SAXParserFactory.newInstance();
+        spf.setNamespaceAware(true);
+        return spf.newSAXParser().getXMLReader();
+    }
+    
+    private static DocumentBuilder newSecureDocumentBuilder() throws Exception {
+        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+        dbf.setNamespaceAware(true);
+        dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+        return dbf.newDocumentBuilder();
+    }
+    
+    private static DocumentBuilder newSecureSchemaAwareDocumentBuilder() throws Exception {
+        SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+        sf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+        dbf.setNamespaceAware(true);
+        dbf.setSchema(sf.newSchema());
+        dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+        return dbf.newDocumentBuilder();
+    }
+    
+    private static DocumentBuilder newDefaultDocumentBuilder() throws Exception {
+        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+        dbf.setNamespaceAware(true);
+        return dbf.newDocumentBuilder();
+    }
+}
diff --git a/tests/jaxp/data/gEntitySP.xml b/tests/jaxp/data/gEntitySP.xml
new file mode 100644
index 0000000..5be35a3
--- /dev/null
+++ b/tests/jaxp/data/gEntitySP.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE root [
+ <!ENTITY x0 "x">
+ <!ENTITY x1 "&x0;&x0;">
+ <!ENTITY x2 "&x1;&x1;">
+ <!ENTITY x3 "&x2;&x2;">
+ <!ENTITY x4 "&x3;&x3;">
+ <!ENTITY x5 "&x4;&x4;">
+ <!ENTITY x6 "&x5;&x5;">
+ <!ENTITY x7 "&x6;&x6;">
+ <!ENTITY x8 "&x7;&x7;">
+ <!ENTITY x9 "&x8;&x8;">
+ <!ENTITY x10 "&x9;&x9;">
+ <!ENTITY x11 "&x10;&x10;">
+ <!ENTITY x12 "&x11;&x11;">
+ <!ENTITY x13 "&x12;&x12;">
+ <!ENTITY x14 "&x13;&x13;">
+ <!ENTITY x15 "&x14;&x14;">
+ <!ENTITY x16 "&x15;&x15;">
+ <!ENTITY x17 "&x16;&x16;">
+ <!ENTITY x18 "&x17;&x17;">
+ <!ENTITY x19 "&x18;&x18;">
+ <!ENTITY x20 "&x19;&x19;">
+ <!ENTITY x21 "&x20;&x20;">
+ <!ENTITY x22 "&x21;&x21;">
+ <!ENTITY x23 "&x22;&x22;">
+ <!ENTITY x24 "&x23;&x23;">
+ <!ENTITY x25 "&x24;&x24;">
+ <!ENTITY x26 "&x25;&x25;">
+ <!ENTITY x27 "&x26;&x26;">
+ <!ENTITY x28 "&x27;&x27;">
+ <!ENTITY x29 "&x28;&x28;">
+ <!ENTITY x30 "&x29;&x29;">
+]>
+<root>&x30;</root>
\ No newline at end of file
diff --git a/tests/jaxp/data/maxOccursSP.xml b/tests/jaxp/data/maxOccursSP.xml
new file mode 100644
index 0000000..36caa47
--- /dev/null
+++ b/tests/jaxp/data/maxOccursSP.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+      xsi:noNamespaceSchemaLocation='maxOccursSP.xsd'>
+ <child>val1</child>
+ <child>val2</child>
+ <child>val3</child>
+ <child>val4</child>
+ <child>val5</child>
+</root>
\ No newline at end of file
diff --git a/tests/jaxp/data/maxOccursSP.xsd b/tests/jaxp/data/maxOccursSP.xsd
new file mode 100644
index 0000000..57b7ba8
--- /dev/null
+++ b/tests/jaxp/data/maxOccursSP.xsd
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'>
+ <xs:element name="root">
+  <xs:complexType>
+   <xs:sequence maxOccurs="1000">
+    <xs:sequence maxOccurs="1000">
+     <xs:element name="child" type="xs:string" maxOccurs='1000'/>
+    </xs:sequence>
+   </xs:sequence>
+  </xs:complexType>
+ </xs:element>
+</xs:schema>
diff --git a/tests/jaxp/data/pEntitySP.dtd b/tests/jaxp/data/pEntitySP.dtd
new file mode 100644
index 0000000..318cb61
--- /dev/null
+++ b/tests/jaxp/data/pEntitySP.dtd
@@ -0,0 +1,31 @@
+<!ENTITY % x0 "x">
+<!ENTITY % x1 "%x0;%x0;">
+<!ENTITY % x2 "%x1;%x1;">
+<!ENTITY % x3 "%x2;%x2;">
+<!ENTITY % x4 "%x3;%x3;">
+<!ENTITY % x5 "%x4;%x4;">
+<!ENTITY % x6 "%x5;%x5;">
+<!ENTITY % x7 "%x6;%x6;">
+<!ENTITY % x8 "%x7;%x7;">
+<!ENTITY % x9 "%x8;%x8;">
+<!ENTITY % x10 "%x9;%x9;">
+<!ENTITY % x11 "%x10;%x10;">
+<!ENTITY % x12 "%x11;%x11;">
+<!ENTITY % x13 "%x12;%x12;">
+<!ENTITY % x14 "%x13;%x13;">
+<!ENTITY % x15 "%x14;%x14;">
+<!ENTITY % x16 "%x15;%x15;">
+<!ENTITY % x17 "%x16;%x16;">
+<!ENTITY % x18 "%x17;%x17;">
+<!ENTITY % x19 "%x18;%x18;">
+<!ENTITY % x20 "%x19;%x19;">
+<!ENTITY % x21 "%x20;%x20;">
+<!ENTITY % x22 "%x21;%x21;">
+<!ENTITY % x23 "%x22;%x22;">
+<!ENTITY % x24 "%x23;%x23;">
+<!ENTITY % x25 "%x24;%x24;">
+<!ENTITY % x26 "%x25;%x25;">
+<!ENTITY % x27 "%x26;%x26;">
+<!ENTITY % x28 "%x27;%x27;">
+<!ENTITY % x29 "%x28;%x28;">
+<!ENTITY % x30 "%x29;%x29;">
\ No newline at end of file
diff --git a/tests/jaxp/data/pEntitySP.xml b/tests/jaxp/data/pEntitySP.xml
new file mode 100644
index 0000000..2f21e3a
--- /dev/null
+++ b/tests/jaxp/data/pEntitySP.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE root SYSTEM "pEntitySP.dtd">
+<root/>
\ No newline at end of file