Skip to content

Commit 3c6d7ef

Browse files
committed
fix/improve the shrinker
related to racket/racket#4531
1 parent d33343a commit 3c6d7ef

File tree

1 file changed

+71
-13
lines changed

1 file changed

+71
-13
lines changed

redex-examples/redex/examples/delim-cont/randomized-tests.rkt

Lines changed: 71 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"reduce.rkt"
55
(except-in redex/reduction-semantics plug)
66
racket/runtime-path)
7+
(module+ test (require rackunit))
78

89
(provide (all-defined-out))
910

@@ -585,15 +586,32 @@
585586
;; it can. redex-check doesn't currently have support for shrinkers, so
586587
;; this is just left on the side to be used when a counterexample is found.
587588

588-
(define (shrink p)
589-
(let loop ([p p])
590-
(cond
591-
[(same-behavior? p)
592-
#f]
593-
[else
594-
(or (for/or ([candidate (in-list (shrink/fixed-candidates p))])
595-
(loop candidate))
596-
p)])))
589+
(define (shrink p #:looks-buggy? [looks-buggy? (λ (x) (not (same-behavior? x)))])
590+
(cond
591+
[(looks-buggy? p)
592+
(let known-buggy-loop ([p p])
593+
;; p is known to have a bug
594+
(let shrunk-candidates-loop ([shrunk-ps (shrink/fixed-candidates p)])
595+
(cond
596+
[(null? shrunk-ps)
597+
;; none of the candidates were buggy, so `p`
598+
;; is a shrunken as we can make it
599+
p]
600+
[else
601+
(define candidate-p (car shrunk-ps))
602+
;; candidate-p is a shrunk version of `p`
603+
(cond
604+
[(looks-buggy? candidate-p)
605+
;; greedily take the first buggy-looking
606+
;; candidate and try to shrink it further
607+
(known-buggy-loop candidate-p)]
608+
[else
609+
;; keep looking at the shrunken candidates
610+
(shrunk-candidates-loop (cdr shrunk-ps))])])))]
611+
[else
612+
(raise-argument-error 'shrink
613+
"a term that looks buggy"
614+
p)]))
597615

598616
;; shrink/fixed-candidates : p -> (listof p)
599617
(define (shrink/fixed-candidates p)
@@ -602,7 +620,7 @@
602620
(define orig-size (size p))
603621
(define shrunk-es (shrink-candidates e))
604622
(define shrunk-ps '())
605-
(for ([shrunk-e shrunk-es])
623+
(for ([shrunk-e (in-list shrunk-es)])
606624
(define shrunk-p (fix-prog `(<> ,s ,o ,shrunk-e)))
607625
(when (< (size shrunk-p) orig-size)
608626
;; this `<` guards against a shrinking
@@ -678,22 +696,32 @@
678696

679697
(define (shrink-rule e)
680698
(match e
681-
[`(wcm ((,v1 ,v2) ,more ...) ,e)
682-
(list `(wcm ,more ,e))]
683699
[`(wcm () ,e) (list e)]
700+
[`(wcm ,bindings ,e)
701+
(for/list ([i (in-range (length bindings))])
702+
`(wcm ,(remove-ith bindings i) ,e))]
684703
[`(% ,e1 ,e2 ,e3) (those-with-holes-or-all (list e1 e2 e3))]
685704
[`(set! ,x ,e) (list e)]
686705
[`(if ,e1 ,e2 ,e3) (those-with-holes-or-all (list e1 e2 e3))]
687706
[`(dw ,x ,e1 ,e2 ,e3) (those-with-holes-or-all (list e1 e2 e3))]
688707
[`(list ,es ...) (those-with-holes-or-all es)]
689708
[`(λ (,x ...) ,e) (list e)]
690709
[`(cont ,v ,e) (those-with-holes-or-all (list v e))]
691-
[`(comp ,e) e]
710+
[`(comp ,e) (list e)]
692711
[`(,f ,x ...)
693712
(those-with-holes-or-all (cons f x))]
694713
[(? x?) (list 0)]
695714
[_ '()]))
696715

716+
(define (remove-ith l i)
717+
(append (take l i)
718+
(drop l (+ i 1))))
719+
(module+ test
720+
(check-equal? (remove-ith (list #f) 0) '())
721+
(check-equal? (remove-ith (list 0 1 2) 0) (list 1 2))
722+
(check-equal? (remove-ith (list 0 1 2) 1) (list 0 2))
723+
(check-equal? (remove-ith (list 0 1 2) 2) (list 0 1)))
724+
697725
(define (those-with-holes-or-all lst)
698726
(cond
699727
[(has-hole? lst)
@@ -709,3 +737,33 @@
709737
[(list? e) (for/or ([e (in-list e)])
710738
(loop e))]
711739
[else #f])))
740+
741+
(module+ test
742+
(define (test-shrink-candidates p)
743+
(define candidates (set))
744+
(define first-call? #t)
745+
(shrink p
746+
#:looks-buggy?
747+
(λ (x)
748+
(cond
749+
[first-call?
750+
(set! first-call? #f)
751+
#t]
752+
[else
753+
(set! candidates (set-add candidates x))
754+
#f])))
755+
candidates)
756+
757+
(check-equal? (test-shrink-candidates `(<> () () 1))
758+
(set))
759+
(check-equal? (test-shrink-candidates `(<> () () (+ 1 2)))
760+
(set `(<> () () +)
761+
`(<> () () 1)
762+
`(<> () () 2)))
763+
(check-equal? (test-shrink-candidates `(<> () () ((1 2) (3 4))))
764+
(set `(<> () () (1 2))
765+
`(<> () () (3 4))
766+
`(<> () () (1 (3 4)))
767+
`(<> () () (2 (3 4)))
768+
`(<> () () ((1 2) 3))
769+
`(<> () () ((1 2) 4)))))

0 commit comments

Comments
 (0)