Document error "Smart matching a non-overloaded object breaks encapsulation"
[p5sagit/p5-mst-13.2.git] / t / op / smartmatch.t
CommitLineData
0d863452 1#!./perl
2
3BEGIN {
4 chdir 't';
5 @INC = '../lib';
6 require './test.pl';
7}
8use strict;
9
10use Tie::Array;
11use Tie::Hash;
12
0d863452 13# Predeclare vars used in the tests:
14my $deep1 = []; push @$deep1, \$deep1;
15my $deep2 = []; push @$deep2, \$deep2;
16
0d863452 17my @nums = (1..10);
18tie my @tied_nums, 'Tie::StdArray';
19@tied_nums = (1..10);
20
21my %hash = (foo => 17, bar => 23);
22tie my %tied_hash, 'Tie::StdHash';
23%tied_hash = %hash;
24
1cfb7049 25{
26 package Test::Object::NoOverload;
27 sub new { bless { key => 1 } }
28}
29
30{
31 package Test::Object::CopyOverload;
32 sub new { bless { key => 1 } }
33 use overload '~~' => sub { my %hash = %{ $_[0] }; %hash ~~ $_[1] };
34}
35
36{
37 package Test::Object::OverloadCodeRef;
38 sub new { bless $_[1] }
39 use overload '~~' => sub { shift->($_[1]) };
40}
41
42our $ov_obj = Test::Object::CopyOverload->new;
43our $obj = Test::Object::NoOverload->new;
44our $false_obj = Test::Object::OverloadCodeRef->new(sub { 0 });
45our $true_obj = Test::Object::OverloadCodeRef->new(sub { 1 });
46
47
0d863452 48# Load and run the tests
49my @tests = map [chomp and split /\t+/, $_, 3], grep !/^#/ && /\S/, <DATA>;
50plan tests => 2 * @tests;
51
52for my $test (@tests) {
53 my ($yn, $left, $right) = @$test;
54
55 match_test($yn, $left, $right);
56 match_test($yn, $right, $left);
57}
58
59sub match_test {
60 my ($yn, $left, $right) = @_;
61
62 die "Bad test spec: ($yn, $left, $right)"
a86f5011 63 unless $yn eq "" || $yn eq "!" || $yn eq '@';
0d863452 64
65 my $tstr = "$left ~~ $right";
66
67 my $res;
3e7dd34d 68 $res = eval $tstr // ""; #/ <- fix syntax colouring
0d863452 69
a86f5011 70 chomp $@;
71
72 if ( $yn eq '@' ) {
73 ok( $@ ne '', sprintf "%s%s: %s", $tstr, $@ ? ( ', $@', $@ ) : ( '', $res ) );
74 } else {
75 if ( $@ ne '' ) {
76 fail("$tstr, \$\@: $@");
77 } else {
78 ok( ($yn eq '!' xor $res), "$tstr: $res");
79 }
80 }
0d863452 81}
82
83
84
85sub foo {}
86sub bar {2}
1cfb7049 87sub gorch {2}
88sub fatal {die "fatal sub\n"}
0d863452 89
1cfb7049 90sub a_const() {die "const\n" if @_; "a constant"}
91sub b_const() {die "const\n" if @_; "a constant"}
0d863452 92
e5de85fa 93# Prefix character :
94# - expected to match
95# ! - expected to not match
96# @ - expected to be a compilation failure
0d863452 97__DATA__
1cfb7049 98# OBJECT
99# - overloaded
100 $ov_obj "key"
101 $ov_obj {"key" => 1}
102! $ov_obj "foo"
103! $ov_obj \&foo
104@ $ov_obj \&fatal
105
106# regular object
107@ $obj "key"
108@ $obj {"key" => 1}
109@ $obj "foo"
110@ $obj $obj
111@ $obj sub { 1 }
112@ $obj sub { 0 }
113@ $obj \&foo
114@ $obj \&fatal
115
0d863452 116# CODE ref against argument
117# - arg is code ref
118 \&foo \&foo
119! \&foo sub {}
120! \&foo \&bar
1cfb7049 121 \&fatal \&fatal
122! \&foo \&fatal
0d863452 123
124# - arg is not code ref
1cfb7049 125 1 sub{shift}
126! 0 sub{shift}
127! undef sub{shift}
128 undef sub{not shift}
129 1 sub{scalar @_}
130 [] \&bar
131 {} \&bar
132 qr// \&bar
133! [] \&foo
134! {} \&foo
135! qr// \&foo
136! undef \&foo
137 undef \&bar
138@ undef \&fatal
139@ 1 \&fatal
140@ [] \&fatal
141@ "foo" \&fatal
142@ qr// \&fatal
143@ $obj \&bar
144 $ov_obj \&bar
0d863452 145
146# - null-prototyped subs
147 a_const "a constant"
148 a_const a_const
149 a_const b_const
1cfb7049 150 \&a_const \&a_const
151! \&a_const \&b_const
152
153# - non-null-prototyped subs
154! \&bar \&gorch
155 bar gorch
156@ fatal bar
0d863452 157
158# HASH ref against:
159# - another hash ref
160 {} {}
161! {} {1 => 2}
162 {1 => 2} {1 => 2}
163 {1 => 2} {1 => 3}
164! {1 => 2} {2 => 3}
165 \%main:: {map {$_ => 'x'} keys %main::}
166
167# - tied hash ref
168 \%hash \%tied_hash
169 \%tied_hash \%tied_hash
170
171# - an array ref
172 \%:: [keys %main::]
173! \%:: []
174 {"" => 1} [undef]
71b0fb34 175 { foo => 1 } ["foo"]
176 { foo => 1 } ["foo", "bar"]
177 \%hash ["foo", "bar"]
178 \%hash ["foo"]
179! \%hash ["quux"]
180 \%hash [qw(foo quux)]
0d863452 181
182# - a regex
183 {foo => 1} qr/^(fo[ox])$/
184! +{0..100} qr/[13579]$/
185
186# - a string
187 +{foo => 1, bar => 2} "foo"
188! +{foo => 1, bar => 2} "baz"
189
190
191# ARRAY ref against:
192# - another array ref
1cfb7049 193 [] []
194! [] [1]
0d863452 195 [["foo"], ["bar"]] [qr/o/, qr/a/]
196 ["foo", "bar"] [qr/o/, qr/a/]
71b0fb34 197! ["foo", "bar"] [qr/o/, "foo"]
1cfb7049 198 $deep1 $deep1
199! $deep1 $deep2
0d863452 200
1cfb7049 201 \@nums \@tied_nums
0d863452 202
203# - a regex
204 [qw(foo bar baz quux)] qr/x/
205! [qw(foo bar baz quux)] qr/y/
206
207# - a number
208 [qw(1foo 2bar)] 2
25a0c96d 209 [qw(foo 2)] 2
210 [qw(foo 2)] 2.0_0e+0
211! [qw(1foo bar2)] 2
0d863452 212
213# - a string
214! [qw(1foo 2bar)] "2"
25a0c96d 215 [qw(1foo 2bar)] "2bar"
0d863452 216
217# Number against number
218 2 2
219! 2 3
220
221# Number against string
222 2 "2"
223 2 "2.0"
224! 2 "2bananas"
225! 2_3 "2_3"
226
227# Regex against string
228 qr/x/ "x"
229! qr/y/ "x"
230
231# Regex against number
232 12345 qr/3/
233
234
235# Test the implicit referencing
236 @nums 7
237 @nums \@nums
238! @nums \\@nums
239 @nums [1..10]
240! @nums [0..9]
241
242 %hash "foo"
243 %hash /bar/
71b0fb34 244 %hash [qw(bar)]
245! %hash [qw(a b c)]
246 %hash %hash
247 %hash {%hash}
248 %hash %tied_hash
249 %tied_hash %tied_hash
250 %hash { foo => 5, bar => 10 }
251! %hash { foo => 5, bar => 10, quux => 15 }
252
253 @nums { 1, '', 2, '' }
254 @nums { 1, '', 12, '' }
255! @nums { 11, '', 12, '' }
b472f62a 256
257# UNDEF
258! 3 undef
259! 1 undef
260! [] undef
261! {} undef
262! \%::main undef
263! [1,2] undef
264! %hash undef
265! @nums undef
266! "foo" undef
267! "" undef
268! !1 undef
269! \&foo undef
270! sub { } undef