1*0Sstevel@tonic-gate#!/usr/bin/perl -w 2*0Sstevel@tonic-gate 3*0Sstevel@tonic-gateBEGIN { 4*0Sstevel@tonic-gate if( $ENV{PERL_CORE} ) { 5*0Sstevel@tonic-gate chdir 't' if -d 't'; 6*0Sstevel@tonic-gate @INC = '../lib'; 7*0Sstevel@tonic-gate } 8*0Sstevel@tonic-gate use Config; 9*0Sstevel@tonic-gate unless ($Config{usedl}) { 10*0Sstevel@tonic-gate print "1..0 # no usedl, skipping\n"; 11*0Sstevel@tonic-gate exit 0; 12*0Sstevel@tonic-gate } 13*0Sstevel@tonic-gate} 14*0Sstevel@tonic-gate 15*0Sstevel@tonic-gate# use warnings; 16*0Sstevel@tonic-gateuse strict; 17*0Sstevel@tonic-gateuse ExtUtils::MakeMaker; 18*0Sstevel@tonic-gateuse ExtUtils::Constant qw (constant_types C_constant XS_constant autoload); 19*0Sstevel@tonic-gateuse File::Spec; 20*0Sstevel@tonic-gateuse Cwd; 21*0Sstevel@tonic-gate 22*0Sstevel@tonic-gatemy $do_utf_tests = $] > 5.006; 23*0Sstevel@tonic-gatemy $better_than_56 = $] > 5.007; 24*0Sstevel@tonic-gate# For debugging set this to 1. 25*0Sstevel@tonic-gatemy $keep_files = 0; 26*0Sstevel@tonic-gate$| = 1; 27*0Sstevel@tonic-gate 28*0Sstevel@tonic-gate# Because were are going to be changing directory before running Makefile.PL 29*0Sstevel@tonic-gatemy $perl = $^X; 30*0Sstevel@tonic-gate# 5.005 doesn't have new enough File::Spec to have rel2abs. But actually we 31*0Sstevel@tonic-gate# only need it when $^X isn't absolute, which is going to be 5.8.0 or later 32*0Sstevel@tonic-gate# (where ExtUtils::Constant is in the core, and tests against the uninstalled 33*0Sstevel@tonic-gate# perl) 34*0Sstevel@tonic-gate$perl = File::Spec->rel2abs ($perl) unless $] < 5.006; 35*0Sstevel@tonic-gate# ExtUtils::Constant::C_constant uses $^X inside a comment, and we want to 36*0Sstevel@tonic-gate# compare output to ensure that it is the same. We were probably run as ./perl 37*0Sstevel@tonic-gate# whereas we will run the child with the full path in $perl. So make $^X for 38*0Sstevel@tonic-gate# us the same as our child will see. 39*0Sstevel@tonic-gate$^X = $perl; 40*0Sstevel@tonic-gatemy $lib = $ENV{PERL_CORE} ? '../../../lib' : '../../blib/lib'; 41*0Sstevel@tonic-gatemy $runperl = "$perl \"-I$lib\""; 42*0Sstevel@tonic-gateprint "# perl=$perl\n"; 43*0Sstevel@tonic-gate 44*0Sstevel@tonic-gatemy $make = $Config{make}; 45*0Sstevel@tonic-gate$make = $ENV{MAKE} if exists $ENV{MAKE}; 46*0Sstevel@tonic-gateif ($^O eq 'MSWin32' && $make eq 'nmake') { $make .= " -nologo"; } 47*0Sstevel@tonic-gate 48*0Sstevel@tonic-gate# Renamed by make clean 49*0Sstevel@tonic-gatemy $makefile = ($^O eq 'VMS' ? 'descrip' : 'Makefile'); 50*0Sstevel@tonic-gatemy $makefile_ext = ($^O eq 'VMS' ? '.mms' : ''); 51*0Sstevel@tonic-gatemy $makefile_rename = $makefile . ($^O eq 'VMS' ? '.mms' : '.old'); 52*0Sstevel@tonic-gate 53*0Sstevel@tonic-gatemy $output = "output"; 54*0Sstevel@tonic-gatemy $package = "ExtTest"; 55*0Sstevel@tonic-gatemy $dir = "ext-$$"; 56*0Sstevel@tonic-gatemy $subdir = 0; 57*0Sstevel@tonic-gate# The real test counter. 58*0Sstevel@tonic-gatemy $realtest = 1; 59*0Sstevel@tonic-gate 60*0Sstevel@tonic-gatemy $orig_cwd = cwd; 61*0Sstevel@tonic-gatemy $updir = File::Spec->updir; 62*0Sstevel@tonic-gatedie "Can't get current directory: $!" unless defined $orig_cwd; 63*0Sstevel@tonic-gate 64*0Sstevel@tonic-gateprint "# $dir being created...\n"; 65*0Sstevel@tonic-gatemkdir $dir, 0777 or die "mkdir: $!\n"; 66*0Sstevel@tonic-gate 67*0Sstevel@tonic-gateEND { 68*0Sstevel@tonic-gate if (defined $orig_cwd and length $orig_cwd) { 69*0Sstevel@tonic-gate chdir $orig_cwd or die "Can't chdir back to '$orig_cwd': $!"; 70*0Sstevel@tonic-gate use File::Path; 71*0Sstevel@tonic-gate print "# $dir being removed...\n"; 72*0Sstevel@tonic-gate rmtree($dir) unless $keep_files; 73*0Sstevel@tonic-gate } else { 74*0Sstevel@tonic-gate # Can't get here. 75*0Sstevel@tonic-gate die "cwd at start was empty, but directory '$dir' was created" if $dir; 76*0Sstevel@tonic-gate } 77*0Sstevel@tonic-gate} 78*0Sstevel@tonic-gate 79*0Sstevel@tonic-gatechdir $dir or die $!; 80*0Sstevel@tonic-gatepush @INC, '../../lib', '../../../lib'; 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gatesub check_for_bonus_files { 83*0Sstevel@tonic-gate my $dir = shift; 84*0Sstevel@tonic-gate my %expect = map {($^O eq 'VMS' ? lc($_) : $_), 1} @_; 85*0Sstevel@tonic-gate 86*0Sstevel@tonic-gate my $fail; 87*0Sstevel@tonic-gate opendir DIR, $dir or die "opendir '$dir': $!"; 88*0Sstevel@tonic-gate while (defined (my $entry = readdir DIR)) { 89*0Sstevel@tonic-gate $entry =~ s/\.$// if $^O eq 'VMS'; # delete trailing dot that indicates no extension 90*0Sstevel@tonic-gate next if $expect{$entry}; 91*0Sstevel@tonic-gate print "# Extra file '$entry'\n"; 92*0Sstevel@tonic-gate $fail = 1; 93*0Sstevel@tonic-gate } 94*0Sstevel@tonic-gate 95*0Sstevel@tonic-gate closedir DIR or warn "closedir '.': $!"; 96*0Sstevel@tonic-gate if ($fail) { 97*0Sstevel@tonic-gate print "not ok $realtest\n"; 98*0Sstevel@tonic-gate } else { 99*0Sstevel@tonic-gate print "ok $realtest\n"; 100*0Sstevel@tonic-gate } 101*0Sstevel@tonic-gate $realtest++; 102*0Sstevel@tonic-gate} 103*0Sstevel@tonic-gate 104*0Sstevel@tonic-gatesub build_and_run { 105*0Sstevel@tonic-gate my ($tests, $expect, $files) = @_; 106*0Sstevel@tonic-gate my $core = $ENV{PERL_CORE} ? ' PERL_CORE=1' : ''; 107*0Sstevel@tonic-gate my @perlout = `$runperl Makefile.PL $core`; 108*0Sstevel@tonic-gate if ($?) { 109*0Sstevel@tonic-gate print "not ok $realtest # $runperl Makefile.PL failed: $?\n"; 110*0Sstevel@tonic-gate print "# $_" foreach @perlout; 111*0Sstevel@tonic-gate exit($?); 112*0Sstevel@tonic-gate } else { 113*0Sstevel@tonic-gate print "ok $realtest\n"; 114*0Sstevel@tonic-gate } 115*0Sstevel@tonic-gate $realtest++; 116*0Sstevel@tonic-gate 117*0Sstevel@tonic-gate if (-f "$makefile$makefile_ext") { 118*0Sstevel@tonic-gate print "ok $realtest\n"; 119*0Sstevel@tonic-gate } else { 120*0Sstevel@tonic-gate print "not ok $realtest\n"; 121*0Sstevel@tonic-gate } 122*0Sstevel@tonic-gate $realtest++; 123*0Sstevel@tonic-gate 124*0Sstevel@tonic-gate my @makeout; 125*0Sstevel@tonic-gate 126*0Sstevel@tonic-gate if ($^O eq 'VMS') { $make .= ' all'; } 127*0Sstevel@tonic-gate 128*0Sstevel@tonic-gate print "# make = '$make'\n"; 129*0Sstevel@tonic-gate @makeout = `$make`; 130*0Sstevel@tonic-gate if ($?) { 131*0Sstevel@tonic-gate print "not ok $realtest # $make failed: $?\n"; 132*0Sstevel@tonic-gate print "# $_" foreach @makeout; 133*0Sstevel@tonic-gate exit($?); 134*0Sstevel@tonic-gate } else { 135*0Sstevel@tonic-gate print "ok $realtest\n"; 136*0Sstevel@tonic-gate } 137*0Sstevel@tonic-gate $realtest++; 138*0Sstevel@tonic-gate 139*0Sstevel@tonic-gate if ($^O eq 'VMS') { $make =~ s{ all}{}; } 140*0Sstevel@tonic-gate 141*0Sstevel@tonic-gate if ($Config{usedl}) { 142*0Sstevel@tonic-gate print "ok $realtest # This is dynamic linking, so no need to make perl\n"; 143*0Sstevel@tonic-gate } else { 144*0Sstevel@tonic-gate my $makeperl = "$make perl"; 145*0Sstevel@tonic-gate print "# make = '$makeperl'\n"; 146*0Sstevel@tonic-gate @makeout = `$makeperl`; 147*0Sstevel@tonic-gate if ($?) { 148*0Sstevel@tonic-gate print "not ok $realtest # $makeperl failed: $?\n"; 149*0Sstevel@tonic-gate print "# $_" foreach @makeout; 150*0Sstevel@tonic-gate exit($?); 151*0Sstevel@tonic-gate } else { 152*0Sstevel@tonic-gate print "ok $realtest\n"; 153*0Sstevel@tonic-gate } 154*0Sstevel@tonic-gate } 155*0Sstevel@tonic-gate $realtest++; 156*0Sstevel@tonic-gate 157*0Sstevel@tonic-gate my $maketest = "$make test"; 158*0Sstevel@tonic-gate print "# make = '$maketest'\n"; 159*0Sstevel@tonic-gate 160*0Sstevel@tonic-gate @makeout = `$maketest`; 161*0Sstevel@tonic-gate 162*0Sstevel@tonic-gate if (open OUTPUT, "<$output") { 163*0Sstevel@tonic-gate local $/; # Slurp it - faster. 164*0Sstevel@tonic-gate print <OUTPUT>; 165*0Sstevel@tonic-gate close OUTPUT or print "# Close $output failed: $!\n"; 166*0Sstevel@tonic-gate } else { 167*0Sstevel@tonic-gate # Harness will report missing test results at this point. 168*0Sstevel@tonic-gate print "# Open <$output failed: $!\n"; 169*0Sstevel@tonic-gate } 170*0Sstevel@tonic-gate 171*0Sstevel@tonic-gate $realtest += $tests; 172*0Sstevel@tonic-gate if ($?) { 173*0Sstevel@tonic-gate print "not ok $realtest # $maketest failed: $?\n"; 174*0Sstevel@tonic-gate print "# $_" foreach @makeout; 175*0Sstevel@tonic-gate } else { 176*0Sstevel@tonic-gate print "ok $realtest - maketest\n"; 177*0Sstevel@tonic-gate } 178*0Sstevel@tonic-gate $realtest++; 179*0Sstevel@tonic-gate 180*0Sstevel@tonic-gate # -x is busted on Win32 < 5.6.1, so we emulate it. 181*0Sstevel@tonic-gate my $regen; 182*0Sstevel@tonic-gate if( $^O eq 'MSWin32' && $] <= 5.006001 ) { 183*0Sstevel@tonic-gate open(REGENTMP, ">regentmp") or die $!; 184*0Sstevel@tonic-gate open(XS, "$package.xs") or die $!; 185*0Sstevel@tonic-gate my $saw_shebang; 186*0Sstevel@tonic-gate while(<XS>) { 187*0Sstevel@tonic-gate $saw_shebang++ if /^#!.*/i ; 188*0Sstevel@tonic-gate print REGENTMP $_ if $saw_shebang; 189*0Sstevel@tonic-gate } 190*0Sstevel@tonic-gate close XS; close REGENTMP; 191*0Sstevel@tonic-gate $regen = `$runperl regentmp`; 192*0Sstevel@tonic-gate unlink 'regentmp'; 193*0Sstevel@tonic-gate } 194*0Sstevel@tonic-gate else { 195*0Sstevel@tonic-gate $regen = `$runperl -x $package.xs`; 196*0Sstevel@tonic-gate } 197*0Sstevel@tonic-gate if ($?) { 198*0Sstevel@tonic-gate print "not ok $realtest # $runperl -x $package.xs failed: $?\n"; 199*0Sstevel@tonic-gate } else { 200*0Sstevel@tonic-gate print "ok $realtest - regen\n"; 201*0Sstevel@tonic-gate } 202*0Sstevel@tonic-gate $realtest++; 203*0Sstevel@tonic-gate 204*0Sstevel@tonic-gate if ($expect eq $regen) { 205*0Sstevel@tonic-gate print "ok $realtest - regen worked\n"; 206*0Sstevel@tonic-gate } else { 207*0Sstevel@tonic-gate print "not ok $realtest - regen worked\n"; 208*0Sstevel@tonic-gate # open FOO, ">expect"; print FOO $expect; 209*0Sstevel@tonic-gate # open FOO, ">regen"; print FOO $regen; close FOO; 210*0Sstevel@tonic-gate } 211*0Sstevel@tonic-gate $realtest++; 212*0Sstevel@tonic-gate 213*0Sstevel@tonic-gate my $makeclean = "$make clean"; 214*0Sstevel@tonic-gate print "# make = '$makeclean'\n"; 215*0Sstevel@tonic-gate @makeout = `$makeclean`; 216*0Sstevel@tonic-gate if ($?) { 217*0Sstevel@tonic-gate print "not ok $realtest # $make failed: $?\n"; 218*0Sstevel@tonic-gate print "# $_" foreach @makeout; 219*0Sstevel@tonic-gate } else { 220*0Sstevel@tonic-gate print "ok $realtest\n"; 221*0Sstevel@tonic-gate } 222*0Sstevel@tonic-gate $realtest++; 223*0Sstevel@tonic-gate 224*0Sstevel@tonic-gate check_for_bonus_files ('.', @$files, $output, $makefile_rename, '.', '..'); 225*0Sstevel@tonic-gate 226*0Sstevel@tonic-gate rename $makefile_rename, $makefile 227*0Sstevel@tonic-gate or die "Can't rename '$makefile_rename' to '$makefile': $!"; 228*0Sstevel@tonic-gate 229*0Sstevel@tonic-gate unlink $output or warn "Can't unlink '$output': $!"; 230*0Sstevel@tonic-gate 231*0Sstevel@tonic-gate # Need to make distclean to remove ../../lib/ExtTest.pm 232*0Sstevel@tonic-gate my $makedistclean = "$make distclean"; 233*0Sstevel@tonic-gate print "# make = '$makedistclean'\n"; 234*0Sstevel@tonic-gate @makeout = `$makedistclean`; 235*0Sstevel@tonic-gate if ($?) { 236*0Sstevel@tonic-gate print "not ok $realtest # $make failed: $?\n"; 237*0Sstevel@tonic-gate print "# $_" foreach @makeout; 238*0Sstevel@tonic-gate } else { 239*0Sstevel@tonic-gate print "ok $realtest\n"; 240*0Sstevel@tonic-gate } 241*0Sstevel@tonic-gate $realtest++; 242*0Sstevel@tonic-gate 243*0Sstevel@tonic-gate check_for_bonus_files ('.', @$files, '.', '..'); 244*0Sstevel@tonic-gate 245*0Sstevel@tonic-gate unless ($keep_files) { 246*0Sstevel@tonic-gate foreach (@$files) { 247*0Sstevel@tonic-gate unlink $_ or warn "unlink $_: $!"; 248*0Sstevel@tonic-gate } 249*0Sstevel@tonic-gate } 250*0Sstevel@tonic-gate 251*0Sstevel@tonic-gate check_for_bonus_files ('.', '.', '..'); 252*0Sstevel@tonic-gate} 253*0Sstevel@tonic-gate 254*0Sstevel@tonic-gatesub Makefile_PL { 255*0Sstevel@tonic-gate my $package = shift; 256*0Sstevel@tonic-gate ################ Makefile.PL 257*0Sstevel@tonic-gate # We really need a Makefile.PL because make test for a no dynamic linking perl 258*0Sstevel@tonic-gate # will run Makefile.PL again as part of the "make perl" target. 259*0Sstevel@tonic-gate my $makefilePL = "Makefile.PL"; 260*0Sstevel@tonic-gate open FH, ">$makefilePL" or die "open >$makefilePL: $!\n"; 261*0Sstevel@tonic-gate print FH <<"EOT"; 262*0Sstevel@tonic-gate#!$perl -w 263*0Sstevel@tonic-gateuse ExtUtils::MakeMaker; 264*0Sstevel@tonic-gateWriteMakefile( 265*0Sstevel@tonic-gate 'NAME' => "$package", 266*0Sstevel@tonic-gate 'VERSION_FROM' => "$package.pm", # finds \$VERSION 267*0Sstevel@tonic-gate (\$] >= 5.005 ? 268*0Sstevel@tonic-gate (#ABSTRACT_FROM => "$package.pm", # XXX add this 269*0Sstevel@tonic-gate AUTHOR => "$0") : ()) 270*0Sstevel@tonic-gate ); 271*0Sstevel@tonic-gateEOT 272*0Sstevel@tonic-gate 273*0Sstevel@tonic-gate close FH or die "close $makefilePL: $!\n"; 274*0Sstevel@tonic-gate return $makefilePL; 275*0Sstevel@tonic-gate} 276*0Sstevel@tonic-gate 277*0Sstevel@tonic-gatesub MANIFEST { 278*0Sstevel@tonic-gate my (@files) = @_; 279*0Sstevel@tonic-gate ################ MANIFEST 280*0Sstevel@tonic-gate # We really need a MANIFEST because make distclean checks it. 281*0Sstevel@tonic-gate my $manifest = "MANIFEST"; 282*0Sstevel@tonic-gate push @files, $manifest; 283*0Sstevel@tonic-gate open FH, ">$manifest" or die "open >$manifest: $!\n"; 284*0Sstevel@tonic-gate print FH "$_\n" foreach @files; 285*0Sstevel@tonic-gate close FH or die "close $manifest: $!\n"; 286*0Sstevel@tonic-gate return @files; 287*0Sstevel@tonic-gate} 288*0Sstevel@tonic-gate 289*0Sstevel@tonic-gatesub write_and_run_extension { 290*0Sstevel@tonic-gate my ($name, $items, $export_names, $package, $header, $testfile, $num_tests) 291*0Sstevel@tonic-gate = @_; 292*0Sstevel@tonic-gate my $types = {}; 293*0Sstevel@tonic-gate my $constant_types = constant_types(); # macro defs 294*0Sstevel@tonic-gate my $C_constant = join "\n", 295*0Sstevel@tonic-gate C_constant ($package, undef, "IV", $types, undef, undef, @$items); 296*0Sstevel@tonic-gate my $XS_constant = XS_constant ($package, $types); # XS for ExtTest::constant 297*0Sstevel@tonic-gate 298*0Sstevel@tonic-gate my $expect = $constant_types . $C_constant . 299*0Sstevel@tonic-gate "\n#### XS Section:\n" . $XS_constant; 300*0Sstevel@tonic-gate 301*0Sstevel@tonic-gate print "# $name\n# $dir/$subdir being created...\n"; 302*0Sstevel@tonic-gate mkdir $subdir, 0777 or die "mkdir: $!\n"; 303*0Sstevel@tonic-gate chdir $subdir or die $!; 304*0Sstevel@tonic-gate 305*0Sstevel@tonic-gate my @files; 306*0Sstevel@tonic-gate 307*0Sstevel@tonic-gate ################ Header 308*0Sstevel@tonic-gate my $header_name = "test.h"; 309*0Sstevel@tonic-gate push @files, $header_name; 310*0Sstevel@tonic-gate open FH, ">$header_name" or die "open >$header_name: $!\n"; 311*0Sstevel@tonic-gate print FH $header or die $!; 312*0Sstevel@tonic-gate close FH or die "close $header_name: $!\n"; 313*0Sstevel@tonic-gate 314*0Sstevel@tonic-gate ################ XS 315*0Sstevel@tonic-gate my $xs = "$package.xs"; 316*0Sstevel@tonic-gate push @files, $xs; 317*0Sstevel@tonic-gate open FH, ">$xs" or die "open >$xs: $!\n"; 318*0Sstevel@tonic-gate 319*0Sstevel@tonic-gate print FH <<'EOT'; 320*0Sstevel@tonic-gate#include "EXTERN.h" 321*0Sstevel@tonic-gate#include "perl.h" 322*0Sstevel@tonic-gate#include "XSUB.h" 323*0Sstevel@tonic-gateEOT 324*0Sstevel@tonic-gate 325*0Sstevel@tonic-gate # XXX Here doc these: 326*0Sstevel@tonic-gate print FH "#include \"$header_name\"\n\n"; 327*0Sstevel@tonic-gate print FH $constant_types; 328*0Sstevel@tonic-gate print FH $C_constant, "\n"; 329*0Sstevel@tonic-gate print FH "MODULE = $package PACKAGE = $package\n"; 330*0Sstevel@tonic-gate print FH "PROTOTYPES: ENABLE\n"; 331*0Sstevel@tonic-gate print FH $XS_constant; 332*0Sstevel@tonic-gate close FH or die "close $xs: $!\n"; 333*0Sstevel@tonic-gate 334*0Sstevel@tonic-gate ################ PM 335*0Sstevel@tonic-gate my $pm = "$package.pm"; 336*0Sstevel@tonic-gate push @files, $pm; 337*0Sstevel@tonic-gate open FH, ">$pm" or die "open >$pm: $!\n"; 338*0Sstevel@tonic-gate print FH "package $package;\n"; 339*0Sstevel@tonic-gate print FH "use $];\n"; 340*0Sstevel@tonic-gate 341*0Sstevel@tonic-gate print FH <<'EOT'; 342*0Sstevel@tonic-gate 343*0Sstevel@tonic-gateuse strict; 344*0Sstevel@tonic-gateEOT 345*0Sstevel@tonic-gate printf FH "use warnings;\n" unless $] < 5.006; 346*0Sstevel@tonic-gate print FH <<'EOT'; 347*0Sstevel@tonic-gateuse Carp; 348*0Sstevel@tonic-gate 349*0Sstevel@tonic-gaterequire Exporter; 350*0Sstevel@tonic-gaterequire DynaLoader; 351*0Sstevel@tonic-gateuse vars qw ($VERSION @ISA @EXPORT_OK $AUTOLOAD); 352*0Sstevel@tonic-gate 353*0Sstevel@tonic-gate$VERSION = '0.01'; 354*0Sstevel@tonic-gate@ISA = qw(Exporter DynaLoader); 355*0Sstevel@tonic-gateEOT 356*0Sstevel@tonic-gate # Having this qw( in the here doc confuses cperl mode far too much to be 357*0Sstevel@tonic-gate # helpful. And I'm using cperl mode to edit this, even if you're not :-) 358*0Sstevel@tonic-gate print FH "\@EXPORT_OK = qw(\n"; 359*0Sstevel@tonic-gate 360*0Sstevel@tonic-gate # Print the names of all our autoloaded constants 361*0Sstevel@tonic-gate print FH "\t$_\n" foreach (@$export_names); 362*0Sstevel@tonic-gate print FH ");\n"; 363*0Sstevel@tonic-gate # Print the AUTOLOAD subroutine ExtUtils::Constant generated for us 364*0Sstevel@tonic-gate print FH autoload ($package, $]); 365*0Sstevel@tonic-gate print FH "bootstrap $package \$VERSION;\n1;\n__END__\n"; 366*0Sstevel@tonic-gate close FH or die "close $pm: $!\n"; 367*0Sstevel@tonic-gate 368*0Sstevel@tonic-gate ################ test.pl 369*0Sstevel@tonic-gate my $testpl = "test.pl"; 370*0Sstevel@tonic-gate push @files, $testpl; 371*0Sstevel@tonic-gate open FH, ">$testpl" or die "open >$testpl: $!\n"; 372*0Sstevel@tonic-gate # Standard test header (need an option to suppress this?) 373*0Sstevel@tonic-gate print FH <<"EOT" or die $!; 374*0Sstevel@tonic-gateuse strict; 375*0Sstevel@tonic-gateuse $package qw(@$export_names); 376*0Sstevel@tonic-gate 377*0Sstevel@tonic-gateprint "1..2\n"; 378*0Sstevel@tonic-gateif (open OUTPUT, ">$output") { 379*0Sstevel@tonic-gate print "ok 1\n"; 380*0Sstevel@tonic-gate select OUTPUT; 381*0Sstevel@tonic-gate} else { 382*0Sstevel@tonic-gate print "not ok 1 # Failed to open '$output': \$!\n"; 383*0Sstevel@tonic-gate exit 1; 384*0Sstevel@tonic-gate} 385*0Sstevel@tonic-gateEOT 386*0Sstevel@tonic-gate print FH $testfile or die $!; 387*0Sstevel@tonic-gate print FH <<"EOT" or die $!; 388*0Sstevel@tonic-gateselect STDOUT; 389*0Sstevel@tonic-gateif (close OUTPUT) { 390*0Sstevel@tonic-gate print "ok 2\n"; 391*0Sstevel@tonic-gate} else { 392*0Sstevel@tonic-gate print "not ok 2 # Failed to close '$output': \$!\n"; 393*0Sstevel@tonic-gate} 394*0Sstevel@tonic-gateEOT 395*0Sstevel@tonic-gate close FH or die "close $testpl: $!\n"; 396*0Sstevel@tonic-gate 397*0Sstevel@tonic-gate push @files, Makefile_PL($package); 398*0Sstevel@tonic-gate @files = MANIFEST (@files); 399*0Sstevel@tonic-gate 400*0Sstevel@tonic-gate build_and_run ($num_tests, $expect, \@files); 401*0Sstevel@tonic-gate 402*0Sstevel@tonic-gate chdir $updir or die "chdir '$updir': $!"; 403*0Sstevel@tonic-gate ++$subdir; 404*0Sstevel@tonic-gate} 405*0Sstevel@tonic-gate# Tests are arrayrefs of the form 406*0Sstevel@tonic-gate# $name, [items], [export_names], $package, $header, $testfile, $num_tests 407*0Sstevel@tonic-gatemy @tests; 408*0Sstevel@tonic-gatemy $before_tests = 4; # Number of "ok"s emitted to build extension 409*0Sstevel@tonic-gatemy $after_tests = 8; # Number of "ok"s emitted after make test run 410*0Sstevel@tonic-gatemy $dummytest = 1; 411*0Sstevel@tonic-gate 412*0Sstevel@tonic-gatemy $here; 413*0Sstevel@tonic-gatesub start_tests { 414*0Sstevel@tonic-gate $dummytest += $before_tests; 415*0Sstevel@tonic-gate $here = $dummytest; 416*0Sstevel@tonic-gate} 417*0Sstevel@tonic-gatesub end_tests { 418*0Sstevel@tonic-gate my ($name, $items, $export_names, $header, $testfile) = @_; 419*0Sstevel@tonic-gate push @tests, [$name, $items, $export_names, $package, $header, $testfile, 420*0Sstevel@tonic-gate $dummytest - $here]; 421*0Sstevel@tonic-gate $dummytest += $after_tests; 422*0Sstevel@tonic-gate} 423*0Sstevel@tonic-gate 424*0Sstevel@tonic-gatemy $pound; 425*0Sstevel@tonic-gateif (ord('A') == 193) { # EBCDIC platform 426*0Sstevel@tonic-gate $pound = chr 177; # A pound sign. (Currency) 427*0Sstevel@tonic-gate} else { # ASCII platform 428*0Sstevel@tonic-gate $pound = chr 163; # A pound sign. (Currency) 429*0Sstevel@tonic-gate} 430*0Sstevel@tonic-gatemy @common_items = ( 431*0Sstevel@tonic-gate {name=>"perl", type=>"PV",}, 432*0Sstevel@tonic-gate {name=>"*/", type=>"PV", value=>'"CLOSE"', macro=>1}, 433*0Sstevel@tonic-gate {name=>"/*", type=>"PV", value=>'"OPEN"', macro=>1}, 434*0Sstevel@tonic-gate {name=>$pound, type=>"PV", value=>'"Sterling"', macro=>1}, 435*0Sstevel@tonic-gate ); 436*0Sstevel@tonic-gate 437*0Sstevel@tonic-gate{ 438*0Sstevel@tonic-gate # Simple tests 439*0Sstevel@tonic-gate start_tests(); 440*0Sstevel@tonic-gate my $parent_rfc1149 = 441*0Sstevel@tonic-gate 'A Standard for the Transmission of IP Datagrams on Avian Carriers'; 442*0Sstevel@tonic-gate # Test the code that generates 1 and 2 letter name comparisons. 443*0Sstevel@tonic-gate my %compass = ( 444*0Sstevel@tonic-gate N => 0, 'NE' => 45, E => 90, SE => 135, 445*0Sstevel@tonic-gate S => 180, SW => 225, W => 270, NW => 315 446*0Sstevel@tonic-gate ); 447*0Sstevel@tonic-gate 448*0Sstevel@tonic-gate my $header = << "EOT"; 449*0Sstevel@tonic-gate#define FIVE 5 450*0Sstevel@tonic-gate#define OK6 "ok 6\\n" 451*0Sstevel@tonic-gate#define OK7 1 452*0Sstevel@tonic-gate#define FARTHING 0.25 453*0Sstevel@tonic-gate#define NOT_ZERO 1 454*0Sstevel@tonic-gate#define Yes 0 455*0Sstevel@tonic-gate#define No 1 456*0Sstevel@tonic-gate#define Undef 1 457*0Sstevel@tonic-gate#define RFC1149 "$parent_rfc1149" 458*0Sstevel@tonic-gate#undef NOTDEF 459*0Sstevel@tonic-gate#define perl "rules" 460*0Sstevel@tonic-gateEOT 461*0Sstevel@tonic-gate 462*0Sstevel@tonic-gate while (my ($point, $bearing) = each %compass) { 463*0Sstevel@tonic-gate $header .= "#define $point $bearing\n" 464*0Sstevel@tonic-gate } 465*0Sstevel@tonic-gate 466*0Sstevel@tonic-gate my @items = ("FIVE", {name=>"OK6", type=>"PV",}, 467*0Sstevel@tonic-gate {name=>"OK7", type=>"PVN", 468*0Sstevel@tonic-gate value=>['"not ok 7\\n\\0ok 7\\n"', 15]}, 469*0Sstevel@tonic-gate {name => "FARTHING", type=>"NV"}, 470*0Sstevel@tonic-gate {name => "NOT_ZERO", type=>"UV", value=>"~(UV)0"}, 471*0Sstevel@tonic-gate {name => "OPEN", type=>"PV", value=>'"/*"', macro=>1}, 472*0Sstevel@tonic-gate {name => "CLOSE", type=>"PV", value=>'"*/"', 473*0Sstevel@tonic-gate macro=>["#if 1\n", "#endif\n"]}, 474*0Sstevel@tonic-gate {name => "ANSWER", default=>["UV", 42]}, "NOTDEF", 475*0Sstevel@tonic-gate {name => "Yes", type=>"YES"}, 476*0Sstevel@tonic-gate {name => "No", type=>"NO"}, 477*0Sstevel@tonic-gate {name => "Undef", type=>"UNDEF"}, 478*0Sstevel@tonic-gate # OK. It wasn't really designed to allow the creation of dual valued 479*0Sstevel@tonic-gate # constants. 480*0Sstevel@tonic-gate # It was more for INADDR_ANY INADDR_BROADCAST INADDR_LOOPBACK INADDR_NONE 481*0Sstevel@tonic-gate {name=>"RFC1149", type=>"SV", value=>"sv_2mortal(temp_sv)", 482*0Sstevel@tonic-gate pre=>"SV *temp_sv = newSVpv(RFC1149, 0); " 483*0Sstevel@tonic-gate . "(void) SvUPGRADE(temp_sv,SVt_PVIV); SvIOK_on(temp_sv); " 484*0Sstevel@tonic-gate . "SvIVX(temp_sv) = 1149;"}, 485*0Sstevel@tonic-gate ); 486*0Sstevel@tonic-gate 487*0Sstevel@tonic-gate push @items, $_ foreach keys %compass; 488*0Sstevel@tonic-gate 489*0Sstevel@tonic-gate # Automatically compile the list of all the macro names, and make them 490*0Sstevel@tonic-gate # exported constants. 491*0Sstevel@tonic-gate my @export_names = map {(ref $_) ? $_->{name} : $_} @items; 492*0Sstevel@tonic-gate 493*0Sstevel@tonic-gate # Exporter::Heavy (currently) isn't able to export the last 3 of these: 494*0Sstevel@tonic-gate push @items, @common_items; 495*0Sstevel@tonic-gate 496*0Sstevel@tonic-gate # XXX there are hardwired still. 497*0Sstevel@tonic-gate my $test_body = <<'EOT'; 498*0Sstevel@tonic-gate# What follows goes to the temporary file. 499*0Sstevel@tonic-gate# IV 500*0Sstevel@tonic-gatemy $five = FIVE; 501*0Sstevel@tonic-gateif ($five == 5) { 502*0Sstevel@tonic-gate print "ok 5\n"; 503*0Sstevel@tonic-gate} else { 504*0Sstevel@tonic-gate print "not ok 5 # \$five\n"; 505*0Sstevel@tonic-gate} 506*0Sstevel@tonic-gate 507*0Sstevel@tonic-gate# PV 508*0Sstevel@tonic-gateprint OK6; 509*0Sstevel@tonic-gate 510*0Sstevel@tonic-gate# PVN containing embedded \0s 511*0Sstevel@tonic-gate$_ = OK7; 512*0Sstevel@tonic-gates/.*\0//s; 513*0Sstevel@tonic-gateprint; 514*0Sstevel@tonic-gate 515*0Sstevel@tonic-gate# NV 516*0Sstevel@tonic-gatemy $farthing = FARTHING; 517*0Sstevel@tonic-gateif ($farthing == 0.25) { 518*0Sstevel@tonic-gate print "ok 8\n"; 519*0Sstevel@tonic-gate} else { 520*0Sstevel@tonic-gate print "not ok 8 # $farthing\n"; 521*0Sstevel@tonic-gate} 522*0Sstevel@tonic-gate 523*0Sstevel@tonic-gate# UV 524*0Sstevel@tonic-gatemy $not_zero = NOT_ZERO; 525*0Sstevel@tonic-gateif ($not_zero > 0 && $not_zero == ~0) { 526*0Sstevel@tonic-gate print "ok 9\n"; 527*0Sstevel@tonic-gate} else { 528*0Sstevel@tonic-gate print "not ok 9 # \$not_zero=$not_zero ~0=" . (~0) . "\n"; 529*0Sstevel@tonic-gate} 530*0Sstevel@tonic-gate 531*0Sstevel@tonic-gate# Value includes a "*/" in an attempt to bust out of a C comment. 532*0Sstevel@tonic-gate# Also tests custom cpp #if clauses 533*0Sstevel@tonic-gatemy $close = CLOSE; 534*0Sstevel@tonic-gateif ($close eq '*/') { 535*0Sstevel@tonic-gate print "ok 10\n"; 536*0Sstevel@tonic-gate} else { 537*0Sstevel@tonic-gate print "not ok 10 # \$close='$close'\n"; 538*0Sstevel@tonic-gate} 539*0Sstevel@tonic-gate 540*0Sstevel@tonic-gate# Default values if macro not defined. 541*0Sstevel@tonic-gatemy $answer = ANSWER; 542*0Sstevel@tonic-gateif ($answer == 42) { 543*0Sstevel@tonic-gate print "ok 11\n"; 544*0Sstevel@tonic-gate} else { 545*0Sstevel@tonic-gate print "not ok 11 # What do you get if you multiply six by nine? '$answer'\n"; 546*0Sstevel@tonic-gate} 547*0Sstevel@tonic-gate 548*0Sstevel@tonic-gate# not defined macro 549*0Sstevel@tonic-gatemy $notdef = eval { NOTDEF; }; 550*0Sstevel@tonic-gateif (defined $notdef) { 551*0Sstevel@tonic-gate print "not ok 12 # \$notdef='$notdef'\n"; 552*0Sstevel@tonic-gate} elsif ($@ !~ /Your vendor has not defined ExtTest macro NOTDEF/) { 553*0Sstevel@tonic-gate print "not ok 12 # \$@='$@'\n"; 554*0Sstevel@tonic-gate} else { 555*0Sstevel@tonic-gate print "ok 12\n"; 556*0Sstevel@tonic-gate} 557*0Sstevel@tonic-gate 558*0Sstevel@tonic-gate# not a macro 559*0Sstevel@tonic-gatemy $notthere = eval { &ExtTest::NOTTHERE; }; 560*0Sstevel@tonic-gateif (defined $notthere) { 561*0Sstevel@tonic-gate print "not ok 13 # \$notthere='$notthere'\n"; 562*0Sstevel@tonic-gate} elsif ($@ !~ /NOTTHERE is not a valid ExtTest macro/) { 563*0Sstevel@tonic-gate chomp $@; 564*0Sstevel@tonic-gate print "not ok 13 # \$@='$@'\n"; 565*0Sstevel@tonic-gate} else { 566*0Sstevel@tonic-gate print "ok 13\n"; 567*0Sstevel@tonic-gate} 568*0Sstevel@tonic-gate 569*0Sstevel@tonic-gate# Truth 570*0Sstevel@tonic-gatemy $yes = Yes; 571*0Sstevel@tonic-gateif ($yes) { 572*0Sstevel@tonic-gate print "ok 14\n"; 573*0Sstevel@tonic-gate} else { 574*0Sstevel@tonic-gate print "not ok 14 # $yes='\$yes'\n"; 575*0Sstevel@tonic-gate} 576*0Sstevel@tonic-gate 577*0Sstevel@tonic-gate# Falsehood 578*0Sstevel@tonic-gatemy $no = No; 579*0Sstevel@tonic-gateif (defined $no and !$no) { 580*0Sstevel@tonic-gate print "ok 15\n"; 581*0Sstevel@tonic-gate} else { 582*0Sstevel@tonic-gate print "not ok 15 # \$no=" . defined ($no) ? "'$no'\n" : "undef\n"; 583*0Sstevel@tonic-gate} 584*0Sstevel@tonic-gate 585*0Sstevel@tonic-gate# Undef 586*0Sstevel@tonic-gatemy $undef = Undef; 587*0Sstevel@tonic-gateunless (defined $undef) { 588*0Sstevel@tonic-gate print "ok 16\n"; 589*0Sstevel@tonic-gate} else { 590*0Sstevel@tonic-gate print "not ok 16 # \$undef='$undef'\n"; 591*0Sstevel@tonic-gate} 592*0Sstevel@tonic-gate 593*0Sstevel@tonic-gate# invalid macro (chosen to look like a mix up between No and SW) 594*0Sstevel@tonic-gate$notdef = eval { &ExtTest::So }; 595*0Sstevel@tonic-gateif (defined $notdef) { 596*0Sstevel@tonic-gate print "not ok 17 # \$notdef='$notdef'\n"; 597*0Sstevel@tonic-gate} elsif ($@ !~ /^So is not a valid ExtTest macro/) { 598*0Sstevel@tonic-gate print "not ok 17 # \$@='$@'\n"; 599*0Sstevel@tonic-gate} else { 600*0Sstevel@tonic-gate print "ok 17\n"; 601*0Sstevel@tonic-gate} 602*0Sstevel@tonic-gate 603*0Sstevel@tonic-gate# invalid defined macro 604*0Sstevel@tonic-gate$notdef = eval { &ExtTest::EW }; 605*0Sstevel@tonic-gateif (defined $notdef) { 606*0Sstevel@tonic-gate print "not ok 18 # \$notdef='$notdef'\n"; 607*0Sstevel@tonic-gate} elsif ($@ !~ /^EW is not a valid ExtTest macro/) { 608*0Sstevel@tonic-gate print "not ok 18 # \$@='$@'\n"; 609*0Sstevel@tonic-gate} else { 610*0Sstevel@tonic-gate print "ok 18\n"; 611*0Sstevel@tonic-gate} 612*0Sstevel@tonic-gate 613*0Sstevel@tonic-gatemy %compass = ( 614*0Sstevel@tonic-gateEOT 615*0Sstevel@tonic-gate 616*0Sstevel@tonic-gatewhile (my ($point, $bearing) = each %compass) { 617*0Sstevel@tonic-gate $test_body .= "'$point' => $bearing, " 618*0Sstevel@tonic-gate} 619*0Sstevel@tonic-gate 620*0Sstevel@tonic-gate$test_body .= <<'EOT'; 621*0Sstevel@tonic-gate 622*0Sstevel@tonic-gate); 623*0Sstevel@tonic-gate 624*0Sstevel@tonic-gatemy $fail; 625*0Sstevel@tonic-gatewhile (my ($point, $bearing) = each %compass) { 626*0Sstevel@tonic-gate my $val = eval $point; 627*0Sstevel@tonic-gate if ($@) { 628*0Sstevel@tonic-gate print "# $point: \$@='$@'\n"; 629*0Sstevel@tonic-gate $fail = 1; 630*0Sstevel@tonic-gate } elsif (!defined $bearing) { 631*0Sstevel@tonic-gate print "# $point: \$val=undef\n"; 632*0Sstevel@tonic-gate $fail = 1; 633*0Sstevel@tonic-gate } elsif ($val != $bearing) { 634*0Sstevel@tonic-gate print "# $point: \$val=$val, not $bearing\n"; 635*0Sstevel@tonic-gate $fail = 1; 636*0Sstevel@tonic-gate } 637*0Sstevel@tonic-gate} 638*0Sstevel@tonic-gateif ($fail) { 639*0Sstevel@tonic-gate print "not ok 19\n"; 640*0Sstevel@tonic-gate} else { 641*0Sstevel@tonic-gate print "ok 19\n"; 642*0Sstevel@tonic-gate} 643*0Sstevel@tonic-gate 644*0Sstevel@tonic-gateEOT 645*0Sstevel@tonic-gate 646*0Sstevel@tonic-gate$test_body .= <<"EOT"; 647*0Sstevel@tonic-gatemy \$rfc1149 = RFC1149; 648*0Sstevel@tonic-gateif (\$rfc1149 ne "$parent_rfc1149") { 649*0Sstevel@tonic-gate print "not ok 20 # '\$rfc1149' ne '$parent_rfc1149'\n"; 650*0Sstevel@tonic-gate} else { 651*0Sstevel@tonic-gate print "ok 20\n"; 652*0Sstevel@tonic-gate} 653*0Sstevel@tonic-gate 654*0Sstevel@tonic-gateif (\$rfc1149 != 1149) { 655*0Sstevel@tonic-gate printf "not ok 21 # %d != 1149\n", \$rfc1149; 656*0Sstevel@tonic-gate} else { 657*0Sstevel@tonic-gate print "ok 21\n"; 658*0Sstevel@tonic-gate} 659*0Sstevel@tonic-gate 660*0Sstevel@tonic-gateEOT 661*0Sstevel@tonic-gate 662*0Sstevel@tonic-gate$test_body .= <<'EOT'; 663*0Sstevel@tonic-gate# test macro=>1 664*0Sstevel@tonic-gatemy $open = OPEN; 665*0Sstevel@tonic-gateif ($open eq '/*') { 666*0Sstevel@tonic-gate print "ok 22\n"; 667*0Sstevel@tonic-gate} else { 668*0Sstevel@tonic-gate print "not ok 22 # \$open='$open'\n"; 669*0Sstevel@tonic-gate} 670*0Sstevel@tonic-gateEOT 671*0Sstevel@tonic-gate$dummytest+=18; 672*0Sstevel@tonic-gate 673*0Sstevel@tonic-gate end_tests("Simple tests", \@items, \@export_names, $header, $test_body); 674*0Sstevel@tonic-gate} 675*0Sstevel@tonic-gate 676*0Sstevel@tonic-gateif ($do_utf_tests) { 677*0Sstevel@tonic-gate # utf8 tests 678*0Sstevel@tonic-gate start_tests(); 679*0Sstevel@tonic-gate my ($inf, $pound_bytes, $pound_utf8); 680*0Sstevel@tonic-gate 681*0Sstevel@tonic-gate $inf = chr 0x221E; 682*0Sstevel@tonic-gate # Check that we can distiguish the pathological case of a string, and the 683*0Sstevel@tonic-gate # utf8 representation of that string. 684*0Sstevel@tonic-gate $pound_utf8 = $pound . '1'; 685*0Sstevel@tonic-gate if ($better_than_56) { 686*0Sstevel@tonic-gate $pound_bytes = $pound_utf8; 687*0Sstevel@tonic-gate utf8::encode ($pound_bytes); 688*0Sstevel@tonic-gate } else { 689*0Sstevel@tonic-gate # Must have that "U*" to generate a zero length UTF string that forces 690*0Sstevel@tonic-gate # top bit set chars (such as the pound sign) into UTF8, so that the 691*0Sstevel@tonic-gate # unpack 'C*' then gets the byte form of the UTF8. 692*0Sstevel@tonic-gate $pound_bytes = pack 'C*', unpack 'C*', $pound_utf8 . pack "U*"; 693*0Sstevel@tonic-gate } 694*0Sstevel@tonic-gate 695*0Sstevel@tonic-gate my @items = (@common_items, 696*0Sstevel@tonic-gate {name=>$inf, type=>"PV", value=>'"Infinity"', macro=>1}, 697*0Sstevel@tonic-gate {name=>$pound_utf8, type=>"PV", value=>'"1 Pound"', macro=>1}, 698*0Sstevel@tonic-gate {name=>$pound_bytes, type=>"PV", value=>'"1 Pound (as bytes)"', 699*0Sstevel@tonic-gate macro=>1}, 700*0Sstevel@tonic-gate ); 701*0Sstevel@tonic-gate 702*0Sstevel@tonic-gate=pod 703*0Sstevel@tonic-gate 704*0Sstevel@tonic-gateThe above set of names seems to produce a suitably bad set of compile 705*0Sstevel@tonic-gateproblems on a Unicode naive version of ExtUtils::Constant (ie 0.11): 706*0Sstevel@tonic-gate 707*0Sstevel@tonic-gatenick@thinking-cap 15439-32-utf$ PERL_CORE=1 ./perl lib/ExtUtils/t/Constant.t 708*0Sstevel@tonic-gate1..33 709*0Sstevel@tonic-gate# perl=/stuff/perl5/15439-32-utf/perl 710*0Sstevel@tonic-gate# ext-30370 being created... 711*0Sstevel@tonic-gateWide character in print at lib/ExtUtils/t/Constant.t line 140. 712*0Sstevel@tonic-gateok 1 713*0Sstevel@tonic-gateok 2 714*0Sstevel@tonic-gate# make = 'make' 715*0Sstevel@tonic-gateExtTest.xs: In function `constant_1': 716*0Sstevel@tonic-gateExtTest.xs:80: warning: multi-character character constant 717*0Sstevel@tonic-gateExtTest.xs:80: warning: case value out of range 718*0Sstevel@tonic-gateok 3 719*0Sstevel@tonic-gate 720*0Sstevel@tonic-gate=cut 721*0Sstevel@tonic-gate 722*0Sstevel@tonic-gate# Grr ` 723*0Sstevel@tonic-gate 724*0Sstevel@tonic-gate # Do this in 7 bit in case someone is testing with some settings that cause 725*0Sstevel@tonic-gate # 8 bit files incapable of storing this character. 726*0Sstevel@tonic-gate my @values 727*0Sstevel@tonic-gate = map {"'" . join (",", unpack "U*", $_ . pack "U*") . "'"} 728*0Sstevel@tonic-gate ($pound, $inf, $pound_bytes, $pound_utf8); 729*0Sstevel@tonic-gate # Values is a list of strings, such as ('194,163,49', '163,49') 730*0Sstevel@tonic-gate 731*0Sstevel@tonic-gate my $test_body .= "my \$test = $dummytest;\n"; 732*0Sstevel@tonic-gate $dummytest += 7 * 3; # 3 tests for each of the 7 things: 733*0Sstevel@tonic-gate 734*0Sstevel@tonic-gate $test_body .= << 'EOT'; 735*0Sstevel@tonic-gate 736*0Sstevel@tonic-gateuse utf8; 737*0Sstevel@tonic-gatemy $better_than_56 = $] > 5.007; 738*0Sstevel@tonic-gate 739*0Sstevel@tonic-gatemy ($pound, $inf, $pound_bytes, $pound_utf8) = map {eval "pack 'U*', $_"} 740*0Sstevel@tonic-gateEOT 741*0Sstevel@tonic-gate 742*0Sstevel@tonic-gate $test_body .= join ",", @values; 743*0Sstevel@tonic-gate 744*0Sstevel@tonic-gate $test_body .= << 'EOT'; 745*0Sstevel@tonic-gate; 746*0Sstevel@tonic-gate 747*0Sstevel@tonic-gateforeach (["perl", "rules", "rules"], 748*0Sstevel@tonic-gate ["/*", "OPEN", "OPEN"], 749*0Sstevel@tonic-gate ["*/", "CLOSE", "CLOSE"], 750*0Sstevel@tonic-gate [$pound, 'Sterling', []], 751*0Sstevel@tonic-gate [$inf, 'Infinity', []], 752*0Sstevel@tonic-gate [$pound_utf8, '1 Pound', '1 Pound (as bytes)'], 753*0Sstevel@tonic-gate [$pound_bytes, '1 Pound (as bytes)', []], 754*0Sstevel@tonic-gate ) { 755*0Sstevel@tonic-gate # Flag an expected error with a reference for the expect string. 756*0Sstevel@tonic-gate my ($string, $expect, $expect_bytes) = @$_; 757*0Sstevel@tonic-gate (my $name = $string) =~ s/([^ -~])/sprintf '\x{%X}', ord $1/ges; 758*0Sstevel@tonic-gate print "# \"$name\" => \'$expect\'\n"; 759*0Sstevel@tonic-gate # Try to force this to be bytes if possible. 760*0Sstevel@tonic-gate if ($better_than_56) { 761*0Sstevel@tonic-gate utf8::downgrade ($string, 1); 762*0Sstevel@tonic-gate } else { 763*0Sstevel@tonic-gate if ($string =~ tr/0-\377// == length $string) { 764*0Sstevel@tonic-gate # No chars outside range 0-255 765*0Sstevel@tonic-gate $string = pack 'C*', unpack 'U*', ($string . pack 'U*'); 766*0Sstevel@tonic-gate } 767*0Sstevel@tonic-gate } 768*0Sstevel@tonic-gateEOT 769*0Sstevel@tonic-gate 770*0Sstevel@tonic-gate $test_body .= "my (\$error, \$got) = ${package}::constant (\$string);\n"; 771*0Sstevel@tonic-gate 772*0Sstevel@tonic-gate $test_body .= <<'EOT'; 773*0Sstevel@tonic-gate if ($error or $got ne $expect) { 774*0Sstevel@tonic-gate print "not ok $test # error '$error', got '$got'\n"; 775*0Sstevel@tonic-gate } else { 776*0Sstevel@tonic-gate print "ok $test\n"; 777*0Sstevel@tonic-gate } 778*0Sstevel@tonic-gate $test++; 779*0Sstevel@tonic-gate print "# Now upgrade '$name' to utf8\n"; 780*0Sstevel@tonic-gate if ($better_than_56) { 781*0Sstevel@tonic-gate utf8::upgrade ($string); 782*0Sstevel@tonic-gate } else { 783*0Sstevel@tonic-gate $string = pack ('U*') . $string; 784*0Sstevel@tonic-gate } 785*0Sstevel@tonic-gateEOT 786*0Sstevel@tonic-gate 787*0Sstevel@tonic-gate $test_body .= "my (\$error, \$got) = ${package}::constant (\$string);\n"; 788*0Sstevel@tonic-gate 789*0Sstevel@tonic-gate $test_body .= <<'EOT'; 790*0Sstevel@tonic-gate if ($error or $got ne $expect) { 791*0Sstevel@tonic-gate print "not ok $test # error '$error', got '$got'\n"; 792*0Sstevel@tonic-gate } else { 793*0Sstevel@tonic-gate print "ok $test\n"; 794*0Sstevel@tonic-gate } 795*0Sstevel@tonic-gate $test++; 796*0Sstevel@tonic-gate if (defined $expect_bytes) { 797*0Sstevel@tonic-gate print "# And now with the utf8 byte sequence for name\n"; 798*0Sstevel@tonic-gate # Try the encoded bytes. 799*0Sstevel@tonic-gate if ($better_than_56) { 800*0Sstevel@tonic-gate utf8::encode ($string); 801*0Sstevel@tonic-gate } else { 802*0Sstevel@tonic-gate $string = pack 'C*', unpack 'C*', $string . pack "U*"; 803*0Sstevel@tonic-gate } 804*0Sstevel@tonic-gateEOT 805*0Sstevel@tonic-gate 806*0Sstevel@tonic-gate $test_body .= "my (\$error, \$got) = ${package}::constant (\$string);\n"; 807*0Sstevel@tonic-gate 808*0Sstevel@tonic-gate $test_body .= <<'EOT'; 809*0Sstevel@tonic-gate if (ref $expect_bytes) { 810*0Sstevel@tonic-gate # Error expected. 811*0Sstevel@tonic-gate if ($error) { 812*0Sstevel@tonic-gate print "ok $test # error='$error' (as expected)\n"; 813*0Sstevel@tonic-gate } else { 814*0Sstevel@tonic-gate print "not ok $test # expected error, got no error and '$got'\n"; 815*0Sstevel@tonic-gate } 816*0Sstevel@tonic-gate } elsif ($got ne $expect_bytes) { 817*0Sstevel@tonic-gate print "not ok $test # error '$error', expect '$expect_bytes', got '$got'\n"; 818*0Sstevel@tonic-gate } else { 819*0Sstevel@tonic-gate print "ok $test\n"; 820*0Sstevel@tonic-gate } 821*0Sstevel@tonic-gate $test++; 822*0Sstevel@tonic-gate } 823*0Sstevel@tonic-gate} 824*0Sstevel@tonic-gateEOT 825*0Sstevel@tonic-gate 826*0Sstevel@tonic-gate end_tests("utf8 tests", \@items, [], "#define perl \"rules\"\n", $test_body); 827*0Sstevel@tonic-gate} 828*0Sstevel@tonic-gate 829*0Sstevel@tonic-gate# XXX I think that I should merge this into the utf8 test above. 830*0Sstevel@tonic-gatesub explict_call_constant { 831*0Sstevel@tonic-gate my ($string, $expect) = @_; 832*0Sstevel@tonic-gate # This does assume simple strings suitable for '' 833*0Sstevel@tonic-gate my $test_body = <<"EOT"; 834*0Sstevel@tonic-gate{ 835*0Sstevel@tonic-gate my (\$error, \$got) = ${package}::constant ('$string');\n; 836*0Sstevel@tonic-gateEOT 837*0Sstevel@tonic-gate 838*0Sstevel@tonic-gate if (defined $expect) { 839*0Sstevel@tonic-gate # No error expected 840*0Sstevel@tonic-gate $test_body .= <<"EOT"; 841*0Sstevel@tonic-gate if (\$error or \$got ne "$expect") { 842*0Sstevel@tonic-gate print "not ok $dummytest # error '\$error', expect '$expect', got '\$got'\n"; 843*0Sstevel@tonic-gate } else { 844*0Sstevel@tonic-gate print "ok $dummytest\n"; 845*0Sstevel@tonic-gate } 846*0Sstevel@tonic-gate } 847*0Sstevel@tonic-gateEOT 848*0Sstevel@tonic-gate } else { 849*0Sstevel@tonic-gate # Error expected. 850*0Sstevel@tonic-gate $test_body .= <<"EOT"; 851*0Sstevel@tonic-gate if (\$error) { 852*0Sstevel@tonic-gate print "ok $dummytest # error='\$error' (as expected)\n"; 853*0Sstevel@tonic-gate } else { 854*0Sstevel@tonic-gate print "not ok $dummytest # expected error, got no error and '\$got'\n"; 855*0Sstevel@tonic-gate } 856*0Sstevel@tonic-gateEOT 857*0Sstevel@tonic-gate } 858*0Sstevel@tonic-gate $dummytest++; 859*0Sstevel@tonic-gate return $test_body . <<'EOT'; 860*0Sstevel@tonic-gate} 861*0Sstevel@tonic-gateEOT 862*0Sstevel@tonic-gate} 863*0Sstevel@tonic-gate 864*0Sstevel@tonic-gate# Simple tests to verify bits of the switch generation system work. 865*0Sstevel@tonic-gatesub simple { 866*0Sstevel@tonic-gate start_tests(); 867*0Sstevel@tonic-gate # Deliberately leave $name in @_, so that it is indexed from 1. 868*0Sstevel@tonic-gate my ($name, @items) = @_; 869*0Sstevel@tonic-gate my $test_header; 870*0Sstevel@tonic-gate my $test_body = "my \$value;\n"; 871*0Sstevel@tonic-gate foreach my $counter (1 .. $#_) { 872*0Sstevel@tonic-gate my $thisname = $_[$counter]; 873*0Sstevel@tonic-gate $test_header .= "#define $thisname $counter\n"; 874*0Sstevel@tonic-gate $test_body .= <<"EOT"; 875*0Sstevel@tonic-gate\$value = $thisname; 876*0Sstevel@tonic-gateif (\$value == $counter) { 877*0Sstevel@tonic-gate print "ok $dummytest\n"; 878*0Sstevel@tonic-gate} else { 879*0Sstevel@tonic-gate print "not ok $dummytest # $thisname gave \$value\n"; 880*0Sstevel@tonic-gate} 881*0Sstevel@tonic-gateEOT 882*0Sstevel@tonic-gate ++$dummytest; 883*0Sstevel@tonic-gate # Yes, the last time round the loop appends a z to the string. 884*0Sstevel@tonic-gate for my $i (0 .. length $thisname) { 885*0Sstevel@tonic-gate my $copyname = $thisname; 886*0Sstevel@tonic-gate substr ($copyname, $i, 1) = 'z'; 887*0Sstevel@tonic-gate $test_body .= explict_call_constant ($copyname, 888*0Sstevel@tonic-gate $copyname eq $thisname 889*0Sstevel@tonic-gate ? $thisname : undef); 890*0Sstevel@tonic-gate } 891*0Sstevel@tonic-gate } 892*0Sstevel@tonic-gate # Ho. This seems to be buggy in 5.005_03: 893*0Sstevel@tonic-gate # # Now remove $name from @_: 894*0Sstevel@tonic-gate # shift @_; 895*0Sstevel@tonic-gate end_tests($name, \@items, \@items, $test_header, $test_body); 896*0Sstevel@tonic-gate} 897*0Sstevel@tonic-gate 898*0Sstevel@tonic-gate# Check that the memeq clauses work correctly when there isn't a switch 899*0Sstevel@tonic-gate# statement to bump off a character 900*0Sstevel@tonic-gatesimple ("Singletons", "A", "AB", "ABC", "ABCD", "ABCDE"); 901*0Sstevel@tonic-gate# Check the three code. 902*0Sstevel@tonic-gatesimple ("Three start", qw(Bea kea Lea lea nea pea rea sea tea Wea yea Zea)); 903*0Sstevel@tonic-gate# There were 162 2 letter words in /usr/share/dict/words on FreeBSD 4.6, which 904*0Sstevel@tonic-gate# I felt was rather too many. So I used words with 2 vowels. 905*0Sstevel@tonic-gatesimple ("Twos and three middle", qw(aa ae ai ea eu ie io oe era eta)); 906*0Sstevel@tonic-gate# Given the choice go for the end, else the earliest point 907*0Sstevel@tonic-gatesimple ("Three end and four symetry", qw(ean ear eat barb marm tart)); 908*0Sstevel@tonic-gate 909*0Sstevel@tonic-gate 910*0Sstevel@tonic-gate# Need this if the single test below is rolled into @tests : 911*0Sstevel@tonic-gate# --$dummytest; 912*0Sstevel@tonic-gateprint "1..$dummytest\n"; 913*0Sstevel@tonic-gate 914*0Sstevel@tonic-gatewrite_and_run_extension @$_ foreach @tests; 915*0Sstevel@tonic-gate 916*0Sstevel@tonic-gate# This was causing an assertion failure (a C<confess>ion) 917*0Sstevel@tonic-gate# Any single byte > 128 should do it. 918*0Sstevel@tonic-gateC_constant ($package, undef, undef, undef, undef, undef, chr 255); 919*0Sstevel@tonic-gateprint "ok $realtest\n"; $realtest++; 920*0Sstevel@tonic-gate 921*0Sstevel@tonic-gateprint STDERR "# You were running with \$keep_files set to $keep_files\n" 922*0Sstevel@tonic-gate if $keep_files; 923