Add a bunch of tests for contract creation error messages.

Also minor fixes to said error messages.
This commit is contained in:
Eric Dobson 2013-12-15 16:49:25 -08:00
parent 09e28b272c
commit 7060bdd0f8
2 changed files with 88 additions and 33 deletions

View File

@ -237,16 +237,16 @@
(map t->c rngs) (map t->c rngs)
(and rst (t->c/neg rst))))] (and rst (t->c/neg rst))))]
;; functions with filters or objects ;; functions with filters or objects
[(arr: dom (Values: (list (Result: rngs _ _) ...)) rst #f '()) [(arr: dom (Values: (list (Result: rngs _ _) ...)) rst #f kws)
(if (not (from-untyped? typed-side)) (if (not (from-untyped? typed-side))
(values (map t->c/neg dom) (let-values ([(mand-kws opt-kws) (partition-kws kws)])
null (values (append (map t->c/neg dom) (append-map conv mand-kws))
(append-map conv opt-kws)
(map t->c rngs) (map t->c rngs)
(and rst (t->c/neg rst))) (and rst (t->c/neg rst))))
(exit (fail #:reason (exit (fail #:reason
(~a "cannot generate contract for function type" (~a "cannot generate contract for function type"
" with filters or objects."))))] " with filters or objects."))))]))
[_ (exit (fail))]))
(with-syntax* (with-syntax*
([(dom* ...) (process-dom dom*)] ([(dom* ...) (process-dom dom*)]
[(opt-dom* ...) opt-dom*] [(opt-dom* ...) opt-dom*]
@ -255,7 +255,9 @@
[(rst-spec ...) (if rst #'(#:rest (listof rst*)) #'())]) [(rst-spec ...) (if rst #'(#:rest (listof rst*)) #'())])
;; Garr, I hate case->! ;; Garr, I hate case->!
(if (and (pair? (syntax-e #'(opt-dom* ...))) case->) (if (and (pair? (syntax-e #'(opt-dom* ...))) case->)
(exit (fail)) (exit (fail #:reason
(~a "cannot generate contract for case function type"
" with optional keyword arguments")))
(if (or rst (pair? (syntax-e #'(opt-dom* ...)))) (if (or rst (pair? (syntax-e #'(opt-dom* ...))))
(if case-> (if case->
#'(dom* ... rst-spec ... . -> . rng*) #'(dom* ... rst-spec ... . -> . rng*)
@ -487,12 +489,11 @@
(set-impersonator!) (set-impersonator!)
#`(parameter/c #,(t->c in) #,(t->c out))] #`(parameter/c #,(t->c in) #,(t->c out))]
[(Hashtable: k v) [(Hashtable: k v)
(when (equal? kind flat-sym) (exit (fail))) (when (equal? kind flat-sym)
(exit (fail #:reason (~a "expected a first-order contract, but got a hashtable."))))
#`(hash/c #,(t->c k #:kind chaperone-sym) #,(t->c v) #:immutable 'dont-care)] #`(hash/c #,(t->c k #:kind chaperone-sym) #,(t->c v) #:immutable 'dont-care)]
[(Channel: t) [(Channel: t)
(set-chaperone!) (set-chaperone!)
#`(channel/c #,(t->c/both t))] #`(channel/c #,(t->c/both t))]
[else [else
(exit (fail #:reason "contract generation not supported for this type"))])))) (exit (fail #:reason "contract generation not supported for this type"))]))))

View File

@ -4,38 +4,92 @@
(for-syntax scheme/base) (for-syntax scheme/base)
(for-template scheme/base) (for-template scheme/base)
(private type-contract) (private type-contract)
(types abbrev numeric-tower) (rep type-rep)
(types abbrev numeric-tower union)
rackunit) rackunit)
(define-syntax-rule (t e) (define-syntax-rule (t e)
(test-not-exn (test-case (format "~a" 'e)
(format "~a" e) (let ((v e))
(λ () (with-check-info (('type v))
(type->contract (type->contract
e e
(λ (#:reason [reason #f]) (λ (#:reason [reason #f])
(error "type could not be converted to contract")))))) (fail-check (or reason "Type could not be converted to contract"))))))))
(define-syntax-rule (t/fail e) (define-syntax-rule (t/fail e expected-reason)
(test-not-exn (test-case (format "~a" 'e)
(format "~a" e) (let ((v e))
(λ () (with-check-info (('expected expected-reason)
('type v))
(define reason
(let/ec exit (let/ec exit
(type->contract e (λ (#:reason [reason #f]) (exit #t))) (type->contract v (λ (#:reason [reason #f]) (exit reason)))
(error "type could be converted to contract"))))) (fail-check "type could be converted to contract")))
(unless (regexp-match? expected-reason reason)
(with-check-info (('reason reason))
(fail-check "Reason didn't match expected.")))))))
(define known-bugs
(test-suite "Known Bugs"
;; This should fail as case-> doesn't support keyword arguments.
(t
(make-Function
(list
(make-arr* (list) -Boolean #:kws (list (make-Keyword '#:key Univ #t)))
(make-arr* (list Univ Univ) -Boolean #:kws (list (make-Keyword '#:key2 Univ #t))))))
;; Polydotted functions should work
(t/fail (-polydots (a) (->... (list) (a a) -Symbol))
"not supported for this type")))
(define (contract-tests) (define (contract-tests)
(test-suite "Contract Tests" (test-suite "Contract Tests"
known-bugs
(t (-Number . -> . -Number)) (t (-Number . -> . -Number))
(t (-Promise -Number)) (t (-Promise -Number))
(t (-set Univ)) (t (-set Univ))
(t (-> Univ -Boolean : -Symbol))
(t (->key -Symbol #:key -Boolean #t Univ))
(t (make-Function
(list (make-arr* (list Univ) -Boolean #:kws (list (make-Keyword '#:key Univ #t))
#:filters -Symbol))))
(t (-struct #'struct-name #f (list (make-fld -Symbol #'acc #f))))
;; Adapted from PR 13815 ;; Adapted from PR 13815
(t (-poly (a) (-> a a))) (t (-poly (a) (-> a a)))
(t (-poly (a) (-mu X (-> a X)))) (t (-poly (a) (-mu X (-> a X))))
(t (-poly (a) (-poly (b) (-> a a)))) (t (-poly (a) (-poly (b) (-> a a))))
(t (-poly (a) (-App (-poly (b) (-> a a)) (list -Number) #'#f))) (t (-poly (a) (-App (-poly (b) (-> a a)) (list -Number) #'#f)))
(t/fail (-poly (a) -Flonum)) (t/fail
(t/fail (-poly (a) (-set -Number))))) (make-Function
(list (make-arr* (list) -Boolean #:kws (list (make-Keyword '#:key Univ #f)))
(make-arr* (list Univ) -Boolean #:kws (list (make-Keyword '#:key2 Univ #f)))))
"case function type with optional keyword arguments")
(t/fail (-poly (a) -Flonum) "non-function polymorphic type")
(t/fail (-> (-> Univ -Boolean : -Symbol) -Symbol)
"function type with filters or objects")
(t/fail (-poly (a) (-set -Number)) "non-function polymorphic type")
(t/fail (cl->*
(-> -Boolean -Boolean)
(-> -Symbol -Symbol))
"two cases of arity 1")
(t/fail (-Syntax (-HT -Symbol -Symbol))
"first-order contract, but got a hashtable.")
(t/fail (-Syntax (-struct #'struct-name #f (list (make-fld -Symbol #'acc #t))))
"first-order contract, .* struct with at least one mutable field")
(t/fail (-struct #'struct-name #f (list (make-fld -Symbol #'acc #f)) (-> -Symbol))
"procedural structs are not supported")
(t/fail (-Syntax (-> -Boolean -Boolean))
#rx"required a first-order .* generate a higher-order")
(t/fail (-set (-Param -Boolean -Boolean))
#rx"required a chaperone or flat contract .* generate an impersonator")
(t/fail (-poly (a b) (-> (Un a b) (Un a b)))
"multiple distinct type variables")
))
(define-go contract-tests) (define-go contract-tests)
(provide contract-tests) (provide contract-tests)