summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Wilson <jessewilson@google.com>2010-11-22 17:18:45 -0800
committerAndroid (Google) Code Review <android-gerrit@google.com>2010-11-22 17:18:45 -0800
commite4897c7a2d4ad0cd98cd054c970c02ca73e33fae (patch)
treee3bf71c751d0a43eff27cfcf2ca84b5e0a136713
parentd501410a90f09d186dc0ba1c8ecbe90a9b36a8ec (diff)
parent838419e39510cb3bf04cf5bfef2929a7cf759e65 (diff)
downloadlibcore-e4897c7a2d4ad0cd98cd054c970c02ca73e33fae.zip
libcore-e4897c7a2d4ad0cd98cd054c970c02ca73e33fae.tar.gz
libcore-e4897c7a2d4ad0cd98cd054c970c02ca73e33fae.tar.bz2
Merge "Test the behavior of pull parser DTD parsing / handling." into dalvik-dev
-rw-r--r--luni/src/test/java/libcore/xml/ExpatPullParserDtdTest.java26
-rw-r--r--luni/src/test/java/libcore/xml/KxmlPullParserDtdTest.java26
-rw-r--r--luni/src/test/java/libcore/xml/PullParserDtdTest.java340
-rw-r--r--luni/src/test/java/libcore/xml/PullParserTest.java35
4 files changed, 393 insertions, 34 deletions
diff --git a/luni/src/test/java/libcore/xml/ExpatPullParserDtdTest.java b/luni/src/test/java/libcore/xml/ExpatPullParserDtdTest.java
new file mode 100644
index 0000000..5e62310
--- /dev/null
+++ b/luni/src/test/java/libcore/xml/ExpatPullParserDtdTest.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed 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 libcore.xml;
+
+import org.apache.harmony.xml.ExpatPullParser;
+import org.xmlpull.v1.XmlPullParser;
+
+public class ExpatPullParserDtdTest extends PullParserDtdTest {
+ @Override XmlPullParser newPullParser() {
+ return new ExpatPullParser();
+ }
+}
diff --git a/luni/src/test/java/libcore/xml/KxmlPullParserDtdTest.java b/luni/src/test/java/libcore/xml/KxmlPullParserDtdTest.java
new file mode 100644
index 0000000..6de11c0
--- /dev/null
+++ b/luni/src/test/java/libcore/xml/KxmlPullParserDtdTest.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed 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 libcore.xml;
+
+import org.kxml2.io.KXmlParser;
+import org.xmlpull.v1.XmlPullParser;
+
+public class KxmlPullParserDtdTest extends PullParserDtdTest {
+ @Override XmlPullParser newPullParser() {
+ return new KXmlParser();
+ }
+}
diff --git a/luni/src/test/java/libcore/xml/PullParserDtdTest.java b/luni/src/test/java/libcore/xml/PullParserDtdTest.java
new file mode 100644
index 0000000..c5282f2
--- /dev/null
+++ b/luni/src/test/java/libcore/xml/PullParserDtdTest.java
@@ -0,0 +1,340 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed 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 libcore.xml;
+
+import java.io.IOException;
+import java.io.StringReader;
+import junit.framework.TestCase;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+/**
+ * Test doctype handling in pull parsers.
+ */
+public abstract class PullParserDtdTest extends TestCase {
+
+ /**
+ * Android's Expat pull parser permits parameter entities to be declared,
+ * but it doesn't permit such entities to be used.
+ */
+ public void testDeclaringParameterEntities() throws Exception {
+ String xml = "<!DOCTYPE foo ["
+ + " <!ENTITY % a \"android\">"
+ + "]><foo></foo>";
+ XmlPullParser parser = newPullParser(xml);
+ while (parser.next() != XmlPullParser.END_DOCUMENT) {
+ }
+ }
+
+ public void testUsingParameterEntitiesInDtds() throws Exception {
+ String xml = "<!DOCTYPE foo ["
+ + " <!ENTITY % a \"android\">"
+ + " <!ENTITY b \"%a;\">"
+ + "]><foo></foo>";
+ XmlPullParser parser = newPullParser(xml);
+ assertParseFailure(parser);
+ }
+
+ public void testUsingParameterInDocuments() throws Exception {
+ String xml = "<!DOCTYPE foo ["
+ + " <!ENTITY % a \"android\">"
+ + "]><foo>&a;</foo>";
+ XmlPullParser parser = newPullParser(xml);
+ assertParseFailure(parser);
+ }
+
+ public void testInternalEntities() throws Exception {
+ String xml = "<!DOCTYPE foo ["
+ + " <!ENTITY a \"android\">"
+ + "]><foo>&a;</foo>";
+ XmlPullParser parser = newPullParser(xml);
+ assertEquals(XmlPullParser.START_TAG, parser.next());
+ assertEquals(XmlPullParser.TEXT, parser.next());
+ assertEquals("android", parser.getText());
+ assertEquals(XmlPullParser.END_TAG, parser.next());
+ assertEquals(XmlPullParser.END_DOCUMENT, parser.next());
+ }
+
+ public void testExternalDtdIsSilentlyIgnored() throws Exception {
+ String xml = "<!DOCTYPE foo SYSTEM \"http://127.0.0.1:1/no-such-file.dtd\"><foo></foo>";
+ XmlPullParser parser = newPullParser(xml);
+ assertEquals(XmlPullParser.START_TAG, parser.next());
+ assertEquals("foo", parser.getName());
+ assertEquals(XmlPullParser.END_TAG, parser.next());
+ assertEquals("foo", parser.getName());
+ assertEquals(XmlPullParser.END_DOCUMENT, parser.next());
+ }
+
+ public void testExternalAndInternalDtd() throws Exception {
+ String xml = "<!DOCTYPE foo SYSTEM \"http://127.0.0.1:1/no-such-file.dtd\" ["
+ + " <!ENTITY a \"android\">"
+ + "]><foo>&a;</foo>";
+ XmlPullParser parser = newPullParser(xml);
+ assertEquals(XmlPullParser.START_TAG, parser.next());
+ assertEquals(XmlPullParser.TEXT, parser.next());
+ assertEquals("android", parser.getText());
+ assertEquals(XmlPullParser.END_TAG, parser.next());
+ assertEquals(XmlPullParser.END_DOCUMENT, parser.next());
+ }
+
+ public void testInternalEntitiesAreParsed() throws Exception {
+ String xml = "<!DOCTYPE foo ["
+ + " <!ENTITY a \"&#38;#65;\">" // &#38; expands to '&', &#65; expands to 'A'
+ + "]><foo>&a;</foo>";
+ XmlPullParser parser = newPullParser(xml);
+ assertEquals(XmlPullParser.START_TAG, parser.next());
+ assertEquals(XmlPullParser.TEXT, parser.next());
+ assertEquals("A", parser.getText());
+ assertEquals(XmlPullParser.END_TAG, parser.next());
+ assertEquals(XmlPullParser.END_DOCUMENT, parser.next());
+ }
+
+ public void testFoolishlyRecursiveInternalEntities() throws Exception {
+ String xml = "<!DOCTYPE foo ["
+ + " <!ENTITY a \"&#38;#38;#38;#38;\">" // expand &#38; to '&' only twice
+ + "]><foo>&a;</foo>";
+ XmlPullParser parser = newPullParser(xml);
+ assertEquals(XmlPullParser.START_TAG, parser.next());
+ assertEquals(XmlPullParser.TEXT, parser.next());
+ assertEquals("&#38;#38;", parser.getText());
+ assertEquals(XmlPullParser.END_TAG, parser.next());
+ assertEquals(XmlPullParser.END_DOCUMENT, parser.next());
+ }
+
+ /**
+ * Android's Expat replaces external entities with the empty string.
+ */
+ public void testUsingExternalEntities() throws Exception {
+ String xml = "<!DOCTYPE foo ["
+ + " <!ENTITY a SYSTEM \"http://localhost:1/no-such-file.xml\">"
+ + "]><foo>&a;</foo>";
+ XmlPullParser parser = newPullParser(xml);
+ assertEquals(XmlPullParser.START_TAG, parser.next());
+ // &a; is dropped!
+ assertEquals(XmlPullParser.END_TAG, parser.next());
+ assertEquals(XmlPullParser.END_DOCUMENT, parser.next());
+ }
+
+ public void testExternalIdIsCaseSensitive() throws Exception {
+ // The spec requires 'SYSTEM' in upper case
+ String xml = "<!DOCTYPE foo ["
+ + " <!ENTITY a system \"http://localhost:1/no-such-file.xml\">"
+ + "]><foo/>";
+ XmlPullParser parser = newPullParser(xml);
+ assertParseFailure(parser);
+ }
+
+ /**
+ * Use a DTD to specify that {@code <foo>} only contains {@code <bar>} tags.
+ * Validating parsers react to this by dropping whitespace between the two
+ * tags.
+ */
+ public void testDtdDoesNotInformIgnorableWhitespace() throws Exception {
+ String xml = "<!DOCTYPE foo [\n"
+ + " <!ELEMENT foo (bar)*>\n"
+ + " <!ELEMENT bar ANY>\n"
+ + "]>"
+ + "<foo> \n <bar></bar> \t </foo>";
+ XmlPullParser parser = newPullParser(xml);
+ assertEquals(XmlPullParser.START_TAG, parser.next());
+ assertEquals("foo", parser.getName());
+ assertEquals(XmlPullParser.TEXT, parser.next());
+ assertEquals(" \n ", parser.getText());
+ assertEquals(XmlPullParser.START_TAG, parser.next());
+ assertEquals("bar", parser.getName());
+ assertEquals(XmlPullParser.END_TAG, parser.next());
+ assertEquals("bar", parser.getName());
+ assertEquals(XmlPullParser.TEXT, parser.next());
+ assertEquals(" \t ", parser.getText());
+ assertEquals(XmlPullParser.END_TAG, parser.next());
+ assertEquals(XmlPullParser.END_DOCUMENT, parser.next());
+ }
+
+ public void testEmptyDoesNotInformIgnorableWhitespace() throws Exception {
+ String xml = "<!DOCTYPE foo [\n"
+ + " <!ELEMENT foo EMPTY>\n"
+ + "]>"
+ + "<foo> \n </foo>";
+ XmlPullParser parser = newPullParser(xml);
+ assertEquals(XmlPullParser.START_TAG, parser.next());
+ assertEquals("foo", parser.getName());
+ assertEquals(XmlPullParser.TEXT, parser.next());
+ assertEquals(" \n ", parser.getText());
+ assertEquals(XmlPullParser.END_TAG, parser.next());
+ assertEquals(XmlPullParser.END_DOCUMENT, parser.next());
+ }
+
+ /**
+ * Test that the parser doesn't expand the entity attributes.
+ */
+ public void testAttributeOfTypeEntity() throws Exception {
+ String xml = "<!DOCTYPE foo [\n"
+ + " <!ENTITY a \"android\">"
+ + " <!ELEMENT foo ANY>\n"
+ + " <!ATTLIST foo\n"
+ + " bar ENTITY #IMPLIED>"
+ + "]>"
+ + "<foo bar=\"a\"></foo>";
+ XmlPullParser parser = newPullParser(xml);
+ assertEquals(XmlPullParser.START_TAG, parser.next());
+ assertEquals("foo", parser.getName());
+ assertEquals("a", parser.getAttributeValue(null, "bar"));
+ assertEquals(XmlPullParser.END_TAG, parser.next());
+ assertEquals(XmlPullParser.END_DOCUMENT, parser.next());
+ }
+
+ public void testTagStructureNotValidated() throws Exception {
+ String xml = "<!DOCTYPE foo [\n"
+ + " <!ELEMENT foo (bar)*>\n"
+ + " <!ELEMENT bar ANY>\n"
+ + " <!ELEMENT baz ANY>\n"
+ + "]>"
+ + "<foo><bar/><bar/><baz/></foo>";
+ XmlPullParser parser = newPullParser(xml);
+ assertEquals(XmlPullParser.START_TAG, parser.next());
+ assertEquals("foo", parser.getName());
+ assertEquals(XmlPullParser.START_TAG, parser.next());
+ assertEquals("bar", parser.getName());
+ assertEquals(XmlPullParser.END_TAG, parser.next());
+ assertEquals(XmlPullParser.START_TAG, parser.next());
+ assertEquals("bar", parser.getName());
+ assertEquals(XmlPullParser.END_TAG, parser.next());
+ assertEquals(XmlPullParser.START_TAG, parser.next());
+ assertEquals("baz", parser.getName());
+ assertEquals(XmlPullParser.END_TAG, parser.next());
+ assertEquals(XmlPullParser.END_TAG, parser.next());
+ assertEquals(XmlPullParser.END_DOCUMENT, parser.next());
+ }
+
+ public void testAttributeDefaultValues() throws Exception {
+ String xml = "<!DOCTYPE foo [\n"
+ + " <!ELEMENT foo ANY>\n"
+ + " <!ATTLIST foo\n"
+ + " bar (a|b|c) \"c\">"
+ + "]>"
+ + "<foo></foo>";
+ XmlPullParser parser = newPullParser(xml);
+ assertEquals(XmlPullParser.START_TAG, parser.next());
+ assertEquals("foo", parser.getName());
+ assertEquals("c", parser.getAttributeValue(null, "bar"));
+ assertEquals(XmlPullParser.END_TAG, parser.next());
+ }
+
+ public void testRequiredAttributesOmitted() throws Exception {
+ String xml = "<!DOCTYPE foo [\n"
+ + " <!ELEMENT foo ANY>\n"
+ + " <!ATTLIST foo\n"
+ + " bar (a|b|c) #REQUIRED>"
+ + "]>"
+ + "<foo></foo>";
+ XmlPullParser parser = newPullParser(xml);
+ assertEquals(XmlPullParser.START_TAG, parser.next());
+ assertEquals("foo", parser.getName());
+ assertEquals(null, parser.getAttributeValue(null, "bar"));
+ assertEquals(XmlPullParser.END_TAG, parser.next());
+ }
+
+ public void testFixedAttributesWithConflictingValues() throws Exception {
+ String xml = "<!DOCTYPE foo [\n"
+ + " <!ELEMENT foo ANY>\n"
+ + " <!ATTLIST foo\n"
+ + " bar (a|b|c) #FIXED \"c\">"
+ + "]>"
+ + "<foo bar=\"a\"></foo>";
+ XmlPullParser parser = newPullParser(xml);
+ assertEquals(XmlPullParser.START_TAG, parser.next());
+ assertEquals("foo", parser.getName());
+ assertEquals("a", parser.getAttributeValue(null, "bar"));
+ assertEquals(XmlPullParser.END_TAG, parser.next());
+ }
+
+ public void testParsingNotations() throws Exception {
+ String xml = "<!DOCTYPE foo [\n"
+ + " <!NOTATION type-a PUBLIC \"application/a\"> \n"
+ + " <!NOTATION type-b PUBLIC \"image/b\">\n"
+ + " <!NOTATION type-c PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n"
+ + " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\"> \n"
+ + " <!ENTITY file SYSTEM \"d.xml\">\n"
+ + " <!ENTITY fileWithNdata SYSTEM \"e.bin\" NDATA type-b>\n"
+ + "]>"
+ + "<foo type=\"type-a\"/>";
+ XmlPullParser parser = newPullParser(xml);
+ assertEquals(XmlPullParser.START_TAG, parser.next());
+ assertEquals("foo", parser.getName());
+ assertEquals(XmlPullParser.END_TAG, parser.next());
+ }
+
+ public void testCommentsInDoctype() throws Exception {
+ String xml = "<!DOCTYPE foo ["
+ + " <!-- ' -->"
+ + "]><foo>android</foo>";
+ XmlPullParser parser = newPullParser(xml);
+ assertEquals(XmlPullParser.START_TAG, parser.next());
+ assertEquals(XmlPullParser.TEXT, parser.next());
+ assertEquals("android", parser.getText());
+ assertEquals(XmlPullParser.END_TAG, parser.next());
+ assertEquals(XmlPullParser.END_DOCUMENT, parser.next());
+ }
+
+ public void testDoctypeNameOnly() throws Exception {
+ String xml = "<!DOCTYPE foo><foo></foo>";
+ XmlPullParser parser = newPullParser(xml);
+ assertEquals(XmlPullParser.START_TAG, parser.next());
+ assertEquals("foo", parser.getName());
+ assertEquals(XmlPullParser.END_TAG, parser.next());
+ assertEquals("foo", parser.getName());
+ assertEquals(XmlPullParser.END_DOCUMENT, parser.next());
+ }
+
+ public void testDoctypeWithNextToken() throws Exception {
+ String xml = "<!DOCTYPE foo [<!ENTITY bb \"bar baz\">]><foo>a&bb;c</foo>";
+ XmlPullParser parser = newPullParser(xml);
+ assertEquals(XmlPullParser.DOCDECL, parser.nextToken());
+ assertEquals(" foo [<!ENTITY bb \"bar baz\">]", parser.getText());
+ assertNull(parser.getName());
+ assertEquals(XmlPullParser.START_TAG, parser.nextToken());
+ assertEquals(XmlPullParser.TEXT, parser.nextToken());
+ assertEquals("a", parser.getText());
+ assertEquals(XmlPullParser.ENTITY_REF, parser.nextToken());
+ assertEquals("bb", parser.getName());
+ assertEquals("bar baz", parser.getText()); // TODO: this fails on gingerbread
+ assertEquals(XmlPullParser.TEXT, parser.nextToken());
+ assertEquals("c", parser.getText());
+ assertEquals(XmlPullParser.END_TAG, parser.next());
+ assertEquals(XmlPullParser.END_DOCUMENT, parser.next());
+ }
+
+ private void assertParseFailure(XmlPullParser parser) throws IOException {
+ try {
+ while (parser.next() != XmlPullParser.END_DOCUMENT) {
+ }
+ fail();
+ } catch (XmlPullParserException expected) {
+ }
+ }
+
+ private XmlPullParser newPullParser(String xml) throws XmlPullParserException {
+ XmlPullParser result = newPullParser();
+ result.setInput(new StringReader(xml));
+ return result;
+ }
+
+ /**
+ * Creates a new pull parser.
+ */
+ abstract XmlPullParser newPullParser();
+}
diff --git a/luni/src/test/java/libcore/xml/PullParserTest.java b/luni/src/test/java/libcore/xml/PullParserTest.java
index d76bed6..47036c6 100644
--- a/luni/src/test/java/libcore/xml/PullParserTest.java
+++ b/luni/src/test/java/libcore/xml/PullParserTest.java
@@ -431,39 +431,6 @@ public abstract class PullParserTest extends TestCase {
assertEquals("]]>", parser.getText());
}
- public void testDoctypeWithNext() throws Exception {
- String s = "<!DOCTYPE foo ["
- + " <!ENTITY bb \"bar baz\">"
- + " <!NOTATION png SYSTEM \"image/png\">"
- + "]><foo>a&bb;c</foo>";
- XmlPullParser parser = newPullParser();
- parser.setInput(new StringReader(
- "<!DOCTYPE foo [<!ENTITY bb \"bar baz\">]><foo>a&bb;c</foo>"));
- assertEquals(XmlPullParser.START_TAG, parser.next());
- assertEquals(XmlPullParser.TEXT, parser.next());
- assertEquals("abar bazc", parser.getText()); // TODO: this fails on gingerbread
- assertEquals(XmlPullParser.END_TAG, parser.next());
- }
-
- public void testDoctypeWithNextToken() throws Exception {
- XmlPullParser parser = newPullParser();
- parser.setInput(new StringReader(
- "<!DOCTYPE foo [<!ENTITY bb \"bar baz\">]><foo>a&bb;c</foo>"));
- assertEquals(XmlPullParser.DOCDECL, parser.nextToken());
- assertEquals(" foo [<!ENTITY bb \"bar baz\">]", parser.getText());
- assertNull(parser.getName());
-
- assertEquals(XmlPullParser.START_TAG, parser.nextToken());
- assertEquals(XmlPullParser.TEXT, parser.nextToken());
- assertEquals("a", parser.getText());
- assertEquals(XmlPullParser.ENTITY_REF, parser.nextToken());
- assertEquals("bb", parser.getName());
- assertEquals("bar baz", parser.getText()); // TODO: this fails on gingerbread
- assertEquals(XmlPullParser.TEXT, parser.nextToken());
- assertEquals("c", parser.getText());
- assertEquals(XmlPullParser.END_TAG, parser.next());
- }
-
public void testProcessingInstructionWithNext() throws Exception {
XmlPullParser parser = newPullParser();
parser.setInput(new StringReader("<foo>ab<?cd efg hij?>kl</foo>"));
@@ -710,7 +677,7 @@ public abstract class PullParserTest extends TestCase {
}
/**
- * Creates a new pull parser with namespace support.
+ * Creates a new pull parser.
*/
abstract XmlPullParser newPullParser();
}