Put back the #! line, false alarm.
[p5sagit/p5-mst-13.2.git] / lib / ExtUtils / t / Constant.t
1 #!/usr/bin/perl -w
2
3 print "1..48\n";
4
5 BEGIN {
6     if( $ENV{PERL_CORE} ) {
7         chdir 't' if -d 't';
8         @INC = '../lib';
9     }
10 }
11
12 # use warnings;
13 use strict;
14 use ExtUtils::MakeMaker;
15 use ExtUtils::Constant qw (constant_types C_constant XS_constant autoload);
16 use Config;
17 use File::Spec::Functions qw(catfile rel2abs);
18 # Because were are going to be changing directory before running Makefile.PL
19 my $perl;
20 $perl = rel2abs( $^X ) unless $] < 5.006; # Hack. Until 5.00503 has rel2abs
21 # ExtUtils::Constant::C_constant uses $^X inside a comment, and we want to
22 # compare output to ensure that it is the same. We were probably run as ./perl
23 # whereas we will run the child with the full path in $perl. So make $^X for
24 # us the same as our child will see.
25 $^X = $perl;
26
27 print "# perl=$perl\n";
28 my $runperl = "$perl \"-I../../lib\"";
29
30 $| = 1;
31
32 my $dir = "ext-$$";
33 my @files;
34
35 print "# $dir being created...\n";
36 mkdir $dir, 0777 or die "mkdir: $!\n";
37
38 my $output = "output";
39
40 # For debugging set this to 1.
41 my $keep_files = 0;
42
43 END {
44     use File::Path;
45     print "# $dir being removed...\n";
46     rmtree($dir) unless $keep_files;
47 }
48
49 my $package = "ExtTest";
50
51 # Test the code that generates 1 and 2 letter name comparisons.
52 my %compass = (
53 N => 0, 'NE' => 45, E => 90, SE => 135, S => 180, SW => 225, W => 270, NW => 315
54 );
55
56 my $parent_rfc1149 =
57   'A Standard for the Transmission of IP Datagrams on Avian Carriers';
58 # Check that 8 bit and unicode names don't cause problems.
59 my $pound = chr 163; # A pound sign. (Currency)
60 my $inf = chr 0x221E;
61 # Check that we can distiguish the pathological case of a string, and the
62 # utf8 representation of that string.
63 my $pound_bytes = my $pound_utf8 = $pound . '1';
64 utf8::encode ($pound_bytes);
65
66 my @names = ("FIVE", {name=>"OK6", type=>"PV",},
67              {name=>"OK7", type=>"PVN",
68               value=>['"not ok 7\\n\\0ok 7\\n"', 15]},
69              {name => "FARTHING", type=>"NV"},
70              {name => "NOT_ZERO", type=>"UV", value=>"~(UV)0"},
71              {name => "OPEN", type=>"PV", value=>'"/*"', macro=>1},
72              {name => "CLOSE", type=>"PV", value=>'"*/"',
73               macro=>["#if 1\n", "#endif\n"]},
74              {name => "ANSWER", default=>["UV", 42]}, "NOTDEF",
75              {name => "Yes", type=>"YES"},
76              {name => "No", type=>"NO"},
77              {name => "Undef", type=>"UNDEF"},
78 # OK. It wasn't really designed to allow the creation of dual valued constants.
79 # It was more for INADDR_ANY INADDR_BROADCAST INADDR_LOOPBACK INADDR_NONE
80              {name=>"RFC1149", type=>"SV", value=>"sv_2mortal(temp_sv)",
81               pre=>"SV *temp_sv = newSVpv(RFC1149, 0); "
82                    . "(void) SvUPGRADE(temp_sv,SVt_PVIV); SvIOK_on(temp_sv); "
83                    . "SvIVX(temp_sv) = 1149;"},
84              {name=>"perl", type=>"PV",},
85 );
86
87 push @names, $_ foreach keys %compass;
88
89 # Automatically compile the list of all the macro names, and make them
90 # exported constants.
91 my @names_only = map {(ref $_) ? $_->{name} : $_} @names;
92
93 # Exporter::Heavy (currently) isn't able to export these names:
94 push @names, ({name=>"*/", type=>"PV", value=>'"CLOSE"', macro=>1},
95               {name=>"/*", type=>"PV", value=>'"OPEN"', macro=>1},
96               {name=>$pound, type=>"PV", value=>'"Sterling"', macro=>1},
97               {name=>$inf, type=>"PV", value=>'"Infinity"', macro=>1},
98               {name=>$pound_utf8, type=>"PV", value=>'"1 Pound"', macro=>1},
99               {name=>$pound_bytes, type=>"PV", value=>'"1 Pound (as bytes)"',
100                macro=>1},
101              );
102
103 =pod
104
105 The above set of names seems to produce a suitably bad set of compile
106 problems on a Unicode naive version of ExtUtils::Constant (ie 0.11):
107
108 nick@thinking-cap 15439-32-utf$ PERL_CORE=1 ./perl lib/ExtUtils/t/Constant.t
109 1..33
110 # perl=/stuff/perl5/15439-32-utf/perl
111 # ext-30370 being created...
112 Wide character in print at lib/ExtUtils/t/Constant.t line 140.
113 ok 1
114 ok 2
115 # make = 'make'
116 ExtTest.xs: In function `constant_1':
117 ExtTest.xs:80: warning: multi-character character constant
118 ExtTest.xs:80: warning: case value out of range
119 ok 3
120
121 =cut
122
123 my $types = {};
124 my $constant_types = constant_types(); # macro defs
125 my $C_constant = join "\n",
126   C_constant ($package, undef, "IV", $types, undef, undef, @names);
127 my $XS_constant = XS_constant ($package, $types); # XS for ExtTest::constant
128
129 ################ Header
130 my $header = catfile($dir, "test.h");
131 push @files, "test.h";
132 open FH, ">$header" or die "open >$header: $!\n";
133 print FH <<"EOT";
134 #define FIVE 5
135 #define OK6 "ok 6\\n"
136 #define OK7 1
137 #define FARTHING 0.25
138 #define NOT_ZERO 1
139 #define Yes 0
140 #define No 1
141 #define Undef 1
142 #define RFC1149 "$parent_rfc1149"
143 #undef NOTDEF
144 #define perl "rules"
145 EOT
146
147 while (my ($point, $bearing) = each %compass) {
148   print FH "#define $point $bearing\n"
149 }
150 close FH or die "close $header: $!\n";
151
152 ################ XS
153 my $xs = catfile($dir, "$package.xs");
154 push @files, "$package.xs";
155 open FH, ">$xs" or die "open >$xs: $!\n";
156
157 print FH <<'EOT';
158 #include "EXTERN.h"
159 #include "perl.h"
160 #include "XSUB.h"
161 EOT
162
163 print FH "#include \"test.h\"\n\n";
164 print FH $constant_types;
165 print FH $C_constant, "\n";
166 print FH "MODULE = $package             PACKAGE = $package\n";
167 print FH "PROTOTYPES: ENABLE\n";
168 print FH $XS_constant;
169 close FH or die "close $xs: $!\n";
170
171 ################ PM
172 my $pm = catfile($dir, "$package.pm");
173 push @files, "$package.pm";
174 open FH, ">$pm" or die "open >$pm: $!\n";
175 print FH "package $package;\n";
176 print FH "use $];\n";
177
178 print FH <<'EOT';
179
180 use strict;
181 EOT
182 printf FH "use warnings;\n" unless $] < 5.006;
183 print FH <<'EOT';
184 use Carp;
185
186 require Exporter;
187 require DynaLoader;
188 use vars qw ($VERSION @ISA @EXPORT_OK $AUTOLOAD);
189
190 $VERSION = '0.01';
191 @ISA = qw(Exporter DynaLoader);
192 @EXPORT_OK = qw(
193 EOT
194
195 # Print the names of all our autoloaded constants
196 print FH "\t$_\n" foreach (@names_only);
197 print FH ");\n";
198 # Print the AUTOLOAD subroutine ExtUtils::Constant generated for us
199 print FH autoload ($package, $]);
200 print FH "bootstrap $package \$VERSION;\n1;\n__END__\n";
201 close FH or die "close $pm: $!\n";
202
203 ################ test.pl
204 my $testpl = catfile($dir, "test.pl");
205 push @files, "test.pl";
206 open FH, ">$testpl" or die "open >$testpl: $!\n";
207
208 print FH "use strict;\n";
209 print FH "use $package qw(@names_only);\n";
210 print FH <<"EOT";
211
212 use utf8;
213
214 print "1..1\n";
215 if (open OUTPUT, ">$output") {
216   print "ok 1\n";
217   select OUTPUT;
218 } else {
219   print "not ok 1 # Failed to open '$output': $!\n";
220   exit 1;
221 }
222 EOT
223
224 print FH << 'EOT';
225
226 # What follows goes to the temporary file.
227 # IV
228 my $five = FIVE;
229 if ($five == 5) {
230   print "ok 5\n";
231 } else {
232   print "not ok 5 # $five\n";
233 }
234
235 # PV
236 print OK6;
237
238 # PVN containing embedded \0s
239 $_ = OK7;
240 s/.*\0//s;
241 print;
242
243 # NV
244 my $farthing = FARTHING;
245 if ($farthing == 0.25) {
246   print "ok 8\n";
247 } else {
248   print "not ok 8 # $farthing\n";
249 }
250
251 # UV
252 my $not_zero = NOT_ZERO;
253 if ($not_zero > 0 && $not_zero == ~0) {
254   print "ok 9\n";
255 } else {
256   print "not ok 9 # \$not_zero=$not_zero ~0=" . (~0) . "\n";
257 }
258
259 # Value includes a "*/" in an attempt to bust out of a C comment.
260 # Also tests custom cpp #if clauses
261 my $close = CLOSE;
262 if ($close eq '*/') {
263   print "ok 10\n";
264 } else {
265   print "not ok 10 # \$close='$close'\n";
266 }
267
268 # Default values if macro not defined.
269 my $answer = ANSWER;
270 if ($answer == 42) {
271   print "ok 11\n";
272 } else {
273   print "not ok 11 # What do you get if you multiply six by nine? '$answer'\n";
274 }
275
276 # not defined macro
277 my $notdef = eval { NOTDEF; };
278 if (defined $notdef) {
279   print "not ok 12 # \$notdef='$notdef'\n";
280 } elsif ($@ !~ /Your vendor has not defined ExtTest macro NOTDEF/) {
281   print "not ok 12 # \$@='$@'\n";
282 } else {
283   print "ok 12\n";
284 }
285
286 # not a macro
287 my $notthere = eval { &ExtTest::NOTTHERE; };
288 if (defined $notthere) {
289   print "not ok 13 # \$notthere='$notthere'\n";
290 } elsif ($@ !~ /NOTTHERE is not a valid ExtTest macro/) {
291   chomp $@;
292   print "not ok 13 # \$@='$@'\n";
293 } else {
294   print "ok 13\n";
295 }
296
297 # Truth
298 my $yes = Yes;
299 if ($yes) {
300   print "ok 14\n";
301 } else {
302   print "not ok 14 # $yes='\$yes'\n";
303 }
304
305 # Falsehood
306 my $no = No;
307 if (defined $no and !$no) {
308   print "ok 15\n";
309 } else {
310   print "not ok 15 # \$no=" . defined ($no) ? "'$no'\n" : "undef\n";
311 }
312
313 # Undef
314 my $undef = Undef;
315 unless (defined $undef) {
316   print "ok 16\n";
317 } else {
318   print "not ok 16 # \$undef='$undef'\n";
319 }
320
321
322 # invalid macro (chosen to look like a mix up between No and SW)
323 $notdef = eval { &ExtTest::So };
324 if (defined $notdef) {
325   print "not ok 17 # \$notdef='$notdef'\n";
326 } elsif ($@ !~ /^So is not a valid ExtTest macro/) {
327   print "not ok 17 # \$@='$@'\n";
328 } else {
329   print "ok 17\n";
330 }
331
332 # invalid defined macro
333 $notdef = eval { &ExtTest::EW };
334 if (defined $notdef) {
335   print "not ok 18 # \$notdef='$notdef'\n";
336 } elsif ($@ !~ /^EW is not a valid ExtTest macro/) {
337   print "not ok 18 # \$@='$@'\n";
338 } else {
339   print "ok 18\n";
340 }
341
342 my %compass = (
343 EOT
344
345 while (my ($point, $bearing) = each %compass) {
346   print FH "'$point' => $bearing, "
347 }
348
349 print FH <<'EOT';
350
351 );
352
353 my $fail;
354 while (my ($point, $bearing) = each %compass) {
355   my $val = eval $point;
356   if ($@) {
357     print "# $point: \$@='$@'\n";
358     $fail = 1;
359   } elsif (!defined $bearing) {
360     print "# $point: \$val=undef\n";
361     $fail = 1;
362   } elsif ($val != $bearing) {
363     print "# $point: \$val=$val, not $bearing\n";
364     $fail = 1;
365   }
366 }
367 if ($fail) {
368   print "not ok 19\n";
369 } else {
370   print "ok 19\n";
371 }
372
373 EOT
374
375 print FH <<"EOT";
376 my \$rfc1149 = RFC1149;
377 if (\$rfc1149 ne "$parent_rfc1149") {
378   print "not ok 20 # '\$rfc1149' ne '$parent_rfc1149'\n";
379 } else {
380   print "ok 20\n";
381 }
382
383 if (\$rfc1149 != 1149) {
384   printf "not ok 21 # %d != 1149\n", \$rfc1149;
385 } else {
386   print "ok 21\n";
387 }
388
389 EOT
390
391 print FH <<'EOT';
392 # test macro=>1
393 my $open = OPEN;
394 if ($open eq '/*') {
395   print "ok 22\n";
396 } else {
397   print "not ok 22 # \$open='$open'\n";
398 }
399 EOT
400
401 # Do this in 7 bit in case someone is testing with some settings that cause
402 # 8 bit files incapable of storing this character.
403 my @values
404  = map {"'" . join (",", unpack "U*", $_) . "'"}
405  ($pound, $inf, $pound_bytes, $pound_utf8);
406 # Values is a list of strings, such as ('194,163,49', '163,49')
407
408 print FH <<'EOT';
409
410 # I can see that this child test program might be about to use parts of
411 # Test::Builder
412
413 my $test = 23;
414 my ($pound, $inf, $pound_bytes, $pound_utf8) = map {eval "pack 'U*', $_"}
415 EOT
416
417 print FH join ",", @values;
418
419 print FH << 'EOT';
420 ;
421
422 foreach (["perl", "rules", "rules"],
423          ["/*", "OPEN", "OPEN"],
424          ["*/", "CLOSE", "CLOSE"],
425          [$pound, 'Sterling', []],
426          [$inf, 'Infinity', []],
427          [$pound_utf8, '1 Pound', '1 Pound (as bytes)'],
428          [$pound_bytes, '1 Pound (as bytes)', []],
429         ) {
430   # Flag an expected error with a reference for the expect string.
431   my ($string, $expect, $expect_bytes) = @$_;
432   (my $name = $string) =~ s/([^ -~])/sprintf '\x{%X}', ord $1/ges;
433   print "# \"$name\" => \'$expect\'\n";
434   # Try to force this to be bytes if possible.
435   utf8::downgrade ($string, 1);
436 EOT
437
438 print FH  "my (\$error, \$got) = ${package}::constant (\$string);\n";
439
440 print FH <<'EOT';
441   if ($error or $got ne $expect) {
442     print "not ok $test # error '$error', got '$got'\n";
443   } else {
444     print "ok $test\n";
445   }
446   $test++;
447   print "# Now upgrade '$name' to utf8\n";
448   utf8::upgrade ($string);
449 EOT
450
451 print FH  "my (\$error, \$got) = ${package}::constant (\$string);\n";
452
453 print FH <<'EOT';
454   if ($error or $got ne $expect) {
455     print "not ok $test # error '$error', got '$got'\n";
456   } else {
457     print "ok $test\n";
458   }
459   $test++;
460   if (defined $expect_bytes) {
461     print "# And now with the utf8 byte sequence for name\n";
462     # Try the encoded bytes.
463     utf8::encode ($string);
464 EOT
465
466 print FH "my (\$error, \$got) = ${package}::constant (\$string);\n";
467
468 print FH <<'EOT';
469     if (ref $expect_bytes) {
470       # Error expected.
471       if ($error) {
472         print "ok $test # error='$error' (as expected)\n";
473       } else {
474         print "not ok $test # expected error, got no error and '$got'\n";
475       }
476     } elsif ($got ne $expect_bytes) {
477       print "not ok $test # error '$error', expect '$expect_bytes', got '$got'\n";
478     } else {
479       print "ok $test\n";
480     }
481     $test++;
482   }
483 }
484 EOT
485
486 close FH or die "close $testpl: $!\n";
487
488 # This is where the test numbers carry on after the test number above are
489 # relayed
490 my $test = 44;
491
492 ################ Makefile.PL
493 # We really need a Makefile.PL because make test for a no dynamic linking perl
494 # will run Makefile.PL again as part of the "make perl" target.
495 my $makefilePL = catfile($dir, "Makefile.PL");
496 push @files, "Makefile.PL";
497 open FH, ">$makefilePL" or die "open >$makefilePL: $!\n";
498 print FH <<"EOT";
499 #!$perl -w
500 use ExtUtils::MakeMaker;
501 WriteMakefile(
502               'NAME'            => "$package",
503               'VERSION_FROM'    => "$package.pm", # finds \$VERSION
504               (\$] >= 5.005 ?
505                (#ABSTRACT_FROM => "$package.pm", # XXX add this
506                 AUTHOR     => "$0") : ())
507              );
508 EOT
509
510 close FH or die "close $makefilePL: $!\n";
511
512 chdir $dir or die $!; push @INC,  '../../lib';
513 END {chdir ".." or warn $!};
514
515 my @perlout = `$runperl Makefile.PL PERL_CORE=1`;
516 if ($?) {
517   print "not ok 1 # $runperl Makefile.PL failed: $?\n";
518   print "# $_" foreach @perlout;
519   exit($?);
520 } else {
521   print "ok 1\n";
522 }
523
524
525 my $makefile = ($^O eq 'VMS' ? 'descrip' : 'Makefile');
526 my $makefile_ext = ($^O eq 'VMS' ? '.mms' : '');
527 if (-f "$makefile$makefile_ext") {
528   print "ok 2\n";
529 } else {
530   print "not ok 2\n";
531 }
532 my $makefile_rename = ($^O eq 'VMS' ? '.mms' : '.old');
533 push @files, "$makefile$makefile_rename"; # Renamed by make clean
534
535 my $make = $Config{make};
536
537 $make = $ENV{MAKE} if exists $ENV{MAKE};
538
539 if ($^O eq 'MSWin32' && $make eq 'nmake') { $make .= " -nologo"; }
540
541 my @makeout;
542
543 if ($^O eq 'VMS') { $make .= ' all'; }
544 print "# make = '$make'\n";
545 @makeout = `$make`;
546 if ($?) {
547   print "not ok 3 # $make failed: $?\n";
548   print "# $_" foreach @makeout;
549   exit($?);
550 } else {
551   print "ok 3\n";
552 }
553
554 if ($^O eq 'VMS') { $make =~ s{ all}{}; }
555
556 if ($Config{usedl}) {
557   print "ok 4\n";
558 } else {
559   my $makeperl = "$make perl";
560   print "# make = '$makeperl'\n";
561   @makeout = `$makeperl`;
562   if ($?) {
563     print "not ok 4 # $makeperl failed: $?\n";
564   print "# $_" foreach @makeout;
565     exit($?);
566   } else {
567     print "ok 4\n";
568   }
569 }
570
571 push @files, $output;
572
573 my $maketest = "$make test";
574 print "# make = '$maketest'\n";
575
576 @makeout = `$maketest`;
577
578 if (open OUTPUT, "<$output") {
579   print while <OUTPUT>;
580   close OUTPUT or print "# Close $output failed: $!\n";
581 } else {
582   # Harness will report missing test results at this point.
583   print "# Open <$output failed: $!\n";
584 }
585
586 if ($?) {
587   print "not ok $test # $maketest failed: $?\n";
588   print "# $_" foreach @makeout;
589 } else {
590   print "ok $test - maketest\n";
591 }
592 $test++;
593
594
595 # -x is busted on Win32 < 5.6.1, so we emulate it.
596 my $regen;
597 if( $^O eq 'MSWin32' && $] <= 5.006001 ) {
598     open(REGENTMP, ">regentmp") or die $!;
599     open(XS, "$package.xs")     or die $!;
600     my $saw_shebang;
601     while(<XS>) {
602         $saw_shebang++ if /^#!.*/i ;
603         print REGENTMP $_ if $saw_shebang;
604     }
605     close XS;  close REGENTMP;
606     $regen = `$runperl regentmp`;
607     unlink 'regentmp';
608 }
609 else {
610     $regen = `$runperl -x $package.xs`;
611 }
612 if ($?) {
613   print "not ok $test # $runperl -x $package.xs failed: $?\n";
614 } else {
615   print "ok $test - regen\n";
616 }
617 $test++;
618
619 my $expect = $constant_types . $C_constant .
620   "\n#### XS Section:\n" . $XS_constant;
621
622 if ($expect eq $regen) {
623   print "ok $test - regen worked\n";
624 } else {
625   print "not ok $test - regen worked\n";
626   # open FOO, ">expect"; print FOO $expect;
627   # open FOO, ">regen"; print FOO $regen; close FOO;
628 }
629 $test++;
630
631 my $makeclean = "$make clean";
632 print "# make = '$makeclean'\n";
633 @makeout = `$makeclean`;
634 if ($?) {
635   print "not ok $test # $make failed: $?\n";
636   print "# $_" foreach @makeout;
637 } else {
638   print "ok $test\n";
639 }
640 $test++;
641
642 unless ($keep_files) {
643   foreach (@files) {
644     unlink $_ or warn "unlink $_: $!";
645   }
646 }
647
648 my $fail;
649 opendir DIR, "." or die "opendir '.': $!";
650 while (defined (my $entry = readdir DIR)) {
651   next if $entry =~ /^\.\.?$/;
652   print "# Extra file '$entry'\n";
653   $fail = 1;
654 }
655 closedir DIR or warn "closedir '.': $!";
656 if ($fail) {
657   print "not ok $test\n";
658 } else {
659   print "ok $test\n";
660 }