Fix test for stringification of arrays.
[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 => 'magic' } }
33     use overload '~~' => sub { my %hash = %{ $_[0] }; $_[1] eq $hash{key} };
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 sub NOT_DEF() { undef }
91
92 # Prefix character :
93 #   - expected to match
94 # ! - expected to not match
95 # @ - expected to be a compilation failure
96 # = - expected to match symmetrically (runs test twice)
97 # Data types to test :
98 #   undef
99 #   Object-overloaded
100 #   Object
101 #   Coderef
102 #   Hash
103 #   Hashref
104 #   Array
105 #   Arrayref
106 #   Tied arrays and hashes
107 #   Arrays that reference themselves
108 #   Regex (// and qr//)
109 #   Range
110 #   Num
111 #   Str
112 # Other syntactic items of interest:
113 #   Constants
114 #   Values returned by a sub call
115 __DATA__
116 # Any ~~ undef
117 !=      $ov_obj         undef
118 !       $obj            undef
119 !       sub {}          undef
120 !       %hash           undef
121 !       \%hash          undef
122 !       {}              undef
123 !       @nums           undef
124 !       \@nums          undef
125 !       []              undef
126 !       %tied_hash      undef
127 !       @tied_nums      undef
128 !       $deep1          undef
129 !       /foo/           undef
130 !       qr/foo/         undef
131 !       21..30          undef
132 !       189             undef
133 !       "foo"           undef
134 !       ""              undef
135 !       !1              undef
136         undef           undef
137         (my $u)         undef
138         NOT_DEF         undef
139         &NOT_DEF        undef
140
141 # Any ~~ object overloaded
142 # object overloaded ~~ Any
143 =!      $ov_obj         \&fatal
144 =       $ov_obj         'magic'
145 =!      $ov_obj         'not magic'
146 =!      $ov_obj         $obj
147
148 # regular object
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           { hop => 'zouu' }
249 !       undef           %hash
250 !       undef           +{"" => "empty key"}
251 !       undef           {}
252
253 # ARRAY ref against:
254 #  - another array ref
255         []                      []
256 =!      []                      [1]
257 !       [["foo"], ["bar"]]      [qr/o/, qr/a/]
258         [["foo"], ["bar"]]      [qr/ARRAY/, qr/ARRAY/]
259         ["foo", "bar"]          [qr/o/, qr/a/]
260         ["foo", "bar"]          [["foo"], ["bar"]]
261 !       ["foo", "bar"]          [qr/o/, "foo"]
262         ["foo", undef, "bar"]   [qr/o/, undef, "bar"]
263         ["foo", undef, "bar"]   [qr/o/, "",    "bar"]
264 !       ["foo", "", "bar"]      [qr/o/, undef, "bar"]
265         $deep1                  $deep1
266 !       $deep1                  $deep2
267
268         \@nums                  \@tied_nums
269
270 #  - a regex
271         qr/x/           [qw(foo bar baz quux)]
272 !       qr/y/           [qw(foo bar baz quux)]
273         /x/             [qw(foo bar baz quux)]
274 !       /y/             [qw(foo bar baz quux)]
275
276 # - a number
277         2               [qw(1foo 2bar)]
278         2               [qw(foo 2)]
279         2.0_0e+0        [qw(foo 2)]
280 !       2               [qw(1foo bar2)]
281
282 # - a string
283 !       "2"             [qw(1foo 2bar)]
284         "2bar"          [qw(1foo 2bar)]
285
286 # Number against number
287         2               2
288         20              2_0
289 !       2               3
290         0               FALSE
291         3-2             TRUE
292         undef           0
293
294 # Number against string
295 =       2               "2"
296 =       2               "2.0"
297 !       2               "2bananas"
298 !=      2_3             "2_3"
299         FALSE           "0"
300
301 # Regex against string
302         "x"             qr/x/
303 !       "x"             qr/y/
304
305 # Regex against number
306         12345           qr/3/
307 !       12345           qr/7/
308
309 # array against string
310         @fooormore      "".\@fooormore
311 !       @keyandmore     "".\@fooormore
312         %fooormore      "".\%fooormore
313 !       %keyandmore     "".\%fooormore
314
315 # Test the implicit referencing
316         7               @nums
317         @nums           \@nums
318 !       @nums           \\@nums
319         @nums           [1..10]
320 !       @nums           [0..9]
321
322         "foo"           %hash
323         /bar/           %hash
324         [qw(bar)]       %hash
325 !       [qw(a b c)]     %hash
326         %hash           %hash
327         %hash           +{%hash}
328         %hash           \%hash
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, '' }