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

Side by Side Diff: tests/test_packagerChrome.py

Issue 29501558: Issue 5383 - Add tests for the Chrome and Firefox packagers (Closed)
Patch Set: Addressing pep8 error from last review Created Aug. 11, 2017, 12:12 p.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 re
6 import json
7 import zipfile
8
9 from xml.etree import ElementTree
10
11 import pytest
12
13 from buildtools import packager, packagerChrome
14 from buildtools.tests.tools import copy_metadata
15
16 ICON_SIZES = [32, 48, 64, 256, 53]
17
18 MINIMUM_MANIFEST = [
Vasily Kuznetsov 2017/08/11 16:46:02 Would it perhaps be more elegant to make this a di
tlucas 2017/08/14 14:23:16 Done.
19 ('manifest_version', 2),
20 ('author', 'Eyeo GmbH'),
21 ('permissions', [
22 'tabs',
23 '<all_urls>',
24 'contextMenus',
25 'webRequest',
26 'webRequestBlocking',
27 'webNavigation',
28 'storage',
29 'unlimitedStorage',
30 'notifications',
31 ]),
32 ('minimum_chrome_version', '49.0'),
33 ('minimum_opera_version', '36.0'),
34 ('devtools_page', 'devtools.html'),
35 ('description', '__MSG_description__'),
36 ('default_locale', 'en_US'),
37 ('short_name', '__MSG_name__'),
38 ('storage', {'managed_schema': 'managed-storage-schema.json'}),
39 ('options_ui', {'open_in_tab': True, 'page': 'options.html'}),
40 ]
41
42
43 @pytest.fixture
44 def chrome_metadata(tmpdir):
45 filename = 'metadata.chrome'
46 copy_metadata(filename, tmpdir)
47
48 return packager.readMetadata(str(tmpdir), 'chrome')
Vasily Kuznetsov 2017/08/11 16:46:01 Could we just read the metadata from the original
tlucas 2017/08/14 14:23:17 It doesn't, since the underlying functions almost
49
50
51 @pytest.fixture
52 def gecko_webext_metadata(tmpdir, chrome_metadata):
53 filename = 'metadata.gecko-webext'
54 copy_metadata(filename, tmpdir)
55
56 # gecko-webext metadata inherits from chrome metadata, assure existence
57 assert chrome_metadata is not None
Vasily Kuznetsov 2017/08/11 16:46:02 Do you really need this assert? Seems like if this
tlucas 2017/08/14 14:23:17 As mentioned above, using the original-file won't
58
59 return packager.readMetadata(str(tmpdir), 'gecko-webext')
60
61
62 @pytest.fixture
63 def icons(tmpdir):
64 """Valid .png files for testing make_icons"""
65 from PIL import Image
66
67 paths = []
68 icon_dir = tmpdir.mkdir('tmp_icons')
69
70 for size in ICON_SIZES:
71 img_path = str(icon_dir.join('abp-{}.png'.format(size)))
72 img = Image.new('1', (size, size if size != 53 else size + 1), 0)
73 img.save(img_path)
74 paths.append(img_path)
75
76 return paths
77
78
79 @pytest.fixture
80 def keyfile(tmpdir):
81 """Test-privatekey for signing files"""
82
83 content = """-----BEGIN RSA PRIVATE KEY-----
Vasily Kuznetsov 2017/08/11 16:46:01 What do you think about putting this into a keyfil
tlucas 2017/08/14 14:23:17 Done.
84 MIIEowIBAAKCAQEA0P06DVxOWZ97cvBZWz7DV0DYTFF7Cdrxnu/sCxnHp8IEq+sM
85 rqodp2i8eTsddnthTnA93wiFiFXz6/9liQKrSBtogEGG2tmrT73jy5mdOehm7h6m
86 Ujy6wLuZQiuY/RWJ6453/0H3bKCA8IlIdU8Pkkn5DJWH+YiiSUD01U5ZMLn8m/+O
87 D/r9CLsgWoJV4VCXyzMItcc8hlRbiSe/3DQmZOPbF0Bd1Jv6lNA4RG0U8oA6q5s1
88 5w3n//FjNOreVocyxgWWWGk/awlkJme1xn3yB3yh74b51FHsr9vhiTjcs+QNO1BS
89 9fA/oavzDOs1Q4fLnTbKn6Jlg5OAjWtiq4vjSQIDAQABAoH/fojTnUNGLP1iwTTE
90 5Xoay7l3PL4YwN7PbGvXfuEdAXV3Xp/yDc7yJWpEsyIXtKT/RX6v91oxf1qLVVhN
91 Iad8DSyLGRyTie5Aywct5RgdGfKcX5AvI5uhdxAeuvGqr5Fa8ERSYzqNlDeZ2glE
92 1cIIq4oeQIBI08zmdXPeyUemuNjK8TEWKOTMOjDLhav/DMviI1cvqp5VIh3RseMr
93 1dwprXe0/LWuCh0BrCZZNH/0smd2etXEq06RhgnE2sZkowktNhSgc2pqls92FT88
94 ObjI/jRXf6OwK7HxIJ1tMKlk/VCvAI2PNWi6E7IZbqN7Rg7859uWybGZkP/h1Qf5
95 fRitAoGBAOJnP3kgavnrUJ482R8MNjOwtqbLf4obS5Y/olOHUi+mu2x+EwxgDtaE
96 sXeMjoIAuZvDoAIG0Hn7+J5ZSYkXT9aXQy/odVWDIpFNFFXNFnS73sAWay/FsMJc
97 NvgbbWJk9fCq23O7ihuSkfM+zh8dAZoHzV4aw3DsZj37yzuTmTJbAoGBAOxPM6Wy
98 fENT8ECGl9d/j8QBV4LvjrfIbz/RcCxgZHG50ELnxCo7FiYRg3d2DjR6Q+EpjclX
99 CC+IwCGGf+RBz53WzJPOBkz+plPZzrhhhtpBuWgegeF+TmYT9pPd9XRHJs5qFCak
100 J3xxgBur3NDtejNLWBc4bgFfrv8hdYeuIKorAoGBAJplWNbssadvv1G6I0NWG5yS
101 lW0X+Akh5iE3kiaucPDIHqa1L55P366RXUku1Hx5rBo6hWL8bK3TlM/ACjLwb+Ti
102 0NHaEDJZtHgsfYKp0veWqyiJ4Vz5zzosktwOMEFaopIWooPBUETPZrLgkMaNDGuT
103 iIz1aXUX8f2xOf6OAHpjAoGBAMNqq9c2xrQW0fNKWn8HKih4w5mv6WHqCrXHyO+p
104 tualNqhdaUdTHXnVudYsdorHISMubeY2ZrqIZ/pRc6mbEsoAO6VvFp7NZ1aoI98u
105 J4qOF3kW4WlMPiEEGUEmqDjELj88UfWygkTSx5Iaibzs5cVNZUeujqnsKpcpYDwX
106 r0OJAoGBAIWgnx72WjcFmL1kgOu2kH8tH5+cIAb/THX8lnCulQIlxss8n26NMMDa
107 Kmh5gC2SOAe92cXG6jCYHZqZtl5gM6xGky1B9j7TDrXVPj+QDcItCuNN4zrdtiah
108 US0KNMZKEMjxsaaMDPHj/bP9ULLbMHvtfvt4EnBQoVCDSZdfeBvZ
109 -----END RSA PRIVATE KEY-----"""
110
111 keyfile_path = str(tmpdir.mkdir('rsakey').join('keyfile'))
112
113 with open(keyfile_path, 'wb') as key_fp:
114 key_fp.write(content)
115
116 return keyfile_path
117
118
119 @pytest.mark.parametrize('release', [True, False])
120 @pytest.mark.parametrize('devenv', [True, False])
121 @pytest.mark.parametrize('ext_type', ['chrome', 'gecko-webext'])
122 def test_create_manifest(srcdir, base_files, release, devenv, ext_type,
123 chrome_metadata, gecko_webext_metadata):
124
125 if ext_type == 'chrome':
126 metadata = chrome_metadata
127 else:
128 metadata = gecko_webext_metadata
129
130 version = packager.getBuildVersion(str(srcdir), metadata, release)
131 params = {
132 'type': ext_type,
133 'baseDir': str(srcdir),
134 'releaseBuild': release,
135 'version': version,
136 'devenv': devenv,
137 'metadata': metadata,
138 }
139 manifest = json.loads(packagerChrome.createManifest(params, base_files))
140
141 expected_values = MINIMUM_MANIFEST + [
Vasily Kuznetsov 2017/08/11 16:46:01 What do you think about just doing these checks di
tlucas 2017/08/14 14:23:16 Looks definitely cleaner, done.
142 ('name', '__MSG_name_' + ('devbuild__' if not release else '_')),
143 ('version', '1.2.3' + ('.0' if not release else '')),
144 ]
145
146 if ext_type == 'gecko-webext':
147 expected_values += [
148 ('applications', {
149 'gecko': {
150 'id': '{d10d0bf8-f5b5-c8b4-a8b2-2b9879e08c5d}',
151 'strict_min_version': '50.0',
152 }
153 })
154 ]
155 if not release:
156 expected_values[-1][1]['gecko'].update({
157 'update_url': ''.join((
158 'https://downloads.adblockplus.org/devbuilds/',
159 'adblockplusfirefox/updates.json'))
160 })
161
162 for key, value in expected_values:
163 assert manifest.get(key, None) == value
164
165
166 def test_sign_binary(base_files, keyfile):
167 from Crypto.Hash import SHA
168 from Crypto.PublicKey import RSA
169 from Crypto.Signature import PKCS1_v1_5
170
171 digest = SHA.new()
172
173 signature = packagerChrome.signBinary(base_files.zipToString(), keyfile)
174
175 with open(keyfile, 'r') as fp:
176 rsa_key = RSA.importKey(fp.read())
177
178 signer = PKCS1_v1_5.new(rsa_key)
179
180 digest.update(base_files.zipToString())
181 assert signer.verify(digest, signature)
182
183
184 def test_get_public_key(keyfile):
185 expected = (
186 '30820122300d06092a864886f70d01010105000382010f003082010a0282010100d0'
187 'fd3a0d5c4e599f7b72f0595b3ec35740d84c517b09daf19eefec0b19c7a7c204abeb'
188 '0caeaa1da768bc793b1d767b614e703ddf08858855f3ebff658902ab481b68804186'
189 'dad9ab4fbde3cb999d39e866ee1ea6523cbac0bb99422b98fd1589eb8e77ff41f76c'
190 'a080f08948754f0f9249f90c9587f988a24940f4d54e5930b9fc9bff8e0ffafd08bb'
191 '205a8255e15097cb3308b5c73c86545b8927bfdc342664e3db17405dd49bfa94d038'
192 '446d14f2803aab9b35e70de7fff16334eade568732c6059658693f6b09642667b5c6'
193 '7df2077ca1ef86f9d451ecafdbe18938dcb3e40d3b5052f5f03fa1abf30ceb354387'
194 'cb9d36ca9fa2658393808d6b62ab8be3490203010001')
195
196 publickey = packagerChrome.getPublicKey(keyfile)
197 assert publickey.encode('hex') == expected
Vasily Kuznetsov 2017/08/11 16:46:01 I just had an idea, what if we just take an MD5 or
tlucas 2017/08/14 14:23:16 Good point, i started using SHA-hashes in the othe
198
199
200 @pytest.mark.usefixtures('chrome_metadata')
201 @pytest.mark.parametrize('devenv', [True, False])
202 def test_get_package_files(srcdir, devenv):
203 filenames = [
204 'foo.html',
205 'foo.js',
206 'foo.json',
207 'foo.xml',
208 ]
209
210 for filename in filenames:
211 srcdir.join(filename).write('', ensure=True)
212
213 params = {
214 'baseDir': str(srcdir),
215 'devenv': devenv,
216 }
217
218 files = packagerChrome.getPackageFiles(params)
219
220 assert ('qunit' in files) == devenv
221
222 for expected in ['icons', 'ui', 'skin', 'ext', '_locales', 'lib',
223 'jquery-ui'] + [name for name in filenames]:
224 assert expected in files
225
226
227 def test_make_icons(icons, capsys):
228 files = packager.Files(set(), set())
229 for path in icons:
230 files[path] = open(path, 'r').read()
231 result = packagerChrome.makeIcons(files, icons)
232
233 out, err = capsys.readouterr()
234
235 assert 'should be square' in err
236 assert set(result) == set(ICON_SIZES)
237
238
239 def test_create_script_page(srcdir, chrome_metadata):
240 params = {'metadata': chrome_metadata}
241
242 template = packagerChrome.createScriptPage(
243 params, 'testIndex.html.tmpl', ('general', 'testScripts')
244 )
245
246 template_scripts = {elem.attrib['src'] for elem in
247 ElementTree.fromstring(template).iter('script')}
248
249 for src in chrome_metadata.get('general', 'testScripts').split():
250 assert src in template_scripts
251
252
253 def test_convert_js(srcdir, base_files, chrome_metadata):
254 params = {
255 'type': 'chrome',
256 'metadata': chrome_metadata,
257 }
258
259 packagerChrome.convertJS(params, base_files)
260 source = base_files['lib/foo.js']
261
262 assert 'var foo;' in source
263 assert 'var bar;' in source
264
265
266 def test_to_json():
267 data = {'bar': ['foo', 'foobar', 1, True]}
268 data_json = packagerChrome.toJson(data)
269
270 assert data_json.endswith('\n')
271 json.loads(data_json)
Vasily Kuznetsov 2017/08/11 16:46:01 Maybe also compare it to the original?
tlucas 2017/08/14 14:23:17 Done.
272
273
274 def test_import_gecko_locales(tmpdir, srcdir, base_files, chrome_metadata):
275 version = packager.getBuildVersion(str(srcdir), chrome_metadata, False)
276 params = {
277 'type': 'chrome',
278 'baseDir': str(srcdir),
279 'releaseBuild': False,
280 'version': version,
281 'devenv': False,
282 'metadata': chrome_metadata,
283 }
284
285 data = {'name': 'foo', 'name_devbuild': 'bar'}
286
287 t_dir = tmpdir.mkdir('_trans').mkdir('en-US')
288 t_dir.join('test.properties').write(
289 '\n'.join('{}={}'.format(k, v) for k, v in data.items()))
290
291 packagerChrome.importGeckoLocales(params, base_files)
292 trans_data = json.loads(base_files['_locales/en_US/messages.json'])
293
294 for key, value in data.items():
295 assert trans_data.get('test_' + key, {}).get('message', '') == value
296
297
298 def test_fix_translations_for_cws(base_files):
299 base_files['_locales/de/messages.json'] = packagerChrome.toJson({})
300 base_files['manifest.json'] = packagerChrome.toJson(dict(MINIMUM_MANIFEST))
301 packagerChrome.fixTranslationsForCWS(base_files)
302
303 ger_messages = json.loads(base_files['_locales/de/messages.json'])
304 eng_messages = json.loads(base_files['_locales/en_US/messages.json'])
305
306 # Check for inserted translations, none were present in 'de' beforehand
307 for match in re.finditer(r'__MSG_(\S+)__', base_files['manifest.json']):
308 name = match.group(1)
309 assert ger_messages[name]['message'] == eng_messages[name]['message']
310
311 # CWS enforces max-lengths on string
312 assert len(ger_messages['description']['message']) <= 132
313 assert len(ger_messages['name']['message']) <= 12
314
315
316 @pytest.mark.usefixtures('base_files', 'gecko_webext_metadata',
317 'chrome_metadata')
318 @pytest.mark.parametrize('release', [True, False])
319 @pytest.mark.parametrize('devenv', [True, False])
320 @pytest.mark.parametrize('ext_type', ['chrome', 'gecko-webext'])
321 @pytest.mark.parametrize('key', [True, False])
322 def test_create_build(srcdir, tmpdir, release, devenv, ext_type,
323 key, keyfile):
324
325 basefiles = [
326 'manifest.json',
327 'lib/foo.js',
328 'foo/logo_50.png',
329 '_locales/en_US/messages.json',
330 '_locales/en-US/test.properties',
331 'logo_44.png',
332 'icons/logo_150.png',
333 ]
334
335 out_file = str(tmpdir.join('out'))
336
337 packagerChrome.createBuild(
338 outFile=out_file,
339 baseDir=str(srcdir),
340 type=ext_type,
341 releaseBuild=release,
342 keyFile=keyfile if key else None,
343 devenv=devenv)
344
345 with zipfile.ZipFile(out_file, 'r') as zipfp:
346 zipfp.testzip()
347
348 filenames = [zipinfo.filename for zipinfo in zipfp.infolist()]
349 for filename in basefiles if not devenv else basefiles + [
350 'devenvPoller__.js',
351 'devenvVersion__',
352 'qunit/index.html',
353 ]:
354 assert filename in filenames
OLDNEW

Powered by Google App Engine
This is Rietveld