blob: e2e85fd4b232adb797c7d0cd271c4879e73ead45 [file] [log] [blame]
Tao Bao481bab82017-12-21 11:23:09 -08001#
2# Copyright (C) 2018 The Android Open Source Project
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
16
17import copy
Tao Baoc7b403a2018-01-30 18:19:04 -080018import os
Tao Baofabe0832018-01-17 15:52:28 -080019import os.path
Tao Bao481bab82017-12-21 11:23:09 -080020import unittest
Tao Baoc7b403a2018-01-30 18:19:04 -080021import zipfile
Tao Bao481bab82017-12-21 11:23:09 -080022
23import common
Tao Bao04e1f012018-02-04 12:13:35 -080024import test_utils
Tao Bao481bab82017-12-21 11:23:09 -080025from ota_from_target_files import (
Tao Baoae5e4c32018-03-01 19:30:00 -080026 _LoadOemDicts, BuildInfo, GetPackageMetadata,
Tao Bao15a146a2018-02-21 16:06:59 -080027 GetTargetFilesZipForSecondaryImages,
28 GetTargetFilesZipWithoutPostinstallConfig,
Tao Bao69203522018-03-08 16:09:01 -080029 Payload, PayloadSigner, POSTINSTALL_CONFIG, PropertyFiles,
30 StreamingPropertyFiles, WriteFingerprintAssertion)
Tao Baofabe0832018-01-17 15:52:28 -080031
32
Tao Baof7140c02018-01-30 17:09:24 -080033def construct_target_files(secondary=False):
34 """Returns a target-files.zip file for generating OTA packages."""
35 target_files = common.MakeTempFile(prefix='target_files-', suffix='.zip')
36 with zipfile.ZipFile(target_files, 'w') as target_files_zip:
37 # META/update_engine_config.txt
38 target_files_zip.writestr(
39 'META/update_engine_config.txt',
40 "PAYLOAD_MAJOR_VERSION=2\nPAYLOAD_MINOR_VERSION=4\n")
41
Tao Bao15a146a2018-02-21 16:06:59 -080042 # META/postinstall_config.txt
43 target_files_zip.writestr(
44 POSTINSTALL_CONFIG,
45 '\n'.join([
46 "RUN_POSTINSTALL_system=true",
47 "POSTINSTALL_PATH_system=system/bin/otapreopt_script",
48 "FILESYSTEM_TYPE_system=ext4",
49 "POSTINSTALL_OPTIONAL_system=true",
50 ]))
51
Tao Baof7140c02018-01-30 17:09:24 -080052 # META/ab_partitions.txt
53 ab_partitions = ['boot', 'system', 'vendor']
54 target_files_zip.writestr(
55 'META/ab_partitions.txt',
56 '\n'.join(ab_partitions))
57
58 # Create dummy images for each of them.
59 for partition in ab_partitions:
60 target_files_zip.writestr('IMAGES/' + partition + '.img',
61 os.urandom(len(partition)))
62
63 if secondary:
64 target_files_zip.writestr('IMAGES/system_other.img',
65 os.urandom(len("system_other")))
66
67 return target_files
68
69
Tao Bao481bab82017-12-21 11:23:09 -080070class MockScriptWriter(object):
71 """A class that mocks edify_generator.EdifyGenerator.
72
73 It simply pushes the incoming arguments onto script stack, which is to assert
74 the calls to EdifyGenerator functions.
75 """
76
77 def __init__(self):
78 self.script = []
79
80 def Mount(self, *args):
81 self.script.append(('Mount',) + args)
82
83 def AssertDevice(self, *args):
84 self.script.append(('AssertDevice',) + args)
85
86 def AssertOemProperty(self, *args):
87 self.script.append(('AssertOemProperty',) + args)
88
89 def AssertFingerprintOrThumbprint(self, *args):
90 self.script.append(('AssertFingerprintOrThumbprint',) + args)
91
92 def AssertSomeFingerprint(self, *args):
93 self.script.append(('AssertSomeFingerprint',) + args)
94
95 def AssertSomeThumbprint(self, *args):
96 self.script.append(('AssertSomeThumbprint',) + args)
97
98
99class BuildInfoTest(unittest.TestCase):
100
101 TEST_INFO_DICT = {
102 'build.prop' : {
103 'ro.product.device' : 'product-device',
104 'ro.product.name' : 'product-name',
105 'ro.build.fingerprint' : 'build-fingerprint',
106 'ro.build.foo' : 'build-foo',
107 },
108 'vendor.build.prop' : {
109 'ro.vendor.build.fingerprint' : 'vendor-build-fingerprint',
110 },
111 'property1' : 'value1',
112 'property2' : 4096,
113 }
114
115 TEST_INFO_DICT_USES_OEM_PROPS = {
116 'build.prop' : {
117 'ro.product.name' : 'product-name',
118 'ro.build.thumbprint' : 'build-thumbprint',
119 'ro.build.bar' : 'build-bar',
120 },
121 'vendor.build.prop' : {
122 'ro.vendor.build.fingerprint' : 'vendor-build-fingerprint',
123 },
124 'property1' : 'value1',
125 'property2' : 4096,
126 'oem_fingerprint_properties' : 'ro.product.device ro.product.brand',
127 }
128
129 TEST_OEM_DICTS = [
130 {
131 'ro.product.brand' : 'brand1',
132 'ro.product.device' : 'device1',
133 },
134 {
135 'ro.product.brand' : 'brand2',
136 'ro.product.device' : 'device2',
137 },
138 {
139 'ro.product.brand' : 'brand3',
140 'ro.product.device' : 'device3',
141 },
142 ]
143
144 def test_init(self):
145 target_info = BuildInfo(self.TEST_INFO_DICT, None)
146 self.assertEqual('product-device', target_info.device)
147 self.assertEqual('build-fingerprint', target_info.fingerprint)
148 self.assertFalse(target_info.is_ab)
149 self.assertIsNone(target_info.oem_props)
150
151 def test_init_with_oem_props(self):
152 target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
153 self.TEST_OEM_DICTS)
154 self.assertEqual('device1', target_info.device)
155 self.assertEqual('brand1/product-name/device1:build-thumbprint',
156 target_info.fingerprint)
157
158 # Swap the order in oem_dicts, which would lead to different BuildInfo.
159 oem_dicts = copy.copy(self.TEST_OEM_DICTS)
160 oem_dicts[0], oem_dicts[2] = oem_dicts[2], oem_dicts[0]
161 target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS, oem_dicts)
162 self.assertEqual('device3', target_info.device)
163 self.assertEqual('brand3/product-name/device3:build-thumbprint',
164 target_info.fingerprint)
165
166 # Missing oem_dict should be rejected.
167 self.assertRaises(AssertionError, BuildInfo,
168 self.TEST_INFO_DICT_USES_OEM_PROPS, None)
169
170 def test___getitem__(self):
171 target_info = BuildInfo(self.TEST_INFO_DICT, None)
172 self.assertEqual('value1', target_info['property1'])
173 self.assertEqual(4096, target_info['property2'])
174 self.assertEqual('build-foo', target_info['build.prop']['ro.build.foo'])
175
176 def test___getitem__with_oem_props(self):
177 target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
178 self.TEST_OEM_DICTS)
179 self.assertEqual('value1', target_info['property1'])
180 self.assertEqual(4096, target_info['property2'])
181 self.assertRaises(KeyError,
182 lambda: target_info['build.prop']['ro.build.foo'])
183
184 def test_get(self):
185 target_info = BuildInfo(self.TEST_INFO_DICT, None)
186 self.assertEqual('value1', target_info.get('property1'))
187 self.assertEqual(4096, target_info.get('property2'))
188 self.assertEqual(4096, target_info.get('property2', 1024))
189 self.assertEqual(1024, target_info.get('property-nonexistent', 1024))
190 self.assertEqual('build-foo', target_info.get('build.prop')['ro.build.foo'])
191
192 def test_get_with_oem_props(self):
193 target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
194 self.TEST_OEM_DICTS)
195 self.assertEqual('value1', target_info.get('property1'))
196 self.assertEqual(4096, target_info.get('property2'))
197 self.assertEqual(4096, target_info.get('property2', 1024))
198 self.assertEqual(1024, target_info.get('property-nonexistent', 1024))
199 self.assertIsNone(target_info.get('build.prop').get('ro.build.foo'))
200 self.assertRaises(KeyError,
201 lambda: target_info.get('build.prop')['ro.build.foo'])
202
203 def test_GetBuildProp(self):
204 target_info = BuildInfo(self.TEST_INFO_DICT, None)
205 self.assertEqual('build-foo', target_info.GetBuildProp('ro.build.foo'))
206 self.assertRaises(common.ExternalError, target_info.GetBuildProp,
207 'ro.build.nonexistent')
208
209 def test_GetBuildProp_with_oem_props(self):
210 target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
211 self.TEST_OEM_DICTS)
212 self.assertEqual('build-bar', target_info.GetBuildProp('ro.build.bar'))
213 self.assertRaises(common.ExternalError, target_info.GetBuildProp,
214 'ro.build.nonexistent')
215
216 def test_GetVendorBuildProp(self):
217 target_info = BuildInfo(self.TEST_INFO_DICT, None)
218 self.assertEqual('vendor-build-fingerprint',
219 target_info.GetVendorBuildProp(
220 'ro.vendor.build.fingerprint'))
221 self.assertRaises(common.ExternalError, target_info.GetVendorBuildProp,
222 'ro.build.nonexistent')
223
224 def test_GetVendorBuildProp_with_oem_props(self):
225 target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
226 self.TEST_OEM_DICTS)
227 self.assertEqual('vendor-build-fingerprint',
228 target_info.GetVendorBuildProp(
229 'ro.vendor.build.fingerprint'))
230 self.assertRaises(common.ExternalError, target_info.GetVendorBuildProp,
231 'ro.build.nonexistent')
232
233 def test_WriteMountOemScript(self):
234 target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
235 self.TEST_OEM_DICTS)
236 script_writer = MockScriptWriter()
237 target_info.WriteMountOemScript(script_writer)
238 self.assertEqual([('Mount', '/oem', None)], script_writer.script)
239
240 def test_WriteDeviceAssertions(self):
241 target_info = BuildInfo(self.TEST_INFO_DICT, None)
242 script_writer = MockScriptWriter()
243 target_info.WriteDeviceAssertions(script_writer, False)
244 self.assertEqual([('AssertDevice', 'product-device')], script_writer.script)
245
246 def test_WriteDeviceAssertions_with_oem_props(self):
247 target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
248 self.TEST_OEM_DICTS)
249 script_writer = MockScriptWriter()
250 target_info.WriteDeviceAssertions(script_writer, False)
251 self.assertEqual(
252 [
253 ('AssertOemProperty', 'ro.product.device',
254 ['device1', 'device2', 'device3'], False),
255 ('AssertOemProperty', 'ro.product.brand',
256 ['brand1', 'brand2', 'brand3'], False),
257 ],
258 script_writer.script)
259
260 def test_WriteFingerprintAssertion_without_oem_props(self):
261 target_info = BuildInfo(self.TEST_INFO_DICT, None)
262 source_info_dict = copy.deepcopy(self.TEST_INFO_DICT)
263 source_info_dict['build.prop']['ro.build.fingerprint'] = (
264 'source-build-fingerprint')
265 source_info = BuildInfo(source_info_dict, None)
266
267 script_writer = MockScriptWriter()
268 WriteFingerprintAssertion(script_writer, target_info, source_info)
269 self.assertEqual(
270 [('AssertSomeFingerprint', 'source-build-fingerprint',
271 'build-fingerprint')],
272 script_writer.script)
273
274 def test_WriteFingerprintAssertion_with_source_oem_props(self):
275 target_info = BuildInfo(self.TEST_INFO_DICT, None)
276 source_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
277 self.TEST_OEM_DICTS)
278
279 script_writer = MockScriptWriter()
280 WriteFingerprintAssertion(script_writer, target_info, source_info)
281 self.assertEqual(
282 [('AssertFingerprintOrThumbprint', 'build-fingerprint',
283 'build-thumbprint')],
284 script_writer.script)
285
286 def test_WriteFingerprintAssertion_with_target_oem_props(self):
287 target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
288 self.TEST_OEM_DICTS)
289 source_info = BuildInfo(self.TEST_INFO_DICT, None)
290
291 script_writer = MockScriptWriter()
292 WriteFingerprintAssertion(script_writer, target_info, source_info)
293 self.assertEqual(
294 [('AssertFingerprintOrThumbprint', 'build-fingerprint',
295 'build-thumbprint')],
296 script_writer.script)
297
298 def test_WriteFingerprintAssertion_with_both_oem_props(self):
299 target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
300 self.TEST_OEM_DICTS)
301 source_info_dict = copy.deepcopy(self.TEST_INFO_DICT_USES_OEM_PROPS)
302 source_info_dict['build.prop']['ro.build.thumbprint'] = (
303 'source-build-thumbprint')
304 source_info = BuildInfo(source_info_dict, self.TEST_OEM_DICTS)
305
306 script_writer = MockScriptWriter()
307 WriteFingerprintAssertion(script_writer, target_info, source_info)
308 self.assertEqual(
309 [('AssertSomeThumbprint', 'build-thumbprint',
310 'source-build-thumbprint')],
311 script_writer.script)
312
313
314class LoadOemDictsTest(unittest.TestCase):
315
316 def tearDown(self):
317 common.Cleanup()
318
319 def test_NoneDict(self):
320 self.assertIsNone(_LoadOemDicts(None))
321
322 def test_SingleDict(self):
323 dict_file = common.MakeTempFile()
324 with open(dict_file, 'w') as dict_fp:
325 dict_fp.write('abc=1\ndef=2\nxyz=foo\na.b.c=bar\n')
326
327 oem_dicts = _LoadOemDicts([dict_file])
328 self.assertEqual(1, len(oem_dicts))
329 self.assertEqual('foo', oem_dicts[0]['xyz'])
330 self.assertEqual('bar', oem_dicts[0]['a.b.c'])
331
332 def test_MultipleDicts(self):
333 oem_source = []
334 for i in range(3):
335 dict_file = common.MakeTempFile()
336 with open(dict_file, 'w') as dict_fp:
337 dict_fp.write(
338 'ro.build.index={}\ndef=2\nxyz=foo\na.b.c=bar\n'.format(i))
339 oem_source.append(dict_file)
340
341 oem_dicts = _LoadOemDicts(oem_source)
342 self.assertEqual(3, len(oem_dicts))
343 for i, oem_dict in enumerate(oem_dicts):
344 self.assertEqual('2', oem_dict['def'])
345 self.assertEqual('foo', oem_dict['xyz'])
346 self.assertEqual('bar', oem_dict['a.b.c'])
347 self.assertEqual('{}'.format(i), oem_dict['ro.build.index'])
Tao Baodf3a48b2018-01-10 16:30:43 -0800348
349
350class OtaFromTargetFilesTest(unittest.TestCase):
351
352 TEST_TARGET_INFO_DICT = {
353 'build.prop' : {
354 'ro.product.device' : 'product-device',
355 'ro.build.fingerprint' : 'build-fingerprint-target',
356 'ro.build.version.incremental' : 'build-version-incremental-target',
Tao Bao35dc2552018-02-01 13:18:00 -0800357 'ro.build.version.sdk' : '27',
358 'ro.build.version.security_patch' : '2017-12-01',
Tao Baodf3a48b2018-01-10 16:30:43 -0800359 'ro.build.date.utc' : '1500000000',
360 },
361 }
362
363 TEST_SOURCE_INFO_DICT = {
364 'build.prop' : {
365 'ro.product.device' : 'product-device',
366 'ro.build.fingerprint' : 'build-fingerprint-source',
367 'ro.build.version.incremental' : 'build-version-incremental-source',
Tao Bao35dc2552018-02-01 13:18:00 -0800368 'ro.build.version.sdk' : '25',
369 'ro.build.version.security_patch' : '2016-12-01',
Tao Baodf3a48b2018-01-10 16:30:43 -0800370 'ro.build.date.utc' : '1400000000',
371 },
372 }
373
374 def setUp(self):
375 # Reset the global options as in ota_from_target_files.py.
376 common.OPTIONS.incremental_source = None
377 common.OPTIONS.downgrade = False
378 common.OPTIONS.timestamp = False
379 common.OPTIONS.wipe_user_data = False
380
Tao Baof5110492018-03-02 09:47:43 -0800381 def tearDown(self):
382 common.Cleanup()
383
Tao Baodf3a48b2018-01-10 16:30:43 -0800384 def test_GetPackageMetadata_abOta_full(self):
385 target_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT)
386 target_info_dict['ab_update'] = 'true'
387 target_info = BuildInfo(target_info_dict, None)
388 metadata = GetPackageMetadata(target_info)
389 self.assertDictEqual(
390 {
391 'ota-type' : 'AB',
392 'ota-required-cache' : '0',
393 'post-build' : 'build-fingerprint-target',
394 'post-build-incremental' : 'build-version-incremental-target',
Tao Bao35dc2552018-02-01 13:18:00 -0800395 'post-sdk-level' : '27',
396 'post-security-patch-level' : '2017-12-01',
Tao Baodf3a48b2018-01-10 16:30:43 -0800397 'post-timestamp' : '1500000000',
398 'pre-device' : 'product-device',
399 },
400 metadata)
401
402 def test_GetPackageMetadata_abOta_incremental(self):
403 target_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT)
404 target_info_dict['ab_update'] = 'true'
405 target_info = BuildInfo(target_info_dict, None)
406 source_info = BuildInfo(self.TEST_SOURCE_INFO_DICT, None)
407 common.OPTIONS.incremental_source = ''
408 metadata = GetPackageMetadata(target_info, source_info)
409 self.assertDictEqual(
410 {
411 'ota-type' : 'AB',
412 'ota-required-cache' : '0',
413 'post-build' : 'build-fingerprint-target',
414 'post-build-incremental' : 'build-version-incremental-target',
Tao Bao35dc2552018-02-01 13:18:00 -0800415 'post-sdk-level' : '27',
416 'post-security-patch-level' : '2017-12-01',
Tao Baodf3a48b2018-01-10 16:30:43 -0800417 'post-timestamp' : '1500000000',
418 'pre-device' : 'product-device',
419 'pre-build' : 'build-fingerprint-source',
420 'pre-build-incremental' : 'build-version-incremental-source',
421 },
422 metadata)
423
424 def test_GetPackageMetadata_nonAbOta_full(self):
425 target_info = BuildInfo(self.TEST_TARGET_INFO_DICT, None)
426 metadata = GetPackageMetadata(target_info)
427 self.assertDictEqual(
428 {
429 'ota-type' : 'BLOCK',
430 'post-build' : 'build-fingerprint-target',
431 'post-build-incremental' : 'build-version-incremental-target',
Tao Bao35dc2552018-02-01 13:18:00 -0800432 'post-sdk-level' : '27',
433 'post-security-patch-level' : '2017-12-01',
Tao Baodf3a48b2018-01-10 16:30:43 -0800434 'post-timestamp' : '1500000000',
435 'pre-device' : 'product-device',
436 },
437 metadata)
438
439 def test_GetPackageMetadata_nonAbOta_incremental(self):
440 target_info = BuildInfo(self.TEST_TARGET_INFO_DICT, None)
441 source_info = BuildInfo(self.TEST_SOURCE_INFO_DICT, None)
442 common.OPTIONS.incremental_source = ''
443 metadata = GetPackageMetadata(target_info, source_info)
444 self.assertDictEqual(
445 {
446 'ota-type' : 'BLOCK',
447 'post-build' : 'build-fingerprint-target',
448 'post-build-incremental' : 'build-version-incremental-target',
Tao Bao35dc2552018-02-01 13:18:00 -0800449 'post-sdk-level' : '27',
450 'post-security-patch-level' : '2017-12-01',
Tao Baodf3a48b2018-01-10 16:30:43 -0800451 'post-timestamp' : '1500000000',
452 'pre-device' : 'product-device',
453 'pre-build' : 'build-fingerprint-source',
454 'pre-build-incremental' : 'build-version-incremental-source',
455 },
456 metadata)
457
458 def test_GetPackageMetadata_wipe(self):
459 target_info = BuildInfo(self.TEST_TARGET_INFO_DICT, None)
460 common.OPTIONS.wipe_user_data = True
461 metadata = GetPackageMetadata(target_info)
462 self.assertDictEqual(
463 {
464 'ota-type' : 'BLOCK',
465 'ota-wipe' : 'yes',
466 'post-build' : 'build-fingerprint-target',
467 'post-build-incremental' : 'build-version-incremental-target',
Tao Bao35dc2552018-02-01 13:18:00 -0800468 'post-sdk-level' : '27',
469 'post-security-patch-level' : '2017-12-01',
Tao Baodf3a48b2018-01-10 16:30:43 -0800470 'post-timestamp' : '1500000000',
471 'pre-device' : 'product-device',
472 },
473 metadata)
474
475 @staticmethod
476 def _test_GetPackageMetadata_swapBuildTimestamps(target_info, source_info):
477 (target_info['build.prop']['ro.build.date.utc'],
478 source_info['build.prop']['ro.build.date.utc']) = (
479 source_info['build.prop']['ro.build.date.utc'],
480 target_info['build.prop']['ro.build.date.utc'])
481
482 def test_GetPackageMetadata_unintentionalDowngradeDetected(self):
483 target_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT)
484 source_info_dict = copy.deepcopy(self.TEST_SOURCE_INFO_DICT)
485 self._test_GetPackageMetadata_swapBuildTimestamps(
486 target_info_dict, source_info_dict)
487
488 target_info = BuildInfo(target_info_dict, None)
489 source_info = BuildInfo(source_info_dict, None)
490 common.OPTIONS.incremental_source = ''
491 self.assertRaises(RuntimeError, GetPackageMetadata, target_info,
492 source_info)
493
494 def test_GetPackageMetadata_downgrade(self):
495 target_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT)
496 source_info_dict = copy.deepcopy(self.TEST_SOURCE_INFO_DICT)
497 self._test_GetPackageMetadata_swapBuildTimestamps(
498 target_info_dict, source_info_dict)
499
500 target_info = BuildInfo(target_info_dict, None)
501 source_info = BuildInfo(source_info_dict, None)
502 common.OPTIONS.incremental_source = ''
503 common.OPTIONS.downgrade = True
504 common.OPTIONS.wipe_user_data = True
505 metadata = GetPackageMetadata(target_info, source_info)
506 self.assertDictEqual(
507 {
508 'ota-downgrade' : 'yes',
509 'ota-type' : 'BLOCK',
510 'ota-wipe' : 'yes',
511 'post-build' : 'build-fingerprint-target',
512 'post-build-incremental' : 'build-version-incremental-target',
Tao Bao35dc2552018-02-01 13:18:00 -0800513 'post-sdk-level' : '27',
514 'post-security-patch-level' : '2017-12-01',
Tao Baodf3a48b2018-01-10 16:30:43 -0800515 'pre-device' : 'product-device',
516 'pre-build' : 'build-fingerprint-source',
517 'pre-build-incremental' : 'build-version-incremental-source',
518 },
519 metadata)
520
521 def test_GetPackageMetadata_overrideTimestamp(self):
522 target_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT)
523 source_info_dict = copy.deepcopy(self.TEST_SOURCE_INFO_DICT)
524 self._test_GetPackageMetadata_swapBuildTimestamps(
525 target_info_dict, source_info_dict)
526
527 target_info = BuildInfo(target_info_dict, None)
528 source_info = BuildInfo(source_info_dict, None)
529 common.OPTIONS.incremental_source = ''
530 common.OPTIONS.timestamp = True
531 metadata = GetPackageMetadata(target_info, source_info)
532 self.assertDictEqual(
533 {
534 'ota-type' : 'BLOCK',
535 'post-build' : 'build-fingerprint-target',
536 'post-build-incremental' : 'build-version-incremental-target',
Tao Bao35dc2552018-02-01 13:18:00 -0800537 'post-sdk-level' : '27',
538 'post-security-patch-level' : '2017-12-01',
Tao Baodf3a48b2018-01-10 16:30:43 -0800539 'post-timestamp' : '1500000001',
540 'pre-device' : 'product-device',
541 'pre-build' : 'build-fingerprint-source',
542 'pre-build-incremental' : 'build-version-incremental-source',
543 },
544 metadata)
Tao Baofabe0832018-01-17 15:52:28 -0800545
Tao Baof7140c02018-01-30 17:09:24 -0800546 def test_GetTargetFilesZipForSecondaryImages(self):
547 input_file = construct_target_files(secondary=True)
548 target_file = GetTargetFilesZipForSecondaryImages(input_file)
549
550 with zipfile.ZipFile(target_file) as verify_zip:
551 namelist = verify_zip.namelist()
552
553 self.assertIn('META/ab_partitions.txt', namelist)
554 self.assertIn('IMAGES/boot.img', namelist)
555 self.assertIn('IMAGES/system.img', namelist)
556 self.assertIn('IMAGES/vendor.img', namelist)
Tao Bao15a146a2018-02-21 16:06:59 -0800557 self.assertIn(POSTINSTALL_CONFIG, namelist)
Tao Baof7140c02018-01-30 17:09:24 -0800558
559 self.assertNotIn('IMAGES/system_other.img', namelist)
560 self.assertNotIn('IMAGES/system.map', namelist)
561
Tao Bao15a146a2018-02-21 16:06:59 -0800562 def test_GetTargetFilesZipForSecondaryImages_skipPostinstall(self):
563 input_file = construct_target_files(secondary=True)
564 target_file = GetTargetFilesZipForSecondaryImages(
565 input_file, skip_postinstall=True)
566
567 with zipfile.ZipFile(target_file) as verify_zip:
568 namelist = verify_zip.namelist()
569
570 self.assertIn('META/ab_partitions.txt', namelist)
571 self.assertIn('IMAGES/boot.img', namelist)
572 self.assertIn('IMAGES/system.img', namelist)
573 self.assertIn('IMAGES/vendor.img', namelist)
574
575 self.assertNotIn('IMAGES/system_other.img', namelist)
576 self.assertNotIn('IMAGES/system.map', namelist)
577 self.assertNotIn(POSTINSTALL_CONFIG, namelist)
578
579 def test_GetTargetFilesZipWithoutPostinstallConfig(self):
580 input_file = construct_target_files()
581 target_file = GetTargetFilesZipWithoutPostinstallConfig(input_file)
582 with zipfile.ZipFile(target_file) as verify_zip:
583 self.assertNotIn(POSTINSTALL_CONFIG, verify_zip.namelist())
584
585 def test_GetTargetFilesZipWithoutPostinstallConfig_missingEntry(self):
586 input_file = construct_target_files()
587 common.ZipDelete(input_file, POSTINSTALL_CONFIG)
588 target_file = GetTargetFilesZipWithoutPostinstallConfig(input_file)
589 with zipfile.ZipFile(target_file) as verify_zip:
590 self.assertNotIn(POSTINSTALL_CONFIG, verify_zip.namelist())
591
Tao Baoae5e4c32018-03-01 19:30:00 -0800592
Tao Bao69203522018-03-08 16:09:01 -0800593class TestPropertyFiles(PropertyFiles):
594 """A class that extends PropertyFiles for testing purpose."""
595
596 def __init__(self):
597 super(TestPropertyFiles, self).__init__()
598 self.name = 'ota-test-property-files'
599 self.required = (
600 'required-entry1',
601 'required-entry2',
602 )
603 self.optional = (
604 'optional-entry1',
605 'optional-entry2',
606 )
607
608
609class PropertyFilesTest(unittest.TestCase):
Tao Baoae5e4c32018-03-01 19:30:00 -0800610
611 def tearDown(self):
612 common.Cleanup()
613
Tao Baof5110492018-03-02 09:47:43 -0800614 @staticmethod
615 def _construct_zip_package(entries):
616 zip_file = common.MakeTempFile(suffix='.zip')
617 with zipfile.ZipFile(zip_file, 'w') as zip_fp:
618 for entry in entries:
619 zip_fp.writestr(
620 entry,
621 entry.replace('.', '-').upper(),
622 zipfile.ZIP_STORED)
623 return zip_file
624
625 @staticmethod
Tao Bao69203522018-03-08 16:09:01 -0800626 def _parse_property_files_string(data):
Tao Baof5110492018-03-02 09:47:43 -0800627 result = {}
628 for token in data.split(','):
629 name, info = token.split(':', 1)
630 result[name] = info
631 return result
632
633 def _verify_entries(self, input_file, tokens, entries):
634 for entry in entries:
635 offset, size = map(int, tokens[entry].split(':'))
636 with open(input_file, 'rb') as input_fp:
637 input_fp.seek(offset)
638 if entry == 'metadata':
639 expected = b'META-INF/COM/ANDROID/METADATA'
640 else:
641 expected = entry.replace('.', '-').upper().encode()
642 self.assertEqual(expected, input_fp.read(size))
643
Tao Baoae5e4c32018-03-01 19:30:00 -0800644 def test_Compute(self):
Tao Baof5110492018-03-02 09:47:43 -0800645 entries = (
Tao Bao69203522018-03-08 16:09:01 -0800646 'required-entry1',
647 'required-entry2',
Tao Baof5110492018-03-02 09:47:43 -0800648 )
649 zip_file = self._construct_zip_package(entries)
Tao Bao69203522018-03-08 16:09:01 -0800650 property_files = TestPropertyFiles()
Tao Baof5110492018-03-02 09:47:43 -0800651 with zipfile.ZipFile(zip_file, 'r') as zip_fp:
Tao Bao69203522018-03-08 16:09:01 -0800652 property_files_string = property_files.Compute(zip_fp)
Tao Baof5110492018-03-02 09:47:43 -0800653
Tao Bao69203522018-03-08 16:09:01 -0800654 tokens = self._parse_property_files_string(property_files_string)
Tao Baof5110492018-03-02 09:47:43 -0800655 self.assertEqual(3, len(tokens))
656 self._verify_entries(zip_file, tokens, entries)
657
Tao Bao69203522018-03-08 16:09:01 -0800658 def test_Compute_withOptionalEntries(self):
Tao Baof5110492018-03-02 09:47:43 -0800659 entries = (
Tao Bao69203522018-03-08 16:09:01 -0800660 'required-entry1',
661 'required-entry2',
662 'optional-entry1',
663 'optional-entry2',
Tao Baof5110492018-03-02 09:47:43 -0800664 )
665 zip_file = self._construct_zip_package(entries)
Tao Bao69203522018-03-08 16:09:01 -0800666 property_files = TestPropertyFiles()
Tao Baof5110492018-03-02 09:47:43 -0800667 with zipfile.ZipFile(zip_file, 'r') as zip_fp:
Tao Bao69203522018-03-08 16:09:01 -0800668 property_files_string = property_files.Compute(zip_fp)
Tao Baof5110492018-03-02 09:47:43 -0800669
Tao Bao69203522018-03-08 16:09:01 -0800670 tokens = self._parse_property_files_string(property_files_string)
Tao Baof5110492018-03-02 09:47:43 -0800671 self.assertEqual(5, len(tokens))
672 self._verify_entries(zip_file, tokens, entries)
673
Tao Bao69203522018-03-08 16:09:01 -0800674 def test_Compute_missingRequiredEntry(self):
675 entries = (
676 'required-entry2',
677 )
678 zip_file = self._construct_zip_package(entries)
679 property_files = TestPropertyFiles()
680 with zipfile.ZipFile(zip_file, 'r') as zip_fp:
681 self.assertRaises(KeyError, property_files.Compute, zip_fp)
682
Tao Baoae5e4c32018-03-01 19:30:00 -0800683 def test_Finalize(self):
Tao Baof5110492018-03-02 09:47:43 -0800684 entries = [
Tao Bao69203522018-03-08 16:09:01 -0800685 'required-entry1',
686 'required-entry2',
Tao Baof5110492018-03-02 09:47:43 -0800687 'META-INF/com/android/metadata',
688 ]
689 zip_file = self._construct_zip_package(entries)
Tao Bao69203522018-03-08 16:09:01 -0800690 property_files = TestPropertyFiles()
Tao Baof5110492018-03-02 09:47:43 -0800691 with zipfile.ZipFile(zip_file, 'r') as zip_fp:
Tao Bao69203522018-03-08 16:09:01 -0800692 # pylint: disable=protected-access
Tao Baoae5e4c32018-03-01 19:30:00 -0800693 raw_metadata = property_files._GetPropertyFilesString(
694 zip_fp, reserve_space=False)
695 streaming_metadata = property_files.Finalize(zip_fp, len(raw_metadata))
Tao Bao69203522018-03-08 16:09:01 -0800696 tokens = self._parse_property_files_string(streaming_metadata)
Tao Baof5110492018-03-02 09:47:43 -0800697
698 self.assertEqual(3, len(tokens))
699 # 'META-INF/com/android/metadata' will be key'd as 'metadata' in the
700 # streaming metadata.
701 entries[2] = 'metadata'
702 self._verify_entries(zip_file, tokens, entries)
703
Tao Baoae5e4c32018-03-01 19:30:00 -0800704 def test_Finalize_assertReservedLength(self):
Tao Baof5110492018-03-02 09:47:43 -0800705 entries = (
Tao Bao69203522018-03-08 16:09:01 -0800706 'required-entry1',
707 'required-entry2',
708 'optional-entry1',
709 'optional-entry2',
Tao Baof5110492018-03-02 09:47:43 -0800710 'META-INF/com/android/metadata',
711 )
712 zip_file = self._construct_zip_package(entries)
Tao Bao69203522018-03-08 16:09:01 -0800713 property_files = TestPropertyFiles()
Tao Baof5110492018-03-02 09:47:43 -0800714 with zipfile.ZipFile(zip_file, 'r') as zip_fp:
715 # First get the raw metadata string (i.e. without padding space).
Tao Bao69203522018-03-08 16:09:01 -0800716 # pylint: disable=protected-access
Tao Baoae5e4c32018-03-01 19:30:00 -0800717 raw_metadata = property_files._GetPropertyFilesString(
718 zip_fp, reserve_space=False)
Tao Baof5110492018-03-02 09:47:43 -0800719 raw_length = len(raw_metadata)
720
721 # Now pass in the exact expected length.
Tao Baoae5e4c32018-03-01 19:30:00 -0800722 streaming_metadata = property_files.Finalize(zip_fp, raw_length)
Tao Baof5110492018-03-02 09:47:43 -0800723 self.assertEqual(raw_length, len(streaming_metadata))
724
725 # Or pass in insufficient length.
726 self.assertRaises(
727 AssertionError,
Tao Baoae5e4c32018-03-01 19:30:00 -0800728 property_files.Finalize,
Tao Baof5110492018-03-02 09:47:43 -0800729 zip_fp,
Tao Baoae5e4c32018-03-01 19:30:00 -0800730 raw_length - 1)
Tao Baof5110492018-03-02 09:47:43 -0800731
732 # Or pass in a much larger size.
Tao Baoae5e4c32018-03-01 19:30:00 -0800733 streaming_metadata = property_files.Finalize(
Tao Baof5110492018-03-02 09:47:43 -0800734 zip_fp,
Tao Baoae5e4c32018-03-01 19:30:00 -0800735 raw_length + 20)
Tao Baof5110492018-03-02 09:47:43 -0800736 self.assertEqual(raw_length + 20, len(streaming_metadata))
737 self.assertEqual(' ' * 20, streaming_metadata[raw_length:])
738
Tao Baoae5e4c32018-03-01 19:30:00 -0800739 def test_Verify(self):
740 entries = (
Tao Bao69203522018-03-08 16:09:01 -0800741 'required-entry1',
742 'required-entry2',
743 'optional-entry1',
744 'optional-entry2',
745 'META-INF/com/android/metadata',
746 )
747 zip_file = self._construct_zip_package(entries)
748 property_files = TestPropertyFiles()
749 with zipfile.ZipFile(zip_file, 'r') as zip_fp:
750 # First get the raw metadata string (i.e. without padding space).
751 # pylint: disable=protected-access
752 raw_metadata = property_files._GetPropertyFilesString(
753 zip_fp, reserve_space=False)
754
755 # Should pass the test if verification passes.
756 property_files.Verify(zip_fp, raw_metadata)
757
758 # Or raise on verification failure.
759 self.assertRaises(
760 AssertionError, property_files.Verify, zip_fp, raw_metadata + 'x')
761
762
763class StreamingPropertyFilesTest(PropertyFilesTest):
764 """Additional sanity checks specialized for StreamingPropertyFiles."""
765
766 def test_init(self):
767 property_files = StreamingPropertyFiles()
768 self.assertEqual('ota-streaming-property-files', property_files.name)
769 self.assertEqual(
770 (
771 'payload.bin',
772 'payload_properties.txt',
773 ),
774 property_files.required)
775 self.assertEqual(
776 (
777 'care_map.txt',
778 'compatibility.zip',
779 ),
780 property_files.optional)
781
782 def test_Compute(self):
783 entries = (
Tao Baoae5e4c32018-03-01 19:30:00 -0800784 'payload.bin',
785 'payload_properties.txt',
786 'care_map.txt',
Tao Bao69203522018-03-08 16:09:01 -0800787 'compatibility.zip',
788 )
789 zip_file = self._construct_zip_package(entries)
790 property_files = StreamingPropertyFiles()
791 with zipfile.ZipFile(zip_file, 'r') as zip_fp:
792 property_files_string = property_files.Compute(zip_fp)
793
794 tokens = self._parse_property_files_string(property_files_string)
795 self.assertEqual(5, len(tokens))
796 self._verify_entries(zip_file, tokens, entries)
797
798 def test_Finalize(self):
799 entries = [
800 'payload.bin',
801 'payload_properties.txt',
802 'care_map.txt',
803 'compatibility.zip',
804 'META-INF/com/android/metadata',
805 ]
806 zip_file = self._construct_zip_package(entries)
807 property_files = StreamingPropertyFiles()
808 with zipfile.ZipFile(zip_file, 'r') as zip_fp:
809 # pylint: disable=protected-access
810 raw_metadata = property_files._GetPropertyFilesString(
811 zip_fp, reserve_space=False)
812 streaming_metadata = property_files.Finalize(zip_fp, len(raw_metadata))
813 tokens = self._parse_property_files_string(streaming_metadata)
814
815 self.assertEqual(5, len(tokens))
816 # 'META-INF/com/android/metadata' will be key'd as 'metadata' in the
817 # streaming metadata.
818 entries[4] = 'metadata'
819 self._verify_entries(zip_file, tokens, entries)
820
821 def test_Verify(self):
822 entries = (
823 'payload.bin',
824 'payload_properties.txt',
825 'care_map.txt',
826 'compatibility.zip',
Tao Baoae5e4c32018-03-01 19:30:00 -0800827 'META-INF/com/android/metadata',
828 )
829 zip_file = self._construct_zip_package(entries)
830 property_files = StreamingPropertyFiles()
831 with zipfile.ZipFile(zip_file, 'r') as zip_fp:
832 # First get the raw metadata string (i.e. without padding space).
Tao Bao69203522018-03-08 16:09:01 -0800833 # pylint: disable=protected-access
Tao Baoae5e4c32018-03-01 19:30:00 -0800834 raw_metadata = property_files._GetPropertyFilesString(
835 zip_fp, reserve_space=False)
836
837 # Should pass the test if verification passes.
838 property_files.Verify(zip_fp, raw_metadata)
839
840 # Or raise on verification failure.
841 self.assertRaises(
842 AssertionError, property_files.Verify, zip_fp, raw_metadata + 'x')
843
Tao Baofabe0832018-01-17 15:52:28 -0800844
845class PayloadSignerTest(unittest.TestCase):
846
847 SIGFILE = 'sigfile.bin'
848 SIGNED_SIGFILE = 'signed-sigfile.bin'
849
850 def setUp(self):
Tao Bao04e1f012018-02-04 12:13:35 -0800851 self.testdata_dir = test_utils.get_testdata_dir()
Tao Baofabe0832018-01-17 15:52:28 -0800852 self.assertTrue(os.path.exists(self.testdata_dir))
853
854 common.OPTIONS.payload_signer = None
855 common.OPTIONS.payload_signer_args = []
856 common.OPTIONS.package_key = os.path.join(self.testdata_dir, 'testkey')
857 common.OPTIONS.key_passwords = {
858 common.OPTIONS.package_key : None,
859 }
860
861 def tearDown(self):
862 common.Cleanup()
863
864 def _assertFilesEqual(self, file1, file2):
865 with open(file1, 'rb') as fp1, open(file2, 'rb') as fp2:
866 self.assertEqual(fp1.read(), fp2.read())
867
868 def test_init(self):
869 payload_signer = PayloadSigner()
870 self.assertEqual('openssl', payload_signer.signer)
871
872 def test_init_withPassword(self):
873 common.OPTIONS.package_key = os.path.join(
874 self.testdata_dir, 'testkey_with_passwd')
875 common.OPTIONS.key_passwords = {
876 common.OPTIONS.package_key : 'foo',
877 }
878 payload_signer = PayloadSigner()
879 self.assertEqual('openssl', payload_signer.signer)
880
881 def test_init_withExternalSigner(self):
882 common.OPTIONS.payload_signer = 'abc'
883 common.OPTIONS.payload_signer_args = ['arg1', 'arg2']
884 payload_signer = PayloadSigner()
885 self.assertEqual('abc', payload_signer.signer)
886 self.assertEqual(['arg1', 'arg2'], payload_signer.signer_args)
887
888 def test_Sign(self):
889 payload_signer = PayloadSigner()
890 input_file = os.path.join(self.testdata_dir, self.SIGFILE)
891 signed_file = payload_signer.Sign(input_file)
892
893 verify_file = os.path.join(self.testdata_dir, self.SIGNED_SIGFILE)
894 self._assertFilesEqual(verify_file, signed_file)
895
896 def test_Sign_withExternalSigner_openssl(self):
897 """Uses openssl as the external payload signer."""
898 common.OPTIONS.payload_signer = 'openssl'
899 common.OPTIONS.payload_signer_args = [
900 'pkeyutl', '-sign', '-keyform', 'DER', '-inkey',
901 os.path.join(self.testdata_dir, 'testkey.pk8'),
902 '-pkeyopt', 'digest:sha256']
903 payload_signer = PayloadSigner()
904 input_file = os.path.join(self.testdata_dir, self.SIGFILE)
905 signed_file = payload_signer.Sign(input_file)
906
907 verify_file = os.path.join(self.testdata_dir, self.SIGNED_SIGFILE)
908 self._assertFilesEqual(verify_file, signed_file)
909
910 def test_Sign_withExternalSigner_script(self):
911 """Uses testdata/payload_signer.sh as the external payload signer."""
912 common.OPTIONS.payload_signer = os.path.join(
913 self.testdata_dir, 'payload_signer.sh')
914 common.OPTIONS.payload_signer_args = [
915 os.path.join(self.testdata_dir, 'testkey.pk8')]
916 payload_signer = PayloadSigner()
917 input_file = os.path.join(self.testdata_dir, self.SIGFILE)
918 signed_file = payload_signer.Sign(input_file)
919
920 verify_file = os.path.join(self.testdata_dir, self.SIGNED_SIGFILE)
921 self._assertFilesEqual(verify_file, signed_file)
Tao Baoc7b403a2018-01-30 18:19:04 -0800922
923
924class PayloadTest(unittest.TestCase):
925
926 def setUp(self):
Tao Bao04e1f012018-02-04 12:13:35 -0800927 self.testdata_dir = test_utils.get_testdata_dir()
Tao Baoc7b403a2018-01-30 18:19:04 -0800928 self.assertTrue(os.path.exists(self.testdata_dir))
929
930 common.OPTIONS.wipe_user_data = False
931 common.OPTIONS.payload_signer = None
932 common.OPTIONS.payload_signer_args = None
933 common.OPTIONS.package_key = os.path.join(self.testdata_dir, 'testkey')
934 common.OPTIONS.key_passwords = {
935 common.OPTIONS.package_key : None,
936 }
937
938 def tearDown(self):
939 common.Cleanup()
940
941 @staticmethod
Tao Baof7140c02018-01-30 17:09:24 -0800942 def _create_payload_full(secondary=False):
943 target_file = construct_target_files(secondary)
Tao Bao667ff572018-02-10 00:02:40 -0800944 payload = Payload(secondary)
Tao Baoc7b403a2018-01-30 18:19:04 -0800945 payload.Generate(target_file)
946 return payload
947
Tao Baof7140c02018-01-30 17:09:24 -0800948 @staticmethod
949 def _create_payload_incremental():
950 target_file = construct_target_files()
951 source_file = construct_target_files()
Tao Baoc7b403a2018-01-30 18:19:04 -0800952 payload = Payload()
953 payload.Generate(target_file, source_file)
954 return payload
955
956 def test_Generate_full(self):
957 payload = self._create_payload_full()
958 self.assertTrue(os.path.exists(payload.payload_file))
959
960 def test_Generate_incremental(self):
961 payload = self._create_payload_incremental()
962 self.assertTrue(os.path.exists(payload.payload_file))
963
964 def test_Generate_additionalArgs(self):
Tao Baof7140c02018-01-30 17:09:24 -0800965 target_file = construct_target_files()
966 source_file = construct_target_files()
Tao Baoc7b403a2018-01-30 18:19:04 -0800967 payload = Payload()
968 # This should work the same as calling payload.Generate(target_file,
969 # source_file).
970 payload.Generate(
971 target_file, additional_args=["--source_image", source_file])
972 self.assertTrue(os.path.exists(payload.payload_file))
973
974 def test_Generate_invalidInput(self):
Tao Baof7140c02018-01-30 17:09:24 -0800975 target_file = construct_target_files()
Tao Baoc7b403a2018-01-30 18:19:04 -0800976 common.ZipDelete(target_file, 'IMAGES/vendor.img')
977 payload = Payload()
978 self.assertRaises(AssertionError, payload.Generate, target_file)
979
980 def test_Sign_full(self):
981 payload = self._create_payload_full()
982 payload.Sign(PayloadSigner())
983
984 output_file = common.MakeTempFile(suffix='.zip')
985 with zipfile.ZipFile(output_file, 'w') as output_zip:
986 payload.WriteToZip(output_zip)
987
988 import check_ota_package_signature
989 check_ota_package_signature.VerifyAbOtaPayload(
990 os.path.join(self.testdata_dir, 'testkey.x509.pem'),
991 output_file)
992
993 def test_Sign_incremental(self):
994 payload = self._create_payload_incremental()
995 payload.Sign(PayloadSigner())
996
997 output_file = common.MakeTempFile(suffix='.zip')
998 with zipfile.ZipFile(output_file, 'w') as output_zip:
999 payload.WriteToZip(output_zip)
1000
1001 import check_ota_package_signature
1002 check_ota_package_signature.VerifyAbOtaPayload(
1003 os.path.join(self.testdata_dir, 'testkey.x509.pem'),
1004 output_file)
1005
1006 def test_Sign_withDataWipe(self):
1007 common.OPTIONS.wipe_user_data = True
1008 payload = self._create_payload_full()
1009 payload.Sign(PayloadSigner())
1010
1011 with open(payload.payload_properties) as properties_fp:
1012 self.assertIn("POWERWASH=1", properties_fp.read())
1013
Tao Bao667ff572018-02-10 00:02:40 -08001014 def test_Sign_secondary(self):
1015 payload = self._create_payload_full(secondary=True)
1016 payload.Sign(PayloadSigner())
1017
1018 with open(payload.payload_properties) as properties_fp:
1019 self.assertIn("SWITCH_SLOT_ON_REBOOT=0", properties_fp.read())
1020
Tao Baoc7b403a2018-01-30 18:19:04 -08001021 def test_Sign_badSigner(self):
1022 """Tests that signing failure can be captured."""
1023 payload = self._create_payload_full()
1024 payload_signer = PayloadSigner()
1025 payload_signer.signer_args.append('bad-option')
1026 self.assertRaises(AssertionError, payload.Sign, payload_signer)
1027
1028 def test_WriteToZip(self):
1029 payload = self._create_payload_full()
1030 payload.Sign(PayloadSigner())
1031
1032 output_file = common.MakeTempFile(suffix='.zip')
1033 with zipfile.ZipFile(output_file, 'w') as output_zip:
1034 payload.WriteToZip(output_zip)
1035
1036 with zipfile.ZipFile(output_file) as verify_zip:
1037 # First make sure we have the essential entries.
1038 namelist = verify_zip.namelist()
1039 self.assertIn(Payload.PAYLOAD_BIN, namelist)
1040 self.assertIn(Payload.PAYLOAD_PROPERTIES_TXT, namelist)
1041
1042 # Then assert these entries are stored.
1043 for entry_info in verify_zip.infolist():
1044 if entry_info.filename not in (Payload.PAYLOAD_BIN,
1045 Payload.PAYLOAD_PROPERTIES_TXT):
1046 continue
1047 self.assertEqual(zipfile.ZIP_STORED, entry_info.compress_type)
1048
1049 def test_WriteToZip_unsignedPayload(self):
1050 """Unsigned payloads should not be allowed to be written to zip."""
1051 payload = self._create_payload_full()
1052
1053 output_file = common.MakeTempFile(suffix='.zip')
1054 with zipfile.ZipFile(output_file, 'w') as output_zip:
1055 self.assertRaises(AssertionError, payload.WriteToZip, output_zip)
1056
1057 # Also test with incremental payload.
1058 payload = self._create_payload_incremental()
1059
1060 output_file = common.MakeTempFile(suffix='.zip')
1061 with zipfile.ZipFile(output_file, 'w') as output_zip:
1062 self.assertRaises(AssertionError, payload.WriteToZip, output_zip)
Tao Baof7140c02018-01-30 17:09:24 -08001063
1064 def test_WriteToZip_secondary(self):
1065 payload = self._create_payload_full(secondary=True)
1066 payload.Sign(PayloadSigner())
1067
1068 output_file = common.MakeTempFile(suffix='.zip')
1069 with zipfile.ZipFile(output_file, 'w') as output_zip:
Tao Bao667ff572018-02-10 00:02:40 -08001070 payload.WriteToZip(output_zip)
Tao Baof7140c02018-01-30 17:09:24 -08001071
1072 with zipfile.ZipFile(output_file) as verify_zip:
1073 # First make sure we have the essential entries.
1074 namelist = verify_zip.namelist()
1075 self.assertIn(Payload.SECONDARY_PAYLOAD_BIN, namelist)
1076 self.assertIn(Payload.SECONDARY_PAYLOAD_PROPERTIES_TXT, namelist)
1077
1078 # Then assert these entries are stored.
1079 for entry_info in verify_zip.infolist():
1080 if entry_info.filename not in (
1081 Payload.SECONDARY_PAYLOAD_BIN,
1082 Payload.SECONDARY_PAYLOAD_PROPERTIES_TXT):
1083 continue
1084 self.assertEqual(zipfile.ZIP_STORED, entry_info.compress_type)