Remove obsolete comment; document test format
[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 {
37     package Test::Object::OverloadCodeRef;
38     sub new { bless $_[1] }
39     use overload '~~' => sub { shift->($_[1]) };
40 }
41
42 our $ov_obj = Test::Object::CopyOverload->new;
43 our $obj = Test::Object::NoOverload->new;
44 our $false_obj = Test::Object::OverloadCodeRef->new(sub { 0 });
45 our $true_obj = Test::Object::OverloadCodeRef->new(sub { 1 });
46
47
48 # Load and run the tests
49 my @tests = map [chomp and split /\t+/, $_, 3], grep !/^#/ && /\S/, <DATA>;
50 plan tests => 2 * @tests;
51
52 for my $test (@tests) {
53     my ($yn, $left, $right) = @$test;
54
55     match_test($yn, $left, $right);
56     match_test($yn, $right, $left);
57 }
58
59 sub match_test {
60     my ($yn, $left, $right) = @_;
61
62     die "Bad test spec: ($yn, $left, $right)"
63         unless $yn eq "" || $yn eq "!" || $yn eq '@';
64     
65     my $tstr = "$left ~~ $right";
66     
67     my $res;
68     $res = eval $tstr // "";    #/ <- fix syntax colouring
69
70     chomp $@;
71
72     if ( $yn eq '@' ) {
73         ok( $@ ne '', sprintf "%s%s: %s", $tstr, $@ ? ( ', $@', $@ ) : ( '', $res ) );
74     } else {
75         if ( $@ ne '' ) {
76             fail("$tstr, \$\@: $@");
77         } else {
78             ok( ($yn eq '!' xor $res), "$tstr: $res");
79         }
80     }
81 }
82
83
84
85 sub foo {}
86 sub bar {2}
87 sub gorch {2}
88 sub fatal {die "fatal sub\n"}
89
90 sub a_const() {die "const\n" if @_; "a constant"}
91 sub b_const() {die "const\n" if @_; "a constant"}
92
93 # Prefix character :
94 #   - expected to match
95 # ! - expected to not match
96 # @ - expected to be a compilation failure
97 __DATA__
98 # OBJECT
99 # - overloaded
100         $ov_obj         "key"
101         $ov_obj         {"key" => 1}
102 !       $ov_obj         "foo"
103 !       $ov_obj         \&foo
104 @       $ov_obj         \&fatal
105
106 # regular object
107 @       $obj    "key"
108 @       $obj    {"key" => 1}
109 @       $obj    "foo"
110 @       $obj    $obj
111 @       $obj    sub { 1 }
112 @       $obj    sub { 0 }
113 @       $obj    \&foo
114 @       $obj    \&fatal
115
116 # CODE ref against argument
117 #  - arg is code ref
118         \&foo           \&foo
119 !       \&foo           sub {}
120 !       \&foo           \&bar
121         \&fatal         \&fatal
122 !       \&foo           \&fatal
123
124 # - arg is not code ref
125         1       sub{shift}
126 !       0       sub{shift}
127 !       undef   sub{shift}
128         undef   sub{not shift}
129         1       sub{scalar @_}
130         []      \&bar
131         {}      \&bar
132         qr//    \&bar
133 !       []      \&foo
134 !       {}      \&foo
135 !       qr//    \&foo
136 !       undef   \&foo
137         undef   \&bar
138 @       undef   \&fatal
139 @       1       \&fatal
140 @       []      \&fatal
141 @       "foo"   \&fatal
142 @       qr//    \&fatal
143 @       $obj    \&bar
144         $ov_obj \&bar
145
146 # - null-prototyped subs
147         a_const         "a constant"
148         a_const         a_const
149         a_const         b_const
150         \&a_const       \&a_const
151 !       \&a_const       \&b_const
152
153 # - non-null-prototyped subs
154 !       \&bar           \&gorch
155         bar             gorch
156 @       fatal           bar
157
158 # HASH ref against:
159 #   - another hash ref
160         {}              {}
161 !       {}              {1 => 2}
162         {1 => 2}        {1 => 2}
163         {1 => 2}        {1 => 3}
164 !       {1 => 2}        {2 => 3}
165         \%main::        {map {$_ => 'x'} keys %main::}
166
167 #  - tied hash ref
168         \%hash          \%tied_hash
169         \%tied_hash     \%tied_hash
170
171 #  - an array ref
172         \%::            [keys %main::]
173 !       \%::            []
174         {"" => 1}       [undef]
175         { foo => 1 }    ["foo"]
176         { foo => 1 }    ["foo", "bar"]
177         \%hash          ["foo", "bar"]
178         \%hash          ["foo"]
179 !       \%hash          ["quux"]
180         \%hash          [qw(foo quux)]
181
182 #  - a regex
183         {foo => 1}      qr/^(fo[ox])$/
184 !       +{0..100}       qr/[13579]$/
185
186 #  - a string
187         +{foo => 1, bar => 2}   "foo"
188 !       +{foo => 1, bar => 2}   "baz"
189
190
191 # ARRAY ref against:
192 #  - another array ref
193         []                      []
194 !       []                      [1]
195         [["foo"], ["bar"]]      [qr/o/, qr/a/]
196         ["foo", "bar"]          [qr/o/, qr/a/]
197 !       ["foo", "bar"]          [qr/o/, "foo"]
198         $deep1                  $deep1
199 !       $deep1                  $deep2
200
201         \@nums                  \@tied_nums
202
203 #  - a regex
204         [qw(foo bar baz quux)]  qr/x/
205 !       [qw(foo bar baz quux)]  qr/y/
206
207 # - a number
208         [qw(1foo 2bar)]         2
209         [qw(foo 2)]             2
210         [qw(foo 2)]             2.0_0e+0
211 !       [qw(1foo bar2)]         2
212
213 # - a string
214 !       [qw(1foo 2bar)]         "2"
215         [qw(1foo 2bar)]         "2bar"
216
217 # Number against number
218         2               2
219 !       2               3
220
221 # Number against string
222         2               "2"
223         2               "2.0"
224 !       2               "2bananas"
225 !       2_3             "2_3"
226
227 # Regex against string
228         qr/x/           "x"
229 !       qr/y/           "x"
230
231 # Regex against number
232         12345           qr/3/
233
234
235 # Test the implicit referencing
236         @nums           7
237         @nums           \@nums
238 !       @nums           \\@nums
239         @nums           [1..10]
240 !       @nums           [0..9]
241
242         %hash           "foo"
243         %hash           /bar/
244         %hash           [qw(bar)]
245 !       %hash           [qw(a b c)]
246         %hash           %hash
247         %hash           {%hash}
248         %hash           %tied_hash
249         %tied_hash      %tied_hash
250         %hash           { foo => 5, bar => 10 }
251 !       %hash           { foo => 5, bar => 10, quux => 15 }
252
253         @nums           {  1, '',  2, '' }
254         @nums           {  1, '', 12, '' }
255 !       @nums           { 11, '', 12, '' }
256
257 # UNDEF
258 !       3               undef
259 !       1               undef
260 !       []              undef
261 !       {}              undef
262 !       \%::main        undef
263 !       [1,2]           undef
264 !       %hash           undef
265 !       @nums           undef
266 !       "foo"           undef
267 !       ""              undef
268 !       !1              undef
269 !       \&foo           undef
270 !       sub { }         undef