############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # 1. Redistributions in source code must retain the above copyright # notice, this list of conditions, and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions, and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # 3. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY # EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # # This software consists of contributions made by Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## from Base import * import string import xml.dom from xml.dom import Node # --- DOMImplementation class DOMImplementationReadTestCase(TestCaseBase): def setUp(self): # self.implementation is already set. pass # Combinations to feed to the hasFeature method; some of these will always # return false, of course. # ('Core', '1.0') was never defined for DOM level 1, it was implicit. Most # DOM level 2 implementations return true, but this is a courtesy. featureMatrix = ( ('Core', None), #('Core', '1.0'), ('Core', '2.0'), ('Core', '3.0'), ('XML', None), ('XML', '1.0'), ('XML', '2.0'), ('XML', '3.0'), ('Traversal', None), ('Traversal', '1.0'), ('Traversal', '2.0'), ('Traversal', '3.0'), ('BogusFeature', None), ('BogusFeature', '1.0'), ('BogusFeature', '2.0'), ('BogusFeature', '3.0'), ) def checkHasFeature(self): impl = self.implementation for feature, level in self.featureMatrix: result1 = impl.hasFeature(feature, level) result2 = impl.hasFeature(string.upper(feature), level) result3 = impl.hasFeature(string.lower(feature), level) expect = ((feature, level) in self.supportedFeatures) self.assertEqual( result1, result2, "Different results from different case feature string.") self.assertEqual( result1, result3, "Different results from different case feature string.") self.assertEqual( (result1 and 1 or 0), expect, "Test for %s, version %s should have returned %s, " "returned %s" % (repr(feature), repr(level), repr(expect), repr(result1))) # --- Node class NodeReadTestCaseBase(TestCaseBase): nodeTypes = ( 'ATTRIBUTE_NODE', 'CDATA_SECTION_NODE', 'COMMENT_NODE', 'DOCUMENT_FRAGMENT_NODE', 'DOCUMENT_NODE', 'DOCUMENT_TYPE_NODE', 'ELEMENT_NODE', 'ENTITY_NODE', 'ENTITY_REFERENCE_NODE', 'NOTATION_NODE', 'PROCESSING_INSTRUCTION_NODE', 'TEXT_NODE', ) def checkNodeTypeConstants(self): for type in self.nodeTypes: checkAttribute(self.node, type, getattr(Node, type)) def checkAttributes(self): if self.node.nodeType == Node.ELEMENT_NODE: checkLength(self.node.attributes, 0) else: checkAttribute(self.node, 'attributes', None) checkReadOnly(self.node, 'attributes') def checkChildNodes(self): if self.node.nodeType in (Node.ATTRIBUTE_NODE, Node.DOCUMENT_NODE, Node.ENTITY_NODE): expectedLength = 1 else: expectedLength = 0 checkLength(self.node.childNodes, expectedLength) checkReadOnly(self.node, 'childNodes') def checkFirstChild(self): # The following node types are expected to have one childNode. if self.node.nodeType not in (Node.ATTRIBUTE_NODE, Node.DOCUMENT_NODE, Node.ENTITY_NODE): expected = None else: expected = self.node.childNodes[0] checkAttributeSameNode(self.node, 'firstChild', expected) checkReadOnly(self.node, 'firstChild') if expected: checkAttributeSameNode(self.node.firstChild, 'parentNode', self.node) def checkLastChild(self): # The following node types are expected to have one childNode. if self.node.nodeType not in (Node.ATTRIBUTE_NODE, Node.DOCUMENT_NODE, Node.ENTITY_NODE): expected = None else: expected = self.node.childNodes[0] checkAttributeSameNode(self.node, 'lastChild', expected) checkReadOnly(self.node, 'lastChild') if expected: checkAttributeSameNode(self.node.lastChild, 'parentNode', self.node) def checkNextSibling(self): checkAttribute(self.node, 'nextSibling', None) checkReadOnly(self.node, 'nextSibling') nodeNameMap = { Node.CDATA_SECTION_NODE: '#cdata-section', Node.COMMENT_NODE: '#comment', Node.DOCUMENT_NODE: '#document', Node.DOCUMENT_FRAGMENT_NODE: '#document-fragment', Node.TEXT_NODE: '#text', } def checkNodeName(self): if self.node.nodeType in (Node.ATTRIBUTE_NODE, Node.DOCUMENT_TYPE_NODE): expected = self.node.name elif self.node.nodeType == Node.ELEMENT_NODE: expected = self.node.tagName elif self.node.nodeType in (Node.ENTITY_NODE, Node.ENTITY_REFERENCE_NODE, Node.NOTATION_NODE): expected = self.expectedNodeName elif self.node.nodeType == Node.PROCESSING_INSTRUCTION_NODE: expected = self.node.target else: expected = self.nodeNameMap[self.node.nodeType] checkAttribute(self.node, 'nodeName', expected) checkReadOnly(self.node, "nodeName") def checkNodeType(self): checkAttribute(self.node, 'nodeType', self.expectedType) checkReadOnly(self.node, "nodeType") emptyNodeValueList = ( Node.DOCUMENT_FRAGMENT_NODE, Node.DOCUMENT_NODE, Node.DOCUMENT_TYPE_NODE, Node.ELEMENT_NODE, Node.ENTITY_NODE, Node.ENTITY_REFERENCE_NODE, Node.NOTATION_NODE, ) def checkNodeValue(self): if self.node.nodeType in self.emptyNodeValueList: expected = None elif self.node.nodeType in (Node.CDATA_SECTION_NODE, Node.COMMENT_NODE, Node.TEXT_NODE, Node.PROCESSING_INSTRUCTION_NODE): expected = self.node.data elif self.node.nodeType == Node.ATTRIBUTE_NODE: expected = self.node.value checkAttribute(self.node, 'nodeValue', expected) def checkParentNode(self): checkAttribute(self.node, 'parentNode', None) checkReadOnly(self.node, 'parentNode') def checkPreviousSibling(self): checkAttribute(self.node, 'previousSibling', None) checkReadOnly(self.node, 'previousSibling') def hasChildNodes(self): if self.node.nodeType in (Node.ATTRIBUTE_NODE, Node.DOCUMENT_NODE, Node.ENTITY_NODE): expectTrue = 1 else: expectTrue = 0 if expectTrue: self.failUnless( self.node.hasChildNodes(), "hasChildNodes returned 'false' when 'true' was expected.") else: self.failIf( self.node.hasChildNodes(), "hasChildNodes returned 'true' when 'false' was expected.") class NodeWriteTestCaseBase(TestCaseBase): TEST_NAME = 'somename' emptyNodeValueList = NodeReadTestCaseBase.emptyNodeValueList readOnlyNodeList = ( Node.ENTITY_NODE, Node.ENTITY_REFERENCE_NODE, Node.NOTATION_NODE, ) def checkNodeValue(self): # Nodetypes that are read-only. if self.node.nodeType in self.readOnlyNodeList: checkReadOnly(self.node, 'nodeValue') return # Nodetypes that should ignore changes. if self.node.nodeType in self.emptyNodeValueList: self.node.nodeValue = "Ignore this." checkAttribute(self.node, "nodeValue", None) return # Nodetypes where nodeValue is an alias. if self.node.nodeType in (Node.CDATA_SECTION_NODE, Node.COMMENT_NODE, Node.TEXT_NODE, Node.PROCESSING_INSTRUCTION_NODE): alias = 'data' elif self.node.nodeType == Node.ATTRIBUTE_NODE: alias = 'value' self.node.nodeValue = 'foo' checkAttribute(self.node, 'nodeValue', 'foo') checkAttribute(self.node, alias, 'foo') allowedChildrenMap = { Node.DOCUMENT_NODE: ( Node.ELEMENT_NODE, # Maximum of one, special case Node.PROCESSING_INSTRUCTION_NODE, Node.COMMENT_NODE, Node.DOCUMENT_TYPE_NODE, # Maximum of one, special case ), Node.DOCUMENT_FRAGMENT_NODE: ( Node.ELEMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE, Node.COMMENT_NODE, Node.TEXT_NODE, Node.CDATA_SECTION_NODE, Node.ENTITY_REFERENCE_NODE, ), Node.DOCUMENT_TYPE_NODE: (), Node.ENTITY_REFERENCE_NODE: ( Node.ELEMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE, Node.COMMENT_NODE, Node.TEXT_NODE, Node.CDATA_SECTION_NODE, Node.ENTITY_REFERENCE_NODE, ), Node.ELEMENT_NODE: ( Node.ELEMENT_NODE, Node.TEXT_NODE, Node.COMMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE, Node.CDATA_SECTION_NODE, Node.ENTITY_REFERENCE_NODE, ), Node.ATTRIBUTE_NODE: ( Node.TEXT_NODE, Node.ENTITY_REFERENCE_NODE, ), Node.PROCESSING_INSTRUCTION_NODE: (), Node.COMMENT_NODE: (), Node.TEXT_NODE: (), Node.CDATA_SECTION_NODE: (), Node.ENTITY_NODE: ( Node.ELEMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE, Node.COMMENT_NODE, Node.TEXT_NODE, Node.CDATA_SECTION_NODE, Node.ENTITY_REFERENCE_NODE, ), Node.NOTATION_NODE: (), } nodeCreateMap = { # from Document 'createAttribute': ('anAttr',), 'createCDATASection': ('a CDATA Section',), 'createComment': ('a Comment',), 'createDocumentFragment': (), 'createElement': ('anElement',), 'createEntityReference': ('anEntityReference',), 'createProcessingInstruction': ('aPI', 'data for PI'), 'createTextNode': ('A Text Node',), # From DOMImplementation (marked as tuples) ('createDocument',): (None, 'aDocument', None), ('createDocumentType',): ('aDocType', 'uri:public', 'uri:system'), } def checkAppendChild(self): allowedChildren = self.allowedChildrenMap[self.node.nodeType] if self.node.nodeType == Node.DOCUMENT_NODE: # To create a better test for Document Nodes, we remove the # documentElement Node. self.node.removeChild(self.node.documentElement) # Since appending a Document Type Node to a Document Node isn't # allowed, we remove it from the allowed children list for now. allowedChildren = allowedChildren[:-1] # We add Document Fragment to the list if any child is allowed. Document # Fragments can also hold such children. This test only adds empty # Document Fragments. if allowedChildren: allowedChildren = allowedChildren + (Node.DOCUMENT_FRAGMENT_NODE,) for factoryMethod, factoryArgs in self.nodeCreateMap.items(): if type(factoryMethod) is type(()): # DOMImplementation methods factory = self.implementation factoryMethod = factoryMethod[0] else: factory = self.document newNode = apply(getattr(factory, factoryMethod), factoryArgs) numberOfChildren = self.node.childNodes.length try: # We append two different copies to see how we fare. Esp. handy # with testing the restrictions of a Document Node returnedNode = self.node.appendChild(newNode) newNode = apply(getattr(factory, factoryMethod), factoryArgs) returnedNode = self.node.appendChild(newNode) except xml.dom.HierarchyRequestErr: if self.node.nodeType == Node.DOCUMENT_NODE: if newNode.nodeType == Node.ELEMENT_NODE: self.assert_(self.node.documentElement, "Couldn't add a Element node to" " an empty Document.") else: # tried to append nonElement to a Document node self.assert_( newNode.nodeType not in allowedChildren, "Couldn't append a %s Node." % TYPE_NAME[newNode.nodeType]) else: # tried to append a node to a nonDocument node self.assert_( newNode.nodeType not in allowedChildren, "Couldn't append a %s Node." % TYPE_NAME[newNode.nodeType]) except xml.dom.NoModificationAllowedErr: self.assert_(self.node.nodeType in self.readOnlyNodeList, "Claim of read-only-ness on a modifiable node. " "Tried to append a %s Node" % TYPE_NAME[newNode.nodeType]) else: if newNode.nodeType != Node.DOCUMENT_FRAGMENT_NODE: self.assert_( isSameNode(newNode, returnedNode), "Returned Node is not the same as has been added.") checkAttributeSameNode(self.node, 'lastChild', newNode) checkLength(self.node.childNodes, numberOfChildren + 2) else: checkLength(self.node.childNodes, numberOfChildren) self.assert_(newNode.nodeType in allowedChildren, "Was allowed to append a %s Node." % TYPE_NAME[newNode.nodeType]) self.assert_( self.node.nodeType not in self.readOnlyNodeList, "Was allowed to append a %s Node to a read-only Node" % TYPE_NAME[newNode.nodeType]) def checkAppendChildForeignNode(self): allowedChildren = self.allowedChildrenMap[self.node.nodeType] # No use when no children are allowed or read-only if not allowedChildren or self.node.nodeType in self.readOnlyNodeList: return foreignDoc = self.implementation.createDocument(None, 'anotherDoc', None) if Node.TEXT_NODE in allowedChildren: foreignNode = foreignDoc.createTextNode('a Text Node') else: foreignNode = foreignDoc.createComment('a Comment Node') self.assertRaises(xml.dom.WrongDocumentErr, self.node.appendChild, foreignNode) def checkAppendChildAncestorNode(self): nodeType = self.node.nodeType if nodeType in self.readOnlyNodeList: return if Node.ELEMENT_NODE not in self.allowedChildrenMap[nodeType]: return if nodeType not in self.allowedChildrenMap[Node.ELEMENT_NODE]: return ancestorNode = self.document.createElement('foo') ancestorNode.appendChild(self.node) self.assertRaises(xml.dom.HierarchyRequestErr, self.node.appendChild, ancestorNode) def checkAppendChildSelf(self): # See DOM erratum core-6 if self.node.nodeType in self.readOnlyNodeList: return if self.node.nodeType not in self.allowedChildrenMap[ self.node.nodeType]: return self.assertRaises(xml.dom.HierarchyRequestErr, self.node.appendChild, self.node) def checkAppendChildWithAttachedNode(self): # Test appending a Node that itself is part of a tree allowedChildren = self.allowedChildrenMap[self.node.nodeType] # No use when no children are allowed or read-only if not allowedChildren or self.node.nodeType in self.readOnlyNodeList: return if Node.TEXT_NODE in allowedChildren: newNode = self.document.createTextNode('a Text Node') else: newNode = self.document.createComment('a Comment Node') oldParent = self.document.createElement('aParentElement') oldParent.appendChild(newNode) self.node.appendChild(newNode) self.failIf(oldParent.hasChildNodes(), "Appended Node not removed from previous parent.") def checkAppendChildNodeParentReadOnly(self): # See DOM erratum core-2 http://www.w3.org/2000/11/DOM-Level-2-errata if self.node.nodeType in self.readOnlyNodeList: return if Node.TEXT_NODE not in self.allowedChildrenMap[self.node.nodeType]: return if self.node.nodeType in [Node.DOCUMENT_NODE, Node.DOCUMENT_TYPE_NODE]: return # can't import doc = self.parse(""" ]> """) # This Text Node has a read-only parent. textNode = doc.doctype.entities.getNamedItem('entity').firstChild # we need self.node to have the same doc as textNode self.node = doc.importNode(self.node, 1) self.assertRaises(xml.dom.NoModificationAllowedErr, self.node.appendChild, textNode) def checkRemoveChild(self): if self.node.nodeType in self.readOnlyNodeList: if self.node.hasChildNodes(): # Test for read-only self.assertRaises(xml.dom.NoModificationAllowedErr, self.node.removeChild, self.node.firstChild) return # If this is a Document Node, let's try and remove the doctype. # We actually test this when we have a doctype, as the Document Node # created for the Document Node tests doesn't *have* a doctype. if self.node.nodeType == Node.DOCUMENT_TYPE_NODE: doc = self.implementation.createDocument('', 'foo', self.node) self.assertRaises(xml.dom.NoModificationAllowedErr, doc.removeChild, doc.doctype) allowedChildren = self.allowedChildrenMap[self.node.nodeType] # No use when no children are allowed if not allowedChildren: return if Node.TEXT_NODE in allowedChildren: newNode = self.document.createTextNode('a Text Node') else: newNode = self.document.createComment('a Comment Node') self.node.appendChild(newNode) returnedNode = self.node.removeChild(newNode) self.assert_(isSameNode(newNode, returnedNode), "Returned Node is not the appended Node.") checkAttribute(newNode, "parentNode", None) checkAttribute(returnedNode, "parentNode", None) def checkRemoveChildNotFound(self): if self.node.nodeType in self.readOnlyNodeList: return loseNode = self.document.createTextNode('booh') self.assertRaises(xml.dom.NotFoundErr, self.node.removeChild, loseNode) def checkInsertBefore(self): if self.node.nodeType in self.readOnlyNodeList: if self.node.hasChildNodes(): # Test for read-only newNode = self.document.createTextNode('a Text Node') self.assertRaises( xml.dom.NoModificationAllowedErr, self.node.insertBefore, newNode, self.node.firstChild) return allowedChildren = self.allowedChildrenMap[self.node.nodeType] if self.node.nodeType == Node.DOCUMENT_NODE: # To create a better test for Document Nodes, we remove the # documentElement Node. self.node.removeChild(self.node.documentElement) # Since inserting a Document Type Node into a Document Node isn't # allowed, we remove it from the allowed children list for now. allowedChildren = allowedChildren[:-1] # No use when no children are allowed. if not allowedChildren: return else: # Append DOCUMENT_FRAGMENT to alowed, because we'll add an empty # fragment. allowedChildren = allowedChildren + (Node.DOCUMENT_FRAGMENT_NODE,) if Node.TEXT_NODE in allowedChildren: refNode = self.document.createTextNode('a Text Node') else: refNode = self.document.createComment('a Comment Node') # Now create the reference to insert before. self.node.appendChild(refNode) for factoryMethod, factoryArgs in self.nodeCreateMap.items(): if type(factoryMethod) is type(()): # DOMImplementation methods factory = self.implementation factoryMethod = factoryMethod[0] else: factory = self.document newNode = apply(getattr(factory, factoryMethod), factoryArgs) numberOfChildren = self.node.childNodes.length try: returnedNode = self.node.insertBefore(newNode, refNode) except xml.dom.HierarchyRequestErr: if self.node.nodeType == Node.DOCUMENT_NODE: if newNode.nodeType == Node.ELEMENT_NODE: self.assert_( self.node.documentElement, "Couldn't add a Element node to an empty Document.") self.assert_(newNode.nodeType not in allowedChildren, "Couldn't append a %s Node." % TYPE_NAME[newNode.nodeType]) except xml.dom.NoModificationAllowedErr: self.assert_(self.node.nodeType in self.readOnlyNodeList, "Claim of read-only-ness on a modifiable node. " "Tried to append a %s Node" % TYPE_NAME[self.node.nodeType]) else: if newNode.nodeType != Node.DOCUMENT_FRAGMENT_NODE: self.assert_( isSameNode(newNode, returnedNode), "Returned Node is not the same as has been added.") checkAttributeSameNode(newNode, 'nextSibling', refNode) checkAttributeSameNode(refNode, 'previousSibling', newNode) checkLength(self.node.childNodes, numberOfChildren + 1) else: checkLength(self.node.childNodes, numberOfChildren) self.assert_(newNode.nodeType in allowedChildren, "Was allowed to insert a %s Node." % TYPE_NAME[newNode.nodeType]) def checkInsertBeforeNotFound(self): allowedChildren = self.allowedChildrenMap[self.node.nodeType] # No use when no children are allowed or read-only if not allowedChildren or self.node.nodeType in self.readOnlyNodeList: return if Node.TEXT_NODE in allowedChildren: refNode = self.document.createTextNode('a Text Node') else: refNode = self.document.createComment('a Comment Node') self.assertRaises( xml.dom.NotFoundErr, self.node.insertBefore, refNode, refNode.cloneNode(0)) def checkInsertBeforeExtraElementToDocument(self): if self.node.nodeType == Node.DOCUMENT_NODE: newNode = self.document.createElement('foo') self.assertRaises( xml.dom.HierarchyRequestErr, self.node.insertBefore, newNode, self.node.documentElement) def checkInsertBeforeForeignNode(self): allowedChildren = self.allowedChildrenMap[self.node.nodeType] # No use when no children are allowed or read-only if not allowedChildren or self.node.nodeType in self.readOnlyNodeList: return foreignDoc = self.implementation.createDocument(None, 'anotherDoc', None) if Node.TEXT_NODE in allowedChildren: refNode = self.document.createTextNode('a Text Node') foreignNode = foreignDoc.createTextNode('a Text Node') else: refNode = self.document.createComment('a Comment Node') foreignNode = foreignDoc.createComment('a Comment Node') self.node.appendChild(refNode) self.assertRaises(xml.dom.WrongDocumentErr, self.node.insertBefore, foreignNode, refNode) def checkInsertBeforeAncestorNode(self): if self.node.nodeType in self.readOnlyNodeList: return if Node.ELEMENT_NODE not in self.allowedChildrenMap[self.node.nodeType]: return if self.node.nodeType not in self.allowedChildrenMap[Node.ELEMENT_NODE]: return ancestorNode = self.document.createElement('foo') ancestorNode.appendChild(self.node) if Node.TEXT_NODE in self.allowedChildrenMap[self.node.nodeType]: refNode = self.document.createTextNode('a Text Node') else: refNode = self.document.createComment('a Comment Node') self.node.appendChild(refNode) self.assertRaises(xml.dom.HierarchyRequestErr, self.node.insertBefore, ancestorNode, refNode) def checkInsertBeforeSelf(self): # See DOM erratum core-7 if self.node.nodeType in self.readOnlyNodeList: return if self.node.nodeType not in self.allowedChildrenMap[ self.node.nodeType]: return if Node.TEXT_NODE in self.allowedChildrenMap[self.node.nodeType]: refNode = self.document.createTextNode('a Text Node') else: refNode = self.document.createComment('a Comment Node') self.node.appendChild(refNode) self.assertRaises(xml.dom.HierarchyRequestErr, self.node.insertBefore, self.node, refNode) def checkInsertBeforeWithAttachedNode(self): # Test appending a Node that itself is part of a tree allowedChildren = self.allowedChildrenMap[self.node.nodeType] # No use when no children are allowed or read-only if not allowedChildren or self.node.nodeType in self.readOnlyNodeList: return if Node.TEXT_NODE in allowedChildren: refNode = self.document.createTextNode('a Text Node') newNode = self.document.createTextNode('a Text Node') else: refNode = self.document.createComment('a Comment Node') newNode = self.document.createComment('a Comment Node') oldParent = self.document.createElement('aParentElement') oldParent.appendChild(newNode) self.node.appendChild(refNode) self.node.insertBefore(newNode, refNode) self.failIf(oldParent.hasChildNodes(), "Appended Node not removed from previous parent.") def checkInsertBeforeNodeParentReadOnly(self): # See DOM erratum core-2 http://www.w3.org/2000/11/DOM-Level-2-errata if self.node.nodeType in self.readOnlyNodeList: return if Node.TEXT_NODE not in self.allowedChildrenMap[self.node.nodeType]: return if self.node.nodeType in [Node.DOCUMENT_NODE, Node.DOCUMENT_TYPE_NODE]: return # can't import doc = self.parse(""" ]> """) # This Text Node has a read-only parent. textNode = doc.doctype.entities.getNamedItem('entity').firstChild refNode = doc.createTextNode('a Text Node') # we need self.node to have the same doc as textNode self.node = doc.importNode(self.node, 1) self.node.appendChild(refNode) self.assertRaises(xml.dom.NoModificationAllowedErr, self.node.insertBefore, textNode, refNode) def checkReplaceChild(self): if self.node.nodeType in self.readOnlyNodeList: if self.node.hasChildNodes(): # Test for read-only newNode = self.document.createTextNode('a Text Node') self.assertRaises( xml.dom.NoModificationAllowedErr, self.node.replaceChild, newNode, self.node.firstChild) return allowedChildren = self.allowedChildrenMap[self.node.nodeType] if self.node.nodeType == Node.DOCUMENT_NODE: # To create a better test for Document Nodes, we remove the # documentElement Node. self.node.removeChild(self.node.documentElement) # Since replacing with a Document Type Node on a Document Node isn't # allowed, we remove it from the allowed children list for now. allowedChildren = allowedChildren[:-1] # No use when no children are allowed. if not allowedChildren: return else: # Append DOCUMENT_FRAGMENT to alowed, because we'll use an empty # fragment. allowedChildren = allowedChildren + (Node.DOCUMENT_FRAGMENT_NODE,) if Node.TEXT_NODE in allowedChildren: refNode = self.document.createTextNode('a Text Node') else: refNode = self.document.createComment('a Comment Node') for factoryMethod, factoryArgs in self.nodeCreateMap.items(): if type(factoryMethod) is type(()): # DOMImplementation methods factory = self.implementation factoryMethod = factoryMethod[0] else: factory = self.document # Now create the reference to replace. We do this for every Node # type we try and replace with. self.node.appendChild(refNode) newNode = apply(getattr(factory, factoryMethod), factoryArgs) numberOfChildren = self.node.childNodes.length try: returnedNode = self.node.replaceChild(newNode, refNode) except xml.dom.HierarchyRequestErr: if self.node.nodeType == Node.DOCUMENT_NODE \ and newNode.nodeType == Node.ELEMENT_NODE: self.assert_( self.node.documentElement, "Couldn't add an Element node to an empty Document.") self.assert_( newNode.nodeType not in allowedChildren, "Couldn't replace an old Node with a %s Node." % TYPE_NAME[newNode.nodeType]) except xml.dom.NoModificationAllowedErr: self.assert_( self.node.nodeType in self.readOnlyNodeList, "Claim of read-only-ness on a modifiable node. " "Tried to replace an old Node with a %s Node" % TYPE_NAME[self.node.nodeType]) else: if newNode.nodeType != Node.DOCUMENT_FRAGMENT_NODE: self.assert_( isSameNode(refNode, returnedNode), "Returned Node is not the same as has been replaced.") checkAttributeSameNode(self.node, 'lastChild', newNode) checkLength(self.node.childNodes, numberOfChildren) self.assert_( isSameNode(refNode, returnedNode), "Returned Node is not the same as has been replaced.") else: checkLength(self.node.childNodes, numberOfChildren - 1) self.assert_(newNode.nodeType in allowedChildren, "Was allowed to replace an old Node with a " "%s Node." % TYPE_NAME[newNode.nodeType]) def checkReplaceChildNotFound(self): allowedChildren = self.allowedChildrenMap[self.node.nodeType] # No use when no children are allowed or read-only if not allowedChildren or self.node.nodeType in self.readOnlyNodeList: return if Node.TEXT_NODE in allowedChildren: refNode = self.document.createTextNode('a Text Node') else: refNode = self.document.createComment('a Comment Node') self.assertRaises( xml.dom.NotFoundErr, self.node.replaceChild, refNode, refNode.cloneNode(0)) def checkReplaceChildExtraElementToDocument(self): if self.node.nodeType == Node.DOCUMENT_NODE: refNode = self.document.createComment('a Comment Node') self.node.appendChild(refNode) newNode = self.document.createElement('foo') self.assertRaises(xml.dom.HierarchyRequestErr, self.node.replaceChild, newNode, refNode) def checkReplaceChildForeignNode(self): allowedChildren = self.allowedChildrenMap[self.node.nodeType] # No use when no children are allowed or read-only if not allowedChildren or self.node.nodeType in self.readOnlyNodeList: return foreignDoc = self.implementation.createDocument(None, 'anotherDoc', None) if Node.TEXT_NODE in allowedChildren: refNode = self.document.createTextNode('a Text Node') foreignNode = foreignDoc.createTextNode('a Text Node') else: refNode = self.document.createComment('a Comment Node') foreignNode = foreignDoc.createComment('a Comment Node') self.node.appendChild(refNode) self.assertRaises(xml.dom.WrongDocumentErr, self.node.replaceChild, foreignNode, refNode) def checkReplaceChildAncestorNode(self): if self.node.nodeType in self.readOnlyNodeList: return if Node.ELEMENT_NODE not in self.allowedChildrenMap[self.node.nodeType]: return if self.node.nodeType not in self.allowedChildrenMap[Node.ELEMENT_NODE]: return ancestorNode = self.document.createElement('foo') ancestorNode.appendChild(self.node) if Node.TEXT_NODE in self.allowedChildrenMap[self.node.nodeType]: refNode = self.document.createTextNode('a Text Node') else: refNode = self.document.createComment('a Comment Node') self.node.appendChild(refNode) self.assertRaises(xml.dom.HierarchyRequestErr, self.node.replaceChild, ancestorNode, refNode) def checkReplaceChildSelf(self): # See DOM erratum core-8 if self.node.nodeType in self.readOnlyNodeList: return if self.node.nodeType not in self.allowedChildrenMap[ self.node.nodeType]: return if Node.TEXT_NODE in self.allowedChildrenMap[self.node.nodeType]: refNode = self.document.createTextNode('a Text Node') else: refNode = self.document.createComment('a Comment Node') self.node.appendChild(refNode) self.assertRaises(xml.dom.HierarchyRequestErr, self.node.replaceChild, self.node, refNode) def checkReplaceChildWithAttachedNode(self): # Test replacing with a Node that itself is part of a tree allowedChildren = self.allowedChildrenMap[self.node.nodeType] # No use when no children are allowed or read-only if not allowedChildren or self.node.nodeType in self.readOnlyNodeList: return if Node.TEXT_NODE in allowedChildren: refNode = self.document.createTextNode('a Text Node') newNode = self.document.createTextNode('a Text Node') else: refNode = self.document.createComment('a Comment Node') newNode = self.document.createComment('a Comment Node') oldParent = self.document.createElement('aParentElement') oldParent.appendChild(newNode) self.node.appendChild(refNode) self.node.replaceChild(newNode, refNode) self.failIf(oldParent.hasChildNodes(), "Replacing Node not removed from previous parent.") def checkReplaceChildNodeParentReadOnly(self): # See DOM erratum core-2 http://www.w3.org/2000/11/DOM-Level-2-errata if self.node.nodeType in self.readOnlyNodeList: return if Node.TEXT_NODE not in self.allowedChildrenMap[self.node.nodeType]: return if self.node.nodeType in [Node.DOCUMENT_NODE, Node.DOCUMENT_TYPE_NODE]: return # can't import doc = self.parse(""" ]> """) # This Text Node has a read-only parent. textNode = doc.doctype.entities.getNamedItem('entity').firstChild # we need self.node to have the same doc as textNode self.node = doc.importNode(self.node, 1) refNode = doc.createTextNode('a Text Node') self.node.appendChild(refNode) self.assertRaises(xml.dom.NoModificationAllowedErr, self.node.replaceChild, textNode, refNode) # --- Document class DocumentReadTestCase(NodeReadTestCaseBase): def setUp(self): self.createDocument() self.node = self.document self.expectedType = Node.DOCUMENT_NODE def checkGetDoctype(self): checkAttribute(self.document, "doctype", None) checkReadOnly(self.document, "doctype") def checkGetImplementation(self): checkAttribute(self.document, "implementation", self.implementation) checkReadOnly(self.document, "implementation") def checkGetDocumentElement(self): checkAttributeNot(self.document, "documentElement", None) checkReadOnly(self.document, "documentElement") def checkCloneNode(self): # TODO: Implementation dependent, what should we test? pass class DocumentWriteTestCase(NodeWriteTestCaseBase): def setUp(self): self.node = self.createDocument() def checkGetElementsByTagName(self): doc = self.document elements = {} names = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'] for c in names: elements[c] = doc.createElement(c) # set up simple tree elements['a'].appendChild(elements['b']) elements['a'].appendChild(elements['d']) elements['b'].appendChild(elements['c']) elements['d'].appendChild(elements['e']) elements['d'].appendChild(elements['h']) elements['e'].appendChild(elements['f']) elements['e'].appendChild(elements['g']) elements['h'].appendChild(elements['i']) doc.documentElement.appendChild(elements['a']) # now test # find all elements in the right order result = doc.getElementsByTagName('*') self.assertEqual(len(result), len(names) + 1) for name, element in map(None, names, result[1:]): self.assertEqual(name, element.tagName) # find single element, top result = doc.getElementsByTagName('a') self.assertEqual(len(result), 1) self.assertEqual(result[0].tagName, 'a') # find single element somewhere in tree result = doc.getElementsByTagName('h') self.assertEqual(len(result), 1) self.assertEqual(result[0].tagName, 'h') def checkCreateAttribute(self): attr = self.document.createAttribute(self.TEST_NAME) checkAttribute(attr, 'nodeType', Node.ATTRIBUTE_NODE) checkAttribute(attr, 'name', self.TEST_NAME) checkAttribute(attr, 'localName', None) checkAttribute(attr, 'prefix', None) checkAttribute(attr, 'namespaceURI', None) checkAttribute(attr, 'value', '') checkAttributeSameNode(attr, 'ownerDocument', self.document) # Note the ':' in the name, createAttribute does not know about # namespaces, so the colon has no special meaning. attr = self.document.createAttribute('not_a_prefix:not_a_localname') checkAttribute(attr, 'name', 'not_a_prefix:not_a_localname') checkAttribute(attr, 'localName', None) checkAttribute(attr, 'prefix', None) self.assertRaises(xml.dom.InvalidCharacterErr, self.document.createAttribute, '5_illegal') def checkCreateCDATASection(self): cdata = self.document.createCDATASection('A CDATA Section') checkAttribute(cdata, 'nodeType', Node.CDATA_SECTION_NODE) checkAttribute(cdata, 'data', 'A CDATA Section') checkAttributeSameNode(cdata, 'ownerDocument', self.document) def checkCreateComment(self): comment = self.document.createComment('A Comment') checkAttribute(comment, 'nodeType', Node.COMMENT_NODE) checkAttribute(comment, 'data', 'A Comment') checkAttributeSameNode(comment, 'ownerDocument', self.document) def checkCreateDocumentFragment(self): fragment = self.document.createDocumentFragment() checkAttribute(fragment, 'nodeType', Node.DOCUMENT_FRAGMENT_NODE) checkLength(fragment.childNodes, 0) checkAttributeSameNode(fragment, 'ownerDocument', self.document) def checkCreateElement(self): el = self.document.createElement(self.TEST_NAME) checkAttribute(el, 'nodeType', Node.ELEMENT_NODE) checkAttribute(el, 'tagName', self.TEST_NAME) checkAttribute(el, 'localName', None) checkAttribute(el, 'prefix', None) checkAttribute(el, 'namespaceURI', None) checkAttributeSameNode(el, 'ownerDocument', self.document) # Note the ':' in the name, createElement does not know about # namespaces, so the colon has no special meaning. el = self.document.createElement('not_a_prefix:not_a_localname') checkAttribute(el, 'tagName', 'not_a_prefix:not_a_localname') checkAttribute(el, 'localName', None) checkAttribute(el, 'prefix', None) def checkCreateElementInvalidCharacter(self): self.assertRaises(xml.dom.InvalidCharacterErr, self.document.createElement, '5_illegal') def checkCreateEntityReference(self): entRef = self.document.createEntityReference('entityReference') checkAttribute(entRef, 'nodeType', Node.ENTITY_REFERENCE_NODE) checkAttribute(entRef, 'nodeName', 'entityReference') checkAttributeSameNode(entRef, 'ownerDocument', self.document) def checkCreateEntityReferenceInvalidCharacter(self): self.assertRaises(xml.dom.InvalidCharacterErr, self.document.createEntityReference, '5_illegal') def checkCreateProcessingInstruction(self): pi = self.document.createProcessingInstruction('PITarget', 'PI Data') checkAttribute(pi, 'nodeType', Node.PROCESSING_INSTRUCTION_NODE) checkAttribute(pi, 'target', 'PITarget') checkAttribute(pi, 'data', 'PI Data') checkAttributeSameNode(pi, 'ownerDocument', self.document) def checkCreateProcessingInstructionInvalidCharacter(self): self.assertRaises( xml.dom.InvalidCharacterErr, self.document.createProcessingInstruction, '5_illegal', 'data') def checkCreateTextNode(self): text = self.document.createTextNode('A Text Node') checkAttribute(text, 'nodeType', Node.TEXT_NODE) checkAttribute(text, 'data', 'A Text Node') checkAttributeSameNode(text, 'ownerDocument', self.document) # --- Element class ElementReadTestCase(NodeReadTestCaseBase): def setUp(self): doc = self.createDocument() self.element = self.node = doc.createElement("per") self.expectedType = Node.ELEMENT_NODE self.floating_element = self.element self.attached_element = doc.createElement("attached") doc.documentElement.appendChild(self.attached_element) def checkDocumentElementChildNodes(self): checkLength(self.document.documentElement.childNodes, 1) def checkAttachedElementParentNode(self): checkAttributeSameNode(self.attached_element, "parentNode", self.document.documentElement) def checkDocumentElementFirstChild(self): checkAttributeSameNode(self.document.documentElement, "firstChild", self.attached_element) checkAttributeSameNode( self.document.documentElement.firstChild, "parentNode", self.document.documentElement) def checkTagName(self): checkAttribute(self.floating_element, "tagName", "per") checkAttribute(self.attached_element, "tagName", "attached") checkReadOnly(self.floating_element, "tagName") def checkGetAttribute(self): self.assertEqual(self.element.getAttribute("ugga"), "", "non-existant attribute should return ''") def checkGetAttributeNode(self): self.assert_(self.element.getAttributeNode("ugga") is None, "non-existant attribute node should return None") def checkCloneNode(self): el = self.element doc = self.document el.appendChild(doc.createTextNode('A Text Node')) el.appendChild(doc.createComment('A Comment')) el.setAttribute('attr1', 'An attribute') el.setAttribute('attr2', 'Another attribute') el.appendChild(el.cloneNode(0)) clone = el.cloneNode(1) self.failIf(isSameNode(el, clone), "Clone is same Node as original.") self.failIf(isSameNode(el, clone.lastChild), "Clone is same Node as original.") checkAttribute(clone, 'parentNode', None) checkLength(clone.childNodes, el.childNodes.length) checkLength(clone.attributes, el.attributes.length) checkLength(clone.lastChild.childNodes, 0) checkLength(clone.lastChild.attributes, el.attributes.length) checkAttribute(clone, 'nodeName', el.nodeName) checkAttribute(clone.lastChild, 'nodeName', el.nodeName) checkAttribute(clone, 'nodeType', el.nodeType) checkAttribute(clone.lastChild, 'nodeType', el.nodeType) checkAttribute(clone, 'nodeValue', el.nodeValue) checkAttribute(clone.lastChild, 'nodeValue', el.nodeValue) for i in range(clone.childNodes.length): checkAttribute(clone.childNodes.item(i), 'nodeType', el.childNodes.item(i).nodeType) if clone.childNodes.item(i).nodeType != Node.ELEMENT_NODE: checkAttribute(clone.childNodes.item(i), 'data', el.childNodes.item(i).data) for i in range(clone.attributes.length): checkAttribute(clone.attributes.item(i), 'name', el.attributes.item(i).name) checkAttribute(clone.lastChild.attributes.item(i), 'name', el.attributes.item(i).name) checkAttribute(clone.attributes.item(i), 'value', el.attributes.item(i).value) checkAttribute(clone.lastChild.attributes.item(i), 'value', el.attributes.item(i).value) # deep and shallow clones should clone attributes value = clone.attributes.item(i).value el.attributes.item(i).value = 'spam' checkAttribute(clone.attributes.item(i), 'value', value) checkAttribute(clone.lastChild.attributes.item(i), 'value', value) checkAttributeSameNode(clone.attributes.item(i), 'ownerElement', clone) checkAttributeSameNode(clone.lastChild.attributes.item(i), 'ownerElement', clone.lastChild) self.failIf(isSameNode(el.attributes.item(i), clone.attributes.item(i))) class ElementWriteTestCase(NodeWriteTestCaseBase): def setUp(self): doc = self.createDocument() self.element = self.node = doc.createElement("per") self.floating_element = self.element self.attached_element = doc.createElement("attached") self.attached_element2 = doc.createElement("attached2") doc.documentElement.appendChild(self.attached_element) doc.documentElement.appendChild(self.attached_element2) def checkAttachedElementsNextSibling(self): checkAttributeSameNode(self.attached_element, "nextSibling", self.attached_element2) checkAttributeSameNode(self.attached_element2, "nextSibling", None) def checkAttachedElementsPreviousSibling(self): checkAttributeSameNode(self.attached_element, "previousSibling", None) checkAttributeSameNode(self.attached_element2, "previousSibling", self.attached_element) def checkGetElementsByTagName(self): doc = self.document el = self.element elements = {} names = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'] for c in names: elements[c] = doc.createElement(c) # set up simple tree elements['a'].appendChild(elements['b']) elements['a'].appendChild(elements['d']) elements['b'].appendChild(elements['c']) elements['d'].appendChild(elements['e']) elements['d'].appendChild(elements['h']) elements['e'].appendChild(elements['f']) elements['e'].appendChild(elements['g']) elements['h'].appendChild(elements['i']) el.appendChild(elements['a']) # now test # find all elements in the right order result = el.getElementsByTagName('*') self.assertEqual(len(result), len(names)) for name, element in map(None, names, result): self.assertEqual(name, element.tagName) # find single element, top result = el.getElementsByTagName('a') self.assertEqual(len(result), 1) self.assertEqual(result[0].tagName, 'a') # find single element somewhere in tree result = el.getElementsByTagName('h') self.assertEqual(len(result), 1) self.assertEqual(result[0].tagName, 'h') def checkSetAttribute(self): self.element.setAttribute("ugga", "foo") self.assert_(self.element.hasAttribute("ugga"), "Test for presence of created attribute returned false.") value = self.element.getAttribute("ugga") self.assertEqual(value, 'foo', "Incorrect attr value returned. Expected 'foo', got " + repr(value)) def checkSetAttributeIllegalCharacter(self): self.assertRaises( xml.dom.InvalidCharacterErr, self.element.setAttribute, '5_illegal', "Don't eat this") def checkSetAttributeNode(self): node = self.document.createAttribute("ugga") node.value = 'foo' returnValue = self.element.setAttributeNode(node) self.assert_( self.element.hasAttribute("ugga"), "Test for presence of created attribute returned false.") self.assert_(returnValue is None, "Returned value is %s" % repr(returnValue)) value = self.element.getAttribute("ugga") self.assertEqual(value, 'foo', "Incorrect attr value returned. Expected 'foo', got " + repr(value)) returnedNode = self.element.getAttributeNode("ugga") self.assert_(isSameNode(node, returnedNode), "Incorrect node returned from getAttributeNode.") def checkSetAttributeNodeReplaceExisting(self): node = self.document.createAttribute("ugga") self.element.setAttributeNode(node) newNode = self.document.createAttribute("ugga") returnValue = self.element.setAttributeNode(newNode) if returnValue is None: self.fail("setAttributeNode did not replace original attribute") self.assert_(isSameNode(node, returnValue), "setAttributeNode returned %s" % repr(returnValue)) def checkSetAttributeNodeWrongDocument(self): foreignDoc = self.implementation.createDocument(None, 'foo', None) foreignAttr = foreignDoc.createAttribute('spam') self.assertRaises(xml.dom.WrongDocumentErr, self.element.setAttributeNodeNS, foreignAttr) def checkSetAttributeNodeAlreadyInUse(self): otherElement = self.document.createElement('foo') otherAttr = self.document.createAttribute('spam') otherElement.setAttributeNodeNS(otherAttr) self.assertRaises(xml.dom.InuseAttributeErr, self.element.setAttributeNodeNS, otherAttr) def checkRemoveAttribute(self): node1 = self.document.createAttribute("foo") node2 = self.document.createAttribute("bar") self.element.setAttributeNode(node1) self.element.setAttributeNode(node2) self.element.removeAttribute("foo") self.failIf( self.element.hasAttribute("foo"), "Test for presence of created attribute still returns true.") self.assert_(self.element.hasAttribute("bar"), "Test for presence of created attribute returned false.") checkAttribute(node1, 'ownerElement', None) def checkRemoveAttributeNode(self): node1 = self.document.createAttribute("foo") node2 = self.document.createAttribute("bar") self.element.setAttributeNode(node1) self.element.setAttributeNode(node2) returnedNode = self.element.removeAttributeNode(node1) self.assert_( isSameNode(node1, returnedNode), "Returned node not the same as the one removed.") checkAttribute(node1, 'ownerElement', None) self.failIf( self.element.hasAttribute("foo"), "Test for presence of created attribute still returns true.") self.assert_( self.element.hasAttribute("bar"), "Test for presence of created attribute returned false.") def checkRemoveAttributeNodeNotFound(self): node = self.document.createAttribute("foo") self.assertRaises(xml.dom.NotFoundErr, self.element.removeAttributeNode, node) # --- CharacterData class CharacterDataReadTestCaseBase(NodeReadTestCaseBase): def checkGetData(self): checkAttribute(self.chardata, "data", "com") def checkGetLength(self): checkLength(self.chardata, 3) self.assertEqual(len(self.chardata.data), 3) self.assertEqual(len(self.chardata._get_data()), 3) def checkSubstringData(self): self.assertEqual(self.chardata.substringData(0, 2), "co") def checkSubstringDataNegativeOffset(self): self.assertRaises(xml.dom.IndexSizeErr, self.chardata.substringData, -2, 0) def checkSubstringDataOffsetGreaterThanLength(self): self.assertRaises(xml.dom.IndexSizeErr, self.chardata.substringData, 10, 0) def checkSubstringDataNegativeCount(self): self.assertRaises(xml.dom.IndexSizeErr, self.chardata.substringData, 0, -2) def checkSubstringDataOffsetAndCountGreaterThanLength(self): self.assertEqual(self.chardata.substringData(1, 10), "om") def checkCloneNode(self): clone = self.chardata.cloneNode(0) deepClone = self.chardata.cloneNode(1) self.failIf(isSameNode(self.chardata, clone), "Clone is same as original.") self.failIf(isSameNode(self.chardata, deepClone), "Clone is same as original.") checkAttribute(clone, 'parentNode', None) checkAttribute(deepClone, 'parentNode', None) checkAttribute(clone, 'nodeType', self.chardata.nodeType) checkAttribute(deepClone, 'nodeType', self.chardata.nodeType) checkAttribute(clone, 'data', self.chardata.data) checkAttribute(deepClone, 'data', self.chardata.data) checkLength(clone.childNodes, 0) checkLength(deepClone.childNodes, 0) class CharacterDataWriteTestCaseBase(NodeWriteTestCaseBase): def checkSetData(self): self.chardata._set_data("data") checkAttribute(self.chardata, "data", "data") def checkAppendData(self): self.chardata.appendData("com") checkAttribute(self.chardata, "data", "comcom") def checkInsertData(self): self.chardata.insertData(2, "com") checkAttribute(self.chardata, "data", "cocomm") def checkInsertDataNegativeOffset(self): self.assertRaises(xml.dom.IndexSizeErr, self.chardata.insertData, -2, 'foo') def checkInsertDataOffsetGreaterThanLength(self): self.assertRaises(xml.dom.IndexSizeErr, self.chardata.insertData, 10, 'foo') def checkDeleteData(self): self.chardata.deleteData(1, 1) checkAttribute(self.chardata, "data", "cm") def checkDeleteDataNegativeOffset(self): self.assertRaises(xml.dom.IndexSizeErr, self.chardata.deleteData, -2, 0) def checkDeleteDataOffsetGreaterThanLength(self): self.assertRaises(xml.dom.IndexSizeErr, self.chardata.deleteData, 10, 0) def checkDeleteDataNegativeCount(self): self.assertRaises(xml.dom.IndexSizeErr, self.chardata.deleteData, 0, -2) def checkDeleteDataOffsetAndCountGreaterThanLength(self): self.chardata.deleteData(0, 10) checkAttribute(self.chardata, "data", "") def checkReplaceData(self): self.chardata.replaceData(1, 3, "uuuu") checkAttribute(self.chardata, "data", "cuuuu") def checkReplaceDataNegativeOffset(self): self.assertRaises(xml.dom.IndexSizeErr, self.chardata.replaceData, -2, 0, 'foo') def checkReplaceDataOffsetGreaterThanLength(self): self.assertRaises(xml.dom.IndexSizeErr, self.chardata.replaceData, 10, 0, 'foo') def checkReplaceDataNegativeCount(self): self.assertRaises(xml.dom.IndexSizeErr, self.chardata.replaceData, 0, -2, 'foo') def checkReplaceDataOffsetAndCountGreaterThanLength(self): self.chardata.replaceData(0, 10, "foo") checkAttribute(self.chardata, "data", "foo") # --- Comment class CommentReadTestCase(CharacterDataReadTestCaseBase): def setUp(self): self.chardata = self.node = self.createDocument().createComment("com") self.expectedType = Node.COMMENT_NODE class CommentWriteTestCase(CharacterDataWriteTestCaseBase): def setUp(self): self.chardata = self.node = self.createDocument().createComment("com") # --- Text class TextReadTestCase(CharacterDataReadTestCaseBase): def setUp(self): self.chardata = self.node = self.createDocument().createTextNode("com") self.expectedType = Node.TEXT_NODE class TextWriteTestCase(CharacterDataWriteTestCaseBase): def setUp(self): self.chardata = self.node = self.createDocument().createTextNode("com") def checkAcquisition(self): if 1: # This test is disabled. Simple implicit acquisition # causes removeAttribute() to be acquired when it # probably should not, but this issue is not of # sufficient importance for now. return cdata = self.document.createTextNode("com") self.document.documentElement.appendChild(cdata) cdata2 = self.document.createTextNode("com2") self.document.documentElement.appendChild(cdata2) attr = self.document.createAttribute("attrName") self.document.documentElement.setAttributeNode(attr) # Technically these should raise. Because of acquisition they # might not. We want to make sure that they don't affect # the tree. try: self.document.documentElement.firstChild.normalize() except: pass try: self.document.documentElement.firstChild.removeAttribute( "attrName") except: pass else: self.fail('removeAttribute() was acquired from documentElement.') checkAttribute(self.document.documentElement.childNodes, "length", 2) checkAttribute(self.document.documentElement.attributes, "length", 1) def checkSplitText(self): newNode = self.chardata.splitText(2) checkAttribute(self.chardata, 'data', 'co') checkAttribute(newNode, 'data', 'm') def checkSplitTextOffsetEqualToLength(self): try: newNode = self.chardata.splitText(self.chardata.length) except xml.dom.IndexSizeErr: self.fail( "INDEX_SIZE_ERR raised on splitText with offset == length.") checkAttribute(self.chardata, 'data', 'com') checkAttribute(newNode, 'data', '') def checkSplitTextNegativeOffset(self): self.assertRaises(xml.dom.IndexSizeErr, self.chardata.splitText, -2) def checkSplitTextOffsetGreateThanLength(self): self.assertRaises(xml.dom.IndexSizeErr, self.chardata.splitText, 10) def checkSplitTextWithParent(self): el = self.document.createElement('foo') el.appendChild(self.chardata) newNode = self.chardata.splitText(2) checkAttributeSameNode(self.chardata, 'nextSibling', newNode) # --- Attr class AttrReadTestCase(NodeReadTestCaseBase): def setUp(self): self.attr = self.node = self.createDocument().createAttribute("name") self.expectedType = Node.ATTRIBUTE_NODE def checkGetName(self): checkAttribute(self.attr, "name", "name") def checkGetSpecified(self): self.assert_(self.attr._get_specified()) self.assert_(self.attr.specified) def checkGetValue(self): checkAttribute(self.attr, "value", "") checkLength(self.attr.childNodes, 1) checkAttribute(self.attr.firstChild, 'nodeType', Node.TEXT_NODE) checkAttribute(self.attr.firstChild, 'data', '') def checkCloneNode(self): clone = self.attr.cloneNode(0) deepClone = self.attr.cloneNode(1) self.failIf(isSameNode(self.attr, clone), "Clone is same as original.") self.failIf(isSameNode(self.attr, deepClone), "Clone is same as original.") checkAttribute(clone, 'parentNode', None) checkAttribute(deepClone, 'parentNode', None) checkAttribute(clone, 'nodeType', self.attr.nodeType) checkAttribute(deepClone, 'nodeType', self.attr.nodeType) checkAttribute(clone, 'name', self.attr.name) checkAttribute(deepClone, 'name', self.attr.name) checkAttribute(clone, 'value', self.attr.value) checkAttribute(deepClone, 'value', self.attr.value) checkAttribute(clone, 'specified', 1) checkAttribute(deepClone, 'specified', 1) checkAttribute(clone, 'nodeName', self.attr.nodeName) checkAttribute(deepClone, 'nodeName', self.attr.nodeName) checkAttribute(clone, 'nodeValue', self.attr.nodeValue) checkAttribute(deepClone, 'nodeValue', self.attr.nodeValue) checkLength(clone.childNodes, 1) # Subtree models value checkAttribute(clone.firstChild, 'nodeType', Node.TEXT_NODE) checkAttribute(clone.firstChild, 'data', self.attr.value) checkLength(deepClone.childNodes, 1) checkAttribute(deepClone.firstChild, 'nodeType', Node.TEXT_NODE) checkAttribute(deepClone.firstChild, 'data', self.attr.value) class AttrWriteTestCase(NodeWriteTestCaseBase): def setUp(self): self.attr = self.node = self.createDocument().createAttribute( "attrName") self.element = self.document.createElement("eltName") def checkSetValue(self): self.attr._set_value("14") checkAttribute(self.attr, "value", "14") checkLength(self.attr.childNodes, 1) checkAttribute(self.attr.firstChild, 'nodeType', Node.TEXT_NODE) checkAttribute(self.attr.firstChild, 'data', '14') def checkManipulateSubTree(self): attr = self.attr self.assert_(attr.hasChildNodes(), "Attr doesn't have subtree to manipulate!") newNode = self.document.createTextNode('New Value') attr.replaceChild(newNode, attr.firstChild) checkAttribute(attr.firstChild, 'data', 'New Value') checkAttribute(attr, 'value', 'New Value') attr.appendChild(self.document.createTextNode(' (appended)')) checkAttribute(attr, 'value', 'New Value (appended)') attr.firstChild.appendData(' ') attr.replaceChild(self.document.createEntityReference('foo'), attr.lastChild) checkAttribute(attr, 'value', 'New Value ') # Setting the value with a string containing an XML reference does *not* # cause it to create an EntiyReference. Everything is a string literal. attr.value = 'Some Value &test;' checkLength(attr.childNodes, 1) checkAttribute(attr.firstChild, 'data', 'Some Value &test;') def checkOwnerElement(self): checkAttribute(self.attr, "ownerElement", None) checkReadOnly(self.attr, "ownerElement") self.element.setAttributeNode(self.attr) checkAttributeSameNode(self.attr, "ownerElement", self.element) checkReadOnly(self.attr, "ownerElement") def checkAttrTwoReferencesIntegrity(self): #XXX this test should be generalized to any reference attr = self.document.createAttribute('spam') self.document.documentElement.setAttributeNode(attr) a1 = self.document.documentElement.attributes.item(0) a2 = self.document.documentElement.attributes.item(0) a1.appendChild(self.document.createTextNode('eggs')) self.assertEqual( a1.childNodes.length, a2.childNodes.length, "Write to one attr reference isn't reflected in another ref.") def checkAttrReferenceElementAttributeIntegrity(self): "changing an attribute node should be reflected by getAttribute" attr = self.document.createAttribute('spam') self.document.documentElement.setAttributeNode(attr) a1 = self.document.documentElement.attributes.item(0) a1.value = 'eggs' self.assertEqual( self.document.documentElement.getAttribute('spam'), 'eggs', "setting value of attr reference isn't reflected by getAttribute") a1.appendChild(self.document.createTextNode('ham')) self.assertEqual( self.document.documentElement.getAttribute('spam'), 'eggsham', "appendChild on attr reference isn't reflected by getAttribute.") def checkSetAttrWithSubtree(self): "setAttributeNode shouldn't lose attr subtree information" eggs = self.document.createTextNode('eggs') ham = self.document.createTextNode('ham') self.attr.appendChild(eggs) self.attr.appendChild(ham) self.element.setAttributeNode(self.attr) # check that getting the attr from the element preserves subtree checkAttribute(self.element.attributes.item(0).childNodes, "length", 3) self.assert_( self.attr.firstChild.nextSibling.isSameNode(eggs), "setting an attribute node destroys children") self.assert_( self.attr.firstChild.nextSibling.nextSibling.isSameNode(ham), "setting an attribute node destroys children") # check that another ref preserves subtree, too attr2 = self.element.getAttributeNode('attrName') checkAttribute(attr2.childNodes, "length", 3) self.assert_( attr2.firstChild.nextSibling.isSameNode(eggs), "setting an attribute node destroys children") self.assert_( attr2.firstChild.nextSibling.nextSibling.isSameNode(ham), "setting an attribute node destroys children") def checkCloneNode(self): attr = self.attr clone = attr.cloneNode(0) self.failIf(isSameNode(attr, clone), "Clone is same Node as original.") checkAttribute(clone, 'value', attr.value) # make sure the cloned attr isn't sharing data with the original oldValue = self.attr.value self.attr.value = 'spam' checkAttribute(clone, 'value', oldValue) # --- Default attributes class DefaultAttrTestCase(TestCaseBase): def setUp(self): self.document = self.parse(""" ]> """) def checkHasAttribute(self): el = self.document.documentElement self.assert_(el.hasAttribute('foo'), 'Default attribute not found.') def checkGetAttribute(self): el = self.document.documentElement self.assertEqual( el.getAttribute('foo'), 'bar', "Wrong value of default attribute found, expected 'bar', found %s" % repr(el.getAttribute('foo'))) def checkCreateElement(self): el = self.document.createElement('doc') self.assert_( el.hasAttribute('foo'), 'Newly created Element Node should have default attribute.') self.assertEqual( el.getAttribute('foo'), 'bar', "Wrong value of default attribute found, expected 'bar', found %s" % el.getAttribute('foo')) checkAttribute(el.getAttributeNode('foo'), 'specified', 0) def checkCloneNode(self): attr = self.document.documentElement.getAttributeNode('foo') clone = attr.cloneNode(0) checkAttribute(clone, 'specified', 1) def checkCloneNodeElement(self): clone = self.document.documentElement.cloneNode(0) checkAttribute(clone.getAttributeNode('foo'), 'specified', 0) # XXX also check that cloned attrs aren't the same nodes, changes # aren't reflected across refs def checkRemoveAttribute(self): el = self.document.documentElement # Replace default with specified attr el.setAttribute('foo', 'baz') el.removeAttribute('foo') self.assert_( el.hasAttribute('foo'), 'Removing specified attribute should restore default attribute.') self.assertEqual( el.getAttribute('foo'), 'bar', "Wrong value of default attribute found, expected 'bar', found %s" % el.getAttribute('foo')) checkAttribute(el.getAttributeNode('foo'), 'specified', 0) def checkRemoveAttributeNode(self): el = self.document.documentElement newAttr = self.document.createAttribute('foo') newAttr.value = 'baz' # Replace default with specified attr el.setAttributeNode(newAttr) el.removeAttributeNode(newAttr) self.assert_( el.hasAttribute('foo'), 'Removing specified attribute should restore default attribute.') self.assertEqual( el.getAttribute('foo'), 'bar', "Wrong value of default attribute found, expected 'bar', found %s" % el.getAttribute('foo')) checkAttribute(el.getAttributeNode('foo'), 'specified', 0) def checkRemoveNamedItem(self): el = self.document.documentElement # Replace default with specified attr el.setAttribute('foo', 'baz') el.attributes.removeNamedItem('foo') self.assert_( el.hasAttribute('foo'), 'Removing specified attribute should restore default attribute.') self.assertEqual( el.getAttribute('foo'), 'bar', "Wrong value of default attribute found, expected 'bar', found %s" % el.getAttribute('foo')) checkAttribute(el.getAttributeNode('foo'), 'specified', 0) def checkSpecified(self): checkAttribute(self.document.documentElement.getAttributeNode('foo'), 'specified', 0) def checkSetAttribute(self): el = self.document.documentElement el.setAttribute('foo', 'baz') checkAttribute(el.getAttributeNode('foo'), 'specified', 1) def checkSetAttributeNode(self): el = self.document.documentElement newAttr = self.document.createAttribute('foo') newAttr.value = 'baz' el.setAttributeNode(newAttr) checkAttribute(el.getAttributeNode('foo'), 'specified', 1) # --- DocumentFragment class DocumentFragmentReadTestCase(NodeReadTestCaseBase): def setUp(self): self.docfrag = self.createDocument().createDocumentFragment() self.node = self.docfrag self.expectedType = Node.DOCUMENT_FRAGMENT_NODE def checkCloneNode(self): frag = self.docfrag frag.appendChild(self.document.createComment('foo')) frag.appendChild(self.document.createTextNode('bar')) clone = frag.cloneNode(0) deepClone = frag.cloneNode(1) self.failIf(isSameNode(frag, clone), "Clone is same Node as original.") self.failIf(isSameNode(frag, deepClone), "Clone is same Node as original.") checkAttribute(clone, 'parentNode', None) checkAttribute(deepClone, 'parentNode', None) checkLength(clone.childNodes, 0) checkLength(deepClone.childNodes, frag.childNodes.length) for i in range(deepClone.childNodes.length): checkAttribute(deepClone.childNodes.item(i), 'nodeType', frag.childNodes.item(i).nodeType) checkAttribute(deepClone.childNodes.item(i), 'data', frag.childNodes.item(i).data) class DocumentFragmentWriteTestCase(NodeWriteTestCaseBase): def setUp(self): self.createDocument() self.docfrag = self.node = self.document.createDocumentFragment() def checkInsertBeforeEnd(self): doc = self.document fragment = self.docfrag fragment.appendChild(doc.createElement('foo')) fragment.appendChild(doc.createTextNode('textual magic')) docelem = doc.documentElement docelem.insertBefore(fragment, None) checkAttribute(docelem.childNodes[0], "nodeName", "foo") checkAttribute(docelem.childNodes[1], "nodeValue", "textual magic") checkLength(docelem.childNodes, 2) checkAttribute(docelem.firstChild, "nodeName", "foo") # --- NodeList class NodeListReadTestCase(TestCaseBase): def setUp(self): self.createDocument() self.list = self.document.createElement("foo")._get_childNodes() def checkGetLength(self): checkLength(self.list, 0) checkLength(self.document.childNodes, 1) def checkItem(self): self.assert_(self.list.item(0) is None) def checkGetItem(self): self.assertRaises(xml.dom.IndexSizeErr, self.list[0]) # there's no cmp for NodeList right now #def checkCmp(self): # list1 = self.document.documentElement._get_childNodes() # list2 = self.document.firstChild._get_childNodes() # self.assertEqual(list1, list2, # "two NodeLists of the same thing don't compare" ## def checkGetSlice(self): ## self.assertEqual(self.list[2:5], []) class NodeListWriteTestCase(TestCaseBase): def setUp(self): self.createDocument() self.list = self.document.childNodes def checkGetLength(self): checkLength(self.list, 1) self.document.appendChild(self.document.createComment('foo')) # A NodeList is 'live', changes to source Node should be reflected checkLength(self.list, 2) def checkItem(self): newNode = self.document.createComment('foo') self.document.appendChild(newNode) # A NodeList is 'live', changes to source Node should be reflected isSameNode(newNode, self.list.item(1)) # This extends to the Nodes contained in the NodeList newNode.data = 'bar' checkAttribute(self.list.item(1), 'data', 'bar') # --- NamedNodeMap class NamedNodeMapReadTestCase(TestCaseBase): def setUp(self): self.map = self.createDocument().createElement("foo")._get_attributes() def checkGetLength(self): checkLength(self.map, 0) def checkGetNamedItem(self): self.assert_(self.map.getNamedItem("uuu") is None) def checkRemoveNamedItem(self): self.assertRaises(xml.dom.NotFoundErr, self.map.removeNamedItem, "uuu") def checkItem(self): self.assert_(self.map.item(0) is None) def checkGetItem(self): try: self.map["uuu"] self.fail("expected KeyError to be raised") except KeyError: pass def checkGet(self): self.assertEqual(self.map.get("uuu", 5), 5) def checkHasKey(self): self.failIf(self.map.has_key("uuu")) def checkItems(self): self.assertEqual(self.map.items(), []) def checkKeys(self): self.assertEqual(self.map.keys(), []) def checkValues(self): self.assertEqual(self.map.values(), []) class NonemptyNamedNodeMapWriteTestCase(TestCaseBase): def setUp(self): self.map = self.createDocument().createElement("foo")._get_attributes() self.attribute = self.document.createAttribute("attrName") self.attribute.value = "attrValue" self.map.setNamedItem(self.attribute) def checkRemoveNonexistentNamedItem(self): self.assertRaises(xml.dom.DOMException, self.map.removeNamedItem, "uuu") def checkRemoveNamedItem(self): attribute2 = self.document.createAttribute("attrName2") self.map.setNamedItem(attribute2) attrOut = self.map.removeNamedItem("attrName2") self.assert_(isSameNode(attrOut, attribute2)) def checkRemoveNamedItemNotFound(self): self.assertRaises(xml.dom.NotFoundErr, self.map.removeNamedItem, "bogus") def checkGetLength(self): checkLength(self.map, 1) def checkGetNamedItem(self): self.assert_(isSameNode(self.attribute, self.map.getNamedItem("attrName"))) def checkGetNonexistentNamedItem(self): self.assert_(self.map.getNamedItem("uuu") is None) def checkItem(self): self.assert_(isSameNode(self.map.item(0), self.attribute)) self.assert_(isSameNode(self.attribute, self.map.item(0))) def checkGetNonexistentItem(self): try: self.map["uuu"] self.fail("expected KeyError to be raised") except KeyError: pass def checkGetItem(self): self.assert_(isSameNode(self.attribute, self.map["attrName"])) def checkGet(self): self.assert_(isSameNode(self.attribute, self.map.get("attrName"))) def checkHasKey(self): self.assert_(self.map.has_key("attrName")) self.assert_(not self.map.has_key("uuu")) def checkItems(self): key, node = self.map.items()[0] self.assertEqual(key, "attrName") self.assert_(isSameNode(self.attribute, node)) def checkKeys(self): self.assertEqual(self.map.keys(), ["attrName"]) def checkValues(self): L = [] for attr in self.map.values(): L.append(attr.value) self.assertEqual(L, ["attrValue"], "bad values list: %s" % `L`) def checkSetNamedItem(self): newAttr = self.document.createAttribute('someAttr') newAttr.value = 'spam' retVal = self.map.setNamedItem(newAttr) self.assert_( retVal is None, "setNamedItem returned %s" % repr(retVal)) checkLength(self.map, 2) self.assert_( isSameNode(self.map.getNamedItem('someAttr'), newAttr), "setNamedItem store seems to have failed, can't retrieve.") def checkSetNamedItemReplacingExistingNode(self): newAttr = self.document.createAttribute('someAttr') self.map.setNamedItem(newAttr) anotherAttr = self.document.createAttribute('someAttr') anotherAttr.value = 'eggs' retVal = self.map.setNamedItem(newAttr) self.assert_(retVal is not None, "setNamedItem returned None") self.assert_(isSameNode(retVal, newAttr), "setNamedItem didn't return replaced Node.") checkLength(self.map, 2) def checkSetNamedItemWrongDocument(self): newDoc = self.implementation.createDocument(None, 'foo', None) foreignAttr = newDoc.createAttribute('someAttr') self.assertRaises(xml.dom.WrongDocumentErr, self.map.setNamedItem, foreignAttr) def checkSetNamedItemAlreadyInUse(self): el = self.document.createElement('someElement') attr = self.document.createAttribute('someAttribute') el.setAttributeNode(attr) self.assertRaises(xml.dom.InuseAttributeErr, self.map.setNamedItem, attr) def checkSetNamedItemHierarchyRequestErr(self): # See DOM erratum core-4. textNode = self.document.createTextNode('text node') self.assertRaises(xml.dom.HierarchyRequestErr, self.map.setNamedItem, textNode) cases = buildCases(__name__, 'Core', None)