Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ on:
push:
branches: ['main']
pull_request:
workflow_dispatch:

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.ref }}
Expand All @@ -30,6 +34,24 @@ jobs:
toolchain: ${{ matrix.rust }}
- run: cargo test --locked --all-features

proptest:
name: Property tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
- run: cargo test --locked --all-features --test proptest

fuzz:
name: Fuzz smoke test
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@nightly
- run: cargo install cargo-fuzz --version 0.13.2 --locked
- run: cargo fuzz run linked_hash_map -- -max_len=1024 -max_total_time=30

msrv:
runs-on: ubuntu-latest
steps:
Expand Down
168 changes: 168 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ serde = { version = "1.0", default-features = false, optional = true }
[dev-dependencies]
serde_test = "1.0"
rustc-hash = "2"
proptest = { version = "~1.8.0", default-features = false, features = ["std"] }
46 changes: 46 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,52 @@ linked list, and the unsafe code has diverged quite a lot from the original
sanitizers, but it should probably still receive more review and testing, and
check for test code coverage.

## Testing unsafe code

The integration test `tests/proptest.rs` uses proptest to compare random operation
sequences against a linear, ordered reference model. It checks contents, lookups,
length, and forward/backward iteration after each operation, using both the default
hasher and a deliberately colliding hasher. Heap-owned keys and values exercise
destruction as well as node reuse, cursor insertion, reordering, retention,
resizing, mutable iteration, and partially consumed drains and owning iterators.
The map contains the shared unsafe linked-list implementation used by the set and
LRU cache.

Run the property tests with:

```sh
cargo test --locked --test proptest
PROPTEST_CASES=10000 cargo test --locked --test proptest
cargo +nightly miri test --locked --test proptest
```

These tests also run in the existing Miri and sanitizer CI jobs, with smaller
default case counts and sequences under Miri. Proptest shrinks failing sequences
and saves regression seeds; keep those seeds when adding a regression test.
Seed persistence is disabled under Miri to avoid filesystem access in isolation.

The `fuzz/` package uses cargo-fuzz/libFuzzer and the same reference-model runner:

```sh
cargo install cargo-fuzz --locked
cargo +nightly fuzz run linked_hash_map -- -max_len=1024
# Bounded smoke test:
cargo +nightly fuzz run linked_hash_map -- -max_len=1024 -max_total_time=30
# Replay a saved failure:
cargo +nightly fuzz run linked_hash_map fuzz/artifacts/linked_hash_map/<artifact>
```

Each four input bytes encode an operation, a key, and a little-endian `i16`
value. Inputs are limited to 256 operations and 32 distinct keys to favor
replacement and node reuse while bounding resource consumption. Generated
corpora, crash artifacts, coverage output, and fuzz build output are ignored.

The GitHub Actions CI workflow preserves upstream's checks and also runs dedicated
property-test and 30-second fuzz-smoke jobs on pull requests and pushes to `main`.
It can also be started manually using **Run workflow** in the Actions tab.
On a new fork, enable repository workflows in the Actions tab if GitHub prompts
for it; workflow files alone cannot enable repository-level Actions settings.

## Credit

There is a huge amount of code in this crate that is copied verbatim from
Expand Down
4 changes: 4 additions & 0 deletions fuzz/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
target
corpus
artifacts
coverage
Loading
Loading