blob: f163f923b739df32d490b3676cc6175bb3b4297c [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))
65
66 zip_file.close()
67 zip_file = zipfile.ZipFile(zip_file_name, "r")
68 info = zip_file.getinfo(arcname)
69
70 self.assertEqual(info.date_time, (2009, 1, 1, 0, 0, 0))
71 mode = (info.external_attr >> 16) & 0o777
72 self.assertEqual(mode, expected_mode)
73 self.assertEqual(zip_file.read(arcname), contents)
74 finally:
75 os.remove(test_file_name)
76 os.remove(zip_file_name)
77
78 def test_ZipWrite(self):
79 file_contents = os.urandom(1024)
80 self._test_ZipWrite(file_contents)
81
82 def test_ZipWrite_with_opts(self):
83 file_contents = os.urandom(1024)
84 self._test_ZipWrite(file_contents, {
85 "arcname": "foobar",
86 "perms": 0o777,
87 "compress_type": zipfile.ZIP_DEFLATED,
88 })
89
90 def test_ZipWrite_large_file(self):
91 kilobytes = 1024
92 megabytes = 1024 * kilobytes
93 gigabytes = 1024 * megabytes
94
95 size = int(2 * gigabytes + 1)
96 block_size = 4 * kilobytes
97 step_size = 4 * megabytes
98 file_contents = random_string_with_holes(
99 size, block_size, step_size)
100 self._test_ZipWrite(file_contents, {
101 "compress_type": zipfile.ZIP_DEFLATED,
102 })
103
104 def test_ZipWrite_resets_ZIP64_LIMIT(self):
105 default_limit = (1 << 31) - 1
106 self.assertEqual(default_limit, zipfile.ZIP64_LIMIT)
107 self._test_ZipWrite('')
108 self.assertEqual(default_limit, zipfile.ZIP64_LIMIT)