mutate-csharp-dafny applies mutation analysis to automatically generate test cases for the Dafny compiler,
and integrates the workflow with existing fuzzing techniques to also simultaneously (and automatically) discover bugs
in the Dafny compiler.
- Fuzzing:
mutate-csharp-dafnyuses a third-party fuzzer (fuzz-d) to generate random programs in Dafny, which is used to apply differential testing on the Dafny compiler backends. - Non-redundant test case generation: if differential testing on a randomly generated program passes the checks,
mutate-csharp-dafnyfuzzes mutants that are undetected by the Dafny regression test suite with the same program, and persists the program as a test case candidate to a specified directory if the compiler crashes or miscompiles given the input. - Program reduction:
mutate-csharp-dafnyuses a third-party program reducer (PERSES) to shrink programs into a debuggable program that can be submitted to the compiler developers. - TRX parser:
.trxis a custom test result format that inherits XML syntax used by the .NET test framework. This can be used to sort test cases by execution time. - Test name extractor: When applying
dotnet --list-testsoption, the same list cannot be trivially fed back to the .NETtestcommand. This escapes the characters necessary to allow the test frameworks to recognise the tests by its name. - Random mutant sampler: Given the mutation registry, randomly sample a specified number of mutants for mutation analysis.
- Examples:
mutate-csharp-dafnyhosts a variety of scripts that showcase howmutate-csharpcan be utilised to apply mutation analysis on a program under test.
To clone mutate-csharp-dafny, run:
git clone --recursive git@github.com:mutatecsharp/mutate-csharp-dafny.gitapt install python3.11
alias python=python3.11
python -m pip install loguruInstall dependencies for fuzz-d.
Install dependencies for PERSES.
mutate-csharp-dafny is supported on Ubuntu 20.04.
At the time of writing, the Dafny compiler is tested with python3.11.
mutate-csharp-dafny logs all actions run by the driver using loguru. To install loguru, run:
python -m pip install logurumutate-csharp-dafny is designed such that all scripts are run within the root directory of mutate-csharp-dafny.
mutate-csharp-dafny requires that all cloned repositories involving mutate-csharp to be within a volume directory,
which can be set with:
export VOLUME_ROOT= {{ folder containing mutate-csharp-dafny }}For the python scripts, prefix the execution with:
PYTHONPATH=$(pwd) ...where the current directory is the root of mutate-csharp-dafny.
PYTHONPATH=$(pwd) ./fuzzing/run-fuzzer-campaign.py --help
usage: run-fuzzer-campaign.py [-h] [--dry-run] [--seed SEED] [--fuzz_d FUZZ_D] [--dafny DAFNY]
[--mutated_dafny MUTATED_DAFNY] [--traced_dafny TRACED_DAFNY]
--output_directory OUTPUT_DIRECTORY [--mutation_registry MUTATION_REGISTRY]
[--tracer_registry TRACER_REGISTRY] [--passing_tests PASSING_TESTS]
[--regression_test_trace_dir REGRESSION_TEST_TRACE_DIR]
[--mutation_test_result MUTATION_TEST_RESULT [MUTATION_TEST_RESULT ...]]
[--source_file_relative_path SOURCE_FILE_RELATIVE_PATH [SOURCE_FILE_RELATIVE_PATH ...]]
[--compilation_timeout COMPILATION_TIMEOUT]
[--generation_timeout GENERATION_TIMEOUT]
[--execution_timeout EXECUTION_TIMEOUT]
[--test_campaign_timeout TEST_CAMPAIGN_TIMEOUT]
options:
-h, --help show this help message and exit
--dry-run Perform dry run.
--seed SEED Optional. Seed for random number generator. Useful to reproduce results.
--fuzz_d FUZZ_D Path to the fuzz-d project.
--dafny DAFNY Path to the non-mutated Dafny project.
--mutated_dafny MUTATED_DAFNY
Path to the mutated Dafny project.
--traced_dafny TRACED_DAFNY
Path to the execution-trace instrumented Dafny project.
--output_directory OUTPUT_DIRECTORY
Path to the persisted/temporary interesting programs output directory.
--mutation_registry MUTATION_REGISTRY
Path to registry generated after mutating the Dafny codebase (.json).
--tracer_registry TRACER_REGISTRY
Path to registry generated after instrumenting the Dafny codebase to trace mutant
executions (.json).
--passing_tests PASSING_TESTS
Path to file containing lists of passing tests.
--regression_test_trace_dir REGRESSION_TEST_TRACE_DIR
Path to directory containing all mutant execution traces after running the Dafny
regression test suite.
--mutation_test_result MUTATION_TEST_RESULT [MUTATION_TEST_RESULT ...]
Path to mutation analysis result(s) of the Dafny regression test suite (.json). The
analysis results will be merged if multiple results are passed.
--source_file_relative_path SOURCE_FILE_RELATIVE_PATH [SOURCE_FILE_RELATIVE_PATH ...]
Optional. If specified, only consider mutants for the specified file(s).
--compilation_timeout COMPILATION_TIMEOUT
Maximum second(s) allowed to compile generated program with the non-mutated Dafny
compiler.
--generation_timeout GENERATION_TIMEOUT
Maximum second(s) allowed to generate program with fuzz-d.
--execution_timeout EXECUTION_TIMEOUT
Maximum second(s) allowed to execute fuzz-d generated program compiled by the non-
mutated Dafny compiler.
--test_campaign_timeout TEST_CAMPAIGN_TIMEOUT
Test campaign time budget in hour(s).The reduce-regular-program.sh is an interestingness test script example and should be modified to suit the
conditions required to shrink the program.
PYTHONPATH=$(pwd) ./parse-tests.py --help
usage: parse-tests.py [-h] --framework FRAMEWORK --passing-tests PASSING_TESTS
options:
-h, --help show this help message and exit
--framework FRAMEWORK
Test target framework. Supports: nunit, mstest.
--passing-tests PASSING_TESTS
Path to list of names of passing tests../mutate-compiler.sh
./generate-tracer.sh
./trace-compiler.sh
./trace-single-test.sh
./run-mutation-testing.shoverwrite-artifact-output.sh: Redirects all output from temporary directory to a specified directory.auto-delete-compilations.py: Watches the specified directory and deletes all compilation artifacts that are over the maximum time limit that a test/mutant combination can be assessed.fuzz-tests.sh: Runs the combined fuzzing / test generation workflow.allow-mutation-env-var.py/allow-tracer-env-var.py: Whitelist the specific mutation file ID environment variables based on the mutation registry.
mutate-csharp-dafny is covered under the terms of the MIT license.
Contributions are welcome!