Skip Menu |

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

Report information
The Basics
Id: 64093
Status: resolved
Priority: 0/
Queue: Test-Weaken

People
Owner: jkegl [...] cpan.org
Requestors: user42 [...] zip.com.au
Cc:
AdminCc:

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



Subject: constructor return multiple values
Date: Tue, 21 Dec 2010 09:29:30 +1100
To: bug-Test-Weaken [...] rt.cpan.org
From: Kevin Ryde <user42 [...] zip.com.au>
I made a mistake in a "constructor" and returned a list of refs instead of a single one, like ret.pl below. I suppose I meant to return \@ret, but instead returned @ret as a list. On returning multiple values only the last one seems to be checked. In ret.pl for example $circular_obj is leaky, but only detected if it's the second in the @ret, not the first. I wonder if Test::Weaken might either process multiple values returned, or give an error if it's not allowed. If allowed then I suppose all the values could be passed to the subsequent "destructor" call. I see the current \($constructor->()) form in Test::Weaken::test() is list context already (and eg. context.pl below), so there'd be no change to the calling, just to what was done if the return is multiple values.
use strict; use warnings; use Test::Weaken; print Test::Weaken->VERSION,"\n"; my $leaks = Test::Weaken::leaks ({ constructor => sub { my $obj = []; my $circular_obj = {}; $circular_obj->{'circular'} = $circular_obj; my @ret = ($circular_obj, $obj); return @ret; }, }); print $leaks ? "leaky\n" : "no leaks\n"; if ($leaks) { my $probes = $leaks->unfreed_proberefs; print @$probes,"\n"; }
use strict; use warnings; use Test::Weaken; print Test::Weaken->VERSION,"\n"; my $leaks = Test::Weaken::leaks ({ constructor => sub { print wantarray(),"\n"; return []; }, });
Yes, the return is in scalar context, and a list in scalar context is reduced to its last item. My thought on this is that Test::Weaken's current behavior is a reasonable way to deal with this kind of user mistake. I'll leave this bug open a little while for further comments and then, absent reasons not to so do, close it. On Mon Dec 20 17:29:42 2010, user42@zip.com.au wrote: Show quoted text
> I made a mistake in a "constructor" and returned a list of refs instead > of a single one, like ret.pl below. I suppose I meant to return \@ret, > but instead returned @ret as a list. > > On returning multiple values only the last one seems to be checked.
Marked as resolved, based on my explanation above.
Subject: Re: [rt.cpan.org #64093] constructor return multiple values
Date: Fri, 13 Jan 2012 08:46:39 +1100
To: bug-Test-Weaken [...] rt.cpan.org
From: Kevin Ryde <user42 [...] zip.com.au>
"Jeffrey Kegler via RT" <bug-Test-Weaken@rt.cpan.org> writes: Show quoted text
> > Yes, the return is in scalar context, and a list in scalar context is > reduced to its last item. My thought on this is that Test::Weaken's > current behavior is a reasonable way to deal with this kind of user > mistake.
Well, the problem with the current behaviour is that silently ignoring lets mistakes go unnoticed. It looks like the result is a successful check when in fact it was unchecked, if you know what I mean. Ie. "silently ignored because you made a mistake in your return" versus "checked successfully there were no leaks in your data". Such a mistake in a constructor could go unnoticed almost forever :-). You thought you'd been good and tested for circular refs in some oopery, but alas due to writing return($foo,$bar); instead of return[$foo,$bar]; it was not so, the subtle or not so subtle difference means $foo is not checked. I think checking all of multiple return values would be good because it'd help xsub stuff returning multiple scalars, there'd be no need to do the map{} etc from my bit of docs taking refs and putting them into a new array. -- The sigfile finance for the layman series: Read a mining company's annual report. The more pages of excrutiating detail about geology and minerals, the less chance it will make money.
OK, I see your point. If this were an application, the expense of buller-proofing the return would not be justified. But in debugging, a potential situation, where a user error might cause problems to be silently ignored, is more important. Let me think out what I want to do. Could you submit a test script? Don't worry a lot about its format, as I'll rearrange that anyway. Thanks, jeffrey On Thu Jan 12 16:46:28 2012, user42@zip.com.au wrote: Show quoted text
> "Jeffrey Kegler via RT" <bug-Test-Weaken@rt.cpan.org> writes:
> > > > Yes, the return is in scalar context, and a list in scalar context is > > reduced to its last item. My thought on this is that Test::Weaken's > > current behavior is a reasonable way to deal with this kind of user > > mistake.
> > Well, the problem with the current behaviour is that silently ignoring > lets mistakes go unnoticed. It looks like the result is a successful > check when in fact it was unchecked, if you know what I mean. > Ie. "silently ignored because you made a mistake in your return" versus > "checked successfully there were no leaks in your data". > > Such a mistake in a constructor could go unnoticed almost forever :-). > You thought you'd been good and tested for circular refs in some oopery, > but alas due to writing > > return($foo,$bar); > > instead of > > return[$foo,$bar]; > > it was not so, the subtle or not so subtle difference means $foo is not > checked. > > I think checking all of multiple return values would be good because > it'd help xsub stuff returning multiple scalars, there'd be no need to > do the map{} etc from my bit of docs taking refs and putting them into a > new array. > > > >
Subject: Re: [rt.cpan.org #64093] constructor return multiple values
Date: Fri, 13 Jan 2012 11:46:34 +1100
To: bug-Test-Weaken [...] rt.cpan.org
From: Kevin Ryde <user42 [...] zip.com.au>
"Jeffrey Kegler via RT" <bug-Test-Weaken@rt.cpan.org> writes: Show quoted text
> > Let me think out what I want to do. Could you submit a test script?
Perhaps per below, adapted from the ret.pl I first posted. As of now the first test fails and the second succeeds (as the last value returned is checked). Of course you could instead make multiple return values an error. That'd still be compatible with the documented behaviour and could relax it as a feature later. The constructor call is already in array context, so switching to map{\$_}&$func() to detect multiple return doesn't change the wantarray() the func sees, if I'm not mistaken. Not that array vs scalar context for the constructor is a documented feature ...
#!/usr/bin/perl -w use strict; use warnings; use Test::Weaken; use Test::More tests => 2; { # first of two return values leaks my $leaks = Test::Weaken::leaks ({ constructor => sub { my $obj = []; my $circular_obj = {}; $circular_obj->{'circular'} = $circular_obj; my @ret = ($circular_obj, $obj); return @ret; }, }); my $unfreed_count = ($leaks ? $leaks->unfreed_count() : 0); is ($unfreed_count, 2, # the hash and the scalar in it 'first of two return values leaky -- detected'); } { # second of two return values leaks my $leaks = Test::Weaken::leaks ({ constructor => sub { my $obj = []; my $circular_obj = {}; $circular_obj->{'circular'} = $circular_obj; my @ret = ($obj, $circular_obj); return @ret; }, }); my $unfreed_count = ($leaks ? $leaks->unfreed_count() : 0); is ($unfreed_count, 2, # the hash and the scalar in it 'second of two return values leaky -- detected'); }
-- ... This is reflected in the sort of menus that offer smoked eel, pad thai and pepper ice cream. (If that strikes you as a ridiculous mixture, you are not conceited enough to work in a professional kitchen, where the vile frequently masquerades as the exotic.) -- Tony White
My current thinking is to make it an error. That way the user says "Oops!" and fixes it. I think that's best. There's no real advantage gained the other way, and there would be complications and potential bugs aplenty. The current release candidate is testing cleanly, and I will wait until after its official release to tackle this ticket. I hope that will just be a few days. thanks, Jeffrey On Thu Jan 12 19:47:04 2012, user42@zip.com.au wrote: Show quoted text
> "Jeffrey Kegler via RT" <bug-Test-Weaken@rt.cpan.org> writes:
> > > > Let me think out what I want to do. Could you submit a test script?
> > Perhaps per below, adapted from the ret.pl I first posted. As of now > the first test fails and the second succeeds (as the last value returned > is checked). > > Of course you could instead make multiple return values an error. > That'd still be compatible with the documented behaviour and could relax > it as a feature later. > > The constructor call is already in array context, so switching to > map{\$_}&$func() to detect multiple return doesn't change the > wantarray() the func sees, if I'm not mistaken. Not that array vs > scalar context for the constructor is a documented feature ... > >
Subject: Re: [rt.cpan.org #64093] constructor return multiple values
Date: Fri, 13 Jan 2012 12:03:05 +1100
To: bug-Test-Weaken [...] rt.cpan.org
From: Kevin Ryde <user42 [...] zip.com.au>
"Jeffrey Kegler via RT" <bug-Test-Weaken@rt.cpan.org> writes: Show quoted text
> > My current thinking is to make it an error. That way the user says > "Oops!" and fixes it. I think that's best. There's no real advantage > gained the other way, and there would be complications and potential > bugs aplenty.
Don't you keep an array of pending targets to be descended? Multiple returns from the constructor could just start that from a few values instead of one, no? Even if you want to start from one you could always make it my $start = [ map {\$_} &$constructor() ]; encapsulating what the constructor would otherwise have to do itself.
I'll keep this possibility in mind when I study this ticket in a few days. Frankly, I just have never seen any value in allowing the constructor to return lists. If the user wants multiple values in an array ref, he can create the array ref and return it from the constructor himself, right? And that way, the user knows precisely what's going on and why. -- jeffrey
Subject: Re: [rt.cpan.org #64093] constructor return multiple values
Date: Sun, 15 Jan 2012 09:46:56 +1100
To: bug-Test-Weaken [...] rt.cpan.org
From: Kevin Ryde <user42 [...] zip.com.au>
"Jeffrey Kegler via RT" <bug-Test-Weaken@rt.cpan.org> writes: Show quoted text
> > If the user wants multiple values in an > array ref, he can create the array ref and return it from the > constructor himself, right?
Oh, well, there's more than one way to do it :-). "return @foo" or "return \@foo" or "return $a,$b", etc. If there's something with a reasonable meaning there's not much reason not to allow it, after all this is perl not python. The multiple values I've wanted to do have sometimes been C-code sub-objects which won't be reached by the normal traversal, and sometimes because I've tinkered with sub-parts in the constructor code and might as well return the parts too so as to be sure they all go as intended ... -- The sigfile restaurant jargon elucidated for the layman series: "Special" -- something almost gone bad that has to be sold today.
Done as checking all returned values.