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

Side by Side Diff: tests/test_packagerWebExt.py

Issue 29501558: Issue 5383 - Add tests for the Chrome and Firefox packagers (Closed)
Patch Set: Asserting PNGs Created Sept. 19, 2017, 10:02 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 json
8 import re
9 from struct import unpack
10
11 import pytest
12 from Crypto.Hash import SHA
13 from Crypto.PublicKey import RSA
14 from Crypto.Signature import PKCS1_v1_5
15
16
17 from buildtools import packager, packagerChrome
18 from buildtools.tests.tools import (DirContent, ZipContent, copy_metadata,
19 run_webext_build, assert_manifest_content,
20 assert_all_locales_present, locale_files)
21 from buildtools.tests.conftest import ALL_LANGUAGES
22
23
24 LOCALES_MODULE = {
25 'test.Foobar': {
26 'message': 'Ensuring dict-copy from modules for $domain$',
27 'description': 'test description',
28 'placeholders': {'content': '$1', 'example': 'www.adblockplus.org'}
29 }
30 }
31
32 DTD_TEST = ('<!ENTITY access.key "access key(&amp;a)">'
33 '<!ENTITY ampersand "foo &amp;-bar">')
34
35 PROPERTIES_TEST = 'description=very descriptive!'
36
37
38 @pytest.fixture
39 def gecko_import(tmpdir):
40 tmpdir.mkdir('_imp').mkdir('en-US').join('gecko.dtd').write(DTD_TEST)
41
42
43 @pytest.fixture
44 def locale_modules(tmpdir):
45 mod_dir = tmpdir.mkdir('_modules')
46 lang_dir = mod_dir.mkdir('en-US')
47 lang_dir.join('module.json').write(json.dumps(LOCALES_MODULE))
48 lang_dir.join('unit.properties').write(json.dumps(PROPERTIES_TEST))
49
50
51 @pytest.fixture
52 def icons(srcdir):
53 icons_dir = srcdir.mkdir('icons')
54 for filename in ['abp-16.png', 'abp-19.png', 'abp-53.png']:
55 shutil.copy(
56 os.path.join(os.path.dirname(__file__), filename),
57 os.path.join(str(icons_dir), filename),
58 )
59
60
61 @pytest.fixture
62 def all_lang_locales(tmpdir):
63 return locale_files(ALL_LANGUAGES, '_locales', tmpdir)
64
65
66 @pytest.fixture
67 def chrome_metadata(tmpdir):
68 filename = 'metadata.chrome'
69 copy_metadata(filename, tmpdir)
70
71
72 @pytest.fixture
73 def gecko_webext_metadata(tmpdir, chrome_metadata):
74 filename = 'metadata.gecko-webext'
75 copy_metadata(filename, tmpdir)
76
77
78 @pytest.fixture
79 def keyfile(tmpdir):
80 """Test-privatekey for signing chrome release-package"""
81 return os.path.join(os.path.dirname(__file__), 'chrome_rsa.pem')
82
83
84 @pytest.fixture
85 def lib_files(tmpdir):
86 files = packager.Files(['lib'], set())
87 files['ext/a.js'] = 'var bar;'
88 files['lib/b.js'] = 'var foo;'
89
90 tmpdir.mkdir('lib').join('b.js').write(files['lib/b.js'])
91 tmpdir.mkdir('ext').join('a.js').write(files['ext/a.js'])
92
93 return files
94
95
96 def assert_gecko_locale_conversion(package):
97 locale = json.loads(package.read('_locales/en_US/messages.json'))
98
99 assert locale.get('test_Foobar', {}) == LOCALES_MODULE['test.Foobar']
100 assert locale.get('access_key', {}) == {'message': 'access key'}
101 assert locale.get('ampersand', {}) == {'message': 'foo -bar'}
102 assert locale.get('_description', {}) == {'message': 'very descriptive!"'}
103
104
105 def assert_convert_js(package, excluded=False):
106 libfoo = package.read('lib/foo.js')
107
108 assert 'var bar;' in libfoo
109 assert 'require.modules["ext_a"]' in libfoo
110
111 assert ('var foo;' in libfoo) != excluded
112 assert ('require.modules["b"]' in libfoo) != excluded
113
114
115 def assert_devenv_scripts(package, devenv):
116 manifest = json.loads(package.read('manifest.json'))
117 filenames = package.namelist()
118 scripts = [
119 'ext/common.js',
120 'ext/background.js',
121 ]
122
123 if devenv:
124 assert 'qunit/index.html' in filenames
125 assert 'devenvPoller__.js' in filenames
126 assert 'devenvVersion__' in filenames
127
128 assert '../ext/common.js' in package.read('qunit/index.html')
129 assert '../ext/background.js' in package.read('qunit/index.html')
130
131 assert set(manifest['background']['scripts']) == set(
132 scripts + ['devenvPoller__.js']
133 )
134 else:
135 assert 'qunit/index.html' not in filenames
136
137 assert set(manifest['background']['scripts']) == set(scripts)
138
139
140 def assert_base_files(package):
141 filenames = set(package.namelist())
142
143 assert 'bar.json' in filenames
144 assert 'manifest.json' in filenames
145 assert 'lib/foo.js' in filenames
146 assert 'foo/logo_50.png' in filenames
147 assert 'icons/logo_150.png' in filenames
148
149
150 def assert_chrome_signature(filename, keyfile):
151 with open(filename, 'r') as fp:
152 content = fp.read()
153
154 _, _, l_pubkey, l_signature = unpack('<4sIII', content[:16])
155 signature = content[16 + l_pubkey: 16 + l_pubkey + l_signature]
156
157 digest = SHA.new()
158 with open(keyfile, 'r') as fp:
159 rsa_key = RSA.importKey(fp.read())
160
161 signer = PKCS1_v1_5.new(rsa_key)
162
163 digest.update(content[16 + l_pubkey + l_signature:])
164 assert signer.verify(digest, signature)
165
166
167 def assert_locale_upfix(package):
168 translations = [
169 json.loads(package.read('_locales/{}/messages.json'.format(lang)))
170 for lang in ALL_LANGUAGES
171 ]
172
173 manifest = package.read('manifest.json')
174
175 # Chrome Web Store requires descriptive translations to be present in
176 # every language.
177 for match in re.finditer(r'__MSG_(\S+)__', manifest):
178 name = match.group(1)
179
180 for other in translations[1:]:
181 assert translations[0][name]['message'] == other[name]['message']
182
183
184 @pytest.mark.usefixtures(
185 'all_lang_locales',
186 'locale_modules',
187 'gecko_import',
188 'icons',
189 'lib_files',
190 'chrome_metadata',
191 'gecko_webext_metadata',
192 )
193 @pytest.mark.parametrize('platform', ['chrome', 'gecko-webext'])
194 @pytest.mark.parametrize('dev_build_release,buildnum', [
195 ('build', None),
196 ('build', '1337'),
197 ('devenv', None),
198 pytest.param('devenv', '1337', marks=pytest.mark.xfail),
199 ('release', None),
200 ('release', '1337'),
201 ])
202 def test_build_webext(platform, dev_build_release, keyfile, tmpdir, srcdir,
203 buildnum, capsys):
204 release = dev_build_release == 'release'
205 devenv = dev_build_release == 'devenv'
Sebastian Noack 2017/09/20 00:58:02 There are actually 3 scenarios: 1. build.py -t {c
tlucas 2017/09/20 08:52:51 You are correct about #1 and #3 - however, there i
Sebastian Noack 2017/09/20 21:36:09 Sorry, I misinterpreted the logic here. If I under
206
207 if platform == 'chrome' and release:
208 key = keyfile
209 else:
210 key = None
211
212 filenames = {
213 'gecko-webext': 'adblockplusfirefox-1.2.3{}.{}',
Vasily Kuznetsov 2017/09/19 17:52:27 I would probably just use the structure of `extens
tlucas 2017/09/20 08:52:52 Done.
214 'chrome': 'adblockpluschrome-1.2.3{}.{}'
215 }
216
217 extensions = {
218 'gecko-webext': {
219 True: 'xpi',
220 False: 'xpi',
221 },
222 'chrome': {
223 True: 'crx',
224 False: 'zip',
225 },
226 }
227
228 expected_manifest = os.path.join(
229 os.path.dirname(__file__),
230 'expecteddata',
231 'manifest_{}_{}_{}.json'.format(platform, dev_build_release, buildnum),
232 )
233
234 run_webext_build(platform, dev_build_release, srcdir, packagerChrome,
235 buildnum=buildnum, keyfile=key)
236
237 # The makeIcons() in packagerChrome.py should warn about non-square
238 # icons via stderr.
239 out, err = capsys.readouterr()
240 assert 'icon should be square' in err
241
242 if devenv:
243 content_class = DirContent
244 out_file_path = os.path.join(str(srcdir), 'devenv.' + platform)
245 else:
246 content_class = ZipContent
247
248 if release:
249 add_version = ''
250 else:
251 add_version = '.' + (buildnum or '0')
252 extension = extensions[platform][release]
253
254 out_file = filenames[platform].format(add_version, extension)
255
256 out_file_path = os.path.abspath(os.path.join(
257 os.path.dirname(__file__), os.pardir, out_file))
258 assert os.path.exists(out_file_path)
259
260 if release and platform == 'chrome':
261 assert_chrome_signature(out_file_path, keyfile)
262
263 with content_class(out_file_path) as package:
264 assert_manifest_content(
265 package.read('manifest.json'), expected_manifest
266 )
267 assert_base_files(package)
268 assert_devenv_scripts(package, devenv)
269 assert_all_locales_present(package, '_locales')
270 assert_gecko_locale_conversion(package)
271 assert_convert_js(package, platform == 'gecko-webext')
272
273 if platform == 'chrome':
274 assert_locale_upfix(package)
OLDNEW
« tests/README.md ('K') | « tests/test_packagerEdge.py ('k') | tests/tools.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld