用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/AzureFoxStudios/wabi --skill wabidb-testing-best-practices命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
| name | wabidb-testing-best-practices |
| description | Learn WabiDB testing: unit, integration, property, fuzz, and crash. |
This skill provides a structured approach to learning WabiDB's testing strategies covering unit, integration, property, fuzz, crash, and benchmark testing.
cargo build systemproptest crate for property testingUse these commands to execute different test types:
# Run all tests
cargo test -p wabidb
# Run unit tests
cargo test -p wabidb --lib
# Run integration tests
cargo test --features test-harness -p wabidb -- replay_test
# Run property tests
cargo test --features test-harness -p wabidb -- property_tests
# Run fuzz tests
cargo test --features test-harness -p wabidb -- fuzz
# Run benchmarks
cargo bench -p wabidb -- projection_read
| Test Type | Key Files | Commands | Purpose |
|---|---|---|---|
| Unit | src/**/mod.rs | cargo test | Validate individual components |
| Property | src/tests/property_tests.rs | cargo test --features test-harness -p wabidb -- property_tests | Property-based validation (16 tests) |
| Integration | src/tests/replay_test.rs | cargo test --features test-harness -p wabidb -- replay_test | End-to-end workflow validation |
| Crash | src/tests/crash_tests.rs | cargo test --features test-harness -p wabidb -- crash_tests | Power-loss recovery validation |
| Fuzz | src/fuzz/mod.rs | cargo test --features test-harness -p wabidb -- fuzz | Input validation and robustness (4 targets) |
| Benchmark | benches/projection_read.rs | cargo bench -p wabidb -- projection_read | Projection read performance (24 benchmarks) |
Pattern: Test individual components in isolation with clear input/output validation.
Key Techniques:
#[test] attributes for individual test casesExample Test Structure:
#[test]
fn record_round_trip_minimal() {
let header = RecordHeader::new(RecordKind::Event, 0, [0u8; 16], 0, 0);
let bytes = header.encode();
let decoded = RecordHeader::decode(&bytes).unwrap();
assert_eq!(header, decoded);
}
Projection Unit Test Patterns:
Each projection with soft-delete (is_deleted) has a 3-test pattern:
fn delete_marks_record() — verifies that setting is_deleted = true marks the recordfn list_*_filters_deleted() — verifies that list excludes deleted by default but includes them when include_deleted: truefn compact_removes_deleted() — verifies that compact() physically removes deleted recordsWabiDB uses proptest = "1" for property-based testing. All 16 property tests are in src/tests/property_tests.rs.
Existing Tests (2):
record_encode_decode_round_trip — RecordHeader encode/decode with generated commit_seq, payload_len, hashescommit_index_encode_decode_round_trip — CommitIndexEntry encode/decode with generated fieldsProjection Record Round-Trips (5):
message_record_postcard_round_trip — MessageRecord postcard encode/decodewiki_page_record_postcard_round_trip — WikiPageRecord postcard encode/decodeforum_post_record_postcard_round_trip — ForumPostRecord postcard encode/decodeincident_record_postcard_round_trip — IncidentRecord postcard encode/decodeuser_record_postcard_round_trip — UserRecord postcard encode/decodeKey Encoding Injectivity (3):
wiki_key_encode_decode_injective — wiki encode_key determinism and collision resistanceforum_key_encode_decode_injective — forum 3-part encode_key determinismincident_key_encode_decode_injective — incident encode_key determinismDomain Type JSON Round-Trips (3):
wiki_page_json_round_trip — WikiPage serde_json round-tripforum_post_json_round_trip — ForumPost serde_json round-tripincident_json_round_trip — Incident serde_json round-tripStrategy Patterns:
fn short_string() -> impl Strategy<Value = String> {
"[a-zA-Z0-9_/.-]{0,64}"
}
fn projection_round_trip<T: Serialize + DeserializeOwned + Debug + PartialEq>(record: &T) {
let encoded = postcard::to_allocvec(record).expect("encode");
let decoded: T = postcard::from_bytes(&encoded).expect("decode");
assert_eq!(*record, decoded);
}
Integration tests live in src/tests/ as lib test modules (not in tests/ directory):
replay_test.rs — Full command-commit-readback flows that exercise the sequencer, segment writer, commit index, and projection dispatcher together.send_message_flow.rs — End-to-end message send: submit a send_message command, verify the MessagesProjection contains the new message.These tests require the test-harness feature flag for engine initialization with test configs.
4 inline fuzz targets in src/fuzz/mod.rs with 14 test cases each:
| Target | Input | Tests |
|---|---|---|
fuzz_record_decode | RecordHeader::decode() | empty, truncated, garbage, max-size |
fuzz_stream_ref_decode | StreamRef::decode() | empty, truncated, garbage, max-size |
fuzz_commit_index_entry_decode | CommitIndexEntry::decode() | empty, truncated, garbage, max-size |
fuzz_parse_composite_key | parse_composite_key() | empty, single-part, multi-part, null-delimited |
Pattern: each target creates an instances list of byte vectors (empty, truncated valid, random, max-size) and asserts decode returns Err for invalid inputs and round-trips for valid ones.
5 physical subprocess crash tests in src/tests/power_loss.rs:
| Boundary # | Name | What Happens | Recovery Expectation |
|---|---|---|---|
| 1 | crash_before_any_write | After commit_seq assigned, before segment write | Transaction was never committed; watermark unchanged |
| 2 | crash_mid_stream_write | After writing one stream, before next stream's segment | Orphan record; skipped on recovery (Option B rollback) |
| 3 | crash_before_batcher_submit | After all segment writes, before batcher submit | All writes durable but not indexed; replayed via segment scan |
| 4 | crash_mid_batcher_submit | After batcher begin, before batcher finish | Incomplete batch; recovered via segment scan |
| 5 | crash_after_batcher_submit | After batcher finish, before response to caller | Fully committed; transaction observed after engine restart |
Tests use subprocess isolation: spawn_crash_child() forks the test binary with WABIDB_CRASH_BOUNDARY env var. A second process opens the engine normally and verifies the recovered state.
Benchmarks live in benches/projection_read.rs using criterion. Populate 10k records across 100 groups for 10 projection types, then measure:
get benchmarks: single-record lookup by exact keylist benchmarks: prefix scans with optional include_deletedcompact benchmark: compaction of 10% deleted recordsRun: cargo bench -p wabidb -- projection_read