You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fix five selection defects; add regression test project. (v2.5.4)
Five defects, none previously covered by any test (the repo had no test
project):
1. Multi-value exclusions were silently ignored on every enumerable/
params path. Root cause: DeferredHashSet fills itself lazily during
Contains, but every call site consulted .Count BEFORE anything had
been pumped, so a freshly created deferred set always looked empty
and the code took the "no exclusions" fast path. Compounding it, the
locals were typed ISet<T>, and DeferredHashSet.Contains hides (new)
rather than overrides, so the pumping Contains could never bind
through that type. Call sites now take Count fast paths only for
already-materialized sets and consult the deferred set through its
concrete type. Affected: RandomSelectIndex/RandomSelectOne/
TryRandomSelectOne with non-ISet exclusions, all *Except overloads
with 2+ exclusions, and NextExcluding with enumerable exclusions.
2. The span-based single-exclusion path (RandomSelectIndexExcept) rented
ArrayPool.Rent(others.Length) -- zero on that path -- and Rent(0)
returns an empty array, so any non-empty source threw
IndexOutOfRangeException.
3. LinkedList.TryRandomPluck walked `i <= r` from First, advancing r+1
times: the first element could never be selected, and drawing the
last index threw NullReferenceException -- including on every draw
from a single-element list.
4. Two selection paths drew from the global Random even when a caller
supplied a seeded instance, breaking deterministic replay.
5. NextExcluding(int, uint, params uint[]) used LINQ Cast<int>() on the
uint values; a boxed uint cannot unbox to int, so any 'others' threw
InvalidCastException. Now Select(v => (int)v).
Tests: new tests/Open.RandomizationExtensions.Tests (xunit, net10.0),
23 regression tests covering each defect plus the previously-working
ISet paths. The library csproj now excludes tests/** from its default
globs (the project lives at the repo root).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
<PackageReleaseNotes>Fixes: multi-value exclusions were silently ignored (deferred exclusion sets reported Count 0 before being pumped); span-based single-exclusion selection threw IndexOutOfRangeException (zero-length pooled rent); LinkedList TryRandomPluck could never select the first element and threw on the last; two selection paths ignored a supplied Random; NextExcluding uint overload threw InvalidCastException.</PackageReleaseNotes>
0 commit comments