Make C<undef ~~ 0> and C<undef ~~ ""> not match (like in 5.10.0)
[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;
289d21b2 9use warnings;
10no warnings 'uninitialized';
0d863452 11
12use Tie::Array;
13use Tie::Hash;
b15feb55 14use Tie::RefHash;
0d863452 15
0d863452 16# Predeclare vars used in the tests:
031a44ed 17my @empty;
18my %empty;
015eb7b9 19my @sparse; $sparse[2] = 2;
031a44ed 20
0d863452 21my $deep1 = []; push @$deep1, \$deep1;
22my $deep2 = []; push @$deep2, \$deep2;
23
0d863452 24my @nums = (1..10);
25tie my @tied_nums, 'Tie::StdArray';
26@tied_nums = (1..10);
27
28my %hash = (foo => 17, bar => 23);
29tie my %tied_hash, 'Tie::StdHash';
30%tied_hash = %hash;
31
1cfb7049 32{
33 package Test::Object::NoOverload;
34 sub new { bless { key => 1 } }
35}
36
37{
6fbc735b 38 package Test::Object::StringOverload;
39 use overload '""' => sub { "object" }, fallback => 1;
40 sub new { bless { key => 1 } }
41}
42
43{
90a32bcb 44 package Test::Object::WithOverload;
6fbc735b 45 sub new { bless { key => ($_[1] // 'magic') } }
2c9d2554 46 use overload '~~' => sub {
47 my %hash = %{ $_[0] };
48 if ($_[2]) { # arguments reversed ?
49 return $_[1] eq reverse $hash{key};
50 }
51 else {
52 return $_[1] eq $hash{key};
53 }
54 };
0483c672 55 use overload '""' => sub { "stringified" };
90a32bcb 56 use overload 'eq' => sub {"$_[0]" eq "$_[1]"};
1cfb7049 57}
58
90a32bcb 59our $ov_obj = Test::Object::WithOverload->new;
6fbc735b 60our $ov_obj_2 = Test::Object::WithOverload->new("object");
1cfb7049 61our $obj = Test::Object::NoOverload->new;
6fbc735b 62our $str_obj = Test::Object::StringOverload->new;
1cfb7049 63
b15feb55 64tie my %refh, 'Tie::RefHash';
65$refh{$ov_obj} = 1;
66
73aec0b1 67my @keyandmore = qw(key and more);
68my @fooormore = qw(foo or more);
69my %keyandmore = map { $_ => 0 } @keyandmore;
70my %fooormore = map { $_ => 0 } @fooormore;
71
0d863452 72# Load and run the tests
fb51372e 73plan tests => 322;
0d863452 74
9e079ace 75while (<DATA>) {
76 next if /^#/ || !/\S/;
77 chomp;
73aec0b1 78 my ($yn, $left, $right, $note) = split /\t+/;
0d863452 79
73aec0b1 80 local $::TODO = $note =~ /TODO/;
0d863452 81
85af77a5 82 die "Bad test spec: ($yn, $left, $right)" if $yn =~ /[^!@=]/;
9e079ace 83
0d863452 84 my $tstr = "$left ~~ $right";
9e079ace 85
85af77a5 86 test_again:
289d21b2 87 my $res;
88 if ($note =~ /NOWARNINGS/) {
89 $res = eval "no warnings; $tstr";
90 }
91 else {
92 $res = eval $tstr;
93 }
0d863452 94
a86f5011 95 chomp $@;
96
85af77a5 97 if ( $yn =~ /@/ ) {
9e079ace 98 ok( $@ ne '', "$tstr dies" )
99 and print "# \$\@ was: $@\n";
a86f5011 100 } else {
85af77a5 101 my $test_name = $tstr . ($yn =~ /!/ ? " does not match" : " matches");
a86f5011 102 if ( $@ ne '' ) {
9e079ace 103 fail($test_name);
104 print "# \$\@ was: $@\n";
a86f5011 105 } else {
85af77a5 106 ok( ($yn =~ /!/ xor $res), $test_name );
a86f5011 107 }
108 }
85af77a5 109
110 if ( $yn =~ s/=// ) {
111 $tstr = "$right ~~ $left";
112 goto test_again;
113 }
0d863452 114}
115
0d863452 116sub foo {}
73aec0b1 117sub bar {42}
118sub gorch {42}
1cfb7049 119sub fatal {die "fatal sub\n"}
0d863452 120
0cfbf1ea 121# to test constant folding
18d11902 122sub FALSE() { 0 }
123sub TRUE() { 1 }
2522c35a 124sub NOT_DEF() { undef }
0d863452 125
e5de85fa 126# Prefix character :
127# - expected to match
128# ! - expected to not match
129# @ - expected to be a compilation failure
85af77a5 130# = - expected to match symmetrically (runs test twice)
73aec0b1 131# Data types to test :
85af77a5 132# undef
73aec0b1 133# Object-overloaded
134# Object
73aec0b1 135# Coderef
136# Hash
137# Hashref
138# Array
139# Arrayref
85af77a5 140# Tied arrays and hashes
141# Arrays that reference themselves
73aec0b1 142# Regex (// and qr//)
85af77a5 143# Range
73aec0b1 144# Num
145# Str
85af77a5 146# Other syntactic items of interest:
147# Constants
148# Values returned by a sub call
0d863452 149__DATA__
85af77a5 150# Any ~~ undef
ad0781bc 151! $ov_obj undef
85af77a5 152! $obj undef
153! sub {} undef
154! %hash undef
155! \%hash undef
156! {} undef
157! @nums undef
158! \@nums undef
159! [] undef
160! %tied_hash undef
161! @tied_nums undef
162! $deep1 undef
163! /foo/ undef
164! qr/foo/ undef
165! 21..30 undef
166! 189 undef
167! "foo" undef
168! "" undef
169! !1 undef
170 undef undef
62ec5f58 171 (my $u) undef
2522c35a 172 NOT_DEF undef
173 &NOT_DEF undef
85af77a5 174
175# Any ~~ object overloaded
ad0781bc 176! \&fatal $ov_obj
2c9d2554 177 'cigam' $ov_obj
178! 'cigam on' $ov_obj
532217f1 179! ['cigam'] $ov_obj
180! ['stringified'] $ov_obj
181! { cigam => 1 } $ov_obj
182! { stringified => 1 } $ov_obj
ad0781bc 183! $obj $ov_obj
184! undef $ov_obj
1cfb7049 185
186# regular object
ad0781bc 187@ $obj $obj
6d743019 188@ $ov_obj $obj
2c9d2554 189=@ \&fatal $obj
ad0781bc 190@ \&FALSE $obj
191@ \&foo $obj
192@ sub { 1 } $obj
193@ sub { 0 } $obj
194@ %keyandmore $obj
195@ {"key" => 1} $obj
196@ @fooormore $obj
197@ ["key" => 1] $obj
198@ /key/ $obj
199@ qr/key/ $obj
200@ "key" $obj
201@ FALSE $obj
202
6fbc735b 203# regular object with "" overload
204@ $obj $str_obj
205=@ \&fatal $str_obj
206@ \&FALSE $str_obj
207@ \&foo $str_obj
208@ sub { 1 } $str_obj
209@ sub { 0 } $str_obj
210@ %keyandmore $str_obj
211@ {"object" => 1} $str_obj
212@ @fooormore $str_obj
213@ ["object" => 1] $str_obj
214@ /object/ $str_obj
215@ qr/object/ $str_obj
216@ "object" $str_obj
217@ FALSE $str_obj
218# Those will treat the $str_obj as a string because of fallback:
219! $ov_obj $str_obj
220 $ov_obj_2 $str_obj
221
ad0781bc 222# object (overloaded or not) ~~ Any
0483c672 223 $obj qr/NoOverload/
224 $ov_obj qr/^stringified$/
532217f1 225= "$ov_obj" "stringified"
6fbc735b 226= "$str_obj" "object"
532217f1 227!= $ov_obj "stringified"
6fbc735b 228 $str_obj "object"
2c9d2554 229 $ov_obj 'magic'
230! $ov_obj 'not magic'
1cfb7049 231
a4a197da 232# ~~ Coderef
233 sub{0} sub { ref $_[0] eq "CODE" }
234 %fooormore sub { $_[0] =~ /^(foo|or|more)$/ }
235! %fooormore sub { $_[0] =~ /^(foo|or|less)$/ }
236 \%fooormore sub { $_[0] =~ /^(foo|or|more)$/ }
237! \%fooormore sub { $_[0] =~ /^(foo|or|less)$/ }
238 +{%fooormore} sub { $_[0] =~ /^(foo|or|more)$/ }
239! +{%fooormore} sub { $_[0] =~ /^(foo|or|less)$/ }
240 @fooormore sub { $_[0] =~ /^(foo|or|more)$/ }
241! @fooormore sub { $_[0] =~ /^(foo|or|less)$/ }
242 \@fooormore sub { $_[0] =~ /^(foo|or|more)$/ }
243! \@fooormore sub { $_[0] =~ /^(foo|or|less)$/ }
244 [@fooormore] sub { $_[0] =~ /^(foo|or|more)$/ }
245! [@fooormore] sub { $_[0] =~ /^(foo|or|less)$/ }
246 %fooormore sub{@_==1}
247 @fooormore sub{@_==1}
248 "foo" sub { $_[0] =~ /^(foo|or|more)$/ }
249! "more" sub { $_[0] =~ /^(foo|or|less)$/ }
73aec0b1 250 /fooormore/ sub{ref $_[0] eq 'Regexp'}
a4a197da 251 qr/fooormore/ sub{ref $_[0] eq 'Regexp'}
252 1 sub{shift}
253! 0 sub{shift}
254! undef sub{shift}
255 undef sub{not shift}
031a44ed 256 NOT_DEF sub{not shift}
257 &NOT_DEF sub{not shift}
a4a197da 258 FALSE sub{not shift}
259 [1] \&bar
260 {a=>1} \&bar
261 qr// \&bar
262! [1] \&foo
263! {a=>1} \&foo
41e726ac 264 $obj sub { ref($_[0]) =~ /NoOverload/ }
90a32bcb 265 $ov_obj sub { ref($_[0]) =~ /WithOverload/ }
a4a197da 266# empty stuff matches, because the sub is never called:
07edf497 267 [] \&foo
268 {} \&foo
031a44ed 269 @empty \&foo
270 %empty \&foo
a4a197da 271! qr// \&foo
272! undef \&foo
273 undef \&bar
274@ undef \&fatal
275@ 1 \&fatal
276@ [1] \&fatal
203d1e89 277@ {a=>1} \&fatal
a4a197da 278@ "foo" \&fatal
279@ qr// \&fatal
203d1e89 280# sub is not called on empty hashes / arrays
07edf497 281 [] \&fatal
282 +{} \&fatal
031a44ed 283 @empty \&fatal
284 %empty \&fatal
532217f1 285# sub is not special on the left
286 sub {0} qr/^CODE/
287 sub {0} sub { ref shift eq "CODE" }
0d863452 288
0d863452 289# HASH ref against:
290# - another hash ref
291 {} {}
2a37c5e7 292=! {} {1 => 2}
0d863452 293 {1 => 2} {1 => 2}
294 {1 => 2} {1 => 3}
031a44ed 295=! {1 => 2} {2 => 3}
296= \%main:: {map {$_ => 'x'} keys %main::}
0d863452 297
298# - tied hash ref
2522c35a 299= \%hash \%tied_hash
0d863452 300 \%tied_hash \%tied_hash
031a44ed 301!= {"a"=>"b"} \%tied_hash
302= %hash %tied_hash
303 %tied_hash %tied_hash
304!= {"a"=>"b"} %tied_hash
b15feb55 305 $ov_obj %refh
306! "$ov_obj" %refh
307 [$ov_obj] %refh
308! ["$ov_obj"] %refh
309 %refh %refh
0d863452 310
311# - an array ref
031a44ed 312# (since this is symmetrical, tests as well hash~~array)
313= [keys %main::] \%::
314= [qw[STDIN STDOUT]] \%::
315=! [] \%::
316=! [""] {}
317=! [] {}
318=! @empty {}
319= [undef] {"" => 1}
320= [""] {"" => 1}
321= ["foo"] { foo => 1 }
322= ["foo", "bar"] { foo => 1 }
323= ["foo", "bar"] \%hash
324= ["foo"] \%hash
325=! ["quux"] \%hash
326= [qw(foo quux)] \%hash
327= @fooormore { foo => 1, or => 2, more => 3 }
328= @fooormore %fooormore
329= @fooormore \%fooormore
330= \@fooormore %fooormore
0d863452 331
332# - a regex
ea0c2dbd 333= qr/^(fo[ox])$/ {foo => 1}
334= /^(fo[ox])$/ %fooormore
031a44ed 335=! qr/[13579]$/ +{0..99}
ea0c2dbd 336=! qr/a*/ {}
031a44ed 337= qr/a*/ {b=>2}
ea0c2dbd 338= qr/B/i {b=>2}
339= /B/i {b=>2}
340=! qr/a+/ {b=>2}
341= qr/^à/ {"à"=>2}
0d863452 342
031a44ed 343# - a scalar
2e0e16c9 344 "foo" +{foo => 1, bar => 2}
031a44ed 345 "foo" %fooormore
2e0e16c9 346! "baz" +{foo => 1, bar => 2}
031a44ed 347! "boz" %fooormore
348! 1 +{foo => 1, bar => 2}
349! 1 %fooormore
350 1 { 1 => 3 }
351 1.0 { 1 => 3 }
352! "1.0" { 1 => 3 }
353! "1.0" { 1.0 => 3 }
354 "1.0" { "1.0" => 3 }
355 "à" { "à" => "À" }
0d863452 356
61a621c6 357# - undef
2522c35a 358! undef { hop => 'zouu' }
61a621c6 359! undef %hash
360! undef +{"" => "empty key"}
2a37c5e7 361! undef {}
0d863452 362
363# ARRAY ref against:
364# - another array ref
1cfb7049 365 [] []
2522c35a 366=! [] [1]
ea0c2dbd 367 [["foo"], ["bar"]] [qr/o/, qr/a/]
368! [["foo"], ["bar"]] [qr/ARRAY/, qr/ARRAY/]
0d863452 369 ["foo", "bar"] [qr/o/, qr/a/]
031a44ed 370! [qr/o/, qr/a/] ["foo", "bar"]
2522c35a 371 ["foo", "bar"] [["foo"], ["bar"]]
71b0fb34 372! ["foo", "bar"] [qr/o/, "foo"]
2522c35a 373 ["foo", undef, "bar"] [qr/o/, undef, "bar"]
fb51372e 374! ["foo", undef, "bar"] [qr/o/, "", "bar"]
2522c35a 375! ["foo", "", "bar"] [qr/o/, undef, "bar"]
1cfb7049 376 $deep1 $deep1
031a44ed 377 @$deep1 @$deep1
1cfb7049 378! $deep1 $deep2
0d863452 379
031a44ed 380= \@nums \@tied_nums
381= @nums \@tied_nums
382= \@nums @tied_nums
383= @nums @tied_nums
384
d0b243e3 385# - an object
386! $obj @fooormore
41e726ac 387 $obj [sub{ref shift}]
d0b243e3 388
0d863452 389# - a regex
ea0c2dbd 390= qr/x/ [qw(foo bar baz quux)]
391=! qr/y/ [qw(foo bar baz quux)]
392= /x/ [qw(foo bar baz quux)]
393=! /y/ [qw(foo bar baz quux)]
394= /FOO/i @fooormore
395=! /bar/ @fooormore
0d863452 396
397# - a number
015eb7b9 398 2 [qw(1.00 2.00)]
b0138e99 399 2 [qw(foo 2)]
400 2.0_0e+0 [qw(foo 2)]
401! 2 [qw(1foo bar2)]
0d863452 402
403# - a string
b0138e99 404! "2" [qw(1foo 2bar)]
405 "2bar" [qw(1foo 2bar)]
0d863452 406
015eb7b9 407# - undef
408 undef [1, 2, undef, 4]
409! undef [1, 2, [undef], 4]
410! undef @fooormore
411 undef @sparse
fb51372e 412 undef [undef]
413! 0 [undef]
414! "" [undef]
415! undef [0]
416! undef [""]
015eb7b9 417
418# - nested arrays and ~~ distributivity
419 11 [[11]]
420! 11 [[12]]
421 "foo" [{foo => "bar"}]
422! "bar" [{foo => "bar"}]
423
0d863452 424# Number against number
425 2 2
33ed63a2 426 20 2_0
0d863452 427! 2 3
18d11902 428 0 FALSE
429 3-2 TRUE
fb51372e 430! undef 0
431! (my $u) 0
0d863452 432
433# Number against string
33ed63a2 434= 2 "2"
435= 2 "2.0"
0d863452 436! 2 "2bananas"
289d21b2 437!= 2_3 "2_3" NOWARNINGS
18d11902 438 FALSE "0"
fb51372e 439! undef "0"
440! undef ""
0d863452 441
442# Regex against string
a566f585 443 "x" qr/x/
444! "x" qr/y/
0d863452 445
446# Regex against number
447 12345 qr/3/
2522c35a 448! 12345 qr/7/
0d863452 449
031a44ed 450# array/hash against string
d444f7e3 451 @fooormore "".\@fooormore
452! @keyandmore "".\@fooormore
453 %fooormore "".\%fooormore
454! %keyandmore "".\%fooormore
f1bef09e 455
0d863452 456# Test the implicit referencing
b0138e99 457 7 @nums
0d863452 458 @nums \@nums
459! @nums \\@nums
460 @nums [1..10]
461! @nums [0..9]
462
2e0e16c9 463 "foo" %hash
464 /bar/ %hash
465 [qw(bar)] %hash
466! [qw(a b c)] %hash
71b0fb34 467 %hash %hash
fceebc47 468 %hash +{%hash}
73aec0b1 469 %hash \%hash
71b0fb34 470 %hash %tied_hash
471 %tied_hash %tied_hash
472 %hash { foo => 5, bar => 10 }
473! %hash { foo => 5, bar => 10, quux => 15 }
474
475 @nums { 1, '', 2, '' }
476 @nums { 1, '', 12, '' }
477! @nums { 11, '', 12, '' }