Skip Menu |

This queue is for tickets about the MRO-Compat CPAN distribution.

Report information
The Basics
Id: 36256
Status: resolved
Priority: 0/
Queue: MRO-Compat

People
Owner: blblack [...] gmail.com
Requestors: aegrimemoria [...] gmail.com
Cc:
AdminCc:

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



Subject: mro::set_mro broken
Calling mro::set_mro('Some::Package', 'c3') dies due to an incorrect sanity check. Also, a couple error messages aren't handled correctly because they're single quoted rather than double quoted. Attached is a patch fixing these issues.
Subject: Compat.pm.patch
--- Compat.pm 2008-05-28 15:43:58.000000000 -0700 +++ Compat.pm~ 2008-05-28 15:48:36.000000000 -0700 @@ -171,14 +171,14 @@ sub __set_mro { my ($classname, $type) = @_; if(!defined $classname || !$type) { - die q{Usage: mro::set_mro($classname, $type)}; + die "Usage: mro::set_mro($classname, $type)"; } if($type eq 'c3') { eval "package $classname; use Class::C3"; die $@ if $@; } - if($type ne 'dfs') { - die q{Invalid mro type "$type"}; + elsif($type ne 'dfs') { + die "Invalid mro type '$type'"; } # In the dfs case, check whether we need to undo C3
On Wed May 28 18:58:30 2008, evazion wrote: Show quoted text
> Calling mro::set_mro('Some::Package', 'c3') dies due to an incorrect > sanity check. Also, a couple error messages aren't handled correctly > because they're single quoted rather than double quoted. Attached is a > patch fixing these issues.
You're definitely right that set_mro is broken. It only works for the "dfs" case (and fails for invalid types), the logic is broken for the "c3" case. The test suite was lacking here, it only covered the "use mro 'c3'" and mro::set_mro('dfs') cases, not the other two possibilities. The first of the two single-quoted error messages was intended, but the second one was not. Does this patch work for you?
=== lib/MRO/Compat.pm ================================================================== --- lib/MRO/Compat.pm (revision 4371) +++ lib/MRO/Compat.pm (local) @@ -170,22 +170,25 @@ sub __set_mro { my ($classname, $type) = @_; + if(!defined $classname || !$type) { die q{Usage: mro::set_mro($classname, $type)}; } + if($type eq 'c3') { eval "package $classname; use Class::C3"; die $@ if $@; } - if($type ne 'dfs') { - die q{Invalid mro type "$type"}; + elsif($type eq 'dfs') { + # In the dfs case, check whether we need to undo C3 + if(defined $Class::C3::MRO{$classname}) { + Class::C3::_remove_method_dispatch_table($classname); + } + delete $Class::C3::MRO{$classname}; } - - # In the dfs case, check whether we need to undo C3 - if(defined $Class::C3::MRO{$classname}) { - Class::C3::_remove_method_dispatch_table($classname); + else { + die qq{Invalid mro type "$type"}; } - delete $Class::C3::MRO{$classname}; return; } === t/20mros.t ================================================================== --- t/20mros.t (revision 4371) +++ t/20mros.t (local) @@ -2,7 +2,7 @@ use strict; use warnings; -use Test::More tests => 8; +use Test::More tests => 14; BEGIN { use_ok('MRO::Compat'); @@ -28,6 +28,8 @@ package GGG3; our @ISA = qw/FFF3/; use mro 'c3'; } +is(mro::get_mro('FFF3'), 'c3'); + is_deeply( mro::get_linear_isa('GGG'), [ 'GGG', 'FFF', 'EEE', 'BBB', 'AAA', 'CCC', 'DDD' ], @@ -50,16 +52,33 @@ is(FFF3->testsub(), 'FFF3_first_in_c3', 'c3 resolution post-init'); mro::set_mro('FFF3', 'dfs'); +is(mro::get_mro('FFF3'), 'dfs'); is_deeply( mro::get_linear_isa('FFF3'), [ 'FFF3', 'EEE3', 'BBB3', 'AAA3', 'CCC3', 'DDD3' ], "get_linear_isa for FFF3 (dfs)", ); -is(FFF3->testsub(), 'FFF3_first_in_dfs', 'dfs resolution post- setmro dfs'); +is(FFF3->testsub(), 'FFF3_first_in_dfs', 'dfs resolution post- set_mro dfs'); is_deeply( mro::get_linear_isa('GGG3'), [ 'GGG3', 'FFF3', 'EEE3', 'BBB3', 'CCC3', 'DDD3', 'AAA3' ], "get_linear_isa for GGG3 (still c3)", ); + +mro::set_mro('FFF3', 'c3'); +is(mro::get_mro('FFF3'), 'c3'); +is_deeply( + mro::get_linear_isa('FFF3'), + [ 'FFF3', 'EEE3', 'BBB3', 'CCC3', 'DDD3', 'AAA3' ], + "get_linear_isa for FFF3 (reset to c3 via set_mro)", +); + +eval "package FFF3; use mro 'dfs'"; +is(mro::get_mro('FFF3'), 'dfs'); +is_deeply( + mro::get_linear_isa('FFF3'), + [ 'FFF3', 'EEE3', 'BBB3', 'AAA3', 'CCC3', 'DDD3' ], + "get_linear_isa for FFF3 (reset to dfs via 'use mro')", +);
From: aegrimemoria [...] gmail.com
On Wed May 28 19:27:43 2008, BLBLACK wrote: Show quoted text
> > You're definitely right that set_mro is broken. It only works for
the Show quoted text
> "dfs" case (and fails for invalid types), the logic is broken for
the Show quoted text
> "c3" case. The test suite was lacking here, it only covered
the "use Show quoted text
> mro 'c3'" and mro::set_mro('dfs') cases, not the other two
possibilities. Show quoted text
> > The first of the two single-quoted error messages was intended, but
the Show quoted text
> second one was not. > > Does this patch work for you?
Yep. Thanks for the quick response!
Fixed in 0.09 (same code as 0.08_01, uploaded to CPAN a few mins ago).