1 | #!./perl
|
---|
2 |
|
---|
3 | BEGIN {
|
---|
4 | chdir 't' if -d 't';
|
---|
5 | @INC = '../lib';
|
---|
6 | }
|
---|
7 |
|
---|
8 | use warnings;
|
---|
9 | use vars qw{ @warnings };
|
---|
10 | BEGIN { # ...and save 'em for later
|
---|
11 | $SIG{'__WARN__'} = sub { push @warnings, @_ }
|
---|
12 | }
|
---|
13 | END { print STDERR @warnings }
|
---|
14 |
|
---|
15 |
|
---|
16 | use strict;
|
---|
17 | use Test::More tests => 81;
|
---|
18 | my $TB = Test::More->builder;
|
---|
19 |
|
---|
20 | BEGIN { use_ok('constant'); }
|
---|
21 |
|
---|
22 | use constant PI => 4 * atan2 1, 1;
|
---|
23 |
|
---|
24 | ok defined PI, 'basic scalar constant';
|
---|
25 | is substr(PI, 0, 7), '3.14159', ' in substr()';
|
---|
26 |
|
---|
27 | sub deg2rad { PI * $_[0] / 180 }
|
---|
28 |
|
---|
29 | my $ninety = deg2rad 90;
|
---|
30 |
|
---|
31 | cmp_ok abs($ninety - 1.5707), '<', 0.0001, ' in math expression';
|
---|
32 |
|
---|
33 | use constant UNDEF1 => undef; # the right way
|
---|
34 | use constant UNDEF2 => ; # the weird way
|
---|
35 | use constant 'UNDEF3' ; # the 'short' way
|
---|
36 | use constant EMPTY => ( ) ; # the right way for lists
|
---|
37 |
|
---|
38 | is UNDEF1, undef, 'right way to declare an undef';
|
---|
39 | is UNDEF2, undef, ' weird way';
|
---|
40 | is UNDEF3, undef, ' short way';
|
---|
41 |
|
---|
42 | # XXX Why is this way different than the other ones?
|
---|
43 | my @undef = UNDEF1;
|
---|
44 | is @undef, 1;
|
---|
45 | is $undef[0], undef;
|
---|
46 |
|
---|
47 | @undef = UNDEF2;
|
---|
48 | is @undef, 0;
|
---|
49 | @undef = UNDEF3;
|
---|
50 | is @undef, 0;
|
---|
51 | @undef = EMPTY;
|
---|
52 | is @undef, 0;
|
---|
53 |
|
---|
54 | use constant COUNTDOWN => scalar reverse 1, 2, 3, 4, 5;
|
---|
55 | use constant COUNTLIST => reverse 1, 2, 3, 4, 5;
|
---|
56 | use constant COUNTLAST => (COUNTLIST)[-1];
|
---|
57 |
|
---|
58 | is COUNTDOWN, '54321';
|
---|
59 | my @cl = COUNTLIST;
|
---|
60 | is @cl, 5;
|
---|
61 | is COUNTDOWN, join '', @cl;
|
---|
62 | is COUNTLAST, 1;
|
---|
63 | is((COUNTLIST)[1], 4);
|
---|
64 |
|
---|
65 | use constant ABC => 'ABC';
|
---|
66 | is "abc${\( ABC )}abc", "abcABCabc";
|
---|
67 |
|
---|
68 | use constant DEF => 'D', 'E', chr ord 'F';
|
---|
69 | is "d e f @{[ DEF ]} d e f", "d e f D E F d e f";
|
---|
70 |
|
---|
71 | use constant SINGLE => "'";
|
---|
72 | use constant DOUBLE => '"';
|
---|
73 | use constant BACK => '\\';
|
---|
74 | my $tt = BACK . SINGLE . DOUBLE ;
|
---|
75 | is $tt, q(\\'");
|
---|
76 |
|
---|
77 | use constant MESS => q('"'\\"'"\\);
|
---|
78 | is MESS, q('"'\\"'"\\);
|
---|
79 | is length(MESS), 8;
|
---|
80 |
|
---|
81 | use constant TRAILING => '12 cats';
|
---|
82 | {
|
---|
83 | no warnings 'numeric';
|
---|
84 | cmp_ok TRAILING, '==', 12;
|
---|
85 | }
|
---|
86 | is TRAILING, '12 cats';
|
---|
87 |
|
---|
88 | use constant LEADING => " \t1234";
|
---|
89 | cmp_ok LEADING, '==', 1234;
|
---|
90 | is LEADING, " \t1234";
|
---|
91 |
|
---|
92 | use constant ZERO1 => 0;
|
---|
93 | use constant ZERO2 => 0.0;
|
---|
94 | use constant ZERO3 => '0.0';
|
---|
95 | is ZERO1, '0';
|
---|
96 | is ZERO2, '0';
|
---|
97 | is ZERO3, '0.0';
|
---|
98 |
|
---|
99 | {
|
---|
100 | package Other;
|
---|
101 | use constant PI => 3.141;
|
---|
102 | }
|
---|
103 |
|
---|
104 | cmp_ok(abs(PI - 3.1416), '<', 0.0001);
|
---|
105 | is Other::PI, 3.141;
|
---|
106 |
|
---|
107 | use constant E2BIG => $! = 7;
|
---|
108 | cmp_ok E2BIG, '==', 7;
|
---|
109 | # This is something like "Arg list too long", but the actual message
|
---|
110 | # text may vary, so we can't test much better than this.
|
---|
111 | cmp_ok length(E2BIG), '>', 6;
|
---|
112 |
|
---|
113 | is @warnings, 0 or diag join "\n", "unexpected warning", @warnings;
|
---|
114 | @warnings = (); # just in case
|
---|
115 | undef &PI;
|
---|
116 | ok @warnings && ($warnings[0] =~ /Constant sub.* undefined/) or
|
---|
117 | diag join "\n", "unexpected warning", @warnings;
|
---|
118 | shift @warnings;
|
---|
119 |
|
---|
120 | is @warnings, 0, "unexpected warning";
|
---|
121 |
|
---|
122 | my $curr_test = $TB->current_test;
|
---|
123 | use constant CSCALAR => \"ok 37\n";
|
---|
124 | use constant CHASH => { foo => "ok 38\n" };
|
---|
125 | use constant CARRAY => [ undef, "ok 39\n" ];
|
---|
126 | use constant CPHASH => [ { foo => 1 }, "ok 40\n" ];
|
---|
127 | use constant CCODE => sub { "ok $_[0]\n" };
|
---|
128 |
|
---|
129 | print ${+CSCALAR};
|
---|
130 | print CHASH->{foo};
|
---|
131 | print CARRAY->[1];
|
---|
132 | print CPHASH->{foo};
|
---|
133 | print CCODE->($curr_test+5);
|
---|
134 |
|
---|
135 | $TB->current_test($curr_test+5);
|
---|
136 |
|
---|
137 | eval q{ CPHASH->{bar} };
|
---|
138 | like $@, qr/^No such pseudo-hash field/, "test missing pseudo-hash field";
|
---|
139 |
|
---|
140 | eval q{ CCODE->{foo} };
|
---|
141 | ok scalar($@ =~ /^Constant is not a HASH/);
|
---|
142 |
|
---|
143 |
|
---|
144 | # Allow leading underscore
|
---|
145 | use constant _PRIVATE => 47;
|
---|
146 | is _PRIVATE, 47;
|
---|
147 |
|
---|
148 | # Disallow doubled leading underscore
|
---|
149 | eval q{
|
---|
150 | use constant __DISALLOWED => "Oops";
|
---|
151 | };
|
---|
152 | like $@, qr/begins with '__'/;
|
---|
153 |
|
---|
154 | # Check on declared() and %declared. This sub should be EXACTLY the
|
---|
155 | # same as the one quoted in the docs!
|
---|
156 | sub declared ($) {
|
---|
157 | use constant 1.01; # don't omit this!
|
---|
158 | my $name = shift;
|
---|
159 | $name =~ s/^::/main::/;
|
---|
160 | my $pkg = caller;
|
---|
161 | my $full_name = $name =~ /::/ ? $name : "${pkg}::$name";
|
---|
162 | $constant::declared{$full_name};
|
---|
163 | }
|
---|
164 |
|
---|
165 | ok declared 'PI';
|
---|
166 | ok $constant::declared{'main::PI'};
|
---|
167 |
|
---|
168 | ok !declared 'PIE';
|
---|
169 | ok !$constant::declared{'main::PIE'};
|
---|
170 |
|
---|
171 | {
|
---|
172 | package Other;
|
---|
173 | use constant IN_OTHER_PACK => 42;
|
---|
174 | ::ok ::declared 'IN_OTHER_PACK';
|
---|
175 | ::ok $constant::declared{'Other::IN_OTHER_PACK'};
|
---|
176 | ::ok ::declared 'main::PI';
|
---|
177 | ::ok $constant::declared{'main::PI'};
|
---|
178 | }
|
---|
179 |
|
---|
180 | ok declared 'Other::IN_OTHER_PACK';
|
---|
181 | ok $constant::declared{'Other::IN_OTHER_PACK'};
|
---|
182 |
|
---|
183 | @warnings = ();
|
---|
184 | eval q{
|
---|
185 | no warnings;
|
---|
186 | use warnings 'constant';
|
---|
187 | use constant 'BEGIN' => 1 ;
|
---|
188 | use constant 'INIT' => 1 ;
|
---|
189 | use constant 'CHECK' => 1 ;
|
---|
190 | use constant 'END' => 1 ;
|
---|
191 | use constant 'DESTROY' => 1 ;
|
---|
192 | use constant 'AUTOLOAD' => 1 ;
|
---|
193 | use constant 'STDIN' => 1 ;
|
---|
194 | use constant 'STDOUT' => 1 ;
|
---|
195 | use constant 'STDERR' => 1 ;
|
---|
196 | use constant 'ARGV' => 1 ;
|
---|
197 | use constant 'ARGVOUT' => 1 ;
|
---|
198 | use constant 'ENV' => 1 ;
|
---|
199 | use constant 'INC' => 1 ;
|
---|
200 | use constant 'SIG' => 1 ;
|
---|
201 | };
|
---|
202 |
|
---|
203 | is @warnings, 15 ;
|
---|
204 | my @Expected_Warnings =
|
---|
205 | (
|
---|
206 | qr/^Constant name 'BEGIN' is a Perl keyword at/,
|
---|
207 | qr/^Constant subroutine BEGIN redefined at/,
|
---|
208 | qr/^Constant name 'INIT' is a Perl keyword at/,
|
---|
209 | qr/^Constant name 'CHECK' is a Perl keyword at/,
|
---|
210 | qr/^Constant name 'END' is a Perl keyword at/,
|
---|
211 | qr/^Constant name 'DESTROY' is a Perl keyword at/,
|
---|
212 | qr/^Constant name 'AUTOLOAD' is a Perl keyword at/,
|
---|
213 | qr/^Constant name 'STDIN' is forced into package main:: a/,
|
---|
214 | qr/^Constant name 'STDOUT' is forced into package main:: at/,
|
---|
215 | qr/^Constant name 'STDERR' is forced into package main:: at/,
|
---|
216 | qr/^Constant name 'ARGV' is forced into package main:: at/,
|
---|
217 | qr/^Constant name 'ARGVOUT' is forced into package main:: at/,
|
---|
218 | qr/^Constant name 'ENV' is forced into package main:: at/,
|
---|
219 | qr/^Constant name 'INC' is forced into package main:: at/,
|
---|
220 | qr/^Constant name 'SIG' is forced into package main:: at/,
|
---|
221 | );
|
---|
222 | for my $idx (0..$#warnings) {
|
---|
223 | like $warnings[$idx], $Expected_Warnings[$idx];
|
---|
224 | }
|
---|
225 | @warnings = ();
|
---|
226 |
|
---|
227 |
|
---|
228 | use constant {
|
---|
229 | THREE => 3,
|
---|
230 | FAMILY => [ qw( John Jane Sally ) ],
|
---|
231 | AGES => { John => 33, Jane => 28, Sally => 3 },
|
---|
232 | RFAM => [ [ qw( John Jane Sally ) ] ],
|
---|
233 | SPIT => sub { shift },
|
---|
234 | PHFAM => [ { John => 1, Jane => 2, Sally => 3 }, 33, 28, 3 ],
|
---|
235 | };
|
---|
236 |
|
---|
237 | is @{+FAMILY}, THREE;
|
---|
238 | is @{+FAMILY}, @{RFAM->[0]};
|
---|
239 | is FAMILY->[2], RFAM->[0]->[2];
|
---|
240 | is AGES->{FAMILY->[1]}, 28;
|
---|
241 | { no warnings 'deprecated'; is PHFAM->{John}, AGES->{John}; }
|
---|
242 | is PHFAM->[3], AGES->{FAMILY->[2]};
|
---|
243 | is @{+PHFAM}, SPIT->(THREE+1);
|
---|
244 | is THREE**3, SPIT->(@{+FAMILY}**3);
|
---|
245 | is AGES->{FAMILY->[THREE-1]}, PHFAM->[THREE];
|
---|
246 |
|
---|
247 | # Allow name of digits/underscores only if it begins with underscore
|
---|
248 | {
|
---|
249 | use warnings FATAL => 'constant';
|
---|
250 | eval q{
|
---|
251 | use constant _1_2_3 => 'allowed';
|
---|
252 | };
|
---|
253 | ok( $@ eq '' );
|
---|
254 | }
|
---|