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