17db96d56Sopenharmony_ciimport array
27db96d56Sopenharmony_ciimport contextlib
37db96d56Sopenharmony_ciimport importlib.util
47db96d56Sopenharmony_ciimport io
57db96d56Sopenharmony_ciimport itertools
67db96d56Sopenharmony_ciimport os
77db96d56Sopenharmony_ciimport pathlib
87db96d56Sopenharmony_ciimport posixpath
97db96d56Sopenharmony_ciimport string
107db96d56Sopenharmony_ciimport struct
117db96d56Sopenharmony_ciimport subprocess
127db96d56Sopenharmony_ciimport sys
137db96d56Sopenharmony_cifrom test.support.script_helper import assert_python_ok
147db96d56Sopenharmony_ciimport time
157db96d56Sopenharmony_ciimport unittest
167db96d56Sopenharmony_ciimport unittest.mock as mock
177db96d56Sopenharmony_ciimport zipfile
187db96d56Sopenharmony_ciimport functools
197db96d56Sopenharmony_ci
207db96d56Sopenharmony_ci
217db96d56Sopenharmony_cifrom tempfile import TemporaryFile
227db96d56Sopenharmony_cifrom random import randint, random, randbytes
237db96d56Sopenharmony_ci
247db96d56Sopenharmony_cifrom test.support import script_helper
257db96d56Sopenharmony_cifrom test.support import (
267db96d56Sopenharmony_ci    findfile, requires_zlib, requires_bz2, requires_lzma,
277db96d56Sopenharmony_ci    captured_stdout, captured_stderr, requires_subprocess
287db96d56Sopenharmony_ci)
297db96d56Sopenharmony_cifrom test.support.os_helper import (
307db96d56Sopenharmony_ci    TESTFN, unlink, rmtree, temp_dir, temp_cwd, fd_count
317db96d56Sopenharmony_ci)
327db96d56Sopenharmony_ci
337db96d56Sopenharmony_ci
347db96d56Sopenharmony_ciTESTFN2 = TESTFN + "2"
357db96d56Sopenharmony_ciTESTFNDIR = TESTFN + "d"
367db96d56Sopenharmony_ciFIXEDTEST_SIZE = 1000
377db96d56Sopenharmony_ciDATAFILES_DIR = 'zipfile_datafiles'
387db96d56Sopenharmony_ci
397db96d56Sopenharmony_ciSMALL_TEST_DATA = [('_ziptest1', '1q2w3e4r5t'),
407db96d56Sopenharmony_ci                   ('ziptest2dir/_ziptest2', 'qawsedrftg'),
417db96d56Sopenharmony_ci                   ('ziptest2dir/ziptest3dir/_ziptest3', 'azsxdcfvgb'),
427db96d56Sopenharmony_ci                   ('ziptest2dir/ziptest3dir/ziptest4dir/_ziptest3', '6y7u8i9o0p')]
437db96d56Sopenharmony_ci
447db96d56Sopenharmony_cidef get_files(test):
457db96d56Sopenharmony_ci    yield TESTFN2
467db96d56Sopenharmony_ci    with TemporaryFile() as f:
477db96d56Sopenharmony_ci        yield f
487db96d56Sopenharmony_ci        test.assertFalse(f.closed)
497db96d56Sopenharmony_ci    with io.BytesIO() as f:
507db96d56Sopenharmony_ci        yield f
517db96d56Sopenharmony_ci        test.assertFalse(f.closed)
527db96d56Sopenharmony_ci
537db96d56Sopenharmony_ciclass AbstractTestsWithSourceFile:
547db96d56Sopenharmony_ci    @classmethod
557db96d56Sopenharmony_ci    def setUpClass(cls):
567db96d56Sopenharmony_ci        cls.line_gen = [bytes("Zipfile test line %d. random float: %f\n" %
577db96d56Sopenharmony_ci                              (i, random()), "ascii")
587db96d56Sopenharmony_ci                        for i in range(FIXEDTEST_SIZE)]
597db96d56Sopenharmony_ci        cls.data = b''.join(cls.line_gen)
607db96d56Sopenharmony_ci
617db96d56Sopenharmony_ci    def setUp(self):
627db96d56Sopenharmony_ci        # Make a source file with some lines
637db96d56Sopenharmony_ci        with open(TESTFN, "wb") as fp:
647db96d56Sopenharmony_ci            fp.write(self.data)
657db96d56Sopenharmony_ci
667db96d56Sopenharmony_ci    def make_test_archive(self, f, compression, compresslevel=None):
677db96d56Sopenharmony_ci        kwargs = {'compression': compression, 'compresslevel': compresslevel}
687db96d56Sopenharmony_ci        # Create the ZIP archive
697db96d56Sopenharmony_ci        with zipfile.ZipFile(f, "w", **kwargs) as zipfp:
707db96d56Sopenharmony_ci            zipfp.write(TESTFN, "another.name")
717db96d56Sopenharmony_ci            zipfp.write(TESTFN, TESTFN)
727db96d56Sopenharmony_ci            zipfp.writestr("strfile", self.data)
737db96d56Sopenharmony_ci            with zipfp.open('written-open-w', mode='w') as f:
747db96d56Sopenharmony_ci                for line in self.line_gen:
757db96d56Sopenharmony_ci                    f.write(line)
767db96d56Sopenharmony_ci
777db96d56Sopenharmony_ci    def zip_test(self, f, compression, compresslevel=None):
787db96d56Sopenharmony_ci        self.make_test_archive(f, compression, compresslevel)
797db96d56Sopenharmony_ci
807db96d56Sopenharmony_ci        # Read the ZIP archive
817db96d56Sopenharmony_ci        with zipfile.ZipFile(f, "r", compression) as zipfp:
827db96d56Sopenharmony_ci            self.assertEqual(zipfp.read(TESTFN), self.data)
837db96d56Sopenharmony_ci            self.assertEqual(zipfp.read("another.name"), self.data)
847db96d56Sopenharmony_ci            self.assertEqual(zipfp.read("strfile"), self.data)
857db96d56Sopenharmony_ci
867db96d56Sopenharmony_ci            # Print the ZIP directory
877db96d56Sopenharmony_ci            fp = io.StringIO()
887db96d56Sopenharmony_ci            zipfp.printdir(file=fp)
897db96d56Sopenharmony_ci            directory = fp.getvalue()
907db96d56Sopenharmony_ci            lines = directory.splitlines()
917db96d56Sopenharmony_ci            self.assertEqual(len(lines), 5) # Number of files + header
927db96d56Sopenharmony_ci
937db96d56Sopenharmony_ci            self.assertIn('File Name', lines[0])
947db96d56Sopenharmony_ci            self.assertIn('Modified', lines[0])
957db96d56Sopenharmony_ci            self.assertIn('Size', lines[0])
967db96d56Sopenharmony_ci
977db96d56Sopenharmony_ci            fn, date, time_, size = lines[1].split()
987db96d56Sopenharmony_ci            self.assertEqual(fn, 'another.name')
997db96d56Sopenharmony_ci            self.assertTrue(time.strptime(date, '%Y-%m-%d'))
1007db96d56Sopenharmony_ci            self.assertTrue(time.strptime(time_, '%H:%M:%S'))
1017db96d56Sopenharmony_ci            self.assertEqual(size, str(len(self.data)))
1027db96d56Sopenharmony_ci
1037db96d56Sopenharmony_ci            # Check the namelist
1047db96d56Sopenharmony_ci            names = zipfp.namelist()
1057db96d56Sopenharmony_ci            self.assertEqual(len(names), 4)
1067db96d56Sopenharmony_ci            self.assertIn(TESTFN, names)
1077db96d56Sopenharmony_ci            self.assertIn("another.name", names)
1087db96d56Sopenharmony_ci            self.assertIn("strfile", names)
1097db96d56Sopenharmony_ci            self.assertIn("written-open-w", names)
1107db96d56Sopenharmony_ci
1117db96d56Sopenharmony_ci            # Check infolist
1127db96d56Sopenharmony_ci            infos = zipfp.infolist()
1137db96d56Sopenharmony_ci            names = [i.filename for i in infos]
1147db96d56Sopenharmony_ci            self.assertEqual(len(names), 4)
1157db96d56Sopenharmony_ci            self.assertIn(TESTFN, names)
1167db96d56Sopenharmony_ci            self.assertIn("another.name", names)
1177db96d56Sopenharmony_ci            self.assertIn("strfile", names)
1187db96d56Sopenharmony_ci            self.assertIn("written-open-w", names)
1197db96d56Sopenharmony_ci            for i in infos:
1207db96d56Sopenharmony_ci                self.assertEqual(i.file_size, len(self.data))
1217db96d56Sopenharmony_ci
1227db96d56Sopenharmony_ci            # check getinfo
1237db96d56Sopenharmony_ci            for nm in (TESTFN, "another.name", "strfile", "written-open-w"):
1247db96d56Sopenharmony_ci                info = zipfp.getinfo(nm)
1257db96d56Sopenharmony_ci                self.assertEqual(info.filename, nm)
1267db96d56Sopenharmony_ci                self.assertEqual(info.file_size, len(self.data))
1277db96d56Sopenharmony_ci
1287db96d56Sopenharmony_ci            # Check that testzip doesn't raise an exception
1297db96d56Sopenharmony_ci            zipfp.testzip()
1307db96d56Sopenharmony_ci
1317db96d56Sopenharmony_ci    def test_basic(self):
1327db96d56Sopenharmony_ci        for f in get_files(self):
1337db96d56Sopenharmony_ci            self.zip_test(f, self.compression)
1347db96d56Sopenharmony_ci
1357db96d56Sopenharmony_ci    def zip_open_test(self, f, compression):
1367db96d56Sopenharmony_ci        self.make_test_archive(f, compression)
1377db96d56Sopenharmony_ci
1387db96d56Sopenharmony_ci        # Read the ZIP archive
1397db96d56Sopenharmony_ci        with zipfile.ZipFile(f, "r", compression) as zipfp:
1407db96d56Sopenharmony_ci            zipdata1 = []
1417db96d56Sopenharmony_ci            with zipfp.open(TESTFN) as zipopen1:
1427db96d56Sopenharmony_ci                while True:
1437db96d56Sopenharmony_ci                    read_data = zipopen1.read(256)
1447db96d56Sopenharmony_ci                    if not read_data:
1457db96d56Sopenharmony_ci                        break
1467db96d56Sopenharmony_ci                    zipdata1.append(read_data)
1477db96d56Sopenharmony_ci
1487db96d56Sopenharmony_ci            zipdata2 = []
1497db96d56Sopenharmony_ci            with zipfp.open("another.name") as zipopen2:
1507db96d56Sopenharmony_ci                while True:
1517db96d56Sopenharmony_ci                    read_data = zipopen2.read(256)
1527db96d56Sopenharmony_ci                    if not read_data:
1537db96d56Sopenharmony_ci                        break
1547db96d56Sopenharmony_ci                    zipdata2.append(read_data)
1557db96d56Sopenharmony_ci
1567db96d56Sopenharmony_ci            self.assertEqual(b''.join(zipdata1), self.data)
1577db96d56Sopenharmony_ci            self.assertEqual(b''.join(zipdata2), self.data)
1587db96d56Sopenharmony_ci
1597db96d56Sopenharmony_ci    def test_open(self):
1607db96d56Sopenharmony_ci        for f in get_files(self):
1617db96d56Sopenharmony_ci            self.zip_open_test(f, self.compression)
1627db96d56Sopenharmony_ci
1637db96d56Sopenharmony_ci    def test_open_with_pathlike(self):
1647db96d56Sopenharmony_ci        path = pathlib.Path(TESTFN2)
1657db96d56Sopenharmony_ci        self.zip_open_test(path, self.compression)
1667db96d56Sopenharmony_ci        with zipfile.ZipFile(path, "r", self.compression) as zipfp:
1677db96d56Sopenharmony_ci            self.assertIsInstance(zipfp.filename, str)
1687db96d56Sopenharmony_ci
1697db96d56Sopenharmony_ci    def zip_random_open_test(self, f, compression):
1707db96d56Sopenharmony_ci        self.make_test_archive(f, compression)
1717db96d56Sopenharmony_ci
1727db96d56Sopenharmony_ci        # Read the ZIP archive
1737db96d56Sopenharmony_ci        with zipfile.ZipFile(f, "r", compression) as zipfp:
1747db96d56Sopenharmony_ci            zipdata1 = []
1757db96d56Sopenharmony_ci            with zipfp.open(TESTFN) as zipopen1:
1767db96d56Sopenharmony_ci                while True:
1777db96d56Sopenharmony_ci                    read_data = zipopen1.read(randint(1, 1024))
1787db96d56Sopenharmony_ci                    if not read_data:
1797db96d56Sopenharmony_ci                        break
1807db96d56Sopenharmony_ci                    zipdata1.append(read_data)
1817db96d56Sopenharmony_ci
1827db96d56Sopenharmony_ci            self.assertEqual(b''.join(zipdata1), self.data)
1837db96d56Sopenharmony_ci
1847db96d56Sopenharmony_ci    def test_random_open(self):
1857db96d56Sopenharmony_ci        for f in get_files(self):
1867db96d56Sopenharmony_ci            self.zip_random_open_test(f, self.compression)
1877db96d56Sopenharmony_ci
1887db96d56Sopenharmony_ci    def zip_read1_test(self, f, compression):
1897db96d56Sopenharmony_ci        self.make_test_archive(f, compression)
1907db96d56Sopenharmony_ci
1917db96d56Sopenharmony_ci        # Read the ZIP archive
1927db96d56Sopenharmony_ci        with zipfile.ZipFile(f, "r") as zipfp, \
1937db96d56Sopenharmony_ci             zipfp.open(TESTFN) as zipopen:
1947db96d56Sopenharmony_ci            zipdata = []
1957db96d56Sopenharmony_ci            while True:
1967db96d56Sopenharmony_ci                read_data = zipopen.read1(-1)
1977db96d56Sopenharmony_ci                if not read_data:
1987db96d56Sopenharmony_ci                    break
1997db96d56Sopenharmony_ci                zipdata.append(read_data)
2007db96d56Sopenharmony_ci
2017db96d56Sopenharmony_ci        self.assertEqual(b''.join(zipdata), self.data)
2027db96d56Sopenharmony_ci
2037db96d56Sopenharmony_ci    def test_read1(self):
2047db96d56Sopenharmony_ci        for f in get_files(self):
2057db96d56Sopenharmony_ci            self.zip_read1_test(f, self.compression)
2067db96d56Sopenharmony_ci
2077db96d56Sopenharmony_ci    def zip_read1_10_test(self, f, compression):
2087db96d56Sopenharmony_ci        self.make_test_archive(f, compression)
2097db96d56Sopenharmony_ci
2107db96d56Sopenharmony_ci        # Read the ZIP archive
2117db96d56Sopenharmony_ci        with zipfile.ZipFile(f, "r") as zipfp, \
2127db96d56Sopenharmony_ci             zipfp.open(TESTFN) as zipopen:
2137db96d56Sopenharmony_ci            zipdata = []
2147db96d56Sopenharmony_ci            while True:
2157db96d56Sopenharmony_ci                read_data = zipopen.read1(10)
2167db96d56Sopenharmony_ci                self.assertLessEqual(len(read_data), 10)
2177db96d56Sopenharmony_ci                if not read_data:
2187db96d56Sopenharmony_ci                    break
2197db96d56Sopenharmony_ci                zipdata.append(read_data)
2207db96d56Sopenharmony_ci
2217db96d56Sopenharmony_ci        self.assertEqual(b''.join(zipdata), self.data)
2227db96d56Sopenharmony_ci
2237db96d56Sopenharmony_ci    def test_read1_10(self):
2247db96d56Sopenharmony_ci        for f in get_files(self):
2257db96d56Sopenharmony_ci            self.zip_read1_10_test(f, self.compression)
2267db96d56Sopenharmony_ci
2277db96d56Sopenharmony_ci    def zip_readline_read_test(self, f, compression):
2287db96d56Sopenharmony_ci        self.make_test_archive(f, compression)
2297db96d56Sopenharmony_ci
2307db96d56Sopenharmony_ci        # Read the ZIP archive
2317db96d56Sopenharmony_ci        with zipfile.ZipFile(f, "r") as zipfp, \
2327db96d56Sopenharmony_ci             zipfp.open(TESTFN) as zipopen:
2337db96d56Sopenharmony_ci            data = b''
2347db96d56Sopenharmony_ci            while True:
2357db96d56Sopenharmony_ci                read = zipopen.readline()
2367db96d56Sopenharmony_ci                if not read:
2377db96d56Sopenharmony_ci                    break
2387db96d56Sopenharmony_ci                data += read
2397db96d56Sopenharmony_ci
2407db96d56Sopenharmony_ci                read = zipopen.read(100)
2417db96d56Sopenharmony_ci                if not read:
2427db96d56Sopenharmony_ci                    break
2437db96d56Sopenharmony_ci                data += read
2447db96d56Sopenharmony_ci
2457db96d56Sopenharmony_ci        self.assertEqual(data, self.data)
2467db96d56Sopenharmony_ci
2477db96d56Sopenharmony_ci    def test_readline_read(self):
2487db96d56Sopenharmony_ci        # Issue #7610: calls to readline() interleaved with calls to read().
2497db96d56Sopenharmony_ci        for f in get_files(self):
2507db96d56Sopenharmony_ci            self.zip_readline_read_test(f, self.compression)
2517db96d56Sopenharmony_ci
2527db96d56Sopenharmony_ci    def zip_readline_test(self, f, compression):
2537db96d56Sopenharmony_ci        self.make_test_archive(f, compression)
2547db96d56Sopenharmony_ci
2557db96d56Sopenharmony_ci        # Read the ZIP archive
2567db96d56Sopenharmony_ci        with zipfile.ZipFile(f, "r") as zipfp:
2577db96d56Sopenharmony_ci            with zipfp.open(TESTFN) as zipopen:
2587db96d56Sopenharmony_ci                for line in self.line_gen:
2597db96d56Sopenharmony_ci                    linedata = zipopen.readline()
2607db96d56Sopenharmony_ci                    self.assertEqual(linedata, line)
2617db96d56Sopenharmony_ci
2627db96d56Sopenharmony_ci    def test_readline(self):
2637db96d56Sopenharmony_ci        for f in get_files(self):
2647db96d56Sopenharmony_ci            self.zip_readline_test(f, self.compression)
2657db96d56Sopenharmony_ci
2667db96d56Sopenharmony_ci    def zip_readlines_test(self, f, compression):
2677db96d56Sopenharmony_ci        self.make_test_archive(f, compression)
2687db96d56Sopenharmony_ci
2697db96d56Sopenharmony_ci        # Read the ZIP archive
2707db96d56Sopenharmony_ci        with zipfile.ZipFile(f, "r") as zipfp:
2717db96d56Sopenharmony_ci            with zipfp.open(TESTFN) as zipopen:
2727db96d56Sopenharmony_ci                ziplines = zipopen.readlines()
2737db96d56Sopenharmony_ci            for line, zipline in zip(self.line_gen, ziplines):
2747db96d56Sopenharmony_ci                self.assertEqual(zipline, line)
2757db96d56Sopenharmony_ci
2767db96d56Sopenharmony_ci    def test_readlines(self):
2777db96d56Sopenharmony_ci        for f in get_files(self):
2787db96d56Sopenharmony_ci            self.zip_readlines_test(f, self.compression)
2797db96d56Sopenharmony_ci
2807db96d56Sopenharmony_ci    def zip_iterlines_test(self, f, compression):
2817db96d56Sopenharmony_ci        self.make_test_archive(f, compression)
2827db96d56Sopenharmony_ci
2837db96d56Sopenharmony_ci        # Read the ZIP archive
2847db96d56Sopenharmony_ci        with zipfile.ZipFile(f, "r") as zipfp:
2857db96d56Sopenharmony_ci            with zipfp.open(TESTFN) as zipopen:
2867db96d56Sopenharmony_ci                for line, zipline in zip(self.line_gen, zipopen):
2877db96d56Sopenharmony_ci                    self.assertEqual(zipline, line)
2887db96d56Sopenharmony_ci
2897db96d56Sopenharmony_ci    def test_iterlines(self):
2907db96d56Sopenharmony_ci        for f in get_files(self):
2917db96d56Sopenharmony_ci            self.zip_iterlines_test(f, self.compression)
2927db96d56Sopenharmony_ci
2937db96d56Sopenharmony_ci    def test_low_compression(self):
2947db96d56Sopenharmony_ci        """Check for cases where compressed data is larger than original."""
2957db96d56Sopenharmony_ci        # Create the ZIP archive
2967db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, "w", self.compression) as zipfp:
2977db96d56Sopenharmony_ci            zipfp.writestr("strfile", '12')
2987db96d56Sopenharmony_ci
2997db96d56Sopenharmony_ci        # Get an open object for strfile
3007db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, "r", self.compression) as zipfp:
3017db96d56Sopenharmony_ci            with zipfp.open("strfile") as openobj:
3027db96d56Sopenharmony_ci                self.assertEqual(openobj.read(1), b'1')
3037db96d56Sopenharmony_ci                self.assertEqual(openobj.read(1), b'2')
3047db96d56Sopenharmony_ci
3057db96d56Sopenharmony_ci    def test_writestr_compression(self):
3067db96d56Sopenharmony_ci        zipfp = zipfile.ZipFile(TESTFN2, "w")
3077db96d56Sopenharmony_ci        zipfp.writestr("b.txt", "hello world", compress_type=self.compression)
3087db96d56Sopenharmony_ci        info = zipfp.getinfo('b.txt')
3097db96d56Sopenharmony_ci        self.assertEqual(info.compress_type, self.compression)
3107db96d56Sopenharmony_ci
3117db96d56Sopenharmony_ci    def test_writestr_compresslevel(self):
3127db96d56Sopenharmony_ci        zipfp = zipfile.ZipFile(TESTFN2, "w", compresslevel=1)
3137db96d56Sopenharmony_ci        zipfp.writestr("a.txt", "hello world", compress_type=self.compression)
3147db96d56Sopenharmony_ci        zipfp.writestr("b.txt", "hello world", compress_type=self.compression,
3157db96d56Sopenharmony_ci                       compresslevel=2)
3167db96d56Sopenharmony_ci
3177db96d56Sopenharmony_ci        # Compression level follows the constructor.
3187db96d56Sopenharmony_ci        a_info = zipfp.getinfo('a.txt')
3197db96d56Sopenharmony_ci        self.assertEqual(a_info.compress_type, self.compression)
3207db96d56Sopenharmony_ci        self.assertEqual(a_info._compresslevel, 1)
3217db96d56Sopenharmony_ci
3227db96d56Sopenharmony_ci        # Compression level is overridden.
3237db96d56Sopenharmony_ci        b_info = zipfp.getinfo('b.txt')
3247db96d56Sopenharmony_ci        self.assertEqual(b_info.compress_type, self.compression)
3257db96d56Sopenharmony_ci        self.assertEqual(b_info._compresslevel, 2)
3267db96d56Sopenharmony_ci
3277db96d56Sopenharmony_ci    def test_read_return_size(self):
3287db96d56Sopenharmony_ci        # Issue #9837: ZipExtFile.read() shouldn't return more bytes
3297db96d56Sopenharmony_ci        # than requested.
3307db96d56Sopenharmony_ci        for test_size in (1, 4095, 4096, 4097, 16384):
3317db96d56Sopenharmony_ci            file_size = test_size + 1
3327db96d56Sopenharmony_ci            junk = randbytes(file_size)
3337db96d56Sopenharmony_ci            with zipfile.ZipFile(io.BytesIO(), "w", self.compression) as zipf:
3347db96d56Sopenharmony_ci                zipf.writestr('foo', junk)
3357db96d56Sopenharmony_ci                with zipf.open('foo', 'r') as fp:
3367db96d56Sopenharmony_ci                    buf = fp.read(test_size)
3377db96d56Sopenharmony_ci                    self.assertEqual(len(buf), test_size)
3387db96d56Sopenharmony_ci
3397db96d56Sopenharmony_ci    def test_truncated_zipfile(self):
3407db96d56Sopenharmony_ci        fp = io.BytesIO()
3417db96d56Sopenharmony_ci        with zipfile.ZipFile(fp, mode='w') as zipf:
3427db96d56Sopenharmony_ci            zipf.writestr('strfile', self.data, compress_type=self.compression)
3437db96d56Sopenharmony_ci            end_offset = fp.tell()
3447db96d56Sopenharmony_ci        zipfiledata = fp.getvalue()
3457db96d56Sopenharmony_ci
3467db96d56Sopenharmony_ci        fp = io.BytesIO(zipfiledata)
3477db96d56Sopenharmony_ci        with zipfile.ZipFile(fp) as zipf:
3487db96d56Sopenharmony_ci            with zipf.open('strfile') as zipopen:
3497db96d56Sopenharmony_ci                fp.truncate(end_offset - 20)
3507db96d56Sopenharmony_ci                with self.assertRaises(EOFError):
3517db96d56Sopenharmony_ci                    zipopen.read()
3527db96d56Sopenharmony_ci
3537db96d56Sopenharmony_ci        fp = io.BytesIO(zipfiledata)
3547db96d56Sopenharmony_ci        with zipfile.ZipFile(fp) as zipf:
3557db96d56Sopenharmony_ci            with zipf.open('strfile') as zipopen:
3567db96d56Sopenharmony_ci                fp.truncate(end_offset - 20)
3577db96d56Sopenharmony_ci                with self.assertRaises(EOFError):
3587db96d56Sopenharmony_ci                    while zipopen.read(100):
3597db96d56Sopenharmony_ci                        pass
3607db96d56Sopenharmony_ci
3617db96d56Sopenharmony_ci        fp = io.BytesIO(zipfiledata)
3627db96d56Sopenharmony_ci        with zipfile.ZipFile(fp) as zipf:
3637db96d56Sopenharmony_ci            with zipf.open('strfile') as zipopen:
3647db96d56Sopenharmony_ci                fp.truncate(end_offset - 20)
3657db96d56Sopenharmony_ci                with self.assertRaises(EOFError):
3667db96d56Sopenharmony_ci                    while zipopen.read1(100):
3677db96d56Sopenharmony_ci                        pass
3687db96d56Sopenharmony_ci
3697db96d56Sopenharmony_ci    def test_repr(self):
3707db96d56Sopenharmony_ci        fname = 'file.name'
3717db96d56Sopenharmony_ci        for f in get_files(self):
3727db96d56Sopenharmony_ci            with zipfile.ZipFile(f, 'w', self.compression) as zipfp:
3737db96d56Sopenharmony_ci                zipfp.write(TESTFN, fname)
3747db96d56Sopenharmony_ci                r = repr(zipfp)
3757db96d56Sopenharmony_ci                self.assertIn("mode='w'", r)
3767db96d56Sopenharmony_ci
3777db96d56Sopenharmony_ci            with zipfile.ZipFile(f, 'r') as zipfp:
3787db96d56Sopenharmony_ci                r = repr(zipfp)
3797db96d56Sopenharmony_ci                if isinstance(f, str):
3807db96d56Sopenharmony_ci                    self.assertIn('filename=%r' % f, r)
3817db96d56Sopenharmony_ci                else:
3827db96d56Sopenharmony_ci                    self.assertIn('file=%r' % f, r)
3837db96d56Sopenharmony_ci                self.assertIn("mode='r'", r)
3847db96d56Sopenharmony_ci                r = repr(zipfp.getinfo(fname))
3857db96d56Sopenharmony_ci                self.assertIn('filename=%r' % fname, r)
3867db96d56Sopenharmony_ci                self.assertIn('filemode=', r)
3877db96d56Sopenharmony_ci                self.assertIn('file_size=', r)
3887db96d56Sopenharmony_ci                if self.compression != zipfile.ZIP_STORED:
3897db96d56Sopenharmony_ci                    self.assertIn('compress_type=', r)
3907db96d56Sopenharmony_ci                    self.assertIn('compress_size=', r)
3917db96d56Sopenharmony_ci                with zipfp.open(fname) as zipopen:
3927db96d56Sopenharmony_ci                    r = repr(zipopen)
3937db96d56Sopenharmony_ci                    self.assertIn('name=%r' % fname, r)
3947db96d56Sopenharmony_ci                    self.assertIn("mode='r'", r)
3957db96d56Sopenharmony_ci                    if self.compression != zipfile.ZIP_STORED:
3967db96d56Sopenharmony_ci                        self.assertIn('compress_type=', r)
3977db96d56Sopenharmony_ci                self.assertIn('[closed]', repr(zipopen))
3987db96d56Sopenharmony_ci            self.assertIn('[closed]', repr(zipfp))
3997db96d56Sopenharmony_ci
4007db96d56Sopenharmony_ci    def test_compresslevel_basic(self):
4017db96d56Sopenharmony_ci        for f in get_files(self):
4027db96d56Sopenharmony_ci            self.zip_test(f, self.compression, compresslevel=9)
4037db96d56Sopenharmony_ci
4047db96d56Sopenharmony_ci    def test_per_file_compresslevel(self):
4057db96d56Sopenharmony_ci        """Check that files within a Zip archive can have different
4067db96d56Sopenharmony_ci        compression levels."""
4077db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, "w", compresslevel=1) as zipfp:
4087db96d56Sopenharmony_ci            zipfp.write(TESTFN, 'compress_1')
4097db96d56Sopenharmony_ci            zipfp.write(TESTFN, 'compress_9', compresslevel=9)
4107db96d56Sopenharmony_ci            one_info = zipfp.getinfo('compress_1')
4117db96d56Sopenharmony_ci            nine_info = zipfp.getinfo('compress_9')
4127db96d56Sopenharmony_ci            self.assertEqual(one_info._compresslevel, 1)
4137db96d56Sopenharmony_ci            self.assertEqual(nine_info._compresslevel, 9)
4147db96d56Sopenharmony_ci
4157db96d56Sopenharmony_ci    def test_writing_errors(self):
4167db96d56Sopenharmony_ci        class BrokenFile(io.BytesIO):
4177db96d56Sopenharmony_ci            def write(self, data):
4187db96d56Sopenharmony_ci                nonlocal count
4197db96d56Sopenharmony_ci                if count is not None:
4207db96d56Sopenharmony_ci                    if count == stop:
4217db96d56Sopenharmony_ci                        raise OSError
4227db96d56Sopenharmony_ci                    count += 1
4237db96d56Sopenharmony_ci                super().write(data)
4247db96d56Sopenharmony_ci
4257db96d56Sopenharmony_ci        stop = 0
4267db96d56Sopenharmony_ci        while True:
4277db96d56Sopenharmony_ci            testfile = BrokenFile()
4287db96d56Sopenharmony_ci            count = None
4297db96d56Sopenharmony_ci            with zipfile.ZipFile(testfile, 'w', self.compression) as zipfp:
4307db96d56Sopenharmony_ci                with zipfp.open('file1', 'w') as f:
4317db96d56Sopenharmony_ci                    f.write(b'data1')
4327db96d56Sopenharmony_ci                count = 0
4337db96d56Sopenharmony_ci                try:
4347db96d56Sopenharmony_ci                    with zipfp.open('file2', 'w') as f:
4357db96d56Sopenharmony_ci                        f.write(b'data2')
4367db96d56Sopenharmony_ci                except OSError:
4377db96d56Sopenharmony_ci                    stop += 1
4387db96d56Sopenharmony_ci                else:
4397db96d56Sopenharmony_ci                    break
4407db96d56Sopenharmony_ci                finally:
4417db96d56Sopenharmony_ci                    count = None
4427db96d56Sopenharmony_ci            with zipfile.ZipFile(io.BytesIO(testfile.getvalue())) as zipfp:
4437db96d56Sopenharmony_ci                self.assertEqual(zipfp.namelist(), ['file1'])
4447db96d56Sopenharmony_ci                self.assertEqual(zipfp.read('file1'), b'data1')
4457db96d56Sopenharmony_ci
4467db96d56Sopenharmony_ci        with zipfile.ZipFile(io.BytesIO(testfile.getvalue())) as zipfp:
4477db96d56Sopenharmony_ci            self.assertEqual(zipfp.namelist(), ['file1', 'file2'])
4487db96d56Sopenharmony_ci            self.assertEqual(zipfp.read('file1'), b'data1')
4497db96d56Sopenharmony_ci            self.assertEqual(zipfp.read('file2'), b'data2')
4507db96d56Sopenharmony_ci
4517db96d56Sopenharmony_ci
4527db96d56Sopenharmony_ci    def tearDown(self):
4537db96d56Sopenharmony_ci        unlink(TESTFN)
4547db96d56Sopenharmony_ci        unlink(TESTFN2)
4557db96d56Sopenharmony_ci
4567db96d56Sopenharmony_ci
4577db96d56Sopenharmony_ciclass StoredTestsWithSourceFile(AbstractTestsWithSourceFile,
4587db96d56Sopenharmony_ci                                unittest.TestCase):
4597db96d56Sopenharmony_ci    compression = zipfile.ZIP_STORED
4607db96d56Sopenharmony_ci    test_low_compression = None
4617db96d56Sopenharmony_ci
4627db96d56Sopenharmony_ci    def zip_test_writestr_permissions(self, f, compression):
4637db96d56Sopenharmony_ci        # Make sure that writestr and open(... mode='w') create files with
4647db96d56Sopenharmony_ci        # mode 0600, when they are passed a name rather than a ZipInfo
4657db96d56Sopenharmony_ci        # instance.
4667db96d56Sopenharmony_ci
4677db96d56Sopenharmony_ci        self.make_test_archive(f, compression)
4687db96d56Sopenharmony_ci        with zipfile.ZipFile(f, "r") as zipfp:
4697db96d56Sopenharmony_ci            zinfo = zipfp.getinfo('strfile')
4707db96d56Sopenharmony_ci            self.assertEqual(zinfo.external_attr, 0o600 << 16)
4717db96d56Sopenharmony_ci
4727db96d56Sopenharmony_ci            zinfo2 = zipfp.getinfo('written-open-w')
4737db96d56Sopenharmony_ci            self.assertEqual(zinfo2.external_attr, 0o600 << 16)
4747db96d56Sopenharmony_ci
4757db96d56Sopenharmony_ci    def test_writestr_permissions(self):
4767db96d56Sopenharmony_ci        for f in get_files(self):
4777db96d56Sopenharmony_ci            self.zip_test_writestr_permissions(f, zipfile.ZIP_STORED)
4787db96d56Sopenharmony_ci
4797db96d56Sopenharmony_ci    def test_absolute_arcnames(self):
4807db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED) as zipfp:
4817db96d56Sopenharmony_ci            zipfp.write(TESTFN, "/absolute")
4827db96d56Sopenharmony_ci
4837db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, "r", zipfile.ZIP_STORED) as zipfp:
4847db96d56Sopenharmony_ci            self.assertEqual(zipfp.namelist(), ["absolute"])
4857db96d56Sopenharmony_ci
4867db96d56Sopenharmony_ci    def test_append_to_zip_file(self):
4877db96d56Sopenharmony_ci        """Test appending to an existing zipfile."""
4887db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED) as zipfp:
4897db96d56Sopenharmony_ci            zipfp.write(TESTFN, TESTFN)
4907db96d56Sopenharmony_ci
4917db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, "a", zipfile.ZIP_STORED) as zipfp:
4927db96d56Sopenharmony_ci            zipfp.writestr("strfile", self.data)
4937db96d56Sopenharmony_ci            self.assertEqual(zipfp.namelist(), [TESTFN, "strfile"])
4947db96d56Sopenharmony_ci
4957db96d56Sopenharmony_ci    def test_append_to_non_zip_file(self):
4967db96d56Sopenharmony_ci        """Test appending to an existing file that is not a zipfile."""
4977db96d56Sopenharmony_ci        # NOTE: this test fails if len(d) < 22 because of the first
4987db96d56Sopenharmony_ci        # line "fpin.seek(-22, 2)" in _EndRecData
4997db96d56Sopenharmony_ci        data = b'I am not a ZipFile!'*10
5007db96d56Sopenharmony_ci        with open(TESTFN2, 'wb') as f:
5017db96d56Sopenharmony_ci            f.write(data)
5027db96d56Sopenharmony_ci
5037db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, "a", zipfile.ZIP_STORED) as zipfp:
5047db96d56Sopenharmony_ci            zipfp.write(TESTFN, TESTFN)
5057db96d56Sopenharmony_ci
5067db96d56Sopenharmony_ci        with open(TESTFN2, 'rb') as f:
5077db96d56Sopenharmony_ci            f.seek(len(data))
5087db96d56Sopenharmony_ci            with zipfile.ZipFile(f, "r") as zipfp:
5097db96d56Sopenharmony_ci                self.assertEqual(zipfp.namelist(), [TESTFN])
5107db96d56Sopenharmony_ci                self.assertEqual(zipfp.read(TESTFN), self.data)
5117db96d56Sopenharmony_ci        with open(TESTFN2, 'rb') as f:
5127db96d56Sopenharmony_ci            self.assertEqual(f.read(len(data)), data)
5137db96d56Sopenharmony_ci            zipfiledata = f.read()
5147db96d56Sopenharmony_ci        with io.BytesIO(zipfiledata) as bio, zipfile.ZipFile(bio) as zipfp:
5157db96d56Sopenharmony_ci            self.assertEqual(zipfp.namelist(), [TESTFN])
5167db96d56Sopenharmony_ci            self.assertEqual(zipfp.read(TESTFN), self.data)
5177db96d56Sopenharmony_ci
5187db96d56Sopenharmony_ci    def test_read_concatenated_zip_file(self):
5197db96d56Sopenharmony_ci        with io.BytesIO() as bio:
5207db96d56Sopenharmony_ci            with zipfile.ZipFile(bio, 'w', zipfile.ZIP_STORED) as zipfp:
5217db96d56Sopenharmony_ci                zipfp.write(TESTFN, TESTFN)
5227db96d56Sopenharmony_ci            zipfiledata = bio.getvalue()
5237db96d56Sopenharmony_ci        data = b'I am not a ZipFile!'*10
5247db96d56Sopenharmony_ci        with open(TESTFN2, 'wb') as f:
5257db96d56Sopenharmony_ci            f.write(data)
5267db96d56Sopenharmony_ci            f.write(zipfiledata)
5277db96d56Sopenharmony_ci
5287db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2) as zipfp:
5297db96d56Sopenharmony_ci            self.assertEqual(zipfp.namelist(), [TESTFN])
5307db96d56Sopenharmony_ci            self.assertEqual(zipfp.read(TESTFN), self.data)
5317db96d56Sopenharmony_ci
5327db96d56Sopenharmony_ci    def test_append_to_concatenated_zip_file(self):
5337db96d56Sopenharmony_ci        with io.BytesIO() as bio:
5347db96d56Sopenharmony_ci            with zipfile.ZipFile(bio, 'w', zipfile.ZIP_STORED) as zipfp:
5357db96d56Sopenharmony_ci                zipfp.write(TESTFN, TESTFN)
5367db96d56Sopenharmony_ci            zipfiledata = bio.getvalue()
5377db96d56Sopenharmony_ci        data = b'I am not a ZipFile!'*1000000
5387db96d56Sopenharmony_ci        with open(TESTFN2, 'wb') as f:
5397db96d56Sopenharmony_ci            f.write(data)
5407db96d56Sopenharmony_ci            f.write(zipfiledata)
5417db96d56Sopenharmony_ci
5427db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, 'a') as zipfp:
5437db96d56Sopenharmony_ci            self.assertEqual(zipfp.namelist(), [TESTFN])
5447db96d56Sopenharmony_ci            zipfp.writestr('strfile', self.data)
5457db96d56Sopenharmony_ci
5467db96d56Sopenharmony_ci        with open(TESTFN2, 'rb') as f:
5477db96d56Sopenharmony_ci            self.assertEqual(f.read(len(data)), data)
5487db96d56Sopenharmony_ci            zipfiledata = f.read()
5497db96d56Sopenharmony_ci        with io.BytesIO(zipfiledata) as bio, zipfile.ZipFile(bio) as zipfp:
5507db96d56Sopenharmony_ci            self.assertEqual(zipfp.namelist(), [TESTFN, 'strfile'])
5517db96d56Sopenharmony_ci            self.assertEqual(zipfp.read(TESTFN), self.data)
5527db96d56Sopenharmony_ci            self.assertEqual(zipfp.read('strfile'), self.data)
5537db96d56Sopenharmony_ci
5547db96d56Sopenharmony_ci    def test_ignores_newline_at_end(self):
5557db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED) as zipfp:
5567db96d56Sopenharmony_ci            zipfp.write(TESTFN, TESTFN)
5577db96d56Sopenharmony_ci        with open(TESTFN2, 'a', encoding='utf-8') as f:
5587db96d56Sopenharmony_ci            f.write("\r\n\00\00\00")
5597db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, "r") as zipfp:
5607db96d56Sopenharmony_ci            self.assertIsInstance(zipfp, zipfile.ZipFile)
5617db96d56Sopenharmony_ci
5627db96d56Sopenharmony_ci    def test_ignores_stuff_appended_past_comments(self):
5637db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED) as zipfp:
5647db96d56Sopenharmony_ci            zipfp.comment = b"this is a comment"
5657db96d56Sopenharmony_ci            zipfp.write(TESTFN, TESTFN)
5667db96d56Sopenharmony_ci        with open(TESTFN2, 'a', encoding='utf-8') as f:
5677db96d56Sopenharmony_ci            f.write("abcdef\r\n")
5687db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, "r") as zipfp:
5697db96d56Sopenharmony_ci            self.assertIsInstance(zipfp, zipfile.ZipFile)
5707db96d56Sopenharmony_ci            self.assertEqual(zipfp.comment, b"this is a comment")
5717db96d56Sopenharmony_ci
5727db96d56Sopenharmony_ci    def test_write_default_name(self):
5737db96d56Sopenharmony_ci        """Check that calling ZipFile.write without arcname specified
5747db96d56Sopenharmony_ci        produces the expected result."""
5757db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, "w") as zipfp:
5767db96d56Sopenharmony_ci            zipfp.write(TESTFN)
5777db96d56Sopenharmony_ci            with open(TESTFN, "rb") as f:
5787db96d56Sopenharmony_ci                self.assertEqual(zipfp.read(TESTFN), f.read())
5797db96d56Sopenharmony_ci
5807db96d56Sopenharmony_ci    def test_io_on_closed_zipextfile(self):
5817db96d56Sopenharmony_ci        fname = "somefile.txt"
5827db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, mode="w") as zipfp:
5837db96d56Sopenharmony_ci            zipfp.writestr(fname, "bogus")
5847db96d56Sopenharmony_ci
5857db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, mode="r") as zipfp:
5867db96d56Sopenharmony_ci            with zipfp.open(fname) as fid:
5877db96d56Sopenharmony_ci                fid.close()
5887db96d56Sopenharmony_ci                self.assertRaises(ValueError, fid.read)
5897db96d56Sopenharmony_ci                self.assertRaises(ValueError, fid.seek, 0)
5907db96d56Sopenharmony_ci                self.assertRaises(ValueError, fid.tell)
5917db96d56Sopenharmony_ci                self.assertRaises(ValueError, fid.readable)
5927db96d56Sopenharmony_ci                self.assertRaises(ValueError, fid.seekable)
5937db96d56Sopenharmony_ci
5947db96d56Sopenharmony_ci    def test_write_to_readonly(self):
5957db96d56Sopenharmony_ci        """Check that trying to call write() on a readonly ZipFile object
5967db96d56Sopenharmony_ci        raises a ValueError."""
5977db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, mode="w") as zipfp:
5987db96d56Sopenharmony_ci            zipfp.writestr("somefile.txt", "bogus")
5997db96d56Sopenharmony_ci
6007db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, mode="r") as zipfp:
6017db96d56Sopenharmony_ci            self.assertRaises(ValueError, zipfp.write, TESTFN)
6027db96d56Sopenharmony_ci
6037db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, mode="r") as zipfp:
6047db96d56Sopenharmony_ci            with self.assertRaises(ValueError):
6057db96d56Sopenharmony_ci                zipfp.open(TESTFN, mode='w')
6067db96d56Sopenharmony_ci
6077db96d56Sopenharmony_ci    def test_add_file_before_1980(self):
6087db96d56Sopenharmony_ci        # Set atime and mtime to 1970-01-01
6097db96d56Sopenharmony_ci        os.utime(TESTFN, (0, 0))
6107db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, "w") as zipfp:
6117db96d56Sopenharmony_ci            self.assertRaises(ValueError, zipfp.write, TESTFN)
6127db96d56Sopenharmony_ci
6137db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, "w", strict_timestamps=False) as zipfp:
6147db96d56Sopenharmony_ci            zipfp.write(TESTFN)
6157db96d56Sopenharmony_ci            zinfo = zipfp.getinfo(TESTFN)
6167db96d56Sopenharmony_ci            self.assertEqual(zinfo.date_time, (1980, 1, 1, 0, 0, 0))
6177db96d56Sopenharmony_ci
6187db96d56Sopenharmony_ci    def test_add_file_after_2107(self):
6197db96d56Sopenharmony_ci        # Set atime and mtime to 2108-12-30
6207db96d56Sopenharmony_ci        ts = 4386268800
6217db96d56Sopenharmony_ci        try:
6227db96d56Sopenharmony_ci            time.localtime(ts)
6237db96d56Sopenharmony_ci        except OverflowError:
6247db96d56Sopenharmony_ci            self.skipTest(f'time.localtime({ts}) raises OverflowError')
6257db96d56Sopenharmony_ci        try:
6267db96d56Sopenharmony_ci            os.utime(TESTFN, (ts, ts))
6277db96d56Sopenharmony_ci        except OverflowError:
6287db96d56Sopenharmony_ci            self.skipTest('Host fs cannot set timestamp to required value.')
6297db96d56Sopenharmony_ci
6307db96d56Sopenharmony_ci        mtime_ns = os.stat(TESTFN).st_mtime_ns
6317db96d56Sopenharmony_ci        if mtime_ns != (4386268800 * 10**9):
6327db96d56Sopenharmony_ci            # XFS filesystem is limited to 32-bit timestamp, but the syscall
6337db96d56Sopenharmony_ci            # didn't fail. Moreover, there is a VFS bug which returns
6347db96d56Sopenharmony_ci            # a cached timestamp which is different than the value on disk.
6357db96d56Sopenharmony_ci            #
6367db96d56Sopenharmony_ci            # Test st_mtime_ns rather than st_mtime to avoid rounding issues.
6377db96d56Sopenharmony_ci            #
6387db96d56Sopenharmony_ci            # https://bugzilla.redhat.com/show_bug.cgi?id=1795576
6397db96d56Sopenharmony_ci            # https://bugs.python.org/issue39460#msg360952
6407db96d56Sopenharmony_ci            self.skipTest(f"Linux VFS/XFS kernel bug detected: {mtime_ns=}")
6417db96d56Sopenharmony_ci
6427db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, "w") as zipfp:
6437db96d56Sopenharmony_ci            self.assertRaises(struct.error, zipfp.write, TESTFN)
6447db96d56Sopenharmony_ci
6457db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, "w", strict_timestamps=False) as zipfp:
6467db96d56Sopenharmony_ci            zipfp.write(TESTFN)
6477db96d56Sopenharmony_ci            zinfo = zipfp.getinfo(TESTFN)
6487db96d56Sopenharmony_ci            self.assertEqual(zinfo.date_time, (2107, 12, 31, 23, 59, 59))
6497db96d56Sopenharmony_ci
6507db96d56Sopenharmony_ci
6517db96d56Sopenharmony_ci@requires_zlib()
6527db96d56Sopenharmony_ciclass DeflateTestsWithSourceFile(AbstractTestsWithSourceFile,
6537db96d56Sopenharmony_ci                                 unittest.TestCase):
6547db96d56Sopenharmony_ci    compression = zipfile.ZIP_DEFLATED
6557db96d56Sopenharmony_ci
6567db96d56Sopenharmony_ci    def test_per_file_compression(self):
6577db96d56Sopenharmony_ci        """Check that files within a Zip archive can have different
6587db96d56Sopenharmony_ci        compression options."""
6597db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, "w") as zipfp:
6607db96d56Sopenharmony_ci            zipfp.write(TESTFN, 'storeme', zipfile.ZIP_STORED)
6617db96d56Sopenharmony_ci            zipfp.write(TESTFN, 'deflateme', zipfile.ZIP_DEFLATED)
6627db96d56Sopenharmony_ci            sinfo = zipfp.getinfo('storeme')
6637db96d56Sopenharmony_ci            dinfo = zipfp.getinfo('deflateme')
6647db96d56Sopenharmony_ci            self.assertEqual(sinfo.compress_type, zipfile.ZIP_STORED)
6657db96d56Sopenharmony_ci            self.assertEqual(dinfo.compress_type, zipfile.ZIP_DEFLATED)
6667db96d56Sopenharmony_ci
6677db96d56Sopenharmony_ci@requires_bz2()
6687db96d56Sopenharmony_ciclass Bzip2TestsWithSourceFile(AbstractTestsWithSourceFile,
6697db96d56Sopenharmony_ci                               unittest.TestCase):
6707db96d56Sopenharmony_ci    compression = zipfile.ZIP_BZIP2
6717db96d56Sopenharmony_ci
6727db96d56Sopenharmony_ci@requires_lzma()
6737db96d56Sopenharmony_ciclass LzmaTestsWithSourceFile(AbstractTestsWithSourceFile,
6747db96d56Sopenharmony_ci                              unittest.TestCase):
6757db96d56Sopenharmony_ci    compression = zipfile.ZIP_LZMA
6767db96d56Sopenharmony_ci
6777db96d56Sopenharmony_ci
6787db96d56Sopenharmony_ciclass AbstractTestZip64InSmallFiles:
6797db96d56Sopenharmony_ci    # These tests test the ZIP64 functionality without using large files,
6807db96d56Sopenharmony_ci    # see test_zipfile64 for proper tests.
6817db96d56Sopenharmony_ci
6827db96d56Sopenharmony_ci    @classmethod
6837db96d56Sopenharmony_ci    def setUpClass(cls):
6847db96d56Sopenharmony_ci        line_gen = (bytes("Test of zipfile line %d." % i, "ascii")
6857db96d56Sopenharmony_ci                    for i in range(0, FIXEDTEST_SIZE))
6867db96d56Sopenharmony_ci        cls.data = b'\n'.join(line_gen)
6877db96d56Sopenharmony_ci
6887db96d56Sopenharmony_ci    def setUp(self):
6897db96d56Sopenharmony_ci        self._limit = zipfile.ZIP64_LIMIT
6907db96d56Sopenharmony_ci        self._filecount_limit = zipfile.ZIP_FILECOUNT_LIMIT
6917db96d56Sopenharmony_ci        zipfile.ZIP64_LIMIT = 1000
6927db96d56Sopenharmony_ci        zipfile.ZIP_FILECOUNT_LIMIT = 9
6937db96d56Sopenharmony_ci
6947db96d56Sopenharmony_ci        # Make a source file with some lines
6957db96d56Sopenharmony_ci        with open(TESTFN, "wb") as fp:
6967db96d56Sopenharmony_ci            fp.write(self.data)
6977db96d56Sopenharmony_ci
6987db96d56Sopenharmony_ci    def zip_test(self, f, compression):
6997db96d56Sopenharmony_ci        # Create the ZIP archive
7007db96d56Sopenharmony_ci        with zipfile.ZipFile(f, "w", compression, allowZip64=True) as zipfp:
7017db96d56Sopenharmony_ci            zipfp.write(TESTFN, "another.name")
7027db96d56Sopenharmony_ci            zipfp.write(TESTFN, TESTFN)
7037db96d56Sopenharmony_ci            zipfp.writestr("strfile", self.data)
7047db96d56Sopenharmony_ci
7057db96d56Sopenharmony_ci        # Read the ZIP archive
7067db96d56Sopenharmony_ci        with zipfile.ZipFile(f, "r", compression) as zipfp:
7077db96d56Sopenharmony_ci            self.assertEqual(zipfp.read(TESTFN), self.data)
7087db96d56Sopenharmony_ci            self.assertEqual(zipfp.read("another.name"), self.data)
7097db96d56Sopenharmony_ci            self.assertEqual(zipfp.read("strfile"), self.data)
7107db96d56Sopenharmony_ci
7117db96d56Sopenharmony_ci            # Print the ZIP directory
7127db96d56Sopenharmony_ci            fp = io.StringIO()
7137db96d56Sopenharmony_ci            zipfp.printdir(fp)
7147db96d56Sopenharmony_ci
7157db96d56Sopenharmony_ci            directory = fp.getvalue()
7167db96d56Sopenharmony_ci            lines = directory.splitlines()
7177db96d56Sopenharmony_ci            self.assertEqual(len(lines), 4) # Number of files + header
7187db96d56Sopenharmony_ci
7197db96d56Sopenharmony_ci            self.assertIn('File Name', lines[0])
7207db96d56Sopenharmony_ci            self.assertIn('Modified', lines[0])
7217db96d56Sopenharmony_ci            self.assertIn('Size', lines[0])
7227db96d56Sopenharmony_ci
7237db96d56Sopenharmony_ci            fn, date, time_, size = lines[1].split()
7247db96d56Sopenharmony_ci            self.assertEqual(fn, 'another.name')
7257db96d56Sopenharmony_ci            self.assertTrue(time.strptime(date, '%Y-%m-%d'))
7267db96d56Sopenharmony_ci            self.assertTrue(time.strptime(time_, '%H:%M:%S'))
7277db96d56Sopenharmony_ci            self.assertEqual(size, str(len(self.data)))
7287db96d56Sopenharmony_ci
7297db96d56Sopenharmony_ci            # Check the namelist
7307db96d56Sopenharmony_ci            names = zipfp.namelist()
7317db96d56Sopenharmony_ci            self.assertEqual(len(names), 3)
7327db96d56Sopenharmony_ci            self.assertIn(TESTFN, names)
7337db96d56Sopenharmony_ci            self.assertIn("another.name", names)
7347db96d56Sopenharmony_ci            self.assertIn("strfile", names)
7357db96d56Sopenharmony_ci
7367db96d56Sopenharmony_ci            # Check infolist
7377db96d56Sopenharmony_ci            infos = zipfp.infolist()
7387db96d56Sopenharmony_ci            names = [i.filename for i in infos]
7397db96d56Sopenharmony_ci            self.assertEqual(len(names), 3)
7407db96d56Sopenharmony_ci            self.assertIn(TESTFN, names)
7417db96d56Sopenharmony_ci            self.assertIn("another.name", names)
7427db96d56Sopenharmony_ci            self.assertIn("strfile", names)
7437db96d56Sopenharmony_ci            for i in infos:
7447db96d56Sopenharmony_ci                self.assertEqual(i.file_size, len(self.data))
7457db96d56Sopenharmony_ci
7467db96d56Sopenharmony_ci            # check getinfo
7477db96d56Sopenharmony_ci            for nm in (TESTFN, "another.name", "strfile"):
7487db96d56Sopenharmony_ci                info = zipfp.getinfo(nm)
7497db96d56Sopenharmony_ci                self.assertEqual(info.filename, nm)
7507db96d56Sopenharmony_ci                self.assertEqual(info.file_size, len(self.data))
7517db96d56Sopenharmony_ci
7527db96d56Sopenharmony_ci            # Check that testzip doesn't raise an exception
7537db96d56Sopenharmony_ci            zipfp.testzip()
7547db96d56Sopenharmony_ci
7557db96d56Sopenharmony_ci    def test_basic(self):
7567db96d56Sopenharmony_ci        for f in get_files(self):
7577db96d56Sopenharmony_ci            self.zip_test(f, self.compression)
7587db96d56Sopenharmony_ci
7597db96d56Sopenharmony_ci    def test_too_many_files(self):
7607db96d56Sopenharmony_ci        # This test checks that more than 64k files can be added to an archive,
7617db96d56Sopenharmony_ci        # and that the resulting archive can be read properly by ZipFile
7627db96d56Sopenharmony_ci        zipf = zipfile.ZipFile(TESTFN, "w", self.compression,
7637db96d56Sopenharmony_ci                               allowZip64=True)
7647db96d56Sopenharmony_ci        zipf.debug = 100
7657db96d56Sopenharmony_ci        numfiles = 15
7667db96d56Sopenharmony_ci        for i in range(numfiles):
7677db96d56Sopenharmony_ci            zipf.writestr("foo%08d" % i, "%d" % (i**3 % 57))
7687db96d56Sopenharmony_ci        self.assertEqual(len(zipf.namelist()), numfiles)
7697db96d56Sopenharmony_ci        zipf.close()
7707db96d56Sopenharmony_ci
7717db96d56Sopenharmony_ci        zipf2 = zipfile.ZipFile(TESTFN, "r", self.compression)
7727db96d56Sopenharmony_ci        self.assertEqual(len(zipf2.namelist()), numfiles)
7737db96d56Sopenharmony_ci        for i in range(numfiles):
7747db96d56Sopenharmony_ci            content = zipf2.read("foo%08d" % i).decode('ascii')
7757db96d56Sopenharmony_ci            self.assertEqual(content, "%d" % (i**3 % 57))
7767db96d56Sopenharmony_ci        zipf2.close()
7777db96d56Sopenharmony_ci
7787db96d56Sopenharmony_ci    def test_too_many_files_append(self):
7797db96d56Sopenharmony_ci        zipf = zipfile.ZipFile(TESTFN, "w", self.compression,
7807db96d56Sopenharmony_ci                               allowZip64=False)
7817db96d56Sopenharmony_ci        zipf.debug = 100
7827db96d56Sopenharmony_ci        numfiles = 9
7837db96d56Sopenharmony_ci        for i in range(numfiles):
7847db96d56Sopenharmony_ci            zipf.writestr("foo%08d" % i, "%d" % (i**3 % 57))
7857db96d56Sopenharmony_ci        self.assertEqual(len(zipf.namelist()), numfiles)
7867db96d56Sopenharmony_ci        with self.assertRaises(zipfile.LargeZipFile):
7877db96d56Sopenharmony_ci            zipf.writestr("foo%08d" % numfiles, b'')
7887db96d56Sopenharmony_ci        self.assertEqual(len(zipf.namelist()), numfiles)
7897db96d56Sopenharmony_ci        zipf.close()
7907db96d56Sopenharmony_ci
7917db96d56Sopenharmony_ci        zipf = zipfile.ZipFile(TESTFN, "a", self.compression,
7927db96d56Sopenharmony_ci                               allowZip64=False)
7937db96d56Sopenharmony_ci        zipf.debug = 100
7947db96d56Sopenharmony_ci        self.assertEqual(len(zipf.namelist()), numfiles)
7957db96d56Sopenharmony_ci        with self.assertRaises(zipfile.LargeZipFile):
7967db96d56Sopenharmony_ci            zipf.writestr("foo%08d" % numfiles, b'')
7977db96d56Sopenharmony_ci        self.assertEqual(len(zipf.namelist()), numfiles)
7987db96d56Sopenharmony_ci        zipf.close()
7997db96d56Sopenharmony_ci
8007db96d56Sopenharmony_ci        zipf = zipfile.ZipFile(TESTFN, "a", self.compression,
8017db96d56Sopenharmony_ci                               allowZip64=True)
8027db96d56Sopenharmony_ci        zipf.debug = 100
8037db96d56Sopenharmony_ci        self.assertEqual(len(zipf.namelist()), numfiles)
8047db96d56Sopenharmony_ci        numfiles2 = 15
8057db96d56Sopenharmony_ci        for i in range(numfiles, numfiles2):
8067db96d56Sopenharmony_ci            zipf.writestr("foo%08d" % i, "%d" % (i**3 % 57))
8077db96d56Sopenharmony_ci        self.assertEqual(len(zipf.namelist()), numfiles2)
8087db96d56Sopenharmony_ci        zipf.close()
8097db96d56Sopenharmony_ci
8107db96d56Sopenharmony_ci        zipf2 = zipfile.ZipFile(TESTFN, "r", self.compression)
8117db96d56Sopenharmony_ci        self.assertEqual(len(zipf2.namelist()), numfiles2)
8127db96d56Sopenharmony_ci        for i in range(numfiles2):
8137db96d56Sopenharmony_ci            content = zipf2.read("foo%08d" % i).decode('ascii')
8147db96d56Sopenharmony_ci            self.assertEqual(content, "%d" % (i**3 % 57))
8157db96d56Sopenharmony_ci        zipf2.close()
8167db96d56Sopenharmony_ci
8177db96d56Sopenharmony_ci    def tearDown(self):
8187db96d56Sopenharmony_ci        zipfile.ZIP64_LIMIT = self._limit
8197db96d56Sopenharmony_ci        zipfile.ZIP_FILECOUNT_LIMIT = self._filecount_limit
8207db96d56Sopenharmony_ci        unlink(TESTFN)
8217db96d56Sopenharmony_ci        unlink(TESTFN2)
8227db96d56Sopenharmony_ci
8237db96d56Sopenharmony_ci
8247db96d56Sopenharmony_ciclass StoredTestZip64InSmallFiles(AbstractTestZip64InSmallFiles,
8257db96d56Sopenharmony_ci                                  unittest.TestCase):
8267db96d56Sopenharmony_ci    compression = zipfile.ZIP_STORED
8277db96d56Sopenharmony_ci
8287db96d56Sopenharmony_ci    def large_file_exception_test(self, f, compression):
8297db96d56Sopenharmony_ci        with zipfile.ZipFile(f, "w", compression, allowZip64=False) as zipfp:
8307db96d56Sopenharmony_ci            self.assertRaises(zipfile.LargeZipFile,
8317db96d56Sopenharmony_ci                              zipfp.write, TESTFN, "another.name")
8327db96d56Sopenharmony_ci
8337db96d56Sopenharmony_ci    def large_file_exception_test2(self, f, compression):
8347db96d56Sopenharmony_ci        with zipfile.ZipFile(f, "w", compression, allowZip64=False) as zipfp:
8357db96d56Sopenharmony_ci            self.assertRaises(zipfile.LargeZipFile,
8367db96d56Sopenharmony_ci                              zipfp.writestr, "another.name", self.data)
8377db96d56Sopenharmony_ci
8387db96d56Sopenharmony_ci    def test_large_file_exception(self):
8397db96d56Sopenharmony_ci        for f in get_files(self):
8407db96d56Sopenharmony_ci            self.large_file_exception_test(f, zipfile.ZIP_STORED)
8417db96d56Sopenharmony_ci            self.large_file_exception_test2(f, zipfile.ZIP_STORED)
8427db96d56Sopenharmony_ci
8437db96d56Sopenharmony_ci    def test_absolute_arcnames(self):
8447db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED,
8457db96d56Sopenharmony_ci                             allowZip64=True) as zipfp:
8467db96d56Sopenharmony_ci            zipfp.write(TESTFN, "/absolute")
8477db96d56Sopenharmony_ci
8487db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, "r", zipfile.ZIP_STORED) as zipfp:
8497db96d56Sopenharmony_ci            self.assertEqual(zipfp.namelist(), ["absolute"])
8507db96d56Sopenharmony_ci
8517db96d56Sopenharmony_ci    def test_append(self):
8527db96d56Sopenharmony_ci        # Test that appending to the Zip64 archive doesn't change
8537db96d56Sopenharmony_ci        # extra fields of existing entries.
8547db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, "w", allowZip64=True) as zipfp:
8557db96d56Sopenharmony_ci            zipfp.writestr("strfile", self.data)
8567db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, "r", allowZip64=True) as zipfp:
8577db96d56Sopenharmony_ci            zinfo = zipfp.getinfo("strfile")
8587db96d56Sopenharmony_ci            extra = zinfo.extra
8597db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, "a", allowZip64=True) as zipfp:
8607db96d56Sopenharmony_ci            zipfp.writestr("strfile2", self.data)
8617db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, "r", allowZip64=True) as zipfp:
8627db96d56Sopenharmony_ci            zinfo = zipfp.getinfo("strfile")
8637db96d56Sopenharmony_ci            self.assertEqual(zinfo.extra, extra)
8647db96d56Sopenharmony_ci
8657db96d56Sopenharmony_ci    def make_zip64_file(
8667db96d56Sopenharmony_ci        self, file_size_64_set=False, file_size_extra=False,
8677db96d56Sopenharmony_ci        compress_size_64_set=False, compress_size_extra=False,
8687db96d56Sopenharmony_ci        header_offset_64_set=False, header_offset_extra=False,
8697db96d56Sopenharmony_ci    ):
8707db96d56Sopenharmony_ci        """Generate bytes sequence for a zip with (incomplete) zip64 data.
8717db96d56Sopenharmony_ci
8727db96d56Sopenharmony_ci        The actual values (not the zip 64 0xffffffff values) stored in the file
8737db96d56Sopenharmony_ci        are:
8747db96d56Sopenharmony_ci        file_size: 8
8757db96d56Sopenharmony_ci        compress_size: 8
8767db96d56Sopenharmony_ci        header_offset: 0
8777db96d56Sopenharmony_ci        """
8787db96d56Sopenharmony_ci        actual_size = 8
8797db96d56Sopenharmony_ci        actual_header_offset = 0
8807db96d56Sopenharmony_ci        local_zip64_fields = []
8817db96d56Sopenharmony_ci        central_zip64_fields = []
8827db96d56Sopenharmony_ci
8837db96d56Sopenharmony_ci        file_size = actual_size
8847db96d56Sopenharmony_ci        if file_size_64_set:
8857db96d56Sopenharmony_ci            file_size = 0xffffffff
8867db96d56Sopenharmony_ci            if file_size_extra:
8877db96d56Sopenharmony_ci                local_zip64_fields.append(actual_size)
8887db96d56Sopenharmony_ci                central_zip64_fields.append(actual_size)
8897db96d56Sopenharmony_ci        file_size = struct.pack("<L", file_size)
8907db96d56Sopenharmony_ci
8917db96d56Sopenharmony_ci        compress_size = actual_size
8927db96d56Sopenharmony_ci        if compress_size_64_set:
8937db96d56Sopenharmony_ci            compress_size = 0xffffffff
8947db96d56Sopenharmony_ci            if compress_size_extra:
8957db96d56Sopenharmony_ci                local_zip64_fields.append(actual_size)
8967db96d56Sopenharmony_ci                central_zip64_fields.append(actual_size)
8977db96d56Sopenharmony_ci        compress_size = struct.pack("<L", compress_size)
8987db96d56Sopenharmony_ci
8997db96d56Sopenharmony_ci        header_offset = actual_header_offset
9007db96d56Sopenharmony_ci        if header_offset_64_set:
9017db96d56Sopenharmony_ci            header_offset = 0xffffffff
9027db96d56Sopenharmony_ci            if header_offset_extra:
9037db96d56Sopenharmony_ci                central_zip64_fields.append(actual_header_offset)
9047db96d56Sopenharmony_ci        header_offset = struct.pack("<L", header_offset)
9057db96d56Sopenharmony_ci
9067db96d56Sopenharmony_ci        local_extra = struct.pack(
9077db96d56Sopenharmony_ci            '<HH' + 'Q'*len(local_zip64_fields),
9087db96d56Sopenharmony_ci            0x0001,
9097db96d56Sopenharmony_ci            8*len(local_zip64_fields),
9107db96d56Sopenharmony_ci            *local_zip64_fields
9117db96d56Sopenharmony_ci        )
9127db96d56Sopenharmony_ci
9137db96d56Sopenharmony_ci        central_extra = struct.pack(
9147db96d56Sopenharmony_ci            '<HH' + 'Q'*len(central_zip64_fields),
9157db96d56Sopenharmony_ci            0x0001,
9167db96d56Sopenharmony_ci            8*len(central_zip64_fields),
9177db96d56Sopenharmony_ci            *central_zip64_fields
9187db96d56Sopenharmony_ci        )
9197db96d56Sopenharmony_ci
9207db96d56Sopenharmony_ci        central_dir_size = struct.pack('<Q', 58 + 8 * len(central_zip64_fields))
9217db96d56Sopenharmony_ci        offset_to_central_dir = struct.pack('<Q', 50 + 8 * len(local_zip64_fields))
9227db96d56Sopenharmony_ci
9237db96d56Sopenharmony_ci        local_extra_length = struct.pack("<H", 4 + 8 * len(local_zip64_fields))
9247db96d56Sopenharmony_ci        central_extra_length = struct.pack("<H", 4 + 8 * len(central_zip64_fields))
9257db96d56Sopenharmony_ci
9267db96d56Sopenharmony_ci        filename = b"test.txt"
9277db96d56Sopenharmony_ci        content = b"test1234"
9287db96d56Sopenharmony_ci        filename_length = struct.pack("<H", len(filename))
9297db96d56Sopenharmony_ci        zip64_contents = (
9307db96d56Sopenharmony_ci            # Local file header
9317db96d56Sopenharmony_ci            b"PK\x03\x04\x14\x00\x00\x00\x00\x00\x00\x00!\x00\x9e%\xf5\xaf"
9327db96d56Sopenharmony_ci            + compress_size
9337db96d56Sopenharmony_ci            + file_size
9347db96d56Sopenharmony_ci            + filename_length
9357db96d56Sopenharmony_ci            + local_extra_length
9367db96d56Sopenharmony_ci            + filename
9377db96d56Sopenharmony_ci            + local_extra
9387db96d56Sopenharmony_ci            + content
9397db96d56Sopenharmony_ci            # Central directory:
9407db96d56Sopenharmony_ci            + b"PK\x01\x02-\x03-\x00\x00\x00\x00\x00\x00\x00!\x00\x9e%\xf5\xaf"
9417db96d56Sopenharmony_ci            + compress_size
9427db96d56Sopenharmony_ci            + file_size
9437db96d56Sopenharmony_ci            + filename_length
9447db96d56Sopenharmony_ci            + central_extra_length
9457db96d56Sopenharmony_ci            + b"\x00\x00\x00\x00\x00\x00\x00\x00\x80\x01"
9467db96d56Sopenharmony_ci            + header_offset
9477db96d56Sopenharmony_ci            + filename
9487db96d56Sopenharmony_ci            + central_extra
9497db96d56Sopenharmony_ci            # Zip64 end of central directory
9507db96d56Sopenharmony_ci            + b"PK\x06\x06,\x00\x00\x00\x00\x00\x00\x00-\x00-"
9517db96d56Sopenharmony_ci            + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00"
9527db96d56Sopenharmony_ci            + b"\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00"
9537db96d56Sopenharmony_ci            + central_dir_size
9547db96d56Sopenharmony_ci            + offset_to_central_dir
9557db96d56Sopenharmony_ci            # Zip64 end of central directory locator
9567db96d56Sopenharmony_ci            + b"PK\x06\x07\x00\x00\x00\x00l\x00\x00\x00\x00\x00\x00\x00\x01"
9577db96d56Sopenharmony_ci            + b"\x00\x00\x00"
9587db96d56Sopenharmony_ci            # end of central directory
9597db96d56Sopenharmony_ci            + b"PK\x05\x06\x00\x00\x00\x00\x01\x00\x01\x00:\x00\x00\x002\x00"
9607db96d56Sopenharmony_ci            + b"\x00\x00\x00\x00"
9617db96d56Sopenharmony_ci        )
9627db96d56Sopenharmony_ci        return zip64_contents
9637db96d56Sopenharmony_ci
9647db96d56Sopenharmony_ci    def test_bad_zip64_extra(self):
9657db96d56Sopenharmony_ci        """Missing zip64 extra records raises an exception.
9667db96d56Sopenharmony_ci
9677db96d56Sopenharmony_ci        There are 4 fields that the zip64 format handles (the disk number is
9687db96d56Sopenharmony_ci        not used in this module and so is ignored here). According to the zip
9697db96d56Sopenharmony_ci        spec:
9707db96d56Sopenharmony_ci              The order of the fields in the zip64 extended
9717db96d56Sopenharmony_ci              information record is fixed, but the fields MUST
9727db96d56Sopenharmony_ci              only appear if the corresponding Local or Central
9737db96d56Sopenharmony_ci              directory record field is set to 0xFFFF or 0xFFFFFFFF.
9747db96d56Sopenharmony_ci
9757db96d56Sopenharmony_ci        If the zip64 extra content doesn't contain enough entries for the
9767db96d56Sopenharmony_ci        number of fields marked with 0xFFFF or 0xFFFFFFFF, we raise an error.
9777db96d56Sopenharmony_ci        This test mismatches the length of the zip64 extra field and the number
9787db96d56Sopenharmony_ci        of fields set to indicate the presence of zip64 data.
9797db96d56Sopenharmony_ci        """
9807db96d56Sopenharmony_ci        # zip64 file size present, no fields in extra, expecting one, equals
9817db96d56Sopenharmony_ci        # missing file size.
9827db96d56Sopenharmony_ci        missing_file_size_extra = self.make_zip64_file(
9837db96d56Sopenharmony_ci            file_size_64_set=True,
9847db96d56Sopenharmony_ci        )
9857db96d56Sopenharmony_ci        with self.assertRaises(zipfile.BadZipFile) as e:
9867db96d56Sopenharmony_ci            zipfile.ZipFile(io.BytesIO(missing_file_size_extra))
9877db96d56Sopenharmony_ci        self.assertIn('file size', str(e.exception).lower())
9887db96d56Sopenharmony_ci
9897db96d56Sopenharmony_ci        # zip64 file size present, zip64 compress size present, one field in
9907db96d56Sopenharmony_ci        # extra, expecting two, equals missing compress size.
9917db96d56Sopenharmony_ci        missing_compress_size_extra = self.make_zip64_file(
9927db96d56Sopenharmony_ci            file_size_64_set=True,
9937db96d56Sopenharmony_ci            file_size_extra=True,
9947db96d56Sopenharmony_ci            compress_size_64_set=True,
9957db96d56Sopenharmony_ci        )
9967db96d56Sopenharmony_ci        with self.assertRaises(zipfile.BadZipFile) as e:
9977db96d56Sopenharmony_ci            zipfile.ZipFile(io.BytesIO(missing_compress_size_extra))
9987db96d56Sopenharmony_ci        self.assertIn('compress size', str(e.exception).lower())
9997db96d56Sopenharmony_ci
10007db96d56Sopenharmony_ci        # zip64 compress size present, no fields in extra, expecting one,
10017db96d56Sopenharmony_ci        # equals missing compress size.
10027db96d56Sopenharmony_ci        missing_compress_size_extra = self.make_zip64_file(
10037db96d56Sopenharmony_ci            compress_size_64_set=True,
10047db96d56Sopenharmony_ci        )
10057db96d56Sopenharmony_ci        with self.assertRaises(zipfile.BadZipFile) as e:
10067db96d56Sopenharmony_ci            zipfile.ZipFile(io.BytesIO(missing_compress_size_extra))
10077db96d56Sopenharmony_ci        self.assertIn('compress size', str(e.exception).lower())
10087db96d56Sopenharmony_ci
10097db96d56Sopenharmony_ci        # zip64 file size present, zip64 compress size present, zip64 header
10107db96d56Sopenharmony_ci        # offset present, two fields in extra, expecting three, equals missing
10117db96d56Sopenharmony_ci        # header offset
10127db96d56Sopenharmony_ci        missing_header_offset_extra = self.make_zip64_file(
10137db96d56Sopenharmony_ci            file_size_64_set=True,
10147db96d56Sopenharmony_ci            file_size_extra=True,
10157db96d56Sopenharmony_ci            compress_size_64_set=True,
10167db96d56Sopenharmony_ci            compress_size_extra=True,
10177db96d56Sopenharmony_ci            header_offset_64_set=True,
10187db96d56Sopenharmony_ci        )
10197db96d56Sopenharmony_ci        with self.assertRaises(zipfile.BadZipFile) as e:
10207db96d56Sopenharmony_ci            zipfile.ZipFile(io.BytesIO(missing_header_offset_extra))
10217db96d56Sopenharmony_ci        self.assertIn('header offset', str(e.exception).lower())
10227db96d56Sopenharmony_ci
10237db96d56Sopenharmony_ci        # zip64 compress size present, zip64 header offset present, one field
10247db96d56Sopenharmony_ci        # in extra, expecting two, equals missing header offset
10257db96d56Sopenharmony_ci        missing_header_offset_extra = self.make_zip64_file(
10267db96d56Sopenharmony_ci            file_size_64_set=False,
10277db96d56Sopenharmony_ci            compress_size_64_set=True,
10287db96d56Sopenharmony_ci            compress_size_extra=True,
10297db96d56Sopenharmony_ci            header_offset_64_set=True,
10307db96d56Sopenharmony_ci        )
10317db96d56Sopenharmony_ci        with self.assertRaises(zipfile.BadZipFile) as e:
10327db96d56Sopenharmony_ci            zipfile.ZipFile(io.BytesIO(missing_header_offset_extra))
10337db96d56Sopenharmony_ci        self.assertIn('header offset', str(e.exception).lower())
10347db96d56Sopenharmony_ci
10357db96d56Sopenharmony_ci        # zip64 file size present, zip64 header offset present, one field in
10367db96d56Sopenharmony_ci        # extra, expecting two, equals missing header offset
10377db96d56Sopenharmony_ci        missing_header_offset_extra = self.make_zip64_file(
10387db96d56Sopenharmony_ci            file_size_64_set=True,
10397db96d56Sopenharmony_ci            file_size_extra=True,
10407db96d56Sopenharmony_ci            compress_size_64_set=False,
10417db96d56Sopenharmony_ci            header_offset_64_set=True,
10427db96d56Sopenharmony_ci        )
10437db96d56Sopenharmony_ci        with self.assertRaises(zipfile.BadZipFile) as e:
10447db96d56Sopenharmony_ci            zipfile.ZipFile(io.BytesIO(missing_header_offset_extra))
10457db96d56Sopenharmony_ci        self.assertIn('header offset', str(e.exception).lower())
10467db96d56Sopenharmony_ci
10477db96d56Sopenharmony_ci        # zip64 header offset present, no fields in extra, expecting one,
10487db96d56Sopenharmony_ci        # equals missing header offset
10497db96d56Sopenharmony_ci        missing_header_offset_extra = self.make_zip64_file(
10507db96d56Sopenharmony_ci            file_size_64_set=False,
10517db96d56Sopenharmony_ci            compress_size_64_set=False,
10527db96d56Sopenharmony_ci            header_offset_64_set=True,
10537db96d56Sopenharmony_ci        )
10547db96d56Sopenharmony_ci        with self.assertRaises(zipfile.BadZipFile) as e:
10557db96d56Sopenharmony_ci            zipfile.ZipFile(io.BytesIO(missing_header_offset_extra))
10567db96d56Sopenharmony_ci        self.assertIn('header offset', str(e.exception).lower())
10577db96d56Sopenharmony_ci
10587db96d56Sopenharmony_ci    def test_generated_valid_zip64_extra(self):
10597db96d56Sopenharmony_ci        # These values are what is set in the make_zip64_file method.
10607db96d56Sopenharmony_ci        expected_file_size = 8
10617db96d56Sopenharmony_ci        expected_compress_size = 8
10627db96d56Sopenharmony_ci        expected_header_offset = 0
10637db96d56Sopenharmony_ci        expected_content = b"test1234"
10647db96d56Sopenharmony_ci
10657db96d56Sopenharmony_ci        # Loop through the various valid combinations of zip64 masks
10667db96d56Sopenharmony_ci        # present and extra fields present.
10677db96d56Sopenharmony_ci        params = (
10687db96d56Sopenharmony_ci            {"file_size_64_set": True, "file_size_extra": True},
10697db96d56Sopenharmony_ci            {"compress_size_64_set": True, "compress_size_extra": True},
10707db96d56Sopenharmony_ci            {"header_offset_64_set": True, "header_offset_extra": True},
10717db96d56Sopenharmony_ci        )
10727db96d56Sopenharmony_ci
10737db96d56Sopenharmony_ci        for r in range(1, len(params) + 1):
10747db96d56Sopenharmony_ci            for combo in itertools.combinations(params, r):
10757db96d56Sopenharmony_ci                kwargs = {}
10767db96d56Sopenharmony_ci                for c in combo:
10777db96d56Sopenharmony_ci                    kwargs.update(c)
10787db96d56Sopenharmony_ci                with zipfile.ZipFile(io.BytesIO(self.make_zip64_file(**kwargs))) as zf:
10797db96d56Sopenharmony_ci                    zinfo = zf.infolist()[0]
10807db96d56Sopenharmony_ci                    self.assertEqual(zinfo.file_size, expected_file_size)
10817db96d56Sopenharmony_ci                    self.assertEqual(zinfo.compress_size, expected_compress_size)
10827db96d56Sopenharmony_ci                    self.assertEqual(zinfo.header_offset, expected_header_offset)
10837db96d56Sopenharmony_ci                    self.assertEqual(zf.read(zinfo), expected_content)
10847db96d56Sopenharmony_ci
10857db96d56Sopenharmony_ci    def test_force_zip64(self):
10867db96d56Sopenharmony_ci        """Test that forcing zip64 extensions correctly notes this in the zip file"""
10877db96d56Sopenharmony_ci
10887db96d56Sopenharmony_ci        # GH-103861 describes an issue where forcing a small file to use zip64
10897db96d56Sopenharmony_ci        # extensions would add a zip64 extra record, but not change the data
10907db96d56Sopenharmony_ci        # sizes to 0xFFFFFFFF to indicate to the extractor that the zip64
10917db96d56Sopenharmony_ci        # record should be read. Additionally, it would not set the required
10927db96d56Sopenharmony_ci        # version to indicate that zip64 extensions are required to extract it.
10937db96d56Sopenharmony_ci        # This test replicates the situation and reads the raw data to specifically ensure:
10947db96d56Sopenharmony_ci        #  - The required extract version is always >= ZIP64_VERSION
10957db96d56Sopenharmony_ci        #  - The compressed and uncompressed size in the file headers are both
10967db96d56Sopenharmony_ci        #     0xFFFFFFFF (ie. point to zip64 record)
10977db96d56Sopenharmony_ci        #  - The zip64 record is provided and has the correct sizes in it
10987db96d56Sopenharmony_ci        # Other aspects of the zip are checked as well, but verifying the above is the main goal.
10997db96d56Sopenharmony_ci        # Because this is hard to verify by parsing the data as a zip, the raw
11007db96d56Sopenharmony_ci        # bytes are checked to ensure that they line up with the zip spec.
11017db96d56Sopenharmony_ci        # The spec for this can be found at: https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT
11027db96d56Sopenharmony_ci        # The relevent sections for this test are:
11037db96d56Sopenharmony_ci        #  - 4.3.7 for local file header
11047db96d56Sopenharmony_ci        #  - 4.5.3 for zip64 extra field
11057db96d56Sopenharmony_ci
11067db96d56Sopenharmony_ci        data = io.BytesIO()
11077db96d56Sopenharmony_ci        with zipfile.ZipFile(data, mode="w", allowZip64=True) as zf:
11087db96d56Sopenharmony_ci            with zf.open("text.txt", mode="w", force_zip64=True) as zi:
11097db96d56Sopenharmony_ci                zi.write(b"_")
11107db96d56Sopenharmony_ci
11117db96d56Sopenharmony_ci        zipdata = data.getvalue()
11127db96d56Sopenharmony_ci
11137db96d56Sopenharmony_ci        # pull out and check zip information
11147db96d56Sopenharmony_ci        (
11157db96d56Sopenharmony_ci            header, vers, os, flags, comp, csize, usize, fn_len,
11167db96d56Sopenharmony_ci            ex_total_len, filename, ex_id, ex_len, ex_usize, ex_csize, cd_sig
11177db96d56Sopenharmony_ci        ) = struct.unpack("<4sBBHH8xIIHH8shhQQx4s", zipdata[:63])
11187db96d56Sopenharmony_ci
11197db96d56Sopenharmony_ci        self.assertEqual(header, b"PK\x03\x04")  # local file header
11207db96d56Sopenharmony_ci        self.assertGreaterEqual(vers, zipfile.ZIP64_VERSION)  # requires zip64 to extract
11217db96d56Sopenharmony_ci        self.assertEqual(os, 0)  # compatible with MS-DOS
11227db96d56Sopenharmony_ci        self.assertEqual(flags, 0)  # no flags
11237db96d56Sopenharmony_ci        self.assertEqual(comp, 0)  # compression method = stored
11247db96d56Sopenharmony_ci        self.assertEqual(csize, 0xFFFFFFFF)  # sizes are in zip64 extra
11257db96d56Sopenharmony_ci        self.assertEqual(usize, 0xFFFFFFFF)
11267db96d56Sopenharmony_ci        self.assertEqual(fn_len, 8)  # filename len
11277db96d56Sopenharmony_ci        self.assertEqual(ex_total_len, 20)  # size of extra records
11287db96d56Sopenharmony_ci        self.assertEqual(ex_id, 1)  # Zip64 extra record
11297db96d56Sopenharmony_ci        self.assertEqual(ex_len, 16)  # 16 bytes of data
11307db96d56Sopenharmony_ci        self.assertEqual(ex_usize, 1)  # uncompressed size
11317db96d56Sopenharmony_ci        self.assertEqual(ex_csize, 1)  # compressed size
11327db96d56Sopenharmony_ci        self.assertEqual(cd_sig, b"PK\x01\x02") # ensure the central directory header is next
11337db96d56Sopenharmony_ci
11347db96d56Sopenharmony_ci        z = zipfile.ZipFile(io.BytesIO(zipdata))
11357db96d56Sopenharmony_ci        zinfos = z.infolist()
11367db96d56Sopenharmony_ci        self.assertEqual(len(zinfos), 1)
11377db96d56Sopenharmony_ci        self.assertGreaterEqual(zinfos[0].extract_version, zipfile.ZIP64_VERSION)  # requires zip64 to extract
11387db96d56Sopenharmony_ci
11397db96d56Sopenharmony_ci    def test_unseekable_zip_unknown_filesize(self):
11407db96d56Sopenharmony_ci        """Test that creating a zip with/without seeking will raise a RuntimeError if zip64 was required but not used"""
11417db96d56Sopenharmony_ci
11427db96d56Sopenharmony_ci        def make_zip(fp):
11437db96d56Sopenharmony_ci            with zipfile.ZipFile(fp, mode="w", allowZip64=True) as zf:
11447db96d56Sopenharmony_ci                with zf.open("text.txt", mode="w", force_zip64=False) as zi:
11457db96d56Sopenharmony_ci                    zi.write(b"_" * (zipfile.ZIP64_LIMIT + 1))
11467db96d56Sopenharmony_ci
11477db96d56Sopenharmony_ci        self.assertRaises(RuntimeError, make_zip, io.BytesIO())
11487db96d56Sopenharmony_ci        self.assertRaises(RuntimeError, make_zip, Unseekable(io.BytesIO()))
11497db96d56Sopenharmony_ci
11507db96d56Sopenharmony_ci    def test_zip64_required_not_allowed_fail(self):
11517db96d56Sopenharmony_ci        """Test that trying to add a large file to a zip that doesn't allow zip64 extensions fails on add"""
11527db96d56Sopenharmony_ci        def make_zip(fp):
11537db96d56Sopenharmony_ci            with zipfile.ZipFile(fp, mode="w", allowZip64=False) as zf:
11547db96d56Sopenharmony_ci                # pretend zipfile.ZipInfo.from_file was used to get the name and filesize
11557db96d56Sopenharmony_ci                info = zipfile.ZipInfo("text.txt")
11567db96d56Sopenharmony_ci                info.file_size = zipfile.ZIP64_LIMIT + 1
11577db96d56Sopenharmony_ci                zf.open(info, mode="w")
11587db96d56Sopenharmony_ci
11597db96d56Sopenharmony_ci        self.assertRaises(zipfile.LargeZipFile, make_zip, io.BytesIO())
11607db96d56Sopenharmony_ci        self.assertRaises(zipfile.LargeZipFile, make_zip, Unseekable(io.BytesIO()))
11617db96d56Sopenharmony_ci
11627db96d56Sopenharmony_ci    def test_unseekable_zip_known_filesize(self):
11637db96d56Sopenharmony_ci        """Test that creating a zip without seeking will use zip64 extensions if the file size is provided up-front"""
11647db96d56Sopenharmony_ci
11657db96d56Sopenharmony_ci        # This test ensures that the zip will use a zip64 data descriptor (same
11667db96d56Sopenharmony_ci        # as a regular data descriptor except the sizes are 8 bytes instead of
11677db96d56Sopenharmony_ci        # 4) record to communicate the size of a file if the zip is being
11687db96d56Sopenharmony_ci        # written to an unseekable stream.
11697db96d56Sopenharmony_ci        # Because this sort of thing is hard to verify by parsing the data back
11707db96d56Sopenharmony_ci        # in as a zip, this test looks at the raw bytes created to ensure that
11717db96d56Sopenharmony_ci        # the correct data has been generated.
11727db96d56Sopenharmony_ci        # The spec for this can be found at: https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT
11737db96d56Sopenharmony_ci        # The relevent sections for this test are:
11747db96d56Sopenharmony_ci        #  - 4.3.7 for local file header
11757db96d56Sopenharmony_ci        #  - 4.3.9 for the data descriptor
11767db96d56Sopenharmony_ci        #  - 4.5.3 for zip64 extra field
11777db96d56Sopenharmony_ci
11787db96d56Sopenharmony_ci        file_size = zipfile.ZIP64_LIMIT + 1
11797db96d56Sopenharmony_ci
11807db96d56Sopenharmony_ci        def make_zip(fp):
11817db96d56Sopenharmony_ci            with zipfile.ZipFile(fp, mode="w", allowZip64=True) as zf:
11827db96d56Sopenharmony_ci                # pretend zipfile.ZipInfo.from_file was used to get the name and filesize
11837db96d56Sopenharmony_ci                info = zipfile.ZipInfo("text.txt")
11847db96d56Sopenharmony_ci                info.file_size = file_size
11857db96d56Sopenharmony_ci                with zf.open(info, mode="w", force_zip64=False) as zi:
11867db96d56Sopenharmony_ci                    zi.write(b"_" * file_size)
11877db96d56Sopenharmony_ci            return fp
11887db96d56Sopenharmony_ci
11897db96d56Sopenharmony_ci        # check seekable file information
11907db96d56Sopenharmony_ci        seekable_data = make_zip(io.BytesIO()).getvalue()
11917db96d56Sopenharmony_ci        (
11927db96d56Sopenharmony_ci            header, vers, os, flags, comp, csize, usize, fn_len,
11937db96d56Sopenharmony_ci            ex_total_len, filename, ex_id, ex_len, ex_usize, ex_csize,
11947db96d56Sopenharmony_ci            cd_sig
11957db96d56Sopenharmony_ci        ) = struct.unpack("<4sBBHH8xIIHH8shhQQ{}x4s".format(file_size), seekable_data[:62 + file_size])
11967db96d56Sopenharmony_ci
11977db96d56Sopenharmony_ci        self.assertEqual(header, b"PK\x03\x04")  # local file header
11987db96d56Sopenharmony_ci        self.assertGreaterEqual(vers, zipfile.ZIP64_VERSION)  # requires zip64 to extract
11997db96d56Sopenharmony_ci        self.assertEqual(os, 0)  # compatible with MS-DOS
12007db96d56Sopenharmony_ci        self.assertEqual(flags, 0)  # no flags set
12017db96d56Sopenharmony_ci        self.assertEqual(comp, 0)  # compression method = stored
12027db96d56Sopenharmony_ci        self.assertEqual(csize, 0xFFFFFFFF)  # sizes are in zip64 extra
12037db96d56Sopenharmony_ci        self.assertEqual(usize, 0xFFFFFFFF)
12047db96d56Sopenharmony_ci        self.assertEqual(fn_len, 8)  # filename len
12057db96d56Sopenharmony_ci        self.assertEqual(ex_total_len, 20)  # size of extra records
12067db96d56Sopenharmony_ci        self.assertEqual(ex_id, 1)  # Zip64 extra record
12077db96d56Sopenharmony_ci        self.assertEqual(ex_len, 16)  # 16 bytes of data
12087db96d56Sopenharmony_ci        self.assertEqual(ex_usize, file_size)  # uncompressed size
12097db96d56Sopenharmony_ci        self.assertEqual(ex_csize, file_size)  # compressed size
12107db96d56Sopenharmony_ci        self.assertEqual(cd_sig, b"PK\x01\x02") # ensure the central directory header is next
12117db96d56Sopenharmony_ci
12127db96d56Sopenharmony_ci        # check unseekable file information
12137db96d56Sopenharmony_ci        unseekable_data = make_zip(Unseekable(io.BytesIO())).fp.getvalue()
12147db96d56Sopenharmony_ci        (
12157db96d56Sopenharmony_ci            header, vers, os, flags, comp, csize, usize, fn_len,
12167db96d56Sopenharmony_ci            ex_total_len, filename, ex_id, ex_len, ex_usize, ex_csize,
12177db96d56Sopenharmony_ci            dd_header, dd_usize, dd_csize, cd_sig
12187db96d56Sopenharmony_ci        ) = struct.unpack("<4sBBHH8xIIHH8shhQQ{}x4s4xQQ4s".format(file_size), unseekable_data[:86 + file_size])
12197db96d56Sopenharmony_ci
12207db96d56Sopenharmony_ci        self.assertEqual(header, b"PK\x03\x04")  # local file header
12217db96d56Sopenharmony_ci        self.assertGreaterEqual(vers, zipfile.ZIP64_VERSION)  # requires zip64 to extract
12227db96d56Sopenharmony_ci        self.assertEqual(os, 0)  # compatible with MS-DOS
12237db96d56Sopenharmony_ci        self.assertEqual("{:b}".format(flags), "1000")  # streaming flag set
12247db96d56Sopenharmony_ci        self.assertEqual(comp, 0)  # compression method = stored
12257db96d56Sopenharmony_ci        self.assertEqual(csize, 0xFFFFFFFF)  # sizes are in zip64 extra
12267db96d56Sopenharmony_ci        self.assertEqual(usize, 0xFFFFFFFF)
12277db96d56Sopenharmony_ci        self.assertEqual(fn_len, 8)  # filename len
12287db96d56Sopenharmony_ci        self.assertEqual(ex_total_len, 20)  # size of extra records
12297db96d56Sopenharmony_ci        self.assertEqual(ex_id, 1)  # Zip64 extra record
12307db96d56Sopenharmony_ci        self.assertEqual(ex_len, 16)  # 16 bytes of data
12317db96d56Sopenharmony_ci        self.assertEqual(ex_usize, 0)  # uncompressed size - 0 to defer to data descriptor
12327db96d56Sopenharmony_ci        self.assertEqual(ex_csize, 0)  # compressed size - 0 to defer to data descriptor
12337db96d56Sopenharmony_ci        self.assertEqual(dd_header, b"PK\07\x08")  # data descriptor
12347db96d56Sopenharmony_ci        self.assertEqual(dd_usize, file_size)  # file size (8 bytes because zip64)
12357db96d56Sopenharmony_ci        self.assertEqual(dd_csize, file_size)  # compressed size (8 bytes because zip64)
12367db96d56Sopenharmony_ci        self.assertEqual(cd_sig, b"PK\x01\x02") # ensure the central directory header is next
12377db96d56Sopenharmony_ci
12387db96d56Sopenharmony_ci
12397db96d56Sopenharmony_ci@requires_zlib()
12407db96d56Sopenharmony_ciclass DeflateTestZip64InSmallFiles(AbstractTestZip64InSmallFiles,
12417db96d56Sopenharmony_ci                                   unittest.TestCase):
12427db96d56Sopenharmony_ci    compression = zipfile.ZIP_DEFLATED
12437db96d56Sopenharmony_ci
12447db96d56Sopenharmony_ci@requires_bz2()
12457db96d56Sopenharmony_ciclass Bzip2TestZip64InSmallFiles(AbstractTestZip64InSmallFiles,
12467db96d56Sopenharmony_ci                                 unittest.TestCase):
12477db96d56Sopenharmony_ci    compression = zipfile.ZIP_BZIP2
12487db96d56Sopenharmony_ci
12497db96d56Sopenharmony_ci@requires_lzma()
12507db96d56Sopenharmony_ciclass LzmaTestZip64InSmallFiles(AbstractTestZip64InSmallFiles,
12517db96d56Sopenharmony_ci                                unittest.TestCase):
12527db96d56Sopenharmony_ci    compression = zipfile.ZIP_LZMA
12537db96d56Sopenharmony_ci
12547db96d56Sopenharmony_ci
12557db96d56Sopenharmony_ciclass AbstractWriterTests:
12567db96d56Sopenharmony_ci
12577db96d56Sopenharmony_ci    def tearDown(self):
12587db96d56Sopenharmony_ci        unlink(TESTFN2)
12597db96d56Sopenharmony_ci
12607db96d56Sopenharmony_ci    def test_close_after_close(self):
12617db96d56Sopenharmony_ci        data = b'content'
12627db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, "w", self.compression) as zipf:
12637db96d56Sopenharmony_ci            w = zipf.open('test', 'w')
12647db96d56Sopenharmony_ci            w.write(data)
12657db96d56Sopenharmony_ci            w.close()
12667db96d56Sopenharmony_ci            self.assertTrue(w.closed)
12677db96d56Sopenharmony_ci            w.close()
12687db96d56Sopenharmony_ci            self.assertTrue(w.closed)
12697db96d56Sopenharmony_ci            self.assertEqual(zipf.read('test'), data)
12707db96d56Sopenharmony_ci
12717db96d56Sopenharmony_ci    def test_write_after_close(self):
12727db96d56Sopenharmony_ci        data = b'content'
12737db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, "w", self.compression) as zipf:
12747db96d56Sopenharmony_ci            w = zipf.open('test', 'w')
12757db96d56Sopenharmony_ci            w.write(data)
12767db96d56Sopenharmony_ci            w.close()
12777db96d56Sopenharmony_ci            self.assertTrue(w.closed)
12787db96d56Sopenharmony_ci            self.assertRaises(ValueError, w.write, b'')
12797db96d56Sopenharmony_ci            self.assertEqual(zipf.read('test'), data)
12807db96d56Sopenharmony_ci
12817db96d56Sopenharmony_ci    def test_issue44439(self):
12827db96d56Sopenharmony_ci        q = array.array('Q', [1, 2, 3, 4, 5])
12837db96d56Sopenharmony_ci        LENGTH = len(q) * q.itemsize
12847db96d56Sopenharmony_ci        with zipfile.ZipFile(io.BytesIO(), 'w', self.compression) as zip:
12857db96d56Sopenharmony_ci            with zip.open('data', 'w') as data:
12867db96d56Sopenharmony_ci                self.assertEqual(data.write(q), LENGTH)
12877db96d56Sopenharmony_ci            self.assertEqual(zip.getinfo('data').file_size, LENGTH)
12887db96d56Sopenharmony_ci
12897db96d56Sopenharmony_ciclass StoredWriterTests(AbstractWriterTests, unittest.TestCase):
12907db96d56Sopenharmony_ci    compression = zipfile.ZIP_STORED
12917db96d56Sopenharmony_ci
12927db96d56Sopenharmony_ci@requires_zlib()
12937db96d56Sopenharmony_ciclass DeflateWriterTests(AbstractWriterTests, unittest.TestCase):
12947db96d56Sopenharmony_ci    compression = zipfile.ZIP_DEFLATED
12957db96d56Sopenharmony_ci
12967db96d56Sopenharmony_ci@requires_bz2()
12977db96d56Sopenharmony_ciclass Bzip2WriterTests(AbstractWriterTests, unittest.TestCase):
12987db96d56Sopenharmony_ci    compression = zipfile.ZIP_BZIP2
12997db96d56Sopenharmony_ci
13007db96d56Sopenharmony_ci@requires_lzma()
13017db96d56Sopenharmony_ciclass LzmaWriterTests(AbstractWriterTests, unittest.TestCase):
13027db96d56Sopenharmony_ci    compression = zipfile.ZIP_LZMA
13037db96d56Sopenharmony_ci
13047db96d56Sopenharmony_ci
13057db96d56Sopenharmony_ciclass PyZipFileTests(unittest.TestCase):
13067db96d56Sopenharmony_ci    def assertCompiledIn(self, name, namelist):
13077db96d56Sopenharmony_ci        if name + 'o' not in namelist:
13087db96d56Sopenharmony_ci            self.assertIn(name + 'c', namelist)
13097db96d56Sopenharmony_ci
13107db96d56Sopenharmony_ci    def requiresWriteAccess(self, path):
13117db96d56Sopenharmony_ci        # effective_ids unavailable on windows
13127db96d56Sopenharmony_ci        if not os.access(path, os.W_OK,
13137db96d56Sopenharmony_ci                         effective_ids=os.access in os.supports_effective_ids):
13147db96d56Sopenharmony_ci            self.skipTest('requires write access to the installed location')
13157db96d56Sopenharmony_ci        filename = os.path.join(path, 'test_zipfile.try')
13167db96d56Sopenharmony_ci        try:
13177db96d56Sopenharmony_ci            fd = os.open(filename, os.O_WRONLY | os.O_CREAT)
13187db96d56Sopenharmony_ci            os.close(fd)
13197db96d56Sopenharmony_ci        except Exception:
13207db96d56Sopenharmony_ci            self.skipTest('requires write access to the installed location')
13217db96d56Sopenharmony_ci        unlink(filename)
13227db96d56Sopenharmony_ci
13237db96d56Sopenharmony_ci    def test_write_pyfile(self):
13247db96d56Sopenharmony_ci        self.requiresWriteAccess(os.path.dirname(__file__))
13257db96d56Sopenharmony_ci        with TemporaryFile() as t, zipfile.PyZipFile(t, "w") as zipfp:
13267db96d56Sopenharmony_ci            fn = __file__
13277db96d56Sopenharmony_ci            if fn.endswith('.pyc'):
13287db96d56Sopenharmony_ci                path_split = fn.split(os.sep)
13297db96d56Sopenharmony_ci                if os.altsep is not None:
13307db96d56Sopenharmony_ci                    path_split.extend(fn.split(os.altsep))
13317db96d56Sopenharmony_ci                if '__pycache__' in path_split:
13327db96d56Sopenharmony_ci                    fn = importlib.util.source_from_cache(fn)
13337db96d56Sopenharmony_ci                else:
13347db96d56Sopenharmony_ci                    fn = fn[:-1]
13357db96d56Sopenharmony_ci
13367db96d56Sopenharmony_ci            zipfp.writepy(fn)
13377db96d56Sopenharmony_ci
13387db96d56Sopenharmony_ci            bn = os.path.basename(fn)
13397db96d56Sopenharmony_ci            self.assertNotIn(bn, zipfp.namelist())
13407db96d56Sopenharmony_ci            self.assertCompiledIn(bn, zipfp.namelist())
13417db96d56Sopenharmony_ci
13427db96d56Sopenharmony_ci        with TemporaryFile() as t, zipfile.PyZipFile(t, "w") as zipfp:
13437db96d56Sopenharmony_ci            fn = __file__
13447db96d56Sopenharmony_ci            if fn.endswith('.pyc'):
13457db96d56Sopenharmony_ci                fn = fn[:-1]
13467db96d56Sopenharmony_ci
13477db96d56Sopenharmony_ci            zipfp.writepy(fn, "testpackage")
13487db96d56Sopenharmony_ci
13497db96d56Sopenharmony_ci            bn = "%s/%s" % ("testpackage", os.path.basename(fn))
13507db96d56Sopenharmony_ci            self.assertNotIn(bn, zipfp.namelist())
13517db96d56Sopenharmony_ci            self.assertCompiledIn(bn, zipfp.namelist())
13527db96d56Sopenharmony_ci
13537db96d56Sopenharmony_ci    def test_write_python_package(self):
13547db96d56Sopenharmony_ci        import email
13557db96d56Sopenharmony_ci        packagedir = os.path.dirname(email.__file__)
13567db96d56Sopenharmony_ci        self.requiresWriteAccess(packagedir)
13577db96d56Sopenharmony_ci
13587db96d56Sopenharmony_ci        with TemporaryFile() as t, zipfile.PyZipFile(t, "w") as zipfp:
13597db96d56Sopenharmony_ci            zipfp.writepy(packagedir)
13607db96d56Sopenharmony_ci
13617db96d56Sopenharmony_ci            # Check for a couple of modules at different levels of the
13627db96d56Sopenharmony_ci            # hierarchy
13637db96d56Sopenharmony_ci            names = zipfp.namelist()
13647db96d56Sopenharmony_ci            self.assertCompiledIn('email/__init__.py', names)
13657db96d56Sopenharmony_ci            self.assertCompiledIn('email/mime/text.py', names)
13667db96d56Sopenharmony_ci
13677db96d56Sopenharmony_ci    def test_write_filtered_python_package(self):
13687db96d56Sopenharmony_ci        import test
13697db96d56Sopenharmony_ci        packagedir = os.path.dirname(test.__file__)
13707db96d56Sopenharmony_ci        self.requiresWriteAccess(packagedir)
13717db96d56Sopenharmony_ci
13727db96d56Sopenharmony_ci        with TemporaryFile() as t, zipfile.PyZipFile(t, "w") as zipfp:
13737db96d56Sopenharmony_ci
13747db96d56Sopenharmony_ci            # first make sure that the test folder gives error messages
13757db96d56Sopenharmony_ci            # (on the badsyntax_... files)
13767db96d56Sopenharmony_ci            with captured_stdout() as reportSIO:
13777db96d56Sopenharmony_ci                zipfp.writepy(packagedir)
13787db96d56Sopenharmony_ci            reportStr = reportSIO.getvalue()
13797db96d56Sopenharmony_ci            self.assertTrue('SyntaxError' in reportStr)
13807db96d56Sopenharmony_ci
13817db96d56Sopenharmony_ci            # then check that the filter works on the whole package
13827db96d56Sopenharmony_ci            with captured_stdout() as reportSIO:
13837db96d56Sopenharmony_ci                zipfp.writepy(packagedir, filterfunc=lambda whatever: False)
13847db96d56Sopenharmony_ci            reportStr = reportSIO.getvalue()
13857db96d56Sopenharmony_ci            self.assertTrue('SyntaxError' not in reportStr)
13867db96d56Sopenharmony_ci
13877db96d56Sopenharmony_ci            # then check that the filter works on individual files
13887db96d56Sopenharmony_ci            def filter(path):
13897db96d56Sopenharmony_ci                return not os.path.basename(path).startswith("bad")
13907db96d56Sopenharmony_ci            with captured_stdout() as reportSIO, self.assertWarns(UserWarning):
13917db96d56Sopenharmony_ci                zipfp.writepy(packagedir, filterfunc=filter)
13927db96d56Sopenharmony_ci            reportStr = reportSIO.getvalue()
13937db96d56Sopenharmony_ci            if reportStr:
13947db96d56Sopenharmony_ci                print(reportStr)
13957db96d56Sopenharmony_ci            self.assertTrue('SyntaxError' not in reportStr)
13967db96d56Sopenharmony_ci
13977db96d56Sopenharmony_ci    def test_write_with_optimization(self):
13987db96d56Sopenharmony_ci        import email
13997db96d56Sopenharmony_ci        packagedir = os.path.dirname(email.__file__)
14007db96d56Sopenharmony_ci        self.requiresWriteAccess(packagedir)
14017db96d56Sopenharmony_ci        optlevel = 1 if __debug__ else 0
14027db96d56Sopenharmony_ci        ext = '.pyc'
14037db96d56Sopenharmony_ci
14047db96d56Sopenharmony_ci        with TemporaryFile() as t, \
14057db96d56Sopenharmony_ci             zipfile.PyZipFile(t, "w", optimize=optlevel) as zipfp:
14067db96d56Sopenharmony_ci            zipfp.writepy(packagedir)
14077db96d56Sopenharmony_ci
14087db96d56Sopenharmony_ci            names = zipfp.namelist()
14097db96d56Sopenharmony_ci            self.assertIn('email/__init__' + ext, names)
14107db96d56Sopenharmony_ci            self.assertIn('email/mime/text' + ext, names)
14117db96d56Sopenharmony_ci
14127db96d56Sopenharmony_ci    def test_write_python_directory(self):
14137db96d56Sopenharmony_ci        os.mkdir(TESTFN2)
14147db96d56Sopenharmony_ci        try:
14157db96d56Sopenharmony_ci            with open(os.path.join(TESTFN2, "mod1.py"), "w", encoding='utf-8') as fp:
14167db96d56Sopenharmony_ci                fp.write("print(42)\n")
14177db96d56Sopenharmony_ci
14187db96d56Sopenharmony_ci            with open(os.path.join(TESTFN2, "mod2.py"), "w", encoding='utf-8') as fp:
14197db96d56Sopenharmony_ci                fp.write("print(42 * 42)\n")
14207db96d56Sopenharmony_ci
14217db96d56Sopenharmony_ci            with open(os.path.join(TESTFN2, "mod2.txt"), "w", encoding='utf-8') as fp:
14227db96d56Sopenharmony_ci                fp.write("bla bla bla\n")
14237db96d56Sopenharmony_ci
14247db96d56Sopenharmony_ci            with TemporaryFile() as t, zipfile.PyZipFile(t, "w") as zipfp:
14257db96d56Sopenharmony_ci                zipfp.writepy(TESTFN2)
14267db96d56Sopenharmony_ci
14277db96d56Sopenharmony_ci                names = zipfp.namelist()
14287db96d56Sopenharmony_ci                self.assertCompiledIn('mod1.py', names)
14297db96d56Sopenharmony_ci                self.assertCompiledIn('mod2.py', names)
14307db96d56Sopenharmony_ci                self.assertNotIn('mod2.txt', names)
14317db96d56Sopenharmony_ci
14327db96d56Sopenharmony_ci        finally:
14337db96d56Sopenharmony_ci            rmtree(TESTFN2)
14347db96d56Sopenharmony_ci
14357db96d56Sopenharmony_ci    def test_write_python_directory_filtered(self):
14367db96d56Sopenharmony_ci        os.mkdir(TESTFN2)
14377db96d56Sopenharmony_ci        try:
14387db96d56Sopenharmony_ci            with open(os.path.join(TESTFN2, "mod1.py"), "w", encoding='utf-8') as fp:
14397db96d56Sopenharmony_ci                fp.write("print(42)\n")
14407db96d56Sopenharmony_ci
14417db96d56Sopenharmony_ci            with open(os.path.join(TESTFN2, "mod2.py"), "w", encoding='utf-8') as fp:
14427db96d56Sopenharmony_ci                fp.write("print(42 * 42)\n")
14437db96d56Sopenharmony_ci
14447db96d56Sopenharmony_ci            with TemporaryFile() as t, zipfile.PyZipFile(t, "w") as zipfp:
14457db96d56Sopenharmony_ci                zipfp.writepy(TESTFN2, filterfunc=lambda fn:
14467db96d56Sopenharmony_ci                                                  not fn.endswith('mod2.py'))
14477db96d56Sopenharmony_ci
14487db96d56Sopenharmony_ci                names = zipfp.namelist()
14497db96d56Sopenharmony_ci                self.assertCompiledIn('mod1.py', names)
14507db96d56Sopenharmony_ci                self.assertNotIn('mod2.py', names)
14517db96d56Sopenharmony_ci
14527db96d56Sopenharmony_ci        finally:
14537db96d56Sopenharmony_ci            rmtree(TESTFN2)
14547db96d56Sopenharmony_ci
14557db96d56Sopenharmony_ci    def test_write_non_pyfile(self):
14567db96d56Sopenharmony_ci        with TemporaryFile() as t, zipfile.PyZipFile(t, "w") as zipfp:
14577db96d56Sopenharmony_ci            with open(TESTFN, 'w', encoding='utf-8') as f:
14587db96d56Sopenharmony_ci                f.write('most definitely not a python file')
14597db96d56Sopenharmony_ci            self.assertRaises(RuntimeError, zipfp.writepy, TESTFN)
14607db96d56Sopenharmony_ci            unlink(TESTFN)
14617db96d56Sopenharmony_ci
14627db96d56Sopenharmony_ci    def test_write_pyfile_bad_syntax(self):
14637db96d56Sopenharmony_ci        os.mkdir(TESTFN2)
14647db96d56Sopenharmony_ci        try:
14657db96d56Sopenharmony_ci            with open(os.path.join(TESTFN2, "mod1.py"), "w", encoding='utf-8') as fp:
14667db96d56Sopenharmony_ci                fp.write("Bad syntax in python file\n")
14677db96d56Sopenharmony_ci
14687db96d56Sopenharmony_ci            with TemporaryFile() as t, zipfile.PyZipFile(t, "w") as zipfp:
14697db96d56Sopenharmony_ci                # syntax errors are printed to stdout
14707db96d56Sopenharmony_ci                with captured_stdout() as s:
14717db96d56Sopenharmony_ci                    zipfp.writepy(os.path.join(TESTFN2, "mod1.py"))
14727db96d56Sopenharmony_ci
14737db96d56Sopenharmony_ci                self.assertIn("SyntaxError", s.getvalue())
14747db96d56Sopenharmony_ci
14757db96d56Sopenharmony_ci                # as it will not have compiled the python file, it will
14767db96d56Sopenharmony_ci                # include the .py file not .pyc
14777db96d56Sopenharmony_ci                names = zipfp.namelist()
14787db96d56Sopenharmony_ci                self.assertIn('mod1.py', names)
14797db96d56Sopenharmony_ci                self.assertNotIn('mod1.pyc', names)
14807db96d56Sopenharmony_ci
14817db96d56Sopenharmony_ci        finally:
14827db96d56Sopenharmony_ci            rmtree(TESTFN2)
14837db96d56Sopenharmony_ci
14847db96d56Sopenharmony_ci    def test_write_pathlike(self):
14857db96d56Sopenharmony_ci        os.mkdir(TESTFN2)
14867db96d56Sopenharmony_ci        try:
14877db96d56Sopenharmony_ci            with open(os.path.join(TESTFN2, "mod1.py"), "w", encoding='utf-8') as fp:
14887db96d56Sopenharmony_ci                fp.write("print(42)\n")
14897db96d56Sopenharmony_ci
14907db96d56Sopenharmony_ci            with TemporaryFile() as t, zipfile.PyZipFile(t, "w") as zipfp:
14917db96d56Sopenharmony_ci                zipfp.writepy(pathlib.Path(TESTFN2) / "mod1.py")
14927db96d56Sopenharmony_ci                names = zipfp.namelist()
14937db96d56Sopenharmony_ci                self.assertCompiledIn('mod1.py', names)
14947db96d56Sopenharmony_ci        finally:
14957db96d56Sopenharmony_ci            rmtree(TESTFN2)
14967db96d56Sopenharmony_ci
14977db96d56Sopenharmony_ci
14987db96d56Sopenharmony_ciclass ExtractTests(unittest.TestCase):
14997db96d56Sopenharmony_ci
15007db96d56Sopenharmony_ci    def make_test_file(self):
15017db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED) as zipfp:
15027db96d56Sopenharmony_ci            for fpath, fdata in SMALL_TEST_DATA:
15037db96d56Sopenharmony_ci                zipfp.writestr(fpath, fdata)
15047db96d56Sopenharmony_ci
15057db96d56Sopenharmony_ci    def test_extract(self):
15067db96d56Sopenharmony_ci        with temp_cwd():
15077db96d56Sopenharmony_ci            self.make_test_file()
15087db96d56Sopenharmony_ci            with zipfile.ZipFile(TESTFN2, "r") as zipfp:
15097db96d56Sopenharmony_ci                for fpath, fdata in SMALL_TEST_DATA:
15107db96d56Sopenharmony_ci                    writtenfile = zipfp.extract(fpath)
15117db96d56Sopenharmony_ci
15127db96d56Sopenharmony_ci                    # make sure it was written to the right place
15137db96d56Sopenharmony_ci                    correctfile = os.path.join(os.getcwd(), fpath)
15147db96d56Sopenharmony_ci                    correctfile = os.path.normpath(correctfile)
15157db96d56Sopenharmony_ci
15167db96d56Sopenharmony_ci                    self.assertEqual(writtenfile, correctfile)
15177db96d56Sopenharmony_ci
15187db96d56Sopenharmony_ci                    # make sure correct data is in correct file
15197db96d56Sopenharmony_ci                    with open(writtenfile, "rb") as f:
15207db96d56Sopenharmony_ci                        self.assertEqual(fdata.encode(), f.read())
15217db96d56Sopenharmony_ci
15227db96d56Sopenharmony_ci                    unlink(writtenfile)
15237db96d56Sopenharmony_ci
15247db96d56Sopenharmony_ci    def _test_extract_with_target(self, target):
15257db96d56Sopenharmony_ci        self.make_test_file()
15267db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, "r") as zipfp:
15277db96d56Sopenharmony_ci            for fpath, fdata in SMALL_TEST_DATA:
15287db96d56Sopenharmony_ci                writtenfile = zipfp.extract(fpath, target)
15297db96d56Sopenharmony_ci
15307db96d56Sopenharmony_ci                # make sure it was written to the right place
15317db96d56Sopenharmony_ci                correctfile = os.path.join(target, fpath)
15327db96d56Sopenharmony_ci                correctfile = os.path.normpath(correctfile)
15337db96d56Sopenharmony_ci                self.assertTrue(os.path.samefile(writtenfile, correctfile), (writtenfile, target))
15347db96d56Sopenharmony_ci
15357db96d56Sopenharmony_ci                # make sure correct data is in correct file
15367db96d56Sopenharmony_ci                with open(writtenfile, "rb") as f:
15377db96d56Sopenharmony_ci                    self.assertEqual(fdata.encode(), f.read())
15387db96d56Sopenharmony_ci
15397db96d56Sopenharmony_ci                unlink(writtenfile)
15407db96d56Sopenharmony_ci
15417db96d56Sopenharmony_ci        unlink(TESTFN2)
15427db96d56Sopenharmony_ci
15437db96d56Sopenharmony_ci    def test_extract_with_target(self):
15447db96d56Sopenharmony_ci        with temp_dir() as extdir:
15457db96d56Sopenharmony_ci            self._test_extract_with_target(extdir)
15467db96d56Sopenharmony_ci
15477db96d56Sopenharmony_ci    def test_extract_with_target_pathlike(self):
15487db96d56Sopenharmony_ci        with temp_dir() as extdir:
15497db96d56Sopenharmony_ci            self._test_extract_with_target(pathlib.Path(extdir))
15507db96d56Sopenharmony_ci
15517db96d56Sopenharmony_ci    def test_extract_all(self):
15527db96d56Sopenharmony_ci        with temp_cwd():
15537db96d56Sopenharmony_ci            self.make_test_file()
15547db96d56Sopenharmony_ci            with zipfile.ZipFile(TESTFN2, "r") as zipfp:
15557db96d56Sopenharmony_ci                zipfp.extractall()
15567db96d56Sopenharmony_ci                for fpath, fdata in SMALL_TEST_DATA:
15577db96d56Sopenharmony_ci                    outfile = os.path.join(os.getcwd(), fpath)
15587db96d56Sopenharmony_ci
15597db96d56Sopenharmony_ci                    with open(outfile, "rb") as f:
15607db96d56Sopenharmony_ci                        self.assertEqual(fdata.encode(), f.read())
15617db96d56Sopenharmony_ci
15627db96d56Sopenharmony_ci                    unlink(outfile)
15637db96d56Sopenharmony_ci
15647db96d56Sopenharmony_ci    def _test_extract_all_with_target(self, target):
15657db96d56Sopenharmony_ci        self.make_test_file()
15667db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, "r") as zipfp:
15677db96d56Sopenharmony_ci            zipfp.extractall(target)
15687db96d56Sopenharmony_ci            for fpath, fdata in SMALL_TEST_DATA:
15697db96d56Sopenharmony_ci                outfile = os.path.join(target, fpath)
15707db96d56Sopenharmony_ci
15717db96d56Sopenharmony_ci                with open(outfile, "rb") as f:
15727db96d56Sopenharmony_ci                    self.assertEqual(fdata.encode(), f.read())
15737db96d56Sopenharmony_ci
15747db96d56Sopenharmony_ci                unlink(outfile)
15757db96d56Sopenharmony_ci
15767db96d56Sopenharmony_ci        unlink(TESTFN2)
15777db96d56Sopenharmony_ci
15787db96d56Sopenharmony_ci    def test_extract_all_with_target(self):
15797db96d56Sopenharmony_ci        with temp_dir() as extdir:
15807db96d56Sopenharmony_ci            self._test_extract_all_with_target(extdir)
15817db96d56Sopenharmony_ci
15827db96d56Sopenharmony_ci    def test_extract_all_with_target_pathlike(self):
15837db96d56Sopenharmony_ci        with temp_dir() as extdir:
15847db96d56Sopenharmony_ci            self._test_extract_all_with_target(pathlib.Path(extdir))
15857db96d56Sopenharmony_ci
15867db96d56Sopenharmony_ci    def check_file(self, filename, content):
15877db96d56Sopenharmony_ci        self.assertTrue(os.path.isfile(filename))
15887db96d56Sopenharmony_ci        with open(filename, 'rb') as f:
15897db96d56Sopenharmony_ci            self.assertEqual(f.read(), content)
15907db96d56Sopenharmony_ci
15917db96d56Sopenharmony_ci    def test_sanitize_windows_name(self):
15927db96d56Sopenharmony_ci        san = zipfile.ZipFile._sanitize_windows_name
15937db96d56Sopenharmony_ci        # Passing pathsep in allows this test to work regardless of platform.
15947db96d56Sopenharmony_ci        self.assertEqual(san(r',,?,C:,foo,bar/z', ','), r'_,C_,foo,bar/z')
15957db96d56Sopenharmony_ci        self.assertEqual(san(r'a\b,c<d>e|f"g?h*i', ','), r'a\b,c_d_e_f_g_h_i')
15967db96d56Sopenharmony_ci        self.assertEqual(san('../../foo../../ba..r', '/'), r'foo/ba..r')
15977db96d56Sopenharmony_ci
15987db96d56Sopenharmony_ci    def test_extract_hackers_arcnames_common_cases(self):
15997db96d56Sopenharmony_ci        common_hacknames = [
16007db96d56Sopenharmony_ci            ('../foo/bar', 'foo/bar'),
16017db96d56Sopenharmony_ci            ('foo/../bar', 'foo/bar'),
16027db96d56Sopenharmony_ci            ('foo/../../bar', 'foo/bar'),
16037db96d56Sopenharmony_ci            ('foo/bar/..', 'foo/bar'),
16047db96d56Sopenharmony_ci            ('./../foo/bar', 'foo/bar'),
16057db96d56Sopenharmony_ci            ('/foo/bar', 'foo/bar'),
16067db96d56Sopenharmony_ci            ('/foo/../bar', 'foo/bar'),
16077db96d56Sopenharmony_ci            ('/foo/../../bar', 'foo/bar'),
16087db96d56Sopenharmony_ci        ]
16097db96d56Sopenharmony_ci        self._test_extract_hackers_arcnames(common_hacknames)
16107db96d56Sopenharmony_ci
16117db96d56Sopenharmony_ci    @unittest.skipIf(os.path.sep != '\\', 'Requires \\ as path separator.')
16127db96d56Sopenharmony_ci    def test_extract_hackers_arcnames_windows_only(self):
16137db96d56Sopenharmony_ci        """Test combination of path fixing and windows name sanitization."""
16147db96d56Sopenharmony_ci        windows_hacknames = [
16157db96d56Sopenharmony_ci            (r'..\foo\bar', 'foo/bar'),
16167db96d56Sopenharmony_ci            (r'..\/foo\/bar', 'foo/bar'),
16177db96d56Sopenharmony_ci            (r'foo/\..\/bar', 'foo/bar'),
16187db96d56Sopenharmony_ci            (r'foo\/../\bar', 'foo/bar'),
16197db96d56Sopenharmony_ci            (r'C:foo/bar', 'foo/bar'),
16207db96d56Sopenharmony_ci            (r'C:/foo/bar', 'foo/bar'),
16217db96d56Sopenharmony_ci            (r'C://foo/bar', 'foo/bar'),
16227db96d56Sopenharmony_ci            (r'C:\foo\bar', 'foo/bar'),
16237db96d56Sopenharmony_ci            (r'//conky/mountpoint/foo/bar', 'foo/bar'),
16247db96d56Sopenharmony_ci            (r'\\conky\mountpoint\foo\bar', 'foo/bar'),
16257db96d56Sopenharmony_ci            (r'///conky/mountpoint/foo/bar', 'mountpoint/foo/bar'),
16267db96d56Sopenharmony_ci            (r'\\\conky\mountpoint\foo\bar', 'mountpoint/foo/bar'),
16277db96d56Sopenharmony_ci            (r'//conky//mountpoint/foo/bar', 'mountpoint/foo/bar'),
16287db96d56Sopenharmony_ci            (r'\\conky\\mountpoint\foo\bar', 'mountpoint/foo/bar'),
16297db96d56Sopenharmony_ci            (r'//?/C:/foo/bar', 'foo/bar'),
16307db96d56Sopenharmony_ci            (r'\\?\C:\foo\bar', 'foo/bar'),
16317db96d56Sopenharmony_ci            (r'C:/../C:/foo/bar', 'C_/foo/bar'),
16327db96d56Sopenharmony_ci            (r'a:b\c<d>e|f"g?h*i', 'b/c_d_e_f_g_h_i'),
16337db96d56Sopenharmony_ci            ('../../foo../../ba..r', 'foo/ba..r'),
16347db96d56Sopenharmony_ci        ]
16357db96d56Sopenharmony_ci        self._test_extract_hackers_arcnames(windows_hacknames)
16367db96d56Sopenharmony_ci
16377db96d56Sopenharmony_ci    @unittest.skipIf(os.path.sep != '/', r'Requires / as path separator.')
16387db96d56Sopenharmony_ci    def test_extract_hackers_arcnames_posix_only(self):
16397db96d56Sopenharmony_ci        posix_hacknames = [
16407db96d56Sopenharmony_ci            ('//foo/bar', 'foo/bar'),
16417db96d56Sopenharmony_ci            ('../../foo../../ba..r', 'foo../ba..r'),
16427db96d56Sopenharmony_ci            (r'foo/..\bar', r'foo/..\bar'),
16437db96d56Sopenharmony_ci        ]
16447db96d56Sopenharmony_ci        self._test_extract_hackers_arcnames(posix_hacknames)
16457db96d56Sopenharmony_ci
16467db96d56Sopenharmony_ci    def _test_extract_hackers_arcnames(self, hacknames):
16477db96d56Sopenharmony_ci        for arcname, fixedname in hacknames:
16487db96d56Sopenharmony_ci            content = b'foobar' + arcname.encode()
16497db96d56Sopenharmony_ci            with zipfile.ZipFile(TESTFN2, 'w', zipfile.ZIP_STORED) as zipfp:
16507db96d56Sopenharmony_ci                zinfo = zipfile.ZipInfo()
16517db96d56Sopenharmony_ci                # preserve backslashes
16527db96d56Sopenharmony_ci                zinfo.filename = arcname
16537db96d56Sopenharmony_ci                zinfo.external_attr = 0o600 << 16
16547db96d56Sopenharmony_ci                zipfp.writestr(zinfo, content)
16557db96d56Sopenharmony_ci
16567db96d56Sopenharmony_ci            arcname = arcname.replace(os.sep, "/")
16577db96d56Sopenharmony_ci            targetpath = os.path.join('target', 'subdir', 'subsub')
16587db96d56Sopenharmony_ci            correctfile = os.path.join(targetpath, *fixedname.split('/'))
16597db96d56Sopenharmony_ci
16607db96d56Sopenharmony_ci            with zipfile.ZipFile(TESTFN2, 'r') as zipfp:
16617db96d56Sopenharmony_ci                writtenfile = zipfp.extract(arcname, targetpath)
16627db96d56Sopenharmony_ci                self.assertEqual(writtenfile, correctfile,
16637db96d56Sopenharmony_ci                                 msg='extract %r: %r != %r' %
16647db96d56Sopenharmony_ci                                 (arcname, writtenfile, correctfile))
16657db96d56Sopenharmony_ci            self.check_file(correctfile, content)
16667db96d56Sopenharmony_ci            rmtree('target')
16677db96d56Sopenharmony_ci
16687db96d56Sopenharmony_ci            with zipfile.ZipFile(TESTFN2, 'r') as zipfp:
16697db96d56Sopenharmony_ci                zipfp.extractall(targetpath)
16707db96d56Sopenharmony_ci            self.check_file(correctfile, content)
16717db96d56Sopenharmony_ci            rmtree('target')
16727db96d56Sopenharmony_ci
16737db96d56Sopenharmony_ci            correctfile = os.path.join(os.getcwd(), *fixedname.split('/'))
16747db96d56Sopenharmony_ci
16757db96d56Sopenharmony_ci            with zipfile.ZipFile(TESTFN2, 'r') as zipfp:
16767db96d56Sopenharmony_ci                writtenfile = zipfp.extract(arcname)
16777db96d56Sopenharmony_ci                self.assertEqual(writtenfile, correctfile,
16787db96d56Sopenharmony_ci                                 msg="extract %r" % arcname)
16797db96d56Sopenharmony_ci            self.check_file(correctfile, content)
16807db96d56Sopenharmony_ci            rmtree(fixedname.split('/')[0])
16817db96d56Sopenharmony_ci
16827db96d56Sopenharmony_ci            with zipfile.ZipFile(TESTFN2, 'r') as zipfp:
16837db96d56Sopenharmony_ci                zipfp.extractall()
16847db96d56Sopenharmony_ci            self.check_file(correctfile, content)
16857db96d56Sopenharmony_ci            rmtree(fixedname.split('/')[0])
16867db96d56Sopenharmony_ci
16877db96d56Sopenharmony_ci            unlink(TESTFN2)
16887db96d56Sopenharmony_ci
16897db96d56Sopenharmony_ci
16907db96d56Sopenharmony_ciclass OtherTests(unittest.TestCase):
16917db96d56Sopenharmony_ci    def test_open_via_zip_info(self):
16927db96d56Sopenharmony_ci        # Create the ZIP archive
16937db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, "w", zipfile.ZIP_STORED) as zipfp:
16947db96d56Sopenharmony_ci            zipfp.writestr("name", "foo")
16957db96d56Sopenharmony_ci            with self.assertWarns(UserWarning):
16967db96d56Sopenharmony_ci                zipfp.writestr("name", "bar")
16977db96d56Sopenharmony_ci            self.assertEqual(zipfp.namelist(), ["name"] * 2)
16987db96d56Sopenharmony_ci
16997db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, "r") as zipfp:
17007db96d56Sopenharmony_ci            infos = zipfp.infolist()
17017db96d56Sopenharmony_ci            data = b""
17027db96d56Sopenharmony_ci            for info in infos:
17037db96d56Sopenharmony_ci                with zipfp.open(info) as zipopen:
17047db96d56Sopenharmony_ci                    data += zipopen.read()
17057db96d56Sopenharmony_ci            self.assertIn(data, {b"foobar", b"barfoo"})
17067db96d56Sopenharmony_ci            data = b""
17077db96d56Sopenharmony_ci            for info in infos:
17087db96d56Sopenharmony_ci                data += zipfp.read(info)
17097db96d56Sopenharmony_ci            self.assertIn(data, {b"foobar", b"barfoo"})
17107db96d56Sopenharmony_ci
17117db96d56Sopenharmony_ci    def test_writestr_extended_local_header_issue1202(self):
17127db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, 'w') as orig_zip:
17137db96d56Sopenharmony_ci            for data in 'abcdefghijklmnop':
17147db96d56Sopenharmony_ci                zinfo = zipfile.ZipInfo(data)
17157db96d56Sopenharmony_ci                zinfo.flag_bits |= zipfile._MASK_USE_DATA_DESCRIPTOR  # Include an extended local header.
17167db96d56Sopenharmony_ci                orig_zip.writestr(zinfo, data)
17177db96d56Sopenharmony_ci
17187db96d56Sopenharmony_ci    def test_close(self):
17197db96d56Sopenharmony_ci        """Check that the zipfile is closed after the 'with' block."""
17207db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, "w") as zipfp:
17217db96d56Sopenharmony_ci            for fpath, fdata in SMALL_TEST_DATA:
17227db96d56Sopenharmony_ci                zipfp.writestr(fpath, fdata)
17237db96d56Sopenharmony_ci                self.assertIsNotNone(zipfp.fp, 'zipfp is not open')
17247db96d56Sopenharmony_ci        self.assertIsNone(zipfp.fp, 'zipfp is not closed')
17257db96d56Sopenharmony_ci
17267db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, "r") as zipfp:
17277db96d56Sopenharmony_ci            self.assertIsNotNone(zipfp.fp, 'zipfp is not open')
17287db96d56Sopenharmony_ci        self.assertIsNone(zipfp.fp, 'zipfp is not closed')
17297db96d56Sopenharmony_ci
17307db96d56Sopenharmony_ci    def test_close_on_exception(self):
17317db96d56Sopenharmony_ci        """Check that the zipfile is closed if an exception is raised in the
17327db96d56Sopenharmony_ci        'with' block."""
17337db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, "w") as zipfp:
17347db96d56Sopenharmony_ci            for fpath, fdata in SMALL_TEST_DATA:
17357db96d56Sopenharmony_ci                zipfp.writestr(fpath, fdata)
17367db96d56Sopenharmony_ci
17377db96d56Sopenharmony_ci        try:
17387db96d56Sopenharmony_ci            with zipfile.ZipFile(TESTFN2, "r") as zipfp2:
17397db96d56Sopenharmony_ci                raise zipfile.BadZipFile()
17407db96d56Sopenharmony_ci        except zipfile.BadZipFile:
17417db96d56Sopenharmony_ci            self.assertIsNone(zipfp2.fp, 'zipfp is not closed')
17427db96d56Sopenharmony_ci
17437db96d56Sopenharmony_ci    def test_unsupported_version(self):
17447db96d56Sopenharmony_ci        # File has an extract_version of 120
17457db96d56Sopenharmony_ci        data = (b'PK\x03\x04x\x00\x00\x00\x00\x00!p\xa1@\x00\x00\x00\x00\x00\x00'
17467db96d56Sopenharmony_ci                b'\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00xPK\x01\x02x\x03x\x00\x00\x00\x00'
17477db96d56Sopenharmony_ci                b'\x00!p\xa1@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00'
17487db96d56Sopenharmony_ci                b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x01\x00\x00\x00\x00xPK\x05\x06'
17497db96d56Sopenharmony_ci                b'\x00\x00\x00\x00\x01\x00\x01\x00/\x00\x00\x00\x1f\x00\x00\x00\x00\x00')
17507db96d56Sopenharmony_ci
17517db96d56Sopenharmony_ci        self.assertRaises(NotImplementedError, zipfile.ZipFile,
17527db96d56Sopenharmony_ci                          io.BytesIO(data), 'r')
17537db96d56Sopenharmony_ci
17547db96d56Sopenharmony_ci    @requires_zlib()
17557db96d56Sopenharmony_ci    def test_read_unicode_filenames(self):
17567db96d56Sopenharmony_ci        # bug #10801
17577db96d56Sopenharmony_ci        fname = findfile('zip_cp437_header.zip')
17587db96d56Sopenharmony_ci        with zipfile.ZipFile(fname) as zipfp:
17597db96d56Sopenharmony_ci            for name in zipfp.namelist():
17607db96d56Sopenharmony_ci                zipfp.open(name).close()
17617db96d56Sopenharmony_ci
17627db96d56Sopenharmony_ci    def test_write_unicode_filenames(self):
17637db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, "w") as zf:
17647db96d56Sopenharmony_ci            zf.writestr("foo.txt", "Test for unicode filename")
17657db96d56Sopenharmony_ci            zf.writestr("\xf6.txt", "Test for unicode filename")
17667db96d56Sopenharmony_ci            self.assertIsInstance(zf.infolist()[0].filename, str)
17677db96d56Sopenharmony_ci
17687db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, "r") as zf:
17697db96d56Sopenharmony_ci            self.assertEqual(zf.filelist[0].filename, "foo.txt")
17707db96d56Sopenharmony_ci            self.assertEqual(zf.filelist[1].filename, "\xf6.txt")
17717db96d56Sopenharmony_ci
17727db96d56Sopenharmony_ci    def test_read_after_write_unicode_filenames(self):
17737db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, 'w') as zipfp:
17747db96d56Sopenharmony_ci            zipfp.writestr('приклад', b'sample')
17757db96d56Sopenharmony_ci            self.assertEqual(zipfp.read('приклад'), b'sample')
17767db96d56Sopenharmony_ci
17777db96d56Sopenharmony_ci    def test_exclusive_create_zip_file(self):
17787db96d56Sopenharmony_ci        """Test exclusive creating a new zipfile."""
17797db96d56Sopenharmony_ci        unlink(TESTFN2)
17807db96d56Sopenharmony_ci        filename = 'testfile.txt'
17817db96d56Sopenharmony_ci        content = b'hello, world. this is some content.'
17827db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, "x", zipfile.ZIP_STORED) as zipfp:
17837db96d56Sopenharmony_ci            zipfp.writestr(filename, content)
17847db96d56Sopenharmony_ci        with self.assertRaises(FileExistsError):
17857db96d56Sopenharmony_ci            zipfile.ZipFile(TESTFN2, "x", zipfile.ZIP_STORED)
17867db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, "r") as zipfp:
17877db96d56Sopenharmony_ci            self.assertEqual(zipfp.namelist(), [filename])
17887db96d56Sopenharmony_ci            self.assertEqual(zipfp.read(filename), content)
17897db96d56Sopenharmony_ci
17907db96d56Sopenharmony_ci    def test_create_non_existent_file_for_append(self):
17917db96d56Sopenharmony_ci        if os.path.exists(TESTFN):
17927db96d56Sopenharmony_ci            os.unlink(TESTFN)
17937db96d56Sopenharmony_ci
17947db96d56Sopenharmony_ci        filename = 'testfile.txt'
17957db96d56Sopenharmony_ci        content = b'hello, world. this is some content.'
17967db96d56Sopenharmony_ci
17977db96d56Sopenharmony_ci        try:
17987db96d56Sopenharmony_ci            with zipfile.ZipFile(TESTFN, 'a') as zf:
17997db96d56Sopenharmony_ci                zf.writestr(filename, content)
18007db96d56Sopenharmony_ci        except OSError:
18017db96d56Sopenharmony_ci            self.fail('Could not append data to a non-existent zip file.')
18027db96d56Sopenharmony_ci
18037db96d56Sopenharmony_ci        self.assertTrue(os.path.exists(TESTFN))
18047db96d56Sopenharmony_ci
18057db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, 'r') as zf:
18067db96d56Sopenharmony_ci            self.assertEqual(zf.read(filename), content)
18077db96d56Sopenharmony_ci
18087db96d56Sopenharmony_ci    def test_close_erroneous_file(self):
18097db96d56Sopenharmony_ci        # This test checks that the ZipFile constructor closes the file object
18107db96d56Sopenharmony_ci        # it opens if there's an error in the file.  If it doesn't, the
18117db96d56Sopenharmony_ci        # traceback holds a reference to the ZipFile object and, indirectly,
18127db96d56Sopenharmony_ci        # the file object.
18137db96d56Sopenharmony_ci        # On Windows, this causes the os.unlink() call to fail because the
18147db96d56Sopenharmony_ci        # underlying file is still open.  This is SF bug #412214.
18157db96d56Sopenharmony_ci        #
18167db96d56Sopenharmony_ci        with open(TESTFN, "w", encoding="utf-8") as fp:
18177db96d56Sopenharmony_ci            fp.write("this is not a legal zip file\n")
18187db96d56Sopenharmony_ci        try:
18197db96d56Sopenharmony_ci            zf = zipfile.ZipFile(TESTFN)
18207db96d56Sopenharmony_ci        except zipfile.BadZipFile:
18217db96d56Sopenharmony_ci            pass
18227db96d56Sopenharmony_ci
18237db96d56Sopenharmony_ci    def test_is_zip_erroneous_file(self):
18247db96d56Sopenharmony_ci        """Check that is_zipfile() correctly identifies non-zip files."""
18257db96d56Sopenharmony_ci        # - passing a filename
18267db96d56Sopenharmony_ci        with open(TESTFN, "w", encoding='utf-8') as fp:
18277db96d56Sopenharmony_ci            fp.write("this is not a legal zip file\n")
18287db96d56Sopenharmony_ci        self.assertFalse(zipfile.is_zipfile(TESTFN))
18297db96d56Sopenharmony_ci        # - passing a path-like object
18307db96d56Sopenharmony_ci        self.assertFalse(zipfile.is_zipfile(pathlib.Path(TESTFN)))
18317db96d56Sopenharmony_ci        # - passing a file object
18327db96d56Sopenharmony_ci        with open(TESTFN, "rb") as fp:
18337db96d56Sopenharmony_ci            self.assertFalse(zipfile.is_zipfile(fp))
18347db96d56Sopenharmony_ci        # - passing a file-like object
18357db96d56Sopenharmony_ci        fp = io.BytesIO()
18367db96d56Sopenharmony_ci        fp.write(b"this is not a legal zip file\n")
18377db96d56Sopenharmony_ci        self.assertFalse(zipfile.is_zipfile(fp))
18387db96d56Sopenharmony_ci        fp.seek(0, 0)
18397db96d56Sopenharmony_ci        self.assertFalse(zipfile.is_zipfile(fp))
18407db96d56Sopenharmony_ci
18417db96d56Sopenharmony_ci    def test_damaged_zipfile(self):
18427db96d56Sopenharmony_ci        """Check that zipfiles with missing bytes at the end raise BadZipFile."""
18437db96d56Sopenharmony_ci        # - Create a valid zip file
18447db96d56Sopenharmony_ci        fp = io.BytesIO()
18457db96d56Sopenharmony_ci        with zipfile.ZipFile(fp, mode="w") as zipf:
18467db96d56Sopenharmony_ci            zipf.writestr("foo.txt", b"O, for a Muse of Fire!")
18477db96d56Sopenharmony_ci        zipfiledata = fp.getvalue()
18487db96d56Sopenharmony_ci
18497db96d56Sopenharmony_ci        # - Now create copies of it missing the last N bytes and make sure
18507db96d56Sopenharmony_ci        #   a BadZipFile exception is raised when we try to open it
18517db96d56Sopenharmony_ci        for N in range(len(zipfiledata)):
18527db96d56Sopenharmony_ci            fp = io.BytesIO(zipfiledata[:N])
18537db96d56Sopenharmony_ci            self.assertRaises(zipfile.BadZipFile, zipfile.ZipFile, fp)
18547db96d56Sopenharmony_ci
18557db96d56Sopenharmony_ci    def test_is_zip_valid_file(self):
18567db96d56Sopenharmony_ci        """Check that is_zipfile() correctly identifies zip files."""
18577db96d56Sopenharmony_ci        # - passing a filename
18587db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, mode="w") as zipf:
18597db96d56Sopenharmony_ci            zipf.writestr("foo.txt", b"O, for a Muse of Fire!")
18607db96d56Sopenharmony_ci
18617db96d56Sopenharmony_ci        self.assertTrue(zipfile.is_zipfile(TESTFN))
18627db96d56Sopenharmony_ci        # - passing a file object
18637db96d56Sopenharmony_ci        with open(TESTFN, "rb") as fp:
18647db96d56Sopenharmony_ci            self.assertTrue(zipfile.is_zipfile(fp))
18657db96d56Sopenharmony_ci            fp.seek(0, 0)
18667db96d56Sopenharmony_ci            zip_contents = fp.read()
18677db96d56Sopenharmony_ci        # - passing a file-like object
18687db96d56Sopenharmony_ci        fp = io.BytesIO()
18697db96d56Sopenharmony_ci        fp.write(zip_contents)
18707db96d56Sopenharmony_ci        self.assertTrue(zipfile.is_zipfile(fp))
18717db96d56Sopenharmony_ci        fp.seek(0, 0)
18727db96d56Sopenharmony_ci        self.assertTrue(zipfile.is_zipfile(fp))
18737db96d56Sopenharmony_ci
18747db96d56Sopenharmony_ci    def test_non_existent_file_raises_OSError(self):
18757db96d56Sopenharmony_ci        # make sure we don't raise an AttributeError when a partially-constructed
18767db96d56Sopenharmony_ci        # ZipFile instance is finalized; this tests for regression on SF tracker
18777db96d56Sopenharmony_ci        # bug #403871.
18787db96d56Sopenharmony_ci
18797db96d56Sopenharmony_ci        # The bug we're testing for caused an AttributeError to be raised
18807db96d56Sopenharmony_ci        # when a ZipFile instance was created for a file that did not
18817db96d56Sopenharmony_ci        # exist; the .fp member was not initialized but was needed by the
18827db96d56Sopenharmony_ci        # __del__() method.  Since the AttributeError is in the __del__(),
18837db96d56Sopenharmony_ci        # it is ignored, but the user should be sufficiently annoyed by
18847db96d56Sopenharmony_ci        # the message on the output that regression will be noticed
18857db96d56Sopenharmony_ci        # quickly.
18867db96d56Sopenharmony_ci        self.assertRaises(OSError, zipfile.ZipFile, TESTFN)
18877db96d56Sopenharmony_ci
18887db96d56Sopenharmony_ci    def test_empty_file_raises_BadZipFile(self):
18897db96d56Sopenharmony_ci        f = open(TESTFN, 'w', encoding='utf-8')
18907db96d56Sopenharmony_ci        f.close()
18917db96d56Sopenharmony_ci        self.assertRaises(zipfile.BadZipFile, zipfile.ZipFile, TESTFN)
18927db96d56Sopenharmony_ci
18937db96d56Sopenharmony_ci        with open(TESTFN, 'w', encoding='utf-8') as fp:
18947db96d56Sopenharmony_ci            fp.write("short file")
18957db96d56Sopenharmony_ci        self.assertRaises(zipfile.BadZipFile, zipfile.ZipFile, TESTFN)
18967db96d56Sopenharmony_ci
18977db96d56Sopenharmony_ci    def test_negative_central_directory_offset_raises_BadZipFile(self):
18987db96d56Sopenharmony_ci        # Zip file containing an empty EOCD record
18997db96d56Sopenharmony_ci        buffer = bytearray(b'PK\x05\x06' + b'\0'*18)
19007db96d56Sopenharmony_ci
19017db96d56Sopenharmony_ci        # Set the size of the central directory bytes to become 1,
19027db96d56Sopenharmony_ci        # causing the central directory offset to become negative
19037db96d56Sopenharmony_ci        for dirsize in 1, 2**32-1:
19047db96d56Sopenharmony_ci            buffer[12:16] = struct.pack('<L', dirsize)
19057db96d56Sopenharmony_ci            f = io.BytesIO(buffer)
19067db96d56Sopenharmony_ci            self.assertRaises(zipfile.BadZipFile, zipfile.ZipFile, f)
19077db96d56Sopenharmony_ci
19087db96d56Sopenharmony_ci    def test_closed_zip_raises_ValueError(self):
19097db96d56Sopenharmony_ci        """Verify that testzip() doesn't swallow inappropriate exceptions."""
19107db96d56Sopenharmony_ci        data = io.BytesIO()
19117db96d56Sopenharmony_ci        with zipfile.ZipFile(data, mode="w") as zipf:
19127db96d56Sopenharmony_ci            zipf.writestr("foo.txt", "O, for a Muse of Fire!")
19137db96d56Sopenharmony_ci
19147db96d56Sopenharmony_ci        # This is correct; calling .read on a closed ZipFile should raise
19157db96d56Sopenharmony_ci        # a ValueError, and so should calling .testzip.  An earlier
19167db96d56Sopenharmony_ci        # version of .testzip would swallow this exception (and any other)
19177db96d56Sopenharmony_ci        # and report that the first file in the archive was corrupt.
19187db96d56Sopenharmony_ci        self.assertRaises(ValueError, zipf.read, "foo.txt")
19197db96d56Sopenharmony_ci        self.assertRaises(ValueError, zipf.open, "foo.txt")
19207db96d56Sopenharmony_ci        self.assertRaises(ValueError, zipf.testzip)
19217db96d56Sopenharmony_ci        self.assertRaises(ValueError, zipf.writestr, "bogus.txt", "bogus")
19227db96d56Sopenharmony_ci        with open(TESTFN, 'w', encoding='utf-8') as f:
19237db96d56Sopenharmony_ci            f.write('zipfile test data')
19247db96d56Sopenharmony_ci        self.assertRaises(ValueError, zipf.write, TESTFN)
19257db96d56Sopenharmony_ci
19267db96d56Sopenharmony_ci    def test_bad_constructor_mode(self):
19277db96d56Sopenharmony_ci        """Check that bad modes passed to ZipFile constructor are caught."""
19287db96d56Sopenharmony_ci        self.assertRaises(ValueError, zipfile.ZipFile, TESTFN, "q")
19297db96d56Sopenharmony_ci
19307db96d56Sopenharmony_ci    def test_bad_open_mode(self):
19317db96d56Sopenharmony_ci        """Check that bad modes passed to ZipFile.open are caught."""
19327db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, mode="w") as zipf:
19337db96d56Sopenharmony_ci            zipf.writestr("foo.txt", "O, for a Muse of Fire!")
19347db96d56Sopenharmony_ci
19357db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, mode="r") as zipf:
19367db96d56Sopenharmony_ci            # read the data to make sure the file is there
19377db96d56Sopenharmony_ci            zipf.read("foo.txt")
19387db96d56Sopenharmony_ci            self.assertRaises(ValueError, zipf.open, "foo.txt", "q")
19397db96d56Sopenharmony_ci            # universal newlines support is removed
19407db96d56Sopenharmony_ci            self.assertRaises(ValueError, zipf.open, "foo.txt", "U")
19417db96d56Sopenharmony_ci            self.assertRaises(ValueError, zipf.open, "foo.txt", "rU")
19427db96d56Sopenharmony_ci
19437db96d56Sopenharmony_ci    def test_read0(self):
19447db96d56Sopenharmony_ci        """Check that calling read(0) on a ZipExtFile object returns an empty
19457db96d56Sopenharmony_ci        string and doesn't advance file pointer."""
19467db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, mode="w") as zipf:
19477db96d56Sopenharmony_ci            zipf.writestr("foo.txt", "O, for a Muse of Fire!")
19487db96d56Sopenharmony_ci            # read the data to make sure the file is there
19497db96d56Sopenharmony_ci            with zipf.open("foo.txt") as f:
19507db96d56Sopenharmony_ci                for i in range(FIXEDTEST_SIZE):
19517db96d56Sopenharmony_ci                    self.assertEqual(f.read(0), b'')
19527db96d56Sopenharmony_ci
19537db96d56Sopenharmony_ci                self.assertEqual(f.read(), b"O, for a Muse of Fire!")
19547db96d56Sopenharmony_ci
19557db96d56Sopenharmony_ci    def test_open_non_existent_item(self):
19567db96d56Sopenharmony_ci        """Check that attempting to call open() for an item that doesn't
19577db96d56Sopenharmony_ci        exist in the archive raises a RuntimeError."""
19587db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, mode="w") as zipf:
19597db96d56Sopenharmony_ci            self.assertRaises(KeyError, zipf.open, "foo.txt", "r")
19607db96d56Sopenharmony_ci
19617db96d56Sopenharmony_ci    def test_bad_compression_mode(self):
19627db96d56Sopenharmony_ci        """Check that bad compression methods passed to ZipFile.open are
19637db96d56Sopenharmony_ci        caught."""
19647db96d56Sopenharmony_ci        self.assertRaises(NotImplementedError, zipfile.ZipFile, TESTFN, "w", -1)
19657db96d56Sopenharmony_ci
19667db96d56Sopenharmony_ci    def test_unsupported_compression(self):
19677db96d56Sopenharmony_ci        # data is declared as shrunk, but actually deflated
19687db96d56Sopenharmony_ci        data = (b'PK\x03\x04.\x00\x00\x00\x01\x00\xe4C\xa1@\x00\x00\x00'
19697db96d56Sopenharmony_ci                b'\x00\x02\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00x\x03\x00PK\x01'
19707db96d56Sopenharmony_ci                b'\x02.\x03.\x00\x00\x00\x01\x00\xe4C\xa1@\x00\x00\x00\x00\x02\x00\x00'
19717db96d56Sopenharmony_ci                b'\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
19727db96d56Sopenharmony_ci                b'\x80\x01\x00\x00\x00\x00xPK\x05\x06\x00\x00\x00\x00\x01\x00\x01\x00'
19737db96d56Sopenharmony_ci                b'/\x00\x00\x00!\x00\x00\x00\x00\x00')
19747db96d56Sopenharmony_ci        with zipfile.ZipFile(io.BytesIO(data), 'r') as zipf:
19757db96d56Sopenharmony_ci            self.assertRaises(NotImplementedError, zipf.open, 'x')
19767db96d56Sopenharmony_ci
19777db96d56Sopenharmony_ci    def test_null_byte_in_filename(self):
19787db96d56Sopenharmony_ci        """Check that a filename containing a null byte is properly
19797db96d56Sopenharmony_ci        terminated."""
19807db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, mode="w") as zipf:
19817db96d56Sopenharmony_ci            zipf.writestr("foo.txt\x00qqq", b"O, for a Muse of Fire!")
19827db96d56Sopenharmony_ci            self.assertEqual(zipf.namelist(), ['foo.txt'])
19837db96d56Sopenharmony_ci
19847db96d56Sopenharmony_ci    def test_struct_sizes(self):
19857db96d56Sopenharmony_ci        """Check that ZIP internal structure sizes are calculated correctly."""
19867db96d56Sopenharmony_ci        self.assertEqual(zipfile.sizeEndCentDir, 22)
19877db96d56Sopenharmony_ci        self.assertEqual(zipfile.sizeCentralDir, 46)
19887db96d56Sopenharmony_ci        self.assertEqual(zipfile.sizeEndCentDir64, 56)
19897db96d56Sopenharmony_ci        self.assertEqual(zipfile.sizeEndCentDir64Locator, 20)
19907db96d56Sopenharmony_ci
19917db96d56Sopenharmony_ci    def test_comments(self):
19927db96d56Sopenharmony_ci        """Check that comments on the archive are handled properly."""
19937db96d56Sopenharmony_ci
19947db96d56Sopenharmony_ci        # check default comment is empty
19957db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, mode="w") as zipf:
19967db96d56Sopenharmony_ci            self.assertEqual(zipf.comment, b'')
19977db96d56Sopenharmony_ci            zipf.writestr("foo.txt", "O, for a Muse of Fire!")
19987db96d56Sopenharmony_ci
19997db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, mode="r") as zipfr:
20007db96d56Sopenharmony_ci            self.assertEqual(zipfr.comment, b'')
20017db96d56Sopenharmony_ci
20027db96d56Sopenharmony_ci        # check a simple short comment
20037db96d56Sopenharmony_ci        comment = b'Bravely taking to his feet, he beat a very brave retreat.'
20047db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, mode="w") as zipf:
20057db96d56Sopenharmony_ci            zipf.comment = comment
20067db96d56Sopenharmony_ci            zipf.writestr("foo.txt", "O, for a Muse of Fire!")
20077db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, mode="r") as zipfr:
20087db96d56Sopenharmony_ci            self.assertEqual(zipf.comment, comment)
20097db96d56Sopenharmony_ci
20107db96d56Sopenharmony_ci        # check a comment of max length
20117db96d56Sopenharmony_ci        comment2 = ''.join(['%d' % (i**3 % 10) for i in range((1 << 16)-1)])
20127db96d56Sopenharmony_ci        comment2 = comment2.encode("ascii")
20137db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, mode="w") as zipf:
20147db96d56Sopenharmony_ci            zipf.comment = comment2
20157db96d56Sopenharmony_ci            zipf.writestr("foo.txt", "O, for a Muse of Fire!")
20167db96d56Sopenharmony_ci
20177db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, mode="r") as zipfr:
20187db96d56Sopenharmony_ci            self.assertEqual(zipfr.comment, comment2)
20197db96d56Sopenharmony_ci
20207db96d56Sopenharmony_ci        # check a comment that is too long is truncated
20217db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, mode="w") as zipf:
20227db96d56Sopenharmony_ci            with self.assertWarns(UserWarning):
20237db96d56Sopenharmony_ci                zipf.comment = comment2 + b'oops'
20247db96d56Sopenharmony_ci            zipf.writestr("foo.txt", "O, for a Muse of Fire!")
20257db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, mode="r") as zipfr:
20267db96d56Sopenharmony_ci            self.assertEqual(zipfr.comment, comment2)
20277db96d56Sopenharmony_ci
20287db96d56Sopenharmony_ci        # check that comments are correctly modified in append mode
20297db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN,mode="w") as zipf:
20307db96d56Sopenharmony_ci            zipf.comment = b"original comment"
20317db96d56Sopenharmony_ci            zipf.writestr("foo.txt", "O, for a Muse of Fire!")
20327db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN,mode="a") as zipf:
20337db96d56Sopenharmony_ci            zipf.comment = b"an updated comment"
20347db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN,mode="r") as zipf:
20357db96d56Sopenharmony_ci            self.assertEqual(zipf.comment, b"an updated comment")
20367db96d56Sopenharmony_ci
20377db96d56Sopenharmony_ci        # check that comments are correctly shortened in append mode
20387db96d56Sopenharmony_ci        # and the file is indeed truncated
20397db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN,mode="w") as zipf:
20407db96d56Sopenharmony_ci            zipf.comment = b"original comment that's longer"
20417db96d56Sopenharmony_ci            zipf.writestr("foo.txt", "O, for a Muse of Fire!")
20427db96d56Sopenharmony_ci        original_zip_size = os.path.getsize(TESTFN)
20437db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN,mode="a") as zipf:
20447db96d56Sopenharmony_ci            zipf.comment = b"shorter comment"
20457db96d56Sopenharmony_ci        self.assertTrue(original_zip_size > os.path.getsize(TESTFN))
20467db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN,mode="r") as zipf:
20477db96d56Sopenharmony_ci            self.assertEqual(zipf.comment, b"shorter comment")
20487db96d56Sopenharmony_ci
20497db96d56Sopenharmony_ci    def test_unicode_comment(self):
20507db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, "w", zipfile.ZIP_STORED) as zipf:
20517db96d56Sopenharmony_ci            zipf.writestr("foo.txt", "O, for a Muse of Fire!")
20527db96d56Sopenharmony_ci            with self.assertRaises(TypeError):
20537db96d56Sopenharmony_ci                zipf.comment = "this is an error"
20547db96d56Sopenharmony_ci
20557db96d56Sopenharmony_ci    def test_change_comment_in_empty_archive(self):
20567db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, "a", zipfile.ZIP_STORED) as zipf:
20577db96d56Sopenharmony_ci            self.assertFalse(zipf.filelist)
20587db96d56Sopenharmony_ci            zipf.comment = b"this is a comment"
20597db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, "r") as zipf:
20607db96d56Sopenharmony_ci            self.assertEqual(zipf.comment, b"this is a comment")
20617db96d56Sopenharmony_ci
20627db96d56Sopenharmony_ci    def test_change_comment_in_nonempty_archive(self):
20637db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, "w", zipfile.ZIP_STORED) as zipf:
20647db96d56Sopenharmony_ci            zipf.writestr("foo.txt", "O, for a Muse of Fire!")
20657db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, "a", zipfile.ZIP_STORED) as zipf:
20667db96d56Sopenharmony_ci            self.assertTrue(zipf.filelist)
20677db96d56Sopenharmony_ci            zipf.comment = b"this is a comment"
20687db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, "r") as zipf:
20697db96d56Sopenharmony_ci            self.assertEqual(zipf.comment, b"this is a comment")
20707db96d56Sopenharmony_ci
20717db96d56Sopenharmony_ci    def test_empty_zipfile(self):
20727db96d56Sopenharmony_ci        # Check that creating a file in 'w' or 'a' mode and closing without
20737db96d56Sopenharmony_ci        # adding any files to the archives creates a valid empty ZIP file
20747db96d56Sopenharmony_ci        zipf = zipfile.ZipFile(TESTFN, mode="w")
20757db96d56Sopenharmony_ci        zipf.close()
20767db96d56Sopenharmony_ci        try:
20777db96d56Sopenharmony_ci            zipf = zipfile.ZipFile(TESTFN, mode="r")
20787db96d56Sopenharmony_ci        except zipfile.BadZipFile:
20797db96d56Sopenharmony_ci            self.fail("Unable to create empty ZIP file in 'w' mode")
20807db96d56Sopenharmony_ci
20817db96d56Sopenharmony_ci        zipf = zipfile.ZipFile(TESTFN, mode="a")
20827db96d56Sopenharmony_ci        zipf.close()
20837db96d56Sopenharmony_ci        try:
20847db96d56Sopenharmony_ci            zipf = zipfile.ZipFile(TESTFN, mode="r")
20857db96d56Sopenharmony_ci        except:
20867db96d56Sopenharmony_ci            self.fail("Unable to create empty ZIP file in 'a' mode")
20877db96d56Sopenharmony_ci
20887db96d56Sopenharmony_ci    def test_open_empty_file(self):
20897db96d56Sopenharmony_ci        # Issue 1710703: Check that opening a file with less than 22 bytes
20907db96d56Sopenharmony_ci        # raises a BadZipFile exception (rather than the previously unhelpful
20917db96d56Sopenharmony_ci        # OSError)
20927db96d56Sopenharmony_ci        f = open(TESTFN, 'w', encoding='utf-8')
20937db96d56Sopenharmony_ci        f.close()
20947db96d56Sopenharmony_ci        self.assertRaises(zipfile.BadZipFile, zipfile.ZipFile, TESTFN, 'r')
20957db96d56Sopenharmony_ci
20967db96d56Sopenharmony_ci    def test_create_zipinfo_before_1980(self):
20977db96d56Sopenharmony_ci        self.assertRaises(ValueError,
20987db96d56Sopenharmony_ci                          zipfile.ZipInfo, 'seventies', (1979, 1, 1, 0, 0, 0))
20997db96d56Sopenharmony_ci
21007db96d56Sopenharmony_ci    def test_create_empty_zipinfo_repr(self):
21017db96d56Sopenharmony_ci        """Before bpo-26185, repr() on empty ZipInfo object was failing."""
21027db96d56Sopenharmony_ci        zi = zipfile.ZipInfo(filename="empty")
21037db96d56Sopenharmony_ci        self.assertEqual(repr(zi), "<ZipInfo filename='empty' file_size=0>")
21047db96d56Sopenharmony_ci
21057db96d56Sopenharmony_ci    def test_create_empty_zipinfo_default_attributes(self):
21067db96d56Sopenharmony_ci        """Ensure all required attributes are set."""
21077db96d56Sopenharmony_ci        zi = zipfile.ZipInfo()
21087db96d56Sopenharmony_ci        self.assertEqual(zi.orig_filename, "NoName")
21097db96d56Sopenharmony_ci        self.assertEqual(zi.filename, "NoName")
21107db96d56Sopenharmony_ci        self.assertEqual(zi.date_time, (1980, 1, 1, 0, 0, 0))
21117db96d56Sopenharmony_ci        self.assertEqual(zi.compress_type, zipfile.ZIP_STORED)
21127db96d56Sopenharmony_ci        self.assertEqual(zi.comment, b"")
21137db96d56Sopenharmony_ci        self.assertEqual(zi.extra, b"")
21147db96d56Sopenharmony_ci        self.assertIn(zi.create_system, (0, 3))
21157db96d56Sopenharmony_ci        self.assertEqual(zi.create_version, zipfile.DEFAULT_VERSION)
21167db96d56Sopenharmony_ci        self.assertEqual(zi.extract_version, zipfile.DEFAULT_VERSION)
21177db96d56Sopenharmony_ci        self.assertEqual(zi.reserved, 0)
21187db96d56Sopenharmony_ci        self.assertEqual(zi.flag_bits, 0)
21197db96d56Sopenharmony_ci        self.assertEqual(zi.volume, 0)
21207db96d56Sopenharmony_ci        self.assertEqual(zi.internal_attr, 0)
21217db96d56Sopenharmony_ci        self.assertEqual(zi.external_attr, 0)
21227db96d56Sopenharmony_ci
21237db96d56Sopenharmony_ci        # Before bpo-26185, both were missing
21247db96d56Sopenharmony_ci        self.assertEqual(zi.file_size, 0)
21257db96d56Sopenharmony_ci        self.assertEqual(zi.compress_size, 0)
21267db96d56Sopenharmony_ci
21277db96d56Sopenharmony_ci    def test_zipfile_with_short_extra_field(self):
21287db96d56Sopenharmony_ci        """If an extra field in the header is less than 4 bytes, skip it."""
21297db96d56Sopenharmony_ci        zipdata = (
21307db96d56Sopenharmony_ci            b'PK\x03\x04\x14\x00\x00\x00\x00\x00\x93\x9b\xad@\x8b\x9e'
21317db96d56Sopenharmony_ci            b'\xd9\xd3\x01\x00\x00\x00\x01\x00\x00\x00\x03\x00\x03\x00ab'
21327db96d56Sopenharmony_ci            b'c\x00\x00\x00APK\x01\x02\x14\x03\x14\x00\x00\x00\x00'
21337db96d56Sopenharmony_ci            b'\x00\x93\x9b\xad@\x8b\x9e\xd9\xd3\x01\x00\x00\x00\x01\x00\x00'
21347db96d56Sopenharmony_ci            b'\x00\x03\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x00'
21357db96d56Sopenharmony_ci            b'\x00\x00\x00abc\x00\x00PK\x05\x06\x00\x00\x00\x00'
21367db96d56Sopenharmony_ci            b'\x01\x00\x01\x003\x00\x00\x00%\x00\x00\x00\x00\x00'
21377db96d56Sopenharmony_ci        )
21387db96d56Sopenharmony_ci        with zipfile.ZipFile(io.BytesIO(zipdata), 'r') as zipf:
21397db96d56Sopenharmony_ci            # testzip returns the name of the first corrupt file, or None
21407db96d56Sopenharmony_ci            self.assertIsNone(zipf.testzip())
21417db96d56Sopenharmony_ci
21427db96d56Sopenharmony_ci    def test_open_conflicting_handles(self):
21437db96d56Sopenharmony_ci        # It's only possible to open one writable file handle at a time
21447db96d56Sopenharmony_ci        msg1 = b"It's fun to charter an accountant!"
21457db96d56Sopenharmony_ci        msg2 = b"And sail the wide accountant sea"
21467db96d56Sopenharmony_ci        msg3 = b"To find, explore the funds offshore"
21477db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, 'w', zipfile.ZIP_STORED) as zipf:
21487db96d56Sopenharmony_ci            with zipf.open('foo', mode='w') as w2:
21497db96d56Sopenharmony_ci                w2.write(msg1)
21507db96d56Sopenharmony_ci            with zipf.open('bar', mode='w') as w1:
21517db96d56Sopenharmony_ci                with self.assertRaises(ValueError):
21527db96d56Sopenharmony_ci                    zipf.open('handle', mode='w')
21537db96d56Sopenharmony_ci                with self.assertRaises(ValueError):
21547db96d56Sopenharmony_ci                    zipf.open('foo', mode='r')
21557db96d56Sopenharmony_ci                with self.assertRaises(ValueError):
21567db96d56Sopenharmony_ci                    zipf.writestr('str', 'abcde')
21577db96d56Sopenharmony_ci                with self.assertRaises(ValueError):
21587db96d56Sopenharmony_ci                    zipf.write(__file__, 'file')
21597db96d56Sopenharmony_ci                with self.assertRaises(ValueError):
21607db96d56Sopenharmony_ci                    zipf.close()
21617db96d56Sopenharmony_ci                w1.write(msg2)
21627db96d56Sopenharmony_ci            with zipf.open('baz', mode='w') as w2:
21637db96d56Sopenharmony_ci                w2.write(msg3)
21647db96d56Sopenharmony_ci
21657db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, 'r') as zipf:
21667db96d56Sopenharmony_ci            self.assertEqual(zipf.read('foo'), msg1)
21677db96d56Sopenharmony_ci            self.assertEqual(zipf.read('bar'), msg2)
21687db96d56Sopenharmony_ci            self.assertEqual(zipf.read('baz'), msg3)
21697db96d56Sopenharmony_ci            self.assertEqual(zipf.namelist(), ['foo', 'bar', 'baz'])
21707db96d56Sopenharmony_ci
21717db96d56Sopenharmony_ci    def test_seek_tell(self):
21727db96d56Sopenharmony_ci        # Test seek functionality
21737db96d56Sopenharmony_ci        txt = b"Where's Bruce?"
21747db96d56Sopenharmony_ci        bloc = txt.find(b"Bruce")
21757db96d56Sopenharmony_ci        # Check seek on a file
21767db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, "w") as zipf:
21777db96d56Sopenharmony_ci            zipf.writestr("foo.txt", txt)
21787db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, "r") as zipf:
21797db96d56Sopenharmony_ci            with zipf.open("foo.txt", "r") as fp:
21807db96d56Sopenharmony_ci                fp.seek(bloc, os.SEEK_SET)
21817db96d56Sopenharmony_ci                self.assertEqual(fp.tell(), bloc)
21827db96d56Sopenharmony_ci                fp.seek(-bloc, os.SEEK_CUR)
21837db96d56Sopenharmony_ci                self.assertEqual(fp.tell(), 0)
21847db96d56Sopenharmony_ci                fp.seek(bloc, os.SEEK_CUR)
21857db96d56Sopenharmony_ci                self.assertEqual(fp.tell(), bloc)
21867db96d56Sopenharmony_ci                self.assertEqual(fp.read(5), txt[bloc:bloc+5])
21877db96d56Sopenharmony_ci                fp.seek(0, os.SEEK_END)
21887db96d56Sopenharmony_ci                self.assertEqual(fp.tell(), len(txt))
21897db96d56Sopenharmony_ci                fp.seek(0, os.SEEK_SET)
21907db96d56Sopenharmony_ci                self.assertEqual(fp.tell(), 0)
21917db96d56Sopenharmony_ci        # Check seek on memory file
21927db96d56Sopenharmony_ci        data = io.BytesIO()
21937db96d56Sopenharmony_ci        with zipfile.ZipFile(data, mode="w") as zipf:
21947db96d56Sopenharmony_ci            zipf.writestr("foo.txt", txt)
21957db96d56Sopenharmony_ci        with zipfile.ZipFile(data, mode="r") as zipf:
21967db96d56Sopenharmony_ci            with zipf.open("foo.txt", "r") as fp:
21977db96d56Sopenharmony_ci                fp.seek(bloc, os.SEEK_SET)
21987db96d56Sopenharmony_ci                self.assertEqual(fp.tell(), bloc)
21997db96d56Sopenharmony_ci                fp.seek(-bloc, os.SEEK_CUR)
22007db96d56Sopenharmony_ci                self.assertEqual(fp.tell(), 0)
22017db96d56Sopenharmony_ci                fp.seek(bloc, os.SEEK_CUR)
22027db96d56Sopenharmony_ci                self.assertEqual(fp.tell(), bloc)
22037db96d56Sopenharmony_ci                self.assertEqual(fp.read(5), txt[bloc:bloc+5])
22047db96d56Sopenharmony_ci                fp.seek(0, os.SEEK_END)
22057db96d56Sopenharmony_ci                self.assertEqual(fp.tell(), len(txt))
22067db96d56Sopenharmony_ci                fp.seek(0, os.SEEK_SET)
22077db96d56Sopenharmony_ci                self.assertEqual(fp.tell(), 0)
22087db96d56Sopenharmony_ci
22097db96d56Sopenharmony_ci    @requires_bz2()
22107db96d56Sopenharmony_ci    def test_decompress_without_3rd_party_library(self):
22117db96d56Sopenharmony_ci        data = b'PK\x05\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
22127db96d56Sopenharmony_ci        zip_file = io.BytesIO(data)
22137db96d56Sopenharmony_ci        with zipfile.ZipFile(zip_file, 'w', compression=zipfile.ZIP_BZIP2) as zf:
22147db96d56Sopenharmony_ci            zf.writestr('a.txt', b'a')
22157db96d56Sopenharmony_ci        with mock.patch('zipfile.bz2', None):
22167db96d56Sopenharmony_ci            with zipfile.ZipFile(zip_file) as zf:
22177db96d56Sopenharmony_ci                self.assertRaises(RuntimeError, zf.extract, 'a.txt')
22187db96d56Sopenharmony_ci
22197db96d56Sopenharmony_ci    @requires_zlib()
22207db96d56Sopenharmony_ci    def test_full_overlap(self):
22217db96d56Sopenharmony_ci        data = (
22227db96d56Sopenharmony_ci            b'PK\x03\x04\x14\x00\x00\x00\x08\x00\xa0lH\x05\xe2\x1e'
22237db96d56Sopenharmony_ci            b'8\xbb\x10\x00\x00\x00\t\x04\x00\x00\x01\x00\x00\x00a\xed'
22247db96d56Sopenharmony_ci            b'\xc0\x81\x08\x00\x00\x00\xc00\xd6\xfbK\\d\x0b`P'
22257db96d56Sopenharmony_ci            b'K\x01\x02\x14\x00\x14\x00\x00\x00\x08\x00\xa0lH\x05\xe2'
22267db96d56Sopenharmony_ci            b'\x1e8\xbb\x10\x00\x00\x00\t\x04\x00\x00\x01\x00\x00\x00\x00'
22277db96d56Sopenharmony_ci            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00aPK'
22287db96d56Sopenharmony_ci            b'\x01\x02\x14\x00\x14\x00\x00\x00\x08\x00\xa0lH\x05\xe2\x1e'
22297db96d56Sopenharmony_ci            b'8\xbb\x10\x00\x00\x00\t\x04\x00\x00\x01\x00\x00\x00\x00\x00'
22307db96d56Sopenharmony_ci            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00bPK\x05'
22317db96d56Sopenharmony_ci            b'\x06\x00\x00\x00\x00\x02\x00\x02\x00^\x00\x00\x00/\x00\x00'
22327db96d56Sopenharmony_ci            b'\x00\x00\x00'
22337db96d56Sopenharmony_ci        )
22347db96d56Sopenharmony_ci        with zipfile.ZipFile(io.BytesIO(data), 'r') as zipf:
22357db96d56Sopenharmony_ci            self.assertEqual(zipf.namelist(), ['a', 'b'])
22367db96d56Sopenharmony_ci            zi = zipf.getinfo('a')
22377db96d56Sopenharmony_ci            self.assertEqual(zi.header_offset, 0)
22387db96d56Sopenharmony_ci            self.assertEqual(zi.compress_size, 16)
22397db96d56Sopenharmony_ci            self.assertEqual(zi.file_size, 1033)
22407db96d56Sopenharmony_ci            zi = zipf.getinfo('b')
22417db96d56Sopenharmony_ci            self.assertEqual(zi.header_offset, 0)
22427db96d56Sopenharmony_ci            self.assertEqual(zi.compress_size, 16)
22437db96d56Sopenharmony_ci            self.assertEqual(zi.file_size, 1033)
22447db96d56Sopenharmony_ci            self.assertEqual(len(zipf.read('a')), 1033)
22457db96d56Sopenharmony_ci            with self.assertRaisesRegex(zipfile.BadZipFile, 'File name.*differ'):
22467db96d56Sopenharmony_ci                zipf.read('b')
22477db96d56Sopenharmony_ci
22487db96d56Sopenharmony_ci    @requires_zlib()
22497db96d56Sopenharmony_ci    def test_quoted_overlap(self):
22507db96d56Sopenharmony_ci        data = (
22517db96d56Sopenharmony_ci            b'PK\x03\x04\x14\x00\x00\x00\x08\x00\xa0lH\x05Y\xfc'
22527db96d56Sopenharmony_ci            b'8\x044\x00\x00\x00(\x04\x00\x00\x01\x00\x00\x00a\x00'
22537db96d56Sopenharmony_ci            b'\x1f\x00\xe0\xffPK\x03\x04\x14\x00\x00\x00\x08\x00\xa0l'
22547db96d56Sopenharmony_ci            b'H\x05\xe2\x1e8\xbb\x10\x00\x00\x00\t\x04\x00\x00\x01\x00'
22557db96d56Sopenharmony_ci            b'\x00\x00b\xed\xc0\x81\x08\x00\x00\x00\xc00\xd6\xfbK\\'
22567db96d56Sopenharmony_ci            b'd\x0b`PK\x01\x02\x14\x00\x14\x00\x00\x00\x08\x00\xa0'
22577db96d56Sopenharmony_ci            b'lH\x05Y\xfc8\x044\x00\x00\x00(\x04\x00\x00\x01'
22587db96d56Sopenharmony_ci            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
22597db96d56Sopenharmony_ci            b'\x00aPK\x01\x02\x14\x00\x14\x00\x00\x00\x08\x00\xa0l'
22607db96d56Sopenharmony_ci            b'H\x05\xe2\x1e8\xbb\x10\x00\x00\x00\t\x04\x00\x00\x01\x00'
22617db96d56Sopenharmony_ci            b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00$\x00\x00\x00'
22627db96d56Sopenharmony_ci            b'bPK\x05\x06\x00\x00\x00\x00\x02\x00\x02\x00^\x00\x00'
22637db96d56Sopenharmony_ci            b'\x00S\x00\x00\x00\x00\x00'
22647db96d56Sopenharmony_ci        )
22657db96d56Sopenharmony_ci        with zipfile.ZipFile(io.BytesIO(data), 'r') as zipf:
22667db96d56Sopenharmony_ci            self.assertEqual(zipf.namelist(), ['a', 'b'])
22677db96d56Sopenharmony_ci            zi = zipf.getinfo('a')
22687db96d56Sopenharmony_ci            self.assertEqual(zi.header_offset, 0)
22697db96d56Sopenharmony_ci            self.assertEqual(zi.compress_size, 52)
22707db96d56Sopenharmony_ci            self.assertEqual(zi.file_size, 1064)
22717db96d56Sopenharmony_ci            zi = zipf.getinfo('b')
22727db96d56Sopenharmony_ci            self.assertEqual(zi.header_offset, 36)
22737db96d56Sopenharmony_ci            self.assertEqual(zi.compress_size, 16)
22747db96d56Sopenharmony_ci            self.assertEqual(zi.file_size, 1033)
22757db96d56Sopenharmony_ci            with self.assertRaisesRegex(zipfile.BadZipFile, 'Overlapped entries'):
22767db96d56Sopenharmony_ci                zipf.read('a')
22777db96d56Sopenharmony_ci            self.assertEqual(len(zipf.read('b')), 1033)
22787db96d56Sopenharmony_ci
22797db96d56Sopenharmony_ci    def tearDown(self):
22807db96d56Sopenharmony_ci        unlink(TESTFN)
22817db96d56Sopenharmony_ci        unlink(TESTFN2)
22827db96d56Sopenharmony_ci
22837db96d56Sopenharmony_ci
22847db96d56Sopenharmony_ciclass AbstractBadCrcTests:
22857db96d56Sopenharmony_ci    def test_testzip_with_bad_crc(self):
22867db96d56Sopenharmony_ci        """Tests that files with bad CRCs return their name from testzip."""
22877db96d56Sopenharmony_ci        zipdata = self.zip_with_bad_crc
22887db96d56Sopenharmony_ci
22897db96d56Sopenharmony_ci        with zipfile.ZipFile(io.BytesIO(zipdata), mode="r") as zipf:
22907db96d56Sopenharmony_ci            # testzip returns the name of the first corrupt file, or None
22917db96d56Sopenharmony_ci            self.assertEqual('afile', zipf.testzip())
22927db96d56Sopenharmony_ci
22937db96d56Sopenharmony_ci    def test_read_with_bad_crc(self):
22947db96d56Sopenharmony_ci        """Tests that files with bad CRCs raise a BadZipFile exception when read."""
22957db96d56Sopenharmony_ci        zipdata = self.zip_with_bad_crc
22967db96d56Sopenharmony_ci
22977db96d56Sopenharmony_ci        # Using ZipFile.read()
22987db96d56Sopenharmony_ci        with zipfile.ZipFile(io.BytesIO(zipdata), mode="r") as zipf:
22997db96d56Sopenharmony_ci            self.assertRaises(zipfile.BadZipFile, zipf.read, 'afile')
23007db96d56Sopenharmony_ci
23017db96d56Sopenharmony_ci        # Using ZipExtFile.read()
23027db96d56Sopenharmony_ci        with zipfile.ZipFile(io.BytesIO(zipdata), mode="r") as zipf:
23037db96d56Sopenharmony_ci            with zipf.open('afile', 'r') as corrupt_file:
23047db96d56Sopenharmony_ci                self.assertRaises(zipfile.BadZipFile, corrupt_file.read)
23057db96d56Sopenharmony_ci
23067db96d56Sopenharmony_ci        # Same with small reads (in order to exercise the buffering logic)
23077db96d56Sopenharmony_ci        with zipfile.ZipFile(io.BytesIO(zipdata), mode="r") as zipf:
23087db96d56Sopenharmony_ci            with zipf.open('afile', 'r') as corrupt_file:
23097db96d56Sopenharmony_ci                corrupt_file.MIN_READ_SIZE = 2
23107db96d56Sopenharmony_ci                with self.assertRaises(zipfile.BadZipFile):
23117db96d56Sopenharmony_ci                    while corrupt_file.read(2):
23127db96d56Sopenharmony_ci                        pass
23137db96d56Sopenharmony_ci
23147db96d56Sopenharmony_ci
23157db96d56Sopenharmony_ciclass StoredBadCrcTests(AbstractBadCrcTests, unittest.TestCase):
23167db96d56Sopenharmony_ci    compression = zipfile.ZIP_STORED
23177db96d56Sopenharmony_ci    zip_with_bad_crc = (
23187db96d56Sopenharmony_ci        b'PK\003\004\024\0\0\0\0\0 \213\212;:r'
23197db96d56Sopenharmony_ci        b'\253\377\f\0\0\0\f\0\0\0\005\0\0\000af'
23207db96d56Sopenharmony_ci        b'ilehello,AworldP'
23217db96d56Sopenharmony_ci        b'K\001\002\024\003\024\0\0\0\0\0 \213\212;:'
23227db96d56Sopenharmony_ci        b'r\253\377\f\0\0\0\f\0\0\0\005\0\0\0\0'
23237db96d56Sopenharmony_ci        b'\0\0\0\0\0\0\0\200\001\0\0\0\000afi'
23247db96d56Sopenharmony_ci        b'lePK\005\006\0\0\0\0\001\0\001\0003\000'
23257db96d56Sopenharmony_ci        b'\0\0/\0\0\0\0\0')
23267db96d56Sopenharmony_ci
23277db96d56Sopenharmony_ci@requires_zlib()
23287db96d56Sopenharmony_ciclass DeflateBadCrcTests(AbstractBadCrcTests, unittest.TestCase):
23297db96d56Sopenharmony_ci    compression = zipfile.ZIP_DEFLATED
23307db96d56Sopenharmony_ci    zip_with_bad_crc = (
23317db96d56Sopenharmony_ci        b'PK\x03\x04\x14\x00\x00\x00\x08\x00n}\x0c=FA'
23327db96d56Sopenharmony_ci        b'KE\x10\x00\x00\x00n\x00\x00\x00\x05\x00\x00\x00af'
23337db96d56Sopenharmony_ci        b'ile\xcbH\xcd\xc9\xc9W(\xcf/\xcaI\xc9\xa0'
23347db96d56Sopenharmony_ci        b'=\x13\x00PK\x01\x02\x14\x03\x14\x00\x00\x00\x08\x00n'
23357db96d56Sopenharmony_ci        b'}\x0c=FAKE\x10\x00\x00\x00n\x00\x00\x00\x05'
23367db96d56Sopenharmony_ci        b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x01\x00\x00\x00'
23377db96d56Sopenharmony_ci        b'\x00afilePK\x05\x06\x00\x00\x00\x00\x01\x00'
23387db96d56Sopenharmony_ci        b'\x01\x003\x00\x00\x003\x00\x00\x00\x00\x00')
23397db96d56Sopenharmony_ci
23407db96d56Sopenharmony_ci@requires_bz2()
23417db96d56Sopenharmony_ciclass Bzip2BadCrcTests(AbstractBadCrcTests, unittest.TestCase):
23427db96d56Sopenharmony_ci    compression = zipfile.ZIP_BZIP2
23437db96d56Sopenharmony_ci    zip_with_bad_crc = (
23447db96d56Sopenharmony_ci        b'PK\x03\x04\x14\x03\x00\x00\x0c\x00nu\x0c=FA'
23457db96d56Sopenharmony_ci        b'KE8\x00\x00\x00n\x00\x00\x00\x05\x00\x00\x00af'
23467db96d56Sopenharmony_ci        b'ileBZh91AY&SY\xd4\xa8\xca'
23477db96d56Sopenharmony_ci        b'\x7f\x00\x00\x0f\x11\x80@\x00\x06D\x90\x80 \x00 \xa5'
23487db96d56Sopenharmony_ci        b'P\xd9!\x03\x03\x13\x13\x13\x89\xa9\xa9\xc2u5:\x9f'
23497db96d56Sopenharmony_ci        b'\x8b\xb9"\x9c(HjTe?\x80PK\x01\x02\x14'
23507db96d56Sopenharmony_ci        b'\x03\x14\x03\x00\x00\x0c\x00nu\x0c=FAKE8'
23517db96d56Sopenharmony_ci        b'\x00\x00\x00n\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00'
23527db96d56Sopenharmony_ci        b'\x00 \x80\x80\x81\x00\x00\x00\x00afilePK'
23537db96d56Sopenharmony_ci        b'\x05\x06\x00\x00\x00\x00\x01\x00\x01\x003\x00\x00\x00[\x00'
23547db96d56Sopenharmony_ci        b'\x00\x00\x00\x00')
23557db96d56Sopenharmony_ci
23567db96d56Sopenharmony_ci@requires_lzma()
23577db96d56Sopenharmony_ciclass LzmaBadCrcTests(AbstractBadCrcTests, unittest.TestCase):
23587db96d56Sopenharmony_ci    compression = zipfile.ZIP_LZMA
23597db96d56Sopenharmony_ci    zip_with_bad_crc = (
23607db96d56Sopenharmony_ci        b'PK\x03\x04\x14\x03\x00\x00\x0e\x00nu\x0c=FA'
23617db96d56Sopenharmony_ci        b'KE\x1b\x00\x00\x00n\x00\x00\x00\x05\x00\x00\x00af'
23627db96d56Sopenharmony_ci        b'ile\t\x04\x05\x00]\x00\x00\x00\x04\x004\x19I'
23637db96d56Sopenharmony_ci        b'\xee\x8d\xe9\x17\x89:3`\tq!.8\x00PK'
23647db96d56Sopenharmony_ci        b'\x01\x02\x14\x03\x14\x03\x00\x00\x0e\x00nu\x0c=FA'
23657db96d56Sopenharmony_ci        b'KE\x1b\x00\x00\x00n\x00\x00\x00\x05\x00\x00\x00\x00\x00'
23667db96d56Sopenharmony_ci        b'\x00\x00\x00\x00 \x80\x80\x81\x00\x00\x00\x00afil'
23677db96d56Sopenharmony_ci        b'ePK\x05\x06\x00\x00\x00\x00\x01\x00\x01\x003\x00\x00'
23687db96d56Sopenharmony_ci        b'\x00>\x00\x00\x00\x00\x00')
23697db96d56Sopenharmony_ci
23707db96d56Sopenharmony_ci
23717db96d56Sopenharmony_ciclass DecryptionTests(unittest.TestCase):
23727db96d56Sopenharmony_ci    """Check that ZIP decryption works. Since the library does not
23737db96d56Sopenharmony_ci    support encryption at the moment, we use a pre-generated encrypted
23747db96d56Sopenharmony_ci    ZIP file."""
23757db96d56Sopenharmony_ci
23767db96d56Sopenharmony_ci    data = (
23777db96d56Sopenharmony_ci        b'PK\x03\x04\x14\x00\x01\x00\x00\x00n\x92i.#y\xef?&\x00\x00\x00\x1a\x00'
23787db96d56Sopenharmony_ci        b'\x00\x00\x08\x00\x00\x00test.txt\xfa\x10\xa0gly|\xfa-\xc5\xc0=\xf9y'
23797db96d56Sopenharmony_ci        b'\x18\xe0\xa8r\xb3Z}Lg\xbc\xae\xf9|\x9b\x19\xe4\x8b\xba\xbb)\x8c\xb0\xdbl'
23807db96d56Sopenharmony_ci        b'PK\x01\x02\x14\x00\x14\x00\x01\x00\x00\x00n\x92i.#y\xef?&\x00\x00\x00'
23817db96d56Sopenharmony_ci        b'\x1a\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x01\x00 \x00\xb6\x81'
23827db96d56Sopenharmony_ci        b'\x00\x00\x00\x00test.txtPK\x05\x06\x00\x00\x00\x00\x01\x00\x01\x006\x00'
23837db96d56Sopenharmony_ci        b'\x00\x00L\x00\x00\x00\x00\x00' )
23847db96d56Sopenharmony_ci    data2 = (
23857db96d56Sopenharmony_ci        b'PK\x03\x04\x14\x00\t\x00\x08\x00\xcf}38xu\xaa\xb2\x14\x00\x00\x00\x00\x02'
23867db96d56Sopenharmony_ci        b'\x00\x00\x04\x00\x15\x00zeroUT\t\x00\x03\xd6\x8b\x92G\xda\x8b\x92GUx\x04'
23877db96d56Sopenharmony_ci        b'\x00\xe8\x03\xe8\x03\xc7<M\xb5a\xceX\xa3Y&\x8b{oE\xd7\x9d\x8c\x98\x02\xc0'
23887db96d56Sopenharmony_ci        b'PK\x07\x08xu\xaa\xb2\x14\x00\x00\x00\x00\x02\x00\x00PK\x01\x02\x17\x03'
23897db96d56Sopenharmony_ci        b'\x14\x00\t\x00\x08\x00\xcf}38xu\xaa\xb2\x14\x00\x00\x00\x00\x02\x00\x00'
23907db96d56Sopenharmony_ci        b'\x04\x00\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x00\x00\x00\x00ze'
23917db96d56Sopenharmony_ci        b'roUT\x05\x00\x03\xd6\x8b\x92GUx\x00\x00PK\x05\x06\x00\x00\x00\x00\x01'
23927db96d56Sopenharmony_ci        b'\x00\x01\x00?\x00\x00\x00[\x00\x00\x00\x00\x00' )
23937db96d56Sopenharmony_ci
23947db96d56Sopenharmony_ci    plain = b'zipfile.py encryption test'
23957db96d56Sopenharmony_ci    plain2 = b'\x00'*512
23967db96d56Sopenharmony_ci
23977db96d56Sopenharmony_ci    def setUp(self):
23987db96d56Sopenharmony_ci        with open(TESTFN, "wb") as fp:
23997db96d56Sopenharmony_ci            fp.write(self.data)
24007db96d56Sopenharmony_ci        self.zip = zipfile.ZipFile(TESTFN, "r")
24017db96d56Sopenharmony_ci        with open(TESTFN2, "wb") as fp:
24027db96d56Sopenharmony_ci            fp.write(self.data2)
24037db96d56Sopenharmony_ci        self.zip2 = zipfile.ZipFile(TESTFN2, "r")
24047db96d56Sopenharmony_ci
24057db96d56Sopenharmony_ci    def tearDown(self):
24067db96d56Sopenharmony_ci        self.zip.close()
24077db96d56Sopenharmony_ci        os.unlink(TESTFN)
24087db96d56Sopenharmony_ci        self.zip2.close()
24097db96d56Sopenharmony_ci        os.unlink(TESTFN2)
24107db96d56Sopenharmony_ci
24117db96d56Sopenharmony_ci    def test_no_password(self):
24127db96d56Sopenharmony_ci        # Reading the encrypted file without password
24137db96d56Sopenharmony_ci        # must generate a RunTime exception
24147db96d56Sopenharmony_ci        self.assertRaises(RuntimeError, self.zip.read, "test.txt")
24157db96d56Sopenharmony_ci        self.assertRaises(RuntimeError, self.zip2.read, "zero")
24167db96d56Sopenharmony_ci
24177db96d56Sopenharmony_ci    def test_bad_password(self):
24187db96d56Sopenharmony_ci        self.zip.setpassword(b"perl")
24197db96d56Sopenharmony_ci        self.assertRaises(RuntimeError, self.zip.read, "test.txt")
24207db96d56Sopenharmony_ci        self.zip2.setpassword(b"perl")
24217db96d56Sopenharmony_ci        self.assertRaises(RuntimeError, self.zip2.read, "zero")
24227db96d56Sopenharmony_ci
24237db96d56Sopenharmony_ci    @requires_zlib()
24247db96d56Sopenharmony_ci    def test_good_password(self):
24257db96d56Sopenharmony_ci        self.zip.setpassword(b"python")
24267db96d56Sopenharmony_ci        self.assertEqual(self.zip.read("test.txt"), self.plain)
24277db96d56Sopenharmony_ci        self.zip2.setpassword(b"12345")
24287db96d56Sopenharmony_ci        self.assertEqual(self.zip2.read("zero"), self.plain2)
24297db96d56Sopenharmony_ci
24307db96d56Sopenharmony_ci    def test_unicode_password(self):
24317db96d56Sopenharmony_ci        expected_msg = "pwd: expected bytes, got str"
24327db96d56Sopenharmony_ci
24337db96d56Sopenharmony_ci        with self.assertRaisesRegex(TypeError, expected_msg):
24347db96d56Sopenharmony_ci            self.zip.setpassword("unicode")
24357db96d56Sopenharmony_ci
24367db96d56Sopenharmony_ci        with self.assertRaisesRegex(TypeError, expected_msg):
24377db96d56Sopenharmony_ci            self.zip.read("test.txt", "python")
24387db96d56Sopenharmony_ci
24397db96d56Sopenharmony_ci        with self.assertRaisesRegex(TypeError, expected_msg):
24407db96d56Sopenharmony_ci            self.zip.open("test.txt", pwd="python")
24417db96d56Sopenharmony_ci
24427db96d56Sopenharmony_ci        with self.assertRaisesRegex(TypeError, expected_msg):
24437db96d56Sopenharmony_ci            self.zip.extract("test.txt", pwd="python")
24447db96d56Sopenharmony_ci
24457db96d56Sopenharmony_ci        with self.assertRaisesRegex(TypeError, expected_msg):
24467db96d56Sopenharmony_ci            self.zip.pwd = "python"
24477db96d56Sopenharmony_ci            self.zip.open("test.txt")
24487db96d56Sopenharmony_ci
24497db96d56Sopenharmony_ci    def test_seek_tell(self):
24507db96d56Sopenharmony_ci        self.zip.setpassword(b"python")
24517db96d56Sopenharmony_ci        txt = self.plain
24527db96d56Sopenharmony_ci        test_word = b'encryption'
24537db96d56Sopenharmony_ci        bloc = txt.find(test_word)
24547db96d56Sopenharmony_ci        bloc_len = len(test_word)
24557db96d56Sopenharmony_ci        with self.zip.open("test.txt", "r") as fp:
24567db96d56Sopenharmony_ci            fp.seek(bloc, os.SEEK_SET)
24577db96d56Sopenharmony_ci            self.assertEqual(fp.tell(), bloc)
24587db96d56Sopenharmony_ci            fp.seek(-bloc, os.SEEK_CUR)
24597db96d56Sopenharmony_ci            self.assertEqual(fp.tell(), 0)
24607db96d56Sopenharmony_ci            fp.seek(bloc, os.SEEK_CUR)
24617db96d56Sopenharmony_ci            self.assertEqual(fp.tell(), bloc)
24627db96d56Sopenharmony_ci            self.assertEqual(fp.read(bloc_len), txt[bloc:bloc+bloc_len])
24637db96d56Sopenharmony_ci
24647db96d56Sopenharmony_ci            # Make sure that the second read after seeking back beyond
24657db96d56Sopenharmony_ci            # _readbuffer returns the same content (ie. rewind to the start of
24667db96d56Sopenharmony_ci            # the file to read forward to the required position).
24677db96d56Sopenharmony_ci            old_read_size = fp.MIN_READ_SIZE
24687db96d56Sopenharmony_ci            fp.MIN_READ_SIZE = 1
24697db96d56Sopenharmony_ci            fp._readbuffer = b''
24707db96d56Sopenharmony_ci            fp._offset = 0
24717db96d56Sopenharmony_ci            fp.seek(0, os.SEEK_SET)
24727db96d56Sopenharmony_ci            self.assertEqual(fp.tell(), 0)
24737db96d56Sopenharmony_ci            fp.seek(bloc, os.SEEK_CUR)
24747db96d56Sopenharmony_ci            self.assertEqual(fp.read(bloc_len), txt[bloc:bloc+bloc_len])
24757db96d56Sopenharmony_ci            fp.MIN_READ_SIZE = old_read_size
24767db96d56Sopenharmony_ci
24777db96d56Sopenharmony_ci            fp.seek(0, os.SEEK_END)
24787db96d56Sopenharmony_ci            self.assertEqual(fp.tell(), len(txt))
24797db96d56Sopenharmony_ci            fp.seek(0, os.SEEK_SET)
24807db96d56Sopenharmony_ci            self.assertEqual(fp.tell(), 0)
24817db96d56Sopenharmony_ci
24827db96d56Sopenharmony_ci            # Read the file completely to definitely call any eof integrity
24837db96d56Sopenharmony_ci            # checks (crc) and make sure they still pass.
24847db96d56Sopenharmony_ci            fp.read()
24857db96d56Sopenharmony_ci
24867db96d56Sopenharmony_ci
24877db96d56Sopenharmony_ciclass AbstractTestsWithRandomBinaryFiles:
24887db96d56Sopenharmony_ci    @classmethod
24897db96d56Sopenharmony_ci    def setUpClass(cls):
24907db96d56Sopenharmony_ci        datacount = randint(16, 64)*1024 + randint(1, 1024)
24917db96d56Sopenharmony_ci        cls.data = b''.join(struct.pack('<f', random()*randint(-1000, 1000))
24927db96d56Sopenharmony_ci                            for i in range(datacount))
24937db96d56Sopenharmony_ci
24947db96d56Sopenharmony_ci    def setUp(self):
24957db96d56Sopenharmony_ci        # Make a source file with some lines
24967db96d56Sopenharmony_ci        with open(TESTFN, "wb") as fp:
24977db96d56Sopenharmony_ci            fp.write(self.data)
24987db96d56Sopenharmony_ci
24997db96d56Sopenharmony_ci    def tearDown(self):
25007db96d56Sopenharmony_ci        unlink(TESTFN)
25017db96d56Sopenharmony_ci        unlink(TESTFN2)
25027db96d56Sopenharmony_ci
25037db96d56Sopenharmony_ci    def make_test_archive(self, f, compression):
25047db96d56Sopenharmony_ci        # Create the ZIP archive
25057db96d56Sopenharmony_ci        with zipfile.ZipFile(f, "w", compression) as zipfp:
25067db96d56Sopenharmony_ci            zipfp.write(TESTFN, "another.name")
25077db96d56Sopenharmony_ci            zipfp.write(TESTFN, TESTFN)
25087db96d56Sopenharmony_ci
25097db96d56Sopenharmony_ci    def zip_test(self, f, compression):
25107db96d56Sopenharmony_ci        self.make_test_archive(f, compression)
25117db96d56Sopenharmony_ci
25127db96d56Sopenharmony_ci        # Read the ZIP archive
25137db96d56Sopenharmony_ci        with zipfile.ZipFile(f, "r", compression) as zipfp:
25147db96d56Sopenharmony_ci            testdata = zipfp.read(TESTFN)
25157db96d56Sopenharmony_ci            self.assertEqual(len(testdata), len(self.data))
25167db96d56Sopenharmony_ci            self.assertEqual(testdata, self.data)
25177db96d56Sopenharmony_ci            self.assertEqual(zipfp.read("another.name"), self.data)
25187db96d56Sopenharmony_ci
25197db96d56Sopenharmony_ci    def test_read(self):
25207db96d56Sopenharmony_ci        for f in get_files(self):
25217db96d56Sopenharmony_ci            self.zip_test(f, self.compression)
25227db96d56Sopenharmony_ci
25237db96d56Sopenharmony_ci    def zip_open_test(self, f, compression):
25247db96d56Sopenharmony_ci        self.make_test_archive(f, compression)
25257db96d56Sopenharmony_ci
25267db96d56Sopenharmony_ci        # Read the ZIP archive
25277db96d56Sopenharmony_ci        with zipfile.ZipFile(f, "r", compression) as zipfp:
25287db96d56Sopenharmony_ci            zipdata1 = []
25297db96d56Sopenharmony_ci            with zipfp.open(TESTFN) as zipopen1:
25307db96d56Sopenharmony_ci                while True:
25317db96d56Sopenharmony_ci                    read_data = zipopen1.read(256)
25327db96d56Sopenharmony_ci                    if not read_data:
25337db96d56Sopenharmony_ci                        break
25347db96d56Sopenharmony_ci                    zipdata1.append(read_data)
25357db96d56Sopenharmony_ci
25367db96d56Sopenharmony_ci            zipdata2 = []
25377db96d56Sopenharmony_ci            with zipfp.open("another.name") as zipopen2:
25387db96d56Sopenharmony_ci                while True:
25397db96d56Sopenharmony_ci                    read_data = zipopen2.read(256)
25407db96d56Sopenharmony_ci                    if not read_data:
25417db96d56Sopenharmony_ci                        break
25427db96d56Sopenharmony_ci                    zipdata2.append(read_data)
25437db96d56Sopenharmony_ci
25447db96d56Sopenharmony_ci            testdata1 = b''.join(zipdata1)
25457db96d56Sopenharmony_ci            self.assertEqual(len(testdata1), len(self.data))
25467db96d56Sopenharmony_ci            self.assertEqual(testdata1, self.data)
25477db96d56Sopenharmony_ci
25487db96d56Sopenharmony_ci            testdata2 = b''.join(zipdata2)
25497db96d56Sopenharmony_ci            self.assertEqual(len(testdata2), len(self.data))
25507db96d56Sopenharmony_ci            self.assertEqual(testdata2, self.data)
25517db96d56Sopenharmony_ci
25527db96d56Sopenharmony_ci    def test_open(self):
25537db96d56Sopenharmony_ci        for f in get_files(self):
25547db96d56Sopenharmony_ci            self.zip_open_test(f, self.compression)
25557db96d56Sopenharmony_ci
25567db96d56Sopenharmony_ci    def zip_random_open_test(self, f, compression):
25577db96d56Sopenharmony_ci        self.make_test_archive(f, compression)
25587db96d56Sopenharmony_ci
25597db96d56Sopenharmony_ci        # Read the ZIP archive
25607db96d56Sopenharmony_ci        with zipfile.ZipFile(f, "r", compression) as zipfp:
25617db96d56Sopenharmony_ci            zipdata1 = []
25627db96d56Sopenharmony_ci            with zipfp.open(TESTFN) as zipopen1:
25637db96d56Sopenharmony_ci                while True:
25647db96d56Sopenharmony_ci                    read_data = zipopen1.read(randint(1, 1024))
25657db96d56Sopenharmony_ci                    if not read_data:
25667db96d56Sopenharmony_ci                        break
25677db96d56Sopenharmony_ci                    zipdata1.append(read_data)
25687db96d56Sopenharmony_ci
25697db96d56Sopenharmony_ci            testdata = b''.join(zipdata1)
25707db96d56Sopenharmony_ci            self.assertEqual(len(testdata), len(self.data))
25717db96d56Sopenharmony_ci            self.assertEqual(testdata, self.data)
25727db96d56Sopenharmony_ci
25737db96d56Sopenharmony_ci    def test_random_open(self):
25747db96d56Sopenharmony_ci        for f in get_files(self):
25757db96d56Sopenharmony_ci            self.zip_random_open_test(f, self.compression)
25767db96d56Sopenharmony_ci
25777db96d56Sopenharmony_ci
25787db96d56Sopenharmony_ciclass StoredTestsWithRandomBinaryFiles(AbstractTestsWithRandomBinaryFiles,
25797db96d56Sopenharmony_ci                                       unittest.TestCase):
25807db96d56Sopenharmony_ci    compression = zipfile.ZIP_STORED
25817db96d56Sopenharmony_ci
25827db96d56Sopenharmony_ci@requires_zlib()
25837db96d56Sopenharmony_ciclass DeflateTestsWithRandomBinaryFiles(AbstractTestsWithRandomBinaryFiles,
25847db96d56Sopenharmony_ci                                        unittest.TestCase):
25857db96d56Sopenharmony_ci    compression = zipfile.ZIP_DEFLATED
25867db96d56Sopenharmony_ci
25877db96d56Sopenharmony_ci@requires_bz2()
25887db96d56Sopenharmony_ciclass Bzip2TestsWithRandomBinaryFiles(AbstractTestsWithRandomBinaryFiles,
25897db96d56Sopenharmony_ci                                      unittest.TestCase):
25907db96d56Sopenharmony_ci    compression = zipfile.ZIP_BZIP2
25917db96d56Sopenharmony_ci
25927db96d56Sopenharmony_ci@requires_lzma()
25937db96d56Sopenharmony_ciclass LzmaTestsWithRandomBinaryFiles(AbstractTestsWithRandomBinaryFiles,
25947db96d56Sopenharmony_ci                                     unittest.TestCase):
25957db96d56Sopenharmony_ci    compression = zipfile.ZIP_LZMA
25967db96d56Sopenharmony_ci
25977db96d56Sopenharmony_ci
25987db96d56Sopenharmony_ci# Provide the tell() method but not seek()
25997db96d56Sopenharmony_ciclass Tellable:
26007db96d56Sopenharmony_ci    def __init__(self, fp):
26017db96d56Sopenharmony_ci        self.fp = fp
26027db96d56Sopenharmony_ci        self.offset = 0
26037db96d56Sopenharmony_ci
26047db96d56Sopenharmony_ci    def write(self, data):
26057db96d56Sopenharmony_ci        n = self.fp.write(data)
26067db96d56Sopenharmony_ci        self.offset += n
26077db96d56Sopenharmony_ci        return n
26087db96d56Sopenharmony_ci
26097db96d56Sopenharmony_ci    def tell(self):
26107db96d56Sopenharmony_ci        return self.offset
26117db96d56Sopenharmony_ci
26127db96d56Sopenharmony_ci    def flush(self):
26137db96d56Sopenharmony_ci        self.fp.flush()
26147db96d56Sopenharmony_ci
26157db96d56Sopenharmony_ciclass Unseekable:
26167db96d56Sopenharmony_ci    def __init__(self, fp):
26177db96d56Sopenharmony_ci        self.fp = fp
26187db96d56Sopenharmony_ci
26197db96d56Sopenharmony_ci    def write(self, data):
26207db96d56Sopenharmony_ci        return self.fp.write(data)
26217db96d56Sopenharmony_ci
26227db96d56Sopenharmony_ci    def flush(self):
26237db96d56Sopenharmony_ci        self.fp.flush()
26247db96d56Sopenharmony_ci
26257db96d56Sopenharmony_ciclass UnseekableTests(unittest.TestCase):
26267db96d56Sopenharmony_ci    def test_writestr(self):
26277db96d56Sopenharmony_ci        for wrapper in (lambda f: f), Tellable, Unseekable:
26287db96d56Sopenharmony_ci            with self.subTest(wrapper=wrapper):
26297db96d56Sopenharmony_ci                f = io.BytesIO()
26307db96d56Sopenharmony_ci                f.write(b'abc')
26317db96d56Sopenharmony_ci                bf = io.BufferedWriter(f)
26327db96d56Sopenharmony_ci                with zipfile.ZipFile(wrapper(bf), 'w', zipfile.ZIP_STORED) as zipfp:
26337db96d56Sopenharmony_ci                    zipfp.writestr('ones', b'111')
26347db96d56Sopenharmony_ci                    zipfp.writestr('twos', b'222')
26357db96d56Sopenharmony_ci                self.assertEqual(f.getvalue()[:5], b'abcPK')
26367db96d56Sopenharmony_ci                with zipfile.ZipFile(f, mode='r') as zipf:
26377db96d56Sopenharmony_ci                    with zipf.open('ones') as zopen:
26387db96d56Sopenharmony_ci                        self.assertEqual(zopen.read(), b'111')
26397db96d56Sopenharmony_ci                    with zipf.open('twos') as zopen:
26407db96d56Sopenharmony_ci                        self.assertEqual(zopen.read(), b'222')
26417db96d56Sopenharmony_ci
26427db96d56Sopenharmony_ci    def test_write(self):
26437db96d56Sopenharmony_ci        for wrapper in (lambda f: f), Tellable, Unseekable:
26447db96d56Sopenharmony_ci            with self.subTest(wrapper=wrapper):
26457db96d56Sopenharmony_ci                f = io.BytesIO()
26467db96d56Sopenharmony_ci                f.write(b'abc')
26477db96d56Sopenharmony_ci                bf = io.BufferedWriter(f)
26487db96d56Sopenharmony_ci                with zipfile.ZipFile(wrapper(bf), 'w', zipfile.ZIP_STORED) as zipfp:
26497db96d56Sopenharmony_ci                    self.addCleanup(unlink, TESTFN)
26507db96d56Sopenharmony_ci                    with open(TESTFN, 'wb') as f2:
26517db96d56Sopenharmony_ci                        f2.write(b'111')
26527db96d56Sopenharmony_ci                    zipfp.write(TESTFN, 'ones')
26537db96d56Sopenharmony_ci                    with open(TESTFN, 'wb') as f2:
26547db96d56Sopenharmony_ci                        f2.write(b'222')
26557db96d56Sopenharmony_ci                    zipfp.write(TESTFN, 'twos')
26567db96d56Sopenharmony_ci                self.assertEqual(f.getvalue()[:5], b'abcPK')
26577db96d56Sopenharmony_ci                with zipfile.ZipFile(f, mode='r') as zipf:
26587db96d56Sopenharmony_ci                    with zipf.open('ones') as zopen:
26597db96d56Sopenharmony_ci                        self.assertEqual(zopen.read(), b'111')
26607db96d56Sopenharmony_ci                    with zipf.open('twos') as zopen:
26617db96d56Sopenharmony_ci                        self.assertEqual(zopen.read(), b'222')
26627db96d56Sopenharmony_ci
26637db96d56Sopenharmony_ci    def test_open_write(self):
26647db96d56Sopenharmony_ci        for wrapper in (lambda f: f), Tellable, Unseekable:
26657db96d56Sopenharmony_ci            with self.subTest(wrapper=wrapper):
26667db96d56Sopenharmony_ci                f = io.BytesIO()
26677db96d56Sopenharmony_ci                f.write(b'abc')
26687db96d56Sopenharmony_ci                bf = io.BufferedWriter(f)
26697db96d56Sopenharmony_ci                with zipfile.ZipFile(wrapper(bf), 'w', zipfile.ZIP_STORED) as zipf:
26707db96d56Sopenharmony_ci                    with zipf.open('ones', 'w') as zopen:
26717db96d56Sopenharmony_ci                        zopen.write(b'111')
26727db96d56Sopenharmony_ci                    with zipf.open('twos', 'w') as zopen:
26737db96d56Sopenharmony_ci                        zopen.write(b'222')
26747db96d56Sopenharmony_ci                self.assertEqual(f.getvalue()[:5], b'abcPK')
26757db96d56Sopenharmony_ci                with zipfile.ZipFile(f) as zipf:
26767db96d56Sopenharmony_ci                    self.assertEqual(zipf.read('ones'), b'111')
26777db96d56Sopenharmony_ci                    self.assertEqual(zipf.read('twos'), b'222')
26787db96d56Sopenharmony_ci
26797db96d56Sopenharmony_ci
26807db96d56Sopenharmony_ci@requires_zlib()
26817db96d56Sopenharmony_ciclass TestsWithMultipleOpens(unittest.TestCase):
26827db96d56Sopenharmony_ci    @classmethod
26837db96d56Sopenharmony_ci    def setUpClass(cls):
26847db96d56Sopenharmony_ci        cls.data1 = b'111' + randbytes(10000)
26857db96d56Sopenharmony_ci        cls.data2 = b'222' + randbytes(10000)
26867db96d56Sopenharmony_ci
26877db96d56Sopenharmony_ci    def make_test_archive(self, f):
26887db96d56Sopenharmony_ci        # Create the ZIP archive
26897db96d56Sopenharmony_ci        with zipfile.ZipFile(f, "w", zipfile.ZIP_DEFLATED) as zipfp:
26907db96d56Sopenharmony_ci            zipfp.writestr('ones', self.data1)
26917db96d56Sopenharmony_ci            zipfp.writestr('twos', self.data2)
26927db96d56Sopenharmony_ci
26937db96d56Sopenharmony_ci    def test_same_file(self):
26947db96d56Sopenharmony_ci        # Verify that (when the ZipFile is in control of creating file objects)
26957db96d56Sopenharmony_ci        # multiple open() calls can be made without interfering with each other.
26967db96d56Sopenharmony_ci        for f in get_files(self):
26977db96d56Sopenharmony_ci            self.make_test_archive(f)
26987db96d56Sopenharmony_ci            with zipfile.ZipFile(f, mode="r") as zipf:
26997db96d56Sopenharmony_ci                with zipf.open('ones') as zopen1, zipf.open('ones') as zopen2:
27007db96d56Sopenharmony_ci                    data1 = zopen1.read(500)
27017db96d56Sopenharmony_ci                    data2 = zopen2.read(500)
27027db96d56Sopenharmony_ci                    data1 += zopen1.read()
27037db96d56Sopenharmony_ci                    data2 += zopen2.read()
27047db96d56Sopenharmony_ci                self.assertEqual(data1, data2)
27057db96d56Sopenharmony_ci                self.assertEqual(data1, self.data1)
27067db96d56Sopenharmony_ci
27077db96d56Sopenharmony_ci    def test_different_file(self):
27087db96d56Sopenharmony_ci        # Verify that (when the ZipFile is in control of creating file objects)
27097db96d56Sopenharmony_ci        # multiple open() calls can be made without interfering with each other.
27107db96d56Sopenharmony_ci        for f in get_files(self):
27117db96d56Sopenharmony_ci            self.make_test_archive(f)
27127db96d56Sopenharmony_ci            with zipfile.ZipFile(f, mode="r") as zipf:
27137db96d56Sopenharmony_ci                with zipf.open('ones') as zopen1, zipf.open('twos') as zopen2:
27147db96d56Sopenharmony_ci                    data1 = zopen1.read(500)
27157db96d56Sopenharmony_ci                    data2 = zopen2.read(500)
27167db96d56Sopenharmony_ci                    data1 += zopen1.read()
27177db96d56Sopenharmony_ci                    data2 += zopen2.read()
27187db96d56Sopenharmony_ci                self.assertEqual(data1, self.data1)
27197db96d56Sopenharmony_ci                self.assertEqual(data2, self.data2)
27207db96d56Sopenharmony_ci
27217db96d56Sopenharmony_ci    def test_interleaved(self):
27227db96d56Sopenharmony_ci        # Verify that (when the ZipFile is in control of creating file objects)
27237db96d56Sopenharmony_ci        # multiple open() calls can be made without interfering with each other.
27247db96d56Sopenharmony_ci        for f in get_files(self):
27257db96d56Sopenharmony_ci            self.make_test_archive(f)
27267db96d56Sopenharmony_ci            with zipfile.ZipFile(f, mode="r") as zipf:
27277db96d56Sopenharmony_ci                with zipf.open('ones') as zopen1:
27287db96d56Sopenharmony_ci                    data1 = zopen1.read(500)
27297db96d56Sopenharmony_ci                    with zipf.open('twos') as zopen2:
27307db96d56Sopenharmony_ci                        data2 = zopen2.read(500)
27317db96d56Sopenharmony_ci                        data1 += zopen1.read()
27327db96d56Sopenharmony_ci                        data2 += zopen2.read()
27337db96d56Sopenharmony_ci                self.assertEqual(data1, self.data1)
27347db96d56Sopenharmony_ci                self.assertEqual(data2, self.data2)
27357db96d56Sopenharmony_ci
27367db96d56Sopenharmony_ci    def test_read_after_close(self):
27377db96d56Sopenharmony_ci        for f in get_files(self):
27387db96d56Sopenharmony_ci            self.make_test_archive(f)
27397db96d56Sopenharmony_ci            with contextlib.ExitStack() as stack:
27407db96d56Sopenharmony_ci                with zipfile.ZipFile(f, 'r') as zipf:
27417db96d56Sopenharmony_ci                    zopen1 = stack.enter_context(zipf.open('ones'))
27427db96d56Sopenharmony_ci                    zopen2 = stack.enter_context(zipf.open('twos'))
27437db96d56Sopenharmony_ci                data1 = zopen1.read(500)
27447db96d56Sopenharmony_ci                data2 = zopen2.read(500)
27457db96d56Sopenharmony_ci                data1 += zopen1.read()
27467db96d56Sopenharmony_ci                data2 += zopen2.read()
27477db96d56Sopenharmony_ci            self.assertEqual(data1, self.data1)
27487db96d56Sopenharmony_ci            self.assertEqual(data2, self.data2)
27497db96d56Sopenharmony_ci
27507db96d56Sopenharmony_ci    def test_read_after_write(self):
27517db96d56Sopenharmony_ci        for f in get_files(self):
27527db96d56Sopenharmony_ci            with zipfile.ZipFile(f, 'w', zipfile.ZIP_DEFLATED) as zipf:
27537db96d56Sopenharmony_ci                zipf.writestr('ones', self.data1)
27547db96d56Sopenharmony_ci                zipf.writestr('twos', self.data2)
27557db96d56Sopenharmony_ci                with zipf.open('ones') as zopen1:
27567db96d56Sopenharmony_ci                    data1 = zopen1.read(500)
27577db96d56Sopenharmony_ci            self.assertEqual(data1, self.data1[:500])
27587db96d56Sopenharmony_ci            with zipfile.ZipFile(f, 'r') as zipf:
27597db96d56Sopenharmony_ci                data1 = zipf.read('ones')
27607db96d56Sopenharmony_ci                data2 = zipf.read('twos')
27617db96d56Sopenharmony_ci            self.assertEqual(data1, self.data1)
27627db96d56Sopenharmony_ci            self.assertEqual(data2, self.data2)
27637db96d56Sopenharmony_ci
27647db96d56Sopenharmony_ci    def test_write_after_read(self):
27657db96d56Sopenharmony_ci        for f in get_files(self):
27667db96d56Sopenharmony_ci            with zipfile.ZipFile(f, "w", zipfile.ZIP_DEFLATED) as zipf:
27677db96d56Sopenharmony_ci                zipf.writestr('ones', self.data1)
27687db96d56Sopenharmony_ci                with zipf.open('ones') as zopen1:
27697db96d56Sopenharmony_ci                    zopen1.read(500)
27707db96d56Sopenharmony_ci                    zipf.writestr('twos', self.data2)
27717db96d56Sopenharmony_ci            with zipfile.ZipFile(f, 'r') as zipf:
27727db96d56Sopenharmony_ci                data1 = zipf.read('ones')
27737db96d56Sopenharmony_ci                data2 = zipf.read('twos')
27747db96d56Sopenharmony_ci            self.assertEqual(data1, self.data1)
27757db96d56Sopenharmony_ci            self.assertEqual(data2, self.data2)
27767db96d56Sopenharmony_ci
27777db96d56Sopenharmony_ci    def test_many_opens(self):
27787db96d56Sopenharmony_ci        # Verify that read() and open() promptly close the file descriptor,
27797db96d56Sopenharmony_ci        # and don't rely on the garbage collector to free resources.
27807db96d56Sopenharmony_ci        startcount = fd_count()
27817db96d56Sopenharmony_ci        self.make_test_archive(TESTFN2)
27827db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, mode="r") as zipf:
27837db96d56Sopenharmony_ci            for x in range(100):
27847db96d56Sopenharmony_ci                zipf.read('ones')
27857db96d56Sopenharmony_ci                with zipf.open('ones') as zopen1:
27867db96d56Sopenharmony_ci                    pass
27877db96d56Sopenharmony_ci        self.assertEqual(startcount, fd_count())
27887db96d56Sopenharmony_ci
27897db96d56Sopenharmony_ci    def test_write_while_reading(self):
27907db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, 'w', zipfile.ZIP_DEFLATED) as zipf:
27917db96d56Sopenharmony_ci            zipf.writestr('ones', self.data1)
27927db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2, 'a', zipfile.ZIP_DEFLATED) as zipf:
27937db96d56Sopenharmony_ci            with zipf.open('ones', 'r') as r1:
27947db96d56Sopenharmony_ci                data1 = r1.read(500)
27957db96d56Sopenharmony_ci                with zipf.open('twos', 'w') as w1:
27967db96d56Sopenharmony_ci                    w1.write(self.data2)
27977db96d56Sopenharmony_ci                data1 += r1.read()
27987db96d56Sopenharmony_ci        self.assertEqual(data1, self.data1)
27997db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN2) as zipf:
28007db96d56Sopenharmony_ci            self.assertEqual(zipf.read('twos'), self.data2)
28017db96d56Sopenharmony_ci
28027db96d56Sopenharmony_ci    def tearDown(self):
28037db96d56Sopenharmony_ci        unlink(TESTFN2)
28047db96d56Sopenharmony_ci
28057db96d56Sopenharmony_ci
28067db96d56Sopenharmony_ciclass TestWithDirectory(unittest.TestCase):
28077db96d56Sopenharmony_ci    def setUp(self):
28087db96d56Sopenharmony_ci        os.mkdir(TESTFN2)
28097db96d56Sopenharmony_ci
28107db96d56Sopenharmony_ci    def test_extract_dir(self):
28117db96d56Sopenharmony_ci        with zipfile.ZipFile(findfile("zipdir.zip")) as zipf:
28127db96d56Sopenharmony_ci            zipf.extractall(TESTFN2)
28137db96d56Sopenharmony_ci        self.assertTrue(os.path.isdir(os.path.join(TESTFN2, "a")))
28147db96d56Sopenharmony_ci        self.assertTrue(os.path.isdir(os.path.join(TESTFN2, "a", "b")))
28157db96d56Sopenharmony_ci        self.assertTrue(os.path.exists(os.path.join(TESTFN2, "a", "b", "c")))
28167db96d56Sopenharmony_ci
28177db96d56Sopenharmony_ci    def test_bug_6050(self):
28187db96d56Sopenharmony_ci        # Extraction should succeed if directories already exist
28197db96d56Sopenharmony_ci        os.mkdir(os.path.join(TESTFN2, "a"))
28207db96d56Sopenharmony_ci        self.test_extract_dir()
28217db96d56Sopenharmony_ci
28227db96d56Sopenharmony_ci    def test_write_dir(self):
28237db96d56Sopenharmony_ci        dirpath = os.path.join(TESTFN2, "x")
28247db96d56Sopenharmony_ci        os.mkdir(dirpath)
28257db96d56Sopenharmony_ci        mode = os.stat(dirpath).st_mode & 0xFFFF
28267db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, "w") as zipf:
28277db96d56Sopenharmony_ci            zipf.write(dirpath)
28287db96d56Sopenharmony_ci            zinfo = zipf.filelist[0]
28297db96d56Sopenharmony_ci            self.assertTrue(zinfo.filename.endswith("/x/"))
28307db96d56Sopenharmony_ci            self.assertEqual(zinfo.external_attr, (mode << 16) | 0x10)
28317db96d56Sopenharmony_ci            zipf.write(dirpath, "y")
28327db96d56Sopenharmony_ci            zinfo = zipf.filelist[1]
28337db96d56Sopenharmony_ci            self.assertTrue(zinfo.filename, "y/")
28347db96d56Sopenharmony_ci            self.assertEqual(zinfo.external_attr, (mode << 16) | 0x10)
28357db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, "r") as zipf:
28367db96d56Sopenharmony_ci            zinfo = zipf.filelist[0]
28377db96d56Sopenharmony_ci            self.assertTrue(zinfo.filename.endswith("/x/"))
28387db96d56Sopenharmony_ci            self.assertEqual(zinfo.external_attr, (mode << 16) | 0x10)
28397db96d56Sopenharmony_ci            zinfo = zipf.filelist[1]
28407db96d56Sopenharmony_ci            self.assertTrue(zinfo.filename, "y/")
28417db96d56Sopenharmony_ci            self.assertEqual(zinfo.external_attr, (mode << 16) | 0x10)
28427db96d56Sopenharmony_ci            target = os.path.join(TESTFN2, "target")
28437db96d56Sopenharmony_ci            os.mkdir(target)
28447db96d56Sopenharmony_ci            zipf.extractall(target)
28457db96d56Sopenharmony_ci            self.assertTrue(os.path.isdir(os.path.join(target, "y")))
28467db96d56Sopenharmony_ci            self.assertEqual(len(os.listdir(target)), 2)
28477db96d56Sopenharmony_ci
28487db96d56Sopenharmony_ci    def test_writestr_dir(self):
28497db96d56Sopenharmony_ci        os.mkdir(os.path.join(TESTFN2, "x"))
28507db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, "w") as zipf:
28517db96d56Sopenharmony_ci            zipf.writestr("x/", b'')
28527db96d56Sopenharmony_ci            zinfo = zipf.filelist[0]
28537db96d56Sopenharmony_ci            self.assertEqual(zinfo.filename, "x/")
28547db96d56Sopenharmony_ci            self.assertEqual(zinfo.external_attr, (0o40775 << 16) | 0x10)
28557db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, "r") as zipf:
28567db96d56Sopenharmony_ci            zinfo = zipf.filelist[0]
28577db96d56Sopenharmony_ci            self.assertTrue(zinfo.filename.endswith("x/"))
28587db96d56Sopenharmony_ci            self.assertEqual(zinfo.external_attr, (0o40775 << 16) | 0x10)
28597db96d56Sopenharmony_ci            target = os.path.join(TESTFN2, "target")
28607db96d56Sopenharmony_ci            os.mkdir(target)
28617db96d56Sopenharmony_ci            zipf.extractall(target)
28627db96d56Sopenharmony_ci            self.assertTrue(os.path.isdir(os.path.join(target, "x")))
28637db96d56Sopenharmony_ci            self.assertEqual(os.listdir(target), ["x"])
28647db96d56Sopenharmony_ci
28657db96d56Sopenharmony_ci    def test_mkdir(self):
28667db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, "w") as zf:
28677db96d56Sopenharmony_ci            zf.mkdir("directory")
28687db96d56Sopenharmony_ci            zinfo = zf.filelist[0]
28697db96d56Sopenharmony_ci            self.assertEqual(zinfo.filename, "directory/")
28707db96d56Sopenharmony_ci            self.assertEqual(zinfo.external_attr, (0o40777 << 16) | 0x10)
28717db96d56Sopenharmony_ci
28727db96d56Sopenharmony_ci            zf.mkdir("directory2/")
28737db96d56Sopenharmony_ci            zinfo = zf.filelist[1]
28747db96d56Sopenharmony_ci            self.assertEqual(zinfo.filename, "directory2/")
28757db96d56Sopenharmony_ci            self.assertEqual(zinfo.external_attr, (0o40777 << 16) | 0x10)
28767db96d56Sopenharmony_ci
28777db96d56Sopenharmony_ci            zf.mkdir("directory3", mode=0o777)
28787db96d56Sopenharmony_ci            zinfo = zf.filelist[2]
28797db96d56Sopenharmony_ci            self.assertEqual(zinfo.filename, "directory3/")
28807db96d56Sopenharmony_ci            self.assertEqual(zinfo.external_attr, (0o40777 << 16) | 0x10)
28817db96d56Sopenharmony_ci
28827db96d56Sopenharmony_ci            old_zinfo = zipfile.ZipInfo("directory4/")
28837db96d56Sopenharmony_ci            old_zinfo.external_attr = (0o40777 << 16) | 0x10
28847db96d56Sopenharmony_ci            old_zinfo.CRC = 0
28857db96d56Sopenharmony_ci            old_zinfo.file_size = 0
28867db96d56Sopenharmony_ci            old_zinfo.compress_size = 0
28877db96d56Sopenharmony_ci            zf.mkdir(old_zinfo)
28887db96d56Sopenharmony_ci            new_zinfo = zf.filelist[3]
28897db96d56Sopenharmony_ci            self.assertEqual(old_zinfo.filename, "directory4/")
28907db96d56Sopenharmony_ci            self.assertEqual(old_zinfo.external_attr, new_zinfo.external_attr)
28917db96d56Sopenharmony_ci
28927db96d56Sopenharmony_ci            target = os.path.join(TESTFN2, "target")
28937db96d56Sopenharmony_ci            os.mkdir(target)
28947db96d56Sopenharmony_ci            zf.extractall(target)
28957db96d56Sopenharmony_ci            self.assertEqual(set(os.listdir(target)), {"directory", "directory2", "directory3", "directory4"})
28967db96d56Sopenharmony_ci
28977db96d56Sopenharmony_ci    def test_create_directory_with_write(self):
28987db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, "w") as zf:
28997db96d56Sopenharmony_ci            zf.writestr(zipfile.ZipInfo('directory/'), '')
29007db96d56Sopenharmony_ci
29017db96d56Sopenharmony_ci            zinfo = zf.filelist[0]
29027db96d56Sopenharmony_ci            self.assertEqual(zinfo.filename, "directory/")
29037db96d56Sopenharmony_ci
29047db96d56Sopenharmony_ci            directory = os.path.join(TESTFN2, "directory2")
29057db96d56Sopenharmony_ci            os.mkdir(directory)
29067db96d56Sopenharmony_ci            mode = os.stat(directory).st_mode
29077db96d56Sopenharmony_ci            zf.write(directory, arcname="directory2/")
29087db96d56Sopenharmony_ci            zinfo = zf.filelist[1]
29097db96d56Sopenharmony_ci            self.assertEqual(zinfo.filename, "directory2/")
29107db96d56Sopenharmony_ci            self.assertEqual(zinfo.external_attr, (mode << 16) | 0x10)
29117db96d56Sopenharmony_ci
29127db96d56Sopenharmony_ci            target = os.path.join(TESTFN2, "target")
29137db96d56Sopenharmony_ci            os.mkdir(target)
29147db96d56Sopenharmony_ci            zf.extractall(target)
29157db96d56Sopenharmony_ci
29167db96d56Sopenharmony_ci            self.assertEqual(set(os.listdir(target)), {"directory", "directory2"})
29177db96d56Sopenharmony_ci
29187db96d56Sopenharmony_ci    def tearDown(self):
29197db96d56Sopenharmony_ci        rmtree(TESTFN2)
29207db96d56Sopenharmony_ci        if os.path.exists(TESTFN):
29217db96d56Sopenharmony_ci            unlink(TESTFN)
29227db96d56Sopenharmony_ci
29237db96d56Sopenharmony_ci
29247db96d56Sopenharmony_ciclass ZipInfoTests(unittest.TestCase):
29257db96d56Sopenharmony_ci    def test_from_file(self):
29267db96d56Sopenharmony_ci        zi = zipfile.ZipInfo.from_file(__file__)
29277db96d56Sopenharmony_ci        self.assertEqual(posixpath.basename(zi.filename), 'test_zipfile.py')
29287db96d56Sopenharmony_ci        self.assertFalse(zi.is_dir())
29297db96d56Sopenharmony_ci        self.assertEqual(zi.file_size, os.path.getsize(__file__))
29307db96d56Sopenharmony_ci
29317db96d56Sopenharmony_ci    def test_from_file_pathlike(self):
29327db96d56Sopenharmony_ci        zi = zipfile.ZipInfo.from_file(pathlib.Path(__file__))
29337db96d56Sopenharmony_ci        self.assertEqual(posixpath.basename(zi.filename), 'test_zipfile.py')
29347db96d56Sopenharmony_ci        self.assertFalse(zi.is_dir())
29357db96d56Sopenharmony_ci        self.assertEqual(zi.file_size, os.path.getsize(__file__))
29367db96d56Sopenharmony_ci
29377db96d56Sopenharmony_ci    def test_from_file_bytes(self):
29387db96d56Sopenharmony_ci        zi = zipfile.ZipInfo.from_file(os.fsencode(__file__), 'test')
29397db96d56Sopenharmony_ci        self.assertEqual(posixpath.basename(zi.filename), 'test')
29407db96d56Sopenharmony_ci        self.assertFalse(zi.is_dir())
29417db96d56Sopenharmony_ci        self.assertEqual(zi.file_size, os.path.getsize(__file__))
29427db96d56Sopenharmony_ci
29437db96d56Sopenharmony_ci    def test_from_file_fileno(self):
29447db96d56Sopenharmony_ci        with open(__file__, 'rb') as f:
29457db96d56Sopenharmony_ci            zi = zipfile.ZipInfo.from_file(f.fileno(), 'test')
29467db96d56Sopenharmony_ci            self.assertEqual(posixpath.basename(zi.filename), 'test')
29477db96d56Sopenharmony_ci            self.assertFalse(zi.is_dir())
29487db96d56Sopenharmony_ci            self.assertEqual(zi.file_size, os.path.getsize(__file__))
29497db96d56Sopenharmony_ci
29507db96d56Sopenharmony_ci    def test_from_dir(self):
29517db96d56Sopenharmony_ci        dirpath = os.path.dirname(os.path.abspath(__file__))
29527db96d56Sopenharmony_ci        zi = zipfile.ZipInfo.from_file(dirpath, 'stdlib_tests')
29537db96d56Sopenharmony_ci        self.assertEqual(zi.filename, 'stdlib_tests/')
29547db96d56Sopenharmony_ci        self.assertTrue(zi.is_dir())
29557db96d56Sopenharmony_ci        self.assertEqual(zi.compress_type, zipfile.ZIP_STORED)
29567db96d56Sopenharmony_ci        self.assertEqual(zi.file_size, 0)
29577db96d56Sopenharmony_ci
29587db96d56Sopenharmony_ci
29597db96d56Sopenharmony_ciclass CommandLineTest(unittest.TestCase):
29607db96d56Sopenharmony_ci
29617db96d56Sopenharmony_ci    def zipfilecmd(self, *args, **kwargs):
29627db96d56Sopenharmony_ci        rc, out, err = script_helper.assert_python_ok('-m', 'zipfile', *args,
29637db96d56Sopenharmony_ci                                                      **kwargs)
29647db96d56Sopenharmony_ci        return out.replace(os.linesep.encode(), b'\n')
29657db96d56Sopenharmony_ci
29667db96d56Sopenharmony_ci    def zipfilecmd_failure(self, *args):
29677db96d56Sopenharmony_ci        return script_helper.assert_python_failure('-m', 'zipfile', *args)
29687db96d56Sopenharmony_ci
29697db96d56Sopenharmony_ci    def test_bad_use(self):
29707db96d56Sopenharmony_ci        rc, out, err = self.zipfilecmd_failure()
29717db96d56Sopenharmony_ci        self.assertEqual(out, b'')
29727db96d56Sopenharmony_ci        self.assertIn(b'usage', err.lower())
29737db96d56Sopenharmony_ci        self.assertIn(b'error', err.lower())
29747db96d56Sopenharmony_ci        self.assertIn(b'required', err.lower())
29757db96d56Sopenharmony_ci        rc, out, err = self.zipfilecmd_failure('-l', '')
29767db96d56Sopenharmony_ci        self.assertEqual(out, b'')
29777db96d56Sopenharmony_ci        self.assertNotEqual(err.strip(), b'')
29787db96d56Sopenharmony_ci
29797db96d56Sopenharmony_ci    def test_test_command(self):
29807db96d56Sopenharmony_ci        zip_name = findfile('zipdir.zip')
29817db96d56Sopenharmony_ci        for opt in '-t', '--test':
29827db96d56Sopenharmony_ci            out = self.zipfilecmd(opt, zip_name)
29837db96d56Sopenharmony_ci            self.assertEqual(out.rstrip(), b'Done testing')
29847db96d56Sopenharmony_ci        zip_name = findfile('testtar.tar')
29857db96d56Sopenharmony_ci        rc, out, err = self.zipfilecmd_failure('-t', zip_name)
29867db96d56Sopenharmony_ci        self.assertEqual(out, b'')
29877db96d56Sopenharmony_ci
29887db96d56Sopenharmony_ci    def test_list_command(self):
29897db96d56Sopenharmony_ci        zip_name = findfile('zipdir.zip')
29907db96d56Sopenharmony_ci        t = io.StringIO()
29917db96d56Sopenharmony_ci        with zipfile.ZipFile(zip_name, 'r') as tf:
29927db96d56Sopenharmony_ci            tf.printdir(t)
29937db96d56Sopenharmony_ci        expected = t.getvalue().encode('ascii', 'backslashreplace')
29947db96d56Sopenharmony_ci        for opt in '-l', '--list':
29957db96d56Sopenharmony_ci            out = self.zipfilecmd(opt, zip_name,
29967db96d56Sopenharmony_ci                                  PYTHONIOENCODING='ascii:backslashreplace')
29977db96d56Sopenharmony_ci            self.assertEqual(out, expected)
29987db96d56Sopenharmony_ci
29997db96d56Sopenharmony_ci    @requires_zlib()
30007db96d56Sopenharmony_ci    def test_create_command(self):
30017db96d56Sopenharmony_ci        self.addCleanup(unlink, TESTFN)
30027db96d56Sopenharmony_ci        with open(TESTFN, 'w', encoding='utf-8') as f:
30037db96d56Sopenharmony_ci            f.write('test 1')
30047db96d56Sopenharmony_ci        os.mkdir(TESTFNDIR)
30057db96d56Sopenharmony_ci        self.addCleanup(rmtree, TESTFNDIR)
30067db96d56Sopenharmony_ci        with open(os.path.join(TESTFNDIR, 'file.txt'), 'w', encoding='utf-8') as f:
30077db96d56Sopenharmony_ci            f.write('test 2')
30087db96d56Sopenharmony_ci        files = [TESTFN, TESTFNDIR]
30097db96d56Sopenharmony_ci        namelist = [TESTFN, TESTFNDIR + '/', TESTFNDIR + '/file.txt']
30107db96d56Sopenharmony_ci        for opt in '-c', '--create':
30117db96d56Sopenharmony_ci            try:
30127db96d56Sopenharmony_ci                out = self.zipfilecmd(opt, TESTFN2, *files)
30137db96d56Sopenharmony_ci                self.assertEqual(out, b'')
30147db96d56Sopenharmony_ci                with zipfile.ZipFile(TESTFN2) as zf:
30157db96d56Sopenharmony_ci                    self.assertEqual(zf.namelist(), namelist)
30167db96d56Sopenharmony_ci                    self.assertEqual(zf.read(namelist[0]), b'test 1')
30177db96d56Sopenharmony_ci                    self.assertEqual(zf.read(namelist[2]), b'test 2')
30187db96d56Sopenharmony_ci            finally:
30197db96d56Sopenharmony_ci                unlink(TESTFN2)
30207db96d56Sopenharmony_ci
30217db96d56Sopenharmony_ci    def test_extract_command(self):
30227db96d56Sopenharmony_ci        zip_name = findfile('zipdir.zip')
30237db96d56Sopenharmony_ci        for opt in '-e', '--extract':
30247db96d56Sopenharmony_ci            with temp_dir() as extdir:
30257db96d56Sopenharmony_ci                out = self.zipfilecmd(opt, zip_name, extdir)
30267db96d56Sopenharmony_ci                self.assertEqual(out, b'')
30277db96d56Sopenharmony_ci                with zipfile.ZipFile(zip_name) as zf:
30287db96d56Sopenharmony_ci                    for zi in zf.infolist():
30297db96d56Sopenharmony_ci                        path = os.path.join(extdir,
30307db96d56Sopenharmony_ci                                    zi.filename.replace('/', os.sep))
30317db96d56Sopenharmony_ci                        if zi.is_dir():
30327db96d56Sopenharmony_ci                            self.assertTrue(os.path.isdir(path))
30337db96d56Sopenharmony_ci                        else:
30347db96d56Sopenharmony_ci                            self.assertTrue(os.path.isfile(path))
30357db96d56Sopenharmony_ci                            with open(path, 'rb') as f:
30367db96d56Sopenharmony_ci                                self.assertEqual(f.read(), zf.read(zi))
30377db96d56Sopenharmony_ci
30387db96d56Sopenharmony_ci
30397db96d56Sopenharmony_ciclass TestExecutablePrependedZip(unittest.TestCase):
30407db96d56Sopenharmony_ci    """Test our ability to open zip files with an executable prepended."""
30417db96d56Sopenharmony_ci
30427db96d56Sopenharmony_ci    def setUp(self):
30437db96d56Sopenharmony_ci        self.exe_zip = findfile('exe_with_zip', subdir='ziptestdata')
30447db96d56Sopenharmony_ci        self.exe_zip64 = findfile('exe_with_z64', subdir='ziptestdata')
30457db96d56Sopenharmony_ci
30467db96d56Sopenharmony_ci    def _test_zip_works(self, name):
30477db96d56Sopenharmony_ci        # bpo28494 sanity check: ensure is_zipfile works on these.
30487db96d56Sopenharmony_ci        self.assertTrue(zipfile.is_zipfile(name),
30497db96d56Sopenharmony_ci                        f'is_zipfile failed on {name}')
30507db96d56Sopenharmony_ci        # Ensure we can operate on these via ZipFile.
30517db96d56Sopenharmony_ci        with zipfile.ZipFile(name) as zipfp:
30527db96d56Sopenharmony_ci            for n in zipfp.namelist():
30537db96d56Sopenharmony_ci                data = zipfp.read(n)
30547db96d56Sopenharmony_ci                self.assertIn(b'FAVORITE_NUMBER', data)
30557db96d56Sopenharmony_ci
30567db96d56Sopenharmony_ci    def test_read_zip_with_exe_prepended(self):
30577db96d56Sopenharmony_ci        self._test_zip_works(self.exe_zip)
30587db96d56Sopenharmony_ci
30597db96d56Sopenharmony_ci    def test_read_zip64_with_exe_prepended(self):
30607db96d56Sopenharmony_ci        self._test_zip_works(self.exe_zip64)
30617db96d56Sopenharmony_ci
30627db96d56Sopenharmony_ci    @unittest.skipUnless(sys.executable, 'sys.executable required.')
30637db96d56Sopenharmony_ci    @unittest.skipUnless(os.access('/bin/bash', os.X_OK),
30647db96d56Sopenharmony_ci                         'Test relies on #!/bin/bash working.')
30657db96d56Sopenharmony_ci    @requires_subprocess()
30667db96d56Sopenharmony_ci    def test_execute_zip2(self):
30677db96d56Sopenharmony_ci        output = subprocess.check_output([self.exe_zip, sys.executable])
30687db96d56Sopenharmony_ci        self.assertIn(b'number in executable: 5', output)
30697db96d56Sopenharmony_ci
30707db96d56Sopenharmony_ci    @unittest.skipUnless(sys.executable, 'sys.executable required.')
30717db96d56Sopenharmony_ci    @unittest.skipUnless(os.access('/bin/bash', os.X_OK),
30727db96d56Sopenharmony_ci                         'Test relies on #!/bin/bash working.')
30737db96d56Sopenharmony_ci    @requires_subprocess()
30747db96d56Sopenharmony_ci    def test_execute_zip64(self):
30757db96d56Sopenharmony_ci        output = subprocess.check_output([self.exe_zip64, sys.executable])
30767db96d56Sopenharmony_ci        self.assertIn(b'number in executable: 5', output)
30777db96d56Sopenharmony_ci
30787db96d56Sopenharmony_ci
30797db96d56Sopenharmony_ci# Poor man's technique to consume a (smallish) iterable.
30807db96d56Sopenharmony_ciconsume = tuple
30817db96d56Sopenharmony_ci
30827db96d56Sopenharmony_ci
30837db96d56Sopenharmony_ci# from jaraco.itertools 5.0
30847db96d56Sopenharmony_ciclass jaraco:
30857db96d56Sopenharmony_ci    class itertools:
30867db96d56Sopenharmony_ci        class Counter:
30877db96d56Sopenharmony_ci            def __init__(self, i):
30887db96d56Sopenharmony_ci                self.count = 0
30897db96d56Sopenharmony_ci                self._orig_iter = iter(i)
30907db96d56Sopenharmony_ci
30917db96d56Sopenharmony_ci            def __iter__(self):
30927db96d56Sopenharmony_ci                return self
30937db96d56Sopenharmony_ci
30947db96d56Sopenharmony_ci            def __next__(self):
30957db96d56Sopenharmony_ci                result = next(self._orig_iter)
30967db96d56Sopenharmony_ci                self.count += 1
30977db96d56Sopenharmony_ci                return result
30987db96d56Sopenharmony_ci
30997db96d56Sopenharmony_ci
31007db96d56Sopenharmony_cidef add_dirs(zf):
31017db96d56Sopenharmony_ci    """
31027db96d56Sopenharmony_ci    Given a writable zip file zf, inject directory entries for
31037db96d56Sopenharmony_ci    any directories implied by the presence of children.
31047db96d56Sopenharmony_ci    """
31057db96d56Sopenharmony_ci    for name in zipfile.CompleteDirs._implied_dirs(zf.namelist()):
31067db96d56Sopenharmony_ci        zf.writestr(name, b"")
31077db96d56Sopenharmony_ci    return zf
31087db96d56Sopenharmony_ci
31097db96d56Sopenharmony_ci
31107db96d56Sopenharmony_cidef build_alpharep_fixture():
31117db96d56Sopenharmony_ci    """
31127db96d56Sopenharmony_ci    Create a zip file with this structure:
31137db96d56Sopenharmony_ci
31147db96d56Sopenharmony_ci    .
31157db96d56Sopenharmony_ci    ├── a.txt
31167db96d56Sopenharmony_ci    ├── b
31177db96d56Sopenharmony_ci    │   ├── c.txt
31187db96d56Sopenharmony_ci    │   ├── d
31197db96d56Sopenharmony_ci    │   │   └── e.txt
31207db96d56Sopenharmony_ci    │   └── f.txt
31217db96d56Sopenharmony_ci    └── g
31227db96d56Sopenharmony_ci        └── h
31237db96d56Sopenharmony_ci            └── i.txt
31247db96d56Sopenharmony_ci
31257db96d56Sopenharmony_ci    This fixture has the following key characteristics:
31267db96d56Sopenharmony_ci
31277db96d56Sopenharmony_ci    - a file at the root (a)
31287db96d56Sopenharmony_ci    - a file two levels deep (b/d/e)
31297db96d56Sopenharmony_ci    - multiple files in a directory (b/c, b/f)
31307db96d56Sopenharmony_ci    - a directory containing only a directory (g/h)
31317db96d56Sopenharmony_ci
31327db96d56Sopenharmony_ci    "alpha" because it uses alphabet
31337db96d56Sopenharmony_ci    "rep" because it's a representative example
31347db96d56Sopenharmony_ci    """
31357db96d56Sopenharmony_ci    data = io.BytesIO()
31367db96d56Sopenharmony_ci    zf = zipfile.ZipFile(data, "w")
31377db96d56Sopenharmony_ci    zf.writestr("a.txt", b"content of a")
31387db96d56Sopenharmony_ci    zf.writestr("b/c.txt", b"content of c")
31397db96d56Sopenharmony_ci    zf.writestr("b/d/e.txt", b"content of e")
31407db96d56Sopenharmony_ci    zf.writestr("b/f.txt", b"content of f")
31417db96d56Sopenharmony_ci    zf.writestr("g/h/i.txt", b"content of i")
31427db96d56Sopenharmony_ci    zf.filename = "alpharep.zip"
31437db96d56Sopenharmony_ci    return zf
31447db96d56Sopenharmony_ci
31457db96d56Sopenharmony_ci
31467db96d56Sopenharmony_cidef pass_alpharep(meth):
31477db96d56Sopenharmony_ci    """
31487db96d56Sopenharmony_ci    Given a method, wrap it in a for loop that invokes method
31497db96d56Sopenharmony_ci    with each subtest.
31507db96d56Sopenharmony_ci    """
31517db96d56Sopenharmony_ci
31527db96d56Sopenharmony_ci    @functools.wraps(meth)
31537db96d56Sopenharmony_ci    def wrapper(self):
31547db96d56Sopenharmony_ci        for alpharep in self.zipfile_alpharep():
31557db96d56Sopenharmony_ci            meth(self, alpharep=alpharep)
31567db96d56Sopenharmony_ci
31577db96d56Sopenharmony_ci    return wrapper
31587db96d56Sopenharmony_ci
31597db96d56Sopenharmony_ci
31607db96d56Sopenharmony_ciclass TestPath(unittest.TestCase):
31617db96d56Sopenharmony_ci    def setUp(self):
31627db96d56Sopenharmony_ci        self.fixtures = contextlib.ExitStack()
31637db96d56Sopenharmony_ci        self.addCleanup(self.fixtures.close)
31647db96d56Sopenharmony_ci
31657db96d56Sopenharmony_ci    def zipfile_alpharep(self):
31667db96d56Sopenharmony_ci        with self.subTest():
31677db96d56Sopenharmony_ci            yield build_alpharep_fixture()
31687db96d56Sopenharmony_ci        with self.subTest():
31697db96d56Sopenharmony_ci            yield add_dirs(build_alpharep_fixture())
31707db96d56Sopenharmony_ci
31717db96d56Sopenharmony_ci    def zipfile_ondisk(self, alpharep):
31727db96d56Sopenharmony_ci        tmpdir = pathlib.Path(self.fixtures.enter_context(temp_dir()))
31737db96d56Sopenharmony_ci        buffer = alpharep.fp
31747db96d56Sopenharmony_ci        alpharep.close()
31757db96d56Sopenharmony_ci        path = tmpdir / alpharep.filename
31767db96d56Sopenharmony_ci        with path.open("wb") as strm:
31777db96d56Sopenharmony_ci            strm.write(buffer.getvalue())
31787db96d56Sopenharmony_ci        return path
31797db96d56Sopenharmony_ci
31807db96d56Sopenharmony_ci    @pass_alpharep
31817db96d56Sopenharmony_ci    def test_iterdir_and_types(self, alpharep):
31827db96d56Sopenharmony_ci        root = zipfile.Path(alpharep)
31837db96d56Sopenharmony_ci        assert root.is_dir()
31847db96d56Sopenharmony_ci        a, b, g = root.iterdir()
31857db96d56Sopenharmony_ci        assert a.is_file()
31867db96d56Sopenharmony_ci        assert b.is_dir()
31877db96d56Sopenharmony_ci        assert g.is_dir()
31887db96d56Sopenharmony_ci        c, f, d = b.iterdir()
31897db96d56Sopenharmony_ci        assert c.is_file() and f.is_file()
31907db96d56Sopenharmony_ci        (e,) = d.iterdir()
31917db96d56Sopenharmony_ci        assert e.is_file()
31927db96d56Sopenharmony_ci        (h,) = g.iterdir()
31937db96d56Sopenharmony_ci        (i,) = h.iterdir()
31947db96d56Sopenharmony_ci        assert i.is_file()
31957db96d56Sopenharmony_ci
31967db96d56Sopenharmony_ci    @pass_alpharep
31977db96d56Sopenharmony_ci    def test_is_file_missing(self, alpharep):
31987db96d56Sopenharmony_ci        root = zipfile.Path(alpharep)
31997db96d56Sopenharmony_ci        assert not root.joinpath('missing.txt').is_file()
32007db96d56Sopenharmony_ci
32017db96d56Sopenharmony_ci    @pass_alpharep
32027db96d56Sopenharmony_ci    def test_iterdir_on_file(self, alpharep):
32037db96d56Sopenharmony_ci        root = zipfile.Path(alpharep)
32047db96d56Sopenharmony_ci        a, b, g = root.iterdir()
32057db96d56Sopenharmony_ci        with self.assertRaises(ValueError):
32067db96d56Sopenharmony_ci            a.iterdir()
32077db96d56Sopenharmony_ci
32087db96d56Sopenharmony_ci    @pass_alpharep
32097db96d56Sopenharmony_ci    def test_subdir_is_dir(self, alpharep):
32107db96d56Sopenharmony_ci        root = zipfile.Path(alpharep)
32117db96d56Sopenharmony_ci        assert (root / 'b').is_dir()
32127db96d56Sopenharmony_ci        assert (root / 'b/').is_dir()
32137db96d56Sopenharmony_ci        assert (root / 'g').is_dir()
32147db96d56Sopenharmony_ci        assert (root / 'g/').is_dir()
32157db96d56Sopenharmony_ci
32167db96d56Sopenharmony_ci    @pass_alpharep
32177db96d56Sopenharmony_ci    def test_open(self, alpharep):
32187db96d56Sopenharmony_ci        root = zipfile.Path(alpharep)
32197db96d56Sopenharmony_ci        a, b, g = root.iterdir()
32207db96d56Sopenharmony_ci        with a.open(encoding="utf-8") as strm:
32217db96d56Sopenharmony_ci            data = strm.read()
32227db96d56Sopenharmony_ci        self.assertEqual(data, "content of a")
32237db96d56Sopenharmony_ci        with a.open('r', "utf-8") as strm:  # not a kw, no gh-101144 TypeError
32247db96d56Sopenharmony_ci            data = strm.read()
32257db96d56Sopenharmony_ci        self.assertEqual(data, "content of a")
32267db96d56Sopenharmony_ci
32277db96d56Sopenharmony_ci    def test_open_encoding_utf16(self):
32287db96d56Sopenharmony_ci        in_memory_file = io.BytesIO()
32297db96d56Sopenharmony_ci        zf = zipfile.ZipFile(in_memory_file, "w")
32307db96d56Sopenharmony_ci        zf.writestr("path/16.txt", "This was utf-16".encode("utf-16"))
32317db96d56Sopenharmony_ci        zf.filename = "test_open_utf16.zip"
32327db96d56Sopenharmony_ci        root = zipfile.Path(zf)
32337db96d56Sopenharmony_ci        (path,) = root.iterdir()
32347db96d56Sopenharmony_ci        u16 = path.joinpath("16.txt")
32357db96d56Sopenharmony_ci        with u16.open('r', "utf-16") as strm:
32367db96d56Sopenharmony_ci            data = strm.read()
32377db96d56Sopenharmony_ci        self.assertEqual(data, "This was utf-16")
32387db96d56Sopenharmony_ci        with u16.open(encoding="utf-16") as strm:
32397db96d56Sopenharmony_ci            data = strm.read()
32407db96d56Sopenharmony_ci        self.assertEqual(data, "This was utf-16")
32417db96d56Sopenharmony_ci
32427db96d56Sopenharmony_ci    def test_open_encoding_errors(self):
32437db96d56Sopenharmony_ci        in_memory_file = io.BytesIO()
32447db96d56Sopenharmony_ci        zf = zipfile.ZipFile(in_memory_file, "w")
32457db96d56Sopenharmony_ci        zf.writestr("path/bad-utf8.bin", b"invalid utf-8: \xff\xff.")
32467db96d56Sopenharmony_ci        zf.filename = "test_read_text_encoding_errors.zip"
32477db96d56Sopenharmony_ci        root = zipfile.Path(zf)
32487db96d56Sopenharmony_ci        (path,) = root.iterdir()
32497db96d56Sopenharmony_ci        u16 = path.joinpath("bad-utf8.bin")
32507db96d56Sopenharmony_ci
32517db96d56Sopenharmony_ci        # encoding= as a positional argument for gh-101144.
32527db96d56Sopenharmony_ci        data = u16.read_text("utf-8", errors="ignore")
32537db96d56Sopenharmony_ci        self.assertEqual(data, "invalid utf-8: .")
32547db96d56Sopenharmony_ci        with u16.open("r", "utf-8", errors="surrogateescape") as f:
32557db96d56Sopenharmony_ci            self.assertEqual(f.read(), "invalid utf-8: \udcff\udcff.")
32567db96d56Sopenharmony_ci
32577db96d56Sopenharmony_ci        # encoding= both positional and keyword is an error; gh-101144.
32587db96d56Sopenharmony_ci        with self.assertRaisesRegex(TypeError, "encoding"):
32597db96d56Sopenharmony_ci            data = u16.read_text("utf-8", encoding="utf-8")
32607db96d56Sopenharmony_ci
32617db96d56Sopenharmony_ci        # both keyword arguments work.
32627db96d56Sopenharmony_ci        with u16.open("r", encoding="utf-8", errors="strict") as f:
32637db96d56Sopenharmony_ci            # error during decoding with wrong codec.
32647db96d56Sopenharmony_ci            with self.assertRaises(UnicodeDecodeError):
32657db96d56Sopenharmony_ci                f.read()
32667db96d56Sopenharmony_ci
32677db96d56Sopenharmony_ci    def test_encoding_warnings(self):
32687db96d56Sopenharmony_ci        """EncodingWarning must blame the read_text and open calls."""
32697db96d56Sopenharmony_ci        code = '''\
32707db96d56Sopenharmony_ciimport io, zipfile
32717db96d56Sopenharmony_ciwith zipfile.ZipFile(io.BytesIO(), "w") as zf:
32727db96d56Sopenharmony_ci    zf.filename = '<test_encoding_warnings in memory zip file>'
32737db96d56Sopenharmony_ci    zf.writestr("path/file.txt", b"Spanish Inquisition")
32747db96d56Sopenharmony_ci    root = zipfile.Path(zf)
32757db96d56Sopenharmony_ci    (path,) = root.iterdir()
32767db96d56Sopenharmony_ci    file_path = path.joinpath("file.txt")
32777db96d56Sopenharmony_ci    unused = file_path.read_text()  # should warn
32787db96d56Sopenharmony_ci    file_path.open("r").close()  # should warn
32797db96d56Sopenharmony_ci'''
32807db96d56Sopenharmony_ci        proc = assert_python_ok('-X', 'warn_default_encoding', '-c', code)
32817db96d56Sopenharmony_ci        warnings = proc.err.splitlines()
32827db96d56Sopenharmony_ci        self.assertEqual(len(warnings), 2, proc.err)
32837db96d56Sopenharmony_ci        self.assertRegex(warnings[0], rb"^<string>:8: EncodingWarning:")
32847db96d56Sopenharmony_ci        self.assertRegex(warnings[1], rb"^<string>:9: EncodingWarning:")
32857db96d56Sopenharmony_ci
32867db96d56Sopenharmony_ci    def test_open_write(self):
32877db96d56Sopenharmony_ci        """
32887db96d56Sopenharmony_ci        If the zipfile is open for write, it should be possible to
32897db96d56Sopenharmony_ci        write bytes or text to it.
32907db96d56Sopenharmony_ci        """
32917db96d56Sopenharmony_ci        zf = zipfile.Path(zipfile.ZipFile(io.BytesIO(), mode='w'))
32927db96d56Sopenharmony_ci        with zf.joinpath('file.bin').open('wb') as strm:
32937db96d56Sopenharmony_ci            strm.write(b'binary contents')
32947db96d56Sopenharmony_ci        with zf.joinpath('file.txt').open('w', encoding="utf-8") as strm:
32957db96d56Sopenharmony_ci            strm.write('text file')
32967db96d56Sopenharmony_ci
32977db96d56Sopenharmony_ci    def test_open_extant_directory(self):
32987db96d56Sopenharmony_ci        """
32997db96d56Sopenharmony_ci        Attempting to open a directory raises IsADirectoryError.
33007db96d56Sopenharmony_ci        """
33017db96d56Sopenharmony_ci        zf = zipfile.Path(add_dirs(build_alpharep_fixture()))
33027db96d56Sopenharmony_ci        with self.assertRaises(IsADirectoryError):
33037db96d56Sopenharmony_ci            zf.joinpath('b').open()
33047db96d56Sopenharmony_ci
33057db96d56Sopenharmony_ci    @pass_alpharep
33067db96d56Sopenharmony_ci    def test_open_binary_invalid_args(self, alpharep):
33077db96d56Sopenharmony_ci        root = zipfile.Path(alpharep)
33087db96d56Sopenharmony_ci        with self.assertRaises(ValueError):
33097db96d56Sopenharmony_ci            root.joinpath('a.txt').open('rb', encoding='utf-8')
33107db96d56Sopenharmony_ci        with self.assertRaises(ValueError):
33117db96d56Sopenharmony_ci            root.joinpath('a.txt').open('rb', 'utf-8')
33127db96d56Sopenharmony_ci
33137db96d56Sopenharmony_ci    def test_open_missing_directory(self):
33147db96d56Sopenharmony_ci        """
33157db96d56Sopenharmony_ci        Attempting to open a missing directory raises FileNotFoundError.
33167db96d56Sopenharmony_ci        """
33177db96d56Sopenharmony_ci        zf = zipfile.Path(add_dirs(build_alpharep_fixture()))
33187db96d56Sopenharmony_ci        with self.assertRaises(FileNotFoundError):
33197db96d56Sopenharmony_ci            zf.joinpath('z').open()
33207db96d56Sopenharmony_ci
33217db96d56Sopenharmony_ci    @pass_alpharep
33227db96d56Sopenharmony_ci    def test_read(self, alpharep):
33237db96d56Sopenharmony_ci        root = zipfile.Path(alpharep)
33247db96d56Sopenharmony_ci        a, b, g = root.iterdir()
33257db96d56Sopenharmony_ci        assert a.read_text(encoding="utf-8") == "content of a"
33267db96d56Sopenharmony_ci        a.read_text("utf-8")  # No positional arg TypeError per gh-101144.
33277db96d56Sopenharmony_ci        assert a.read_bytes() == b"content of a"
33287db96d56Sopenharmony_ci
33297db96d56Sopenharmony_ci    @pass_alpharep
33307db96d56Sopenharmony_ci    def test_joinpath(self, alpharep):
33317db96d56Sopenharmony_ci        root = zipfile.Path(alpharep)
33327db96d56Sopenharmony_ci        a = root.joinpath("a.txt")
33337db96d56Sopenharmony_ci        assert a.is_file()
33347db96d56Sopenharmony_ci        e = root.joinpath("b").joinpath("d").joinpath("e.txt")
33357db96d56Sopenharmony_ci        assert e.read_text(encoding="utf-8") == "content of e"
33367db96d56Sopenharmony_ci
33377db96d56Sopenharmony_ci    @pass_alpharep
33387db96d56Sopenharmony_ci    def test_joinpath_multiple(self, alpharep):
33397db96d56Sopenharmony_ci        root = zipfile.Path(alpharep)
33407db96d56Sopenharmony_ci        e = root.joinpath("b", "d", "e.txt")
33417db96d56Sopenharmony_ci        assert e.read_text(encoding="utf-8") == "content of e"
33427db96d56Sopenharmony_ci
33437db96d56Sopenharmony_ci    @pass_alpharep
33447db96d56Sopenharmony_ci    def test_traverse_truediv(self, alpharep):
33457db96d56Sopenharmony_ci        root = zipfile.Path(alpharep)
33467db96d56Sopenharmony_ci        a = root / "a.txt"
33477db96d56Sopenharmony_ci        assert a.is_file()
33487db96d56Sopenharmony_ci        e = root / "b" / "d" / "e.txt"
33497db96d56Sopenharmony_ci        assert e.read_text(encoding="utf-8") == "content of e"
33507db96d56Sopenharmony_ci
33517db96d56Sopenharmony_ci    @pass_alpharep
33527db96d56Sopenharmony_ci    def test_traverse_simplediv(self, alpharep):
33537db96d56Sopenharmony_ci        """
33547db96d56Sopenharmony_ci        Disable the __future__.division when testing traversal.
33557db96d56Sopenharmony_ci        """
33567db96d56Sopenharmony_ci        code = compile(
33577db96d56Sopenharmony_ci            source="zipfile.Path(alpharep) / 'a'",
33587db96d56Sopenharmony_ci            filename="(test)",
33597db96d56Sopenharmony_ci            mode="eval",
33607db96d56Sopenharmony_ci            dont_inherit=True,
33617db96d56Sopenharmony_ci        )
33627db96d56Sopenharmony_ci        eval(code)
33637db96d56Sopenharmony_ci
33647db96d56Sopenharmony_ci    @pass_alpharep
33657db96d56Sopenharmony_ci    def test_pathlike_construction(self, alpharep):
33667db96d56Sopenharmony_ci        """
33677db96d56Sopenharmony_ci        zipfile.Path should be constructable from a path-like object
33687db96d56Sopenharmony_ci        """
33697db96d56Sopenharmony_ci        zipfile_ondisk = self.zipfile_ondisk(alpharep)
33707db96d56Sopenharmony_ci        pathlike = pathlib.Path(str(zipfile_ondisk))
33717db96d56Sopenharmony_ci        zipfile.Path(pathlike)
33727db96d56Sopenharmony_ci
33737db96d56Sopenharmony_ci    @pass_alpharep
33747db96d56Sopenharmony_ci    def test_traverse_pathlike(self, alpharep):
33757db96d56Sopenharmony_ci        root = zipfile.Path(alpharep)
33767db96d56Sopenharmony_ci        root / pathlib.Path("a")
33777db96d56Sopenharmony_ci
33787db96d56Sopenharmony_ci    @pass_alpharep
33797db96d56Sopenharmony_ci    def test_parent(self, alpharep):
33807db96d56Sopenharmony_ci        root = zipfile.Path(alpharep)
33817db96d56Sopenharmony_ci        assert (root / 'a').parent.at == ''
33827db96d56Sopenharmony_ci        assert (root / 'a' / 'b').parent.at == 'a/'
33837db96d56Sopenharmony_ci
33847db96d56Sopenharmony_ci    @pass_alpharep
33857db96d56Sopenharmony_ci    def test_dir_parent(self, alpharep):
33867db96d56Sopenharmony_ci        root = zipfile.Path(alpharep)
33877db96d56Sopenharmony_ci        assert (root / 'b').parent.at == ''
33887db96d56Sopenharmony_ci        assert (root / 'b/').parent.at == ''
33897db96d56Sopenharmony_ci
33907db96d56Sopenharmony_ci    @pass_alpharep
33917db96d56Sopenharmony_ci    def test_missing_dir_parent(self, alpharep):
33927db96d56Sopenharmony_ci        root = zipfile.Path(alpharep)
33937db96d56Sopenharmony_ci        assert (root / 'missing dir/').parent.at == ''
33947db96d56Sopenharmony_ci
33957db96d56Sopenharmony_ci    @pass_alpharep
33967db96d56Sopenharmony_ci    def test_mutability(self, alpharep):
33977db96d56Sopenharmony_ci        """
33987db96d56Sopenharmony_ci        If the underlying zipfile is changed, the Path object should
33997db96d56Sopenharmony_ci        reflect that change.
34007db96d56Sopenharmony_ci        """
34017db96d56Sopenharmony_ci        root = zipfile.Path(alpharep)
34027db96d56Sopenharmony_ci        a, b, g = root.iterdir()
34037db96d56Sopenharmony_ci        alpharep.writestr('foo.txt', 'foo')
34047db96d56Sopenharmony_ci        alpharep.writestr('bar/baz.txt', 'baz')
34057db96d56Sopenharmony_ci        assert any(child.name == 'foo.txt' for child in root.iterdir())
34067db96d56Sopenharmony_ci        assert (root / 'foo.txt').read_text(encoding="utf-8") == 'foo'
34077db96d56Sopenharmony_ci        (baz,) = (root / 'bar').iterdir()
34087db96d56Sopenharmony_ci        assert baz.read_text(encoding="utf-8") == 'baz'
34097db96d56Sopenharmony_ci
34107db96d56Sopenharmony_ci    HUGE_ZIPFILE_NUM_ENTRIES = 2 ** 13
34117db96d56Sopenharmony_ci
34127db96d56Sopenharmony_ci    def huge_zipfile(self):
34137db96d56Sopenharmony_ci        """Create a read-only zipfile with a huge number of entries entries."""
34147db96d56Sopenharmony_ci        strm = io.BytesIO()
34157db96d56Sopenharmony_ci        zf = zipfile.ZipFile(strm, "w")
34167db96d56Sopenharmony_ci        for entry in map(str, range(self.HUGE_ZIPFILE_NUM_ENTRIES)):
34177db96d56Sopenharmony_ci            zf.writestr(entry, entry)
34187db96d56Sopenharmony_ci        zf.mode = 'r'
34197db96d56Sopenharmony_ci        return zf
34207db96d56Sopenharmony_ci
34217db96d56Sopenharmony_ci    def test_joinpath_constant_time(self):
34227db96d56Sopenharmony_ci        """
34237db96d56Sopenharmony_ci        Ensure joinpath on items in zipfile is linear time.
34247db96d56Sopenharmony_ci        """
34257db96d56Sopenharmony_ci        root = zipfile.Path(self.huge_zipfile())
34267db96d56Sopenharmony_ci        entries = jaraco.itertools.Counter(root.iterdir())
34277db96d56Sopenharmony_ci        for entry in entries:
34287db96d56Sopenharmony_ci            entry.joinpath('suffix')
34297db96d56Sopenharmony_ci        # Check the file iterated all items
34307db96d56Sopenharmony_ci        assert entries.count == self.HUGE_ZIPFILE_NUM_ENTRIES
34317db96d56Sopenharmony_ci
34327db96d56Sopenharmony_ci    # @func_timeout.func_set_timeout(3)
34337db96d56Sopenharmony_ci    def test_implied_dirs_performance(self):
34347db96d56Sopenharmony_ci        data = ['/'.join(string.ascii_lowercase + str(n)) for n in range(10000)]
34357db96d56Sopenharmony_ci        zipfile.CompleteDirs._implied_dirs(data)
34367db96d56Sopenharmony_ci
34377db96d56Sopenharmony_ci    @pass_alpharep
34387db96d56Sopenharmony_ci    def test_read_does_not_close(self, alpharep):
34397db96d56Sopenharmony_ci        alpharep = self.zipfile_ondisk(alpharep)
34407db96d56Sopenharmony_ci        with zipfile.ZipFile(alpharep) as file:
34417db96d56Sopenharmony_ci            for rep in range(2):
34427db96d56Sopenharmony_ci                zipfile.Path(file, 'a.txt').read_text(encoding="utf-8")
34437db96d56Sopenharmony_ci
34447db96d56Sopenharmony_ci    @pass_alpharep
34457db96d56Sopenharmony_ci    def test_subclass(self, alpharep):
34467db96d56Sopenharmony_ci        class Subclass(zipfile.Path):
34477db96d56Sopenharmony_ci            pass
34487db96d56Sopenharmony_ci
34497db96d56Sopenharmony_ci        root = Subclass(alpharep)
34507db96d56Sopenharmony_ci        assert isinstance(root / 'b', Subclass)
34517db96d56Sopenharmony_ci
34527db96d56Sopenharmony_ci    @pass_alpharep
34537db96d56Sopenharmony_ci    def test_filename(self, alpharep):
34547db96d56Sopenharmony_ci        root = zipfile.Path(alpharep)
34557db96d56Sopenharmony_ci        assert root.filename == pathlib.Path('alpharep.zip')
34567db96d56Sopenharmony_ci
34577db96d56Sopenharmony_ci    @pass_alpharep
34587db96d56Sopenharmony_ci    def test_root_name(self, alpharep):
34597db96d56Sopenharmony_ci        """
34607db96d56Sopenharmony_ci        The name of the root should be the name of the zipfile
34617db96d56Sopenharmony_ci        """
34627db96d56Sopenharmony_ci        root = zipfile.Path(alpharep)
34637db96d56Sopenharmony_ci        assert root.name == 'alpharep.zip' == root.filename.name
34647db96d56Sopenharmony_ci
34657db96d56Sopenharmony_ci    @pass_alpharep
34667db96d56Sopenharmony_ci    def test_suffix(self, alpharep):
34677db96d56Sopenharmony_ci        """
34687db96d56Sopenharmony_ci        The suffix of the root should be the suffix of the zipfile.
34697db96d56Sopenharmony_ci        The suffix of each nested file is the final component's last suffix, if any.
34707db96d56Sopenharmony_ci        Includes the leading period, just like pathlib.Path.
34717db96d56Sopenharmony_ci        """
34727db96d56Sopenharmony_ci        root = zipfile.Path(alpharep)
34737db96d56Sopenharmony_ci        assert root.suffix == '.zip' == root.filename.suffix
34747db96d56Sopenharmony_ci
34757db96d56Sopenharmony_ci        b = root / "b.txt"
34767db96d56Sopenharmony_ci        assert b.suffix == ".txt"
34777db96d56Sopenharmony_ci
34787db96d56Sopenharmony_ci        c = root / "c" / "filename.tar.gz"
34797db96d56Sopenharmony_ci        assert c.suffix == ".gz"
34807db96d56Sopenharmony_ci
34817db96d56Sopenharmony_ci        d = root / "d"
34827db96d56Sopenharmony_ci        assert d.suffix == ""
34837db96d56Sopenharmony_ci
34847db96d56Sopenharmony_ci    @pass_alpharep
34857db96d56Sopenharmony_ci    def test_suffixes(self, alpharep):
34867db96d56Sopenharmony_ci        """
34877db96d56Sopenharmony_ci        The suffix of the root should be the suffix of the zipfile.
34887db96d56Sopenharmony_ci        The suffix of each nested file is the final component's last suffix, if any.
34897db96d56Sopenharmony_ci        Includes the leading period, just like pathlib.Path.
34907db96d56Sopenharmony_ci        """
34917db96d56Sopenharmony_ci        root = zipfile.Path(alpharep)
34927db96d56Sopenharmony_ci        assert root.suffixes == ['.zip'] == root.filename.suffixes
34937db96d56Sopenharmony_ci
34947db96d56Sopenharmony_ci        b = root / 'b.txt'
34957db96d56Sopenharmony_ci        assert b.suffixes == ['.txt']
34967db96d56Sopenharmony_ci
34977db96d56Sopenharmony_ci        c = root / 'c' / 'filename.tar.gz'
34987db96d56Sopenharmony_ci        assert c.suffixes == ['.tar', '.gz']
34997db96d56Sopenharmony_ci
35007db96d56Sopenharmony_ci        d = root / 'd'
35017db96d56Sopenharmony_ci        assert d.suffixes == []
35027db96d56Sopenharmony_ci
35037db96d56Sopenharmony_ci        e = root / '.hgrc'
35047db96d56Sopenharmony_ci        assert e.suffixes == []
35057db96d56Sopenharmony_ci
35067db96d56Sopenharmony_ci    @pass_alpharep
35077db96d56Sopenharmony_ci    def test_stem(self, alpharep):
35087db96d56Sopenharmony_ci        """
35097db96d56Sopenharmony_ci        The final path component, without its suffix
35107db96d56Sopenharmony_ci        """
35117db96d56Sopenharmony_ci        root = zipfile.Path(alpharep)
35127db96d56Sopenharmony_ci        assert root.stem == 'alpharep' == root.filename.stem
35137db96d56Sopenharmony_ci
35147db96d56Sopenharmony_ci        b = root / "b.txt"
35157db96d56Sopenharmony_ci        assert b.stem == "b"
35167db96d56Sopenharmony_ci
35177db96d56Sopenharmony_ci        c = root / "c" / "filename.tar.gz"
35187db96d56Sopenharmony_ci        assert c.stem == "filename.tar"
35197db96d56Sopenharmony_ci
35207db96d56Sopenharmony_ci        d = root / "d"
35217db96d56Sopenharmony_ci        assert d.stem == "d"
35227db96d56Sopenharmony_ci
35237db96d56Sopenharmony_ci    @pass_alpharep
35247db96d56Sopenharmony_ci    def test_root_parent(self, alpharep):
35257db96d56Sopenharmony_ci        root = zipfile.Path(alpharep)
35267db96d56Sopenharmony_ci        assert root.parent == pathlib.Path('.')
35277db96d56Sopenharmony_ci        root.root.filename = 'foo/bar.zip'
35287db96d56Sopenharmony_ci        assert root.parent == pathlib.Path('foo')
35297db96d56Sopenharmony_ci
35307db96d56Sopenharmony_ci    @pass_alpharep
35317db96d56Sopenharmony_ci    def test_root_unnamed(self, alpharep):
35327db96d56Sopenharmony_ci        """
35337db96d56Sopenharmony_ci        It is an error to attempt to get the name
35347db96d56Sopenharmony_ci        or parent of an unnamed zipfile.
35357db96d56Sopenharmony_ci        """
35367db96d56Sopenharmony_ci        alpharep.filename = None
35377db96d56Sopenharmony_ci        root = zipfile.Path(alpharep)
35387db96d56Sopenharmony_ci        with self.assertRaises(TypeError):
35397db96d56Sopenharmony_ci            root.name
35407db96d56Sopenharmony_ci        with self.assertRaises(TypeError):
35417db96d56Sopenharmony_ci            root.parent
35427db96d56Sopenharmony_ci
35437db96d56Sopenharmony_ci        # .name and .parent should still work on subs
35447db96d56Sopenharmony_ci        sub = root / "b"
35457db96d56Sopenharmony_ci        assert sub.name == "b"
35467db96d56Sopenharmony_ci        assert sub.parent
35477db96d56Sopenharmony_ci
35487db96d56Sopenharmony_ci    @pass_alpharep
35497db96d56Sopenharmony_ci    def test_inheritance(self, alpharep):
35507db96d56Sopenharmony_ci        cls = type('PathChild', (zipfile.Path,), {})
35517db96d56Sopenharmony_ci        for alpharep in self.zipfile_alpharep():
35527db96d56Sopenharmony_ci            file = cls(alpharep).joinpath('some dir').parent
35537db96d56Sopenharmony_ci            assert isinstance(file, cls)
35547db96d56Sopenharmony_ci
35557db96d56Sopenharmony_ci    @pass_alpharep
35567db96d56Sopenharmony_ci    def test_extract_orig_with_implied_dirs(self, alpharep):
35577db96d56Sopenharmony_ci        """
35587db96d56Sopenharmony_ci        A zip file wrapped in a Path should extract even with implied dirs.
35597db96d56Sopenharmony_ci        """
35607db96d56Sopenharmony_ci        source_path = self.zipfile_ondisk(alpharep)
35617db96d56Sopenharmony_ci        zf = zipfile.ZipFile(source_path)
35627db96d56Sopenharmony_ci        # wrap the zipfile for its side effect
35637db96d56Sopenharmony_ci        zipfile.Path(zf)
35647db96d56Sopenharmony_ci        zf.extractall(source_path.parent)
35657db96d56Sopenharmony_ci
35667db96d56Sopenharmony_ci    def test_malformed_paths(self):
35677db96d56Sopenharmony_ci        """
35687db96d56Sopenharmony_ci        Path should handle malformed paths.
35697db96d56Sopenharmony_ci        """
35707db96d56Sopenharmony_ci        data = io.BytesIO()
35717db96d56Sopenharmony_ci        zf = zipfile.ZipFile(data, "w")
35727db96d56Sopenharmony_ci        zf.writestr("/one-slash.txt", b"content")
35737db96d56Sopenharmony_ci        zf.writestr("//two-slash.txt", b"content")
35747db96d56Sopenharmony_ci        zf.writestr("../parent.txt", b"content")
35757db96d56Sopenharmony_ci        zf.filename = ''
35767db96d56Sopenharmony_ci        root = zipfile.Path(zf)
35777db96d56Sopenharmony_ci        assert list(map(str, root.iterdir())) == [
35787db96d56Sopenharmony_ci            'one-slash.txt',
35797db96d56Sopenharmony_ci            'two-slash.txt',
35807db96d56Sopenharmony_ci            'parent.txt',
35817db96d56Sopenharmony_ci        ]
35827db96d56Sopenharmony_ci
35837db96d56Sopenharmony_ci
35847db96d56Sopenharmony_ciclass EncodedMetadataTests(unittest.TestCase):
35857db96d56Sopenharmony_ci    file_names = ['\u4e00', '\u4e8c', '\u4e09']  # Han 'one', 'two', 'three'
35867db96d56Sopenharmony_ci    file_content = [
35877db96d56Sopenharmony_ci        "This is pure ASCII.\n".encode('ascii'),
35887db96d56Sopenharmony_ci        # This is modern Japanese. (UTF-8)
35897db96d56Sopenharmony_ci        "\u3053\u308c\u306f\u73fe\u4ee3\u7684\u65e5\u672c\u8a9e\u3067\u3059\u3002\n".encode('utf-8'),
35907db96d56Sopenharmony_ci        # This is obsolete Japanese. (Shift JIS)
35917db96d56Sopenharmony_ci        "\u3053\u308c\u306f\u53e4\u3044\u65e5\u672c\u8a9e\u3067\u3059\u3002\n".encode('shift_jis'),
35927db96d56Sopenharmony_ci    ]
35937db96d56Sopenharmony_ci
35947db96d56Sopenharmony_ci    def setUp(self):
35957db96d56Sopenharmony_ci        self.addCleanup(unlink, TESTFN)
35967db96d56Sopenharmony_ci        # Create .zip of 3 members with Han names encoded in Shift JIS.
35977db96d56Sopenharmony_ci        # Each name is 1 Han character encoding to 2 bytes in Shift JIS.
35987db96d56Sopenharmony_ci        # The ASCII names are arbitrary as long as they are length 2 and
35997db96d56Sopenharmony_ci        # not otherwise contained in the zip file.
36007db96d56Sopenharmony_ci        # Data elements are encoded bytes (ascii, utf-8, shift_jis).
36017db96d56Sopenharmony_ci        placeholders = ["n1", "n2"] + self.file_names[2:]
36027db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, mode="w") as tf:
36037db96d56Sopenharmony_ci            for temp, content in zip(placeholders, self.file_content):
36047db96d56Sopenharmony_ci                tf.writestr(temp, content, zipfile.ZIP_STORED)
36057db96d56Sopenharmony_ci        # Hack in the Shift JIS names with flag bit 11 (UTF-8) unset.
36067db96d56Sopenharmony_ci        with open(TESTFN, "rb") as tf:
36077db96d56Sopenharmony_ci            data = tf.read()
36087db96d56Sopenharmony_ci        for name, temp in zip(self.file_names, placeholders[:2]):
36097db96d56Sopenharmony_ci            data = data.replace(temp.encode('ascii'),
36107db96d56Sopenharmony_ci                                name.encode('shift_jis'))
36117db96d56Sopenharmony_ci        with open(TESTFN, "wb") as tf:
36127db96d56Sopenharmony_ci            tf.write(data)
36137db96d56Sopenharmony_ci
36147db96d56Sopenharmony_ci    def _test_read(self, zipfp, expected_names, expected_content):
36157db96d56Sopenharmony_ci        # Check the namelist
36167db96d56Sopenharmony_ci        names = zipfp.namelist()
36177db96d56Sopenharmony_ci        self.assertEqual(sorted(names), sorted(expected_names))
36187db96d56Sopenharmony_ci
36197db96d56Sopenharmony_ci        # Check infolist
36207db96d56Sopenharmony_ci        infos = zipfp.infolist()
36217db96d56Sopenharmony_ci        names = [zi.filename for zi in infos]
36227db96d56Sopenharmony_ci        self.assertEqual(sorted(names), sorted(expected_names))
36237db96d56Sopenharmony_ci
36247db96d56Sopenharmony_ci        # check getinfo
36257db96d56Sopenharmony_ci        for name, content in zip(expected_names, expected_content):
36267db96d56Sopenharmony_ci            info = zipfp.getinfo(name)
36277db96d56Sopenharmony_ci            self.assertEqual(info.filename, name)
36287db96d56Sopenharmony_ci            self.assertEqual(info.file_size, len(content))
36297db96d56Sopenharmony_ci            self.assertEqual(zipfp.read(name), content)
36307db96d56Sopenharmony_ci
36317db96d56Sopenharmony_ci    def test_read_with_metadata_encoding(self):
36327db96d56Sopenharmony_ci        # Read the ZIP archive with correct metadata_encoding
36337db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, "r", metadata_encoding='shift_jis') as zipfp:
36347db96d56Sopenharmony_ci            self._test_read(zipfp, self.file_names, self.file_content)
36357db96d56Sopenharmony_ci
36367db96d56Sopenharmony_ci    def test_read_without_metadata_encoding(self):
36377db96d56Sopenharmony_ci        # Read the ZIP archive without metadata_encoding
36387db96d56Sopenharmony_ci        expected_names = [name.encode('shift_jis').decode('cp437')
36397db96d56Sopenharmony_ci                          for name in self.file_names[:2]] + self.file_names[2:]
36407db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, "r") as zipfp:
36417db96d56Sopenharmony_ci            self._test_read(zipfp, expected_names, self.file_content)
36427db96d56Sopenharmony_ci
36437db96d56Sopenharmony_ci    def test_read_with_incorrect_metadata_encoding(self):
36447db96d56Sopenharmony_ci        # Read the ZIP archive with incorrect metadata_encoding
36457db96d56Sopenharmony_ci        expected_names = [name.encode('shift_jis').decode('koi8-u')
36467db96d56Sopenharmony_ci                          for name in self.file_names[:2]] + self.file_names[2:]
36477db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, "r", metadata_encoding='koi8-u') as zipfp:
36487db96d56Sopenharmony_ci            self._test_read(zipfp, expected_names, self.file_content)
36497db96d56Sopenharmony_ci
36507db96d56Sopenharmony_ci    def test_read_with_unsuitable_metadata_encoding(self):
36517db96d56Sopenharmony_ci        # Read the ZIP archive with metadata_encoding unsuitable for
36527db96d56Sopenharmony_ci        # decoding metadata
36537db96d56Sopenharmony_ci        with self.assertRaises(UnicodeDecodeError):
36547db96d56Sopenharmony_ci            zipfile.ZipFile(TESTFN, "r", metadata_encoding='ascii')
36557db96d56Sopenharmony_ci        with self.assertRaises(UnicodeDecodeError):
36567db96d56Sopenharmony_ci            zipfile.ZipFile(TESTFN, "r", metadata_encoding='utf-8')
36577db96d56Sopenharmony_ci
36587db96d56Sopenharmony_ci    def test_read_after_append(self):
36597db96d56Sopenharmony_ci        newname = '\u56db'  # Han 'four'
36607db96d56Sopenharmony_ci        expected_names = [name.encode('shift_jis').decode('cp437')
36617db96d56Sopenharmony_ci                          for name in self.file_names[:2]] + self.file_names[2:]
36627db96d56Sopenharmony_ci        expected_names.append(newname)
36637db96d56Sopenharmony_ci        expected_content = (*self.file_content, b"newcontent")
36647db96d56Sopenharmony_ci
36657db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, "a") as zipfp:
36667db96d56Sopenharmony_ci            zipfp.writestr(newname, "newcontent")
36677db96d56Sopenharmony_ci            self.assertEqual(sorted(zipfp.namelist()), sorted(expected_names))
36687db96d56Sopenharmony_ci
36697db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, "r") as zipfp:
36707db96d56Sopenharmony_ci            self._test_read(zipfp, expected_names, expected_content)
36717db96d56Sopenharmony_ci
36727db96d56Sopenharmony_ci        with zipfile.ZipFile(TESTFN, "r", metadata_encoding='shift_jis') as zipfp:
36737db96d56Sopenharmony_ci            self.assertEqual(sorted(zipfp.namelist()), sorted(expected_names))
36747db96d56Sopenharmony_ci            for i, (name, content) in enumerate(zip(expected_names, expected_content)):
36757db96d56Sopenharmony_ci                info = zipfp.getinfo(name)
36767db96d56Sopenharmony_ci                self.assertEqual(info.filename, name)
36777db96d56Sopenharmony_ci                self.assertEqual(info.file_size, len(content))
36787db96d56Sopenharmony_ci                if i < 2:
36797db96d56Sopenharmony_ci                    with self.assertRaises(zipfile.BadZipFile):
36807db96d56Sopenharmony_ci                        zipfp.read(name)
36817db96d56Sopenharmony_ci                else:
36827db96d56Sopenharmony_ci                    self.assertEqual(zipfp.read(name), content)
36837db96d56Sopenharmony_ci
36847db96d56Sopenharmony_ci    def test_write_with_metadata_encoding(self):
36857db96d56Sopenharmony_ci        ZF = zipfile.ZipFile
36867db96d56Sopenharmony_ci        for mode in ("w", "x", "a"):
36877db96d56Sopenharmony_ci            with self.assertRaisesRegex(ValueError,
36887db96d56Sopenharmony_ci                                        "^metadata_encoding is only"):
36897db96d56Sopenharmony_ci                ZF("nonesuch.zip", mode, metadata_encoding="shift_jis")
36907db96d56Sopenharmony_ci
36917db96d56Sopenharmony_ci    def test_cli_with_metadata_encoding(self):
36927db96d56Sopenharmony_ci        errmsg = "Non-conforming encodings not supported with -c."
36937db96d56Sopenharmony_ci        args = ["--metadata-encoding=shift_jis", "-c", "nonesuch", "nonesuch"]
36947db96d56Sopenharmony_ci        with captured_stdout() as stdout:
36957db96d56Sopenharmony_ci            with captured_stderr() as stderr:
36967db96d56Sopenharmony_ci                self.assertRaises(SystemExit, zipfile.main, args)
36977db96d56Sopenharmony_ci        self.assertEqual(stdout.getvalue(), "")
36987db96d56Sopenharmony_ci        self.assertIn(errmsg, stderr.getvalue())
36997db96d56Sopenharmony_ci
37007db96d56Sopenharmony_ci        with captured_stdout() as stdout:
37017db96d56Sopenharmony_ci            zipfile.main(["--metadata-encoding=shift_jis", "-t", TESTFN])
37027db96d56Sopenharmony_ci        listing = stdout.getvalue()
37037db96d56Sopenharmony_ci
37047db96d56Sopenharmony_ci        with captured_stdout() as stdout:
37057db96d56Sopenharmony_ci            zipfile.main(["--metadata-encoding=shift_jis", "-l", TESTFN])
37067db96d56Sopenharmony_ci        listing = stdout.getvalue()
37077db96d56Sopenharmony_ci        for name in self.file_names:
37087db96d56Sopenharmony_ci            self.assertIn(name, listing)
37097db96d56Sopenharmony_ci
37107db96d56Sopenharmony_ci    def test_cli_with_metadata_encoding_extract(self):
37117db96d56Sopenharmony_ci        os.mkdir(TESTFN2)
37127db96d56Sopenharmony_ci        self.addCleanup(rmtree, TESTFN2)
37137db96d56Sopenharmony_ci        # Depending on locale, extracted file names can be not encodable
37147db96d56Sopenharmony_ci        # with the filesystem encoding.
37157db96d56Sopenharmony_ci        for fn in self.file_names:
37167db96d56Sopenharmony_ci            try:
37177db96d56Sopenharmony_ci                os.stat(os.path.join(TESTFN2, fn))
37187db96d56Sopenharmony_ci            except OSError:
37197db96d56Sopenharmony_ci                pass
37207db96d56Sopenharmony_ci            except UnicodeEncodeError:
37217db96d56Sopenharmony_ci                self.skipTest(f'cannot encode file name {fn!r}')
37227db96d56Sopenharmony_ci
37237db96d56Sopenharmony_ci        zipfile.main(["--metadata-encoding=shift_jis", "-e", TESTFN, TESTFN2])
37247db96d56Sopenharmony_ci        listing = os.listdir(TESTFN2)
37257db96d56Sopenharmony_ci        for name in self.file_names:
37267db96d56Sopenharmony_ci            self.assertIn(name, listing)
37277db96d56Sopenharmony_ci
37287db96d56Sopenharmony_ci
37297db96d56Sopenharmony_ciclass StripExtraTests(unittest.TestCase):
37307db96d56Sopenharmony_ci    # Note: all of the "z" characters are technically invalid, but up
37317db96d56Sopenharmony_ci    # to 3 bytes at the end of the extra will be passed through as they
37327db96d56Sopenharmony_ci    # are too short to encode a valid extra.
37337db96d56Sopenharmony_ci
37347db96d56Sopenharmony_ci    ZIP64_EXTRA = 1
37357db96d56Sopenharmony_ci
37367db96d56Sopenharmony_ci    def test_no_data(self):
37377db96d56Sopenharmony_ci        s = struct.Struct("<HH")
37387db96d56Sopenharmony_ci        a = s.pack(self.ZIP64_EXTRA, 0)
37397db96d56Sopenharmony_ci        b = s.pack(2, 0)
37407db96d56Sopenharmony_ci        c = s.pack(3, 0)
37417db96d56Sopenharmony_ci
37427db96d56Sopenharmony_ci        self.assertEqual(b'', zipfile._strip_extra(a, (self.ZIP64_EXTRA,)))
37437db96d56Sopenharmony_ci        self.assertEqual(b, zipfile._strip_extra(b, (self.ZIP64_EXTRA,)))
37447db96d56Sopenharmony_ci        self.assertEqual(
37457db96d56Sopenharmony_ci            b+b"z", zipfile._strip_extra(b+b"z", (self.ZIP64_EXTRA,)))
37467db96d56Sopenharmony_ci
37477db96d56Sopenharmony_ci        self.assertEqual(b+c, zipfile._strip_extra(a+b+c, (self.ZIP64_EXTRA,)))
37487db96d56Sopenharmony_ci        self.assertEqual(b+c, zipfile._strip_extra(b+a+c, (self.ZIP64_EXTRA,)))
37497db96d56Sopenharmony_ci        self.assertEqual(b+c, zipfile._strip_extra(b+c+a, (self.ZIP64_EXTRA,)))
37507db96d56Sopenharmony_ci
37517db96d56Sopenharmony_ci    def test_with_data(self):
37527db96d56Sopenharmony_ci        s = struct.Struct("<HH")
37537db96d56Sopenharmony_ci        a = s.pack(self.ZIP64_EXTRA, 1) + b"a"
37547db96d56Sopenharmony_ci        b = s.pack(2, 2) + b"bb"
37557db96d56Sopenharmony_ci        c = s.pack(3, 3) + b"ccc"
37567db96d56Sopenharmony_ci
37577db96d56Sopenharmony_ci        self.assertEqual(b"", zipfile._strip_extra(a, (self.ZIP64_EXTRA,)))
37587db96d56Sopenharmony_ci        self.assertEqual(b, zipfile._strip_extra(b, (self.ZIP64_EXTRA,)))
37597db96d56Sopenharmony_ci        self.assertEqual(
37607db96d56Sopenharmony_ci            b+b"z", zipfile._strip_extra(b+b"z", (self.ZIP64_EXTRA,)))
37617db96d56Sopenharmony_ci
37627db96d56Sopenharmony_ci        self.assertEqual(b+c, zipfile._strip_extra(a+b+c, (self.ZIP64_EXTRA,)))
37637db96d56Sopenharmony_ci        self.assertEqual(b+c, zipfile._strip_extra(b+a+c, (self.ZIP64_EXTRA,)))
37647db96d56Sopenharmony_ci        self.assertEqual(b+c, zipfile._strip_extra(b+c+a, (self.ZIP64_EXTRA,)))
37657db96d56Sopenharmony_ci
37667db96d56Sopenharmony_ci    def test_multiples(self):
37677db96d56Sopenharmony_ci        s = struct.Struct("<HH")
37687db96d56Sopenharmony_ci        a = s.pack(self.ZIP64_EXTRA, 1) + b"a"
37697db96d56Sopenharmony_ci        b = s.pack(2, 2) + b"bb"
37707db96d56Sopenharmony_ci
37717db96d56Sopenharmony_ci        self.assertEqual(b"", zipfile._strip_extra(a+a, (self.ZIP64_EXTRA,)))
37727db96d56Sopenharmony_ci        self.assertEqual(b"", zipfile._strip_extra(a+a+a, (self.ZIP64_EXTRA,)))
37737db96d56Sopenharmony_ci        self.assertEqual(
37747db96d56Sopenharmony_ci            b"z", zipfile._strip_extra(a+a+b"z", (self.ZIP64_EXTRA,)))
37757db96d56Sopenharmony_ci        self.assertEqual(
37767db96d56Sopenharmony_ci            b+b"z", zipfile._strip_extra(a+a+b+b"z", (self.ZIP64_EXTRA,)))
37777db96d56Sopenharmony_ci
37787db96d56Sopenharmony_ci        self.assertEqual(b, zipfile._strip_extra(a+a+b, (self.ZIP64_EXTRA,)))
37797db96d56Sopenharmony_ci        self.assertEqual(b, zipfile._strip_extra(a+b+a, (self.ZIP64_EXTRA,)))
37807db96d56Sopenharmony_ci        self.assertEqual(b, zipfile._strip_extra(b+a+a, (self.ZIP64_EXTRA,)))
37817db96d56Sopenharmony_ci
37827db96d56Sopenharmony_ci    def test_too_short(self):
37837db96d56Sopenharmony_ci        self.assertEqual(b"", zipfile._strip_extra(b"", (self.ZIP64_EXTRA,)))
37847db96d56Sopenharmony_ci        self.assertEqual(b"z", zipfile._strip_extra(b"z", (self.ZIP64_EXTRA,)))
37857db96d56Sopenharmony_ci        self.assertEqual(
37867db96d56Sopenharmony_ci            b"zz", zipfile._strip_extra(b"zz", (self.ZIP64_EXTRA,)))
37877db96d56Sopenharmony_ci        self.assertEqual(
37887db96d56Sopenharmony_ci            b"zzz", zipfile._strip_extra(b"zzz", (self.ZIP64_EXTRA,)))
37897db96d56Sopenharmony_ci
37907db96d56Sopenharmony_ci
37917db96d56Sopenharmony_ciif __name__ == "__main__":
37927db96d56Sopenharmony_ci    unittest.main()
3793