Skip to content

Feat/adversarial tests#16

Merged
jcfangc merged 9 commits into
mainfrom
feat/adversarial-tests
Jun 27, 2026
Merged

Feat/adversarial tests#16
jcfangc merged 9 commits into
mainfrom
feat/adversarial-tests

Conversation

@jcfangc

@jcfangc jcfangc commented Jun 27, 2026

Copy link
Copy Markdown
Owner

No description provided.

jcfangc and others added 8 commits June 27, 2026 07:47
87 passing + 6 ignored bug reproducers (marked B1-B3).

Confirmed bugs:
1. B1: set_chunk doesn't mask unused high bits after write
   File: src/bit_string/impls_for_editing/impls_for_set.rs:26
   Fix: add self.words.mask_unused_bits(self.bit_len) at end of set_chunk

2. B2: BitStr::count_ones includes source bits beyond view's end
   File: src/traits/bits_arith/funcs_for_count_ones.rs:19
   Fix: mask bits[full_words] with low_mask(rem) before counting

3. B3: BitStr::find misses occurrences straddling unaligned→aligned word boundary
   File: src/bit_str/impls_for_matching/impls_for_find.rs:73
   Fix: extend unaligned scan range to cover cross-boundary positions

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: DeepSeek AI <service@deepseek.com>
tests/adversarial.rs → entry point with shared helpers + mod declarations
tests/adversarial/
  tests_for_construction.rs   — new, zeros, ones, repeat, from_words, from_str
  tests_for_access.rs         — get, first, last, get_chunk
  tests_for_editing.rs        — push, pop, insert, remove, set, set_chunk, truncate, clear
  tests_for_concat.rs         — push_bit_string, insert_bit_string, split_off
  tests_for_slice_drain.rs    — slice, slice_from, slice_until, drain_interval(_assign)
  tests_for_replace.rs        — replace, replace_interval(_assign)
  tests_for_retain.rs         — retain
  tests_for_bitwise.rs        — not, and, or, xor
  tests_for_shift.rs          — shl, shr
  tests_for_count.rs          — count_ones/zeros, leading_*, trailing_*
  tests_for_matching.rs       — matches_at, starts_with, ends_with, contains, find, rfind, strip
  tests_for_ord_hash.rs       — Ord, PartialOrd, Eq, Hash
  tests_for_fmt.rs            — Display, Debug
  tests_for_iter.rs           — Iterator, DoubleEndedIterator
  tests_for_predicates.rs     — any, all, is_all_zeros, is_all_ones, is_empty
  tests_for_bitstr.rs         — clone invariants, BitStr views, slice chains
  tests_for_stress.rs         — extend, stress, memory, set_chunk precision, invariant chain
  tests_for_bugs.rs           — 7 ignored bug reproducers (B1, B2, B3)

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: DeepSeek AI <service@deepseek.com>
Bug 1 (set_chunk): Add mask_unused_bits() at end of set_chunk to restore
the unused-bits-zeroed invariant after writing bits into the last word.
- src/bit_string/impls_for_editing/impls_for_set.rs

Bug 2 (count_ones): Mask the last partial word with low_mask(rem) before
counting. The old code trusted the invariant but BitStr sub-views share
the source's words where bits beyond the view's end may be non-zero.
- src/traits/bits_arith/funcs_for_count_ones.rs

Bug 3 (find/contains/rfind): Extend unaligned scan range to cover
needles that straddle the unaligned→aligned word boundary.
bits_equal_at already handles cross-boundary reads correctly.
- src/bit_str/impls_for_matching/impls_for_find.rs

All 93 adversarial tests now pass (was 86+7 ignored).

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: DeepSeek AI <service@deepseek.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: DeepSeek AI <service@deepseek.com>
Target both-sides-unaligned Eq/Ord/Hash, unaligned find/contains/rfind,
structural vs semantic Eq, trailing_zeros/ones on unaligned views,
get_chunk on unaligned views, strip on unaligned views, matches_at both
misaligned, BitStr iter/predicates/display on unaligned views, and
edge cases for retain/set_chunk/push-pop at word boundaries.

Discovered B4: rfind misses the last occurrence on unaligned haystacks
when the aligned portion has fewer than SMALL_WORDS words.
In impls_for_find.rs the find_last_word call is gated behind
aligned.len() >= SMALL_WORDS — when this fails the aligned portion
is never scanned and rfind falls through to only scanning the first
partial word.

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: DeepSeek AI <service@deepseek.com>
The rfind unaligned path gated find_last_word behind
aligned.len() >= SMALL_WORDS. When the aligned portion was too small
(e.g. 2 words on AVX2 needing 4), find_last_word was never called and
only the first partial word was scanned — missing all occurrences in
the aligned remainder.

Fix: pull the SMALL_WORDS gate up to only control find_any_candidate
(quick rejection). find_last_word is always called and handles small
inputs via its own internal scalar fallback.

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: DeepSeek AI <service@deepseek.com>
Add cat() helper to adversarial.rs, distribute 34 round-2 tests:
- tests_for_ord_hash.rs   (+8: both-unaligned Eq/Ord/Hash, structural-vs-semantic)
- tests_for_matching.rs   (+9: unaligned find/rfind/contains, strip, matches_at)
- tests_for_count.rs      (+3: trailing_zeros/ones unaligned)
- tests_for_access.rs     (+2: get_chunk unaligned)
- tests_for_retain.rs     (+2: retain at word boundaries)
- tests_for_editing.rs    (+4: set_chunk edge cases, push/pop boundaries)
- tests_for_iter.rs       (+2: BitStr iter unaligned)
- tests_for_predicates.rs (+3: predicates unaligned)
- tests_for_fmt.rs        (+1: BitStr Display unaligned)

Delete tests_for_round2.rs — no separate round file needed.

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: DeepSeek AI <service@deepseek.com>
@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 80.00000% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/bit_str/impls_for_matching/impls_for_find.rs 71.42% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

@codspeed-hq

codspeed-hq Bot commented Jun 27, 2026

Copy link
Copy Markdown

Merging this PR will degrade performance by 12.44%

❌ 9 regressed benchmarks
✅ 162 untouched benchmarks
⏩ 11 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
ends_with/len_65/no/bit_string 343.9 ns 402.2 ns -14.5%
ends_with/len_65/yes/bit_string 343.9 ns 402.2 ns -14.5%
matches_at/len_65/no/aligned/bit_string 401.7 ns 460 ns -12.68%
matches_at/len_65/yes/aligned/bit_string 401.7 ns 460 ns -12.68%
matches_at/len_65/no/unaligned/bit_string 405 ns 463.3 ns -12.59%
matches_at/len_65/yes/unaligned/bit_string 405 ns 463.3 ns -12.59%
count_ones/len_65/alternating/bit_string 248.6 ns 278.6 ns -10.77%
count_ones/len_65/dense/bit_string 248.6 ns 278.6 ns -10.77%
count_ones/len_65/sparse/bit_string 248.6 ns 278.6 ns -10.77%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing feat/adversarial-tests (ed298b7) with main (cd6871e)

Open in CodSpeed

Footnotes

  1. 11 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

The stdarch_aarch64_prefetch feature gate was copied from the library
code but is not needed in the test binary — no prefetch intrinsics
are used in tests.  On stable Rust this causes a compile error.

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: DeepSeek AI <service@deepseek.com>
@jcfangc
jcfangc merged commit 770e07b into main Jun 27, 2026
6 of 7 checks passed
@jcfangc
jcfangc deleted the feat/adversarial-tests branch June 27, 2026 15:08
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.

2 participants