Skip Menu |

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

Report information
The Basics
Id: 71831
Status: resolved
Priority: 0/
Queue: Test-MockObject

People
Owner: Nobody in particular
Requestors: koterpillar [...] gmail.com
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in:
  • 1.06
  • 1.09
  • 1.20110612
Fixed in: (no value)



Subject: Test::MockObject::Externds does not clear its calls
The objects created with Test::MockObject::Extends do not call Test::MockObject::DESTROY and, as such, their calls are not cleared. This will be a problem if a new Test::MockObject is allocated the same address later. The attached program demonstrates the behaviour: it Extends an object and lets it go out of scope. When another object is created, it will likely be allocated the same address in memory, and report call_pos and friends from the first one. This is not a problem with normal Test::MockObject, which destroys the calls in DESTROY. The expected output from the program is: Created object: Test::MockObject=HASH(0x9be88c8) Created object: Test::MockObject=HASH(0x9be88c8) Created object: T::MO::E::a=HASH(0x9be88c8) Created object: T::MO::E::b=HASH(0x9be88c8) The address pairs should be the same, but no extra lines should be printed. However, the actual output is: Created object: Test::MockObject=HASH(0x9be88c8) Created object: Test::MockObject=HASH(0x9be88c8) Created object: T::MO::E::a=HASH(0x9be88c8) Created object: T::MO::E::b=HASH(0x9be88c8) test The last line indicates the newly-created object inherited call records from the previous one.
Subject: mockobject.pm
#!/usr/bin/env perl use warnings; use strict; use Test::MockObject; use Test::MockObject::Extends; sub mocked { my $obj = Test::MockObject->new(); print "Created object: $obj\n"; print $obj->call_pos(1) . "\n" if $obj->call_pos(1); $obj->set_true('test'); $obj->test(); } mocked(); mocked(); sub extended { my $obj = bless {}, 'Ggg'; $obj = Test::MockObject::Extends->new($obj); print "Created object: $obj\n"; print $obj->call_pos(1) . "\n" if $obj->call_pos(1); $obj->set_true('test'); $obj->test(); } extended(); extended();
From: jkahrman [...] mathworks.com
I have a patch for this that's been working for us. On Fri Oct 21 01:52:18 2011, http://koterpillar.myopenid.com/ wrote: Show quoted text
> The objects created with Test::MockObject::Extends do not call > Test::MockObject::DESTROY and, as such, their calls are not cleared. > > This will be a problem if a new Test::MockObject is allocated the same > address later. > > The attached program demonstrates the behaviour: it Extends an object > and lets it go out of scope. When another object is created, it will > likely be allocated the same address in memory, and report call_pos and > friends from the first one. > > This is not a problem with normal Test::MockObject, which destroys the > calls in DESTROY. > > The expected output from the program is: > > Created object: Test::MockObject=HASH(0x9be88c8) > Created object: Test::MockObject=HASH(0x9be88c8) > Created object: T::MO::E::a=HASH(0x9be88c8) > Created object: T::MO::E::b=HASH(0x9be88c8) > > The address pairs should be the same, but no extra lines should be > printed. > > However, the actual output is: > > Created object: Test::MockObject=HASH(0x9be88c8) > Created object: Test::MockObject=HASH(0x9be88c8) > Created object: T::MO::E::a=HASH(0x9be88c8) > Created object: T::MO::E::b=HASH(0x9be88c8) > test > > The last line indicates the newly-created object inherited call records > from the previous one.
Subject: TMOE.rt71831.patch
--- Test-MockObject-1.20120301/Test/MockObject/Extends.pm 2013-07-24 22:25:40.000000000 -0400 +++ Test-MockObject-1.20120301.rt71831/Test/MockObject/Extends.pm 2015-11-09 22:52:08.000000000 -0500 @@ -26,9 +26,10 @@ my $parent_class = $class->get_class( $fake_class ); $class->check_class_loaded( $parent_class ); - my $self = blessed( $fake_class ) ? $fake_class : {}; + my $blessed = blessed( $fake_class ); + my $self = $blessed ? $fake_class : {}; - bless $self, $class->gen_package( $parent_class ); + bless $self, $class->gen_package( $parent_class, $blessed ); } sub check_class_loaded @@ -55,8 +56,8 @@ sub gen_package { - my ($class, $parent) = @_; - my $package = 'T::MO::E::' . $packname++; + my ($class, $parent, $blessed) = @_; + my $package = 'T::MO::E::' . $packname++; no strict 'refs'; *{ $package . '::mock' } = \&mock; @@ -65,11 +66,27 @@ *{ $package . '::can' } = $class->gen_can( $parent ); *{ $package . '::isa' } = $class->gen_isa( $parent ); *{ $package . '::AUTOLOAD' } = $class->gen_autoload( $parent ); + *{ $package . '::DESTROY' } = $class->gen_DESTROY( $parent, $blessed ); *{ $package . '::__get_parents' } = $class->gen_get_parents( $parent ); return $package; } +sub gen_DESTROY { + my ($class, $parent, $blessed) = @_; + + return sub { + my ($self) = @_; + my @mocked = keys %{Test::MockObject::_subs( $self )}; + $self->unmock($_) + for @mocked; + Test::MockObject::DESTROY($self); + return $blessed + ? bless $self, $parent + : (); + }; +} + sub gen_get_parents { my ($self, $parent) = @_; @@ -150,7 +167,7 @@ { my ($self, $name, $sub) = @_; - Test::MockObject::_set_log( $self, $name, ( $name =~ s/^-// ? 0 : 1 ) ); + Test::MockObject::mock( $self, $name, $sub ); my $mock_sub = sub { @@ -172,7 +189,7 @@ { my ($self, $name) = @_; - Test::MockObject::_set_log( $self, $name, 0 ); + Test::MockObject::remove( $self, $name ); no strict 'refs'; my $glob = *{ ref( $self ) . '::' }; delete $glob->{ $name };
From: jkahrman [...] mathworks.com
Someone also uploaded a different patch last year via github: https://github.com/chromatic/Test-MockObject/pull/15 On Thu Oct 26 10:54:30 2017, jkahrman@mathworks.com wrote: Show quoted text
> I have a patch for this that's been working for us. > > On Fri Oct 21 01:52:18 2011, http://koterpillar.myopenid.com/ wrote:
> > The objects created with Test::MockObject::Extends do not call > > Test::MockObject::DESTROY and, as such, their calls are not cleared. > > > > This will be a problem if a new Test::MockObject is allocated the same > > address later. > > > > The attached program demonstrates the behaviour: it Extends an object > > and lets it go out of scope. When another object is created, it will > > likely be allocated the same address in memory, and report call_pos and > > friends from the first one. > > > > This is not a problem with normal Test::MockObject, which destroys the > > calls in DESTROY. > > > > The expected output from the program is: > > > > Created object: Test::MockObject=HASH(0x9be88c8) > > Created object: Test::MockObject=HASH(0x9be88c8) > > Created object: T::MO::E::a=HASH(0x9be88c8) > > Created object: T::MO::E::b=HASH(0x9be88c8) > > > > The address pairs should be the same, but no extra lines should be > > printed. > > > > However, the actual output is: > > > > Created object: Test::MockObject=HASH(0x9be88c8) > > Created object: Test::MockObject=HASH(0x9be88c8) > > Created object: T::MO::E::a=HASH(0x9be88c8) > > Created object: T::MO::E::b=HASH(0x9be88c8) > > test > > > > The last line indicates the newly-created object inherited call records > > from the previous one.
>
From: jkahrman [...] mathworks.com
Someone also uploaded a different patch last year via github: https://github.com/chromatic/Test-MockObject/pull/15 On Thu Oct 26 10:54:30 2017, jkahrman@mathworks.com wrote: Show quoted text
> I have a patch for this that's been working for us. > > On Fri Oct 21 01:52:18 2011, http://koterpillar.myopenid.com/ wrote:
> > The objects created with Test::MockObject::Extends do not call > > Test::MockObject::DESTROY and, as such, their calls are not cleared. > > > > This will be a problem if a new Test::MockObject is allocated the same > > address later. > > > > The attached program demonstrates the behaviour: it Extends an object > > and lets it go out of scope. When another object is created, it will > > likely be allocated the same address in memory, and report call_pos and > > friends from the first one. > > > > This is not a problem with normal Test::MockObject, which destroys the > > calls in DESTROY. > > > > The expected output from the program is: > > > > Created object: Test::MockObject=HASH(0x9be88c8) > > Created object: Test::MockObject=HASH(0x9be88c8) > > Created object: T::MO::E::a=HASH(0x9be88c8) > > Created object: T::MO::E::b=HASH(0x9be88c8) > > > > The address pairs should be the same, but no extra lines should be > > printed. > > > > However, the actual output is: > > > > Created object: Test::MockObject=HASH(0x9be88c8) > > Created object: Test::MockObject=HASH(0x9be88c8) > > Created object: T::MO::E::a=HASH(0x9be88c8) > > Created object: T::MO::E::b=HASH(0x9be88c8) > > test > > > > The last line indicates the newly-created object inherited call records > > from the previous one.
>
Fixed in 1.20180705. Apologies for letting this linger.