diff options
author | Jesse Wilson <jessewilson@google.com> | 2010-02-19 09:22:21 -0800 |
---|---|---|
committer | Jesse Wilson <jessewilson@google.com> | 2010-02-19 09:22:21 -0800 |
commit | 1ec94feeb09591c30996c7c0834d6f131e204922 (patch) | |
tree | 28de8c0740a3032d3a5bd6c3a9414e448f9dd7b7 /xml/src/test/java | |
parent | 3fe3b27d0af854f28fc8de612271c0ca9cd6a8f7 (diff) | |
download | libcore-1ec94feeb09591c30996c7c0834d6f131e204922.zip libcore-1ec94feeb09591c30996c7c0834d6f131e204922.tar.gz libcore-1ec94feeb09591c30996c7c0834d6f131e204922.tar.bz2 |
Filling in some gaps in our XML DOM v3 API.
Specifically, these methods on Node:
- setTextContent()
- isSameNode()
- lookupPrefix()
- lookupNamespaceURI()
In order to implement the last 2 I needed to fix our KXml parser
to include namespace attributes (ie. xmlns) in the pulled document.
Previously these were being elided.
Added a new testcase to verify our behaviour. It passes the RI. On
Dalvik we have a small issue with entity declarations.
Added a new testcase to verify Node.getBaseURI(). This test fails
because the method isn't implemented. Part of this test required
moving a method out to Support_Resources.java; in order to verify
the BaseURI the XML must be read from a file and not a stream (so
that path information exists).
Also...
- Style cleanup: changing static calls to look like static calls.
- Efficiency: avoiding concatenating with "" when unnecessary
- Duplication: sharing prefix validation between attributes and elements
- Renaming NodeTests to NodeTest for vogar-friendliness
Outstanding:
- I need to write a test for setTextContent().
Diffstat (limited to 'xml/src/test/java')
-rw-r--r-- | xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderTest.java | 25 | ||||
-rw-r--r-- | xml/src/test/java/tests/xml/AllTests.java | 2 | ||||
-rw-r--r-- | xml/src/test/java/tests/xml/DomTest.java | 280 | ||||
-rw-r--r-- | xml/src/test/java/tests/xml/NodeTest.java | 86 | ||||
-rw-r--r-- | xml/src/test/java/tests/xml/NodeTests.java | 47 |
5 files changed, 371 insertions, 69 deletions
diff --git a/xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderTest.java b/xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderTest.java index 02b6d80..6b10a0d 100644 --- a/xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderTest.java +++ b/xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderTest.java @@ -34,6 +34,7 @@ import org.xml.sax.SAXParseException; import tests.api.org.xml.sax.support.MethodLogger; import tests.api.org.xml.sax.support.MockHandler; import tests.api.org.xml.sax.support.MockResolver; +import tests.support.resource.Support_Resources; import tests.util.TestEnvironment; import javax.xml.parsers.DocumentBuilder; @@ -41,8 +42,6 @@ import javax.xml.parsers.DocumentBuilderFactory; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; @@ -272,7 +271,7 @@ public class DocumentBuilderTest extends TestCase { args = {java.io.File.class} ) public void testGetBaseURI() throws IOException, SAXException { - File f = resourceToTmpFile("/simple.xml"); + File f = Support_Resources.resourceToTempFile("/simple.xml"); Document d = db.parse(f); assertTrue(d.getDocumentElement().getBaseURI().startsWith("file://")); } @@ -291,7 +290,7 @@ public class DocumentBuilderTest extends TestCase { args = {java.io.File.class} ) public void test_parseLjava_io_File() throws IOException { - File f = resourceToTmpFile("/simple.xml"); + File f = Support_Resources.resourceToTempFile("/simple.xml"); // case 1: Trivial use. try { @@ -333,7 +332,7 @@ public class DocumentBuilderTest extends TestCase { } // case 4: Try to parse incorrect xml file - f = resourceToTmpFile("/wrong.xml"); + f = Support_Resources.resourceToTempFile("/wrong.xml"); try { db.parse(f); fail("Expected SAXException was not thrown"); @@ -344,22 +343,6 @@ public class DocumentBuilderTest extends TestCase { } } - private File resourceToTmpFile(String path) throws IOException, - FileNotFoundException { - File f = File.createTempFile("out", ".xml"); - f.deleteOnExit(); - FileOutputStream out = new FileOutputStream(f); - - InputStream xml = getClass().getResourceAsStream(path); - while (xml.available() > 0) { - out.write(xml.read()); - } - out.flush(); - out.close(); - xml.close(); - return f; - } - /** * @tests javax.xml.parsers.DocumentBuilder#parse(java.io.InputStream) * Case 1: Try to parse correct xml document. diff --git a/xml/src/test/java/tests/xml/AllTests.java b/xml/src/test/java/tests/xml/AllTests.java index 45ca18e..89da364 100644 --- a/xml/src/test/java/tests/xml/AllTests.java +++ b/xml/src/test/java/tests/xml/AllTests.java @@ -26,7 +26,7 @@ public class AllTests { suite.addTestSuite(SimpleParserTest.class); suite.addTestSuite(SimpleBuilderTest.class); - suite.addTestSuite(NodeTests.class); + suite.addTestSuite(NodeTest.class); //suite.addTest(tests.org.w3c.dom.AllTests.suite()); suite.addTest(tests.api.javax.xml.parsers.AllTests.suite()); diff --git a/xml/src/test/java/tests/xml/DomTest.java b/xml/src/test/java/tests/xml/DomTest.java new file mode 100644 index 0000000..d6031ed --- /dev/null +++ b/xml/src/test/java/tests/xml/DomTest.java @@ -0,0 +1,280 @@ +/* + * 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 tests.xml; + +import junit.framework.TestCase; +import org.w3c.dom.Attr; +import org.w3c.dom.CDATASection; +import org.w3c.dom.Comment; +import org.w3c.dom.Document; +import org.w3c.dom.DocumentType; +import org.w3c.dom.Element; +import org.w3c.dom.Entity; +import org.w3c.dom.Node; +import org.w3c.dom.ProcessingInstruction; +import org.w3c.dom.Text; +import org.xml.sax.InputSource; + +import javax.xml.parsers.DocumentBuilderFactory; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Construct a DOM and then interrogate it. + */ +public class DomTest extends TestCase { + + private final String xml + = "<!DOCTYPE menu [" + + " <!ENTITY sp \"Maple Syrup\">" + + "]>" + + "<menu>\n" + + " <item xmlns=\"http://food\" xmlns:a=\"http://addons\">\n" + + " <name a:standard=\"strawberry\" deluxe=\"&sp;\">Waffles</name>\n" + + " <description xmlns=\"http://marketing\">Belgian<![CDATA[ waffles & strawberries (< 5g ]]>of fat)</description>\n" + + " <a:option>Whipped Cream</a:option>\n" + + " <a:option>&sp;</a:option>\n" + + " <?wafflemaker square shape?>\n" + + " <nutrition>\n" + + " <a:vitamins xmlns:a=\"http://usda\">\n" + + " <!-- add other vitamins? --> \n" + + " <a:vitaminc>60%</a:vitaminc>\n" + + " </a:vitamins>\n" + + " </nutrition>\n" + + " </item>\n" + + "</menu>"; + + private Document document; + private DocumentType doctype; + private Entity sp; + private Element menu; + private Element item; + private Attr itemXmlns; + private Attr itemXmlnsA; + private Element name; + private Attr standard; + private Attr deluxe; + private Element description; + private Text descriptionText1; + private CDATASection descriptionText2; + private Text descriptionText3; + private Element option1; + private Element option2; + private Node option2Reference; // Text on RI, EntityReference on Dalvik + private ProcessingInstruction wafflemaker; + private Element nutrition; + private Element vitamins; + private Attr vitaminsXmlnsA; + private Comment comment; + private Element vitaminc; + private Text vitamincText; + + private List<Node> allNodes; + + @Override protected void setUp() throws Exception { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setNamespaceAware(true); + + document = factory.newDocumentBuilder() + .parse(new InputSource(new StringReader(xml))); + + // doctype nodes + doctype = document.getDoctype(); + if (doctype.getEntities() != null) { + sp = (Entity) doctype.getEntities().item(0); + } + + // document nodes + menu = document.getDocumentElement(); + item = (Element) menu.getChildNodes().item(1); + itemXmlns = item.getAttributeNode("xmlns"); + itemXmlnsA = item.getAttributeNode("xmlns:a"); + name = (Element) item.getChildNodes().item(1); + standard = name.getAttributeNode("a:standard"); + deluxe = name.getAttributeNode("deluxe"); + description = (Element) item.getChildNodes().item(3); + descriptionText1 = (Text) description.getChildNodes().item(0); + descriptionText2 = (CDATASection) description.getChildNodes().item(1); + descriptionText3 = (Text) description.getChildNodes().item(2); + option1 = (Element) item.getChildNodes().item(5); + option2 = (Element) item.getChildNodes().item(7); + option2Reference = option2.getChildNodes().item(0); + wafflemaker = (ProcessingInstruction) item.getChildNodes().item(9); + nutrition = (Element) item.getChildNodes().item(11); + vitamins = (Element) nutrition.getChildNodes().item(1); + vitaminsXmlnsA = vitamins.getAttributeNode("xmlns:a"); + comment = (Comment) vitamins.getChildNodes().item(1); + vitaminc = (Element) vitamins.getChildNodes().item(3); + vitamincText = (Text) vitaminc.getChildNodes().item(0); + + allNodes = new ArrayList<Node>(); + + if (sp != null) { + allNodes.add(sp); + } + + allNodes.addAll(Arrays.asList(document, doctype, menu, item, itemXmlns, + itemXmlnsA, name, standard, deluxe, description, + descriptionText1, descriptionText2, descriptionText3, option1, + option2, option2Reference, wafflemaker, nutrition, vitamins, + vitaminsXmlnsA, comment, vitaminc, vitamincText)); + } + + /** + * Android's parsed DOM doesn't include entity declarations. These nodes will + * only be tested for implementations that support them. + */ + public void testEntityDeclarations() { + assertNotNull("This implementation does not parse entity declarations", sp); + } + + public void testLookupNamespaceURIByPrefix() { + assertEquals(null, doctype.lookupNamespaceURI("a")); + if (sp != null) { + assertEquals(null, sp.lookupNamespaceURI("a")); + } + assertEquals(null, document.lookupNamespaceURI("a")); + assertEquals(null, menu.lookupNamespaceURI("a")); + assertEquals("http://addons", item.lookupNamespaceURI("a")); + assertEquals("http://addons", itemXmlns.lookupNamespaceURI("a")); + assertEquals("http://addons", itemXmlnsA.lookupNamespaceURI("a")); + assertEquals("http://addons", name.lookupNamespaceURI("a")); + assertEquals("http://addons", standard.lookupNamespaceURI("a")); + assertEquals("http://addons", deluxe.lookupNamespaceURI("a")); + assertEquals("http://addons", description.lookupNamespaceURI("a")); + assertEquals("http://addons", descriptionText1.lookupNamespaceURI("a")); + assertEquals("http://addons", descriptionText2.lookupNamespaceURI("a")); + assertEquals("http://addons", descriptionText3.lookupNamespaceURI("a")); + assertEquals("http://addons", option1.lookupNamespaceURI("a")); + assertEquals("http://addons", option2.lookupNamespaceURI("a")); + assertEquals("http://addons", option2Reference.lookupNamespaceURI("a")); + assertEquals("http://addons", wafflemaker.lookupNamespaceURI("a")); + assertEquals("http://addons", nutrition.lookupNamespaceURI("a")); + assertEquals("http://usda", vitamins.lookupNamespaceURI("a")); + assertEquals("http://usda", vitaminsXmlnsA.lookupNamespaceURI("a")); + assertEquals("http://usda", comment.lookupNamespaceURI("a")); + assertEquals("http://usda", vitaminc.lookupNamespaceURI("a")); + assertEquals("http://usda", vitamincText.lookupNamespaceURI("a")); + } + + public void testLookupNamespaceURIWithNullPrefix() { + assertEquals(null, document.lookupNamespaceURI(null)); + assertEquals(null, doctype.lookupNamespaceURI(null)); + if (sp != null) { + assertEquals(null, sp.lookupNamespaceURI(null)); + } + assertEquals(null, menu.lookupNamespaceURI(null)); + assertEquals("http://food", item.lookupNamespaceURI(null)); + assertEquals("http://food", itemXmlns.lookupNamespaceURI(null)); + assertEquals("http://food", itemXmlnsA.lookupNamespaceURI(null)); + assertEquals("http://food", name.lookupNamespaceURI(null)); + assertEquals("http://food", standard.lookupNamespaceURI(null)); + assertEquals("http://food", deluxe.lookupNamespaceURI(null)); + assertEquals("http://marketing", description.lookupNamespaceURI(null)); + assertEquals("http://marketing", descriptionText1.lookupNamespaceURI(null)); + assertEquals("http://marketing", descriptionText2.lookupNamespaceURI(null)); + assertEquals("http://marketing", descriptionText3.lookupNamespaceURI(null)); + assertEquals("http://food", option1.lookupNamespaceURI(null)); + assertEquals("http://food", option2.lookupNamespaceURI(null)); + assertEquals("http://food", option2Reference.lookupNamespaceURI(null)); + assertEquals("http://food", wafflemaker.lookupNamespaceURI(null)); + assertEquals("http://food", nutrition.lookupNamespaceURI(null)); + assertEquals("http://food", vitamins.lookupNamespaceURI(null)); + assertEquals("http://food", vitaminsXmlnsA.lookupNamespaceURI(null)); + assertEquals("http://food", comment.lookupNamespaceURI(null)); + assertEquals("http://food", vitaminc.lookupNamespaceURI(null)); + assertEquals("http://food", vitamincText.lookupNamespaceURI(null)); + } + + public void testLookupNamespaceURIWithXmlnsPrefix() { + for (Node node : allNodes) { + assertEquals(null, node.lookupNamespaceURI("xmlns")); + } + } + + public void testLookupPrefixWithShadowedUri() { + assertEquals(null, document.lookupPrefix("http://addons")); + assertEquals(null, doctype.lookupPrefix("http://addons")); + if (sp != null) { + assertEquals(null, sp.lookupPrefix("http://addons")); + } + assertEquals(null, menu.lookupPrefix("http://addons")); + assertEquals("a", item.lookupPrefix("http://addons")); + assertEquals("a", itemXmlns.lookupPrefix("http://addons")); + assertEquals("a", itemXmlnsA.lookupPrefix("http://addons")); + assertEquals("a", name.lookupPrefix("http://addons")); + assertEquals("a", standard.lookupPrefix("http://addons")); + assertEquals("a", deluxe.lookupPrefix("http://addons")); + assertEquals("a", description.lookupPrefix("http://addons")); + assertEquals("a", descriptionText1.lookupPrefix("http://addons")); + assertEquals("a", descriptionText2.lookupPrefix("http://addons")); + assertEquals("a", descriptionText3.lookupPrefix("http://addons")); + assertEquals("a", option1.lookupPrefix("http://addons")); + assertEquals("a", option2.lookupPrefix("http://addons")); + assertEquals("a", option2Reference.lookupPrefix("http://addons")); + assertEquals("a", wafflemaker.lookupPrefix("http://addons")); + assertEquals("a", nutrition.lookupPrefix("http://addons")); + assertEquals(null, vitamins.lookupPrefix("http://addons")); + assertEquals(null, vitaminsXmlnsA.lookupPrefix("http://addons")); + assertEquals(null, comment.lookupPrefix("http://addons")); + assertEquals(null, vitaminc.lookupPrefix("http://addons")); + assertEquals(null, vitamincText.lookupPrefix("http://addons")); + } + + public void testLookupPrefixWithUnusedUri() { + for (Node node : allNodes) { + assertEquals(null, node.lookupPrefix("http://unused")); + } + } + + public void testLookupPrefixWithNullUri() { + for (Node node : allNodes) { + assertEquals(null, node.lookupPrefix(null)); + } + } + + public void testLookupPrefixWithShadowingUri() { + assertEquals(null, document.lookupPrefix("http://usda")); + assertEquals(null, doctype.lookupPrefix("http://usda")); + if (sp != null) { + assertEquals(null, sp.lookupPrefix("http://usda")); + } + assertEquals(null, menu.lookupPrefix("http://usda")); + assertEquals(null, item.lookupPrefix("http://usda")); + assertEquals(null, itemXmlns.lookupPrefix("http://usda")); + assertEquals(null, itemXmlnsA.lookupPrefix("http://usda")); + assertEquals(null, name.lookupPrefix("http://usda")); + assertEquals(null, standard.lookupPrefix("http://usda")); + assertEquals(null, deluxe.lookupPrefix("http://usda")); + assertEquals(null, description.lookupPrefix("http://usda")); + assertEquals(null, descriptionText1.lookupPrefix("http://usda")); + assertEquals(null, descriptionText2.lookupPrefix("http://usda")); + assertEquals(null, descriptionText3.lookupPrefix("http://usda")); + assertEquals(null, option1.lookupPrefix("http://usda")); + assertEquals(null, option2.lookupPrefix("http://usda")); + assertEquals(null, option2Reference.lookupPrefix("http://usda")); + assertEquals(null, wafflemaker.lookupPrefix("http://usda")); + assertEquals(null, nutrition.lookupPrefix("http://usda")); + assertEquals("a", vitamins.lookupPrefix("http://usda")); + assertEquals("a", vitaminsXmlnsA.lookupPrefix("http://usda")); + assertEquals("a", comment.lookupPrefix("http://usda")); + assertEquals("a", vitaminc.lookupPrefix("http://usda")); + assertEquals("a", vitamincText.lookupPrefix("http://usda")); + } +} diff --git a/xml/src/test/java/tests/xml/NodeTest.java b/xml/src/test/java/tests/xml/NodeTest.java new file mode 100644 index 0000000..dc3a333 --- /dev/null +++ b/xml/src/test/java/tests/xml/NodeTest.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2009 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 tests.xml; + +import dalvik.annotation.TestTargetClass; +import junit.framework.TestCase; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import tests.support.resource.Support_Resources; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +@TestTargetClass(Node.class) +public class NodeTest extends TestCase { + + /** + * For bug 779: Node#getNextSibling throws IndexOutOfBoundsException. + */ + public void test_getNextSibling() throws Exception { + // Calling getNextSibling when there is no next sibling should return null. + // From http://code.google.com/p/android/issues/detail?id=779. + ByteArrayInputStream bis = new ByteArrayInputStream("<root/>".getBytes()); + Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(bis); + Node root = document.getDocumentElement(); + assertNull(root.getNextSibling()); + } + + public void testGetBaseUri() throws Exception { + DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + File file = Support_Resources.resourceToTempFile("/simple.xml"); + Document document = builder.parse(file); + + String baseUri = "file:" + file.getPath(); + assertEquals(baseUri, document.getBaseURI()); + + Element documentElement = document.getDocumentElement(); + for (Node node : flattenSubtree(documentElement)) { + if (node.getNodeType() == Node.ELEMENT_NODE + || node.getNodeType() == Node.DOCUMENT_NODE) { + assertEquals("Unexpected base URI for " + node, baseUri, node.getBaseURI()); + } else { + assertNull("Unexpected base URI for " + node, node.getBaseURI()); + } + } + + // TODO: test other node types + // TODO: test resolution of relative paths + // TODO: test URI santization + } + + private List<Node> flattenSubtree(Node subtree) { + List<Node> result = new ArrayList<Node>(); + traverse(subtree, result); + return result; + } + + private void traverse(Node node, List<Node> sink) { + sink.add(node); + + NodeList children = node.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + traverse(children.item(i), sink); + } + } +} diff --git a/xml/src/test/java/tests/xml/NodeTests.java b/xml/src/test/java/tests/xml/NodeTests.java deleted file mode 100644 index e46e216..0000000 --- a/xml/src/test/java/tests/xml/NodeTests.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2009 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 tests.xml; - -import dalvik.annotation.TestLevel; -import dalvik.annotation.TestTargetNew; -import dalvik.annotation.TestTargetClass; - -import junit.framework.TestCase; - -import org.w3c.dom.Document; -import org.w3c.dom.Node; - -import java.io.ByteArrayInputStream; -import javax.xml.parsers.DocumentBuilderFactory; - -@TestTargetClass(Node.class) -public class NodeTests extends TestCase { - @TestTargetNew( - level = TestLevel.PARTIAL, - notes = "Issue #779: org.w3c.dom.Node#getNextSibling throws IndexOutOfBoundsException.", - method = "getNextSibling", - args = {} - ) - public void test_getNextSibling() throws Exception { - // Calling getNextSibling when there is no next sibling should return null. - // From http://code.google.com/p/android/issues/detail?id=779. - ByteArrayInputStream bis = new ByteArrayInputStream("<root/>".getBytes()); - Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(bis); - Node root = document.getDocumentElement(); - assertNull(root.getNextSibling()); - } -} |