blob: f349dd3101d34b297faa4b3775e389f2a40e1968 [file] [log] [blame]
/*
* Copyright 2008 Google Inc.
*
* 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 com.google.gwt.xml.client;
import com.google.gwt.junit.DoNotRunWith;
import com.google.gwt.junit.Platform;
import com.google.gwt.junit.client.GWTTestCase;
import com.google.gwt.xml.client.impl.DOMParseException;
import com.google.gwt.xml.client.impl.XMLParserImplSafari;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
/**
* This class poorly tests all the methods in the GWT XML parser.
*/
public class XMLTest extends GWTTestCase {
private static List<Node> asList(Node[] nodes) {
return Arrays.asList(nodes);
}
private static void assertAttributeMapEquals(NamedNodeMap listA,
NamedNodeMap listB) {
// This is only for checking attribute maps.
assertEquals(listA.getLength(), listB.getLength());
for (int i = 0, n = listA.getLength(); i < n; ++i) {
final Node itemA = listA.item(i);
final Node itemB = listB.getNamedItem(itemA.getNodeName());
assertNotNull(itemB);
assertEquals(itemA.getNodeType(), itemB.getNodeType());
assertEquals(itemA.getNodeValue(), itemB.getNodeValue());
}
}
private static void assertCharacterDataEquals(CharacterData charDataA,
CharacterData charDataB) {
assertEquals(charDataA.getData(), charDataB.getData());
}
private static void assertDocumentEquals(Document docA, Document docB) {
assertNodeListEquals(docA.getChildNodes(), docB.getChildNodes());
}
private static void assertElementEquals(Element elemA, Element elemB) {
assertEquals(elemA.getNodeName(), elemB.getNodeName());
assertAttributeMapEquals(elemA.getAttributes(), elemB.getAttributes());
assertNodeListEquals(elemA.getChildNodes(), elemB.getChildNodes());
}
private static void assertNodeEquals(Node nodeA, Node nodeB) {
assertNotNull(nodeA);
assertNotNull(nodeB);
final int typeA = nodeA.getNodeType();
final int typeB = nodeB.getNodeType();
assertEquals(typeA, typeB);
switch (typeA) {
case Node.ELEMENT_NODE:
assertElementEquals((Element) nodeA, (Element) nodeB);
break;
case Node.COMMENT_NODE:
case Node.CDATA_SECTION_NODE:
case Node.TEXT_NODE:
assertCharacterDataEquals((CharacterData) nodeA, (CharacterData) nodeB);
break;
case Node.PROCESSING_INSTRUCTION_NODE:
assertProcessingInstructionEquals((ProcessingInstruction) nodeA,
(ProcessingInstruction) nodeB);
break;
default:
fail("Unexpected node type: " + nodeA.toString());
break;
}
}
private static void assertNodeListEquals(NodeList listA, NodeList listB) {
final int sizeA = listA.getLength();
final int sizeB = listB.getLength();
assertEquals(sizeA, sizeB);
for (int i = 0, n = sizeA; i < n; ++i) {
assertNodeEquals(listA.item(i), listB.item(i));
}
}
private static void assertProcessingInstructionEquals(
ProcessingInstruction piA, ProcessingInstruction piB) {
assertEquals(piA.getData(), piB.getData());
}
private static Document createTestDocument() {
Document d = XMLParser.createDocument();
Element top = d.createElement("doc");
top.setAttribute("fluffy", "true");
top.setAttribute("numAttributes", "2");
d.appendChild(top);
ProcessingInstruction commentBefore = d.createProcessingInstruction(
"target", "some data");
d.insertBefore(commentBefore, top);
Comment commentAfter = d.createComment("after the element");
d.insertBefore(commentAfter, null);
for (int i = 0; i < 3; i++) {
Element e = d.createElement("e" + i);
e.setAttribute("id", "e" + i + "Id");
top.appendChild(e);
}
Element deep = d.createElement("deep");
top.getFirstChild().appendChild(deep);
deep.setAttribute("depth", "1 foot");
Element deep2 = d.createElement("deep");
deep2.setAttribute("depth", "2 feet");
top.getFirstChild().getFirstChild().appendChild(deep2);
top.appendChild(d.createTextNode("0123456789"));
top.appendChild(d.createTextNode("abcdefghij"));
top.appendChild(d.createElement("e4"));
top.appendChild(d.createCDATASection("klmnopqrst"));
return d;
}
/**
* Returns the module name for GWT unit test running.
*/
@Override
public String getModuleName() {
return "com.google.gwt.xml.XML";
}
public void testAttr() {
Document d = createTestDocument();
Element de = d.getDocumentElement();
de.setAttribute("created", "true");
assertEquals("true", de.getAttribute("created"));
de.setAttribute("set", "toAValue");
assertEquals("toAValue", de.getAttribute("set"));
assertTrue(de.getAttributeNode("set").getSpecified());
assertEquals(de.getAttributeNode("unset"), null);
}
public void testCreate() {
Document d = XMLParser.createDocument();
CDATASection createCDATA = d.createCDATASection("sampl<<< >>e data");
Comment createComment = d.createComment("a sample comment");
DocumentFragment createDocumentFragment = d.createDocumentFragment();
Element elementWithChildren = d.createElement("elementWithChildren");
ProcessingInstruction createProcessingInstruction = d.createProcessingInstruction(
"target", "processing instruction data");
Text createTextNode = d.createTextNode("sample text node");
List<Node> canHaveChildren = asList(new Node[] {
createDocumentFragment, elementWithChildren});
List<Node> canBeChildren = asList(new Node[] {
createCDATA, createComment, elementWithChildren,
createProcessingInstruction, createTextNode});
for (int i = 0; i < canHaveChildren.size(); i++) {
Node parent = canHaveChildren.get(i);
Node cloneParent = parent.cloneNode(false);
if (canBeChildren.contains(parent)) {
d.appendChild(cloneParent);
}
for (int j = 0; j < canBeChildren.size(); j++) {
Node child = canBeChildren.get(j);
cloneParent.appendChild(child.cloneNode(false));
}
for (int j = 0; j < canBeChildren.size(); j++) {
Node clonedChild = cloneParent.getChildNodes().item(j);
Node hopefullySameChild = canBeChildren.get(j);
assertEquals(hopefullySameChild.cloneNode(false).toString(),
clonedChild.toString());
}
Node deepClonedNode = parent.cloneNode(true);
assertEquals(parent.toString(), deepClonedNode.toString());
}
// Now check the document.
XMLParser.removeWhitespace(d);
assertDocumentEquals(XMLParser.parse("<elementWithChildren>"
+ "<![CDATA[sampl<<< >>e data]]>" + "<!--a sample comment-->"
+ "<elementWithChildren/>" + "<?target processing instruction data?>"
+ "sample text node" + "</elementWithChildren>"), d);
}
public void testDocument() {
Document d = createTestDocument();
NodeList e1Nodes = d.getElementsByTagName("e1");
assertEquals(1, e1Nodes.getLength());
Node e1Node = e1Nodes.item(0);
assertEquals("e1", ((Element) e1Node).getTagName());
// It used to be that XML nodes without a DTD would never be returned by getElementById().
// In DOM 4, an Element's "id" attribute is always used as its id. [1]
// This seems to be the behavior starting with Chrome 11 and Firefox 32.
// [1] http://www.w3.org/TR/dom/#concept-id
Element e1NodeDirect = d.getElementById("e1Id");
// Allow both the old and new behavior.
if (e1NodeDirect != null) {
// Check toString() first for a better error message.
assertEquals("getElementId returned unexpected element for XML node",
e1Node.toString(), e1NodeDirect.toString());
// Not the same for Firefox 32. TODO: investigate.
// assertSame("getElementId returned unexpected element for XML node",
// e1Node, e1NodeDirect);
}
Document alienDoc = XMLParser.createDocument();
Node alienNode11 = alienDoc.importNode(e1Node, true);
alienDoc.appendChild(alienNode11);
assertNotSame(e1Node, alienNode11);
assertEquals(e1Node.toString(), alienNode11.toString());
}
public void testElement() {
Document d = createTestDocument();
Element top = d.getDocumentElement();
NodeList el = top.getElementsByTagName("e1");
assertEquals(1, el.getLength());
NodeList deepNodes = top.getElementsByTagName("deep");
assertEquals(2, deepNodes.getLength());
Element d1 = (Element) deepNodes.item(0);
assertTrue(d1.hasAttribute("depth"));
assertFalse(d1.hasAttribute("height"));
d1.removeAttribute("depth");
assertFalse(d1.hasAttribute("depth"));
Element d2 = (Element) deepNodes.item(1);
assertTrue(d2.hasAttribute("depth"));
Attr depthAttr = d2.getAttributeNode("depth");
assertNotNull(depthAttr);
d2.removeAttribute("depth");
assertFalse(d2.hasAttribute("depth"));
}
public void testForIssue733() {
// TODO (knorton):
// http://code.google.com/p/google-web-toolkit/issues/detail?id=2346
// Fixing issue #733 has been deferred for Safari2. See the bug URL for more
// details. This should be enabled as soon as that bug is fixed.
if (XMLParserImplSafari.isSafari2LevelWebKit()) {
return;
}
final Document document = XMLParser.createDocument();
final Element element = document.createElement("foo");
document.appendChild(element);
element.setAttribute("bar", "<");
final String xmlAsString = document.toString();
try {
XMLParser.parse(xmlAsString);
} catch (DOMParseException e) {
fail(xmlAsString + " is invalid XML.");
}
}
public void testNamedNodeMap() {
Document d = createTestDocument();
NamedNodeMap m = d.getDocumentElement().getAttributes();
assertEquals("true", ((Attr) m.getNamedItem("fluffy")).getValue());
assertEquals(2, m.getLength());
}
public void testNavigation() {
Document d = createTestDocument();
Element documentElement = d.getDocumentElement();
assertEquals("getPreviousSibling", documentElement.getPreviousSibling(),
d.getChildNodes().item(0));
assertEquals("getNextSibling", documentElement.getNextSibling(),
d.getChildNodes().item(2));
assertEquals("getDocumentElement", documentElement, d.getChildNodes().item(
1));
assertEquals("getTagName", "doc", documentElement.getTagName());
NodeList documentElementChildNodes = documentElement.getChildNodes();
int deChildNodesLength = documentElementChildNodes.getLength();
assertEquals("getFirstChild", documentElement.getFirstChild(),
documentElementChildNodes.item(0));
assertEquals("getLastChild", documentElement.getLastChild(),
documentElementChildNodes.item(deChildNodesLength - 1));
assertEquals("getNextSibling2",
documentElement.getFirstChild().getNextSibling(),
documentElementChildNodes.item(1));
assertEquals("getPreviousSibling2",
documentElement.getLastChild().getPreviousSibling(),
documentElementChildNodes.item(deChildNodesLength - 2));
}
public void testNode() {
Document ns = XMLParser.parse("<x:doc xmlns:x=\"http://x\"/>");
String xUrl = "http://x";
assertEquals(xUrl, ns.getFirstChild().getNamespaceURI());
Element top = ns.getDocumentElement();
Text xxx = ns.createTextNode("xxx");
top.appendChild(xxx);
Text yyy = ns.createTextNode("yyy");
top.appendChild(yyy);
assertEquals("xxx", xxx.getNodeValue());
assertEquals(xxx.getParentNode(), top);
xxx.setNodeValue("x");
assertEquals("x", xxx.getData());
assertEquals(xxx.getOwnerDocument(), ns);
top.removeChild(xxx);
assertEquals(1, top.getChildNodes().getLength());
Comment commentNode = ns.createComment("comment ccc");
top.replaceChild(commentNode, yyy);
assertEquals(top.getFirstChild(), commentNode);
assertEquals(1, top.getChildNodes().getLength());
}
/**
* At one point, this test was failing on one Safari configuration in
* Production Mode in the 1.5 release branch.
*/
@DoNotRunWith({Platform.HtmlUnitUnknown})
public void testParse() {
Document docA = XMLParser.parse("<!--hello--> <a spam=\"ham\">\n <?pi hello ?>dfgdfg <b/>\t</a>");
Document docB = XMLParser.createDocument();
docB.appendChild(docB.createComment("hello"));
final Element eleB = docB.createElement("a");
docB.appendChild(eleB);
eleB.setAttribute("spam", "ham");
eleB.appendChild(docB.createTextNode("\n "));
eleB.appendChild(docB.createProcessingInstruction("pi", "hello "));
eleB.appendChild(docB.createTextNode("dfgdfg "));
eleB.appendChild(docB.createElement("b"));
eleB.appendChild(docB.createTextNode("\t"));
assertDocumentEquals(docA, docB);
try {
XMLParser.parse("<<<");
fail();
} catch (DOMParseException e) {
}
}
public void testPrefix() {
Document d = XMLParser.parse("<?xml version=\"1.0\"?>\r\n"
+ "<!-- both namespace prefixes are available throughout -->\r\n"
+ "<bk:book xmlns:bk=\'urn:loc.gov:books\'\r\n"
+ " xmlns:isbn=\'urn:ISBN:0-395-36341-6\'>\r\n"
+ " <bk:title>Cheaper by the Dozen</bk:title>\r\n"
+ " <isbn:number>1568491379</isbn:number>\r\n" + "</bk:book>");
assertEquals("bk:book", d.getDocumentElement().getNodeName());
assertEquals("bk", d.getDocumentElement().getPrefix());
assertEquals(1, d.getElementsByTagName("book").getLength());
assertEquals(d.getElementsByTagName("book").item(0), d.getDocumentElement());
}
public void testProcessingInstruction() {
Document d = createTestDocument();
ProcessingInstruction pi = (ProcessingInstruction) d.getChildNodes().item(0);
assertEquals("target", pi.getTarget());
assertEquals("some data", pi.getData());
pi.setData("other data");
assertEquals("other data", pi.getData());
}
public void testText() {
Document d = createTestDocument();
List<Node> textLikeNodes = Arrays.asList(new Node[] {
d.createTextNode(""), d.createCDATASection(""), d.createComment("")});
StringBuffer b = new StringBuffer();
for (char i = 32; i < 30000; i++) {
b.append(i);
}
for (Iterator<Node> iter = textLikeNodes.iterator(); iter.hasNext();) {
CharacterData textLike = (CharacterData) iter.next();
textLike.setData(b.toString());
// CHECKSTYLE_OFF
assertEquals("initialLength type:" + textLike.getNodeType(), 30000 - 32,
textLike.getLength());
assertEquals("initialEquals", textLike.getData(), b.toString());
// CHECKSTYLE_ON
}
for (int i = 32; i < 29900; i += 100) {
for (Iterator<Node> iter = textLikeNodes.iterator(); iter.hasNext();) {
CharacterData textLike = (CharacterData) iter.next();
// CHECKSTYLE_OFF
assertEquals("substring type:" + textLike.getNodeType() + " count: "
+ i, b.substring(i, i + 100), textLike.substringData(i, 100));
// CHECKSTYLE_ON
}
}
for (Iterator<Node> iter = textLikeNodes.iterator(); iter.hasNext();) {
StringBuffer bTemp = new StringBuffer(b.toString());
CharacterData textLike = (CharacterData) iter.next();
textLike.deleteData(100, 100);
bTemp.delete(100, 200);
// CHECKSTYLE_OFF
assertEquals("deleteLength type:" + textLike.getNodeType(),
bTemp.length(), textLike.getData().length());
assertEquals("deleteEquals type:" + textLike.getNodeType(),
bTemp.toString(), textLike.getData());
// CHECKSTYLE_ON
bTemp.setLength(0);
}
for (Iterator<Node> iter = textLikeNodes.iterator(); iter.hasNext();) {
StringBuffer bTemp = new StringBuffer(b.toString());
CharacterData textLike = (CharacterData) iter.next();
textLike.setData(bTemp.toString());
textLike.replaceData(50, 100, " ");
bTemp.replace(50, 150, " ");
// CHECKSTYLE_OFF
assertEquals("replaceLength type:" + textLike.getNodeType(),
bTemp.length(), textLike.getData().length());
assertEquals("replaceEquals type:" + textLike.getNodeType(),
bTemp.toString(), textLike.getData());
// CHECKSTYLE_ON
bTemp.setLength(0);
}
for (Iterator<Node> iter = textLikeNodes.iterator(); iter.hasNext();) {
CharacterData textLike = (CharacterData) iter.next();
textLike.appendData("!!!");
assertTrue("endswith!!!", textLike.getData().endsWith("!!!"));
textLike.insertData(0, "!");
textLike.insertData(1, "@@");
assertTrue("startsWith !@@", textLike.getData().startsWith("!@@"));
}
Text t = (Text) d.getDocumentElement().getChildNodes().item(3);
Text rightT = t.splitText(5);
assertEquals("t and leftT parent equality", t.getParentNode(),
rightT.getParentNode());
assertEquals("leftT.getPreviousSibling", rightT.getPreviousSibling(), t);
assertEquals("t.length", 5, t.getData().length());
assertEquals("leftT.length", 5, rightT.getData().length());
assertEquals("t data", "01234", t.getData());
assertEquals("LeftT data", "56789", rightT.getData());
CDATASection cd = (CDATASection) d.getDocumentElement().getChildNodes().item(
7);
Text rightCD = cd.splitText(5);
assertEquals("cd and leftCd parent equality", cd.getParentNode(),
rightCD.getParentNode());
assertEquals("leftCD.getPreviousSibling", rightCD.getPreviousSibling(), cd);
assertEquals("cd length", 5, cd.getData().length());
assertEquals("leftCD.length", 5, rightCD.getData().length());
assertEquals("cd data", "klmno", cd.getData());
assertEquals("leftCD data", "pqrst", rightCD.getData());
d.getDocumentElement().normalize();
assertEquals(
"normalized t",
"0123456789abcdefghij",
d.getDocumentElement().getChildNodes().item(3).toString());
}
}