Ctrl K
ComunidadGuías…

Nostos.Backend.Tests/Portability/PortableZipAdapterTests.cs

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
using System.Buffers.Binary;
using System.Diagnostics;
using System.IO.Compression;
using System.Text;
using System.Reflection;
using Nostos.Backend.Services.Portability;
using Xunit;
using Xunit.Abstractions;

namespace Nostos.Backend.Tests.Portability;

public sealed class PortableZipAdapterTests(ITestOutputHelper output)
{
    private static PortableArchiveBufferBudget Budget() => new(PortableArchiveLimits.MaxExplicitBufferBytes);
    private static readonly DateTimeOffset Timestamp = new(2020, 1, 2, 3, 4, 6, TimeSpan.Zero);

    [Theory]
    [InlineData(31, CompressionLevel.NoCompression, 1, false)]
    [InlineData(4 * 1024 * 1024, CompressionLevel.NoCompression, 1, false)]
    [InlineData(31, CompressionLevel.Optimal, 1, false)]
    [InlineData(2 * 1024 * 1024, CompressionLevel.Optimal, 1, false)]
    [InlineData(4 * 1024 * 1024, CompressionLevel.Optimal, 1, false)]
    [InlineData(2 * 1024 * 1024, CompressionLevel.Optimal, 1, true)]
    [InlineData(1, CompressionLevel.NoCompression, 2000, false)]
    [InlineData(1, CompressionLevel.NoCompression, 20000, false)]
    public async Task Writer_is_byte_identical_to_native_with_no_physical_sync_io(
        int size, CompressionLevel compression, int count, bool compressible)
    {
        var clock = Stopwatch.StartNew();
        var payload = Payload(size, compressible);
        var budget = Budget();
        using var real = new CountingSink();
        var adapter = new BoundedSynchronousCaptureSink(real, budget);
        await WriteZipAsync(adapter, payload, compression, count);
        // Native DisposeAsync may itself flush asynchronously, draining captured metadata.
        await adapter.CompleteAsync();
        await adapter.CompleteAsync();
        var bytes = real.ToArray();
        using var reference = new CountingSink(allowSync: true);
        await WriteZipAsync(reference, payload, compression, count);
        Assert.Equal(reference.ToArray(), bytes);
        Assert.True(reference.SyncCalls > 0);
        Assert.Equal(0, real.SyncCalls);
        Assert.Equal(bytes.LongLength, adapter.BytesWritten);
        Assert.InRange(adapter.SynchronousHighWaterBytes, 1, PortableArchiveLimits.MaxSynchronousZipWriteBufferBytes - 1);
        using (var archive = new ZipArchive(new MemoryStream(bytes), ZipArchiveMode.Read))
        {
            Assert.Equal(count, archive.Entries.Count);
            foreach (var entry in archive.Entries)
            {
                using var input = entry.Open();
                using var contents = new MemoryStream();
                input.CopyTo(contents);
                Assert.Equal(payload, contents.ToArray());
            }
        }
        output.WriteLine($"writer entries={count}, payload={size}, compression={compression}, pending high-water={adapter.SynchronousHighWaterBytes}, max sync write={adapter.MaxSingleSynchronousWriteBytes}, allocated high-water={budget.HighWaterBytes}, elapsed={clock.Elapsed.TotalSeconds:F3}s");
        await adapter.DisposeAsync();
        Assert.Equal(0, budget.CurrentBytes);
    }

    [Theory]
    [InlineData(false)]
    [InlineData(true)]
    public async Task Writer_max_data_deflate_purge_stays_bounded(bool compressible)
    {
        // Generated in 1 MiB chunks; no archive-sized capture or media-sized test input.
        var budget = Budget();
        using var destination = new CountingSink(discard: true);
        await using var sink = new BoundedSynchronousCaptureSink(destination, budget);
        var payload = Payload(1024 * 1024, compressible);
        await using (var archive = await ZipArchive.CreateAsync(sink, ZipArchiveMode.Create, true, null))
        {
            await using var entry = await archive.CreateEntry("data/library.json", CompressionLevel.Optimal).OpenAsync();
            for (long written = 0; written < PortableArchiveLimits.MaxDataBytes; written += payload.Length)
                await entry.WriteAsync(payload);
        }
        await sink.CompleteAsync();
        Assert.Equal(0, destination.SyncCalls);
        Assert.InRange(sink.SynchronousHighWaterBytes, 1, PortableArchiveLimits.MaxSynchronousZipWriteBufferBytes - 1);
        output.WriteLine($"64 MiB deflate compressible={compressible}: pending={sink.SynchronousHighWaterBytes}, single={sink.MaxSingleSynchronousWriteBytes}, budget={budget.HighWaterBytes}");
        await sink.DisposeAsync();
        Assert.Equal(0, budget.CurrentBytes);
    }

    [Fact]
    public async Task Writer_orders_all_sync_and_async_overloads_and_flushes()
    {
        var budget = Budget();
        using var real = new CountingSink();
        var sink = new BoundedSynchronousCaptureSink(real, budget);
        sink.Write(new byte[] { 1 }, 0, 1);
        sink.WriteByte(2);
        sink.Flush();
        Assert.Equal(0, real.AsyncCalls);
        await sink.WriteAsync(new byte[] { 3 }, 0, 1, CancellationToken.None);
        sink.Write(new byte[] { 4 }.AsSpan());
        await sink.FlushAsync(CancellationToken.None);
        sink.WriteByte(5);
        await sink.WriteAsync(new byte[] { 6 }.AsMemory());
        sink.WriteByte(7);
        await sink.DisposeAsync();
        Assert.Equal(new byte[] { 1, 2, 3, 4, 5, 6, 7 }, real.ToArray());
        Assert.Equal(0, real.SyncCalls);
        Assert.Equal(0, budget.CurrentBytes);
    }

    [Fact]
    public async Task Writer_cap_overflow_poisoning_prevents_completion_or_retry()
    {
        var budget = Budget();
        using var real = new CountingSink();
        var sink = new BoundedSynchronousCaptureSink(real, budget);
        sink.Write(new byte[PortableArchiveLimits.MaxSynchronousZipWriteBufferBytes]);
        AssertCode("zip_sync_buffer_exceeded", () => sink.WriteByte(1));
        Assert.True(sink.IsPoisoned);
        await AssertCodeAsync("zip_sink_poisoned", () => sink.CompleteAsync());
        AssertCode("zip_sink_poisoned", () => sink.WriteByte(1));
        Assert.Equal(0, real.AsyncCalls);
        Assert.Equal(0, real.SyncCalls);
        await sink.DisposeAsync();
        Assert.Equal(0, budget.CurrentBytes);
    }

    [Fact]
    public void Writer_sync_dispose_with_pending_bytes_errors_without_io()
    {
        var budget = Budget();
        using var real = new CountingSink();
        var sink = new BoundedSynchronousCaptureSink(real, budget, leaveOpen: false);
        sink.WriteByte(1);
        AssertCode("zip_sync_dispose_pending", sink.Dispose);
        Assert.True(sink.IsPoisoned);
        Assert.Equal(0, real.AsyncCalls);
        Assert.Equal(0, real.SyncCalls);
        Assert.Equal(0, real.AsyncDisposals);
        Assert.Equal(0, budget.CurrentBytes);
    }

    [Theory]
    [InlineData("write")]
    [InlineData("flush")]
    [InlineData("complete")]
    public async Task Writer_cancellation_poisoning_never_reports_success(string operation)
    {
        var budget = Budget();
        using var real = new CountingSink();
        var sink = new BoundedSynchronousCaptureSink(real, budget);
        sink.WriteByte(1);
        using var cts = new CancellationTokenSource();
        cts.Cancel();
        await Assert.ThrowsAnyAsync<OperationCanceledException>(() => operation switch
        {
            "write" => sink.WriteAsync(new byte[] { 2 }.AsMemory(), cts.Token).AsTask(),
            "flush" => sink.FlushAsync(cts.Token),
            _ => sink.CompleteAsync(cts.Token),
        });
        Assert.True(sink.IsPoisoned);
        await AssertCodeAsync("zip_sink_poisoned", () => sink.CompleteAsync());
        Assert.Equal(0, real.AsyncCalls);
        Assert.Equal(0, real.SyncCalls);
        await sink.DisposeAsync();
        Assert.Equal(0, budget.CurrentBytes);
    }

    [Theory]
    [InlineData(false)]
    [InlineData(true)]
    public async Task Writer_failed_drain_or_flush_poisoning_never_retries(bool failFlush)
    {
        var budget = Budget();
        using var real = new CountingSink { FailWrite = !failFlush, FailFlush = failFlush };
        var sink = new BoundedSynchronousCaptureSink(real, budget, leaveOpen: false);
        sink.WriteByte(1);
        await Assert.ThrowsAsync<IOException>(() => sink.CompleteAsync());
        Assert.True(sink.IsPoisoned);
        var calls = real.AsyncCalls;
        await AssertCodeAsync("zip_sink_poisoned", () => sink.CompleteAsync());
        Assert.Equal(calls, real.AsyncCalls);
        Assert.Equal(0, real.SyncCalls);
        await sink.DisposeAsync();
        Assert.Equal(1, real.AsyncDisposals);
        Assert.Equal(0, budget.CurrentBytes);
    }

    [Theory]
    [InlineData(false, CompressionLevel.NoCompression)]
    [InlineData(true, CompressionLevel.NoCompression)]
    [InlineData(false, CompressionLevel.Optimal)]
    [InlineData(true, CompressionLevel.Optimal)]
    public async Task Reader_first_native_index_is_memory_only_and_entries_are_async(bool descriptor, CompressionLevel compression)
    {
        var payload = Payload(2 * 1024 * 1024, false);
        var bytes = await NativeZipAsync(payload, compression, descriptor);
        using var physical = new CountingReadStream(bytes);
        await using var source = Source(physical, shortReads: 137);
        var budget = Budget();
        var layout = await PortableZipTailLocator.LocateAsync(source, budget);
        using var tail = await budget.RentAsync(layout.PrefetchLength, CancellationToken.None);
        await PortableZipMetadata.ReadExactlyAsync(source, layout.CentralDirectoryOffset, tail.Memory, CancellationToken.None);
        await using var cache = new PortableArchiveRangeCache(source, budget);
        await using var stream = new PrefetchedZipTailSourceStream(source, layout.CentralDirectoryOffset, tail.Memory, cache);
        await using var archive = await ZipArchive.CreateAsync(stream, ZipArchiveMode.Read, true, null);
        var readsBeforeIndex = physical.AsyncCalls;
        Assert.Single(archive.Entries);
        Assert.Equal(readsBeforeIndex, physical.AsyncCalls);
        Assert.False(cache.TryRead(0, new byte[30], out _)); // Initial EOCD probing may warm tail-adjacent pages, never the local header.
        await using var entry = await archive.Entries[0].OpenAsync();
        using var contents = new MemoryStream();
        await entry.CopyToAsync(contents);
        Assert.Equal(payload, contents.ToArray());
        Assert.True(physical.AsyncCalls > readsBeforeIndex);
        Assert.Equal(0, physical.SyncCalls);
        output.WriteLine($"reader tail={tail.Length}, tail allocation={tail.AccountedBytes}, range cache high-water={cache.HighWaterBytes}, total budget high-water={budget.HighWaterBytes}");
        await cache.DisposeAsync();
        tail.Dispose();
        Assert.Equal(0, budget.CurrentBytes);
    }

    [Fact]
    public async Task Writer_to_validated_reader_roundtrip_matches_every_entry()
    {
        var payload = Payload(2 * 1024 * 1024, false);
        using var real = new CountingSink();
        var writerBudget = Budget();
        await using (var sink = new BoundedSynchronousCaptureSink(real, writerBudget))
        {
            await WriteZipAsync(sink, payload, CompressionLevel.Optimal, 3);
            await sink.CompleteAsync();
        }
        Assert.Equal(0, writerBudget.CurrentBytes);
        using var physical = new CountingReadStream(real.ToArray());
        await using var source = Source(physical);
        var budget = Budget();
        await using (var reader = await PortableArchiveZipReader.OpenAsync(source, budget))
        {
            var calls = physical.AsyncCalls;
            Assert.Equal(3, reader.Archive.Entries.Count);
            Assert.Equal(calls, physical.AsyncCalls);
            AssertNativeLayout(reader);
            foreach (var item in reader.Archive.Entries)
            {
                await using var entry = await item.OpenAsync();
                AssertNativeDataOffset(reader, item);
                using var contents = new MemoryStream();
                await entry.CopyToAsync(contents);
                Assert.Equal(payload, contents.ToArray());
            }
            output.WriteLine($"factory reader: tail={reader.PrefetchedTailBytes}, tail allocation={reader.PrefetchedTailAllocatedBytes}, range cache high-water={reader.RangeCacheHighWaterBytes}, budget={budget.HighWaterBytes}");
        }
        Assert.Equal(0, physical.SyncCalls);
        Assert.Equal(0, budget.CurrentBytes);
    }

    [Theory]
    [InlineData(false)]
    [InlineData(true)]
    public async Task Reader_accepts_native_stored_and_deflated_without_descriptors(bool deflated)
    {
        var bytes = await NativeZipAsync(Payload(400, false), deflated ? CompressionLevel.Optimal : CompressionLevel.NoCompression, false);
        await ReadValidatedAsync(bytes, Payload(400, false));
    }

    [Fact]
    public async Task Reader_sync_cache_miss_does_no_io_and_preserves_position()
    {
        var bytes = await NativeZipAsync(Payload(1024, false), CompressionLevel.NoCompression, false);
        using var physical = new CountingReadStream(bytes);
        await using var source = Source(physical);
        var budget = Budget();
        var layout = await PortableZipTailLocator.LocateAsync(source, budget);
        using var tail = await budget.RentAsync(layout.PrefetchLength, CancellationToken.None);
        await PortableZipMetadata.ReadExactlyAsync(source, layout.CentralDirectoryOffset, tail.Memory, CancellationToken.None);
        await using var cache = new PortableArchiveRangeCache(source, budget);
        using var stream = new PrefetchedZipTailSourceStream(source, layout.CentralDirectoryOffset, tail.Memory, cache);
        var calls = physical.AsyncCalls;
        AssertCode("zip_sync_cache_miss", () => stream.ReadByte());
        AssertCode("zip_sync_cache_miss", () => { _ = stream.Read(new byte[1].AsSpan()); });
        Assert.Equal(0, stream.Position);
        Assert.Equal(calls, physical.AsyncCalls);
        Assert.Equal(0, physical.SyncCalls);
        var first = new byte[1];
        Assert.Equal(1, await stream.ReadAsync(first, 0, 1));
        stream.Position = 0;
        Assert.Equal(bytes[0], stream.ReadByte()); // Resident pages are allowed, never populated synchronously.
        stream.Seek(-1, SeekOrigin.End);
        Assert.Equal(bytes[^1], stream.ReadByte());
        Assert.Equal(-1, stream.ReadByte());
        stream.Seek(10, SeekOrigin.End);
        Assert.Equal(0, stream.Read(new byte[1]));
        Assert.Throws<IOException>(() => stream.Seek(-1, SeekOrigin.Begin));
        stream.Position = long.MaxValue;
        Assert.Throws<IOException>(() => stream.Seek(1, SeekOrigin.Current));
        await cache.DisposeAsync(); tail.Dispose();
        Assert.Equal(0, budget.CurrentBytes);
    }

    [Theory]
    [InlineData("no_eocd", "invalid_zip")]
    [InlineData("comment", "invalid_zip")]
    [InlineData("directory_cap", "invalid_zip")]
    [InlineData("entry_cap", "too_many_entries")]
    [InlineData("directory_offset", "invalid_zip")]
    [InlineData("directory_overlap", "invalid_zip")]
    [InlineData("truncated_entry", "invalid_zip")]
    [InlineData("name_overrun", "invalid_zip")]
    [InlineData("local_offset", "invalid_zip")]
    [InlineData("overlap", "invalid_zip")]
    [InlineData("encrypted", "invalid_zip")]
    [InlineData("multi_disk", "invalid_zip")]
    [InlineData("entry_multi_disk", "invalid_zip")]
    [InlineData("method", "invalid_zip")]
    [InlineData("duplicate_path", "duplicate_path")]
    [InlineData("duplicate_offset", "invalid_zip")]
    [InlineData("unsafe_path", "unsafe_archive_path")]
    [InlineData("missing_zip64_extra", "invalid_zip")]
    [InlineData("malformed_extra", "invalid_zip")]
    [InlineData("local_method", "invalid_zip")]
    [InlineData("local_name", "invalid_zip")]
    [InlineData("local_sizes", "invalid_zip")]
    [InlineData("descriptor", "invalid_zip")]
    public async Task Hostile_archive_is_rejected_before_large_allocation(string attack, string code)
    {
        var bytes = await NativeZipAsync(Payload(40, false), CompressionLevel.NoCompression, true, 2);
        var eocd = bytes.Length - 22;
        var cd = (int)U32(bytes, eocd + 16);
        var second = cd + 46 + U16(bytes, cd + 28);
        switch (attack)
        {
            case "no_eocd": W32(bytes, eocd, 0); break;
            case "comment": W16(bytes, eocd + 20, ushort.MaxValue); break;
            case "directory_cap": W32(bytes, eocd + 12, PortableArchiveLimits.MaxCentralDirectoryBytes + 1); break;
            case "entry_cap": W16(bytes, eocd + 8, 20001); W16(bytes, eocd + 10, 20001); break;
            case "directory_offset": W32(bytes, eocd + 16, (uint)bytes.Length + 1); break;
            case "directory_overlap": W32(bytes, eocd + 16, (uint)eocd); break;
            case "truncated_entry": W32(bytes, eocd + 12, 45); break;
            case "name_overrun": W16(bytes, cd + 28, ushort.MaxValue); break;
            case "local_offset": W32(bytes, cd + 42, (uint)bytes.Length + 1); break;
            case "overlap": W32(bytes, cd + 20, 80); W32(bytes, cd + 24, 80); break;
            case "encrypted": W16(bytes, cd + 8, 1); break;
            case "multi_disk": W16(bytes, eocd + 4, 1); break;
            case "entry_multi_disk": W16(bytes, cd + 34, 1); break;
            case "method": W16(bytes, cd + 10, 99); break;
            case "duplicate_path": bytes.AsSpan(cd + 46, U16(bytes, cd + 28)).CopyTo(bytes.AsSpan(second + 46)); break;
            case "duplicate_offset": W32(bytes, second + 42, 0); break;
            case "unsafe_path": bytes[cd + 46] = (byte)'/'; break;
            case "missing_zip64_extra": W32(bytes, cd + 24, uint.MaxValue); break;
            case "malformed_extra": W16(bytes, cd + 30, 1); break;
            case "local_method": W16(bytes, 8, 8); break;
            case "local_name": bytes[30] ^= 1; break;
            case "local_sizes": W16(bytes, 6, 0); W16(bytes, cd + 8, 0); break;
            case "descriptor": bytes[30 + U16(bytes, 26) + 40 + 4] ^= 1; break;
        }
        using var physical = new CountingReadStream(bytes);
        await using var source = Source(physical);
        var budget = Budget();
        await AssertCodeAsync(code, async () => { await using var reader = await PortableArchiveZipReader.OpenAsync(source, budget); });
        Assert.Equal(0, physical.SyncCalls);
        Assert.Equal(0, budget.CurrentBytes);
        Assert.True(budget.HighWaterBytes <= 2 * 1024 * 1024);
    }

    [Fact]
    public async Task Source_shorter_than_declared_is_archive_source_truncated()
    {
        var budget = Budget();
        await using var source = new RangePortableArchiveSource(1000, (_, _, _) => ValueTask.FromResult(0));
        await AssertCodeAsync("archive_source_truncated", async () => { await using var reader = await PortableArchiveZipReader.OpenAsync(source, budget); });
        Assert.Equal(0, budget.CurrentBytes);
    }

    [Fact]
    public async Task Over_limit_source_is_rejected_before_read_or_allocation()
    {
        var budget = Budget();
        var calls = 0;
        await using var source = new RangePortableArchiveSource(PortableArchiveLimits.MaxArchiveBytes + 1,
            (_, _, _) => { calls++; throw new InvalidOperationException(); });
        await AssertCodeAsync("archive_too_large", () => PortableZipTailLocator.LocateAsync(source, budget));
        Assert.Equal(0, calls);
        Assert.Equal(0, budget.HighWaterBytes);
    }

    [Fact]
    public void Range_cache_rejects_oversized_page_before_allocation_rounding()
    {
        var source = new RangePortableArchiveSource(10, (_, _, _) => ValueTask.FromResult(0));
        Assert.Throws<ArgumentOutOfRangeException>(() => new PortableArchiveRangeCache(source, Budget(), int.MaxValue));
    }

    [Theory]
    [InlineData(false, false)]
    [InlineData(false, true)]
    [InlineData(true, false)]
    [InlineData(true, true)]
    public async Task Reader_supports_all_four_standard_descriptor_forms(bool zip64, bool signature)
    {
        var payload = Payload(40, false);
        var original = await NativeZipAsync(payload, CompressionLevel.NoCompression, true);
        var cd = (int)U32(original, original.Length - 6);
        var descriptorOffset = cd - 16;
        using var bytes = new MemoryStream();
        bytes.Write(original.AsSpan(0, descriptorOffset));
        using (var writer = new BinaryWriter(bytes, Encoding.UTF8, true))
        {
            if (signature) writer.Write(0x08074b50u);
            writer.Write(U32(original, descriptorOffset + 4));
            if (zip64) { writer.Write((ulong)payload.Length); writer.Write((ulong)payload.Length); }
            else { writer.Write((uint)payload.Length); writer.Write((uint)payload.Length); }
        }
        var newCd = (uint)bytes.Length;
        bytes.Write(original.AsSpan(cd));
        var modified = bytes.ToArray();
        W32(modified, modified.Length - 6, newCd);
        await ReadValidatedAsync(modified, payload);
    }

    [Fact]
    public async Task Reader_rejects_actual_nested_physical_entry_overlap()
    {
        var bytes = await NativeZipAsync(Payload(256, false), CompressionLevel.NoCompression, false, 2);
        var cd = (int)U32(bytes, bytes.Length - 6);
        var secondCd = cd + 46 + U16(bytes, cd + 28);
        var secondLocal = (int)U32(bytes, secondCd + 42);
        var headerLength = 30 + U16(bytes, secondLocal + 26);
        var nestedOffset = 30 + U16(bytes, 26) + 10;
        var nestedHeader = bytes.AsSpan(secondLocal, headerLength).ToArray();
        W32(nestedHeader, 14, 0); W32(nestedHeader, 18, 0); W32(nestedHeader, 22, 0);
        nestedHeader.CopyTo(bytes.AsSpan(nestedOffset));
        W32(bytes, secondCd + 16, 0); W32(bytes, secondCd + 20, 0); W32(bytes, secondCd + 24, 0);
        W32(bytes, secondCd + 42, (uint)nestedOffset);
        var budget = Budget();
        using var physical = new CountingReadStream(bytes);
        await using var source = Source(physical);
        var exception = await Assert.ThrowsAsync<PortableArchiveException>(() => PortableArchiveZipReader.OpenAsync(source, budget));
        Assert.Equal("invalid_zip", exception.Code);
        Assert.Contains("overlap", exception.Message);
        Assert.Equal(0, physical.SyncCalls);
        Assert.Equal(0, budget.CurrentBytes);
    }

    [Theory]
    [InlineData("valid")]
    [InlineData("locator_outside")]
    [InlineData("locator_missing")]
    [InlineData("locator_disk")]
    [InlineData("record_short")]
    [InlineData("record_large")]
    [InlineData("record_overlap")]
    [InlineData("record_disk")]
    [InlineData("count_disagreement")]
    [InlineData("classic_disagreement")]
    [InlineData("unsigned_overflow")]
    [InlineData("directory_cap")]
    [InlineData("entry_cap")]
    [InlineData("directory_outside")]
    [InlineData("tail_gap")]
    public async Task Sparse_zip64_tail_is_bounded_and_validated(string scenario)
    {
        var payload = Payload(40, false);
        var native = await NativeZipAsync(payload, CompressionLevel.NoCompression, false);
        var nativeCd = (int)U32(native, native.Length - 6);
        const long cdOffset = (long)uint.MaxValue + 4096;
        var local = native[..nativeCd];
        var directory = native[nativeCd..^22];
        var tail = Zip64Tail(directory, cdOffset);
        var record = directory.Length;
        var locator = record + 56;
        switch (scenario)
        {
            case "locator_outside": W64(tail, locator + 8, (ulong)(cdOffset + tail.Length)); break;
            case "locator_missing": W32(tail, locator, 0); break;
            case "locator_disk": W32(tail, locator + 4, 1); break;
            case "record_short": W64(tail, record + 4, 43); break;
            case "record_large": W64(tail, record + 4, PortableArchiveLimits.MaxZip64EndRecordBytes); break;
            case "record_overlap": W64(tail, record + 4, 45); break;
            case "record_disk": W32(tail, record + 16, 1); break;
            case "count_disagreement": W64(tail, record + 24, 2); break;
            case "classic_disagreement": W16(tail, tail.Length - 12, 2); break;
            case "unsigned_overflow": W64(tail, record + 48, ulong.MaxValue); break;
            case "directory_cap": W64(tail, record + 40, PortableArchiveLimits.MaxCentralDirectoryBytes + 1); break;
            case "entry_cap": W64(tail, record + 24, 20001); W64(tail, record + 32, 20001); break;
            case "directory_outside": W64(tail, record + 48, (ulong)(cdOffset + tail.Length)); break;
            case "tail_gap": W64(tail, record + 48, (ulong)(cdOffset - PortableArchiveLimits.MaxPrefetchedZipTailBytes)); break;
        }
        var sourceCalls = 0;
        await using var source = SparseSource(local, cdOffset, tail, () => sourceCalls++);
        var budget = Budget();
        if (scenario == "valid")
        {
            await using (var reader = await PortableArchiveZipReader.OpenAsync(source, budget))
            {
                AssertNativeLayout(reader);
                Assert.True(reader.TailLayout.IsZip64);
                Assert.True(reader.TailLayout.CentralDirectoryOffset > uint.MaxValue);
                var calls = sourceCalls;
                Assert.Single(reader.Archive.Entries);
                Assert.Equal(calls, sourceCalls);
                await using var entry = await reader.Archive.Entries[0].OpenAsync();
                using var contents = new MemoryStream();
                await entry.CopyToAsync(contents);
                Assert.Equal(payload, contents.ToArray());
                Assert.True(budget.HighWaterBytes < 3 * 1024 * 1024);
                output.WriteLine($"sparse ZIP64 length={source.Length}, tail={reader.PrefetchedTailBytes}, budget={budget.HighWaterBytes}, source calls={sourceCalls}");
            }
        }
        else
        {
            await AssertCodeAsync(scenario == "entry_cap" ? "too_many_entries" : "invalid_zip",
                () => PortableArchiveZipReader.OpenAsync(source, budget));
            Assert.True(budget.HighWaterBytes < 256 * 1024);
        }
        Assert.Equal(0, budget.CurrentBytes);
    }

    [Theory]
    [InlineData(1)]
    [InlineData(2)]
    [InlineData(3)]
    public async Task Reader_accepts_unchanged_existing_generated_historical_fixtures(int version)
    {
        // Reuse the existing private generator verbatim without widening another slice's test API.
        var method = typeof(PortableMigrationFixtureAndCompatTests).GetMethod("CreateFixtureAsync", BindingFlags.NonPublic | BindingFlags.Static)!;
        var task = (Task)method.Invoke(null, new object[] { $"data{version}.nostos", version })!;
        await task;
        using var fixture = (IDisposable)task.GetType().GetProperty("Result")!.GetValue(task)!;
        var bytes = (byte[])fixture.GetType().GetProperty("Bytes")!.GetValue(fixture)!;
        using var native = new ZipArchive(new MemoryStream(bytes), ZipArchiveMode.Read);
        using var physical = new CountingReadStream(bytes);
        await using var source = Source(physical);
        var budget = Budget();
        await using (var reader = await PortableArchiveZipReader.OpenAsync(source, budget))
        {
            Assert.Equal(native.Entries.Count, reader.Archive.Entries.Count);
            AssertNativeLayout(reader);
            foreach (var item in reader.Archive.Entries)
            {
                using var expected = native.GetEntry(item.FullName)!.Open();
                using var expectedBytes = new MemoryStream();
                await expected.CopyToAsync(expectedBytes);
                await using var actual = await item.OpenAsync();
                AssertNativeDataOffset(reader, item);
                using var actualBytes = new MemoryStream();
                await actual.CopyToAsync(actualBytes);
                Assert.Equal(expectedBytes.ToArray(), actualBytes.ToArray());
            }
        }
        Assert.Equal(0, physical.SyncCalls);
        Assert.Equal(0, budget.CurrentBytes);
    }

    [Fact]
    public async Task Maximum_directory_and_full_range_cache_fit_the_64_mib_budget()
    {
        var native = await NativeZipAsync(Array.Empty<byte>(), CompressionLevel.NoCompression, false, 256);
        var cd = (int)U32(native, native.Length - 6);
        using var directory = new MemoryStream();
        var position = cd;
        for (var i = 0; i < 256; i++)
        {
            var recordLength = 46 + U16(native, position + 28);
            var entry = native.AsSpan(position, recordLength).ToArray();
            var extraLength = 65536 - recordLength;
            W16(entry, 30, (ushort)extraLength);
            directory.Write(entry);
            var extra = new byte[extraLength];
            W16(extra, 0, 0xffff); W16(extra, 2, (ushort)(extraLength - 4));
            directory.Write(extra);
            position += recordLength;
        }
        Assert.Equal(PortableArchiveLimits.MaxCentralDirectoryBytes, directory.Length);
        const long sparseCd = (long)uint.MaxValue + 4096;
        // ZIP64 EOCD is needed only for the sparse offset, not the individual entries.
        var tail = Zip64Tail(directory.ToArray(), sparseCd, 256);
        await using var source = SparseSource(native[..cd], sparseCd, tail);
        var budget = Budget();
        await using (var reader = await PortableArchiveZipReader.OpenAsync(source, budget))
        {
            AssertNativeLayout(reader);
            Assert.Equal(32 * 1024 * 1024, reader.PrefetchedTailAllocatedBytes);
            for (var page = 1; page <= 16; page++)
            {
                reader.Stream.Position = page * 1024L * 1024;
                Assert.Equal(1, await reader.Stream.ReadAsync(new byte[1]));
            }
            Assert.Equal(16 * 1024 * 1024, reader.RangeCacheHighWaterBytes);
            Assert.Equal(48 * 1024 * 1024, budget.HighWaterBytes);
            output.WriteLine($"max reader footprint: logical tail={reader.PrefetchedTailBytes}, tail allocation={reader.PrefetchedTailAllocatedBytes}, range cache={reader.RangeCacheHighWaterBytes}, total={budget.HighWaterBytes}");
        }
        Assert.Equal(0, budget.CurrentBytes);
    }

    [Fact]
    public async Task Reader_cancellation_during_prefetch_and_layout_returns_every_lease()
    {
        var bytes = await NativeZipAsync(Payload(1024, false), CompressionLevel.NoCompression, false);
        foreach (var cancelOnCall in new[] { 1, 3, 4 })
        {
            using var cts = new CancellationTokenSource();
            var calls = 0;
            await using var source = new RangePortableArchiveSource(bytes.Length, (offset, buffer, ct) =>
            {
                if (++calls == cancelOnCall) cts.Cancel();
                ct.ThrowIfCancellationRequested();
                bytes.AsMemory((int)offset, buffer.Length).CopyTo(buffer);
                return ValueTask.FromResult(buffer.Length);
            });
            var budget = Budget();
            await Assert.ThrowsAnyAsync<OperationCanceledException>(() => PortableArchiveZipReader.OpenAsync(source, budget, cts.Token));
            Assert.Equal(0, budget.CurrentBytes);
        }
    }

    private static void W64(byte[] bytes, int offset, ulong value) => BinaryPrimitives.WriteUInt64LittleEndian(bytes.AsSpan(offset), value);
    private static byte[] Zip64Tail(byte[] directory, long cdOffset, int count = 1)
    {
        using var tail = new MemoryStream();
        using (var writer = new BinaryWriter(tail, Encoding.UTF8, true))
        {
            writer.Write(directory);
            writer.Write(0x06064b50u); writer.Write(44UL); writer.Write((ushort)45); writer.Write((ushort)45);
            writer.Write(0u); writer.Write(0u); writer.Write((ulong)count); writer.Write((ulong)count);
            writer.Write((ulong)directory.Length); writer.Write((ulong)cdOffset);
            writer.Write(0x07064b50u); writer.Write(0u); writer.Write((ulong)(cdOffset + directory.Length)); writer.Write(1u);
            writer.Write(0x06054b50u); writer.Write((ushort)0); writer.Write((ushort)0);
            writer.Write(ushort.MaxValue); writer.Write(ushort.MaxValue); writer.Write(uint.MaxValue); writer.Write(uint.MaxValue); writer.Write((ushort)0);
        }
        return tail.ToArray();
    }
    private static RangePortableArchiveSource SparseSource(byte[] local, long tailOffset, byte[] tail, Action? onRead = null) =>
        new(tailOffset + tail.Length, (offset, buffer, ct) =>
        {
            ct.ThrowIfCancellationRequested();
            onRead?.Invoke();
            buffer.Span.Clear();
            CopyOverlap(local, 0, offset, buffer.Span);
            CopyOverlap(tail, tailOffset, offset, buffer.Span);
            return ValueTask.FromResult(buffer.Length);
        });
    private static void CopyOverlap(byte[] bytes, long start, long offset, Span<byte> buffer)
    {
        var from = Math.Max(start, offset);
        var to = Math.Min(start + bytes.Length, offset + buffer.Length);
        if (from < to) bytes.AsSpan((int)(from - start), (int)(to - from)).CopyTo(buffer[(int)(from - offset)..]);
    }

    [Theory]
    [InlineData("valid")]
    [InlineData("truncated")]
    [InlineData("missing_value")]
    [InlineData("overflow")]
    [InlineData("duplicate")]
    [InlineData("local_extra")]
    public async Task Zip64_entry_replacement_fields_are_validated(string scenario)
    {
        var payload = Payload(40, false);
        var bytes = await NativeZipAsync(payload, CompressionLevel.NoCompression, false);
        var cd = (int)U32(bytes, bytes.Length - 6);
        var nameLength = U16(bytes, cd + 28);
        var header = bytes.AsSpan(cd, 46 + nameLength).ToArray();
        W32(header, 20, uint.MaxValue); W32(header, 24, uint.MaxValue); W32(header, 42, uint.MaxValue);
        var extra = new byte[28];
        W16(extra, 0, 1); W16(extra, 2, 24);
        W64(extra, 4, (ulong)payload.Length); W64(extra, 12, (ulong)payload.Length); W64(extra, 20, 0);
        switch (scenario)
        {
            case "truncated": W16(extra, 2, 25); break;
            case "missing_value": extra = extra[..20]; W16(extra, 2, 16); break;
            case "overflow": W64(extra, 20, ulong.MaxValue); break;
            case "duplicate": extra = extra.Concat(extra).ToArray(); break;
            case "local_extra": W16(bytes, 28, 1); break;
        }
        W16(header, 30, (ushort)extra.Length);
        using var buffer = new MemoryStream();
        buffer.Write(bytes.AsSpan(0, cd)); buffer.Write(header); buffer.Write(extra); buffer.Write(bytes.AsSpan(bytes.Length - 22));
        var modified = buffer.ToArray();
        W32(modified, modified.Length - 10, (uint)(header.Length + extra.Length));
        if (scenario == "valid") await ReadValidatedAsync(modified, payload);
        else
        {
            using var physical = new CountingReadStream(modified);
            await using var source = Source(physical);
            var budget = Budget();
            await AssertCodeAsync("invalid_zip", () => PortableArchiveZipReader.OpenAsync(source, budget));
            Assert.Equal(0, budget.CurrentBytes);
            Assert.Equal(0, physical.SyncCalls);
        }
    }

    [Fact]
    public async Task Maximum_legal_comment_is_accepted_with_bounded_tail()
    {
        var bytes = await NativeZipAsync(Payload(40, false), CompressionLevel.NoCompression, false);
        W16(bytes, bytes.Length - 2, ushort.MaxValue);
        await ReadValidatedAsync(bytes.Concat(new byte[ushort.MaxValue]).ToArray(), Payload(40, false));
    }

    [Fact]
    public async Task Writer_sync_dispose_never_disposes_owned_sink_but_async_cleanup_does()
    {
        var budget = Budget();
        using var real = new CountingSink();
        var sink = new BoundedSynchronousCaptureSink(real, budget, leaveOpen: false);
        sink.Dispose();
        Assert.Equal(0, real.AsyncDisposals);
        Assert.Equal(0, real.SyncCalls);
        await sink.DisposeAsync();
        await sink.DisposeAsync();
        Assert.Equal(1, real.AsyncDisposals);
        Assert.Equal(0, budget.CurrentBytes);
    }

    [Fact]
    public async Task Writer_partial_drain_failure_is_not_replayed()
    {
        var budget = Budget();
        using var real = new CountingSink { PartialWriteFailure = true };
        var sink = new BoundedSynchronousCaptureSink(real, budget);
        sink.Write(new byte[] { 1, 2, 3 });
        await Assert.ThrowsAsync<IOException>(() => sink.WriteAsync(new byte[] { 4 }.AsMemory()).AsTask());
        Assert.Equal(new byte[] { 1 }, real.ToArray());
        Assert.True(sink.IsPoisoned);
        Assert.Equal(0, sink.BytesWritten);
        await AssertCodeAsync("zip_sink_poisoned", () => sink.CompleteAsync());
        await sink.DisposeAsync();
        Assert.Equal(new byte[] { 1 }, real.ToArray());
        Assert.Equal(0, real.SyncCalls);
        Assert.Equal(0, budget.CurrentBytes);
    }

    [Fact]
    public async Task Reader_premature_eof_after_tail_prefetch_releases_tail_and_cache()
    {
        var bytes = await NativeZipAsync(Payload(1024, false), CompressionLevel.NoCompression, false);
        var cd = U32(bytes, bytes.Length - 6);
        var calls = 0;
        await using var source = new RangePortableArchiveSource(bytes.Length, (offset, buffer, _) =>
        {
            calls++;
            // Discovery and prefetch succeed; local-header page retrieval ends prematurely.
            if (calls >= 4 && offset < cd) return ValueTask.FromResult(0);
            bytes.AsMemory((int)offset, buffer.Length).CopyTo(buffer);
            return ValueTask.FromResult(buffer.Length);
        });
        var budget = Budget();
        await AssertCodeAsync("archive_source_truncated", () => PortableArchiveZipReader.OpenAsync(source, budget));
        Assert.Equal(0, budget.CurrentBytes);
    }

    [Fact]
    public async Task Dual_eocd_offset_differential_is_rejected_before_factory_returns()
    {
        var (bytes, firstCd, secondCd, secondLocal) = await DualViewAsync(true, false);
        using var native = new ZipArchive(new MemoryStream(bytes), ZipArchiveMode.Read);
        Assert.Equal(secondCd, NativeField<long>(native, "_centralDirectoryStart"));
        Assert.Equal(secondLocal, NativeField<long>(Assert.Single(native.Entries), "_offsetOfLocalHeader"));
        using var physical = new CountingReadStream(bytes);
        await using var source = Source(physical);
        var budget = Budget();
        await AssertCodeAsync("invalid_zip", () => PortableArchiveZipReader.OpenAsync(source, budget));
        Assert.Equal(0, budget.CurrentBytes);
        Assert.Equal(0, physical.SyncCalls);
        using var entry = native.Entries[0].Open();
        using var contents = new MemoryStream();
        entry.CopyTo(contents);
        Assert.Equal(Enumerable.Repeat((byte)'B', 40).ToArray(), contents.ToArray());
        output.WriteLine($"Closed EOCD differential: legacy validated CD={firstCd}, local=0; real runtime selects CD={secondCd}, local={secondLocal}; factory rejects invalid_zip before returning.");
    }

    [Fact]
    public async Task Surplus_zip64_offset_differential_is_rejected_before_factory_returns()
    {
        var (bytes, cd, alternateLocal) = await SurplusZip64OffsetAsync();
        using var native = new ZipArchive(new MemoryStream(bytes), ZipArchiveMode.Read);
        Assert.Equal(cd, NativeField<long>(native, "_centralDirectoryStart"));
        Assert.Equal(alternateLocal, NativeField<long>(Assert.Single(native.Entries), "_offsetOfLocalHeader"));
        using var physical = new CountingReadStream(bytes);
        await using var source = Source(physical);
        var budget = Budget();
        await AssertCodeAsync("invalid_zip", () => PortableArchiveZipReader.OpenAsync(source, budget));
        Assert.Equal(0, budget.CurrentBytes);
        Assert.Equal(0, physical.SyncCalls);
        output.WriteLine($"Closed ZIP64 surplus differential: CD={cd}, legacy validated local=0, native local={alternateLocal}; factory rejects invalid_zip before returning.");
    }

    private static async Task<(byte[] Bytes, long Cd, long AlternateLocal)> SurplusZip64OffsetAsync()
    {
        var first = await NativeZipAsync(Enumerable.Repeat((byte)'A', 40).ToArray(), CompressionLevel.NoCompression, false);
        var second = await NativeZipAsync(Enumerable.Repeat((byte)'B', 40).ToArray(), CompressionLevel.NoCompression, false);
        var localLength = (int)U32(first, first.Length - 6);
        var central = first.AsSpan(localLength, first.Length - localLength - 22).ToArray();
        W32(central, 42, uint.MaxValue);
        W16(central, 30, 32);
        var extra = new byte[32];
        W16(extra, 0, 1); W16(extra, 2, 28);
        // Only offset is a sentinel: our old parser consumed the first value, while native
        // skips the first two slots for a >=28-byte "all fields" ZIP64 extra.
        W64(extra, 4, 0); W64(extra, 12, 40); W64(extra, 20, (ulong)localLength);
        using var buffer = new MemoryStream();
        buffer.Write(first.AsSpan(0, localLength)); buffer.Write(second.AsSpan(0, localLength));
        var cd = buffer.Length;
        buffer.Write(central); buffer.Write(extra); buffer.Write(first.AsSpan(first.Length - 22));
        var bytes = buffer.ToArray();
        W32(bytes, bytes.Length - 10, (uint)(central.Length + extra.Length));
        W32(bytes, bytes.Length - 6, (uint)cd);
        return (bytes, cd, localLength);
    }

    [Theory]
    [InlineData("outer_eof_inner_short")]
    [InlineData("outer_eof_inner_eof")]
    [InlineData("outer_short_inner_eof")]
    [InlineData("outer_eof_inner_long")]
    [InlineData("signature_in_comment")]
    [InlineData("signature_in_payload")]
    [InlineData("signature_in_directory_comment")]
    [InlineData("signature_in_directory_crc")]
    public async Task Eocd_candidates_are_selected_without_fallback_or_payload_rejection(string scenario)
    {
        byte[] bytes;
        var accepted = scenario is "outer_eof_inner_eof" or "outer_short_inner_eof"
            or "signature_in_payload" or "signature_in_directory_comment" or "signature_in_directory_crc";
        var expectedPayload = scenario.StartsWith("outer_", StringComparison.Ordinal)
            ? Enumerable.Repeat((byte)'B', 40).ToArray() : new byte[64];
        if (scenario.StartsWith("outer_", StringComparison.Ordinal))
        {
            var fixture = await DualViewAsync(scenario != "outer_short_inner_eof", scenario != "outer_eof_inner_short");
            bytes = fixture.Bytes;
            if (scenario == "outer_eof_inner_long")
            {
                W16(bytes, bytes.Length - 32 - 2, 33);
                await Assert.ThrowsAsync<InvalidDataException>(async () =>
                {
                    await using var native = await ZipArchive.CreateAsync(new MemoryStream(bytes), ZipArchiveMode.Read, false, null);
                });
                output.WriteLine("inner comment longer than EOF: native rejects the last candidate; no fallback to the valid outer EOCD");
            }
            else
            {
                await using var native = await ZipArchive.CreateAsync(new MemoryStream(bytes), ZipArchiveMode.Read, false, null);
                Assert.Equal(fixture.SecondCd, NativeField<long>(native, "_centralDirectoryStart"));
                Assert.Equal(fixture.SecondLocal, NativeField<long>(Assert.Single(native.Entries), "_offsetOfLocalHeader"));
                output.WriteLine($"{scenario}: real native selects later CD={fixture.SecondCd}, local={fixture.SecondLocal} regardless of EOF comment validity.");
            }
        }
        else
        {
            var payload = new byte[64];
            if (scenario == "signature_in_payload") W32(payload, 7, 0x06054b50);
            expectedPayload = payload;
            bytes = await NativeZipAsync(payload, CompressionLevel.NoCompression, false);
            var cd = (int)U32(bytes, bytes.Length - 6);
            if (scenario == "signature_in_comment")
            {
                W16(bytes, bytes.Length - 2, 64);
                var comment = new byte[64];
                W32(comment, 0, 0x06054b50);
                bytes = bytes.Concat(comment).ToArray();
            }
            else if (scenario == "signature_in_directory_comment")
            {
                W16(bytes, cd + 32, 64);
                W32(bytes, bytes.Length - 10, U32(bytes, bytes.Length - 10) + 64);
                var comment = new byte[64];
                W32(comment, 0, 0x06054b50);
                bytes = InsertBytes(bytes, bytes.Length - 22, comment);
            }
            else if (scenario == "signature_in_directory_crc")
            {
                W32(bytes, cd + 16, 0x06054b50); W32(bytes, 14, 0x06054b50);
            }
            await using var native = await ZipArchive.CreateAsync(new MemoryStream(bytes), ZipArchiveMode.Read, false, null);
            var nativeCd = NativeField<long>(native, "_centralDirectoryStart");
            Assert.Equal(scenario == "signature_in_comment" ? 0 : cd, nativeCd);
            output.WriteLine($"{scenario}: real native CD={nativeCd}; last eligible EOCD policy ignores earlier signatures.");
        }
        if (accepted)
            await ReadValidatedAsync(bytes, expectedPayload);
        else
        {
            using var physical = new CountingReadStream(bytes);
            await using var source = Source(physical);
            var budget = Budget();
            var exception = await Assert.ThrowsAsync<PortableArchiveException>(() => PortableArchiveZipReader.OpenAsync(source, budget));
            Assert.Equal("invalid_zip", exception.Code);
            Assert.Contains("comment must end exactly at EOF", exception.Message);
            Assert.Equal(1, physical.AsyncCalls); // Reject the selected record, never try an earlier one.
            Assert.Equal(0, physical.SyncCalls);
            Assert.Equal(0, budget.CurrentBytes);
        }
        output.WriteLine($"{scenario}: {(accepted ? "accepted with identical native directory/local/data offsets" : "rejected selected EOCD whose comment misses EOF")}");
    }

    [Theory]
    [InlineData(4090)]
    [InlineData(4092)]
    [InlineData(4094)]
    [InlineData(65500)]
    public async Task Eocd_candidates_across_native_backward_search_blocks_are_rejected(int distanceFromEnd)
    {
        var bytes = await NativeZipAsync(new byte[40], CompressionLevel.NoCompression, false);
        var eocd = bytes.AsSpan(bytes.Length - 22, 22).ToArray();
        const int commentLength = ushort.MaxValue;
        W16(bytes, bytes.Length - 2, commentLength);
        var comment = new byte[commentLength];
        eocd.CopyTo(comment.AsSpan(commentLength - distanceFromEnd));
        bytes = bytes.Concat(comment).ToArray();
        await using var native = await ZipArchive.CreateAsync(new MemoryStream(bytes), ZipArchiveMode.Read, false, null);
        Assert.Equal(string.Empty, native.Comment); // Later fake EOCD declares no comment, despite trailer bytes.
        Assert.Single(native.Entries);
        output.WriteLine($"native selected fake EOCD at EOF-{distanceFromEnd}, including 4096-byte search-block boundaries");
        using var physical = new CountingReadStream(bytes);
        await using var source = Source(physical);
        var budget = Budget();
        await AssertCodeAsync("invalid_zip", () => PortableArchiveZipReader.OpenAsync(source, budget));
        Assert.Equal(0, budget.CurrentBytes);
        Assert.Equal(0, physical.SyncCalls);
    }

    [Theory]
    [InlineData("trailing_bytes")]
    [InlineData("directory_gap")]
    [InlineData("prepended_absolute_offsets")]
    [InlineData("prepended_unadjusted_offsets")]
    [InlineData("short_signature_comment")]
    public async Task Eocd_boundaries_and_prepended_data_have_explicit_policy(string scenario)
    {
        var payload = Payload(40, false);
        var bytes = await NativeZipAsync(payload, CompressionLevel.NoCompression, false);
        var cd = (int)U32(bytes, bytes.Length - 6);
        var accepted = scenario == "prepended_absolute_offsets";
        switch (scenario)
        {
            case "trailing_bytes": bytes = bytes.Concat(new byte[32]).ToArray(); break;
            case "directory_gap": bytes = InsertBytes(bytes, bytes.Length - 22, new byte[16]); break;
            case "short_signature_comment":
                W16(bytes, bytes.Length - 2, 4);
                bytes = bytes.Concat(new byte[] { 0x50, 0x4b, 0x05, 0x06 }).ToArray(); break;
            default:
                var prefix = Encoding.ASCII.GetBytes("Nostos synthetic prefix");
                if (accepted)
                {
                    W32(bytes, cd + 42, (uint)prefix.Length);
                    W32(bytes, bytes.Length - 6, (uint)(cd + prefix.Length));
                }
                bytes = prefix.Concat(bytes).ToArray(); break;
        }
        if (scenario == "short_signature_comment")
        {
            await Assert.ThrowsAsync<InvalidDataException>(async () =>
            {
                await using var native = await ZipArchive.CreateAsync(new MemoryStream(bytes), ZipArchiveMode.Read, false, null);
            });
        }
        else if (scenario == "prepended_unadjusted_offsets")
        {
            await using var native = await ZipArchive.CreateAsync(new MemoryStream(bytes), ZipArchiveMode.Read, false, null);
            Assert.Throws<InvalidDataException>(() => _ = native.Entries);
        }
        else
        {
            await using var native = await ZipArchive.CreateAsync(new MemoryStream(bytes), ZipArchiveMode.Read, false, null);
            Assert.Single(native.Entries);
            Assert.Equal(scenario == "prepended_absolute_offsets" ? cd + "Nostos synthetic prefix".Length : cd,
                NativeField<long>(native, "_centralDirectoryStart"));
        }
        if (accepted) await ReadValidatedAsync(bytes, payload);
        else
        {
            using var physical = new CountingReadStream(bytes);
            await using var source = Source(physical);
            var budget = Budget();
            await AssertCodeAsync("invalid_zip", () => PortableArchiveZipReader.OpenAsync(source, budget));
            Assert.Equal(0, budget.CurrentBytes);
            Assert.Equal(0, physical.SyncCalls);
        }
        output.WriteLine($"{scenario}: {(accepted ? "validated native directory/local/data offsets agree" : "factory rejects invalid_zip before returning")}");
    }

    [Theory]
    [InlineData(false, false)]
    [InlineData(true, false)]
    [InlineData(false, true)]
    [InlineData(true, true)]
    public async Task Native_zip64_selection_and_classic_disagreement_are_proven(bool sentinels, bool disagree)
    {
        var payload = Payload(40, false);
        var normal = await NativeZipAsync(payload, CompressionLevel.NoCompression, false);
        var cd = (int)U32(normal, normal.Length - 6);
        var directory = normal[cd..^22];
        var tail = Zip64Tail(directory, cd);
        if (!sentinels)
        {
            W16(tail, tail.Length - 14, 1); W16(tail, tail.Length - 12, 1);
            W32(tail, tail.Length - 10, (uint)directory.Length); W32(tail, tail.Length - 6, (uint)cd);
        }
        if (disagree) W64(tail, directory.Length + 48, 0);
        var bytes = normal[..cd].Concat(tail).ToArray();
        await using var native = await ZipArchive.CreateAsync(new MemoryStream(bytes), ZipArchiveMode.Read, false, null);
        Assert.Equal(sentinels && disagree ? 0 : cd, NativeField<long>(native, "_centralDirectoryStart"));
        output.WriteLine($"ZIP64: sentinels={sentinels}, disagreement={disagree}, native CD={NativeField<long>(native, "_centralDirectoryStart")}; locator only consulted when native classic sentinel trigger is present.");
        if (!disagree) await ReadValidatedAsync(bytes, payload);
        else
        {
            using var physical = new CountingReadStream(bytes);
            await using var source = Source(physical);
            var budget = Budget();
            await AssertCodeAsync("invalid_zip", () => PortableArchiveZipReader.OpenAsync(source, budget));
            Assert.Equal(0, budget.CurrentBytes);
            Assert.Equal(0, physical.SyncCalls);
        }
    }

    [Fact]
    public async Task Changed_prefetched_eocd_view_is_rejected_before_native_construction()
    {
        var (changed, _, _, _) = await DualViewAsync(true, false);
        var initial = (byte[])changed.Clone();
        W32(initial, changed.Length - 32 - 22, 0); // Hide the second signature during initial discovery.
        var calls = 0;
        await using var source = new RangePortableArchiveSource(initial.Length, (offset, buffer, _) =>
        {
            var view = ++calls >= 3 ? changed : initial;
            view.AsMemory((int)offset, buffer.Length).CopyTo(buffer);
            return ValueTask.FromResult(buffer.Length);
        });
        var budget = Budget();
        await AssertCodeAsync("invalid_zip", () => PortableArchiveZipReader.OpenAsync(source, budget));
        Assert.Equal(3, calls); // Discovery, locator probe, tail prefetch; no local-header/native reads.
        Assert.Equal(0, budget.CurrentBytes);
    }

    [Theory]
    [InlineData("locator_record_offset")]
    [InlineData("record_directory_offset")]
    [InlineData("record_length")]
    public async Task Changed_prefetched_zip64_view_is_rejected_before_native_construction(string mutation)
    {
        var normal = await NativeZipAsync(Payload(40, false), CompressionLevel.NoCompression, false);
        var cd = (int)U32(normal, normal.Length - 6);
        var directory = normal[cd..^22];
        var initial = normal[..cd].Concat(Zip64Tail(directory, cd)).ToArray();
        var changed = (byte[])initial.Clone();
        var record = cd + directory.Length;
        switch (mutation)
        {
            case "locator_record_offset": W64(changed, record + 56 + 8, (ulong)(record + 1)); break;
            case "record_directory_offset": W64(changed, record + 48, 0); break;
            default: W64(changed, record + 4, 45); break;
        }
        var calls = 0;
        await using var source = new RangePortableArchiveSource(initial.Length, (offset, buffer, _) =>
        {
            var view = ++calls >= 4 ? changed : initial;
            view.AsMemory((int)offset, buffer.Length).CopyTo(buffer);
            return ValueTask.FromResult(buffer.Length);
        });
        var budget = Budget();
        await AssertCodeAsync("invalid_zip", () => PortableArchiveZipReader.OpenAsync(source, budget));
        Assert.Equal(4, calls); // Initial search/locator/record, then snapshot; no entry/native construction.
        Assert.Equal(0, budget.CurrentBytes);
    }

    [Theory]
    [InlineData("local_name_length", "invalid_zip")]
    [InlineData("local_name_case", "invalid_zip")]
    [InlineData("local_name_separator", "invalid_zip")]
    [InlineData("local_extra_length_overrun", "invalid_zip")]
    [InlineData("valid_local_extra", null)]
    [InlineData("descriptor_zero_sizes", null)]
    [InlineData("zip64_without_central_sentinel", "invalid_zip")]
    [InlineData("zip64_without_local_sentinel", "invalid_zip")]
    [InlineData("central_sentinel_without_zip64", "invalid_zip")]
    [InlineData("local_sentinel_without_zip64", "invalid_zip")]
    [InlineData("case_duplicate", "duplicate_path")]
    [InlineData("separator_alias", "unsafe_archive_path")]
    public async Task Entry_level_parser_differentials_are_agreed_or_rejected(string scenario, string? code)
    {
        var payload = Payload(40, false);
        var bytes = await NativeZipAsync(payload, CompressionLevel.NoCompression, scenario == "descriptor_zero_sizes",
            scenario is "case_duplicate" or "separator_alias" ? 2 : 1);
        var cd = (int)U32(bytes, bytes.Length - 6);
        switch (scenario)
        {
            case "local_name_length": W16(bytes, 26, (ushort)(U16(bytes, 26) + 1)); break;
            case "local_name_case": bytes[30] = (byte)'M'; break;
            case "local_name_separator": bytes[35] = (byte)'\\'; break;
            case "local_extra_length_overrun": W16(bytes, 28, ushort.MaxValue); break;
            case "valid_local_extra":
                var extra = new byte[] { 0xff, 0xff, 4, 0, 1, 2, 3, 4 };
                W16(bytes, 28, (ushort)extra.Length);
                W32(bytes, bytes.Length - 6, (uint)(cd + extra.Length));
                bytes = InsertBytes(bytes, 30 + U16(bytes, 26), extra); break;
            case "descriptor_zero_sizes":
                Assert.Equal(0u, U32(bytes, 14)); Assert.Equal(0u, U32(bytes, 18)); Assert.Equal(0u, U32(bytes, 22));
                Assert.NotEqual(0, U16(bytes, 6) & 8); break;
            case "zip64_without_central_sentinel":
                var centralExtra = new byte[20]; W16(centralExtra, 0, 1); W16(centralExtra, 2, 16);
                W64(centralExtra, 4, 999); W64(centralExtra, 12, 888);
                W16(bytes, cd + 30, 20); W32(bytes, bytes.Length - 10, U32(bytes, bytes.Length - 10) + 20);
                bytes = InsertBytes(bytes, cd + 46 + U16(bytes, cd + 28), centralExtra); break;
            case "zip64_without_local_sentinel":
                var localExtra = new byte[20]; W16(localExtra, 0, 1); W16(localExtra, 2, 16);
                W64(localExtra, 4, 999); W64(localExtra, 12, 888);
                W16(bytes, 28, 20); W32(bytes, bytes.Length - 6, (uint)(cd + 20));
                bytes = InsertBytes(bytes, 30 + U16(bytes, 26), localExtra); break;
            case "central_sentinel_without_zip64": W32(bytes, cd + 42, uint.MaxValue); break;
            case "local_sentinel_without_zip64": W32(bytes, 22, uint.MaxValue); break;
            default:
                var secondCd = cd + 46 + U16(bytes, cd + 28);
                var secondLocal = (int)U32(bytes, secondCd + 42);
                var firstName = bytes.AsSpan(cd + 46, U16(bytes, cd + 28)).ToArray();
                var otherName = Encoding.UTF8.GetBytes(scenario == "case_duplicate"
                    ? Encoding.UTF8.GetString(firstName).ToUpperInvariant()
                    : Encoding.UTF8.GetString(firstName).Replace('/', '\\'));
                otherName.CopyTo(bytes.AsSpan(secondCd + 46)); otherName.CopyTo(bytes.AsSpan(secondLocal + 30)); break;
        }
        if (code is null) await ReadValidatedAsync(bytes, payload);
        else
        {
            using var physical = new CountingReadStream(bytes);
            await using var source = Source(physical);
            var budget = Budget();
            await AssertCodeAsync(code, () => PortableArchiveZipReader.OpenAsync(source, budget));
            Assert.Equal(0, budget.CurrentBytes);
            Assert.Equal(0, physical.SyncCalls);
        }
        if (code is not null)
        {
            try
            {
                await using var native = await ZipArchive.CreateAsync(new MemoryStream(bytes), ZipArchiveMode.Read, false, null);
                var nativeEntries = native.Entries;
                output.WriteLine($"native {scenario}: CD={NativeField<long>(native, "_centralDirectoryStart")}, local offsets={string.Join(',', nativeEntries.Select(x => NativeField<long>(x, "_offsetOfLocalHeader")))}");
            }
            catch (InvalidDataException) { output.WriteLine($"native {scenario}: rejects metadata before opening an entry"); }
        }
        output.WriteLine($"{scenario}: {(code is null ? "validated native local/data offsets agree" : $"rejected {code} before factory return")}");
    }

    [Theory]
    [InlineData(1)]
    [InlineData(2)]
    [InlineData(3)]
    [InlineData(4)]
    [InlineData(5)]
    [InlineData(7)]
    [InlineData(15)]
    public async Task Canonical_zip64_sentinel_subsets_match_native_local_offsets(int fields)
    {
        var payload = Payload(40, false);
        var bytes = await NativeZipAsync(payload, CompressionLevel.NoCompression, false);
        var cd = (int)U32(bytes, bytes.Length - 6);
        var values = new List<byte>();
        for (var bit = 0; bit < 4; bit++)
        {
            if ((fields & (1 << bit)) == 0) continue;
            if (bit == 3) { W16(bytes, cd + 34, ushort.MaxValue); values.AddRange(new byte[4]); }
            else
            {
                W32(bytes, cd + (bit == 0 ? 24 : bit == 1 ? 20 : 42), uint.MaxValue);
                var value = new byte[8]; W64(value, 0, bit == 2 ? 0UL : 40UL); values.AddRange(value);
            }
        }
        var extra = new byte[4 + values.Count]; W16(extra, 0, 1); W16(extra, 2, (ushort)values.Count);
        values.ToArray().CopyTo(extra.AsSpan(4));
        W16(bytes, cd + 30, (ushort)extra.Length); W32(bytes, bytes.Length - 10, U32(bytes, bytes.Length - 10) + (uint)extra.Length);
        bytes = InsertBytes(bytes, cd + 46 + U16(bytes, cd + 28), extra);
        await ReadValidatedAsync(bytes, payload);
    }

    [Theory]
    [InlineData(40)]
    [InlineData(8192)]
    public async Task Native_incomplete_comment_signature_probe_is_rejected_by_structural_policy(int payloadLength)
    {
        var bytes = await NativeZipAsync(new byte[payloadLength], CompressionLevel.NoCompression, false);
        W16(bytes, bytes.Length - 2, 4);
        bytes = bytes.Concat(new byte[] { 0x50, 0x4b, 0x05, 0x06 }).ToArray();
        if (payloadLength == 40)
        {
            await Assert.ThrowsAsync<InvalidDataException>(async () =>
            {
                await using var native = await ZipArchive.CreateAsync(new MemoryStream(bytes), ZipArchiveMode.Read, false, null);
            });
        }
        else
        {
            await using var native = await ZipArchive.CreateAsync(new MemoryStream(bytes), ZipArchiveMode.Read, false, null);
            Assert.Single(native.Entries);
        }
        using var physical = new CountingReadStream(bytes);
        await using var source = Source(physical);
        var budget = Budget();
        var exception = await Assert.ThrowsAsync<PortableArchiveException>(() => PortableArchiveZipReader.OpenAsync(source, budget));
        Assert.Equal("invalid_zip", exception.Code);
        Assert.Contains("comment contains an EOCD signature", exception.Message);
        Assert.Equal(1, physical.AsyncCalls);
        Assert.Equal(0, physical.SyncCalls);
        Assert.Equal(0, budget.CurrentBytes);
        output.WriteLine($"incomplete last-comment signature: payload={payloadLength}, native={(payloadLength == 40 ? "rejects buffered over-read candidate" : "chooses actual EOCD")}; factory rejects the selected comment, not an incomplete candidate");
    }

    [Theory]
    [InlineData("single_epub", false)]
    [InlineData("single_epub", true)]
    [InlineData("two_epubs", false)]
    [InlineData("two_epubs", true)]
    [InlineData("signature_at_media_end", false)]
    [InlineData("signature_at_media_end", true)]
    [InlineData("many_signatures_and_fake_record", false)]
    [InlineData("many_signatures_and_fake_record", true)]
    [InlineData("signature_in_filename", false)]
    [InlineData("signature_in_filename", true)]
    public async Task Exporter_shaped_nested_zip_and_signature_media_are_accepted(string shape, bool descriptors)
    {
        var epub = CreateEpub();
        var media = new Dictionary<string, byte[]>();
        const string firstPath = "media/books/00000000000000000000000000000001/book.epub";
        switch (shape)
        {
            case "single_epub": media.Add(firstPath, epub); break;
            case "two_epubs":
                media.Add(firstPath, epub);
                media.Add("media/books/00000000000000000000000000000002/book.epub", CreateEpub("Second book"));
                break;
            case "signature_at_media_end":
                media.Add(firstPath, Payload(40, false).Concat(new byte[] { 0x50, 0x4b, 5, 6 }).ToArray());
                break;
            case "many_signatures_and_fake_record":
                var payload = new byte[2048];
                for (var i = 0; i < payload.Length; i += 32) W32(payload, i, 0x06054b50);
                // Each all-zero suffix is a complete fake EOCD for an empty directory.
                W16(payload, payload.Length - 32 + 20, 10);
                media.Add(firstPath, payload);
                break;
            default:
                // UTF-8 encodes these ASCII/control characters as the exact four magic bytes.
                // ZIP names and the existing path guard permit them; no filesystem name is used.
                media.Add("media/books/00000000000000000000000000000001/PK\u0005\u0006.epub", epub);
                break;
        }
        var expected = new Dictionary<string, byte[]>
        {
            [PortableArchiveFormat.DataPath] = Encoding.UTF8.GetBytes("{\"version\":3,\"books\":[],\"source\":\"native exporter shape\"}"),
        };
        foreach (var item in media) expected.Add(item.Key, item.Value);
        expected.Add(PortableArchiveFormat.ManifestPath, Encoding.UTF8.GetBytes("{\"format\":\"nostos-portable\",\"formatVersion\":1,\"media\":[]}"));
        using var memory = new MemoryStream();
        using var nonSeekable = new CountingSink(allowSync: true);
        // Match the real exporter: deflated library, stored media, deflated manifest last.
        using (var archive = new ZipArchive(descriptors ? nonSeekable : memory, ZipArchiveMode.Create, true))
            foreach (var item in expected)
            {
                var entry = archive.CreateEntry(item.Key, item.Key.EndsWith(".json", StringComparison.Ordinal)
                    ? CompressionLevel.Optimal : CompressionLevel.NoCompression);
                entry.LastWriteTime = Timestamp;
                await using var target = entry.Open();
                await target.WriteAsync(item.Value);
            }
        var bytes = descriptors ? nonSeekable.ToArray() : memory.ToArray();
        Assert.True(bytes.Length < 64 * 1024);
        using (var native = new ZipArchive(new MemoryStream(bytes), ZipArchiveMode.Read))
        {
            Assert.Equal(string.Empty, native.Comment);
            Assert.Equal(PortableArchiveFormat.DataPath, native.Entries[0].FullName);
            Assert.Equal(PortableArchiveFormat.ManifestPath, native.Entries[^1].FullName);
            foreach (var item in native.Entries)
            {
                var flags = Convert.ToUInt16(NativeField<object>(item, "_generalPurposeBitFlag"));
                Assert.Equal(descriptors, (flags & 8) != 0);
                Assert.Equal(item.FullName.EndsWith(".json", StringComparison.Ordinal) ? 8 : 0,
                    Convert.ToInt32(NativeField<object>(item, "_storedCompressionMethod")));
            }
        }
        await AssertArchiveContentsAsync(bytes, expected);
    }

    [Theory]
    [InlineData(false)]
    [InlineData(true)]
    public async Task Real_exporter_with_nested_epub_is_accepted(bool nonSeekable)
    {
        await using var library = await LocalPortableTestLibrary.CreateAsync();
        var ids = await PortableArchiveTestSupport.PopulateRepresentativeAsync(library.Db, library.Storage);
        var epub = CreateEpub();
        using (var media = new MemoryStream(epub))
            await library.Storage.SaveBookFileAsync(ids.EpubBookId, media, "source.epub");
        using var memory = new MemoryStream();
        using var sink = new CountingSink(allowSync: true);
        await library.Portability().ExportAsync(nonSeekable ? sink : memory);
        var bytes = nonSeekable ? sink.ToArray() : memory.ToArray();
        Assert.True(bytes.Length < 64 * 1024);
        var expected = new Dictionary<string, byte[]>();
        using (var native = new ZipArchive(new MemoryStream(bytes), ZipArchiveMode.Read))
        {
            Assert.Equal(string.Empty, native.Comment);
            Assert.Equal(PortableArchiveFormat.DataPath, native.Entries[0].FullName);
            Assert.Equal(PortableArchiveFormat.ManifestPath, native.Entries[^1].FullName);
            foreach (var entry in native.Entries)
            {
                await using var input = await entry.OpenAsync();
                using var contents = new MemoryStream();
                await input.CopyToAsync(contents);
                expected.Add(entry.FullName, contents.ToArray());
            }
        }
        Assert.Single(expected.Values, value => value.SequenceEqual(epub));
        await AssertArchiveContentsAsync(bytes, expected);
    }

    private static byte[] CreateEpub(string title = "Nested book")
    {
        using var bytes = new MemoryStream();
        using (var archive = new ZipArchive(bytes, ZipArchiveMode.Create, true))
        {
            var files = new Dictionary<string, string>
            {
                ["mimetype"] = "application/epub+zip",
                ["META-INF/container.xml"] = "<?xml version=\"1.0\"?><container version=\"1.0\" xmlns=\"urn:oasis:names:tc:opendocument:xmlns:container\"><rootfiles><rootfile full-path=\"OEBPS/content.opf\" media-type=\"application/oebps-package+xml\"/></rootfiles></container>",
                ["OEBPS/content.opf"] = $"<package version=\"2.0\" unique-identifier=\"id\" xmlns=\"http://www.idpf.org/2007/opf\"><metadata xmlns:dc=\"http://purl.org/dc/elements/1.1/\"><dc:identifier id=\"id\">urn:uuid:00000000-0000-0000-0000-000000000001</dc:identifier><dc:title>{title}</dc:title><dc:language>en</dc:language></metadata><manifest><item id=\"chapter\" href=\"chapter.xhtml\" media-type=\"application/xhtml+xml\"/><item id=\"ncx\" href=\"toc.ncx\" media-type=\"application/x-dtbncx+xml\"/></manifest><spine toc=\"ncx\"><itemref idref=\"chapter\"/></spine></package>",
                ["OEBPS/chapter.xhtml"] = $"<html xmlns=\"http://www.w3.org/1999/xhtml\"><head><title>{title}</title></head><body><p>Stored EPUB compatibility proof.</p></body></html>",
                ["OEBPS/toc.ncx"] = $"<ncx version=\"2005-1\" xmlns=\"http://www.daisy.org/z3986/2005/ncx/\"><head><meta name=\"dtb:uid\" content=\"urn:uuid:00000000-0000-0000-0000-000000000001\"/></head><docTitle><text>{title}</text></docTitle><navMap><navPoint id=\"chapter\" playOrder=\"1\"><navLabel><text>{title}</text></navLabel><content src=\"chapter.xhtml\"/></navPoint></navMap></ncx>",
            };
            foreach (var file in files)
            {
                var entry = archive.CreateEntry(file.Key, file.Key == "mimetype" ? CompressionLevel.NoCompression : CompressionLevel.Optimal);
                entry.LastWriteTime = Timestamp;
                using var target = entry.Open();
                target.Write(Encoding.UTF8.GetBytes(file.Value));
            }
        }
        var result = bytes.ToArray();
        Assert.Equal(0x06054b50u, U32(result, result.Length - 22));
        using var native = new ZipArchive(new MemoryStream(result), ZipArchiveMode.Read);
        Assert.Equal("mimetype", native.Entries[0].FullName);
        Assert.Equal(5, native.Entries.Count);
        return result;
    }

    private static async Task AssertArchiveContentsAsync(byte[] bytes, IReadOnlyDictionary<string, byte[]> expected)
    {
        using var physical = new CountingReadStream(bytes);
        await using var source = Source(physical);
        var budget = Budget();
        await using (var reader = await PortableArchiveZipReader.OpenAsync(source, budget))
        {
            AssertNativeLayout(reader);
            Assert.Equal(expected.Count, reader.Archive.Entries.Count);
            var calls = physical.AsyncCalls;
            _ = reader.Archive.Entries;
            Assert.Equal(calls, physical.AsyncCalls);
            foreach (var item in reader.Archive.Entries)
            {
                await using var entry = await item.OpenAsync();
                AssertNativeDataOffset(reader, item);
                using var contents = new MemoryStream();
                await entry.CopyToAsync(contents);
                Assert.Equal(expected[item.FullName], contents.ToArray());
            }
        }
        Assert.Equal(0, physical.SyncCalls);
        Assert.Equal(0, budget.CurrentBytes);
    }

    private static byte[] InsertBytes(byte[] bytes, int offset, byte[] inserted) =>
        bytes[..offset].Concat(inserted).Concat(bytes[offset..]).ToArray();

    private static void AssertNativeLayout(PortableArchiveZipReader reader)
    {
        Assert.Equal(reader.TailLayout.CentralDirectoryOffset, NativeField<long>(reader.Archive, "_centralDirectoryStart"));
        Assert.Equal(reader.Directory.Count, reader.Archive.Entries.Count);
        for (var i = 0; i < reader.Directory.Count; i++)
        {
            var expected = reader.Directory[i];
            var native = reader.Archive.Entries[i];
            Assert.Equal(expected.LocalHeaderOffset, NativeField<long>(native, "_offsetOfLocalHeader"));
            Assert.Equal(expected.Flags, Convert.ToUInt16(NativeField<object>(native, "_generalPurposeBitFlag")));
            Assert.Equal(expected.CompressionMethod, Convert.ToUInt16(NativeField<object>(native, "_storedCompressionMethod")));
            Assert.Equal(expected.Crc32, native.Crc32);
        }
    }
    private static void AssertNativeDataOffset(PortableArchiveZipReader reader, ZipArchiveEntry native)
    {
        var expected = Assert.Single(reader.EntryLayouts, x => x.Path == native.FullName);
        Assert.Equal(expected.DataOffset, NativeField<long>(native, "_storedOffsetOfCompressedData"));
    }

    private static T NativeField<T>(object instance, string name)
    {
        // Test-only runtime characterization. Product code never reflects native private state.
        var field = instance.GetType().GetField(name, BindingFlags.NonPublic | BindingFlags.Instance);
        Assert.NotNull(field);
        return (T)field.GetValue(instance)!;
    }

    private static async Task<(byte[] Bytes, long FirstCd, long SecondCd, long SecondLocal)> DualViewAsync(bool firstEndsAtEof, bool secondEndsAtEof)
    {
        var first = await NativeZipAsync(Enumerable.Repeat((byte)'A', 40).ToArray(), CompressionLevel.NoCompression, false);
        var second = await NativeZipAsync(Enumerable.Repeat((byte)'B', 40).ToArray(), CompressionLevel.NoCompression, false);
        const int trailerLength = 32;
        var firstCd = U32(first, first.Length - 6);
        var secondOffset = first.Length;
        var secondCd = U32(second, second.Length - 6);
        W32(second, (int)secondCd + 42, (uint)secondOffset);
        W32(second, second.Length - 6, (uint)(secondCd + secondOffset));
        W16(second, second.Length - 2, (ushort)(secondEndsAtEof ? trailerLength : 0));
        W16(first, first.Length - 2, (ushort)(firstEndsAtEof ? second.Length + trailerLength : 0));
        return (first.Concat(second).Concat(new byte[trailerLength]).ToArray(), firstCd, secondCd + secondOffset, secondOffset);
    }

    private async Task ReadValidatedAsync(byte[] bytes, byte[] payload)
    {
        using var physical = new CountingReadStream(bytes);
        await using var source = Source(physical, shortReads: 11);
        var budget = Budget();
        await using (var reader = await PortableArchiveZipReader.OpenAsync(source, budget))
        {
            AssertNativeLayout(reader);
            foreach (var item in reader.Archive.Entries)
            {
                await using var entry = await item.OpenAsync();
                AssertNativeDataOffset(reader, item);
                using var contents = new MemoryStream();
                await entry.CopyToAsync(contents);
                Assert.Equal(payload, contents.ToArray());
            }
        }
        Assert.Equal(0, physical.SyncCalls);
        Assert.Equal(0, budget.CurrentBytes);
    }
    private static RangePortableArchiveSource Source(CountingReadStream physical, int shortReads = int.MaxValue) =>
        new(physical.Length, async (offset, buffer, ct) =>
        {
            physical.Position = offset;
            return await physical.ReadAsync(buffer[..Math.Min(buffer.Length, shortReads)], ct);
        });
    private static byte[] Payload(int size, bool compressible)
    {
        var bytes = new byte[size];
        if (!compressible) new Random(12345).NextBytes(bytes);
        else Array.Fill(bytes, (byte)'a');
        return bytes;
    }
    private static async Task WriteZipAsync(Stream destination, byte[] payload, CompressionLevel compression, int count)
    {
        await using var archive = await ZipArchive.CreateAsync(destination, ZipArchiveMode.Create, true, null);
        for (var i = 0; i < count; i++)
        {
            var entry = archive.CreateEntry($"media/books/{i:x32}/book.epub", compression);
            entry.LastWriteTime = Timestamp;
            await using var stream = await entry.OpenAsync();
            await stream.WriteAsync(payload.AsMemory());
        }
    }
    private static async Task<byte[]> NativeZipAsync(byte[] payload, CompressionLevel compression, bool descriptor, int count = 1)
    {
        if (descriptor)
        {
            using var sink = new CountingSink(allowSync: true);
            await WriteZipAsync(sink, payload, compression, count);
            return sink.ToArray();
        }
        using var buffer = new MemoryStream();
        using (var archive = new ZipArchive(buffer, ZipArchiveMode.Create, true))
            for (var i = 0; i < count; i++)
            {
                var entry = archive.CreateEntry($"media/books/{i:x32}/book.epub", compression);
                entry.LastWriteTime = Timestamp;
                using var stream = entry.Open();
                stream.Write(payload);
            }
        return buffer.ToArray();
    }
    private static void AssertCode(string code, Action action) => Assert.Equal(code, Assert.Throws<PortableArchiveException>(action).Code);
    private static async Task AssertCodeAsync(string code, Func<Task> action) => Assert.Equal(code, (await Assert.ThrowsAsync<PortableArchiveException>(action)).Code);
    private static ushort U16(byte[] bytes, int offset) => BinaryPrimitives.ReadUInt16LittleEndian(bytes.AsSpan(offset));
    private static uint U32(byte[] bytes, int offset) => BinaryPrimitives.ReadUInt32LittleEndian(bytes.AsSpan(offset));
    private static void W16(byte[] bytes, int offset, ushort value) => BinaryPrimitives.WriteUInt16LittleEndian(bytes.AsSpan(offset), value);
    private static void W32(byte[] bytes, int offset, uint value) => BinaryPrimitives.WriteUInt32LittleEndian(bytes.AsSpan(offset), value);

    private sealed class CountingSink(bool allowSync = false, bool discard = false) : Stream
    {
        private readonly MemoryStream _buffer = new();
        public int SyncCalls { get; private set; }
        public int AsyncCalls { get; private set; }
        public int AsyncDisposals { get; private set; }
        public bool FailWrite { get; init; }
        public bool FailFlush { get; init; }
        public bool PartialWriteFailure { get; init; }
        public byte[] ToArray() => _buffer.ToArray();
        public override bool CanRead => false;
        public override bool CanSeek => false;
        public override bool CanWrite => true;
        public override long Length => throw new NotSupportedException();
        public override long Position { get => throw new NotSupportedException(); set => throw new NotSupportedException(); }
        private void Sync() { SyncCalls++; if (!allowSync) throw new InvalidOperationException("Physical synchronous IO forbidden."); }
        public override void Write(byte[] buffer, int offset, int count) { Sync(); if (!discard) _buffer.Write(buffer, offset, count); }
        public override void Write(ReadOnlySpan<byte> buffer) { Sync(); if (!discard) _buffer.Write(buffer); }
        public override void WriteByte(byte value) { Sync(); if (!discard) _buffer.WriteByte(value); }
        public override void Flush() { Sync(); }
        public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) => WriteAsync(buffer.AsMemory(offset, count), cancellationToken).AsTask();
        public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default)
        {
            cancellationToken.ThrowIfCancellationRequested();
            AsyncCalls++;
            if (FailWrite) throw new IOException("Injected write failure.");
            if (PartialWriteFailure)
            {
                _buffer.Write(buffer.Span[..1]);
                throw new IOException("Injected failure after partial write.");
            }
            if (!discard) _buffer.Write(buffer.Span);
            return ValueTask.CompletedTask;
        }
        public override Task FlushAsync(CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            AsyncCalls++;
            if (FailFlush) throw new IOException("Injected flush failure.");
            return Task.CompletedTask;
        }
        public override ValueTask DisposeAsync() { AsyncDisposals++; return ValueTask.CompletedTask; }
        public override int Read(byte[] buffer, int offset, int count) => throw new NotSupportedException();
        public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException();
        public override void SetLength(long value) => throw new NotSupportedException();
    }
    private sealed class CountingReadStream : Stream
    {
        private readonly MemoryStream _buffer;
        public CountingReadStream(byte[] bytes) => _buffer = new(bytes, false);
        public int SyncCalls { get; private set; }
        public int AsyncCalls { get; private set; }
        public override bool CanRead => true;
        public override bool CanSeek => true;
        public override bool CanWrite => false;
        public override long Length => _buffer.Length;
        public override long Position { get => _buffer.Position; set => _buffer.Position = value; }
        private int Sync() { SyncCalls++; throw new InvalidOperationException("Physical synchronous IO forbidden."); }
        public override int Read(byte[] buffer, int offset, int count) => Sync();
        public override int Read(Span<byte> buffer) => Sync();
        public override int ReadByte() => Sync();
        public override ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default)
        {
            cancellationToken.ThrowIfCancellationRequested();
            AsyncCalls++;
            return ValueTask.FromResult(_buffer.Read(buffer.Span));
        }
        public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) => ReadAsync(buffer.AsMemory(offset, count), cancellationToken).AsTask();
        public override void Flush() { }
        public override long Seek(long offset, SeekOrigin origin) => _buffer.Seek(offset, origin);
        public override void SetLength(long value) => throw new NotSupportedException();
        public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();
    }
}