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

Hi All,
Is there a way to have a test.pl file test a module's function which when called exits?
Example (not actual code from module but similar functionality):
use CGI qw(:standard); sub goAway{ my $message=shift; print header; print "<HTML><BODY><script language=javascript>alert($message);</scr +ipt>Sorry dude, hit back button</BODY></HTML>"; exit(0); }
To test, we could grab stdout and see if it matches what we expect, but, since the code calls exit(0); it never returns to the test program. Gracias,

----
Zak

Replies are listed 'Best First'.
Re: Unique testing problem
by BrowserUk (Patriarch) on May 23, 2003 at 21:01 UTC

    You could override the builtin exit function for your testing

    D:\Perl\test>perl58 use subs 'exit'; sub exit{ print 'Exit override received:', @_; CORE::exit(@_); } exit 123; ^Z Exit override received:123

    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
Re: Unique testing problem
by BazB (Priest) on May 23, 2003 at 20:04 UTC

    Unless you've got a reason not to do so, change the exit to a die, then you can use an eval block to capture the exception in your testing code.

    Example:

    sub fall_over { die "Urgh!"; } eval { fall_over(); } print "We should have died!\n" if $@;


    If the information in this post is inaccurate, or just plain wrong, don't just downvote - please post explaining what's wrong.
    That way everyone learns.

Re: Unique testing problem
by adrianh (Chancellor) on May 23, 2003 at 23:30 UTC

    BrowserUk's answer is the most sensible one for the script you outlined - but in the spirit of TMTOWTDI:

    1. You could add an END block, which will be run after the exit.
    2. Create an object with a DESTROY handler and ensure it won't be destroyed until the final GC phase before exit (e.g. make it self referencing, or put it in a package global). This can be useful since the DESTROY handler is run after the END blocks have been executed, allowing your to check that they did what you expected.

    So that's three ways of doing it ;-)

    { package SelfRef; sub new { my $self_ref; bless \($self_ref = \$self_ref), shift; }; sub DESTROY { print "destroy handler in phase 2 GC\n"; }; }; SelfRef->new; END { print "end block\n" }; use subs 'exit'; sub exit { print "overrided exit(@_)\n"; CORE::exit(@_); } exit(0); __END__ # produces overrided exit(0) end block destroy handler in phase 2 GC
Re: Unique testing problem
by little (Curate) on May 24, 2003 at 10:33 UTC

    ... but, since the code calls exit(0); it never returns to the test program

    So you better go along the lines of BazB's suggestion, as an exit would kill your mod_perl on a webserver. No need to fumble with exit here. Just just die and return reasonable stuff. See SIGDIE by Adam for an elaboration on that.

    Have a nice day
    All decision is left to your taste

    Update
    No need to have your own __DIE__ handler, just die for a good reason die "action failed .. some more elusive stuff" and the place where you call it should be able to interpet those comments on proper death. *smile*
    keep it simple

      So you better go along the lines of BazB's suggestion, as an exit would kill your mod_perl on a webserver

      Nobody's mentioned mod_perl :-)

      Also, since perl 5.6, mod_perl overrides exit behind the scenes so it's often a non-issue.

      No need to fumble with exit here. Just just die and return reasonable stuff. See SIGDIE by Adam for an elaboration on that.

      I would not recommend using a __DIE__ handler in mod_perl code. It's global nature causes problems if you need to support multiple applications, virtual hosts, etc.

      Alternative Exception Handling Techniques in the mod_perl guide has more info on this.

      Personally, if there was the opportunity, I would probably try to refactor the code so that there were not multiple exit points for the program, rather than throwing exceptions into the mix. Multiple exit points are a Code Smell in my experience.

Re: Unique testing problem
by zakzebrowski (Curate) on May 27, 2003 at 10:43 UTC
    Thanks for your responces, I'm sure we'll be able to use one of them... :)

    ----
    Zak
    Pluralitas non est ponenda sine neccesitate - mysql's philosphy