A mutation framework for s-expression languages.
See the documentation for a full overview, and the example below for a teaser.
raco pkg install mutate
https://docs.racket-lang.org/mutate/index.html
or, once installed,
raco docs mutate
To define a mutation engine that does two things:
- swap the branches of if’s
- negate all numeric constants
The same code is also in full-example.rkt
.
#lang racket
(require syntax/parse
"../main.rkt"
"../quick.rkt")
(define program-mutations
(build-mutation-engine
#:mutators
(define-simple-mutator (if-swap stx)
#:pattern ({~literal if} cond t e)
#:when (list? (syntax->datum #'cond))
#'(if cond e t))
(define-constant-mutator (constant-swap v)
[(? number?) #:-> (- v)])
#:syntax-only
#:streaming
#:module-mutator))
(define program-to-mutate
#'(module test-program racket
(#%module-begin
(require "a.rkt")
(define x (if (yes?) 0 42))
(define y (if (negative? x)
"negative!"
(if (zero? x)
"zero!"
"positive!")))
(displayln y))))
(map syntax->datum
(stream->list (program-mutations program-to-mutate)))
;; =>
#;'((module test-program racket
(#%module-begin
(require "a.rkt")
(define x (if (yes?) 42 0))
(define y (if (negative? x) "negative!" (if (zero? x) "zero!" "positive!")))
(displayln y)))
(module test-program racket
(#%module-begin
(require "a.rkt")
(define x (if (yes?) 0 -42))
(define y (if (negative? x) "negative!" (if (zero? x) "zero!" "positive!")))
(displayln y)))
(module test-program racket
(#%module-begin
(require "a.rkt")
(define x (if (yes?) 0 42))
(define y (if (negative? x) (if (zero? x) "zero!" "positive!") "negative!"))
(displayln y)))
(module test-program racket
(#%module-begin
(require "a.rkt")
(define x (if (yes?) 0 42))
(define y (if (negative? x) "negative!" (if (zero? x) "positive!" "zero!")))
(displayln y))))
Add support for reporting statistics about number of mutants, distribution of mutators triggering, etc
This can even include visualization support.