Make ~~ qr// non-commutative
[p5sagit/p5-mst-13.2.git] / t / op / smartmatch.t
1 #!./perl
2
3 BEGIN {
4     chdir 't';
5     @INC = '../lib';
6     require './test.pl';
7 }
8 use strict;
9
10 use Tie::Array;
11 use Tie::Hash;
12
13 # Predeclare vars used in the tests:
14 my $deep1 = []; push @$deep1, \$deep1;
15 my $deep2 = []; push @$deep2, \$deep2;
16
17 my @nums = (1..10);
18 tie my @tied_nums, 'Tie::StdArray';
19 @tied_nums =  (1..10);
20
21 my %hash = (foo => 17, bar => 23);
22 tie my %tied_hash, 'Tie::StdHash';
23 %tied_hash = %hash;
24
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 our $ov_obj = Test::Object::CopyOverload->new;
37 our $obj = Test::Object::NoOverload->new;
38
39 my @keyandmore = qw(key and more);
40 my @fooormore = qw(foo or more);
41 my %keyandmore = map { $_ => 0 } @keyandmore;
42 my %fooormore = map { $_ => 0 } @fooormore;
43
44 # Load and run the tests
45 plan "no_plan";
46
47 while (<DATA>) {
48     next if /^#/ || !/\S/;
49     chomp;
50     my ($yn, $left, $right, $note) = split /\t+/;
51
52     local $::TODO = $note =~ /TODO/;
53
54     die "Bad test spec: ($yn, $left, $right)" if $yn =~ /[^!@=]/;
55
56     my $tstr = "$left ~~ $right";
57
58     test_again:
59     my $res = eval $tstr;
60
61     chomp $@;
62
63     if ( $yn =~ /@/ ) {
64         ok( $@ ne '', "$tstr dies" )
65             and print "# \$\@ was: $@\n";
66     } else {
67         my $test_name = $tstr . ($yn =~ /!/ ? " does not match" : " matches");
68         if ( $@ ne '' ) {
69             fail($test_name);
70             print "# \$\@ was: $@\n";
71         } else {
72             ok( ($yn =~ /!/ xor $res), $test_name );
73         }
74     }
75
76     if ( $yn =~ s/=// ) {
77         $tstr = "$right ~~ $left";
78         goto test_again;
79     }
80 }
81
82
83
84 sub foo {}
85 sub bar {42}
86 sub gorch {42}
87 sub fatal {die "fatal sub\n"}
88
89 # to test constant folding
90 sub FALSE() { 0 }
91 sub TRUE() { 1 }
92
93 # Prefix character :
94 #   - expected to match
95 # ! - expected to not match
96 # @ - expected to be a compilation failure
97 # = - expected to match symmetrically (runs test twice)
98 # Data types to test :
99 #   undef
100 #   Object-overloaded
101 #   Object
102 #   Coderef
103 #   Hash
104 #   Hashref
105 #   Array
106 #   Arrayref
107 #   Tied arrays and hashes
108 #   Arrays that reference themselves
109 #   Regex (// and qr//)
110 #   Range
111 #   Num
112 #   Str
113 # Other syntactic items of interest:
114 #   Constants
115 #   Values returned by a sub call
116 __DATA__
117 # Any ~~ undef
118 !       $ov_obj         undef
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
138         (my $u)         undef
139
140 # Any ~~ object overloaded
141 # object overloaded ~~ Any
142         $ov_obj         $ov_obj
143 =@      $ov_obj         \&fatal
144 =!      $ov_obj         \&FALSE
145 =       $ov_obj         \&TRUE
146 =!      $ov_obj         \&foo
147 =       $ov_obj         \&bar
148 =       $ov_obj         sub { shift ~~ "key" }
149 =!      $ov_obj         sub { shift ne "key" }
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}
156 =       $ov_obj         @keyandmore
157 =!      $ov_obj         @fooormore
158 =       $ov_obj         ["key" => 1]
159 =!      $ov_obj         ["foo" => 1]
160 =       $ov_obj         /key/                           TODO
161 =!      $ov_obj         /foo/
162 =       $ov_obj         qr/Key/i                        TODO
163 =!      $ov_obj         qr/foo/
164 =       $ov_obj         "key"                           TODO
165 =!      $ov_obj         "foo"
166 =!      $ov_obj         FALSE
167 =!      $ov_obj         TRUE
168
169 # regular object
170 =@      $obj    $ov_obj
171 @       $obj    $obj
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
185
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)$/ }
204         /fooormore/     sub{ref $_[0] eq 'Regexp'}
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:
217 !       []              \&foo
218 !       {}              \&foo
219 !       qr//            \&foo
220 !       undef           \&foo
221         undef           \&bar
222 @       undef           \&fatal
223 @       1               \&fatal
224 @       [1]             \&fatal
225 @       {a=>1}          \&fatal
226 @       "foo"           \&fatal
227 @       qr//            \&fatal
228 # sub is not called on empty hashes / arrays
229 !       []              \&fatal
230 !       +{}             \&fatal
231
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
246         [keys %main::]  \%::
247 !       []              \%::
248 !       [""]            {}
249 !       []              {}
250         [undef]         {"" => 1}
251         [""]            {"" => 1}
252         ["foo"]         { foo => 1 }
253         ["foo", "bar"]  { foo => 1 }
254         ["foo", "bar"]  \%hash
255         ["foo"]         \%hash
256 !       ["quux"]        \%hash
257         [qw(foo quux)]  \%hash
258
259 #  - a regex
260         qr/^(fo[ox])$/          {foo => 1}
261 !       qr/[13579]$/            +{0..99}
262 !       qr/a*/                  {}
263         qr/a*/                  {b=>2}
264
265 #  - a string
266         "foo"           +{foo => 1, bar => 2}
267 !       "baz"           +{foo => 1, bar => 2}
268
269 #  - undef
270 !       undef           %hash
271 !       undef           +{"" => "empty key"}
272 !       undef           {}
273
274 # ARRAY ref against:
275 #  - another array ref
276         []                      []
277 !       []                      [1]
278 !       [["foo"], ["bar"]]      [qr/o/, qr/a/]
279         [["foo"], ["bar"]]      [qr/ARRAY/, qr/ARRAY/]
280         ["foo", "bar"]          [qr/o/, qr/a/]
281 !       ["foo", "bar"]          [qr/o/, "foo"]
282         $deep1                  $deep1
283 !       $deep1                  $deep2
284
285         \@nums                  \@tied_nums
286
287 #  - a regex
288         qr/x/           [qw(foo bar baz quux)]
289 !       qr/y/           [qw(foo bar baz quux)]
290         /x/             [qw(foo bar baz quux)]
291 !       /y/             [qw(foo bar baz quux)]
292
293 # - a number
294         2               [qw(1foo 2bar)]
295         2               [qw(foo 2)]
296         2.0_0e+0        [qw(foo 2)]
297 !       2               [qw(1foo bar2)]
298
299 # - a string
300 !       "2"             [qw(1foo 2bar)]
301         "2bar"          [qw(1foo 2bar)]
302
303 # Number against number
304         2               2
305 !       2               3
306         0               FALSE
307         3-2             TRUE
308
309 # Number against string
310         2               "2"
311         2               "2.0"
312 !       2               "2bananas"
313 !       2_3             "2_3"
314         FALSE           "0"
315
316 # Regex against string
317         "x"             qr/x/
318 !       "x"             qr/y/
319
320 # Regex against number
321         12345           qr/3/
322
323 # Test the implicit referencing
324         7               @nums
325         @nums           \@nums
326 !       @nums           \\@nums
327         @nums           [1..10]
328 !       @nums           [0..9]
329
330         "foo"           %hash
331         /bar/           %hash
332         [qw(bar)]       %hash
333 !       [qw(a b c)]     %hash
334         %hash           %hash
335         %hash           +{%hash}
336         %hash           \%hash
337         %hash           %tied_hash
338         %tied_hash      %tied_hash
339         %hash           { foo => 5, bar => 10 }
340 !       %hash           { foo => 5, bar => 10, quux => 15 }
341
342         @nums           {  1, '',  2, '' }
343         @nums           {  1, '', 12, '' }
344 !       @nums           { 11, '', 12, '' }