fuzz
OCaml fuzz testing with Crowbar for protocol implementations. Use when Claude needs to: (1) Write fuzz tests for parsers and encoders, (2) Test roundtrip invariants (parse(encode(x)) = x), (3) Verify boundary conditions and error handling, (4) Test state machines and transitions, (5) Organize fuzz test suites for large codebases, (6) Run long-lived AFL campaigns with Crowbar
What this skill does
# OCaml Fuzz Testing with Crowbar
## Core Philosophy
1. **One fuzz file per module**: `fuzz_foo.ml` tests `lib/foo.ml`. Keeps tests organized and discoverable.
2. **Roundtrip everything**: If you have `encode` and `decode`, test `decode(encode(x)) = x`.
3. **Crash-safety first**: Parsers must never crash on arbitrary input, even malformed data.
4. **Boundary conditions matter**: Test edge cases (0, max values, empty input, overflow).
5. **State machines need transition coverage**: Test all valid and invalid state transitions.
## Build Configuration
### Simple single-file setup (per-package)
For standalone packages, use one fuzz file per package:
```
ocaml-foo/
├── lib/
├── fuzz/
│ ├── dune
│ └── fuzz_foo.ml
└── dune-project
```
**fuzz/dune:**
```lisp
(executable
(name fuzz_foo)
(modules fuzz_foo)
(libraries foo crowbar))
; Quick check with Crowbar (no AFL instrumentation)
(rule
(alias fuzz)
(deps fuzz_foo.exe)
(action
(run %{exe:fuzz_foo.exe})))
; AFL-instrumented build target (use with --profile=afl)
(rule
(alias fuzz-afl)
(deps
(source_tree input)
fuzz_foo.exe)
(action
(echo "AFL fuzzer built: %{exe:fuzz_foo.exe}\n")))
```
**Seed corpus**: Create `fuzz/input/` with sample inputs:
```bash
mkdir -p fuzz/input
echo -n "" > fuzz/input/empty
# Add representative samples as seed inputs
```
**fuzz/fuzz_foo.ml:**
```ocaml
open Crowbar
let test_parse_crash_safety buf =
ignore (Foo.parse buf);
check true
let () =
add_test ~name:"foo: parse crash safety" [ bytes ] test_parse_crash_safety
```
### Multi-module setup (large codebases)
For larger projects with many modules:
```lisp
(executable
(name fuzz)
(libraries crowbar borealis)
(modules
fuzz
fuzz_common
fuzz_foo
fuzz_bar))
```
Main entry point (`fuzz/fuzz.ml`):
```ocaml
(* Force linking of modules that register tests via side effects *)
let () =
Fuzz_common.run ();
Fuzz_foo.run ();
Fuzz_bar.run ()
```
Each fuzz module ends with:
```ocaml
let run () = ()
```
This ensures the module is linked and its `add_test` calls execute.
---
## Style Guidelines
When writing fuzz tests, follow these conventions:
1. **Define test functions separately** at the top of the file
2. **Register all tests at the end** with grouped `add_test` calls
3. **Use `bytes` directly** instead of custom generators
4. **Use a `truncate` helper** to limit input size for protocol messages
5. **Return `()` directly** - no need for `check true` in most cases
6. **Add `Crypto_rng_unix.use_default ()`** at the top if crypto is used
### Example structure
```ocaml
(** Fuzz tests for Foo module. *)
open Crowbar
open Fuzz_common
(** Decode - must not crash on arbitrary input. *)
let test_decode buf =
let buf = truncate buf in
let _ = Foo.decode (to_bytes buf) in
()
(** Roundtrip - valid values must round-trip. *)
let test_roundtrip buf =
let buf = truncate buf in
match Foo.decode (to_bytes buf) with
| Error _ -> ()
| Ok v ->
let encoded = Foo.encode v in
match Foo.decode encoded with
| Error _ -> fail "re-decode failed"
| Ok v' -> if v <> v' then fail "roundtrip mismatch"
(** Pretty-print - must not crash. *)
let test_pp n =
let v = Foo.of_int (n mod 4) in
let _ = Format.asprintf "%a" Foo.pp v in
()
(* All add_test calls in run function - no side effects at module init *)
let run () =
add_test ~name:"foo: decode crash safety" [ bytes ] test_decode;
add_test ~name:"foo: roundtrip" [ bytes ] test_roundtrip;
add_test ~name:"foo: pp" [ uint8 ] test_pp
```
**Main entry point (fuzz/fuzz.ml):**
```ocaml
(* Initialize crypto RNG if needed by any module *)
let () = Crypto_rng_unix.use_default ()
(* Register all fuzz tests *)
let () =
Fuzz_common.run ();
Fuzz_foo.run ();
Fuzz_bar.run ()
```
---
## Test Patterns
### 1. Crash-safety test (parsers must not crash)
```ocaml
open Crowbar
open Fuzz_common
(** Decode - must not crash on arbitrary input. *)
let test_decode buf =
let buf = truncate buf in
let _ = Foo.decode (to_bytes buf) in
()
(** Decode with exceptions - must not crash. *)
let test_decode_exn buf =
let buf = truncate buf in
(try ignore (Foo.decode_exn (to_bytes buf)) with _ -> ());
()
let run () =
add_test ~name:"foo: decode crash safety" [ bytes ] test_decode;
add_test ~name:"foo: decode_exn crash safety" [ bytes ] test_decode_exn
```
**Key points**:
- Use `bytes` generator for arbitrary binary input (produces `string` type)
- Use `ignore` to discard results without warnings
- Use `| exception _ -> ()` to catch any exceptions
- `check true` signals test passed
### 2. Roundtrip test (encode/decode pairs)
```ocaml
(** Roundtrip - valid values must round-trip. *)
let test_roundtrip buf =
let buf = truncate buf in
match Foo.decode (to_bytes buf) with
| Error _ -> () (* Invalid input is fine *)
| Ok original ->
let encoded = Foo.encode original in
match Foo.decode encoded with
| Error _ -> fail "re-decode failed"
| Ok decoded ->
if original <> decoded then fail "roundtrip mismatch"
let run () =
add_test ~name:"foo: roundtrip" [ bytes ] test_roundtrip
```
**Key points**:
- If initial decode fails, that's OK (input was invalid)
- If re-decode fails after encode, that's a bug
- Compare original and decoded values
### 3. Constrained type roundtrip (smart constructors)
```ocaml
(** APID roundtrip - valid values must round-trip. *)
let test_apid_roundtrip n =
match Apid.of_int n with
| None -> if n >= 0 && n <= 2047 then fail "should accept valid value"
| Some apid ->
let n' = Apid.to_int apid in
if n <> n' then fail "roundtrip mismatch"
let run () =
add_test ~name:"apid: roundtrip" [ range 2048 ] test_apid_roundtrip
```
### 4. Boundary tests
```ocaml
(** Max valid value. *)
let test_max_valid () =
match Apid.of_int 2047 with
| None -> fail "2047 should be valid"
| Some apid -> if Apid.to_int apid <> 2047 then fail "value mismatch"
(** Min valid value. *)
let test_min_valid () =
match Apid.of_int 0 with
| None -> fail "0 should be valid"
| Some apid -> if Apid.to_int apid <> 0 then fail "value mismatch"
let run () =
add_test ~name:"apid: max_valid" [ const () ] test_max_valid;
add_test ~name:"apid: min_valid" [ const () ] test_min_valid
```
**Key points**:
- Use `[ const () ]` for tests with no random input
- Never use `[]` as generator list (causes type error)
### 5. Invalid input rejection
```ocaml
(** Values above max must be rejected. *)
let test_invalid_above n =
let invalid = 2048 + n in
match Apid.of_int invalid with
| None -> ()
| Some _ -> fail "should reject values > 2047"
(** Negative values must be rejected. *)
let test_invalid_negative n =
let invalid = -(n + 1) in
match Apid.of_int invalid with
| None -> ()
| Some _ -> fail "should reject negative values"
let run () =
add_test ~name:"apid: invalid_above" [ range 1000 ] test_invalid_above;
add_test ~name:"apid: invalid_negative" [ range 1000 ] test_invalid_negative
```
### 6. Pretty-printer safety
```ocaml
(** Pretty-print - must not crash. *)
let test_pp buf =
let buf = truncate buf in
match Foo.decode (to_bytes buf) with
| Error _ -> ()
| Ok v -> let _ = Format.asprintf "%a" Foo.pp v in ()
let run () =
add_test ~name:"foo: pp" [ bytes ] test_pp
```
### 7. State machine transitions
```ocaml
(** Test valid state transitions. *)
let test_activate_pending kid algo material_buf =
let material = to_bytes material_buf in
if Bytes.length material = 0 then ()
else
let key = Key.v ~kid ~algorithm:algo ~material in
match Key.activate key with
| Error _ -> () (* May fail if material invalid *)
| Ok active_key ->
if Key.state active_key <> Key.Active then fail "wrong state"
(** Test invalid state transitions return errors. *)
let test_activate_empty_fails kid algo =
let key = Key.empty ~kid ~algorithm:algo in
match Key.activate key with
| Ok _ -> fail "should fail on Empty key"
|Related in Security
mac-ops
IncludedComprehensive macOS workstation operations — diagnose kernel panics, identify failing drives, audit launchd startup items, decode wake reasons, triage TCC permission denials, manage APFS snapshots, recover from no-boot. Use for: Mac is slow, slow bootup, won't boot, kernel panic, kernel_task hot, mds_stores CPU, photoanalysisd, cloudd, login loop, gray screen, sleep wake failure, drive failing, IO errors, APFS snapshots eating space, Time Machine local snapshots, Spotlight indexing, launchd, LaunchAgent, LaunchDaemon, login items, TCC permissions, Full Disk Access, Screen Recording denied, Gatekeeper, quarantine, com.apple.quarantine, app is damaged, helper tool, /Library/PrivilegedHelperTools, pmset, wake reasons, dark wake, sysdiagnose, panic.ips, DiagnosticReports, configuration profile, MDM profile, remote diagnostics over SSH.
a11y-audit
IncludedRun accessibility audits on web projects combining automated scanning (axe-core, Lighthouse) with WCAG 2.1 AA compliance mapping, manual check guidance, and structured reporting. Output is configurable: markdown report only, markdown plus machine-readable JSON, or markdown plus issue tracker integration. Use this skill whenever the user mentions "accessibility audit", "a11y audit", "WCAG audit", "accessibility check", "compliance scan", or asks to check a web project for accessibility issues. Also trigger when the user wants to verify WCAG conformance or map findings to a specific standard (CAN-ASC-6.2, EN 301 549, ADA/AODA).
erpclaw
IncludedAI-native ERP system with self-extending OS. Full accounting, invoicing, inventory, purchasing, tax, billing, HR, payroll, advanced accounting (ASC 606/842, intercompany, consolidation), and financial reporting. 413 actions across 14 domains, 43 expansion modules. Constitutional guardrails, adversarial audit, schema migration. Double-entry GL, immutable audit trail, US GAAP.
assess
IncludedAssesses and rates quality 0-10 across multiple dimensions (correctness, maintainability, security, performance, testability, simplicity) with pros/cons analysis. Compares against project conventions and prior decisions from memory. Produces structured evaluation reports with actionable improvement suggestions. Use when evaluating code, designs, architectures, or comparing alternative approaches.
spring-boot-security-jwt
IncludedProvides JWT authentication and authorization patterns for Spring Boot 3.5.x covering token generation with JJWT, Bearer/cookie authentication, database/OAuth2 integration, and RBAC/permission-based access control using Spring Security 6.x. Use when implementing authentication or authorization in Spring Boot applications.
code-hardcode-audit
IncludedDetect hardcoded values, magic numbers, and leaked secrets. TRIGGERS - hardcode audit, magic numbers, PLR2004, secret scanning.