in reply to RFC: Test::Destroy ('Chasing shadows')
This module could be implemented by simply looking at the reference count of the object in question, but there is no pure Perl method to my knowledge to accomplish this.
I have to admit if it were me I would forget the pure-perl restriction and just use weaken from Scalar::Util :-)
use Test::More tests => 1; use Scalar::Util qw(weaken); { my $original = bless {},'My::Test::Class'; weaken $original; ok !defined($original), '$object garbage collected'; }
which also has the advantage of working on non-blessed references.
The module name is still in flux, but as it is for testing the destruction of objects, I found Test::DESTROY appealing - any better idea?
Maybe Test::GarbageCollected, Test::Destroyed or Test::LastReference?
Test::DESTROY implies (to me) that you are testing the DESTROY method, not the fact that the object has been garbage collected.
The best method I came up to implement the inverse of destroyed_ok was to fork() the test a second time and use not destroyed_ok() there, observing the output, because most likely, the main program still holds a reference to the object if it assumes to be able to use the object afterwards. A simple look at the reference count would help of course ...
Again, I would just use weaken.
use Test::More tests => 1; use Scalar::Util qw(weaken); { my $original = bless {},'My::Test::Class'; my $copy = $original; weaken $original; ok defined($original), '$object still accessible'; }
Update: It will also fail for some pathological cases. Consider:
{ package Foo; sub new { my ($class, $name) = @_; bless {}, $class; }; my $In_global_destruction; END { $In_global_destruction++ }; my $Saved; sub DESTROY { my $self = shift; if ($In_global_destruction) { warn "really destroying $self\n"; } else { warn "not really destroying $self\n"; $Saved = $self; }; }; }; use strict; use warnings; use Test::More 'no_plan'; use Scalar::Util qw(weaken); my $copy; { my $original = Foo->new; $copy = $original; weaken $copy; destroyed_ok($original, '$original'); }; ok !defined($copy), '$original really destroyed'; __END__ # produces not really destroying Foo=HASH(0x512f0) ok 1 - $original was destroyed not ok 2 - $original really destroyed # Failed test (foo.pl at line 113) 1..2 # Looks like you failed 1 tests of 2. really destroying Foo=HASH(0x512f0)
which is, I guess, exactly the sort of subtle bug you're trying to detect :-)
|
|---|