[racket] How to write a unit test for syntax-parse expectation failure error message?
On 12/02/2012 12:14 PM, Greg Hendershott wrote:
> I'd like to write a unit test that a syntax-parse expectation failure
> elicits a certain error message. For instance, I'd do a regexp-match?
> that "something" is present in a message like "expected something".
>
> However it seems that syntax-parse expectation failures don't raise an
> exception. In other words, this will never return 'caught:
>
> (with-handlers ([exn? (lambda (exn) 'caught)])
> something-that-elicits-a-syntax-parse-expectation-failure)
>
> (At first I'd tried exn:syntax?, and when that didn't work, I checked
> to see if it was any kind of exception. Seems not.)
>
> Is there another way to go about this?
No, that's how you do it. For example:
(require syntax/parse)
(with-handlers ([exn:fail:syntax? (lambda (e) 'caught)])
(syntax-parse #'1 [x:id 'id]))
;; => 'caught
I suspect that what you actually want to do is test a macro that uses
syntax-parse; in that case, the issue you're running into is that the
macro raises a syntax error at compile time, but the with-handlers
doesn't (or rather, wouldn't) get set up to catch the exception until
run time.
There are two ways to fix the problem. One is to use eval or expand in
your test:
(define testing-ns (make-base-namespace))
;; setup testing-ns
(with-handlers ([exn:fail:syntax? ___])
(parameterize ((current-namespace testing-ns))
(expand '(macro-using-syntax-parse ___))))
The other way is to wrap the macro call in something that catches the
compile-time exception and produces code that raises a similar run-time
exception:
(with-handler ([exn:fail:syntax? ___])
(convert-syntax-error
(macro-using-syntax-parse ___)))
The syntax-parse tests use the second technique. Here's the definition
of convert-syntax-error from tests/stxparse/setup:
(define-syntax (convert-syntax-error stx)
(syntax-case stx ()
[(_ expr)
(with-handlers ([exn:fail:syntax?
(lambda (e)
#`(error '#,(exn-message e)))])
(parameterize ((error-print-source-location #f))
(local-expand #'expr 'expression null)))]))
Ryan