source: TI12-security/trunk/python/ndg.security.test/ndg/security/test/elementTreeC14n/testC14n.py @ 3237

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/python/ndg.security.test/ndg/security/test/elementTreeC14n/testC14n.py@3237
Revision 3237, 7.1 KB checked in by pjkersha, 12 years ago (diff)

Test new ElementTree Canonicalisation method. Tests created based on ...

Some tests still to complete. Nb. absence of init.py _ I don't this included in the ndg.security.test egg for the moment.

  • Property svn:executable set to *
Line 
1#!/usr/bin/env python
2"""NDG ElementTreeC14n class unit tests
3
4NERC Data Grid Project
5"""
6__author__ = "P J Kershaw"
7__date__ = "03/01/07"
8__copyright__ = "(C) 2007 STFC & NERC"
9__license__ = \
10"""This software may be distributed under the terms of the Q Public
11License, version 1.0 or later."""
12__contact__ = "P.J.Kershaw@rl.ac.uk"
13__revision__ = '$Id: ElementTreeC14nTest.py 3202 2008-01-11 13:42:34Z pjkersha $'
14
15import unittest
16import os
17import sys
18import getpass
19import traceback
20
21from StringIO import StringIO
22
23from elementtree import ElementTree as ET
24
25# Minidom based Canonicalization from ZSI for comparison
26from ZSI.wstools.c14n import Canonicalize
27
28xpdVars = os.path.expandvars
29jnPath = os.path.join
30
31class ElementTreeC14nTestCase(unittest.TestCase):
32   
33    def setUp(self):
34       
35        if 'NDGSEC_INT_DEBUG' in os.environ:
36            import pdb
37            pdb.set_trace()         
38
39
40    def test1UTF8DocEncoding(self):
41        xml = '<?xml version="1.0" encoding="UTF-8"?>\n<a/>\n'
42        elem = ET.fromstring(xml)
43        f = StringIO()
44        ET.ElementTree(elem).write_c14n(f)
45        c14n = f.getvalue()
46
47   
48    def test2NormalizedLineBreaks(self):
49        xml = '<?xml version="1.0" encoding="UTF-8"?>\r\n<a/>\r\n'
50        elem = ET.fromstring(xml)
51        f = StringIO()
52        ET.ElementTree(elem).write_c14n(f)
53        c14n = f.getvalue()
54        self.failIf('\r' in c14n, "Carriage return \r char found in c14n")
55
56   
57    def test3NormalizedAttrVals(self):
58        pass
59
60   
61    def test4CharAndParsedEntityRefsReplaced(self):
62        pass
63
64   
65    def test5CDATASectionsReplaced(self):
66        xml = \
67"""<?xml version="1.0" encoding="UTF-8"?>
68<script>
69<![CDATA[
70function matchwo(a,b)
71{
72if (a < b && a > 0) then
73   {
74   print("Match");
75   return 1;
76   }
77else
78   {
79   print('Different');
80   return 0;
81   }
82}
83]]>
84</script>
85"""
86        elem = ET.fromstring(xml)
87        f = StringIO()
88        ET.ElementTree(elem).write_c14n(f)
89        c14n = f.getvalue()
90       
91        self.failIf('CDATA' in c14n, "CDATA not removed, c14n = %s" % c14n)
92        self.failUnless('&lt;' in c14n,
93                        "Less than not converted, c14n = %s" % c14n)
94        self.failUnless('&gt;' in c14n, 
95                        "Greater than not converted, c14n = %s" % c14n)
96        self.failUnless('&amp;' in c14n, 
97                        "Ampersand not converted, c14n = %s" % c14n)
98
99        # Test for double quotes / apostrophes?
100       
101   
102    def test6XMLDeclAndDTDRemoved(self):
103        xmlDecl = '<?xml version="1.0" encoding="UTF-8"?>'
104        dtd = \
105"""<!DOCTYPE note [
106  <!ELEMENT note (to,from,heading,body)>
107  <!ELEMENT to      (#PCDATA)>
108  <!ELEMENT from    (#PCDATA)>
109  <!ELEMENT heading (#PCDATA)>
110  <!ELEMENT body    (#PCDATA)>
111]>
112"""
113        xml = \
114"""%s
115%s<a/>""" % (xmlDecl, dtd)
116
117        elem = ET.fromstring(xml)
118        f = StringIO()
119        ET.ElementTree(elem).write_c14n(f)
120        c14n = f.getvalue()
121        self.failIf('<?xml version="1.0" encoding="UTF-8"?>' in c14n, 
122                    "XML Declaration not removed")
123        self.failIf(dtd in c14n, "DTD not removed")
124
125   
126    def test7EmptyElemsConvertedStartEndPairs(self):
127        elem = ET.fromstring('<?xml version="1.0" encoding="UTF-8"?><a/>')
128        f = StringIO()
129        ET.ElementTree(elem).write_c14n(f)
130        c14n = f.getvalue()
131        self.failUnless(c14n == '<a></a>', "C14N = %s" % c14n)
132
133         
134    def test8WhitespaceNormalized(self):
135        '''...outside the document element and within start and end tags'''
136        dat = \
137'''        1 2
138  3'''
139 
140        xml = \
141'''<?xml version="1.0" encoding="UTF-8"?>
142<doc xmlns="http://example.com/default">
143  <a
144     a2="2"   a1="1"
145  >%s</a>
146</doc>
147
148''' % dat
149        elem = ET.fromstring(xml)
150        f = StringIO()
151        ET.ElementTree(elem).write_c14n(f)
152        c14n = f.getvalue()
153        self.failUnless('a1="1" a2="2"' in c14n, 
154                        "Expecting single space between attributes")
155        self.failUnless(dat in c14n, 
156                        "Expecting element content to be preserved")
157       
158        sub = xml[xml.find('<a'), xml.find('</a>')]
159        self.failIf('\n' in sub, 
160                    "Expecting removal of line breaks for 'a' element")
161     
162     
163    def test9WhitespaceInCharContentRetained(self):
164        '''Nb. excludes chars removed during line break normalization'''
165
166       
167    def test10AttrValDelimitersSet2DblQuotes(self):
168        xml = \
169"""<?xml version="1.0" encoding="UTF-8"?>
170  <b y:a1='1' a3='"3"'
171     xmlns:y='http://example.com/y' y:a2='2'/>
172"""
173
174        elem = ET.fromstring(xml)
175        f = StringIO()
176        ET.ElementTree(elem).write_c14n(f)
177        c14n = f.getvalue()
178        self.failIf("'" in c14n, 
179                    "Expecting removal of apostrophes C14N = %s" % c14n)
180
181   
182    def test11SpecialCharsReplaced(self):
183        '''i.e. within attribute values and character content'''
184       
185       
186    def test12SuperflousNSdeclsRemoved(self):
187        extraNS = "http://example.com/default"
188        xml = \
189"""<?xml version="1.0" encoding="UTF-8"?>
190<doc xmlns:x="http://example.com/x" xmlns="%s">
191  <b y:a1='1' xmlns="%s" a3='"3"'
192     xmlns:y='http://example.com/y' y:a2='2'/>
193</doc>""" % (extraNS, extraNS)
194
195        elem = ET.fromstring(xml)
196        f = StringIO()
197        ET.ElementTree(elem).write_c14n(f)
198        c14n = f.getvalue()
199        print c14n
200       
201        # Namespace should now only occur once...
202        self.failUnless(c14n.find(extraNS) == c14n.rfind(extraNS), 
203                    "Expecting removal of extra NS %s in output = %s" % \
204                    (extraNS, c14n))
205       
206       
207    def test13DefAttrsAdded2EachElem(self):
208        '''Implies reference to doc schema??'''
209
210   
211    def test14LexicographicOrderApplied(self):
212        '''... to namespace declarations and attributes of each element'''
213        xml = \
214'''<?xml version="1.0" encoding="UTF-8"?>
215<doc xmlns:x="http://example.com/x" xmlns="http://example.com/default">
216  <b y:a1='1' xmlns="http://example.com/default" a3='"3"'
217     xmlns:y='http://example.com/y' y:a2='2'/>
218</doc>
219'''
220
221    def test15CmpZSIc14n(self):
222        elem = ET.parse('./windows-ac.xml')
223        elem.write('./c14n-windows-ac.xml', method="c14n")
224        etC14n = open('./c14n-windows-ac.xml').read()
225       
226        from xml.dom.ext.reader import PyExpat
227        reader = PyExpat.Reader()
228        dom = reader.fromStream(open('./windows-ac.xml'))
229       
230        zsiC14n = Canonicalize(dom)
231        open('./zsi-c14n-windows-ac.xml', 'w').write(zsiC14n)
232        self.failUnless(etC14n == zsiC14n, "ZSI C14N output differs")
233       
234    def test16Cmplxmlc14n(self):
235        from StringIO import StringIO
236
237        elem = ET.parse('./windows-ac.xml')
238        etF = StringIO()
239        elem.write(etF, method="c14n")
240
241        from lxml import etree as lxmlET
242       
243        lxmlElem = lxmlET.parse('./windows-ac.xml')
244        lxmlETf = StringIO()
245        lxmlElem.write_c14n(lxmlETf)
246        open('./lxml-c14n-windows-ac.xml', 'w').write(lxmlETf.getvalue())
247        self.failUnless(etF.getvalue() == lxmlETf.getvalue(),
248                        "lxml C14N output differs")
249       
250       
251                                       
252if __name__ == "__main__":
253    unittest.main()
254
Note: See TracBrowser for help on using the repository browser.