Smart match when a hash is on the RHS
[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
1cfb7049 36our $ov_obj = Test::Object::CopyOverload->new;
37our $obj = Test::Object::NoOverload->new;
1cfb7049 38
73aec0b1 39my @keyandmore = qw(key and more);
40my @fooormore = qw(foo or more);
41my %keyandmore = map { $_ => 0 } @keyandmore;
42my %fooormore = map { $_ => 0 } @fooormore;
43
0d863452 44# Load and run the tests
9e079ace 45plan "no_plan";
0d863452 46
9e079ace 47while (<DATA>) {
48 next if /^#/ || !/\S/;
49 chomp;
73aec0b1 50 my ($yn, $left, $right, $note) = split /\t+/;
0d863452 51
73aec0b1 52 local $::TODO = $note =~ /TODO/;
0d863452 53
85af77a5 54 die "Bad test spec: ($yn, $left, $right)" if $yn =~ /[^!@=]/;
9e079ace 55
0d863452 56 my $tstr = "$left ~~ $right";
9e079ace 57
85af77a5 58 test_again:
9e079ace 59 my $res = eval $tstr;
0d863452 60
a86f5011 61 chomp $@;
62
85af77a5 63 if ( $yn =~ /@/ ) {
9e079ace 64 ok( $@ ne '', "$tstr dies" )
65 and print "# \$\@ was: $@\n";
a86f5011 66 } else {
85af77a5 67 my $test_name = $tstr . ($yn =~ /!/ ? " does not match" : " matches");
a86f5011 68 if ( $@ ne '' ) {
9e079ace 69 fail($test_name);
70 print "# \$\@ was: $@\n";
a86f5011 71 } else {
85af77a5 72 ok( ($yn =~ /!/ xor $res), $test_name );
a86f5011 73 }
74 }
85af77a5 75
76 if ( $yn =~ s/=// ) {
77 $tstr = "$right ~~ $left";
78 goto test_again;
79 }
0d863452 80}
81
82
83
84sub foo {}
73aec0b1 85sub bar {42}
86sub gorch {42}
1cfb7049 87sub fatal {die "fatal sub\n"}
0d863452 88
0cfbf1ea 89# to test constant folding
18d11902 90sub FALSE() { 0 }
91sub TRUE() { 1 }
0d863452 92
e5de85fa 93# Prefix character :
94# - expected to match
95# ! - expected to not match
96# @ - expected to be a compilation failure
85af77a5 97# = - expected to match symmetrically (runs test twice)
73aec0b1 98# Data types to test :
85af77a5 99# undef
73aec0b1 100# Object-overloaded
101# Object
73aec0b1 102# Coderef
103# Hash
104# Hashref
105# Array
106# Arrayref
85af77a5 107# Tied arrays and hashes
108# Arrays that reference themselves
73aec0b1 109# Regex (// and qr//)
85af77a5 110# Range
73aec0b1 111# Num
112# Str
85af77a5 113# Other syntactic items of interest:
114# Constants
115# Values returned by a sub call
0d863452 116__DATA__
85af77a5 117# Any ~~ undef
33570f8b 118! $ov_obj undef
85af77a5 119! $obj undef
120! sub {} undef
121! %hash undef
122! \%hash undef
123! {} undef
124! @nums undef
125! \@nums undef
126! [] undef
127! %tied_hash undef
128! @tied_nums undef
129! $deep1 undef
130! /foo/ undef
131! qr/foo/ undef
132! 21..30 undef
133! 189 undef
134! "foo" undef
135! "" undef
136! !1 undef
137 undef undef
62ec5f58 138 (my $u) undef
85af77a5 139
140# Any ~~ object overloaded
141# object overloaded ~~ Any
4cbab0e9 142 $ov_obj $ov_obj
85af77a5 143=@ $ov_obj \&fatal
144=! $ov_obj \&FALSE
0cfbf1ea 145= $ov_obj \&TRUE
85af77a5 146=! $ov_obj \&foo
147= $ov_obj \&bar
148= $ov_obj sub { shift ~~ "key" }
a4a197da 149=! $ov_obj sub { shift ne "key" }
85af77a5 150=! $ov_obj sub { shift ~~ "foo" }
151= $ov_obj %keyandmore TODO
152=! $ov_obj %fooormore
153= $ov_obj {"key" => 1}
154= $ov_obj {"key" => 1, bar => 2} TODO
155=! $ov_obj {"foo" => 1}
61a621c6 156= $ov_obj @keyandmore TODO
85af77a5 157=! $ov_obj @fooormore
61a621c6 158= $ov_obj ["key" => 1] TODO
85af77a5 159=! $ov_obj ["foo" => 1]
61a621c6 160= $ov_obj /key/ TODO
85af77a5 161=! $ov_obj /foo/
61a621c6 162= $ov_obj qr/Key/i TODO
85af77a5 163=! $ov_obj qr/foo/
61a621c6 164= $ov_obj "key" TODO
85af77a5 165=! $ov_obj "foo"
166=! $ov_obj FALSE
0cfbf1ea 167=! $ov_obj TRUE
1cfb7049 168
169# regular object
85af77a5 170=@ $obj $ov_obj
0cfbf1ea 171@ $obj $obj
85af77a5 172=@ $obj \&fatal
173=@ $obj \&FALSE
174=@ $obj \&foo
175=@ $obj sub { 1 }
176=@ $obj sub { 0 }
177=@ $obj %keyandmore
178=@ $obj {"key" => 1}
179=@ $obj @fooormore
180=@ $obj ["key" => 1]
181=@ $obj /key/
182=@ $obj qr/key/
183=@ $obj "key"
184=@ $obj FALSE
1cfb7049 185
a4a197da 186# ~~ Coderef
187 sub{0} sub { ref $_[0] eq "CODE" }
188 %fooormore sub { $_[0] =~ /^(foo|or|more)$/ }
189! %fooormore sub { $_[0] =~ /^(foo|or|less)$/ }
190 \%fooormore sub { $_[0] =~ /^(foo|or|more)$/ }
191! \%fooormore sub { $_[0] =~ /^(foo|or|less)$/ }
192 +{%fooormore} sub { $_[0] =~ /^(foo|or|more)$/ }
193! +{%fooormore} sub { $_[0] =~ /^(foo|or|less)$/ }
194 @fooormore sub { $_[0] =~ /^(foo|or|more)$/ }
195! @fooormore sub { $_[0] =~ /^(foo|or|less)$/ }
196 \@fooormore sub { $_[0] =~ /^(foo|or|more)$/ }
197! \@fooormore sub { $_[0] =~ /^(foo|or|less)$/ }
198 [@fooormore] sub { $_[0] =~ /^(foo|or|more)$/ }
199! [@fooormore] sub { $_[0] =~ /^(foo|or|less)$/ }
200 %fooormore sub{@_==1}
201 @fooormore sub{@_==1}
202 "foo" sub { $_[0] =~ /^(foo|or|more)$/ }
203! "more" sub { $_[0] =~ /^(foo|or|less)$/ }
73aec0b1 204 /fooormore/ sub{ref $_[0] eq 'Regexp'}
a4a197da 205 qr/fooormore/ sub{ref $_[0] eq 'Regexp'}
206 1 sub{shift}
207! 0 sub{shift}
208! undef sub{shift}
209 undef sub{not shift}
210 FALSE sub{not shift}
211 [1] \&bar
212 {a=>1} \&bar
213 qr// \&bar
214! [1] \&foo
215! {a=>1} \&foo
216# empty stuff matches, because the sub is never called:
168ff818 217! [] \&foo
218! {} \&foo
a4a197da 219! qr// \&foo
220! undef \&foo
221 undef \&bar
222@ undef \&fatal
223@ 1 \&fatal
224@ [1] \&fatal
203d1e89 225@ {a=>1} \&fatal
a4a197da 226@ "foo" \&fatal
227@ qr// \&fatal
203d1e89 228# sub is not called on empty hashes / arrays
168ff818 229! [] \&fatal
230! +{} \&fatal
0d863452 231
0d863452 232# HASH ref against:
233# - another hash ref
234 {} {}
235! {} {1 => 2}
236 {1 => 2} {1 => 2}
237 {1 => 2} {1 => 3}
238! {1 => 2} {2 => 3}
239 \%main:: {map {$_ => 'x'} keys %main::}
240
241# - tied hash ref
242 \%hash \%tied_hash
243 \%tied_hash \%tied_hash
244
245# - an array ref
2e0e16c9 246 [keys %main::] \%::
247! [] \%::
248 [undef] {"" => 1}
249 ["foo"] { foo => 1 }
250 ["foo", "bar"] { foo => 1 }
251 ["foo", "bar"] \%hash
252 ["foo"] \%hash
253! ["quux"] \%hash
254 [qw(foo quux)] \%hash
0d863452 255
256# - a regex
2e0e16c9 257 qr/^(fo[ox])$/ {foo => 1}
258! qr/[13579]$/ +{0..99}
0d863452 259
260# - a string
2e0e16c9 261 "foo" +{foo => 1, bar => 2}
262! "baz" +{foo => 1, bar => 2}
0d863452 263
61a621c6 264# - undef
265! undef %hash
266! undef +{"" => "empty key"}
0d863452 267
268# ARRAY ref against:
269# - another array ref
1cfb7049 270 [] []
271! [] [1]
0d863452 272 [["foo"], ["bar"]] [qr/o/, qr/a/]
273 ["foo", "bar"] [qr/o/, qr/a/]
71b0fb34 274! ["foo", "bar"] [qr/o/, "foo"]
1cfb7049 275 $deep1 $deep1
276! $deep1 $deep2
0d863452 277
1cfb7049 278 \@nums \@tied_nums
0d863452 279
280# - a regex
281 [qw(foo bar baz quux)] qr/x/
282! [qw(foo bar baz quux)] qr/y/
283
284# - a number
285 [qw(1foo 2bar)] 2
25a0c96d 286 [qw(foo 2)] 2
287 [qw(foo 2)] 2.0_0e+0
288! [qw(1foo bar2)] 2
0d863452 289
290# - a string
291! [qw(1foo 2bar)] "2"
25a0c96d 292 [qw(1foo 2bar)] "2bar"
0d863452 293
294# Number against number
295 2 2
296! 2 3
18d11902 297 0 FALSE
298 3-2 TRUE
0d863452 299
300# Number against string
301 2 "2"
302 2 "2.0"
303! 2 "2bananas"
304! 2_3 "2_3"
18d11902 305 FALSE "0"
0d863452 306
307# Regex against string
308 qr/x/ "x"
309! qr/y/ "x"
310
311# Regex against number
312 12345 qr/3/
313
314
315# Test the implicit referencing
316 @nums 7
317 @nums \@nums
318! @nums \\@nums
319 @nums [1..10]
320! @nums [0..9]
321
2e0e16c9 322 "foo" %hash
323 /bar/ %hash
324 [qw(bar)] %hash
325! [qw(a b c)] %hash
71b0fb34 326 %hash %hash
fceebc47 327 %hash +{%hash}
73aec0b1 328 %hash \%hash
71b0fb34 329 %hash %tied_hash
330 %tied_hash %tied_hash
331 %hash { foo => 5, bar => 10 }
332! %hash { foo => 5, bar => 10, quux => 15 }
333
334 @nums { 1, '', 2, '' }
335 @nums { 1, '', 12, '' }
336! @nums { 11, '', 12, '' }