blob: 6da286ce400f9e21b39c14bb13e26dbc7e1b3411 [file] [log] [blame]
Dan Albert8e0178d2015-01-27 15:53:15 -08001#
2# Copyright (C) 2015 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#
16import os
17import tempfile
18import time
19import unittest
20import zipfile
Tao Bao31b08072017-11-08 15:50:59 -080021from hashlib import sha1
22
Dan Albert8e0178d2015-01-27 15:53:15 -080023import common
Tao Bao04e1f012018-02-04 12:13:35 -080024import test_utils
Tianjie Xu9c384d22017-06-20 17:00:55 -070025import validate_target_files
Dan Albert8e0178d2015-01-27 15:53:15 -080026
Tao Bao04e1f012018-02-04 12:13:35 -080027
Tao Bao31b08072017-11-08 15:50:59 -080028KiB = 1024
29MiB = 1024 * KiB
30GiB = 1024 * MiB
Dan Albert8e0178d2015-01-27 15:53:15 -080031
Tao Bao1c830bf2017-12-25 10:43:47 -080032
Tao Baof3282b42015-04-01 11:21:55 -070033def get_2gb_string():
Tao Bao31b08072017-11-08 15:50:59 -080034 size = int(2 * GiB + 1)
35 block_size = 4 * KiB
36 step_size = 4 * MiB
37 # Generate a long string with holes, e.g. 'xyz\x00abc\x00...'.
38 for _ in range(0, size, step_size):
39 yield os.urandom(block_size)
40 yield '\0' * (step_size - block_size)
Tao Baof3282b42015-04-01 11:21:55 -070041
Dan Albert8e0178d2015-01-27 15:53:15 -080042
43class CommonZipTest(unittest.TestCase):
Tao Bao31b08072017-11-08 15:50:59 -080044 def _verify(self, zip_file, zip_file_name, arcname, expected_hash,
Tao Baof3282b42015-04-01 11:21:55 -070045 test_file_name=None, expected_stat=None, expected_mode=0o644,
46 expected_compress_type=zipfile.ZIP_STORED):
47 # Verify the stat if present.
48 if test_file_name is not None:
49 new_stat = os.stat(test_file_name)
50 self.assertEqual(int(expected_stat.st_mode), int(new_stat.st_mode))
51 self.assertEqual(int(expected_stat.st_mtime), int(new_stat.st_mtime))
52
53 # Reopen the zip file to verify.
54 zip_file = zipfile.ZipFile(zip_file_name, "r")
55
56 # Verify the timestamp.
57 info = zip_file.getinfo(arcname)
58 self.assertEqual(info.date_time, (2009, 1, 1, 0, 0, 0))
59
60 # Verify the file mode.
61 mode = (info.external_attr >> 16) & 0o777
62 self.assertEqual(mode, expected_mode)
63
64 # Verify the compress type.
65 self.assertEqual(info.compress_type, expected_compress_type)
66
67 # Verify the zip contents.
Tao Bao31b08072017-11-08 15:50:59 -080068 entry = zip_file.open(arcname)
69 sha1_hash = sha1()
70 for chunk in iter(lambda: entry.read(4 * MiB), ''):
71 sha1_hash.update(chunk)
72 self.assertEqual(expected_hash, sha1_hash.hexdigest())
Tao Baof3282b42015-04-01 11:21:55 -070073 self.assertIsNone(zip_file.testzip())
74
Dan Albert8e0178d2015-01-27 15:53:15 -080075 def _test_ZipWrite(self, contents, extra_zipwrite_args=None):
76 extra_zipwrite_args = dict(extra_zipwrite_args or {})
77
78 test_file = tempfile.NamedTemporaryFile(delete=False)
Dan Albert8e0178d2015-01-27 15:53:15 -080079 test_file_name = test_file.name
Tao Baof3282b42015-04-01 11:21:55 -070080
81 zip_file = tempfile.NamedTemporaryFile(delete=False)
Dan Albert8e0178d2015-01-27 15:53:15 -080082 zip_file_name = zip_file.name
83
84 # File names within an archive strip the leading slash.
85 arcname = extra_zipwrite_args.get("arcname", test_file_name)
86 if arcname[0] == "/":
87 arcname = arcname[1:]
88
89 zip_file.close()
90 zip_file = zipfile.ZipFile(zip_file_name, "w")
91
92 try:
Tao Bao31b08072017-11-08 15:50:59 -080093 sha1_hash = sha1()
94 for data in contents:
95 sha1_hash.update(data)
96 test_file.write(data)
Dan Albert8e0178d2015-01-27 15:53:15 -080097 test_file.close()
98
Tao Baof3282b42015-04-01 11:21:55 -070099 expected_stat = os.stat(test_file_name)
Dan Albert8e0178d2015-01-27 15:53:15 -0800100 expected_mode = extra_zipwrite_args.get("perms", 0o644)
Tao Baof3282b42015-04-01 11:21:55 -0700101 expected_compress_type = extra_zipwrite_args.get("compress_type",
102 zipfile.ZIP_STORED)
Dan Albert8e0178d2015-01-27 15:53:15 -0800103 time.sleep(5) # Make sure the atime/mtime will change measurably.
104
105 common.ZipWrite(zip_file, test_file_name, **extra_zipwrite_args)
Tao Baof3282b42015-04-01 11:21:55 -0700106 common.ZipClose(zip_file)
Dan Albert8e0178d2015-01-27 15:53:15 -0800107
Tao Bao31b08072017-11-08 15:50:59 -0800108 self._verify(zip_file, zip_file_name, arcname, sha1_hash.hexdigest(),
109 test_file_name, expected_stat, expected_mode,
110 expected_compress_type)
Dan Albert8e0178d2015-01-27 15:53:15 -0800111 finally:
112 os.remove(test_file_name)
113 os.remove(zip_file_name)
114
Tao Baof3282b42015-04-01 11:21:55 -0700115 def _test_ZipWriteStr(self, zinfo_or_arcname, contents, extra_args=None):
116 extra_args = dict(extra_args or {})
117
118 zip_file = tempfile.NamedTemporaryFile(delete=False)
119 zip_file_name = zip_file.name
120 zip_file.close()
121
122 zip_file = zipfile.ZipFile(zip_file_name, "w")
123
124 try:
125 expected_compress_type = extra_args.get("compress_type",
126 zipfile.ZIP_STORED)
127 time.sleep(5) # Make sure the atime/mtime will change measurably.
128
129 if not isinstance(zinfo_or_arcname, zipfile.ZipInfo):
Tao Bao58c1b962015-05-20 09:32:18 -0700130 arcname = zinfo_or_arcname
131 expected_mode = extra_args.get("perms", 0o644)
Tao Baof3282b42015-04-01 11:21:55 -0700132 else:
Tao Bao58c1b962015-05-20 09:32:18 -0700133 arcname = zinfo_or_arcname.filename
134 expected_mode = extra_args.get("perms",
135 zinfo_or_arcname.external_attr >> 16)
Tao Baof3282b42015-04-01 11:21:55 -0700136
Tao Bao58c1b962015-05-20 09:32:18 -0700137 common.ZipWriteStr(zip_file, zinfo_or_arcname, contents, **extra_args)
Tao Baof3282b42015-04-01 11:21:55 -0700138 common.ZipClose(zip_file)
139
Tao Bao31b08072017-11-08 15:50:59 -0800140 self._verify(zip_file, zip_file_name, arcname, sha1(contents).hexdigest(),
Tao Bao58c1b962015-05-20 09:32:18 -0700141 expected_mode=expected_mode,
Tao Baof3282b42015-04-01 11:21:55 -0700142 expected_compress_type=expected_compress_type)
143 finally:
144 os.remove(zip_file_name)
145
146 def _test_ZipWriteStr_large_file(self, large, small, extra_args=None):
147 extra_args = dict(extra_args or {})
148
149 zip_file = tempfile.NamedTemporaryFile(delete=False)
150 zip_file_name = zip_file.name
151
152 test_file = tempfile.NamedTemporaryFile(delete=False)
153 test_file_name = test_file.name
154
155 arcname_large = test_file_name
156 arcname_small = "bar"
157
158 # File names within an archive strip the leading slash.
159 if arcname_large[0] == "/":
160 arcname_large = arcname_large[1:]
161
162 zip_file.close()
163 zip_file = zipfile.ZipFile(zip_file_name, "w")
164
165 try:
Tao Bao31b08072017-11-08 15:50:59 -0800166 sha1_hash = sha1()
167 for data in large:
168 sha1_hash.update(data)
169 test_file.write(data)
Tao Baof3282b42015-04-01 11:21:55 -0700170 test_file.close()
171
172 expected_stat = os.stat(test_file_name)
173 expected_mode = 0o644
174 expected_compress_type = extra_args.get("compress_type",
175 zipfile.ZIP_STORED)
176 time.sleep(5) # Make sure the atime/mtime will change measurably.
177
178 common.ZipWrite(zip_file, test_file_name, **extra_args)
179 common.ZipWriteStr(zip_file, arcname_small, small, **extra_args)
180 common.ZipClose(zip_file)
181
182 # Verify the contents written by ZipWrite().
Tao Bao31b08072017-11-08 15:50:59 -0800183 self._verify(zip_file, zip_file_name, arcname_large,
184 sha1_hash.hexdigest(), test_file_name, expected_stat,
185 expected_mode, expected_compress_type)
Tao Baof3282b42015-04-01 11:21:55 -0700186
187 # Verify the contents written by ZipWriteStr().
Tao Bao31b08072017-11-08 15:50:59 -0800188 self._verify(zip_file, zip_file_name, arcname_small,
189 sha1(small).hexdigest(),
Tao Baof3282b42015-04-01 11:21:55 -0700190 expected_compress_type=expected_compress_type)
191 finally:
192 os.remove(zip_file_name)
193 os.remove(test_file_name)
194
195 def _test_reset_ZIP64_LIMIT(self, func, *args):
196 default_limit = (1 << 31) - 1
197 self.assertEqual(default_limit, zipfile.ZIP64_LIMIT)
198 func(*args)
199 self.assertEqual(default_limit, zipfile.ZIP64_LIMIT)
200
Dan Albert8e0178d2015-01-27 15:53:15 -0800201 def test_ZipWrite(self):
202 file_contents = os.urandom(1024)
203 self._test_ZipWrite(file_contents)
204
205 def test_ZipWrite_with_opts(self):
206 file_contents = os.urandom(1024)
207 self._test_ZipWrite(file_contents, {
208 "arcname": "foobar",
209 "perms": 0o777,
210 "compress_type": zipfile.ZIP_DEFLATED,
211 })
Tao Baof3282b42015-04-01 11:21:55 -0700212 self._test_ZipWrite(file_contents, {
213 "arcname": "foobar",
214 "perms": 0o700,
215 "compress_type": zipfile.ZIP_STORED,
216 })
Dan Albert8e0178d2015-01-27 15:53:15 -0800217
218 def test_ZipWrite_large_file(self):
Tao Baof3282b42015-04-01 11:21:55 -0700219 file_contents = get_2gb_string()
Dan Albert8e0178d2015-01-27 15:53:15 -0800220 self._test_ZipWrite(file_contents, {
221 "compress_type": zipfile.ZIP_DEFLATED,
222 })
223
224 def test_ZipWrite_resets_ZIP64_LIMIT(self):
Tao Baof3282b42015-04-01 11:21:55 -0700225 self._test_reset_ZIP64_LIMIT(self._test_ZipWrite, "")
226
227 def test_ZipWriteStr(self):
228 random_string = os.urandom(1024)
229 # Passing arcname
230 self._test_ZipWriteStr("foo", random_string)
231
232 # Passing zinfo
233 zinfo = zipfile.ZipInfo(filename="foo")
234 self._test_ZipWriteStr(zinfo, random_string)
235
236 # Timestamp in the zinfo should be overwritten.
237 zinfo.date_time = (2015, 3, 1, 15, 30, 0)
238 self._test_ZipWriteStr(zinfo, random_string)
239
240 def test_ZipWriteStr_with_opts(self):
241 random_string = os.urandom(1024)
242 # Passing arcname
243 self._test_ZipWriteStr("foo", random_string, {
Tao Bao58c1b962015-05-20 09:32:18 -0700244 "perms": 0o700,
Tao Baof3282b42015-04-01 11:21:55 -0700245 "compress_type": zipfile.ZIP_DEFLATED,
246 })
Tao Bao58c1b962015-05-20 09:32:18 -0700247 self._test_ZipWriteStr("bar", random_string, {
Tao Baof3282b42015-04-01 11:21:55 -0700248 "compress_type": zipfile.ZIP_STORED,
249 })
250
251 # Passing zinfo
252 zinfo = zipfile.ZipInfo(filename="foo")
253 self._test_ZipWriteStr(zinfo, random_string, {
254 "compress_type": zipfile.ZIP_DEFLATED,
255 })
256 self._test_ZipWriteStr(zinfo, random_string, {
Tao Bao58c1b962015-05-20 09:32:18 -0700257 "perms": 0o600,
Tao Baof3282b42015-04-01 11:21:55 -0700258 "compress_type": zipfile.ZIP_STORED,
259 })
260
261 def test_ZipWriteStr_large_file(self):
262 # zipfile.writestr() doesn't work when the str size is over 2GiB even with
263 # the workaround. We will only test the case of writing a string into a
264 # large archive.
265 long_string = get_2gb_string()
266 short_string = os.urandom(1024)
267 self._test_ZipWriteStr_large_file(long_string, short_string, {
268 "compress_type": zipfile.ZIP_DEFLATED,
269 })
270
271 def test_ZipWriteStr_resets_ZIP64_LIMIT(self):
272 self._test_reset_ZIP64_LIMIT(self._test_ZipWriteStr, "foo", "")
273 zinfo = zipfile.ZipInfo(filename="foo")
274 self._test_reset_ZIP64_LIMIT(self._test_ZipWriteStr, zinfo, "")
Tao Bao58c1b962015-05-20 09:32:18 -0700275
276 def test_bug21309935(self):
277 zip_file = tempfile.NamedTemporaryFile(delete=False)
278 zip_file_name = zip_file.name
279 zip_file.close()
280
281 try:
282 random_string = os.urandom(1024)
283 zip_file = zipfile.ZipFile(zip_file_name, "w")
284 # Default perms should be 0o644 when passing the filename.
285 common.ZipWriteStr(zip_file, "foo", random_string)
286 # Honor the specified perms.
287 common.ZipWriteStr(zip_file, "bar", random_string, perms=0o755)
288 # The perms in zinfo should be untouched.
289 zinfo = zipfile.ZipInfo(filename="baz")
290 zinfo.external_attr = 0o740 << 16
291 common.ZipWriteStr(zip_file, zinfo, random_string)
292 # Explicitly specified perms has the priority.
293 zinfo = zipfile.ZipInfo(filename="qux")
294 zinfo.external_attr = 0o700 << 16
295 common.ZipWriteStr(zip_file, zinfo, random_string, perms=0o400)
296 common.ZipClose(zip_file)
297
Tao Bao31b08072017-11-08 15:50:59 -0800298 self._verify(zip_file, zip_file_name, "foo",
299 sha1(random_string).hexdigest(),
Tao Bao58c1b962015-05-20 09:32:18 -0700300 expected_mode=0o644)
Tao Bao31b08072017-11-08 15:50:59 -0800301 self._verify(zip_file, zip_file_name, "bar",
302 sha1(random_string).hexdigest(),
Tao Bao58c1b962015-05-20 09:32:18 -0700303 expected_mode=0o755)
Tao Bao31b08072017-11-08 15:50:59 -0800304 self._verify(zip_file, zip_file_name, "baz",
305 sha1(random_string).hexdigest(),
Tao Bao58c1b962015-05-20 09:32:18 -0700306 expected_mode=0o740)
Tao Bao31b08072017-11-08 15:50:59 -0800307 self._verify(zip_file, zip_file_name, "qux",
308 sha1(random_string).hexdigest(),
Tao Bao58c1b962015-05-20 09:32:18 -0700309 expected_mode=0o400)
310 finally:
311 os.remove(zip_file_name)
Tianjie Xu9c384d22017-06-20 17:00:55 -0700312
Tao Bao89d7ab22017-12-14 17:05:33 -0800313 def test_ZipDelete(self):
314 zip_file = tempfile.NamedTemporaryFile(delete=False, suffix='.zip')
315 output_zip = zipfile.ZipFile(zip_file.name, 'w',
316 compression=zipfile.ZIP_DEFLATED)
317 with tempfile.NamedTemporaryFile() as entry_file:
318 entry_file.write(os.urandom(1024))
319 common.ZipWrite(output_zip, entry_file.name, arcname='Test1')
320 common.ZipWrite(output_zip, entry_file.name, arcname='Test2')
321 common.ZipWrite(output_zip, entry_file.name, arcname='Test3')
322 common.ZipClose(output_zip)
323 zip_file.close()
324
325 try:
326 common.ZipDelete(zip_file.name, 'Test2')
327 with zipfile.ZipFile(zip_file.name, 'r') as check_zip:
328 entries = check_zip.namelist()
329 self.assertTrue('Test1' in entries)
330 self.assertFalse('Test2' in entries)
331 self.assertTrue('Test3' in entries)
332
333 self.assertRaises(AssertionError, common.ZipDelete, zip_file.name,
334 'Test2')
335 with zipfile.ZipFile(zip_file.name, 'r') as check_zip:
336 entries = check_zip.namelist()
337 self.assertTrue('Test1' in entries)
338 self.assertFalse('Test2' in entries)
339 self.assertTrue('Test3' in entries)
340
341 common.ZipDelete(zip_file.name, ['Test3'])
342 with zipfile.ZipFile(zip_file.name, 'r') as check_zip:
343 entries = check_zip.namelist()
344 self.assertTrue('Test1' in entries)
345 self.assertFalse('Test2' in entries)
346 self.assertFalse('Test3' in entries)
347
348 common.ZipDelete(zip_file.name, ['Test1', 'Test2'])
349 with zipfile.ZipFile(zip_file.name, 'r') as check_zip:
350 entries = check_zip.namelist()
351 self.assertFalse('Test1' in entries)
352 self.assertFalse('Test2' in entries)
353 self.assertFalse('Test3' in entries)
354 finally:
355 os.remove(zip_file.name)
356
357
Tao Bao818ddf52018-01-05 11:17:34 -0800358class CommonApkUtilsTest(unittest.TestCase):
359 """Tests the APK utils related functions."""
360
361 APKCERTS_TXT1 = (
362 'name="RecoveryLocalizer.apk" certificate="certs/devkey.x509.pem"'
363 ' private_key="certs/devkey.pk8"\n'
364 'name="Settings.apk"'
365 ' certificate="build/target/product/security/platform.x509.pem"'
366 ' private_key="build/target/product/security/platform.pk8"\n'
367 'name="TV.apk" certificate="PRESIGNED" private_key=""\n'
368 )
369
370 APKCERTS_CERTMAP1 = {
371 'RecoveryLocalizer.apk' : 'certs/devkey',
372 'Settings.apk' : 'build/target/product/security/platform',
373 'TV.apk' : 'PRESIGNED',
374 }
375
376 APKCERTS_TXT2 = (
377 'name="Compressed1.apk" certificate="certs/compressed1.x509.pem"'
378 ' private_key="certs/compressed1.pk8" compressed="gz"\n'
379 'name="Compressed2a.apk" certificate="certs/compressed2.x509.pem"'
380 ' private_key="certs/compressed2.pk8" compressed="gz"\n'
381 'name="Compressed2b.apk" certificate="certs/compressed2.x509.pem"'
382 ' private_key="certs/compressed2.pk8" compressed="gz"\n'
383 'name="Compressed3.apk" certificate="certs/compressed3.x509.pem"'
384 ' private_key="certs/compressed3.pk8" compressed="gz"\n'
385 )
386
387 APKCERTS_CERTMAP2 = {
388 'Compressed1.apk' : 'certs/compressed1',
389 'Compressed2a.apk' : 'certs/compressed2',
390 'Compressed2b.apk' : 'certs/compressed2',
391 'Compressed3.apk' : 'certs/compressed3',
392 }
393
394 APKCERTS_TXT3 = (
395 'name="Compressed4.apk" certificate="certs/compressed4.x509.pem"'
396 ' private_key="certs/compressed4.pk8" compressed="xz"\n'
397 )
398
399 APKCERTS_CERTMAP3 = {
400 'Compressed4.apk' : 'certs/compressed4',
401 }
402
403 def tearDown(self):
404 common.Cleanup()
405
406 @staticmethod
407 def _write_apkcerts_txt(apkcerts_txt, additional=None):
408 if additional is None:
409 additional = []
410 target_files = common.MakeTempFile(suffix='.zip')
411 with zipfile.ZipFile(target_files, 'w') as target_files_zip:
412 target_files_zip.writestr('META/apkcerts.txt', apkcerts_txt)
413 for entry in additional:
414 target_files_zip.writestr(entry, '')
415 return target_files
416
417 def test_ReadApkCerts_NoncompressedApks(self):
418 target_files = self._write_apkcerts_txt(self.APKCERTS_TXT1)
419 with zipfile.ZipFile(target_files, 'r') as input_zip:
420 certmap, ext = common.ReadApkCerts(input_zip)
421
422 self.assertDictEqual(self.APKCERTS_CERTMAP1, certmap)
423 self.assertIsNone(ext)
424
425 def test_ReadApkCerts_CompressedApks(self):
426 # We have "installed" Compressed1.apk.gz only. Note that Compressed3.apk is
427 # not stored in '.gz' format, so it shouldn't be considered as installed.
428 target_files = self._write_apkcerts_txt(
429 self.APKCERTS_TXT2,
430 ['Compressed1.apk.gz', 'Compressed3.apk'])
431
432 with zipfile.ZipFile(target_files, 'r') as input_zip:
433 certmap, ext = common.ReadApkCerts(input_zip)
434
435 self.assertDictEqual(self.APKCERTS_CERTMAP2, certmap)
436 self.assertEqual('.gz', ext)
437
438 # Alternative case with '.xz'.
439 target_files = self._write_apkcerts_txt(
440 self.APKCERTS_TXT3, ['Compressed4.apk.xz'])
441
442 with zipfile.ZipFile(target_files, 'r') as input_zip:
443 certmap, ext = common.ReadApkCerts(input_zip)
444
445 self.assertDictEqual(self.APKCERTS_CERTMAP3, certmap)
446 self.assertEqual('.xz', ext)
447
448 def test_ReadApkCerts_CompressedAndNoncompressedApks(self):
449 target_files = self._write_apkcerts_txt(
450 self.APKCERTS_TXT1 + self.APKCERTS_TXT2,
451 ['Compressed1.apk.gz', 'Compressed3.apk'])
452
453 with zipfile.ZipFile(target_files, 'r') as input_zip:
454 certmap, ext = common.ReadApkCerts(input_zip)
455
456 certmap_merged = self.APKCERTS_CERTMAP1.copy()
457 certmap_merged.update(self.APKCERTS_CERTMAP2)
458 self.assertDictEqual(certmap_merged, certmap)
459 self.assertEqual('.gz', ext)
460
461 def test_ReadApkCerts_MultipleCompressionMethods(self):
462 target_files = self._write_apkcerts_txt(
463 self.APKCERTS_TXT2 + self.APKCERTS_TXT3,
464 ['Compressed1.apk.gz', 'Compressed4.apk.xz'])
465
466 with zipfile.ZipFile(target_files, 'r') as input_zip:
467 self.assertRaises(ValueError, common.ReadApkCerts, input_zip)
468
469 def test_ReadApkCerts_MismatchingKeys(self):
470 malformed_apkcerts_txt = (
471 'name="App1.apk" certificate="certs/cert1.x509.pem"'
472 ' private_key="certs/cert2.pk8"\n'
473 )
474 target_files = self._write_apkcerts_txt(malformed_apkcerts_txt)
475
476 with zipfile.ZipFile(target_files, 'r') as input_zip:
477 self.assertRaises(ValueError, common.ReadApkCerts, input_zip)
478
Tao Bao04e1f012018-02-04 12:13:35 -0800479 def test_ExtractPublicKey(self):
480 testdata_dir = test_utils.get_testdata_dir()
481 cert = os.path.join(testdata_dir, 'testkey.x509.pem')
482 pubkey = os.path.join(testdata_dir, 'testkey.pubkey.pem')
483 with open(pubkey, 'rb') as pubkey_fp:
484 self.assertEqual(pubkey_fp.read(), common.ExtractPublicKey(cert))
485
486 def test_ExtractPublicKey_invalidInput(self):
487 testdata_dir = test_utils.get_testdata_dir()
488 wrong_input = os.path.join(testdata_dir, 'testkey.pk8')
489 self.assertRaises(AssertionError, common.ExtractPublicKey, wrong_input)
490
Tao Bao818ddf52018-01-05 11:17:34 -0800491
Tianjie Xu9c384d22017-06-20 17:00:55 -0700492class InstallRecoveryScriptFormatTest(unittest.TestCase):
Tao Bao1c830bf2017-12-25 10:43:47 -0800493 """Checks the format of install-recovery.sh.
Tianjie Xu9c384d22017-06-20 17:00:55 -0700494
Tao Bao1c830bf2017-12-25 10:43:47 -0800495 Its format should match between common.py and validate_target_files.py.
496 """
Tianjie Xu9c384d22017-06-20 17:00:55 -0700497
498 def setUp(self):
Tao Bao1c830bf2017-12-25 10:43:47 -0800499 self._tempdir = common.MakeTempDir()
Tianjie Xu9c384d22017-06-20 17:00:55 -0700500 # Create a dummy dict that contains the fstab info for boot&recovery.
501 self._info = {"fstab" : {}}
Tao Bao1c830bf2017-12-25 10:43:47 -0800502 dummy_fstab = [
503 "/dev/soc.0/by-name/boot /boot emmc defaults defaults",
504 "/dev/soc.0/by-name/recovery /recovery emmc defaults defaults"]
Tao Bao31b08072017-11-08 15:50:59 -0800505 self._info["fstab"] = common.LoadRecoveryFSTab("\n".join, 2, dummy_fstab)
Tianjie Xudf055582017-11-07 12:22:58 -0800506 # Construct the gzipped recovery.img and boot.img
507 self.recovery_data = bytearray([
508 0x1f, 0x8b, 0x08, 0x00, 0x81, 0x11, 0x02, 0x5a, 0x00, 0x03, 0x2b, 0x4a,
509 0x4d, 0xce, 0x2f, 0x4b, 0x2d, 0xaa, 0x04, 0x00, 0xc9, 0x93, 0x43, 0xf3,
510 0x08, 0x00, 0x00, 0x00
511 ])
512 # echo -n "boot" | gzip -f | hd
513 self.boot_data = bytearray([
514 0x1f, 0x8b, 0x08, 0x00, 0x8c, 0x12, 0x02, 0x5a, 0x00, 0x03, 0x4b, 0xca,
515 0xcf, 0x2f, 0x01, 0x00, 0xc4, 0xae, 0xed, 0x46, 0x04, 0x00, 0x00, 0x00
516 ])
Tianjie Xu9c384d22017-06-20 17:00:55 -0700517
518 def _out_tmp_sink(self, name, data, prefix="SYSTEM"):
519 loc = os.path.join(self._tempdir, prefix, name)
520 if not os.path.exists(os.path.dirname(loc)):
521 os.makedirs(os.path.dirname(loc))
522 with open(loc, "w+") as f:
523 f.write(data)
524
525 def test_full_recovery(self):
Tao Bao31b08072017-11-08 15:50:59 -0800526 recovery_image = common.File("recovery.img", self.recovery_data)
527 boot_image = common.File("boot.img", self.boot_data)
Tianjie Xu9c384d22017-06-20 17:00:55 -0700528 self._info["full_recovery_image"] = "true"
529
530 common.MakeRecoveryPatch(self._tempdir, self._out_tmp_sink,
531 recovery_image, boot_image, self._info)
532 validate_target_files.ValidateInstallRecoveryScript(self._tempdir,
533 self._info)
534
535 def test_recovery_from_boot(self):
Tao Bao31b08072017-11-08 15:50:59 -0800536 recovery_image = common.File("recovery.img", self.recovery_data)
Tianjie Xu9c384d22017-06-20 17:00:55 -0700537 self._out_tmp_sink("recovery.img", recovery_image.data, "IMAGES")
Tao Bao31b08072017-11-08 15:50:59 -0800538 boot_image = common.File("boot.img", self.boot_data)
Tianjie Xu9c384d22017-06-20 17:00:55 -0700539 self._out_tmp_sink("boot.img", boot_image.data, "IMAGES")
540
541 common.MakeRecoveryPatch(self._tempdir, self._out_tmp_sink,
542 recovery_image, boot_image, self._info)
543 validate_target_files.ValidateInstallRecoveryScript(self._tempdir,
544 self._info)
545 # Validate 'recovery-from-boot' with bonus argument.
546 self._out_tmp_sink("etc/recovery-resource.dat", "bonus", "SYSTEM")
547 common.MakeRecoveryPatch(self._tempdir, self._out_tmp_sink,
548 recovery_image, boot_image, self._info)
549 validate_target_files.ValidateInstallRecoveryScript(self._tempdir,
550 self._info)
551
552 def tearDown(self):
Tao Bao1c830bf2017-12-25 10:43:47 -0800553 common.Cleanup()