Commit | Line | Data |
---|---|---|
8d6d96c1 HS |
1 | #!./perl -w |
2 | ||
3 | BEGIN { | |
8d6d96c1 HS |
4 | chdir 't' if -d 't'; |
5 | @INC = '../lib'; | |
ead3e279 | 6 | require './test.pl'; |
8d6d96c1 HS |
7 | } |
8 | ||
ead3e279 | 9 | use strict; |
8d6d96c1 | 10 | |
8d6d96c1 HS |
11 | tie my $c => 'Tie::Monitor'; |
12 | ||
ead3e279 NC |
13 | sub expected_tie_calls { |
14 | my ($obj, $rexp, $wexp) = @_; | |
15 | local $::Level = $::Level + 1; | |
16 | my ($rgot, $wgot) = $obj->init(); | |
17 | is ($rgot, $rexp); | |
18 | is ($wgot, $wexp); | |
8d6d96c1 HS |
19 | } |
20 | ||
ead3e279 | 21 | # Use ok() instead of is(), cmp_ok() etc, to strictly control number of accesses |
8d6d96c1 | 22 | my($r, $s); |
ead3e279 NC |
23 | ok($r = $c + 0 == 0, 'the thing itself'); |
24 | expected_tie_calls(tied $c, 1, 0); | |
25 | ok($r = "$c" eq '0', 'the thing itself'); | |
26 | expected_tie_calls(tied $c, 1, 0); | |
27 | ||
28 | ok($c . 'x' eq '0x', 'concat'); | |
29 | expected_tie_calls(tied $c, 1, 0); | |
30 | ok('x' . $c eq 'x0', 'concat'); | |
31 | expected_tie_calls(tied $c, 1, 0); | |
8d6d96c1 | 32 | $s = $c . $c; |
ead3e279 NC |
33 | ok($s eq '00', 'concat'); |
34 | expected_tie_calls(tied $c, 2, 0); | |
8d6d96c1 HS |
35 | $r = 'x'; |
36 | $s = $c = $r . 'y'; | |
ead3e279 NC |
37 | ok($s eq 'xy', 'concat'); |
38 | expected_tie_calls(tied $c, 1, 1); | |
8d6d96c1 | 39 | $s = $c = $c . 'x'; |
ead3e279 NC |
40 | ok($s eq '0x', 'concat'); |
41 | expected_tie_calls(tied $c, 2, 1); | |
8d6d96c1 | 42 | $s = $c = 'x' . $c; |
ead3e279 NC |
43 | ok($s eq 'x0', 'concat'); |
44 | expected_tie_calls(tied $c, 2, 1); | |
8d6d96c1 | 45 | $s = $c = $c . $c; |
ead3e279 NC |
46 | ok($s eq '00', 'concat'); |
47 | expected_tie_calls(tied $c, 3, 1); | |
8d6d96c1 | 48 | |
1e968d83 | 49 | $s = chop($c); |
ead3e279 NC |
50 | ok($s eq '0', 'multiple magic in core functions'); |
51 | expected_tie_calls(tied $c, 1, 1); | |
1e968d83 | 52 | |
5cf4b255 FC |
53 | $c = *strat; |
54 | $s = $c; | |
ead3e279 NC |
55 | ok($s eq *strat, |
56 | 'Assignment should not ignore magic when the last thing assigned was a glob'); | |
074ededa | 57 | expected_tie_calls(tied $c, 1, 1); |
5cf4b255 | 58 | |
f64c9ac5 FC |
59 | # A plain *foo should not call get-magic on *foo. |
60 | # This method of scalar-tying an immutable glob relies on details of the | |
61 | # current implementation that are subject to change. This test may need to | |
62 | # be rewritten if they do change. | |
63 | my $tyre = tie $::{gelp} => 'Tie::Monitor'; | |
64 | # Compilation of this eval autovivifies the *gelp glob. | |
65 | eval '$tyre->init(0); () = \*gelp'; | |
66 | my($rgot, $wgot) = $tyre->init(0); | |
ead3e279 NC |
67 | ok($rgot == 0, 'a plain *foo causes no get-magic'); |
68 | ok($wgot == 0, 'a plain *foo causes no set-magic'); | |
f64c9ac5 | 69 | |
767eda44 FC |
70 | # get-magic when exiting a non-lvalue sub in potentially autovivify- |
71 | # ing context | |
074ededa | 72 | my $tied_to = tie $_{elem}, "Tie::Monitor"; |
767eda44 FC |
73 | eval { () = sub { delete $_{elem} }->()->[3] }; |
74 | ok +($tied_to->init)[0], | |
75 | 'get-magic is called on mortal magic var on sub exit in autoviv context'; | |
76 | $tied_to = tie $_{elem}, "Tie::Monitor"; | |
77 | eval { () = sub { return delete $_{elem} }->()->[3] }; | |
78 | ok +($tied_to->init)[0], | |
79 | 'get-magic is called on mortal magic var on return in autoviv context'; | |
80 | ||
ead3e279 | 81 | done_testing(); |
5cf4b255 | 82 | |
8d6d96c1 HS |
83 | # adapted from Tie::Counter by Abigail |
84 | package Tie::Monitor; | |
85 | ||
86 | sub TIESCALAR { | |
87 | my($class, $value) = @_; | |
88 | bless { | |
89 | read => 0, | |
90 | write => 0, | |
91 | values => [ 0 ], | |
92 | }; | |
93 | } | |
94 | ||
95 | sub FETCH { | |
96 | my $self = shift; | |
97 | ++$self->{read}; | |
98 | $self->{values}[$#{ $self->{values} }]; | |
99 | } | |
100 | ||
101 | sub STORE { | |
102 | my($self, $value) = @_; | |
103 | ++$self->{write}; | |
104 | push @{ $self->{values} }, $value; | |
105 | } | |
106 | ||
107 | sub init { | |
108 | my $self = shift; | |
109 | my @results = ($self->{read}, $self->{write}); | |
110 | $self->{read} = $self->{write} = 0; | |
111 | $self->{values} = [ 0 ]; | |
112 | @results; | |
113 | } |