How do I run the EK9 fuzzer?
← Fuzzing and Mutation Testing · Ref: Q750
The -fuzz flag runs grammar-based fuzz testing that stress-tests the compiler with randomly generated EK9 source files.
BASIC USAGE
ek9 -fuzz 60
This runs the fuzzer for 60 minutes, generating random EK9 programs and feeding them through the full compilation pipeline. Crash-inducing inputs are saved to ./fuzz-crashes/ automatically.
DURATION
The parameter is in minutes. Use longer durations for deeper coverage:
ek9 -fuzz 5 Quick smoke test (5 minutes). ek9 -fuzz 60 Normal development session (1 hour). ek9 -fuzz 1440 Overnight run (24 hours).
WORKER THREADS
The fuzzer uses multiple worker threads to maximise throughput. It automatically detects available CPU cores and distributes work across them.
WHAT IT GENERATES
Each iteration creates a syntactically-aware EK9 source file containing randomly selected constructs: functions, classes, records, traits, enumerations, streams, control flow, operators, and generics. The generator understands EK9 grammar rules so that most files parse successfully and exercise deeper compiler phases.
CRASH FILES
When the compiler throws an unexpected exception on a generated file, that file is saved to ./fuzz-crashes/ with a descriptive filename. These files are minimal reproduction cases for bug reports.
See Q749 for fuzzing overview. See Q751 for output formats. See Q752 for the HTML dashboard. See Q757 for crash file details. See Q2 for compile and run basics.
Example
defines module qa.fuzzingandmutation.runfuzzer <?- Example code that a fuzzer might generate and test. This demonstrates the kind of constructs the grammar-based fuzzer combines: classes with operators, pure functions, stream pipelines, and control flow. -?> defines class Temperature reading as Float: Float() Temperature() -> initial as Float this.reading :=? initial operator $ as pure <- rtn as String: $this.reading operator < as pure -> other as Temperature <- rtn as Boolean: this.reading < other.reading default operator ? defines function averageReading() -> readings as List of Float <- average as Float: 0.0 count <- length readings zero <- 0 if count > zero total <- 0.0 for reading in readings total: total + reading average: total / #^count defines program RunFuzzerDemo() stdout <- Stdout() readings <- [20.5, 22.1, 19.8, 25.3, 18.7] avg <- averageReading(readings) stdout.println(`Average temperature: ${avg}`) cold <- Temperature(15.0) warm <- Temperature(30.0) stdout.println(`Cold: ${cold}, Warm: ${warm}`) coldLessThanWarm <- cold < warm stdout.println(`Cold < Warm: ${coldLessThanWarm}`)
Other ways to ask this
- What is the ek9 -fuzz flag for?
- How do I fuzz the EK9 compiler to find crashes?
- How long should I run the EK9 fuzzer?
Coming from another language?
Java: no built-in fuzzer, use Jazzer or JQF (separate tools, separate setup). Python: no built-in, Hypothesis for property-based testing, Atheris for coverage-guided fuzzing. Rust: cargo-fuzz wraps libFuzzer (must write harness functions). Go: go test -fuzz (built-in since 1.18 but requires writing Fuzz* functions). EK9: ek9 -fuzz <minutes> runs immediately with zero setup, no harness code needed.
Keywords: run, thread, crash, fuzz, grammar, generate, random, compiler, smoke, minutes, worker, duration