3
$\begingroup$

I want to demonstrate that Catch[x_] does not catch things thrown with a tag.

Catch[Throw[0, 0]]

gives

Throw::nocatch: Uncaught Throw[0,0] returned to top level.

Hold[Throw[0, 0]]

But I cannot put this behaviour into a VerificationTest that results in Success. I tried

VerificationTest[Catch[Throw[0, 0]], 
 Hold[Throw[0, 0]], {Throw::nocatch}, {}]

but this gives an Error TestResultObject.

Usually, using the third argument is the way to go with messages:

VerificationTest[Message[a::b], Null, {a::b}]

I guess I could use something like GeneralUtilities`CatchAll to construct the test manually, but I was under the impression that VerificationTest catches all Error conditions.

Any ideas?


I also seems to require manual work to catch Abort[].

VerificationTest[Abort[], $Aborted]

gives an Error-result too, but the Abort is shielded from the rest of the execution:

VerificationTest[Abort[], $Aborted]*2

does not give $Aborted like Abort[]*2 does.

$\endgroup$
  • $\begingroup$ It was hard to follow that post for me. Could you maybe add a scrrenshot or two? p.s. what about Catch[ Catch[Throw[0, 0]];, _] =!= Null $\endgroup$ – Kuba Aug 30 '16 at 13:56
2
$\begingroup$

On a rare occasion, something produces an uncaught Throw that must be tested for, and as you have noticed, checking for the message is insufficient. So, if I know the form, e.g. Throw[0, 0], I wrap the expression in another Catch, and then use the outer Catch to return the test result, e.g.

VerificationTest[
 Catch[  Catch[Throw[0, 0]]; (* or some other expression *)
   True, (* No uncaught Throw *)
   _, (* Catch all tagged Throws *)
   False&
 ]
]

The key is the last argument has to be a function, which normally would return

f[thrownValue, tag]

But, in this case we just want it to return False if the execution ever makes it to that branch. For untagged Throw, we have to exercise some caution as Catch[Throw[...]] will return the value passed by Throw. So, the solution is to have Catch return a value that is not likely to be thrown, e.g.

VerificationTest[
 Catch[ (*throwing expression*); "Not Thrown"],
 "Not Thrown"
]

where Catch will produce "Not Thrown", if no uncaught, untagged Throw is produced. These two forms can be combined if the form is not known, as follows

VerificationTest[
 Catch[ Catch[ expr; "Not Thrown"], _, "Tagged expr Thrown"&]
 ,
 "Not Thrown"
]
$\endgroup$
0
$\begingroup$

A VerificationTest with Outcome Error cannot be fixed by changing the expected-messages argument. This only applies to MessagesFailure Outcome (orange versus yellow cross, a bit hard to distinguish).

Tests that result in Error must be fixed on a case-by-case basis: There could be an error in either of the expressions involved in the test or in some of the options (e.g. the SameTest not returning True or False).

$\endgroup$
0
$\begingroup$

You could use CheckAll to "catch" all "uncaught" control flow statements. Then wrap those statements with special head to make sure that they were not returned by ordinary evaluation of expression.

ClearAll[stoppedControlFlow, confineControlFlow]
stoppedControlFlow // Attributes = HoldAll;
confineControlFlow = Function[,
    CheckAll[#, Function[, Replace[HoldComplete@##, {
        HoldComplete[_, Hold@ctrlFlow__] :> stoppedControlFlow@ctrlFlow,
        HoldComplete[result_, Hold[]] :> result
    }], HoldAllComplete]],
    HoldAllComplete
];

Now all following VerificationTests are successful.

VerificationTest[2 + 3 // confineControlFlow, 5]
VerificationTest[Catch[Throw[0, 0]] // confineControlFlow, stoppedControlFlow@Throw[0, 0]]
VerificationTest[Abort[] // confineControlFlow, stoppedControlFlow@Abort[]]
VerificationTest[Goto[1] // confineControlFlow, stoppedControlFlow@Goto[1]]
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.