192 lines
5.6 KiB
Racket
192 lines
5.6 KiB
Racket
#lang racket/base
|
|
|
|
(require
|
|
"test-utils.rkt"
|
|
racket/base
|
|
racket/port
|
|
racket/promise
|
|
rackunit
|
|
(for-syntax
|
|
racket/base
|
|
racket/format
|
|
syntax/parse))
|
|
|
|
(provide tests)
|
|
(gen-test-main)
|
|
|
|
(define-namespace-anchor anchor)
|
|
|
|
(define base-ns
|
|
(delay
|
|
(define ns (namespace-anchor->empty-namespace anchor))
|
|
(parameterize ([current-namespace ns])
|
|
(namespace-require 'typed/racket/base))
|
|
ns))
|
|
|
|
;; get-ns: boolean? -> namespace?
|
|
;; Returns a namespace with the bindings of typed/racket/base.
|
|
;; If the argument is true, then it is a new namespace. This is slower but allows for tests that need
|
|
;; to mutate the namespace to not clash with each other.
|
|
(define (get-ns fresh)
|
|
(if fresh
|
|
(let ([ns (variable-reference->empty-namespace
|
|
(eval '(#%variable-reference) (force base-ns)))])
|
|
(parameterize ([current-namespace ns])
|
|
(namespace-require 'typed/racket/base)
|
|
ns))
|
|
(force base-ns)))
|
|
|
|
(begin-for-syntax
|
|
(define-splicing-syntax-class fresh-kw
|
|
(pattern (~seq) #:attr fresh #'#f)
|
|
(pattern #:fresh #:attr fresh #'#t)))
|
|
|
|
(define-syntax (test-form-exn stx)
|
|
(syntax-parse stx
|
|
[(_ f:fresh-kw regexp:expr form:expr)
|
|
(quasisyntax/loc stx
|
|
(test-case #,(~a (syntax->datum #'form))
|
|
(check-exn
|
|
regexp
|
|
(lambda ()
|
|
(eval `(#%top-interaction .
|
|
,(syntax->datum #'form)) (get-ns f.fresh))))))]))
|
|
|
|
(define-syntax (test-form-not-exn stx)
|
|
(syntax-parse stx
|
|
[(_ f:fresh-kw form:expr)
|
|
(quasisyntax/loc stx
|
|
(test-case #,(~a (syntax->datum #'form))
|
|
(check-not-exn
|
|
(lambda ()
|
|
(eval `(#%top-interaction .
|
|
,(syntax->datum #'form)) (get-ns f.fresh))))))]))
|
|
|
|
(define-syntax (test-form stx)
|
|
(syntax-parse stx
|
|
[(_ f:fresh-kw (~seq regexp:expr form:expr) ...)
|
|
(quasisyntax/loc stx
|
|
(test-case #,(~a (syntax->datum #'(form ...)))
|
|
(define ns (get-ns f.fresh))
|
|
(check-regexp-match
|
|
regexp
|
|
(with-output-to-string
|
|
(lambda ()
|
|
(eval `(#%top-interaction .
|
|
,(syntax->datum #'form)) ns)))) ...))]))
|
|
|
|
;; Add 'only at the toplevel tests'
|
|
(define tests
|
|
(test-suite "Interactive tests"
|
|
|
|
(test-form #:fresh
|
|
#rx"" (module test racket)
|
|
#rx"" (define module displayln)
|
|
#rx"racket" (module 'racket))
|
|
|
|
(test-form (regexp-quote "String")
|
|
"foo")
|
|
(test-form (regexp-quote "String")
|
|
(begin "foo"))
|
|
(test-form (regexp-quote "String")
|
|
(begin "foo" "bar"))
|
|
(test-form #rx"^$"
|
|
(begin))
|
|
(test-form #rx"^$"
|
|
(define x "foo"))
|
|
(test-form #rx"^$"
|
|
(begin (: x String)
|
|
(define x "foo")))
|
|
(test-form #rx"^$"
|
|
(struct foo ()))
|
|
|
|
;; Make sure that optimized expressions work
|
|
(test-form #rx"Flonum"
|
|
(+ 1.0 2.0))
|
|
|
|
;; PR 14487
|
|
(test-form-not-exn
|
|
(begin
|
|
(require/typed racket/base
|
|
[#:opaque Evt evt?]
|
|
[alarm-evt (Real -> Evt)]
|
|
[sync (Evt -> Any)])
|
|
(void evt?)))
|
|
|
|
;; PR 14380
|
|
(test-form-not-exn (begin - (void)))
|
|
|
|
;; bug that delayed 6.3
|
|
(test-form-exn #rx"Any"
|
|
(let ((x : Any 0))
|
|
(define (f) (set! x #t))
|
|
(when (number? x)
|
|
(add1 x))))
|
|
|
|
(test-form-not-exn
|
|
(let ((x 0))
|
|
(set! x 1)))
|
|
|
|
;; test message for undefined id
|
|
(test-form-exn #rx"either undefined or missing a type annotation"
|
|
(a-name-that-isnt-bound))
|
|
|
|
;; Make sure unannotated definitions with the wrong number of values
|
|
;; don't produce an internal error
|
|
(test-form-exn #rx"Expression should produce 1 values"
|
|
(define zzzzz (values 1 2)))
|
|
|
|
(test-form #rx"1"
|
|
(:type 1))
|
|
(test-form (regexp-quote "(U Positive-Byte Zero)")
|
|
(:type Byte))
|
|
(test-form (regexp-quote "(U 0 1 Byte-Larger-Than-One")
|
|
(:type #:verbose Byte))
|
|
(test-form-exn #rx":type.*applied to arguments"
|
|
:type)
|
|
(test-form-exn #rx":type.*only valid at the top-level"
|
|
(list (:type)))
|
|
(test-form-exn #rx"exactly one argument"
|
|
(:type))
|
|
(test-form-exn #rx"exactly one argument"
|
|
(:type 1 2))
|
|
(test-form-exn #rx"exactly one argument"
|
|
(:type #:verbose))
|
|
|
|
(test-form #rx"Positive-Index"
|
|
(:print-type (+ 1 1)))
|
|
(test-form (regexp-quote "(values One One)")
|
|
(:print-type (values 1 1)))
|
|
(test-form-exn #rx":print-type.*applied to arguments"
|
|
:print-type)
|
|
(test-form-exn #rx":print-type.*only valid at the top-level"
|
|
(list (:print-type)))
|
|
(test-form-exn #rx"exactly one argument"
|
|
(:print-type))
|
|
(test-form-exn #rx"exactly one argument"
|
|
(:print-type 1 2))
|
|
|
|
(test-form (regexp-quote "(-> 4 Zero Zero)")
|
|
(:query-type/args * 4 0))
|
|
(test-form-exn #rx":query-type/args.*applied to arguments"
|
|
:query-type/args)
|
|
(test-form-exn #rx":query-type/args.*only valid at the top-level"
|
|
(list (:query-type/args)))
|
|
(test-form-exn #rx"at least one argument"
|
|
(:query-type/args))
|
|
|
|
(test-form (regexp-quote "(-> One)")
|
|
(:query-type/result * 1))
|
|
(test-form #rx"not in the given function's range.\n"
|
|
(:query-type/result + String))
|
|
(test-form-exn #rx":query-type/result.*applied to arguments"
|
|
:query-type/result)
|
|
(test-form-exn #rx":query-type/result.*only valid at the top-level"
|
|
(list (:query-type/result)))
|
|
(test-form-exn #rx"exactly two arguments"
|
|
(:query-type/result))
|
|
(test-form-exn #rx"exactly two arguments"
|
|
(:query-type/result 1 2 3))
|
|
(test-form #rx"not in the given function's range"
|
|
(:query-type/result syntax-local-expand-expression Boolean))))
|