Brittle exception tests
Marc Nieper-Wißkirchen
(16 Jun 2020 07:37 UTC)
|
Re: Brittle exception tests
Wolfgang Corcoran-Mathe
(16 Jun 2020 19:19 UTC)
|
Re: Brittle exception tests Marc Nieper-Wißkirchen (16 Jun 2020 20:19 UTC)
|
Re: Brittle exception tests
John Cowan
(16 Jun 2020 21:45 UTC)
|
Re: Brittle exception tests
Marc Nieper-Wißkirchen
(17 Jun 2020 10:33 UTC)
|
Re: Brittle exception tests
Wolfgang Corcoran-Mathe
(17 Jun 2020 22:19 UTC)
|
Am Di., 16. Juni 2020 um 21:19 Uhr schrieb Wolfgang Corcoran-Mathe <xxxxxx@sigwinch.xyz>: > > On 2020-06-16 09:37 +0200, Marc Nieper-Wißkirchen wrote: > > in your test suite, you use your macro `catch-exceptions` in a few places. > > However, it catches every exception so it makes those tests a bit > > meaningless ... > > Agreed, it's very brittle. I'm not sure how to do better, though. > > I've reviewed the tests of some other SRFIs for hints. Those which > use SRFI 64 (e.g. SRFI 146) generally use `test-error' without an > `error-type' argument (the meaning of which is implementation-defined, > anyway), effectively giving a success result if any exception is > raised. Others (like 135) use `guard' with a single #t clause, > which is another catch-all. With respect to SRFI 146, I have to blame myself. But I couldn't do much because of the error type argument being implementation-dependent. Maybe a post-finalization note can be added to SRFI 64 saying that in R7RS systems the error type argument can be a predicate. > Perhaps `error-object?' could be used meaningfully here: > > (define-syntax catch-errors > (syntax-rules () > ((_ expr) > (guard (exn ((error-object? exn) 'error)) expr)))) > > A few tests in Chibi suggest that this doesn't narrow the net much. > I'd appreciate any suggestions for a better way to do this. I'm not at all sure whether I have a good answer. But I think we have to look at the tests individually. In the error test for `maybe-join', there is not much to test because "it is an error" does not have to be signaled. Your test only tests your specific implementation, not any portable implementation. In my opinion, portable test suites are most helpful (because they encourage alternative implementations), so I would drop that particular test. And I would use `assume' of SRFI 145 instead of `error' in the sample implementation because `assume' is exactly for these "it is an error" cases. The same comment holds for all other occurrences of `catch-errors' except for the test for `maybe-if', where the specification says that an error is signaled. Here, you cannot use `error-object?' either in a portable test because a portable implementation may not use `error' to signal the error but use `raise' on some implementation-defined object. Thus, you cannot guard against such an error portably (except with a catch-all guard, which is brittle for tests and which should be a no-go for programs). But you cannot cure this in your implementation or in your tests. The problem lies in the specification. As I have already written to John, an error that has to be signaled but which I cannot test against, is not only no more helpful than the condition "it is an error" (as you can see by not being able to write a proper portable test), but even worse than "it is an error" because it disallows the kinds of optimizations underlying the idea of SRFI 145. I have asked John (whom I included in CC) to remove the requirement that the error has to be signaled. While I think this makes the most sense and is most helpful to implementers and programmers, he has disagreed. I haven't yet understood his argument. But in any case, if an error MUST be signaled, SRFI 189 really needs to export a predicate, say, `maybe-if-error?` that can be used to test again. The reason why a sensible test cannot be written at the moment is exactly that such a predicate is missing. As soon as you have `maybe-if-error` you can write such a test and all issues with the tests have been resolved. But, if I could decide, I would change the meaning of (maybe-if maybe-expr just-expr nothing-expr) to (let ((%maybe-expr maybe-expr)) (cond ((just? %maybe-expr) just-expr) ((nothing? %maybe-expr) nothing-expr) (else (assume #f "maybe-if: maybe expected" %maybe-expr)))) I think this captures the underlying intent completely and it reduces the question of how and whether the error is reported to a more primitive form, namely `assume` from SRFI 145, which is always good. The sample implementation of SRFI 145 even has a feature identifier for this. Marc