X-Git-Url: http://git.vpit.fr/?a=blobdiff_plain;f=t%2F15-self.t;h=a9560ab52230a53a9140e336bfddb571612838d7;hb=ecc16f5aeded896b3ab1f0019fc489bb5e15bc08;hp=504c4b217bfb46499b8bb0c321d87534df07d47b;hpb=ff3e3f39b252f61a6061d3e3de3f24147bbdd77d;p=perl%2Fmodules%2FVariable-Magic.git diff --git a/t/15-self.t b/t/15-self.t index 504c4b2..a9560ab 100644 --- a/t/15-self.t +++ b/t/15-self.t @@ -1,11 +1,19 @@ -#!perl -T +#!perl use strict; use warnings; -use Test::More tests => 17; +use Test::More; -use Variable::Magic qw/wizard cast dispell getdata getsig/; +my $tests; +BEGIN { $tests = 18 } + +plan tests => $tests; + +use Variable::Magic qw; + +use lib 't/lib'; +use Variable::Magic::TestGlobalDestruction; my $c = 0; @@ -39,7 +47,6 @@ my $c = 0; $w = getdata $wiz, $wiz; is($c, 1, 'getdata on magical self doesn\'t trigger callbacks'); - # is(getsig($w), getsig($wiz), 'getdata returns the correct wizard'); $res = eval { dispell $wiz, $wiz }; is($@, '', 're-dispell on self doesn\'t croak'); @@ -50,13 +57,151 @@ my $c = 0; ok($res, 're-re-cast on self is valid'); } +{ + my %testcases; + + BEGIN { + my %magics = do { + my @magics = qw; + push @magics, 'local' if MGf_LOCAL; + push @magics, qw if VMG_UVAR; + map { $_ => 1 } @magics; + }; + + %testcases = ( + SCALAR => { + id => 1, + ctor => sub { my $val = 123; \$val }, + tests => [ + get => [ sub { my $val = ${$_[0]} } => 123 ], + set => [ sub { ${$_[0]} = 456; $_[0] } => \456 ], + free => [ ], + ], + }, + ARRAY => { + id => 2, + ctor => sub { [ 0 .. 2 ] }, + tests => [ + len => [ sub { my $len = @{$_[0]} } => 3 ], + clear => [ sub { @{$_[0]} = (); $_[0] } => [ ] ], + free => [ ], + ], + }, + HASH => { + id => 3, + ctor => sub { +{ foo => 'bar' } }, + tests => [ + clear => [ sub { %{$_[0]} = (); $_[0] } => +{ } ], + free => [ ], + fetch => [ sub { my $val = $_[0]->{foo} } => 'bar' ], + store => [ sub { $_[0]->{foo} = 'baz'; $_[0] } => { foo => 'baz' } ], + exists => [ sub { my $res = exists $_[0]->{foo} } => 1 ], + delete => [ sub { my $val = delete $_[0]->{foo} } => 'bar' ], + ], + }, + ); + + my $count; + + for my $testcases (map $_->{tests}, values %testcases) { + my $i = 0; + while ($i < $#$testcases) { + if ($magics{$testcases->[$i]}) { + $i += 2; + ++$count; + } else { + splice @$testcases, $i, 2; + } + } + } + + $tests += $count * 2 * 2 * 3; + } + + my @types = sort { $testcases{$a}->{id} <=> $testcases{$b}->{id} } + keys %testcases; + + my $other_wiz = wizard data => sub { 'abc' }; + + for my $type (@types) { + my $ctor = $testcases{$type}->{ctor}; + + my @testcases = @{$testcases{$type}->{tests}}; + while (@testcases >= 2) { + my ($magic, $test) = splice @testcases, 0, 2; + + for my $dispell (0, 1) { + for my $die (0, 1) { + my $desc = $dispell ? 'dispell' : 'cast'; + $desc .= " a $type from a $magic callback"; + $desc .= ' and dieing' if $die; + + my $wiz; + my $code = $dispell + ? sub { &dispell($_[0], $wiz); die 'oops' if $die; return } + : sub { &cast($_[0], $other_wiz); die 'oops' if $die; return }; + $wiz = wizard( + data => sub { 'xyz' }, + $magic => $code, + ); + + my ($var, $res, $err); + if ($magic eq 'free') { + eval { + my $v = $ctor->(); + &cast($v, $wiz); + }; + $err = $@; + } else { + $var = $ctor->(); + &cast($var, $wiz); + $res = eval { + $test->[0]->($var); + }; + $err = $@; + } + + if ($die) { + like $err, qr/^oops at/, "$desc: correct error"; + is $res, undef, "$desc: returned undef"; + } else { + is $err, '', "$desc: no error"; + is_deeply $res, $test->[1], "$desc: returned value"; + } + if (not defined $var) { + pass "$desc: meaningless"; + } elsif ($dispell) { + my $data = &getdata($var, $wiz); + is $data, undef, "$desc: correctly dispelled"; + } else { + my $data = &getdata($var, $other_wiz); + is $data, 'abc', "$desc: correctly cast"; + } + } + } + } + } +} + +SKIP: { + skip "Called twice starting from perl 5.24" => 1 if "$]" >= 5.024; + + my $recasted = 0; + + my $wiz2 = wizard; + my $wiz1 = wizard free => sub { ++$recasted; &cast($_[0], $wiz2); die 'xxx' }; + + local $@; + my $res = eval { + my $v = do { my $val = 123; \$val }; + &cast($v, $wiz1); + }; + + is $recasted, 1, 'recasting free callback called only once'; +} + eval q[ use lib 't/lib'; BEGIN { require Variable::Magic::TestDestroyRequired; } ]; is $@, '', 'wizard destruction at the end of BEGIN-time require doesn\'t panic'; - -if ((defined $ENV{PERL_DESTRUCT_LEVEL} and $ENV{PERL_DESTRUCT_LEVEL} >= 3) - or eval "use Perl::Destruct::Level level => 3; 1") { - diag 'Test global destruction'; -}