| ... | @@ -638,3 +638,85 @@ pub fn extract(dest: Io.Dir, fr: *File.Reader, options: ExtractOptions) !void { | ... | @@ -638,3 +638,85 @@ pub fn extract(dest: Io.Dir, fr: *File.Reader, options: ExtractOptions) !void { |
| 638 | } | 638 | } |
| 639 | } | 639 | } |
| 640 | } | 640 | } |
| | 641 | |
| | 642 | const testing = std.testing; |
| | 643 | |
| | 644 | test "extractTo" { |
| | 645 | const io = testing.io; |
| | 646 | var tmp = testing.tmpDir(.{}); |
| | 647 | defer tmp.cleanup(); |
| | 648 | |
| | 649 | try tmp.dir.writeFile(io, .{ |
| | 650 | .sub_path = "test.zip", |
| | 651 | .data = @embedFile("zip/testdata/test.zip"), |
| | 652 | }); |
| | 653 | |
| | 654 | var file = try tmp.dir.openFile(io, "test.zip", .{}); |
| | 655 | defer file.close(io); |
| | 656 | var read_buf: [512]u8 = undefined; |
| | 657 | var reader = file.reader(io, &read_buf); |
| | 658 | |
| | 659 | const Expected = struct { |
| | 660 | contents: []const u8, |
| | 661 | compression: CompressionMethod, |
| | 662 | }; |
| | 663 | const expected_map = std.StaticStringMap(Expected).initComptime(.{ |
| | 664 | .{ "deflate.txt", Expected{ .contents = "aaaaaaaaaaaaaaaaaaaaaaaa\n", .compression = .deflate } }, |
| | 665 | .{ "store.txt", Expected{ .contents = "hello world\n", .compression = .store } }, |
| | 666 | .{ "dir/", Expected{ .contents = "", .compression = .store } }, |
| | 667 | }); |
| | 668 | |
| | 669 | var iter = try Iterator.init(&reader); |
| | 670 | var num_entries: usize = 0; |
| | 671 | while (try iter.next()) |entry| { |
| | 672 | var filename_buf: [256]u8 = undefined; |
| | 673 | const filename = try entry.getFilename(&reader, &filename_buf, .{}); |
| | 674 | const expected = expected_map.get(filename) orelse { |
| | 675 | std.debug.print("found unexpected filename: {f}\n", .{std.ascii.hexEscape(filename, .lower)}); |
| | 676 | return error.UnexpectedFilename; |
| | 677 | }; |
| | 678 | var buf: [256]u8 = undefined; |
| | 679 | var w: Writer = .fixed(&buf); |
| | 680 | try entry.extractTo(&reader, &w); |
| | 681 | try testing.expectEqualStrings(expected.contents, w.buffered()); |
| | 682 | try testing.expectEqual(expected.compression, entry.compression_method); |
| | 683 | num_entries += 1; |
| | 684 | } |
| | 685 | try testing.expectEqual(expected_map.kvs.len, num_entries); |
| | 686 | } |
| | 687 | |
| | 688 | test "output buffers too small" { |
| | 689 | const io = testing.io; |
| | 690 | var tmp = testing.tmpDir(.{}); |
| | 691 | defer tmp.cleanup(); |
| | 692 | |
| | 693 | try tmp.dir.writeFile(io, .{ |
| | 694 | .sub_path = "test.zip", |
| | 695 | .data = @embedFile("zip/testdata/test.zip"), |
| | 696 | }); |
| | 697 | |
| | 698 | var file = try tmp.dir.openFile(io, "test.zip", .{}); |
| | 699 | defer file.close(io); |
| | 700 | var read_buf: [512]u8 = undefined; |
| | 701 | var reader = file.reader(io, &read_buf); |
| | 702 | |
| | 703 | var iter = try Iterator.init(&reader); |
| | 704 | var num_entries: usize = 0; |
| | 705 | while (try iter.next()) |entry| { |
| | 706 | try testing.expectError( |
| | 707 | error.ZipInsufficientBuffer, |
| | 708 | entry.getFilename(&reader, &.{}, .{}), |
| | 709 | ); |
| | 710 | |
| | 711 | if (entry.uncompressed_size <= 1) continue; |
| | 712 | |
| | 713 | var buf: [1]u8 = undefined; |
| | 714 | var w: Writer = .fixed(&buf); |
| | 715 | try testing.expectError( |
| | 716 | error.WriteFailed, |
| | 717 | entry.extractTo(&reader, &w), |
| | 718 | ); |
| | 719 | num_entries += 1; |
| | 720 | } |
| | 721 | try std.testing.expect(num_entries > 0); |
| | 722 | } |