1#!/usr/bin/perl 2 3use strict; 4use Test::More tests => 17; 5use Config; 6use DynaLoader; 7use ExtUtils::CBuilder; 8 9my ($source_file, $obj_file, $lib_file); 10 11require_ok( 'ExtUtils::ParseXS' ); 12 13chdir('t') if -d 't'; 14 15use Carp; $SIG{__WARN__} = \&Carp::cluck; 16 17# Some trickery for Android. If we leave @INC as-is, it'll have '.' in it. 18# Later on, the 'require XSTest' end up in DynaLoader looking for 19# ./PL_XSTest.so, but unless our current directory happens to be in 20# LD_LIBRARY_PATH, Android's linker will never find the file, and the test 21# will fail. Instead, if we have all absolute paths, it'll just work. 22@INC = map { File::Spec->rel2abs($_) } @INC 23 if $^O =~ /android/; 24 25######################### 26 27{ # first block: try without linenumbers 28my $pxs = ExtUtils::ParseXS->new; 29# Try sending to filehandle 30tie *FH, 'Foo'; 31$pxs->process_file( filename => 'XSTest.xs', output => \*FH, prototypes => 1 ); 32like tied(*FH)->content, '/is_even/', "Test that output contains some text"; 33 34$source_file = 'XSTest.c'; 35 36# Try sending to file 37$pxs->process_file(filename => 'XSTest.xs', output => $source_file, prototypes => 0); 38ok -e $source_file, "Create an output file"; 39 40my $quiet = $ENV{PERL_CORE} && !$ENV{HARNESS_ACTIVE}; 41my $b = ExtUtils::CBuilder->new(quiet => $quiet); 42 43SKIP: { 44 skip "no compiler available", 2 45 if ! $b->have_compiler; 46 $obj_file = $b->compile( source => $source_file ); 47 ok $obj_file, "ExtUtils::CBuilder::compile() returned true value"; 48 ok -e $obj_file, "Make sure $obj_file exists"; 49} 50 51SKIP: { 52 skip "no dynamic loading", 5 53 if !$b->have_compiler || !$Config{usedl}; 54 my $module = 'XSTest'; 55 $lib_file = $b->link( objects => $obj_file, module_name => $module ); 56 ok $lib_file, "ExtUtils::CBuilder::link() returned true value"; 57 ok -e $lib_file, "Make sure $lib_file exists"; 58 59 eval {require XSTest}; 60 is $@, '', "No error message recorded, as expected"; 61 ok XSTest::is_even(8), 62 "Function created thru XS returned expected true value"; 63 ok !XSTest::is_even(9), 64 "Function created thru XS returned expected false value"; 65 66 # Win32 needs to close the DLL before it can unlink it, but unfortunately 67 # dl_unload_file was missing on Win32 prior to perl change #24679! 68 if ($^O eq 'MSWin32' and defined &DynaLoader::dl_unload_file) { 69 for (my $i = 0; $i < @DynaLoader::dl_modules; $i++) { 70 if ($DynaLoader::dl_modules[$i] eq $module) { 71 DynaLoader::dl_unload_file($DynaLoader::dl_librefs[$i]); 72 last; 73 } 74 } 75 } 76} 77 78my $seen = 0; 79open my $IN, '<', $source_file 80 or die "Unable to open $source_file: $!"; 81while (my $l = <$IN>) { 82 $seen++ if $l =~ m/#line\s1\s/; 83} 84is( $seen, 1, "Line numbers created in output file, as intended" ); 85{ 86 #rewind .c file and regexp it to look for code generation problems 87 local $/ = undef; 88 seek($IN, 0, 0); 89 my $filecontents = <$IN>; 90 my $good_T_BOOL_re = 91qr|\QXS_EUPXS(XS_XSTest_T_BOOL)\E 92.+? 93#line \d+\Q "XSTest.c" 94 ST(0) = boolSV(RETVAL); 95 } 96 XSRETURN(1); 97} 98\E|s; 99 like($filecontents, $good_T_BOOL_re, "T_BOOL doesn\'t have an extra sv_newmortal or sv_2mortal"); 100 101 my $good_T_BOOL_2_re = 102qr|\QXS_EUPXS(XS_XSTest_T_BOOL_2)\E 103.+? 104#line \d+\Q "XSTest.c" 105 sv_setsv(ST(0), boolSV(in)); 106 SvSETMAGIC(ST(0)); 107 } 108 XSRETURN(1); 109} 110\E|s; 111 like($filecontents, $good_T_BOOL_2_re, 'T_BOOL_2 doesn\'t have an extra sv_newmortal or sv_2mortal'); 112 my $good_T_BOOL_OUT_re = 113qr|\QXS_EUPXS(XS_XSTest_T_BOOL_OUT)\E 114.+? 115#line \d+\Q "XSTest.c" 116 sv_setsv(ST(0), boolSV(out)); 117 SvSETMAGIC(ST(0)); 118 } 119 XSRETURN_EMPTY; 120} 121\E|s; 122 like($filecontents, $good_T_BOOL_OUT_re, 'T_BOOL_OUT doesn\'t have an extra sv_newmortal or sv_2mortal'); 123 124} 125close $IN or die "Unable to close $source_file: $!"; 126 127unless ($ENV{PERL_NO_CLEANUP}) { 128 for ( $obj_file, $lib_file, $source_file) { 129 next unless defined $_; 130 1 while unlink $_; 131 } 132} 133} 134 135##################################################################### 136 137{ # second block: try with linenumbers 138my $pxs = ExtUtils::ParseXS->new; 139# Try sending to filehandle 140tie *FH, 'Foo'; 141$pxs->process_file( 142 filename => 'XSTest.xs', 143 output => \*FH, 144 prototypes => 1, 145 linenumbers => 0, 146); 147like tied(*FH)->content, '/is_even/', "Test that output contains some text"; 148 149$source_file = 'XSTest.c'; 150 151# Try sending to file 152$pxs->process_file( 153 filename => 'XSTest.xs', 154 output => $source_file, 155 prototypes => 0, 156 linenumbers => 0, 157); 158ok -e $source_file, "Create an output file"; 159 160 161my $seen = 0; 162open my $IN, '<', $source_file 163 or die "Unable to open $source_file: $!"; 164while (my $l = <$IN>) { 165 $seen++ if $l =~ m/#line\s1\s/; 166} 167close $IN or die "Unable to close $source_file: $!"; 168is( $seen, 0, "No linenumbers created in output file, as intended" ); 169 170unless ($ENV{PERL_NO_CLEANUP}) { 171 for ( $obj_file, $lib_file, $source_file) { 172 next unless defined $_; 173 1 while unlink $_; 174 } 175} 176} 177##################################################################### 178 179sub Foo::TIEHANDLE { bless {}, 'Foo' } 180sub Foo::PRINT { shift->{buf} .= join '', @_ } 181sub Foo::content { shift->{buf} } 182