xref: /openbsd-src/gnu/usr.bin/perl/lib/builtin.t (revision 5486feefcc8cb79b19e014ab332cc5dfd05b3b33)
1*5486feefSafresh1#!./perl
2256a93a4Safresh1
3256a93a4Safresh1BEGIN {
4256a93a4Safresh1    chdir 't' if -d 't';
5256a93a4Safresh1    require './test.pl';
6256a93a4Safresh1    set_up_inc('../lib');
7256a93a4Safresh1}
8256a93a4Safresh1
9f2a19305Safresh1use v5.36;
10256a93a4Safresh1no warnings 'experimental::builtin';
11256a93a4Safresh1
12256a93a4Safresh1package FetchStoreCounter {
13f2a19305Safresh1    sub TIESCALAR($class, @args) { bless \@args, $class }
14f2a19305Safresh1
15f2a19305Safresh1    sub FETCH($self)    { $self->[0]->$*++ }
16f2a19305Safresh1    sub STORE($self, $) { $self->[1]->$*++ }
17256a93a4Safresh1}
18256a93a4Safresh1
19256a93a4Safresh1# booleans
20256a93a4Safresh1{
21256a93a4Safresh1    use builtin qw( true false is_bool );
22256a93a4Safresh1
23256a93a4Safresh1    ok(true, 'true is true');
24256a93a4Safresh1    ok(!false, 'false is false');
25256a93a4Safresh1
26256a93a4Safresh1    ok(is_bool(true), 'true is bool');
27256a93a4Safresh1    ok(is_bool(false), 'false is bool');
28256a93a4Safresh1    ok(!is_bool(undef), 'undef is not bool');
29256a93a4Safresh1    ok(!is_bool(1), '1 is not bool');
30256a93a4Safresh1    ok(!is_bool(""), 'empty is not bool');
31256a93a4Safresh1
32256a93a4Safresh1    my $truevar  = (5 == 5);
33256a93a4Safresh1    my $falsevar = (5 == 6);
34256a93a4Safresh1
35256a93a4Safresh1    ok(is_bool($truevar), '$truevar is bool');
36256a93a4Safresh1    ok(is_bool($falsevar), '$falsevar is bool');
37256a93a4Safresh1
38256a93a4Safresh1    ok(is_bool(is_bool(true)), 'is_bool true is bool');
39256a93a4Safresh1    ok(is_bool(is_bool(123)),  'is_bool false is bool');
40256a93a4Safresh1
41256a93a4Safresh1    # Invokes magic
42256a93a4Safresh1
43256a93a4Safresh1    tie my $tied, FetchStoreCounter => (\my $fetchcount, \my $storecount);
44256a93a4Safresh1
45256a93a4Safresh1    my $_dummy = is_bool($tied);
46256a93a4Safresh1    is($fetchcount, 1, 'is_bool() invokes FETCH magic');
47256a93a4Safresh1
48256a93a4Safresh1    $tied = is_bool(false);
49f2a19305Safresh1    is($storecount, 1, 'is_bool() invokes STORE magic');
50f2a19305Safresh1
51f2a19305Safresh1    is(prototype(\&builtin::is_bool), '$', 'is_bool prototype');
52256a93a4Safresh1}
53256a93a4Safresh1
54*5486feefSafresh1# float constants
55*5486feefSafresh1{
56*5486feefSafresh1    use builtin qw( inf nan );
57*5486feefSafresh1
58*5486feefSafresh1    ok(inf, 'inf is true');
59*5486feefSafresh1    ok(inf > 1E10, 'inf is bigger than 1E10');
60*5486feefSafresh1    ok(inf == inf, 'inf is equal to inf');
61*5486feefSafresh1    ok(inf == inf + 1, 'inf is equal to inf + 1');
62*5486feefSafresh1
63*5486feefSafresh1    # Invoke the real XSUB
64*5486feefSafresh1    my $inf = ( \&builtin::inf )->();
65*5486feefSafresh1    ok($inf == $inf + 1, 'inf returned by real xsub');
66*5486feefSafresh1
67*5486feefSafresh1    ok(nan != nan, 'NaN is not equal to NaN');
68*5486feefSafresh1
69*5486feefSafresh1    my $nan = ( \&builtin::nan )->();
70*5486feefSafresh1    ok($nan != $nan, 'NaN returned by real xsub');
71*5486feefSafresh1}
72*5486feefSafresh1
73256a93a4Safresh1# weakrefs
74256a93a4Safresh1{
75256a93a4Safresh1    use builtin qw( is_weak weaken unweaken );
76256a93a4Safresh1
77256a93a4Safresh1    my $arr = [];
78256a93a4Safresh1    my $ref = $arr;
79256a93a4Safresh1
80256a93a4Safresh1    ok(!is_weak($ref), 'ref is not weak initially');
81256a93a4Safresh1
82256a93a4Safresh1    weaken($ref);
83256a93a4Safresh1    ok(is_weak($ref), 'ref is weak after weaken()');
84256a93a4Safresh1
85256a93a4Safresh1    unweaken($ref);
86256a93a4Safresh1    ok(!is_weak($ref), 'ref is not weak after unweaken()');
87256a93a4Safresh1
88256a93a4Safresh1    weaken($ref);
89256a93a4Safresh1    undef $arr;
90256a93a4Safresh1    is($ref, undef, 'ref is now undef after arr is cleared');
91f2a19305Safresh1
92f2a19305Safresh1    is(prototype(\&builtin::weaken), '$', 'weaken prototype');
93f2a19305Safresh1    is(prototype(\&builtin::unweaken), '$', 'unweaken prototype');
94f2a19305Safresh1    is(prototype(\&builtin::is_weak), '$', 'is_weak prototype');
95256a93a4Safresh1}
96256a93a4Safresh1
97256a93a4Safresh1# reference queries
98256a93a4Safresh1{
99256a93a4Safresh1    use builtin qw( refaddr reftype blessed );
100256a93a4Safresh1
101256a93a4Safresh1    my $arr = [];
102256a93a4Safresh1    my $obj = bless [], "Object";
103256a93a4Safresh1
104256a93a4Safresh1    is(refaddr($arr),        $arr+0, 'refaddr yields same as ref in numeric context');
105256a93a4Safresh1    is(refaddr("not a ref"), undef,  'refaddr yields undef for non-reference');
106256a93a4Safresh1
107256a93a4Safresh1    is(reftype($arr),        "ARRAY", 'reftype yields type string');
108256a93a4Safresh1    is(reftype($obj),        "ARRAY", 'reftype yields basic container type for blessed object');
109256a93a4Safresh1    is(reftype("not a ref"), undef,   'reftype yields undef for non-reference');
110256a93a4Safresh1
111256a93a4Safresh1    is(blessed($arr), undef, 'blessed yields undef for non-object');
112256a93a4Safresh1    is(blessed($obj), "Object", 'blessed yields package name for object');
113256a93a4Safresh1
114256a93a4Safresh1    # blessed() as a boolean
115256a93a4Safresh1    is(blessed($obj) ? "YES" : "NO", "YES", 'blessed in boolean context still works');
116256a93a4Safresh1
117256a93a4Safresh1    # blessed() appears false as a boolean on package "0"
118256a93a4Safresh1    is(blessed(bless [], "0") ? "YES" : "NO", "NO", 'blessed in boolean context handles "0" cornercase');
119f2a19305Safresh1
120f2a19305Safresh1    is(prototype(\&builtin::blessed), '$', 'blessed prototype');
121f2a19305Safresh1    is(prototype(\&builtin::refaddr), '$', 'refaddr prototype');
122f2a19305Safresh1    is(prototype(\&builtin::reftype), '$', 'reftype prototype');
123256a93a4Safresh1}
124256a93a4Safresh1
125256a93a4Safresh1# created_as_...
126256a93a4Safresh1{
127256a93a4Safresh1    use builtin qw( created_as_string created_as_number );
128256a93a4Safresh1
129256a93a4Safresh1    # some literal constants
130256a93a4Safresh1    ok(!created_as_string(undef), 'undef created as !string');
131256a93a4Safresh1    ok(!created_as_number(undef), 'undef created as !number');
132256a93a4Safresh1
133256a93a4Safresh1    ok( created_as_string("abc"), 'abc created as string');
134256a93a4Safresh1    ok(!created_as_number("abc"), 'abc created as number');
135256a93a4Safresh1
136256a93a4Safresh1    ok(!created_as_string(123),   '123 created as !string');
137256a93a4Safresh1    ok( created_as_number(123),   '123 created as !number');
138256a93a4Safresh1
139256a93a4Safresh1    ok(!created_as_string(1.23),   '1.23 created as !string');
140256a93a4Safresh1    ok( created_as_number(1.23),   '1.23 created as !number');
141256a93a4Safresh1
142256a93a4Safresh1    ok(!created_as_string([]),    '[] created as !string');
143256a93a4Safresh1    ok(!created_as_number([]),    '[] created as !number');
144256a93a4Safresh1
145256a93a4Safresh1    ok(!created_as_string(builtin::true), 'true created as !string');
146256a93a4Safresh1    ok(!created_as_number(builtin::true), 'true created as !number');
147256a93a4Safresh1
148256a93a4Safresh1    ok(builtin::is_bool(created_as_string(0)), 'created_as_string returns bool');
149256a93a4Safresh1    ok(builtin::is_bool(created_as_number(0)), 'created_as_number returns bool');
150256a93a4Safresh1
151256a93a4Safresh1    # variables
152256a93a4Safresh1    my $just_pv = "def";
153256a93a4Safresh1    ok( created_as_string($just_pv), 'def created as string');
154256a93a4Safresh1    ok(!created_as_number($just_pv), 'def created as number');
155256a93a4Safresh1
156256a93a4Safresh1    my $just_iv = 456;
157256a93a4Safresh1    ok(!created_as_string($just_iv), '456 created as string');
158256a93a4Safresh1    ok( created_as_number($just_iv), '456 created as number');
159256a93a4Safresh1
160256a93a4Safresh1    my $just_nv = 4.56;
161256a93a4Safresh1    ok(!created_as_string($just_nv), '456 created as string');
162256a93a4Safresh1    ok( created_as_number($just_nv), '456 created as number');
163256a93a4Safresh1
164256a93a4Safresh1    # variables reused
165256a93a4Safresh1    my $originally_pv = "1";
166256a93a4Safresh1    my $pv_as_iv = $originally_pv + 0;
167256a93a4Safresh1    ok( created_as_string($originally_pv), 'PV reused as IV created as string');
168256a93a4Safresh1    ok(!created_as_number($originally_pv), 'PV reused as IV created as !number');
169256a93a4Safresh1    ok(!created_as_string($pv_as_iv), 'New number from PV created as !string');
170256a93a4Safresh1    ok( created_as_number($pv_as_iv), 'New number from PV created as number');
171256a93a4Safresh1
172256a93a4Safresh1    my $originally_iv = 1;
173256a93a4Safresh1    my $iv_as_pv = "$originally_iv";
174256a93a4Safresh1    ok(!created_as_string($originally_iv), 'IV reused as PV created as !string');
175256a93a4Safresh1    ok( created_as_number($originally_iv), 'IV reused as PV created as number');
176256a93a4Safresh1    ok( created_as_string($iv_as_pv), 'New string from IV created as string');
177256a93a4Safresh1    ok(!created_as_number($iv_as_pv), 'New string from IV created as !number');
178256a93a4Safresh1
179256a93a4Safresh1    my $originally_nv = 1.1;
180256a93a4Safresh1    my $nv_as_pv = "$originally_nv";
181256a93a4Safresh1    ok(!created_as_string($originally_nv), 'NV reused as PV created as !string');
182256a93a4Safresh1    ok( created_as_number($originally_nv), 'NV reused as PV created as number');
183256a93a4Safresh1    ok( created_as_string($nv_as_pv), 'New string from NV created as string');
184256a93a4Safresh1    ok(!created_as_number($nv_as_pv), 'New string from NV created as !number');
185256a93a4Safresh1
186256a93a4Safresh1    # magic
187256a93a4Safresh1    local $1;
188256a93a4Safresh1    "hello" =~ m/(.*)/;
189256a93a4Safresh1    ok(created_as_string($1), 'magic string');
190f2a19305Safresh1
191f2a19305Safresh1    is(prototype(\&builtin::created_as_string), '$', 'created_as_string prototype');
192f2a19305Safresh1    is(prototype(\&builtin::created_as_number), '$', 'created_as_number prototype');
193256a93a4Safresh1}
194256a93a4Safresh1
195*5486feefSafresh1# stringify
196*5486feefSafresh1{
197*5486feefSafresh1    use builtin qw( stringify );
198*5486feefSafresh1
199*5486feefSafresh1    is(stringify("abc"), "abc", 'stringify a plain string');
200*5486feefSafresh1    is(stringify(123),   "123", 'stringify a number');
201*5486feefSafresh1
202*5486feefSafresh1    my $aref = [];
203*5486feefSafresh1    is(stringify($aref), "$aref", 'stringify an array ref');
204*5486feefSafresh1
205*5486feefSafresh1    use builtin qw( created_as_string );
206*5486feefSafresh1    ok(!ref stringify($aref),               'stringified arrayref is not a ref');
207*5486feefSafresh1    ok(created_as_string(stringify($aref)), 'stringified arrayref is created as string');
208*5486feefSafresh1
209*5486feefSafresh1    package WithOverloadedStringify {
210*5486feefSafresh1        use overload '""' => sub { return "STRING" };
211*5486feefSafresh1    }
212*5486feefSafresh1
213*5486feefSafresh1    is(stringify(bless [], "WithOverloadedStringify"), "STRING", 'stringify invokes "" overload');
214*5486feefSafresh1}
215*5486feefSafresh1
216256a93a4Safresh1# ceil, floor
217256a93a4Safresh1{
218256a93a4Safresh1    use builtin qw( ceil floor );
219256a93a4Safresh1
220256a93a4Safresh1    cmp_ok(ceil(1.5), '==', 2, 'ceil(1.5) == 2');
221256a93a4Safresh1    cmp_ok(floor(1.5), '==', 1, 'floor(1.5) == 1');
222256a93a4Safresh1
223256a93a4Safresh1    # Invokes magic
224256a93a4Safresh1
225256a93a4Safresh1    tie my $tied, FetchStoreCounter => (\my $fetchcount, \my $storecount);
226256a93a4Safresh1
227256a93a4Safresh1    my $_dummy = ceil($tied);
228256a93a4Safresh1    is($fetchcount, 1, 'ceil() invokes FETCH magic');
229256a93a4Safresh1
230256a93a4Safresh1    $tied = ceil(1.1);
231256a93a4Safresh1    is($storecount, 1, 'ceil() TARG invokes STORE magic');
232256a93a4Safresh1
233256a93a4Safresh1    $fetchcount = $storecount = 0;
234256a93a4Safresh1    tie $tied, FetchStoreCounter => (\$fetchcount, \$storecount);
235256a93a4Safresh1
236256a93a4Safresh1    $_dummy = floor($tied);
237256a93a4Safresh1    is($fetchcount, 1, 'floor() invokes FETCH magic');
238256a93a4Safresh1
239256a93a4Safresh1    $tied = floor(1.1);
240256a93a4Safresh1    is($storecount, 1, 'floor() TARG invokes STORE magic');
241f2a19305Safresh1
242f2a19305Safresh1    is(prototype(\&builtin::ceil), '$', 'ceil prototype');
243f2a19305Safresh1    is(prototype(\&builtin::floor), '$', 'floor prototype');
244256a93a4Safresh1}
245256a93a4Safresh1
246256a93a4Safresh1# imports are lexical; should not be visible here
247256a93a4Safresh1{
248256a93a4Safresh1    my $ok = eval 'true()'; my $e = $@;
249256a93a4Safresh1    ok(!$ok, 'true() not visible outside of lexical scope');
250256a93a4Safresh1    like($e, qr/^Undefined subroutine &main::true called at /, 'failure from true() not visible');
251256a93a4Safresh1}
252256a93a4Safresh1
253256a93a4Safresh1# lexical imports work fine in a variety of situations
254256a93a4Safresh1{
255256a93a4Safresh1    sub regularfunc {
256256a93a4Safresh1        use builtin 'true';
257256a93a4Safresh1        return true;
258256a93a4Safresh1    }
259256a93a4Safresh1    ok(regularfunc(), 'true in regular sub');
260256a93a4Safresh1
261256a93a4Safresh1    my sub lexicalfunc {
262256a93a4Safresh1        use builtin 'true';
263256a93a4Safresh1        return true;
264256a93a4Safresh1    }
265256a93a4Safresh1    ok(lexicalfunc(), 'true in lexical sub');
266256a93a4Safresh1
267256a93a4Safresh1    my $coderef = sub {
268256a93a4Safresh1        use builtin 'true';
269256a93a4Safresh1        return true;
270256a93a4Safresh1    };
271256a93a4Safresh1    ok($coderef->(), 'true in anon sub');
272256a93a4Safresh1
273256a93a4Safresh1    sub recursefunc {
274256a93a4Safresh1        use builtin 'true';
275256a93a4Safresh1        return recursefunc() if @_;
276256a93a4Safresh1        return true;
277256a93a4Safresh1    }
278256a93a4Safresh1    ok(recursefunc("rec"), 'true in self-recursive sub');
279256a93a4Safresh1
280*5486feefSafresh1    my sub recurselexicalfunc {
281*5486feefSafresh1        use builtin 'true';
282*5486feefSafresh1        return __SUB__->() if @_;
283*5486feefSafresh1        return true;
284*5486feefSafresh1    }
285*5486feefSafresh1    ok(recurselexicalfunc("rec"), 'true in self-recursive lexical sub');
286*5486feefSafresh1
287256a93a4Safresh1    my $recursecoderef = sub {
288256a93a4Safresh1        use builtin 'true';
289256a93a4Safresh1        return __SUB__->() if @_;
290256a93a4Safresh1        return true;
291256a93a4Safresh1    };
292256a93a4Safresh1    ok($recursecoderef->("rec"), 'true in self-recursive anon sub');
293256a93a4Safresh1}
294256a93a4Safresh1
295256a93a4Safresh1{
296256a93a4Safresh1    use builtin qw( true false );
297256a93a4Safresh1
298256a93a4Safresh1    my $val = true;
299256a93a4Safresh1    cmp_ok($val, $_, !!1, "true is equivalent to !!1 by $_") for qw( eq == );
300256a93a4Safresh1    cmp_ok($val, $_,  !0, "true is equivalent to  !0 by $_") for qw( eq == );
301256a93a4Safresh1
302256a93a4Safresh1    $val = false;
303256a93a4Safresh1    cmp_ok($val, $_, !!0, "false is equivalent to !!0 by $_") for qw( eq == );
304256a93a4Safresh1    cmp_ok($val, $_,  !1, "false is equivalent to  !1 by $_") for qw( eq == );
305256a93a4Safresh1}
306256a93a4Safresh1
307256a93a4Safresh1# indexed
308256a93a4Safresh1{
309256a93a4Safresh1    use builtin qw( indexed );
310256a93a4Safresh1
311256a93a4Safresh1    # We don't have Test::More's is_deeply here
312256a93a4Safresh1
313256a93a4Safresh1    ok(eq_array([indexed], [] ),
314256a93a4Safresh1        'indexed on empty list');
315256a93a4Safresh1
316256a93a4Safresh1    ok(eq_array([indexed "A"], [0, "A"] ),
317256a93a4Safresh1        'indexed on singleton list');
318256a93a4Safresh1
319256a93a4Safresh1    ok(eq_array([indexed "X" .. "Z"], [0, "X", 1, "Y", 2, "Z"] ),
320256a93a4Safresh1        'indexed on 3-item list');
321256a93a4Safresh1
322256a93a4Safresh1    my @orig = (1..3);
323256a93a4Safresh1    $_++ for indexed @orig;
324256a93a4Safresh1    ok(eq_array(\@orig, [1 .. 3]), 'indexed copies values, does not alias');
325256a93a4Safresh1
326256a93a4Safresh1    {
327256a93a4Safresh1        my $ok = 1;
328256a93a4Safresh1        foreach my ($len, $s) (indexed "", "x", "xx") {
329256a93a4Safresh1            length($s) == $len or undef $ok;
330256a93a4Safresh1        }
331256a93a4Safresh1        ok($ok, 'indexed operates nicely with multivar foreach');
332256a93a4Safresh1    }
333256a93a4Safresh1
334256a93a4Safresh1    {
335256a93a4Safresh1        my %hash = indexed "a" .. "e";
336256a93a4Safresh1        ok(eq_hash(\%hash, { 0 => "a", 1 => "b", 2 => "c", 3 => "d", 4 => "e" }),
337256a93a4Safresh1            'indexed can be used to create hashes');
338256a93a4Safresh1    }
339256a93a4Safresh1
340256a93a4Safresh1    {
341256a93a4Safresh1        no warnings 'scalar';
342256a93a4Safresh1
343256a93a4Safresh1        my $count = indexed 'i', 'ii', 'iii', 'iv';
344256a93a4Safresh1        is($count, 8, 'indexed in scalar context yields size of list it would return');
345256a93a4Safresh1    }
346*5486feefSafresh1
347*5486feefSafresh1    is(prototype(\&builtin::indexed), '@', 'indexed prototype');
348256a93a4Safresh1}
349256a93a4Safresh1
350256a93a4Safresh1# Vanilla trim tests
351256a93a4Safresh1{
352256a93a4Safresh1    use builtin qw( trim );
353256a93a4Safresh1
354f2a19305Safresh1    is(trim("    Hello world!   ")      , "Hello world!"  , 'trim spaces');
355f2a19305Safresh1    is(trim("\tHello world!\t")         , "Hello world!"  , 'trim tabs');
356f2a19305Safresh1    is(trim("\n\n\nHello\nworld!\n")    , "Hello\nworld!" , 'trim \n');
357f2a19305Safresh1    is(trim("\t\n\n\nHello world!\n \t"), "Hello world!"  , 'trim all three');
358f2a19305Safresh1    is(trim("Perl")                     , "Perl"          , 'trim nothing');
359f2a19305Safresh1    is(trim('')                         , ""              , 'trim empty string');
360f2a19305Safresh1
361f2a19305Safresh1    is(prototype(\&builtin::trim), '$', 'trim prototype');
362256a93a4Safresh1}
363256a93a4Safresh1
364256a93a4Safresh1TODO: {
365256a93a4Safresh1    my $warn = '';
366256a93a4Safresh1    local $SIG{__WARN__} = sub { $warn .= join "", @_; };
367256a93a4Safresh1
368f2a19305Safresh1    is(builtin::trim(undef), "", 'trim undef');
369256a93a4Safresh1    like($warn    , qr/^Use of uninitialized value in subroutine entry at/,
370f2a19305Safresh1         'trim undef triggers warning');
371256a93a4Safresh1    local $main::TODO = "Currently uses generic value for the name of non-opcode builtins";
372256a93a4Safresh1    like($warn    , qr/^Use of uninitialized value in trim at/,
373f2a19305Safresh1         'trim undef triggers warning using actual name of builtin');
374256a93a4Safresh1}
375256a93a4Safresh1
376256a93a4Safresh1# Fancier trim tests against a regexp and unicode
377256a93a4Safresh1{
378256a93a4Safresh1    use builtin qw( trim );
379256a93a4Safresh1    my $nbsp = chr utf8::unicode_to_native(0xA0);
380256a93a4Safresh1
381f2a19305Safresh1    is(trim("   \N{U+2603}       "), "\N{U+2603}", 'trim with unicode content');
382256a93a4Safresh1    is(trim("\N{U+2029}foobar\x{2028} "), "foobar",
383f2a19305Safresh1            'trim with unicode whitespace');
384f2a19305Safresh1    is(trim("$nbsp foobar$nbsp    "), "foobar", 'trim with latin1 whitespace');
385256a93a4Safresh1}
386256a93a4Safresh1
387256a93a4Safresh1# Test on a magical fetching variable
388256a93a4Safresh1{
389256a93a4Safresh1    use builtin qw( trim );
390256a93a4Safresh1
391256a93a4Safresh1    my $str3 = "   Hello world!\t";
392256a93a4Safresh1    $str3 =~ m/(.+Hello)/;
393f2a19305Safresh1    is(trim($1), "Hello", "trim on a magical variable");
394256a93a4Safresh1}
395256a93a4Safresh1
396256a93a4Safresh1# Inplace edit, my, our variables
397256a93a4Safresh1{
398256a93a4Safresh1    use builtin qw( trim );
399256a93a4Safresh1
400256a93a4Safresh1    my $str4 = "\t\tHello world!\n\n";
401256a93a4Safresh1    $str4 = trim($str4);
402f2a19305Safresh1    is($str4, "Hello world!", "trim on an inplace variable");
403256a93a4Safresh1
404256a93a4Safresh1    our $str2 = "\t\nHello world!\t  ";
405f2a19305Safresh1    is(trim($str2), "Hello world!", "trim on an our \$var");
406f2a19305Safresh1}
407f2a19305Safresh1
408f2a19305Safresh1# Lexical export
409f2a19305Safresh1{
410f2a19305Safresh1    my $name;
411f2a19305Safresh1    BEGIN {
412f2a19305Safresh1        use builtin qw( export_lexically );
413f2a19305Safresh1
414f2a19305Safresh1        $name = "message";
415f2a19305Safresh1        export_lexically $name => sub { "Hello, world" };
416f2a19305Safresh1    }
417f2a19305Safresh1
418f2a19305Safresh1    is(message(), "Hello, world", 'Lexically exported sub is callable');
419f2a19305Safresh1    ok(!__PACKAGE__->can("message"), 'Exported sub is not visible via ->can');
420f2a19305Safresh1
421f2a19305Safresh1    is($name, "message", '$name argument was not modified by export_lexically');
422f2a19305Safresh1
423f2a19305Safresh1    our ( $scalar, @array, %hash );
424f2a19305Safresh1    BEGIN {
425f2a19305Safresh1        use builtin qw( export_lexically );
426f2a19305Safresh1
427f2a19305Safresh1        export_lexically
428f2a19305Safresh1            '$SCALAR' => \$scalar,
429f2a19305Safresh1            '@ARRAY'  => \@array,
430f2a19305Safresh1            '%HASH'   => \%hash;
431f2a19305Safresh1    }
432f2a19305Safresh1
433f2a19305Safresh1    $::scalar = "value";
434f2a19305Safresh1    is($SCALAR, "value", 'Lexically exported scalar is accessible');
435f2a19305Safresh1
436f2a19305Safresh1    @::array = ('a' .. 'e');
437f2a19305Safresh1    is(scalar @ARRAY, 5, 'Lexically exported array is accessible');
438f2a19305Safresh1
439f2a19305Safresh1    %::hash = (key => "val");
440f2a19305Safresh1    is($HASH{key}, "val", 'Lexically exported hash is accessible');
441256a93a4Safresh1}
442256a93a4Safresh1
443*5486feefSafresh1# load_module
444*5486feefSafresh1{
445*5486feefSafresh1    use builtin qw( load_module );
446*5486feefSafresh1    use feature qw( try );
447*5486feefSafresh1    my ($ok, $e);
448*5486feefSafresh1
449*5486feefSafresh1    # Can't really test this sans string eval, as it's a compilation error:
450*5486feefSafresh1    eval 'load_module();';
451*5486feefSafresh1    $e = $@;
452*5486feefSafresh1    ok($e, 'load_module(); fails');
453*5486feefSafresh1    like($e, qr/^Not enough arguments for builtin::load_module at/, 'load_module(); fails with correct error');
454*5486feefSafresh1    eval 'load_module;';
455*5486feefSafresh1    $e = $@;
456*5486feefSafresh1    ok($e, 'load_module; fails');
457*5486feefSafresh1    like($e, qr/^Not enough arguments for builtin::load_module at/, 'load_module; fails with correct error');
458*5486feefSafresh1
459*5486feefSafresh1    # Failure to load module croaks
460*5486feefSafresh1    try {
461*5486feefSafresh1        load_module(undef);
462*5486feefSafresh1    } catch ($e) {
463*5486feefSafresh1        ok($e, 'load_module(undef) fails');
464*5486feefSafresh1        like($e, qr/^Usage: builtin::load_module\(defined string\)/, 'load_module(undef) fails with correct error');
465*5486feefSafresh1    };
466*5486feefSafresh1    try {
467*5486feefSafresh1        load_module(\"Foo");
468*5486feefSafresh1    } catch ($e) {
469*5486feefSafresh1        ok($e, 'load_module(\"Foo") fails');
470*5486feefSafresh1        like($e, qr/^Usage: builtin::load_module\(defined string\)/, 'load_module(\"Foo") fails with correct error');
471*5486feefSafresh1    };
472*5486feefSafresh1    try {
473*5486feefSafresh1        load_module(["Foo"]);
474*5486feefSafresh1    } catch ($e) {
475*5486feefSafresh1        ok($e, 'load_module(["Foo"]) fails');
476*5486feefSafresh1        like($e, qr/^Usage: builtin::load_module\(defined string\)/, 'load_module(["Foo"]) fails with correct error');
477*5486feefSafresh1    };
478*5486feefSafresh1    try {
479*5486feefSafresh1        load_module('5.36');
480*5486feefSafresh1    }
481*5486feefSafresh1    catch ($e) {
482*5486feefSafresh1        ok($e, 'load_module("5.36") fails');
483*5486feefSafresh1        like($e, qr/^Can't locate 5[.]36[.]pm in \@INC/, 'load_module("5.36") fails with correct error');
484*5486feefSafresh1    };
485*5486feefSafresh1    try {
486*5486feefSafresh1        load_module('v5.36');
487*5486feefSafresh1    }
488*5486feefSafresh1    catch ($e) {
489*5486feefSafresh1        ok($e, 'load_module("v5.36") fails');
490*5486feefSafresh1        like($e, qr/^Can't locate v5[.]36[.]pm in \@INC/, 'load_module("v5.36") fails with correct error');
491*5486feefSafresh1    };
492*5486feefSafresh1    try {
493*5486feefSafresh1        load_module("Dies");
494*5486feefSafresh1        fail('load_module("Dies") succeeded!');
495*5486feefSafresh1    }
496*5486feefSafresh1    catch ($e) {
497*5486feefSafresh1        ok($e, 'load_module("Dies") fails');
498*5486feefSafresh1        like($e, qr/^Can't locate Dies[.]pm in \@INC/, 'load_module("Dies") fails with correct error');
499*5486feefSafresh1    }
500*5486feefSafresh1    my $module_name = 'Dies';
501*5486feefSafresh1    try {
502*5486feefSafresh1        load_module($module_name);
503*5486feefSafresh1        fail('load_module($module_name) $module_name=Dies succeeded!');
504*5486feefSafresh1    }
505*5486feefSafresh1    catch ($e) {
506*5486feefSafresh1        ok($e, 'load_module($module_name) $module_name=Dies fails');
507*5486feefSafresh1        like($e, qr/^Can't locate Dies[.]pm in \@INC/, 'load_module($module_name) $module_name=Dies fails with correct error');
508*5486feefSafresh1    }
509*5486feefSafresh1    $module_name =~ m!(\w+)!;
510*5486feefSafresh1    try {
511*5486feefSafresh1        load_module($1);
512*5486feefSafresh1        fail('load_module($1) from $module_name=Dies succeeded!');
513*5486feefSafresh1    }
514*5486feefSafresh1    catch ($e) {
515*5486feefSafresh1        ok($e, 'load_module($1) from $module_name=Dies fails');
516*5486feefSafresh1        like($e, qr/^Can't locate Dies[.]pm in \@INC/, 'load_module($1) from $module_name=Dies fails with correct error');
517*5486feefSafresh1    }
518*5486feefSafresh1    "Dies" =~ m!(\w+)!;
519*5486feefSafresh1    try {
520*5486feefSafresh1        load_module($1);
521*5486feefSafresh1        fail('load_module($1) from "Dies" succeeded!');
522*5486feefSafresh1    }
523*5486feefSafresh1    catch ($e) {
524*5486feefSafresh1        ok($e, 'load_module($1) from "Dies" fails');
525*5486feefSafresh1        like($e, qr/^Can't locate Dies[.]pm in \@INC/, 'load_module($1) from "Dies" fails with correct error');
526*5486feefSafresh1    }
527*5486feefSafresh1
528*5486feefSafresh1    # Loading module goes well
529*5486feefSafresh1    my $ret;
530*5486feefSafresh1    try {
531*5486feefSafresh1        $ret = load_module("strict");
532*5486feefSafresh1        pass('load_module("strict") worked');
533*5486feefSafresh1        is($ret, "strict", 'load_module("strict") returned "strict"');
534*5486feefSafresh1    }
535*5486feefSafresh1    catch ($e) {
536*5486feefSafresh1        fail('load_module("strict") errored: ' . $e);
537*5486feefSafresh1    }
538*5486feefSafresh1    $module_name = 'strict';
539*5486feefSafresh1    try {
540*5486feefSafresh1        $ret = load_module($module_name);
541*5486feefSafresh1        pass('load_module($module_name) $module_name=strict worked');
542*5486feefSafresh1        is($ret, "strict", 'load_module($module_name) returned "strict"');
543*5486feefSafresh1    }
544*5486feefSafresh1    catch ($e) {
545*5486feefSafresh1        fail('load_module($module_name) $module_name=strict errored: ' . $e);
546*5486feefSafresh1    }
547*5486feefSafresh1    $module_name =~ m!(\w+)!;
548*5486feefSafresh1    try {
549*5486feefSafresh1        $ret = load_module($1);
550*5486feefSafresh1        pass('load_module($1) from $module_name=strict worked');
551*5486feefSafresh1        is($ret, "strict", 'load_module($1) from $module_name=strict returned "strict"');
552*5486feefSafresh1    }
553*5486feefSafresh1    catch ($e) {
554*5486feefSafresh1        fail('load_module($1) from $module_name=strict errored: ' . $e);
555*5486feefSafresh1    }
556*5486feefSafresh1    "strict" =~ m!(\w+)!;
557*5486feefSafresh1    try {
558*5486feefSafresh1        $ret = load_module($1);
559*5486feefSafresh1        pass('load_module($1) from "strict" worked');
560*5486feefSafresh1        is($ret, "strict", 'load_module($1) from "strict" returned "strict"');
561*5486feefSafresh1    }
562*5486feefSafresh1    catch ($e) {
563*5486feefSafresh1        fail('load_module($1) from "strict" errored: ' . $e);
564*5486feefSafresh1    }
565*5486feefSafresh1
566*5486feefSafresh1    # Slightly more complex, based on tie
567*5486feefSafresh1    {
568*5486feefSafresh1        package BuiltinTestTie {
569*5486feefSafresh1            sub TIESCALAR {
570*5486feefSafresh1                bless $_[1], $_[0];
571*5486feefSafresh1            }
572*5486feefSafresh1            sub FETCH {
573*5486feefSafresh1                ${$_[0]}
574*5486feefSafresh1            }
575*5486feefSafresh1        }
576*5486feefSafresh1        my $x;
577*5486feefSafresh1        tie my $y, BuiltinTestTie => \$x;
578*5486feefSafresh1        $x = "strict";
579*5486feefSafresh1        try {
580*5486feefSafresh1            $ret = load_module($y);
581*5486feefSafresh1            pass('load_module($y) from $y tied to $x=strict worked');
582*5486feefSafresh1            is($ret, "strict", 'load_module($y) from $y tied to $x=strict worked and returned "strict"');
583*5486feefSafresh1        }
584*5486feefSafresh1        catch ($e) {
585*5486feefSafresh1            fail('load_module($y) from $y tied to $x=strict failed: ' . $e);
586*5486feefSafresh1        };
587*5486feefSafresh1    }
588*5486feefSafresh1
589*5486feefSafresh1    # Can be used to import a symbol to the current namespace, too:
590*5486feefSafresh1    {
591*5486feefSafresh1        my $aref = [];
592*5486feefSafresh1        my $aref_stringified = "$aref";
593*5486feefSafresh1        my $got = eval '
594*5486feefSafresh1            BEGIN {
595*5486feefSafresh1                load_module("builtin")->import("stringify");
596*5486feefSafresh1            }
597*5486feefSafresh1            stringify($aref);
598*5486feefSafresh1        ';
599*5486feefSafresh1        if (my $error = $@) {
600*5486feefSafresh1            fail('load_module("builtin")->import("stringify") failed: ' . $error);
601*5486feefSafresh1        }
602*5486feefSafresh1        is($got, $aref_stringified, 'load_module("builtin")->import("stringify") works, stringifying $aref');
603*5486feefSafresh1    }
604*5486feefSafresh1}
605*5486feefSafresh1
606*5486feefSafresh1# version bundles
607*5486feefSafresh1{
608*5486feefSafresh1    use builtin ':5.39';
609*5486feefSafresh1    ok(true, 'true() is available from :5.39 bundle');
610*5486feefSafresh1
611*5486feefSafresh1    # parse errors
612*5486feefSafresh1    foreach my $bundle (qw( :x :5.x :5.36x :5.36.1000 :5.1000 :5.36.1.2 ),
613*5486feefSafresh1                        ":  +5.+39", ":  +5.+40. -10", ": 5.40", ":5 .40", ":5.+40",
614*5486feefSafresh1                        ":5.40 .0", ":5.40.-10", ":5.40\0") {
615*5486feefSafresh1        (my $pretty_bundle = $bundle) =~ s/([^[:print:]])/ sprintf("\\%o", ord $1) /ge;
616*5486feefSafresh1        ok(!defined eval "use builtin '$bundle';", $pretty_bundle.' is invalid bundle');
617*5486feefSafresh1        like($@, qr/^Invalid version bundle "\Q$pretty_bundle\E" at /);
618*5486feefSafresh1    }
619*5486feefSafresh1}
620*5486feefSafresh1
621*5486feefSafresh1# github #21981
622*5486feefSafresh1{
623*5486feefSafresh1    fresh_perl_is(<<'EOS', "", {}, "github 21981: panic in intro_my");
624*5486feefSafresh1use B;
625*5486feefSafresh1BEGIN { B::save_BEGINs; }
626*5486feefSafresh1use v5.39;
627*5486feefSafresh1EOS
628*5486feefSafresh1}
629*5486feefSafresh1
630*5486feefSafresh1# github #22542
631*5486feefSafresh1{
632*5486feefSafresh1    # some of these functions don't error at this point, but they might be updated
633*5486feefSafresh1    # and see the same problem we fix here
634*5486feefSafresh1    for my $func (qw(is_bool is_weak blessed refaddr reftype ceil floor is_tainted
635*5486feefSafresh1                     trim stringify created_as_string created_as_number)) {
636*5486feefSafresh1        my $arg =
637*5486feefSafresh1          $func =~ /ceil|floor|created_as/ ? "1.1" :
638*5486feefSafresh1          $func =~ /(^ref|blessed|is_weak)/ ? "\\1" : '"abc"';
639*5486feefSafresh1        fresh_perl_is(<<"EOS", "ok", {}, "goto $func");
640*5486feefSafresh1no warnings "experimental";
641*5486feefSafresh1sub f { goto &builtin::$func }
642*5486feefSafresh1f($arg);
643*5486feefSafresh1print "ok";
644*5486feefSafresh1EOS
645*5486feefSafresh1    }
646*5486feefSafresh1}
647*5486feefSafresh1
648256a93a4Safresh1# vim: tabstop=4 shiftwidth=4 expandtab autoindent softtabstop=4
649256a93a4Safresh1
650256a93a4Safresh1done_testing();
651