Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: tests/test_packagerWebExt.py

Issue 29586561: Noissue - Make comparable_xml safe against ambiguous tags (Closed)
Patch Set: Created Oct. 23, 2017, 10:20 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # This Source Code Form is subject to the terms of the Mozilla Public 1 # This Source Code Form is subject to the terms of the Mozilla Public
2 # License, v. 2.0. If a copy of the MPL was not distributed with this 2 # License, v. 2.0. If a copy of the MPL was not distributed with this
3 # file, You can obtain one at http://mozilla.org/MPL/2.0/. 3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 4
5 import difflib 5 import difflib
6 import json 6 import json
7 import os 7 import os
8 import re 8 import re
9 import shutil 9 import shutil
10 import zipfile 10 import zipfile
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 files['ext/c.js'] = 'var this_is_c;' 233 files['ext/c.js'] = 'var this_is_c;'
234 234
235 tmpdir.mkdir('lib').join('b.js').write(files['lib/b.js']) 235 tmpdir.mkdir('lib').join('b.js').write(files['lib/b.js'])
236 ext_dir = tmpdir.mkdir('ext') 236 ext_dir = tmpdir.mkdir('ext')
237 ext_dir.join('a.js').write(files['ext/a.js']) 237 ext_dir.join('a.js').write(files['ext/a.js'])
238 ext_dir.join('c.js').write(files['ext/c.js']) 238 ext_dir.join('c.js').write(files['ext/c.js'])
239 239
240 return files 240 return files
241 241
242 242
243 def comparable_xml(xml):
244 """Create a nonambiguous representation of a given XML tree.
245
246 Note that this function is not safe against ambiguous tags
247 containing differently distributed children, e.g.:
248
249 '<a><b><c/></b><b><d/></b></a>'
250 vs.
251 '<a><b/><b><c/><d/></b></a>'
252
253 This is irrelevant for comparing the XML used by the tests of this
254 module.
255 """
256 def get_leafs_string(tree):
257 """Recursively build a string representing all xml leaf-nodes."""
258 root_str = '{}|{}|{}'.format(tree.tag, tree.tail, tree.text).strip()
259 result = []
260
261 if len(tree) > 0:
262 for subtree in tree:
263 for leaf in get_leafs_string(subtree):
264 result.append('{}__{}'.format(root_str, leaf))
265 for k, v in tree.attrib.items():
266 result.append('{}__{}:{}'.format(root_str, k, v))
267 else:
268 result.append(root_str)
269 return result
270
271 # XML data itself shall not be sorted, hence we can safely sort
272 # our string representations in order to produce a valid unified diff.
273 return sorted(get_leafs_string(ElementTree.fromstring(xml)))
274
275
276 def comparable_json(json_string): 243 def comparable_json(json_string):
277 """Create a nonambiguous representation of a given JSON string.""" 244 """Create a nonambiguous representation of a given JSON string."""
278 return json.dumps( 245 return json.dumps(
279 json.loads(json_string), sort_keys=True, indent=0 246 json.loads(json_string), sort_keys=True, indent=0
280 ).split('\n') 247 ).split('\n')
281 248
282 249
250 def comparable_xml(xml):
251 """Create a nonambiguous representation of a given XML tree."""
252 def strip(s):
253 if s is None:
254 return ''
255 return s.strip()
256
257 def transform(elt):
258 subs = sorted(transform(s) for s in elt)
259 attrs = tuple('{}={}'.format(k, v) for k, v in elt.attrib.items())
Vasily Kuznetsov 2017/10/23 12:48:20 Since you're doing a `comparable_json` later, we c
tlucas 2017/10/23 13:21:36 Good point - Done.
260 return (elt.tag, strip(elt.tail), strip(elt.text), attrs, subs)
261
262 return comparable_json(json.dumps(transform(ElementTree.fromstring(xml))))
Vasily Kuznetsov 2017/10/23 12:48:20 Its kind of a pity that we're doing `json.dumps` h
tlucas 2017/10/23 13:21:36 No, you are right - dumps(loads(dumps())) is defin
263
264
283 def assert_manifest_content(manifest, expected_path): 265 def assert_manifest_content(manifest, expected_path):
284 extension = os.path.basename(expected_path).split('.')[-1] 266 extension = os.path.basename(expected_path).split('.')[-1]
285 267
286 with open(expected_path, 'r') as fp: 268 with open(expected_path, 'r') as fp:
287 if extension == 'xml': 269 if extension == 'xml':
288 generated = comparable_xml(manifest) 270 generated = comparable_xml(manifest)
289 expected = comparable_xml(fp.read()) 271 expected = comparable_xml(fp.read())
290 else: 272 else:
291 generated = comparable_json(manifest) 273 generated = comparable_json(manifest)
292 expected = comparable_json(fp.read()) 274 expected = comparable_json(fp.read())
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
476 expected = os.path.join( 458 expected = os.path.join(
477 os.path.dirname(__file__), 459 os.path.dirname(__file__),
478 'expecteddata', 460 'expecteddata',
479 filename.format(name, ext), 461 filename.format(name, ext),
480 ) 462 )
481 463
482 assert_manifest_content( 464 assert_manifest_content(
483 package.read(os.path.join(folder, '{}.{}'.format(name, ext))), 465 package.read(os.path.join(folder, '{}.{}'.format(name, ext))),
484 expected, 466 expected,
485 ) 467 )
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld