test_common.py revision 8e0178d41b9eeb6754eda07292d78762e3169140
1#
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)
109