xref: /openbsd-src/gnu/usr.bin/perl/ext/XS-APItest/t/autoload.t (revision 5759b3d249badf144a6240f7eec4dcf9df003e6b)
1898184e3Ssthen#!perl
2898184e3Ssthen
3898184e3Ssthen# This script tests not only the interface for XS AUTOLOAD routines to find
4898184e3Ssthen# out the sub name, but also that that interface does not interfere with
5898184e3Ssthen# prototypes, the way it did before 5.15.4.
6898184e3Ssthen
7898184e3Ssthenuse strict;
8898184e3Ssthenuse warnings;
9898184e3Ssthen
10898184e3Ssthenuse Test::More tests => 26;
11898184e3Ssthen
12898184e3Ssthenuse XS::APItest;
13898184e3Ssthen
14898184e3Ssthenis XS::APItest::AutoLoader::frob(), 'frob', 'name passed to XS AUTOLOAD';
15898184e3Ssthenis "XS::APItest::AutoLoader::fr\0b"->(), "fr\0b",
16898184e3Ssthen  'name with embedded null passed to XS AUTOLOAD';
17898184e3Ssthenis "XS::APItest::AutoLoader::fr\x{1ed9}b"->(), "fr\x{1ed9}b",
18898184e3Ssthen  'Unicode name passed to XS AUTOLOAD';
19898184e3Ssthen
20898184e3Ssthen*AUTOLOAD = *XS::APItest::AutoLoader::AUTOLOADp;
21898184e3Ssthen
22898184e3Ssthenis frob(), 'frob', 'name passed to XS AUTOLOAD with proto';
23898184e3Ssthenis prototype \&AUTOLOAD, '*$', 'prototype is unchanged';
24898184e3Ssthenis "fr\0b"->(), "fr\0b",
25898184e3Ssthen  'name with embedded null passed to XS AUTOLOAD with proto';
26898184e3Ssthenis prototype \&AUTOLOAD, '*$', 'proto unchanged after embedded-null call';
27898184e3Ssthenis "fr\x{1ed9}b"->(), "fr\x{1ed9}b",
28898184e3Ssthen  'Unicode name passed to XS AUTOLOAD with proto';
29898184e3Ssthenis prototype \&AUTOLOAD, '*$', 'prototype is unchanged after Unicode call';
30898184e3Ssthen
31898184e3Ssthen# Test that the prototype was preserved from the parser’s point of view
32898184e3Ssthen
33898184e3Ssthenok !eval "sub { ::AUTOLOAD(1) }",
34898184e3Ssthen   'parse failure due to AUTOLOAD prototype';
35898184e3Ssthenok eval "sub { ::AUTOLOAD(1,2) }", 'successful parse respecting prototype'
36898184e3Ssthen  or diag $@;
37898184e3Ssthen
38898184e3Ssthenpackage fribble { sub a { return 7 } }
39898184e3Ssthenno warnings 'once';
40898184e3Ssthen*a = \&AUTOLOAD;
41898184e3Ssthen'$'->();
42898184e3Ssthen# &a('fribble') will return '$'
43898184e3Ssthen# But if intuit_method does not see the (*...) proto, this compiles as
44898184e3Ssthen# fribble->a
45898184e3Ssthenno strict;
46898184e3Ssthenis eval 'a fribble, 3', '$', 'intuit_method sees * in AUTOLOAD proto'
47898184e3Ssthen  or diag $@;
48898184e3Ssthen
49898184e3Ssthen# precedence check
50898184e3Ssthen# *$ should parse as a list operator, but right now the AUTOLOAD
51898184e3Ssthen# sub name is $
52898184e3Ssthenis join(" ", eval 'a "b", "c"'), '$',
53898184e3Ssthen   'precedence determination respects prototype of AUTOLOAD sub';
54898184e3Ssthen
55898184e3Ssthen{
56898184e3Ssthen    my $w;
57898184e3Ssthen    local $SIG{__WARN__} = sub { $w .= shift };
58898184e3Ssthen    eval 'sub a($){}';
59898184e3Ssthen    like $w, qr/^Prototype mismatch: sub main::a \(\*\$\) vs \(\$\)/m,
60898184e3Ssthen        'proto warnings respect AUTOLOAD prototypes';
61898184e3Ssthen    undef $w;
62898184e3Ssthen    *a = \&AUTOLOAD;
63898184e3Ssthen    like $w, qr/^Prototype mismatch: sub main::a \(\$\) vs \(\*\$\)/m,
64898184e3Ssthen        'GV assignment proto warnings respect AUTOLOAD prototypes';
65898184e3Ssthen}
66898184e3Ssthen
67898184e3Ssthen
68898184e3Ssthen#
69898184e3Ssthen# This is a test for AUTOLOAD implemented as an XSUB.
70898184e3Ssthen# It tests that $AUTOLOAD is set correctly, including the
71898184e3Ssthen# case of inheritance.
72898184e3Ssthen#
73898184e3Ssthen# Rationale: Due to change ed850460, $AUTOLOAD is not currently set
74898184e3Ssthen# for XSUB AUTOLOADs at all.  Instead, as of adb5a9ae the PV of the
75898184e3Ssthen# AUTOLOAD XSUB is set to the name of the method. We cruelly test it
76898184e3Ssthen# regardless.
77898184e3Ssthen#
78898184e3Ssthen
79898184e3Ssthen# First, make sure we have the XS AUTOLOAD available for testing
80898184e3Ssthenok(XS::APItest::AUTOLOADtest->can('AUTOLOAD'), 'Test class ->can AUTOLOAD');
81898184e3Ssthen
82898184e3Ssthen# Used to communicate from the XS AUTOLOAD to Perl land
83*5759b3d2Safresh1our $the_method;
84898184e3Ssthen
85898184e3Ssthen# First, set up the Perl equivalent to what we're testing in
86898184e3Ssthen# XS so we have a comparison
87898184e3Ssthenpackage PerlBase;
88*5759b3d2Safresh1our $AUTOLOAD;
89898184e3Ssthensub AUTOLOAD {
90898184e3Ssthen  Test::More::ok(defined $AUTOLOAD);
91898184e3Ssthen  return 1 if not defined $AUTOLOAD;
92898184e3Ssthen  $main::the_method = $AUTOLOAD;
93898184e3Ssthen  return 0;
94898184e3Ssthen}
95898184e3Ssthen
96898184e3Ssthenpackage PerlDerived;
97*5759b3d2Safresh1our @ISA = qw(PerlBase);
98898184e3Ssthen
99898184e3Ssthenpackage Derived;
100*5759b3d2Safresh1our @ISA = qw(XS::APItest::AUTOLOADtest);
101898184e3Ssthen
102898184e3Ssthenpackage main;
103898184e3Ssthen
104898184e3Ssthen# Test Perl AUTOLOAD in base class directly
105898184e3Ssthen$the_method = undef;
106898184e3Ssthenis(PerlBase->Blah(), 0,
107898184e3Ssthen   "Perl AUTOLOAD gets called and returns success");
108898184e3Ssthenis($the_method, 'PerlBase::Blah',
109898184e3Ssthen   'Scalar set to correct class/method name');
110898184e3Ssthen
111898184e3Ssthen# Test Perl AUTOLOAD in derived class
112898184e3Ssthen$the_method = undef;
113898184e3Ssthenis(PerlDerived->Boo(), 0,
114898184e3Ssthen   'Perl AUTOLOAD on derived class gets called and returns success');
115898184e3Ssthenis($the_method, 'PerlDerived::Boo',
116898184e3Ssthen   'Scalar set to correct class/method name');
117898184e3Ssthen
118898184e3Ssthen# Test XS AUTOLOAD in base class directly
119898184e3Ssthen$the_method = undef;
120898184e3Ssthenis(XS::APItest::AUTOLOADtest->Blah(), 0,
121898184e3Ssthen     'XS AUTOLOAD gets called and returns success');
122898184e3Ssthenis($the_method, 'XS::APItest::AUTOLOADtest::Blah',
123898184e3Ssthen     'Scalar set to correct class/method name');
124898184e3Ssthen
125898184e3Ssthen# Test XS AUTOLOAD in derived class directly
126898184e3Ssthen$the_method = undef;
127898184e3Ssthenis(Derived->Foo(), 0,
128898184e3Ssthen     'XS AUTOLOAD gets called and returns success');
129898184e3Ssthenis($the_method, 'Derived::Foo',
130898184e3Ssthen     'Scalar set to correct class/method name');
131