#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))) ;; 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))))