|
10 | 10 | from manage.logging import LOGGER |
11 | 11 |
|
12 | 12 |
|
| 13 | +@pytest.mark.parametrize("suffix", [".zip", ".nupkg"]) |
| 14 | +@pytest.mark.parametrize("repair", [False, True]) |
| 15 | +def test_extract_package_streaming(tmp_path, monkeypatch, suffix, repair): |
| 16 | + """Extract in bounded reads while preserving overwrite and repair behavior.""" |
| 17 | + import zipfile |
| 18 | + |
| 19 | + package = tmp_path / ("package" + suffix) |
| 20 | + prefix = tmp_path / "install" |
| 21 | + prefix.mkdir() |
| 22 | + existing = prefix / "existing.txt" |
| 23 | + existing.write_bytes(b"original") |
| 24 | + chunk_size = 10 * 1024 * 1024 |
| 25 | + data = bytes(range(256)) * (chunk_size // 256 + 1) |
| 26 | + archive_prefix = "tools/" if suffix == ".nupkg" else "" |
| 27 | + with zipfile.ZipFile(package, "w", zipfile.ZIP_DEFLATED) as zf: |
| 28 | + zf.writestr(archive_prefix + "nested/data.bin", data) |
| 29 | + zf.writestr(archive_prefix + "empty.txt", b"") |
| 30 | + zf.writestr(archive_prefix + "existing.txt", b"replacement") |
| 31 | + if suffix == ".nupkg": |
| 32 | + zf.writestr("metadata.txt", b"ignored") |
| 33 | + |
| 34 | + reads = [] |
| 35 | + original_read = zipfile.ZipExtFile.read |
| 36 | + |
| 37 | + def bounded_read(self, n=-1): |
| 38 | + assert n == chunk_size |
| 39 | + result = original_read(self, n) |
| 40 | + if self.name == archive_prefix + "nested/data.bin": |
| 41 | + reads.append(len(result)) |
| 42 | + return result |
| 43 | + |
| 44 | + monkeypatch.setattr(zipfile.ZipExtFile, "read", bounded_read) |
| 45 | + progress = [] |
| 46 | + IC.extract_package(package, prefix, calculate_dest=Path, |
| 47 | + on_progress=progress.append, repair=repair) |
| 48 | + assert (prefix / "nested/data.bin").read_bytes() == data |
| 49 | + assert (prefix / "empty.txt").read_bytes() == b"" |
| 50 | + assert existing.read_bytes() == (b"replacement" if repair else b"original") |
| 51 | + assert not (prefix / "metadata.txt").exists() |
| 52 | + assert reads == [chunk_size, 256, 0] |
| 53 | + assert progress[0] == 0 |
| 54 | + assert 100 in progress |
| 55 | + assert (None in progress) == (not repair) |
| 56 | + |
| 57 | + |
13 | 58 | def test_print_cli_shortcuts(patched_installs, assert_log, monkeypatch, tmp_path): |
14 | 59 | class Cmd: |
15 | 60 | scratch = {} |
|
0 commit comments