Skip Menu |

This queue is for tickets about the Test-Trap CPAN distribution.

Report information
The Basics
Id: 91687
Status: open
Priority: 0/
Queue: Test-Trap

People
Owner: Nobody in particular
Requestors: zurom [...] mail.ru
Cc:
AdminCc:

Bug Information
Severity: Wishlist
Broken in: (no value)
Fixed in: (no value)



Subject: Wrong exit code after die
This prints 'undef' instead of 255 Show quoted text
> perl -MTest::Trap -e 'trap{ die "aa" }; print $trap->exit // "undef"'
undef Show quoted text
> echo $?
0 But .. Show quoted text
> perl -e 'die "aa"' > echo $?
255
Subject: Re: [rt.cpan.org #91687] Wrong exit code after die
Date: Fri, 27 Dec 2013 18:06:18 +0100
To: bug-Test-Trap [...] rt.cpan.org
From: The Sidhekin <sidhekin [...] gmail.com>
On Fri, Dec 27, 2013 at 1:06 PM, http://zurom.id.mail.ru/ via RT < bug-Test-Trap@rt.cpan.org> wrote: Show quoted text
> This prints 'undef' instead of 255 >
> > perl -MTest::Trap -e 'trap{ die "aa" }; print $trap->exit // "undef"'
> undef >
> > echo $?
> 0 >
It's supposed to, and documented to: "Any property will be undef if not actually trapped" and, for the C<exit> accessor: "The exit code, if the latest trap tried to exit." C<die()> is not C<exit()>: It throws an exception, and only an uncaught exception will cause an exit, from the outermost scope. C<trap {}>, like C<eval {}>, by default traps the exception, so it doesn't go uncaught. (And even if you're using a custom C<trap {}> that does not capture exceptions, the exception will just propagate out of the C<trap {}> and cause an exit from the outermost scope; the C<trap {}> will in that case never return.) But .. Show quoted text
> > perl -e 'die "aa"' > > echo $?
> 255 >
C<trap {}> is an analogue to C<eval {}>, so the comparison should not be with a bare C<die()>, but one inside an C<eval{}>: $ perl -e 'eval { die "aa" }' $ echo $? 0 I think I'll be closing this as not-a-bug. At most, I could clarify the documentation of the C<exit> accessor. Perhaps: "(Will never be set by exceptions; these will be trapped without exit by the default C<:die> layer, or else propagate out of the trap function.)" Would that help? Eirik
From: zurom [...] mail.ru
I think it will be more clear if you show the right code to get exit set to 255 after die (as it realy happens without trap{..})
Subject: Re: [rt.cpan.org #91687] Wrong exit code after die
Date: Fri, 27 Dec 2013 19:01:42 +0100
To: bug-Test-Trap [...] rt.cpan.org
From: The Sidhekin <sidhekin [...] gmail.com>
On Fri, Dec 27, 2013 at 6:22 PM, http://zurom.id.mail.ru/ via RT < bug-Test-Trap@rt.cpan.org> wrote: Show quoted text
> Queue: Test-Trap > Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=91687 > > > I think it will be more clear if you show the right code to get exit set > to 255 after die (as it realy happens without trap{..}) >
As I said, by intention (and documentation) trap {} compares to eval {}. Not to "without trap {}". You could set exit to 255 after die, using a (user defined) layer, like so: use Test::Trap sub { my $self = shift; $self->Teardown(sub { defined $self->{die} and $self->{exit}=255 }); $self->Next; }; ... but I suspect you're just going to end up with more trouble along this route. I certainly won't document that kind of thing. If you tell me what you're trying to do, perhaps I can suggest a better route? Eirik
Show quoted text
> If you tell me what you're trying to do, perhaps I can suggest a better > route?
I've wrote unit-test fo cgi scripts where all inner code covered by sub _run. And the only thing that i can test is that sub. And of cource the HTTP status depends on exit status, so we've got 500 after die... So the tests should show that script ends with exit code no equal to zero. It is important i think
... and in my case the die itself is not so important as the exit status
Subject: Re: [rt.cpan.org #91687] Wrong exit code after die
Date: Mon, 30 Dec 2013 14:38:49 +0100
To: bug-Test-Trap [...] rt.cpan.org
From: The Sidhekin <sidhekin [...] gmail.com>
On Mon, Dec 30, 2013 at 10:54 AM, http://zurom.id.mail.ru/ via RT < bug-Test-Trap@rt.cpan.org> wrote: Show quoted text
> > I've wrote unit-test fo cgi scripts where all inner code covered by sub > _run. And the only thing that i can test is that sub. > And of cource the HTTP status depends on exit status, so we've got 500 > after die... > > So the tests should show that script ends with exit code no equal to zero. > It is important i think
... Show quoted text
> ... and in my case the die itself is not so important as the exit status >
Right. Assuming you have already considered and dismissed the frameworks for tests with (real or mocked) webservers ... they can be rather heavy, after all ... If you're treating &_run as a black box, there is no way an ordinary exit layer could trap all kinds of non-zero exits, so conceptually, it's insufficient. Perl is just too powerful for a pure-purl trap to properly contain it ... For instance: $ perl -e 'exec "false"' $ echo $? 1 $ perl -MTest::Trap -e 'trap { exec "false" }; print $trap->exit // "undef"' $ echo $? 1 (See the caveats for more ways to escape the trap.) 1) The only way to safely handle every kind of exit from black boxes, is in a process of its own. A bit heavier and slower, but it will work. I might even want to write up a special layer for that ... sounds like it could be useful ... haven't needed it yet, though. And I'll need to sleep on it, in any case. It's kinda orthogonal to what I was originally trying to do with Test::Trap. 2) If &_run is not a black box, but you control it and the code it calls, you could rewrite them so that they never exec(), never POSIX::_exit(), never throw exceptions (that they don't themselves catch), perhaps never even return, but always just exit(). Or at least, so that you know in each (test) case whether it will return, exit, or throw an exception. And then write the tests accordingly. 3) If it is not specified whether the code should return or exit with zero on success, nor whether it should throw an exception or exit with non-zero on failure, the test code must allow for either. But we cannot safely trap every kind of exit in the standard layers. As a middle way, you may decide to avoid troublesome exits, and just write the tests so as to allow for either of return/exception and zero/non-zero trappable exit. Perhaps with helpers: sub did_succeed { my $trap = shift; my $name = shift // "Expecting return or zero exit value"; if ($trap->leaveby eq "exit") { $trap->exit_is(0, $name); } else { $trap->did_return($name); } } sub did_fail { my $trap = shift; my $name = shift // "Expecting exception or non-zero exit value"; if ($trap->leaveby eq "exit") { $trap->exit_isnt(0, $name); } else { $trap->did_die($name); } } ... or even drop them in a C<< { package Test::Trap; ... } >> for monkey-patched helper methods. :) But again, this will not help you if &_run or code called from it may use exec() or CORE::exit() or other non-pure-perl stuff, as mentioned in the caveats. For that, a subprocess will be needed, and Test::Trap does not (as yet) have any such mechanism. Eirik
Show quoted text
> Assuming you have already considered and dismissed the frameworks for tests with (real or mocked) webservers
Yes you're right, such frameworks is too heavy. I'd prefer more simple approach Show quoted text
> If you're treating &_run as a black box
Yes, it is really a black box, as most of the scripts were written a long time ago and the task is to cover them with tests and do not touch if possible. In any case, it is quite dangerous to do refactoring without unit tests. Scripts are important enough Show quoted text
> I might even want to write up a special layer for that ... sounds like it could be useful
Yes it could help 2&3 are not an option unfortunatly as it is a black box