[racket] How to write a unit test for syntax-parse expectation failure error message?

83 views
Skip to first unread message

Greg Hendershott

unread,
Dec 2, 2012, 12:14:56 PM12/2/12
to us...@racket-lang.org
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?

p.s. Having such a unit test would be a nice-to-have, not
must-have. So if this can't be done, that's fine. I just wanted to
double-check if there's some way.
____________________
Racket Users list:
http://lists.racket-lang.org/users

Ryan Culpepper

unread,
Dec 2, 2012, 1:34:02 PM12/2/12
to Greg Hendershott, us...@racket-lang.org
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

Greg Hendershott

unread,
Dec 2, 2012, 5:59:28 PM12/2/12
to Ryan Culpepper, us...@racket-lang.org
Perfect -- thank you!

Matthias Felleisen

unread,
Dec 3, 2012, 8:28:15 AM12/3/12
to Ryan Culpepper, us...@racket-lang.org

Can this be abstracted into a linguistic construct and supplied via rackunit? or syntax/rackunit?

Eli Barzilay

unread,
Dec 3, 2012, 11:41:58 AM12/3/12
to Matthias Felleisen, us...@racket-lang.org
Three hours ago, Matthias Felleisen wrote:
>
> Can this be abstracted into a linguistic construct and supplied via
> rackunit? or syntax/rackunit?

As a side note, it's something that my testing library has been doing
with the plain `=>':

#lang racket
(require tests/eli-tester)
(test (λ) =error> "bad syntax")

But it also does it for all tests, for example:

(test (λ) => 3) ; test failure, runtime, not a syntax error

Which I think most people didn't want. (And IIRC the conclusion was
that there should be a specific arrow for them.)

--
((lambda (x) (x x)) (lambda (x) (x x))) Eli Barzilay:
http://barzilay.org/ Maze is Life!

Reply all
Reply to author
Forward
0 new messages