Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Testing a module with eval() where $@ is clobbered (pre v5.14)

by stevieb (Canon)
on Jan 16, 2016 at 23:38 UTC ( [id://1152948]=perlquestion: print w/replies, xml ) Need Help??

stevieb has asked for the wisdom of the Perl Monks concerning the following question:

It's a slow Saturday, so I thought I'd ask a question here that I'm sure I'm already missing the answer for.

So, I like my tests to pass on all platforms, but pre v5.14, eval had some issues. Instead of modifying my code to work around those (because my understanding is that you need to do trickery around the eval within the module), or using external modules (Try::Catch, Try::Tiny), instead, I wrote my test like the following example code. Is this reasonable, or are there holes in doing things this way, that could possibly cause issues for newer versions of perl where eval actually does The Right Thing?

What happens is, that my test calls an object method, and that method creates a (temporary, ie. it goes out of scope within the method call) internal object of its own class. The new temp object, based on calls within the method call being tested has at least one eval in it (which, based on docs in Try::Tiny and other reliable sources state that using $@ in pre-v5.14 isn't good (because it's global) due to clobbering), clobbers $@ with a successful pass, and my check for $@ fails horribly.

{ $SIG{__DIE__} = sub { ok (1 == 1, "if the thing with the guy in the place, we +croak"); }; # $obj->blah() croaks() guaranteed, but it creates a # temp object of its own class, which has eval() and # clobbers $@, so $@ is always '' when things return # back to the test eval { $obj->blah(do_this => 1); }; }

Is this a safe way to work around the versions of perl that have broken eval without modifying module code, or is there a better way (without having to add any code to the module being tested)? Also, does doing things in this fashion compromise latter tests/test files?

Replies are listed 'Best First'.
Re: Testing a module with eval() where $@ is clobbered (pre v5.14)
by Anonymous Monk on Jan 17, 2016 at 11:22 UTC

    What your module code definitely shouldn't be doing is the unfortunately common but wrong idiom eval {...}; if ($@) {handle_error} - instead, you should do something like eval { ...; 1 } or handle_error;. If you're doing the former in your module, then you need to change the module code.

    That gives you reliable detection of errors, and other than that, you could customize your tests to not check the contents of $@ pre-5.14. (Also, I seem to remember some long-standing issues with $SIG{__DIE__} inside of evals, so be careful with that too. And also IIRC even post-5.14 some smaller issues with $@ remained, so to say that $@ now works perfectly isn't quite correct either. Lazy Sunday, so I don't have the references for both issues handy at the moment...)

      Found 'em. RT#123738, RT#123773, and perlvar:

      Due to an implementation glitch, the $SIG{__DIE__} hook is called even inside an eval(). Do not use this to rewrite a pending exception in $@, or as a bizarre substitute for overriding CORE::GLOBAL::die(). This strange action at a distance may be fixed in a future release so that $SIG{__DIE__} is only called if your program is about to exit, as was the original intent. Any other use is deprecated.
Re: Testing a module with eval() where $@ is clobbered (pre v5.14)
by Anonymous Monk on Jan 17, 2016 at 05:12 UTC
    :) too many words , but does this shed any light? Or do you really need the value of $@ that gets clobbered
    my $ret; eval { $ret = $foo->blah; 1 } or warn "it failed but did err get clobbered? $@";

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1152948]
Approved by kevbot
Front-paged by Old_Gray_Bear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having an uproarious good time at the Monastery: (3)
As of 2024-04-25 05:45 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found