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