6993c2e732cc22898d5a6b018aede75f2730fba0
[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] }; $_[1] ~~ %hash };
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 sub foo {}
83 sub bar {42}
84 sub gorch {42}
85 sub fatal {die "fatal sub\n"}
86
87 # to test constant folding
88 sub FALSE() { 0 }
89 sub TRUE() { 1 }
90
91 # Prefix character :
92 #   - expected to match
93 # ! - expected to not match
94 # @ - expected to be a compilation failure
95 # = - expected to match symmetrically (runs test twice)
96 # Data types to test :
97 #   undef
98 #   Object-overloaded
99 #   Object
100 #   Coderef
101 #   Hash
102 #   Hashref
103 #   Array
104 #   Arrayref
105 #   Tied arrays and hashes
106 #   Arrays that reference themselves
107 #   Regex (// and qr//)
108 #   Range
109 #   Num
110 #   Str
111 # Other syntactic items of interest:
112 #   Constants
113 #   Values returned by a sub call
114 __DATA__
115 # Any ~~ undef
116 !=      $ov_obj         undef
117 !       $obj            undef
118 !       sub {}          undef
119 !       %hash           undef
120 !       \%hash          undef
121 !       {}              undef
122 !       @nums           undef
123 !       \@nums          undef
124 !       []              undef
125 !       %tied_hash      undef
126 !       @tied_nums      undef
127 !       $deep1          undef
128 !       /foo/           undef
129 !       qr/foo/         undef
130 !       21..30          undef
131 !       189             undef
132 !       "foo"           undef
133 !       ""              undef
134 !       !1              undef
135         undef           undef
136         (my $u)         undef
137
138 # Any ~~ object overloaded
139 # object overloaded ~~ Any
140         $ov_obj         $ov_obj
141 =!      $ov_obj         \&fatal
142 =       $ov_obj         {"key" => 2}
143 =!      $ov_obj         {"key" => 1, bar => 2}
144 =       $ov_obj         /key/
145 =!      $ov_obj         /bar/
146
147 # regular object
148 =@      $obj    $ov_obj
149 @       $obj    $obj
150 =@      $obj    \&fatal
151 =@      $obj    \&FALSE
152 =@      $obj    \&foo
153 =@      $obj    sub { 1 }
154 =@      $obj    sub { 0 }
155 =@      $obj    %keyandmore
156 =@      $obj    {"key" => 1}
157 =@      $obj    @fooormore
158 =@      $obj    ["key" => 1]
159 =@      $obj    /key/
160 =@      $obj    qr/key/
161 =@      $obj    "key"
162 =@      $obj    FALSE
163
164 # ~~ Coderef
165         sub{0}          sub { ref $_[0] eq "CODE" }
166         %fooormore      sub { $_[0] =~ /^(foo|or|more)$/ }
167 !       %fooormore      sub { $_[0] =~ /^(foo|or|less)$/ }
168         \%fooormore     sub { $_[0] =~ /^(foo|or|more)$/ }
169 !       \%fooormore     sub { $_[0] =~ /^(foo|or|less)$/ }
170         +{%fooormore}   sub { $_[0] =~ /^(foo|or|more)$/ }
171 !       +{%fooormore}   sub { $_[0] =~ /^(foo|or|less)$/ }
172         @fooormore      sub { $_[0] =~ /^(foo|or|more)$/ }
173 !       @fooormore      sub { $_[0] =~ /^(foo|or|less)$/ }
174         \@fooormore     sub { $_[0] =~ /^(foo|or|more)$/ }
175 !       \@fooormore     sub { $_[0] =~ /^(foo|or|less)$/ }
176         [@fooormore]    sub { $_[0] =~ /^(foo|or|more)$/ }
177 !       [@fooormore]    sub { $_[0] =~ /^(foo|or|less)$/ }
178         %fooormore      sub{@_==1}
179         @fooormore      sub{@_==1}
180         "foo"           sub { $_[0] =~ /^(foo|or|more)$/ }
181 !       "more"          sub { $_[0] =~ /^(foo|or|less)$/ }
182         /fooormore/     sub{ref $_[0] eq 'Regexp'}
183         qr/fooormore/   sub{ref $_[0] eq 'Regexp'}
184         1               sub{shift}
185 !       0               sub{shift}
186 !       undef           sub{shift}
187         undef           sub{not shift}
188         FALSE           sub{not shift}
189         [1]             \&bar
190         {a=>1}          \&bar
191         qr//            \&bar
192 !       [1]             \&foo
193 !       {a=>1}          \&foo
194 # empty stuff matches, because the sub is never called:
195         []              \&foo
196         {}              \&foo
197 !       qr//            \&foo
198 !       undef           \&foo
199         undef           \&bar
200 @       undef           \&fatal
201 @       1               \&fatal
202 @       [1]             \&fatal
203 @       {a=>1}          \&fatal
204 @       "foo"           \&fatal
205 @       qr//            \&fatal
206 # sub is not called on empty hashes / arrays
207         []              \&fatal
208         +{}             \&fatal
209
210 # HASH ref against:
211 #   - another hash ref
212         {}              {}
213 =!      {}              {1 => 2}
214         {1 => 2}        {1 => 2}
215         {1 => 2}        {1 => 3}
216 !       {1 => 2}        {2 => 3}
217         \%main::        {map {$_ => 'x'} keys %main::}
218
219 #  - tied hash ref
220         \%hash          \%tied_hash
221         \%tied_hash     \%tied_hash
222
223 #  - an array ref
224         [keys %main::]  \%::
225 !       []              \%::
226 !       [""]            {}
227 !       []              {}
228         [undef]         {"" => 1}
229         [""]            {"" => 1}
230         ["foo"]         { foo => 1 }
231         ["foo", "bar"]  { foo => 1 }
232         ["foo", "bar"]  \%hash
233         ["foo"]         \%hash
234 !       ["quux"]        \%hash
235         [qw(foo quux)]  \%hash
236
237 #  - a regex
238         qr/^(fo[ox])$/          {foo => 1}
239 !       qr/[13579]$/            +{0..99}
240 !       qr/a*/                  {}
241         qr/a*/                  {b=>2}
242
243 #  - a string
244         "foo"           +{foo => 1, bar => 2}
245 !       "baz"           +{foo => 1, bar => 2}
246
247 #  - undef
248 !       undef           %hash
249 !       undef           +{"" => "empty key"}
250 !       undef           {}
251
252 # ARRAY ref against:
253 #  - another array ref
254         []                      []
255 !       []                      [1]
256 !       [["foo"], ["bar"]]      [qr/o/, qr/a/]
257         [["foo"], ["bar"]]      [qr/ARRAY/, qr/ARRAY/]
258         ["foo", "bar"]          [qr/o/, qr/a/]
259 !       ["foo", "bar"]          [qr/o/, "foo"]
260         $deep1                  $deep1
261 !       $deep1                  $deep2
262
263         \@nums                  \@tied_nums
264
265 #  - a regex
266         qr/x/           [qw(foo bar baz quux)]
267 !       qr/y/           [qw(foo bar baz quux)]
268         /x/             [qw(foo bar baz quux)]
269 !       /y/             [qw(foo bar baz quux)]
270
271 # - a number
272         2               [qw(1foo 2bar)]
273         2               [qw(foo 2)]
274         2.0_0e+0        [qw(foo 2)]
275 !       2               [qw(1foo bar2)]
276
277 # - a string
278 !       "2"             [qw(1foo 2bar)]
279         "2bar"          [qw(1foo 2bar)]
280
281 # Number against number
282         2               2
283         20              2_0
284 !       2               3
285         0               FALSE
286         3-2             TRUE
287         undef           0
288
289 # Number against string
290 =       2               "2"
291 =       2               "2.0"
292 !       2               "2bananas"
293 !=      2_3             "2_3"
294         FALSE           "0"
295
296 # Regex against string
297         "x"             qr/x/
298 !       "x"             qr/y/
299
300 # Regex against number
301         12345           qr/3/
302
303 # Test the implicit referencing
304         7               @nums
305         @nums           \@nums
306 !       @nums           \\@nums
307         @nums           [1..10]
308 !       @nums           [0..9]
309
310         "foo"           %hash
311         /bar/           %hash
312         [qw(bar)]       %hash
313 !       [qw(a b c)]     %hash
314         %hash           %hash
315         %hash           +{%hash}
316         %hash           \%hash
317         %hash           %tied_hash
318         %tied_hash      %tied_hash
319         %hash           { foo => 5, bar => 10 }
320 !       %hash           { foo => 5, bar => 10, quux => 15 }
321
322         @nums           {  1, '',  2, '' }
323         @nums           {  1, '', 12, '' }
324 !       @nums           { 11, '', 12, '' }