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

Side by Side Diff: tests/tools.py

Issue 29501558: Issue 5383 - Add tests for the Chrome and Firefox packagers (Closed)
Patch Set: Completely purge PIL / Pillow, added edge-extension fixture / assert Created Sept. 11, 2017, 8:43 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
OLDNEW
(Empty)
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
3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5 import os
6 import shutil
7 import zipfile
8 import json
9
10 from xml.etree import ElementTree
11
12 from buildtools.packagerChrome import defaultLocale
13 from buildtools.tests.conftest import MESSAGES_EN_US
14
15
16 ALL_LANGUAGES = ['en_US', 'de', 'it']
17
18
19 class Content(object):
20 """Base class for a unified ZipFile / Directory interface.
21
22 Base class for providing a unified context manager interface for
23 accessing files. This class is subclassed by ZipContent and DirContent,
24 which provide the additional methods "namelist()" and "read(path)".
25 """
26
27 def __enter__(self):
28 return self
29
30 def __exit__(self, exc_type, exc_value, exc_tb):
31 self._close()
32
33
34 class ZipContent(Content):
35 """Provides a unified context manager for ZipFile access.
36
37 Inherits the context manager API from Content.
38 If desired, the specified ZipFile is deleted on exiting the manager.
39 """
40
41 def __init__(self, zip_path, delete_on_close=True):
42 """Constructor of ZipContent handling the file <zip_path>.
43
44 The parameter 'delete_on_close' causes the context manager to
45 delete the handled ZipFile (specified by zip_path) if set to
46 True (default).
47 """
48
49 self._zip_path = zip_path
50 self._zip_file = zipfile.ZipFile(zip_path)
51 self._delete_on_close = delete_on_close
52 super(ZipContent, self).__init__()
53
54 def _close(self):
55 self._zip_file.close()
56 if self._delete_on_close:
57 # if specified, delete the handled file
58 os.remove(self._zip_path)
59
60 def namelist(self):
61 return self._zip_file.namelist()
62
63 def read(self, path):
64 return self._zip_file.read(path)
65
66
67 class DirContent(Content):
68 """Provides a unified context manager for directory access.
69
70 Inherits the context managet API from Content.
71 """
72
73 def __init__(self, path):
74 """Constructor of DirContent handling <path>.
75 """
76
77 self._path = path
78 super(DirContent, self).__init__()
79
80 def _close(self):
81 pass
82
83 def namelist(self):
84 """Generate a list of filenames, as expected from ZipFile.nameslist().
85 """
86
87 result = []
88 for parent, directories, files in os.walk(self._path):
89 for filename in files:
90 file_path = os.path.join(parent, filename)
91 rel_path = os.path.relpath(file_path, self._path)
92 result.append(rel_path)
93 return result
94
95 def read(self, path):
96 content = None
97 with open(os.path.join(self._path, path)) as fp:
98 content = fp.read()
99 return content
100
101
102 def copy_metadata(filename, tmpdir):
103 """Copy the used metadata to the used temporary directory."""
104 path = os.path.join(os.path.dirname(__file__), filename)
105 destination = str(tmpdir.join(filename))
106 shutil.copy(path, destination)
107
108
109 def run_webext_build(ext_type, build_type, srcdir, packager_module,
110 keyfile=None):
111 """Run a build process
112
113 Run a desired build process without unintenionally invoking the
114 releaseAutomation.
115 """
116 from buildtools.build import processArgs
117 args = ['build.py', '-t', ext_type, build_type]
118
119 if keyfile:
120 args += ['-k', keyfile]
121
122 if not build_type == 'release':
123 processArgs(str(srcdir), args)
124 else:
125 # We don't want to accidentaly run releaseAutomation in tests
126 packager_module.createBuild(
127 str(srcdir),
128 ext_type,
129 releaseBuild=True,
130 keyFile=keyfile,
131 )
132
133
134 def locale_files(languages, rootfolder, srcdir):
135 """Generate example locales.
136
137 languages: tuple, list or set of languages to include
138 rootdir: folder-name to create the locale-folders in
139 """
140 for lang in languages:
141 subfolders = rootfolder.split(os.pathsep) + [lang, 'messages.json']
142 json_file = srcdir.ensure(*subfolders)
143 if lang == defaultLocale:
144 json_file.write(MESSAGES_EN_US)
145 else:
146 json_file.write('{}')
147
148
149 def assert_all_locales_present(package, locales_path):
150 names = {x for x in package.namelist() if x.startswith(locales_path)}
151 assert names == {
152 os.path.join(locales_path, lang, 'messages.json')
153 for lang in ALL_LANGUAGES
154 }
155
156
157 def compare_xml(a, b):
158 def get_leafs_string(tree):
159 """Recursively build a string representing all leaf-nodes"""
160 root_str = '{}|{}|{}'.format(tree.tag, tree.tail, tree.text).strip()
161 result = []
162
163 if len(tree) > 0:
164 for subtree in tree:
165 for leaf in get_leafs_string(subtree):
166 result.append('{}__{}'.format(root_str, leaf))
167 else:
168 result.append(root_str)
169 return result
170
171 tree_a = ElementTree.fromstring(a)
172 tree_b = ElementTree.fromstring(b)
173
174 return set(get_leafs_string(tree_a)) == set(get_leafs_string(tree_b))
Vasily Kuznetsov 2017/09/11 12:50:08 This function and the one below seems to be only u
tlucas 2017/09/12 11:32:12 Acknowledged.
175
176
177 def compare_json(a, b):
Vasily Kuznetsov 2017/09/11 12:50:08 It seems like this function essentially compares t
tlucas 2017/09/12 11:32:11 I'm not sure if it would be a good idea to just ig
Sebastian Noack 2017/09/12 21:55:26 I agree, turning lists into sets when comparing th
tlucas 2017/09/13 13:43:25 Agreed - i came up with a different solution, plea
178 def get_leafs_string(obj):
179 """Recursively build a string representing all leaf-nodes"""
180 result = []
181 if isinstance(obj, list):
182 for item in obj:
183 for repr_str in get_leafs_string(item):
184 result.append(':,' + repr_str)
185 elif isinstance(obj, dict):
186 for k, v in obj.items():
187 for repr_str in get_leafs_string(v):
188 result.append('{}:{}'.format(k, repr_str))
189 else:
190 result = [str(obj)]
191
192 return result
193
194 tree_a = json.loads(a)
195 tree_b = json.loads(b)
196 return set(get_leafs_string(tree_a)) == set(get_leafs_string(tree_b))
197
198
199 def assert_manifest_content(manifest, expected_path):
200 extension = os.path.basename(expected_path).split('.')[-1]
201
202 with open(expected_path, 'r') as fp:
203 if extension == 'xml':
204 assert compare_xml(manifest, fp.read())
205 else:
206 assert compare_json(manifest, fp.read())
OLDNEW
« tests/test_packagerWebExt.py ('K') | « tests/test_packagerWebExt.py ('k') | tox.ini » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld