Skip to content

Sweep every span query, mutating ones included - #134

Merged
mattlorimor merged 1 commit into
masterfrom
test/span-query-roster
Aug 20, 2026
Merged

Sweep every span query, mutating ones included#134
mattlorimor merged 1 commit into
masterfrom
test/span-query-roster

Conversation

@mattlorimor

Copy link
Copy Markdown
Owner

TestSpanAndArrayQueriesAgree reached 5 of the 20 structures offering a span query. It now reaches all 19 with a pure one, and a second sweep covers the 13 whose span query also changes the structure.

Two properties, not one

The mutating half needed a different shape. Agreeing on every answer is only half of it: two paths can return the same value at every step and leave the structure holding different things. A filter that answers correctly while holding the wrong thing doesn't fail at the seam — it fails later, somewhere else, for no visible reason.

So each pair in TestSpanAndArrayMutatingQueriesAgree is driven step for step through its own instance, comparing the answer at every key, and then compared through its payload — the same oracle the equivalence sweep uses.

Two mutators (InvertibleBloomLookupTable.Remove, SublimeCountMinSketch.Remove) answer with the structure itself, so there is no value to compare and the state is the whole check. The table also needs the fixed-width helper, since it refuses a key of any other length.

Rosters

Both sweeps check against rosters derived from the library's span surface, split by whether the method mutates:

  • WithPureSpanQueries — 19 structures (Test, Count, TryGetValue)
  • WithMutatingSpanQueries — 13 (TestAndAdd, TestAndRemove, Remove)

A structure that gains a span query fails these until it is covered.

Verification

Five probes, each with the build exit checked:

  • InvertibleBloomLookupTable.Remove's array path applying twice → killed with left different states. This is the one that matters: a fluent mutator has no answer to compare, so nothing but the state check could see it.
  • BloomFilter.TestAndAdd's array path negating its result → killed with answered differently for key 0. The mirror case: identical state, wrong answer.
  • dropping InfiniFilter from the mutating roster → killed, named
  • dropping HeavyKeeper from the pure roster → killed, named
  • the pre-existing equivalence and allocation sweeps still pass

Clean dotnet build -c Release -warnaserror, exit 0 unpiped. 907 tests passing, up 1.

A comment I had to correct

I first annotated PrivateCountMinSketch and DpswSketch as drawing noise per query, which would mean their two overloads need only agree in distribution. That's wrong, and the tests passing is what exposed it: the noise is drawn once at construction and lives in the counters — which is precisely what stops repeated queries from averaging it away. A query is an ordinary read, and the two overloads must return the identical double. The comment now says that.

TestSpanAndArrayQueriesAgree reached 5 of the 20 structures offering a span
query. It now reaches all 19 with a pure one, and a second sweep covers the 13
whose span query also changes the structure.

The mutating half needed a different shape. Agreeing on every answer is only
half of it: two paths can return the same value at every step and leave the
structure holding different things, and a filter that answers correctly while
holding the wrong thing does not fail at the seam -- it fails later, somewhere
else, for no visible reason. Each pair is driven step for step through its own
instance and then compared through its payload, the same oracle the equivalence
sweep uses.

Two mutators answer with the structure itself, so there is no value to compare
and the state is the whole check. InvertibleBloomLookupTable needs the
fixed-width helper, since it refuses a key of any other length.

Both sweeps are checked against rosters derived from the span surface, split by
whether the method mutates. A structure that gains a span query fails these
until it is covered.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JH2NRDbhF5bwAsTAP7znb9
@mattlorimor
mattlorimor merged commit 51e0d90 into master Aug 20, 2026
7 checks passed
@mattlorimor
mattlorimor deleted the test/span-query-roster branch August 20, 2026 03:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant