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