Skip to content
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ install:
- raco pkg config catalogs >> catalog-config.txt
- raco pkg config --set catalogs `cat catalog-config.txt`
- raco pkg install --auto $PKG-test
- raco pkg install --auto $PKG-typed
- raco pkg install --auto $PKG-typed || true
- raco pkg install --auto compiler-lib
- ls $HOME/.racket/download-cache

Expand Down
37 changes: 37 additions & 0 deletions rackunit-doc/rackunit/scribblings/check.scrbl
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,27 @@ entirely.
]
}

@defform[(check-compile-time-exn exn-predicate body)
#:contracts ([exn-predicate (or/c (-> any/c any/c) regexp?)]
[body (-> any/c)])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry if I was being unclear. I think:

1.body should be renamed to expr; and
2. It should not be in #:contracts.

For the first one, there's a convention to use the name body as described here. Because this operand only allows an expression, it should be named expr instead.

For the second one, I would hope that it is possible to write (check-compile-time-exn #rx"foo" 1), but 1 would not satisfy (-> any/c) as it's not a function. Switching from (-> any/c) to any/c wouldn't work either because (I would hope that) it's possible to write (check-compile-time-exn #rx"foo" (values 1 2 3)), but again, (values 1 2 3) would not satisfy any/c. So just leave it out from #:contracts.

void?]{

Similar to @racket[check-exn], but checks that an expression, @racket[body],
raises a runtime or compile time exception and that either @racket[exn-predicate]
returns a true value if it is a function, or that it matches the
message in the exception if @racket[exn-predicate] is a regexp.
In the latter case, the exception raised must be an @racket[exn:fail?].
}

@defform[(check-syntax-exn exn-predicate body)
#:contracts ([exn-predicate (or/c (-> any/c any/c) regexp?)]
[body (-> any)])
void?]{

Same as @racket[check-compile-time-exn], but only catches compile-time
@racket[exn:fail:syntax?] exceptions and runtime exceptions in @racket[body].
}

@defproc[(check-not-exn (thunk (-> any)) (message (or/c string? #f) #f)) void?]{

Checks that @racket[thunk] does not raise any exceptions.
Expand All @@ -189,6 +210,22 @@ the check fails.

}

@defform[(check-not-compile-time-exn body)
#:contracts ([body (-> any)])
void?]{

Similar to @racket[check-not-exn], but checks that an expression, @racket[body],
does not raise a runtime or compile time exception.
}

@defform[(check-not-syntax-exn body)
#:contracts ([body (-> any)])
void?]{

Same as @racket[check-not-compile-time-exn], but only catches compile-time
@racket[exn:fail:syntax?] exceptions and runtime exceptions in @racket[body].
}

@defproc[(check-regexp-match (regexp regexp?)
(string string?))
void?]{
Expand Down
73 changes: 63 additions & 10 deletions rackunit-lib/rackunit/private/check.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
racket/match
rackunit/log
syntax/parse/define
syntax/macro-testing
"base.rkt"
"equal-within.rkt"
"check-info.rkt"
Expand All @@ -28,7 +29,11 @@

check
check-exn
check-compile-time-exn
check-syntax-exn
check-not-exn
check-not-compile-time-exn
check-not-syntax-exn
check-true
check-false
check-pred
Expand Down Expand Up @@ -139,7 +144,7 @@
(procedure-arity-includes? thunk 0))
(raise-arguments-error name "thunk must be a procedure that accepts 0 arguments" "thunk" thunk)))

(define-check (check-exn raw-pred thunk)
(define-check (check-exn-helper raw-pred thunk location)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better to not try and reuse the check-exn code. Checks are kind of hard to reuse, since they're sensitive to the source location of their usage site and they have some slightly whacky semantics. Plus there's no need to try and reuse the regex/predicate parts of check-exn.

(let ([pred
(cond [(regexp? raw-pred)
(λ (x) (and (exn:fail? x) (regexp-match raw-pred (exn-message x))))]
Expand All @@ -164,29 +169,77 @@
[exn:fail?
(lambda (exn)
(with-default-check-info*
(list
(make-check-message "Wrong exception raised")
(make-check-info 'exn-message (exn-message exn))
(make-check-info 'exn exn))
(append (list
(make-check-message "Wrong exception raised")
(make-check-info 'exn-message (exn-message exn))
(make-check-info 'exn exn))
(if (equal? location null)
null
(list
(make-check-location location))))
(lambda () (fail-check))))])
(thunk))
(with-default-check-info*
(list (make-check-message "No exception raised"))
(lambda () (fail-check))))))

(define-check (check-not-exn thunk)
(define-check (check-exn raw-pred thunk)
(check-exn-helper raw-pred thunk null ))

(define-syntax (check-compile-time-exn stx)
(with-syntax ([loc (datum->syntax #f 'loc stx)])
(syntax-parse stx
[(_ raw-pred body)
(syntax/loc stx (check-exn-helper raw-pred
(lambda ()
(convert-compile-time-error body))
(syntax->location #'loc)))])))

(define-syntax (check-syntax-exn stx)
(with-syntax ([loc (datum->syntax #f 'loc stx)])
(syntax-parse stx
[(_ raw-pred body)
(syntax/loc stx (check-exn-helper raw-pred
(lambda ()
(convert-syntax-error body))
(syntax->location #'loc)))])))

(define-check (check-not-exn-helper thunk location)
(raise-error-if-not-thunk 'check-not-exn thunk)
(with-handlers
([exn:test:check? refail-check]
[exn?
(lambda (exn)
(with-default-check-info*
(list
(make-check-message "Exception raised")
(make-check-info 'exception-message (exn-message exn))
(make-check-info 'exception exn))
(append (list
(make-check-message "Exception raised")
(make-check-info 'exception-message (exn-message exn))
(make-check-info 'exception exn))
(if (equal? location null)
null
(list
(make-check-location location))))
(lambda () (fail-check))))])
(thunk)))

(define-check (check-not-exn thunk)
(check-not-exn-helper thunk null))

(define-syntax (check-not-compile-time-exn stx)
(with-syntax ([loc (datum->syntax #f 'loc stx)])
(syntax-parse stx
[(_ body)
(syntax/loc stx (check-not-exn-helper (lambda ()
(convert-compile-time-error body))
(syntax->location #'loc)))])))

(define-syntax (check-not-syntax-exn stx)
(with-syntax ([loc (datum->syntax #f 'loc stx)])
(syntax-parse stx
[(_ body)
(syntax/loc stx (check-not-exn-helper (lambda ()
(convert-syntax-error body))
(syntax->location #'loc)))])))

(define-syntax-rule (define-simple-check-values [header body ...] ...)
(begin (define-simple-check header body ...) ...))
Expand Down
20 changes: 20 additions & 0 deletions rackunit-lib/rackunit/private/test.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,11 @@
test-false
test-not-false
test-exn
test-compile-time-exn
test-syntax-exn
test-not-exn
test-not-compile-time-exn
test-not-syntax-exn

foldts-test-suite
fold-test-results
Expand All @@ -97,7 +101,11 @@

check
check-exn
check-compile-time-exn
check-syntax-exn
check-not-exn
check-not-compile-time-exn
check-not-syntax-exn
check-true
check-false
check-pred
Expand Down Expand Up @@ -173,5 +181,17 @@
(define-shortcut (test-exn pred thunk)
(check-exn pred thunk))

(define-shortcut (test-compile-time-exn pred thunk)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these shortcut forms should be skipped, actually. They won't work quite right for check-compile-time-exn, since it accepts a variable number of body forms instead of a single thunk. The shortcuts really only work for checks that behave much more like functions: notice there isn't a test-match shortcut either, since check-match is similarly unusual.

(check-compile-time-exn pred thunk))

(define-shortcut (test-syntax-exn pred thunk)
(check-syntax-exn pred thunk))

(define-shortcut (test-not-exn thunk)
(check-not-exn thunk))

(define-shortcut (test-not-compile-time-exn thunk)
(check-not-compile-time-exn thunk))

(define-shortcut (test-not-syntax-exn thunk)
(check-not-syntax-exn thunk))
30 changes: 29 additions & 1 deletion rackunit-test/tests/rackunit/check-test.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
rackunit
rackunit/private/check
rackunit/private/result
rackunit/private/test-suite)
rackunit/private/test-suite
syntax/macro-testing)

(define (make-failure-test name pred . args)
(test-case
Expand Down Expand Up @@ -434,6 +435,33 @@
(check-exn exn:fail:contract?
(lambda ()
(check-not-exn (lambda (x) x)))))

;; Verify syntax and compile time errors are now
;; supported by check-compile-time-exn, check-syntax-exn,
;; check-not-compile-time-exn, check-not-syntax-expand
(test-case
"check-compile-time-exn converts compile time exceptions to runtime phase"
(check-compile-time-exn exn:fail:syntax?
(lambda ()
(if (= 1 1) 1))))

(test-case
"check-syntax-exn converts compile time syntax exceptions to runtime phase"
(check-syntax-exn exn:fail:syntax?
(lambda ()
(struct foo (fizz) #:constructor-name bar)
(foo 53))))

(test-case
"check-not-compile-time-exn does not call any compile time exceptions when none are provided"
(check-not-compile-time-exn (lambda ()
(if (= 1 1) 1 1))))

(test-case
"check-not-syntax-exn does not call any compile time exceptions when none are provided"
(check-not-syntax-exn (lambda ()
(struct foo (fizz) #:constructor-name bar)
(bar 53))))

;; Regression test
;; Uses of check (and derived forms) used to be un-compilable!
Expand Down
8 changes: 5 additions & 3 deletions rackunit-typed/rackunit/main.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,11 @@
(test-false (check-false v))
(test-not-false (check-not-false v))
(test-exn (check-exn pred thunk))
(test-not-exn (check-not-exn thunk)))
(test-compile-time-exn (check-compile-time-exn pred thunk))
(test-syntax-exn (check-syntax-exn pred thunk))
(test-not-exn (check-not-exn thunk))
(test-not-compile-time-exn (check-not-compile-time-exn thunk))
(test-not-syntax-exn (check-not-syntax-exn thunk)))


; 3.4
Expand Down Expand Up @@ -310,5 +314,3 @@
Any))]
[current-check-around
(Parameter ((Thunk Any) -> Any))])