Skip Menu |

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

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

People
Owner: chromatic [...] cpan.org
Requestors: adamk [...] cpan.org
Cc:
AdminCc:

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



Subject: Test::MockObject triggers re-entrance bug in UNIVERSAL::isa
In some situations, it appears that using Test::MockObject changes the class sufficiently to trigger spurious warnings. I _suspect_ this is due to the (already filed against UNIVERSAL::isa|can) re-entrance bug, but that is not an informed conclusion, just one based on best guess. I've filed this seperately, because the same case NOT mocked does not show the problem, so mocking is introducing something extra. Find attached the proof for this, as a test script. It uses some extra modules that aren't your deps, so you should either use it for your own testing, or do some copy paste from those modules and keep the script in the distribution. I'll add additional edge cases as I discover them. This can really be solved in two ways. Either make it so that Mocking does not trigger the re-entrance (or whatever the problem actually is) bug, or fix the re-entrance bug in UNIVERSAL::can|isa and do an incremental release to update the dependency so the newer version of those get installed. Unfortunately, this STILL doesn't fix my original problem, but these last two bugs are obscuring the "real" problem I feel.
Subject: edge-cases.t
#!/usr/bin/perl -w # Test whether Test::MockObject is sane with several variations of edge cases use strict; use File::Spec (); use Params::Util; use Class::Inspector; # Do we have Test::MockObject use constant TMOE => 'Test::MockObject::Extend'; use constant TMOE_INSTALLED => Class::Inspector->installed(TMOE); use Test::More; BEGIN { TMOE_INSTALLED ? plan( skip_all => 'Test::MockObject::Extends not available' ) : plan( tests => 33 ); } # Look for warnings as we go, we shouldn't see any my $problem_count = 0; local $SIG{__WARN__} = sub { $problem_count += 1 }; # This is so we can local $SIG{__DIE__} = sub { $problem_count += 10 }; # tell them apart. sub no_problems () { is( $problem_count, 0, 'No problems fired' ); } # Testing an object sub test_object { my $foo = shift; ok( $foo->isa('Foo'), '$foo->isa("Foo") ok' ); no_problems; ok( Params::Util::_INSTANCE($foo, 'Foo'), '_INSTANCE($foo, "Foo")' ); no_problems; is( $foo->foo_foo($foo), 'yes', 'An isa inside an assertion in a mocked method ok' ); no_problems; isa_ok( $foo, 'Foo' ); no_problems; is( $foo->autoload_foo($foo), 'yes', 'An isa inside an assertion in an AUTOLOAD ok' ); no_problems; } ##################################################################### # Main Testing # Prove the functions work normally my $foo1 = Foo->new; test_object( $foo1 ); # Repeat for a transparent subclass my $bar1 = Foo::Bar->new; isa_ok( $bar1, 'Foo' ); isa_ok( $bar1, 'Foo::Bar' ); is( $bar1->foo, 'foo', '->foo is ok' ); is( $bar1->bar, 'bar', '->bar is ok' ); test_object( $bar1 ); # Do both of them still work with UNIVERSAL::isa|can loaded use_ok( 'UNIVERSAL::isa' ); use_ok( 'UNIVERSAL::can' ); my $foo2 = Foo->new; test_object( $foo2 ); my $bar2 = Foo::Bar->new; test_object( $bar2 ); # Do both still work when transparently mock-extended use_ok( 'Test::MockObject::Extends' ); my $foo3 = Test::MockObject::Extends->new( $foo1 ); test_object( $foo3 ); my $bar3 = Test::MockObject::Extends->new( $bar1 ); test_object( $bar3 ); exit(0); ##################################################################### # The Test Package package Foo; sub new { bless { }, $_[0]; } # A boring method sub foo { 'foo' } # A normally-interesting method sub foo_foo { my $self = shift; if ( Params::Util::_INSTANCE(shift, 'Foo') ) { return 'yes'; } else { return 'no'; } } sub AUTOLOAD { my ($method) = $Foo::AUTOLOAD =~ m/^.*::(.*)$/s or return undef; if ( $method eq 'autoload_foo' ) { if ( Params::Util::_INSTANCE(shift, 'Foo') ) { return 'yes'; } else { return 'no'; } } else { die "Tests not meant to be able to get here"; } } package Foo::Bar; use base 'Foo'; use vars qw{$VERSION}; BEGIN { $VERSION = '0.01'; } sub bar { 'bar' } 1;
I can't reproduce this with 1.07; please re-open if you can. Thanks for the report!