blob: 5fdc1320c9aae61c5b5ed0133152491b92fc7856 [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
21
22import common
23
24
25def random_string_with_holes(size, block_size, step_size):
26 data = ["\0"] * size
27 for begin in range(0, size, step_size):
28 end = begin + block_size
29 data[begin:end] = os.urandom(block_size)
30 return "".join(data)
31
32
33class CommonZipTest(unittest.TestCase):
34 def _test_ZipWrite(self, contents, extra_zipwrite_args=None):
35 extra_zipwrite_args = dict(extra_zipwrite_args or {})
36
37 test_file = tempfile.NamedTemporaryFile(delete=False)
38 zip_file = tempfile.NamedTemporaryFile(delete=False)
39
40 test_file_name = test_file.name
41 zip_file_name = zip_file.name
42
43 # File names within an archive strip the leading slash.
44 arcname = extra_zipwrite_args.get("arcname", test_file_name)
45 if arcname[0] == "/":
46 arcname = arcname[1:]
47
48 zip_file.close()
49 zip_file = zipfile.ZipFile(zip_file_name, "w")
50
51 try:
52 test_file.write(contents)
53 test_file.close()
54
55 old_stat = os.stat(test_file_name)
56 expected_mode = extra_zipwrite_args.get("perms", 0o644)
57
58 time.sleep(5) # Make sure the atime/mtime will change measurably.
59
60 common.ZipWrite(zip_file, test_file_name, **extra_zipwrite_args)
61
62 new_stat = os.stat(test_file_name)
63 self.assertEqual(int(old_stat.st_mode), int(new_stat.st_mode))
64 self.assertEqual(int(old_stat.st_mtime), int(new_stat.st_mtime))
Dan Albertd6d1beb2015-03-23 16:54:39 -070065 self.assertIsNone(zip_file.testzip())
Dan Albert8e0178d2015-01-27 15:53:15 -080066
67 zip_file.close()
68 zip_file = zipfile.ZipFile(zip_file_name, "r")
69 info = zip_file.getinfo(arcname)
70
71 self.assertEqual(info.date_time, (2009, 1, 1, 0, 0, 0))
72 mode = (info.external_attr >> 16) & 0o777
73 self.assertEqual(mode, expected_mode)
74 self.assertEqual(zip_file.read(arcname), contents)
Dan Albertd6d1beb2015-03-23 16:54:39 -070075 self.assertIsNone(zip_file.testzip())
Dan Albert8e0178d2015-01-27 15:53:15 -080076 finally:
77 os.remove(test_file_name)
78 os.remove(zip_file_name)
79
80 def test_ZipWrite(self):
81 file_contents = os.urandom(1024)
82 self._test_ZipWrite(file_contents)
83
84 def test_ZipWrite_with_opts(self):
85 file_contents = os.urandom(1024)
86 self._test_ZipWrite(file_contents, {
87 "arcname": "foobar",
88 "perms": 0o777,
89 "compress_type": zipfile.ZIP_DEFLATED,
90 })
91
92 def test_ZipWrite_large_file(self):
93 kilobytes = 1024
94 megabytes = 1024 * kilobytes
95 gigabytes = 1024 * megabytes
96
97 size = int(2 * gigabytes + 1)
98 block_size = 4 * kilobytes
99 step_size = 4 * megabytes
100 file_contents = random_string_with_holes(
101 size, block_size, step_size)
102 self._test_ZipWrite(file_contents, {
103 "compress_type": zipfile.ZIP_DEFLATED,
104 })
105
106 def test_ZipWrite_resets_ZIP64_LIMIT(self):
107 default_limit = (1 << 31) - 1
108 self.assertEqual(default_limit, zipfile.ZIP64_LIMIT)
109 self._test_ZipWrite('')
110 self.assertEqual(default_limit, zipfile.ZIP64_LIMIT)