Skip to content

Phase 3 test coverage: 3 proptest properties for DiscreteDistribution#132

Merged
joshfactorial merged 4 commits into
developfrom
test/phase-3-proptest
May 20, 2026
Merged

Phase 3 test coverage: 3 proptest properties for DiscreteDistribution#132
joshfactorial merged 4 commits into
developfrom
test/phase-3-proptest

Conversation

@joshfactorial
Copy link
Copy Markdown
Collaborator

@joshfactorial joshfactorial commented May 20, 2026

DiscreteDistribution::sample is hot-path code shared by every model (quality scores, fragment lengths, indel lengths, nucleotide selection). Blanketing its CDF binary search with randomized inputs is cheap insurance against off-by-one bugs that the 7 hand-rolled fixtures here can't surface.

Adds proptest = "1" as a common dev-dep and three properties on DiscreteDistribution:

  • proptest_sample_returns_value_from_input_set: for any positive weight vector of length 2..=10 and any rand ∈ [0, 1], the sample output is in the input value set. Catches any future bisect bug that returns an out-of-range index. proptest's shrink space naturally exercises the rand=0.0 and rand=1.0 boundaries.

  • proptest_empirical_frequency_approaches_weights: 20,000 samples drawn through a deterministic NeatRng must produce a histogram within 3% of N per bin (well above the worst-case binomial standard deviation, comfortably below the threshold a systematic CDF bug would induce). Catches any off-by-one in cumulative_sum or the bisect predicate that would show up as a measurable skew.

  • proptest_all_zero_weights_always_returns_first_value: documents the actual (non-uniform!) behavior when all weights are zero. The new() constructor sets the CDF to [1.0; n], which makes bisect-left return index 0 on every sample. Note that this is not a uniform fallback — the uniform fallback for quality models lives one layer up in QualityScoreModel::from_counts. Renaming this contract would now be a deliberate change, not a silent regression.

cargo test --workspace: 200 common tests (was 197), 158 rneat tests, all passing.

Closes #104

DiscreteDistribution::sample is hot-path code shared by every model
(quality scores, fragment lengths, indel lengths, nucleotide
selection). Blanketing its CDF binary search with randomized inputs
is cheap insurance against off-by-one bugs that the 7 hand-rolled
fixtures here can't surface.

Adds `proptest = "1"` as a common dev-dep and three properties on
DiscreteDistribution:

- `proptest_sample_returns_value_from_input_set`: for any positive
  weight vector of length 2..=10 and any rand ∈ [0, 1], the sample
  output is in the input value set. Catches any future bisect bug
  that returns an out-of-range index. proptest's shrink space
  naturally exercises the rand=0.0 and rand=1.0 boundaries.

- `proptest_empirical_frequency_approaches_weights`: 20,000 samples
  drawn through a deterministic NeatRng must produce a histogram
  within 3% of N per bin (well above the worst-case binomial standard
  deviation, comfortably below the threshold a systematic CDF bug
  would induce). Catches any off-by-one in cumulative_sum or the
  bisect predicate that would show up as a measurable skew.

- `proptest_all_zero_weights_always_returns_first_value`: documents
  the actual (non-uniform!) behavior when all weights are zero. The
  `new()` constructor sets the CDF to `[1.0; n]`, which makes
  bisect-left return index 0 on every sample. Note that this is *not*
  a uniform fallback — the uniform fallback for quality models lives
  one layer up in QualityScoreModel::from_counts. Renaming this
  contract would now be a deliberate change, not a silent regression.

cargo test --workspace: 200 common tests (was 197), 158 rneat tests,
all passing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@joshfactorial joshfactorial linked an issue May 20, 2026 that may be closed by this pull request
@joshfactorial joshfactorial merged commit d767ae8 into develop May 20, 2026
1 check passed
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.

Fill out testing

1 participant