Skip to content

Only Gzip checks that async compression output is byte-identical to sync; Deflate, ZLib, Brotli and AES have no such test (async-surface spec) #83

Description

@matt-edmondson

What's missing

The async-surface spec requires three tests for each provider whose stream path was converted to genuine async:

A fake-async implementation reaches for the synchronous path and throws; a genuine one passes. This
is deterministic and machine-independent. Each converted provider gets:
1. An `AsyncOnlyStream` test proving it never touches the synchronous members.
2. A round-trip test asserting the async path produces byte-identical output to the sync path.
3. A cancellation test asserting an already-cancelled token is honoured before work begins.

  1. An AsyncOnlyStream test proving it never touches the synchronous members.
  2. A round-trip test asserting the async path produces byte-identical output to the sync path.
  3. A cancellation test asserting an already-cancelled token is honoured before work begins.

Items 1 and 3 are covered for every converted provider. Item 2 is covered for Gzip only: GzipAsyncCompression_ProducesTheSameBytesAsTheSynchronousPathAsync (Essentials.Tests/AsyncStreamIoTests.cs:75).

The other converted providers have only round trips:

  • Deflate, ZLib and Brotli. CompressionProvider_RoundTripsThroughAsyncOnlyStreamsAsync, which runs over StreamingCompressionProviders.
  • AES. AesEncryptionRoundTripsThroughAsyncOnlyStreamsAsync.
  • Elsewhere. ProviderContractTests and RoundTripTests also only round-trip the async path back to the original.

Why it matters

A round trip only shows that async compress and async decompress agree with each other. It does not show that the async path emits the same stream as the sync path. Two kinds of divergence would pass every current test while producing output the sync path, or another consumer, may not accept:

  • a different compression level, or a missing final flush or footer, as long as the async decompressor tolerates it;
  • an AES async path that writes the IV or padding differently from TryEncrypt.

Data written by TryCompressAsync and later read through the synchronous API is exactly the case the spec's byte-identity test exists to protect.

Acceptance criteria

  • A [DynamicData] test over Deflate, ZLib and Brotli, mirroring the Gzip one. For a fixed payload, the bytes TryCompressAsync writes into an AsyncOnlyStream equal the bytes the synchronous TryCompress produces.
  • An AES test with a fixed key and IV. The bytes TryEncryptAsync writes into an AsyncOnlyStream equal the synchronous TryEncrypt output.
  • Optionally, the Gzip-specific test folds into the parameterised one.
  • Test-only change, tagged [patch].

Dependencies

None. Release 1 of the spec has shipped (PR #14 and PR #15), and this closes its remaining test gap. Release 2, the ValueTask migration, is tracked under #8.

Activity

  1. matt-edmondson commented on Oct 6, 2026

    @matt-edmondson
    ContributorAuthor

    Triage

    Recommended next step: Parameterise the Gzip byte-identity test with [DynamicData] over Deflate, ZLib and Brotli. Add an AES fixed-key/IV test comparing TryEncryptAsync against TryEncrypt. Tag the change [patch].


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions