racket/collects/tests/mzscheme/deep.ss
2008-04-08 21:42:38 +00:00

243 lines
5.8 KiB
Scheme

(load-relative "loadtest.ss")
(Section 'deep)
; Test deep stacks
(define (nontail-loop n esc)
(let loop ([n n])
(if (zero? n)
(esc 0)
(sub1 (loop (sub1 n))))))
(define proc-depth (find-depth (lambda (n) (nontail-loop n (lambda (x) x)))))
(printf "non-tail loop overflows at ~a~n" proc-depth)
(test (- proc-depth) 'deep-recursion (nontail-loop proc-depth (lambda (x) x)))
(test 0 'deep-recursion-escape/ec
(let/ec k
(nontail-loop proc-depth k)))
(test 0 'deep-recursion-escape/cc
(let/cc k
(nontail-loop proc-depth k)))
(test 0 'deep-recursion-resume/escape
((let/ec k
(nontail-loop proc-depth
(lambda (v)
(let/cc inside
(k inside))
(k (lambda () 0)))))))
(test 0 'deep-recursion-resume/abort
(call-with-continuation-prompt
(lambda ()
(nontail-loop proc-depth
(lambda (v)
(abort-current-continuation
(default-continuation-prompt-tag)
(lambda () 0)))))))
(test 0 'deep-recursion-resume/escape/thread
(let ([v #f])
(thread-wait
(thread
(lambda ()
(set! v
((let/ec k
(nontail-loop proc-depth
(lambda (v)
(let/cc inside
(k (lambda ()
(thread-wait (thread inside))
0)))
(k (lambda () 0))))))))))
v))
(test (- proc-depth) 'deep-recursion-resume
((lambda (x) (if (procedure? x) (x) x))
(let/ec k
(nontail-loop proc-depth
(lambda (v)
(let/cc inside
(k inside))
0)))))
(define (read-deep depth)
(define paren-port
(let* ([depth depth]
[closing? #f]
[count depth])
(make-input-port
'name
(lambda (s)
(bytes-set!
s
0
(cond
[closing?
(if (= count depth)
eof
(begin
(set! count (add1 count))
(char->integer #\)) ))]
[else
(set! count (sub1 count))
(when (zero? count)
(set! closing? #t))
(char->integer #\()]))
1)
#f
void)))
(read paren-port))
(define read-depth (find-depth read-deep))
(printf "nested paren read overflows at ~a~n" read-depth)
(define deep-list (read-deep read-depth))
(test #t 'read-deep (pair? deep-list))
(define s (open-output-string))
(display deep-list s)
(test 'ok 'display 'ok)
(test #t 'equal? (equal? deep-list (read (open-input-string (get-output-string s)))))
(define (try-pairs mk-a mk-d cons)
(let ()
(define l1 (mk-a 0))
(define l2 (mk-a 0))
(define l3 (mk-a 1))
(test #t equal? l1 l2)
(test #f equal? l1 l3)
(test #t equal? (cons l1 l3) (cons l2 l3))
(test #f equal? (cons l1 l2) (cons l2 l3))
(test #t = (equal-hash-code l1) (equal-hash-code l2)))
(let ()
(define l1 (mk-d #f))
(define l2 (mk-d #f))
(define l3 (mk-d #t))
(test #t equal? l1 l2)
(test #f equal? l1 l3)
(test #t equal? (cons l1 l3) (cons l2 l3))
(test #f equal? (cons l1 l2) (cons l2 l3))
(test #t = (equal-hash-code l1) (equal-hash-code l2))))
(try-pairs (lambda (v)
(read (open-input-string (format "#0=(cons ~a #0#)" v))))
(lambda (v)
(read (open-input-string (format "#0=(cons #0# ~a)" v))))
cons)
(try-pairs (lambda (v)
(let ([p (mcons v v)])
(set-mcdr! p p)
p))
(lambda (v)
(let ([p (mcons v v)])
(set-mcar! p p)
p))
mcons)
(define (vec-test i)
(define l1 (vector 0 0))
(define l2 (vector 0 0))
(define l3 (vector 1 1))
(vector-set! l1 i l1)
(vector-set! l2 i l2)
(vector-set! l3 i l3)
(test #t equal? l1 l2)
(test #f equal? l1 l3)
(test #t equal? (vector l1 l3) (vector l2 l3))
(test #f equal? (vector l1 l2) (vector l2 l3))
(test #t = (equal-hash-code l1) (equal-hash-code l2)))
(vec-test 0)
(vec-test 1)
(define-struct a (b c) #:inspector (make-inspector) #:mutable)
(define l1 (make-a 0 #f))
(set-a-b! l1 l1)
(define l2 (make-a 0 #f))
(set-a-b! l2 l2)
(define l3 (make-a 0 #t))
(set-a-b! l3 l2)
(test #t equal? l1 l2)
(test #f equal? l1 l3)
(test #t equal? (make-a l1 l3) (make-a l2 l3))
(test #f equal? (make-a l1 l2) (make-a l2 l3))
(test #t = (equal-hash-code l1) (equal-hash-code l2))
(define l1 (box 0))
(set-box! l1 l1)
(define l2 (box 0))
(set-box! l2 l2)
(test #t equal? l1 l2)
(test #t = (equal-hash-code l1) (equal-hash-code l2))
;; ----------------------------------------
;; Overflow in hashing:
(define (hash-deep n)
(let loop ([n n][a null])
(if (zero? n)
a
(loop (sub1 n) (list a "apple")))))
(define (init-hash-table ht)
(let loop ([n 25])
(unless (zero? n)
(hash-set! ht (gensym) (gensym))
(loop (sub1 n)))))
(define hash-depth
(let ([ht (make-hash)])
(init-hash-table ht)
(find-depth
(lambda (n)
(nontail-loop (quotient proc-depth 3)
(lambda (x)
(hash-set! ht
(hash-deep n)
#t)
x))))))
(printf "hashing overflows at ~a\n" hash-depth)
(define (try-deep-hash hash-depth put-depth get-depth)
(let* ([ht (make-hash)]
[val (gensym)]
[key (hash-deep hash-depth)]
[code (equal-hash-code key)])
(init-hash-table ht)
(nontail-loop put-depth
(lambda (x)
(test code 'code (equal-hash-code key))
(hash-set! ht key val)
x))
(nontail-loop get-depth
(lambda (x)
(test code 'code (equal-hash-code key))
(test val 'deep-hash (hash-ref ht key))
x))))
(for-each (lambda (hash-depth)
(for-each (lambda (proc-depth)
(try-deep-hash hash-depth 0 proc-depth))
(list 0
(quotient proc-depth 2)
(quotient proc-depth 3)
(quotient proc-depth 4))))
(list hash-depth
(* 2 hash-depth)
(quotient hash-depth 2)))
;; ----------------------------------------
(report-errs)