1################################################################################
2#
3#            !!!!!   Do NOT edit this file directly!   !!!!!
4#
5#            Edit mktests.PL and/or parts/inc/ppphtest instead.
6#
7#  This file was automatically generated from the definition files in the
8#  parts/inc/ subdirectory by mktests.PL. To learn more about how all this
9#  works, please read the F<HACKERS> file that came with this distribution.
10#
11################################################################################
12
13use FindBin ();
14
15BEGIN {
16  if ($ENV{'PERL_CORE'}) {
17    chdir 't' if -d 't';
18    unshift @INC, '../lib' if -d '../lib' && -d '../ext';
19    require Config; Config->import;
20    use vars '%Config';
21    if (" $Config{'extensions'} " !~ m[ Devel/PPPort ]) {
22      print "1..0 # Skip -- Perl configured without Devel::PPPort module\n";
23      exit 0;
24    }
25  }
26
27  use lib "$FindBin::Bin";
28  use lib "$FindBin::Bin/../parts/inc";
29
30  die qq[Cannot find "$FindBin::Bin/../parts/inc"] unless -d "$FindBin::Bin/../parts/inc";
31
32  sub load {
33    require 'testutil.pl';
34    require 'inctools';
35  }
36
37  if (235) {
38    load();
39    plan(tests => 235);
40  }
41}
42
43use Devel::PPPort;
44use strict;
45BEGIN { $^W = 1; }
46
47package Devel::PPPort;
48use vars '@ISA';
49require DynaLoader;
50@ISA = qw(DynaLoader);
51Devel::PPPort->bootstrap;
52
53package main;
54
55# BEWARE: This number and SKIP_SLOW_TESTS must be the same!!!
56
57BEGIN {
58  if ($ENV{'SKIP_SLOW_TESTS'}) {
59    skip("skip: SKIP_SLOW_TESTS", 235);
60    exit 0;
61  }
62}
63
64use File::Path qw/rmtree mkpath/;
65use Config;
66
67my $tmp = 'ppptmp';
68my $inc = '';
69my $isVMS = $^O eq 'VMS';
70my $isMAC = $^O eq 'MacOS';
71my $perl = find_perl();
72
73rmtree($tmp) if -d $tmp;
74mkpath($tmp) or die "mkpath $tmp: $!\n";
75chdir($tmp) or die "chdir $tmp: $!\n";
76
77if ($ENV{'PERL_CORE'}) {
78  if (-d '../../lib') {
79    if ($isVMS) {
80      $inc = '"-I../../lib"';
81    }
82    elsif ($isMAC) {
83      $inc = '-I:::lib';
84    }
85    else {
86      $inc = '-I../../lib';
87    }
88    unshift @INC, '../../lib';
89  }
90}
91if ($perl =~ m!^\./!) {
92  $perl = ".$perl";
93}
94
95END {
96  chdir('..') if !-d $tmp && -d "../$tmp";
97  rmtree($tmp) if -d $tmp;
98}
99
100ok(&Devel::PPPort::WriteFile("ppport.h"));
101
102# Check GetFileContents()
103is(-e "ppport.h", 1);
104
105my $data;
106
107open(F, "<ppport.h") or die "Failed to open ppport.h: $!";
108while(<F>) {
109  $data .= $_;
110}
111close(F);
112
113is(Devel::PPPort::GetFileContents("ppport.h"), $data);
114is(Devel::PPPort::GetFileContents(), $data);
115
116sub comment
117{
118  my $c = shift;
119  my $x = 0;
120  $c =~ s/^/sprintf("# %2d| ", ++$x)/meg;
121  $c .= "\n" unless $c =~ /[\r\n]$/;
122  print $c;
123}
124
125sub ppport
126{
127  my @args = ('ppport.h', @_);
128  unshift @args, $inc if $inc;
129  my $run = $perl =~ m/\s/ ? qq("$perl") : $perl;
130  $run .= ' -MMac::err=unix' if $isMAC;
131  for (@args) {
132    $_ = qq("$_") if $isVMS && /^[^"]/;
133    $run .= " $_";
134  }
135  print "# *** running $run ***\n";
136  $run .= ' 2>&1' unless $isMAC;
137  my @out = `$run`;
138  my $out = join '', @out;
139  comment($out);
140  return wantarray ? @out : $out;
141}
142
143sub matches
144{
145  my($str, $re, $mod) = @_;
146  my @n;
147  eval "\@n = \$str =~ /$re/g$mod;";
148  if ($@) {
149    my $err = $@;
150    $err =~ s/^/# *** /mg;
151    print "# *** ERROR ***\n$err\n";
152  }
153  return $@ ? -42 : scalar @n;
154}
155
156sub eq_files
157{
158  my($f1, $f2) = @_;
159  return 0 unless -e $f1 && -e $f2;
160  local *F;
161  for ($f1, $f2) {
162    print "# File: $_\n";
163    unless (open F, $_) {
164      print "# couldn't open $_: $!\n";
165      return 0;
166    }
167    $_ = do { local $/; <F> };
168    close F;
169    comment($_);
170  }
171  return $f1 eq $f2;
172}
173
174my @tests;
175
176for (split /\s*={70,}\s*/, do { local $/; <DATA> }) {
177  s/^\s+//; s/\s+$//;
178  my($c, %f);
179  ($c, @f{m/-{20,}\s+(\S+)\s+-{20,}/g}) = split /\s*-{20,}\s+\S+\s+-{20,}\s*/;
180  push @tests, { code => $c, files => \%f };
181}
182
183my $t;
184for $t (@tests) {
185  print "#\n", ('# ', '-'x70, "\n")x3, "#\n";
186  my $f;
187  for $f (keys %{$t->{files}}) {
188    my @f = split /\//, $f;
189    if (@f > 1) {
190      pop @f;
191      my $path = join '/', @f;
192      mkpath($path) or die "mkpath('$path'): $!\n";
193    }
194    my $txt = $t->{files}{$f};
195    local *F;
196    open F, ">$f" or die "open $f: $!\n";
197    print F "$txt\n";
198    close F;
199    print "# *** writing $f ***\n";
200    comment($txt);
201  }
202
203  print "# *** evaluating test code ***\n";
204  comment($t->{code});
205
206  eval $t->{code};
207  if ($@) {
208    my $err = $@;
209    $err =~ s/^/# *** /mg;
210    print "# *** ERROR ***\n$err\n";
211  }
212  is($@, '');
213
214  for (keys %{$t->{files}}) {
215    unlink $_ or die "unlink('$_'): $!\n";
216  }
217}
218
219sub find_perl
220{
221  my $perl = $^X;
222
223  return $perl if $isVMS;
224
225  my $exe = $Config{'_exe'} || '';
226
227  if ($perl =~ /^perl\Q$exe\E$/i) {
228    $perl = "perl$exe";
229    eval "require File::Spec";
230    if ($@) {
231      $perl = "./$perl";
232    } else {
233      $perl = File::Spec->catfile(File::Spec->curdir(), $perl);
234    }
235  }
236
237  if ($perl !~ /\Q$exe\E$/i) {
238    $perl .= $exe;
239  }
240
241  warn "find_perl: cannot find $perl from $^X" unless -f $perl;
242
243  return $perl;
244}
245
246__DATA__
247
248my $o = ppport(qw(--help));
249ok($o =~ /^Usage:.*ppport\.h/m);
250ok($o =~ /--help/m);
251
252$o = ppport(qw(--version));
253ok($o =~ /^This is.*ppport.*\d+\.\d+(?:_?\d+)?\.$/);
254
255$o = ppport(qw(--nochanges));
256ok($o =~ /^Scanning.*test\.xs/mi);
257ok($o =~ /Analyzing.*test\.xs/mi);
258is(matches($o, '^Scanning', 'm'), 1);
259is(matches($o, 'Analyzing', 'm'), 1);
260ok($o =~ /Uses Perl_newSViv instead of newSViv/);
261
262$o = ppport(qw(--quiet --nochanges));
263ok($o =~ /^\s*$/);
264
265---------------------------- test.xs ------------------------------------------
266
267Perl_newSViv();
268
269===============================================================================
270
271# check if C and C++ comments are filtered correctly
272
273my $o = ppport(qw(--copy=a));
274ok($o =~ /^Scanning.*MyExt\.xs/mi);
275ok($o =~ /Analyzing.*MyExt\.xs/mi);
276is(matches($o, '^Scanning', 'm'), 1);
277ok($o =~ /^Needs to include.*ppport\.h/m);
278ok($o !~ /^Uses grok_bin/m);
279ok($o !~ /^Uses newSVpv/m);
280ok($o =~ /Uses 1 C\+\+ style comment/m);
281ok(eq_files('MyExt.xsa', 'MyExt.ra'));
282
283# check if C++ are left untouched with --cplusplus
284
285$o = ppport(qw(--copy=b --cplusplus));
286ok($o =~ /^Scanning.*MyExt\.xs/mi);
287ok($o =~ /Analyzing.*MyExt\.xs/mi);
288is(matches($o, '^Scanning', 'm'), 1);
289ok($o =~ /^Needs to include.*ppport\.h/m);
290ok($o !~ /^Uses grok_bin/m);
291ok($o !~ /^Uses newSVpv/m);
292ok($o !~ /Uses \d+ C\+\+ style comment/m);
293ok(eq_files('MyExt.xsb', 'MyExt.rb'));
294
295unlink qw(MyExt.xsa MyExt.xsb);
296
297---------------------------- MyExt.xs -----------------------------------------
298
299newSVuv();
300    // newSVpv();
301  XPUSHs(foo);
302/* grok_bin(); */
303
304---------------------------- MyExt.ra -----------------------------------------
305
306#include "ppport.h"
307newSVuv();
308    /* newSVpv(); */
309  XPUSHs(foo);
310/* grok_bin(); */
311
312---------------------------- MyExt.rb -----------------------------------------
313
314#include "ppport.h"
315newSVuv();
316    // newSVpv();
317  XPUSHs(foo);
318/* grok_bin(); */
319
320===============================================================================
321
322my $o = ppport(qw(--nochanges file1.xs));
323ok($o =~ /^Scanning.*file1\.xs/mi);
324ok($o =~ /Analyzing.*file1\.xs/mi);
325ok($o !~ /^Scanning.*file2\.xs/mi);
326ok($o =~ /^Uses newCONSTSUB/m);
327ok($o =~ /^Uses PL_expect/m);
328ok($o =~ /^Uses SvPV_nolen.*depends.*sv_2pv_flags/m);
329ok($o =~ /WARNING: PL_expect/m);
330ok($o =~ /^Analysis completed \(1 warning\)/m);
331ok($o =~ /^Looks good/m);
332
333$o = ppport(qw(--nochanges --nohints file1.xs));
334ok($o =~ /^Scanning.*file1\.xs/mi);
335ok($o =~ /Analyzing.*file1\.xs/mi);
336ok($o !~ /^Scanning.*file2\.xs/mi);
337ok($o =~ /^Uses newCONSTSUB/m);
338ok($o =~ /^Uses PL_expect/m);
339ok($o =~ /^Uses SvPV_nolen.*depends.*sv_2pv_flags/m);
340ok($o =~ /WARNING: PL_expect/m);
341ok($o =~ /^Analysis completed \(1 warning\)/m);
342ok($o =~ /^Looks good/m);
343
344$o = ppport(qw(--nochanges --nohints --nodiag file1.xs));
345ok($o =~ /^Scanning.*file1\.xs/mi);
346ok($o =~ /Analyzing.*file1\.xs/mi);
347ok($o !~ /^Scanning.*file2\.xs/mi);
348ok($o !~ /^Uses newCONSTSUB/m);
349ok($o !~ /^Uses PL_expect/m);
350ok($o !~ /^Uses SvPV_nolen/m);
351ok($o =~ /WARNING: PL_expect/m);
352ok($o =~ /^Analysis completed \(1 warning\)/m);
353ok($o =~ /^Looks good/m);
354
355$o = ppport(qw(--nochanges --quiet file1.xs));
356ok($o =~ /^\s*$/);
357
358$o = ppport(qw(--nochanges file2.xs));
359ok($o =~ /^Scanning.*file2\.xs/mi);
360ok($o =~ /Analyzing.*file2\.xs/mi);
361ok($o !~ /^Scanning.*file1\.xs/mi);
362ok($o =~ /^Uses mXPUSHp/m);
363ok($o =~ /^Needs to include.*ppport\.h/m);
364ok($o !~ /^Looks good/m);
365ok($o =~ /^1 potentially required change detected/m);
366
367$o = ppport(qw(--nochanges --nohints file2.xs));
368ok($o =~ /^Scanning.*file2\.xs/mi);
369ok($o =~ /Analyzing.*file2\.xs/mi);
370ok($o !~ /^Scanning.*file1\.xs/mi);
371ok($o =~ /^Uses mXPUSHp/m);
372ok($o =~ /^Needs to include.*ppport\.h/m);
373ok($o !~ /^Looks good/m);
374ok($o =~ /^1 potentially required change detected/m);
375
376$o = ppport(qw(--nochanges --nohints --nodiag file2.xs));
377ok($o =~ /^Scanning.*file2\.xs/mi);
378ok($o =~ /Analyzing.*file2\.xs/mi);
379ok($o !~ /^Scanning.*file1\.xs/mi);
380ok($o !~ /^Uses mXPUSHp/m);
381ok($o !~ /^Needs to include.*ppport\.h/m);
382ok($o !~ /^Looks good/m);
383ok($o =~ /^1 potentially required change detected/m);
384
385$o = ppport(qw(--nochanges --quiet file2.xs));
386ok($o =~ /^\s*$/);
387
388---------------------------- file1.xs -----------------------------------------
389
390#define NEED_newCONSTSUB
391#define NEED_PL_parser
392#include "ppport.h"
393
394newCONSTSUB();
395SvPV_nolen();
396PL_expect = 0;
397
398---------------------------- file2.xs -----------------------------------------
399
400mXPUSHp(foo);
401
402===============================================================================
403
404my $o = ppport(qw(--nochanges));
405ok($o =~ /^Scanning.*FooBar\.xs/mi);
406ok($o =~ /Analyzing.*FooBar\.xs/mi);
407is(matches($o, '^Scanning', 'm'), 1);
408ok($o !~ /^Looks good/m);
409ok($o =~ /^Uses grok_bin/m);
410
411---------------------------- FooBar.xs ----------------------------------------
412
413newSViv();
414XPUSHs(foo);
415grok_bin();
416
417===============================================================================
418
419my $o = ppport(qw(--nochanges));
420ok($o =~ /^Scanning.*First\.xs/mi);
421ok($o =~ /Analyzing.*First\.xs/mi);
422ok($o =~ /^Scanning.*second\.h/mi);
423ok($o =~ /Analyzing.*second\.h/mi);
424ok($o =~ /^Scanning.*sub.*third\.c/mi);
425ok($o =~ /Analyzing.*sub.*third\.c/mi);
426ok($o !~ /^Scanning.*foobar/mi);
427is(matches($o, '^Scanning', 'm'), 3);
428
429---------------------------- First.xs -----------------------------------------
430
431one
432
433---------------------------- foobar.xyz ---------------------------------------
434
435two
436
437---------------------------- second.h -----------------------------------------
438
439three
440
441---------------------------- sub/third.c --------------------------------------
442
443four
444
445===============================================================================
446
447my $o = ppport(qw(--nochanges));
448ok($o =~ /Possibly wrong #define NEED_foobar in.*test.xs/i);
449
450---------------------------- test.xs ------------------------------------------
451
452#define NEED_foobar
453
454===============================================================================
455
456# And now some complex "real-world" example
457
458my $o = ppport(qw(--copy=f));
459for (qw(main.xs mod1.c mod2.c mod3.c mod4.c mod5.c)) {
460  ok($o =~ /^Scanning.*\Q$_\E/mi);
461  ok($o =~ /Analyzing.*\Q$_\E/i);
462}
463is(matches($o, '^Scanning', 'm'), 6);
464
465is(matches($o, '^Writing copy of', 'm'), 5);
466ok(!-e "mod5.cf");
467
468for (qw(main.xs mod1.c mod2.c mod3.c mod4.c)) {
469  ok($o =~ /^Writing copy of.*\Q$_\E.*with changes/mi);
470  ok(-e "${_}f");
471  ok(eq_files("${_}f", "${_}r"));
472  unlink "${_}f";
473}
474
475---------------------------- main.xs ------------------------------------------
476
477#include "EXTERN.h"
478#include "perl.h"
479#include "XSUB.h"
480
481#define NEED_newCONSTSUB
482#define NEED_grok_hex_GLOBAL
483#include "ppport.h"
484
485newCONSTSUB();
486grok_hex();
487Perl_grok_bin(aTHX_ foo, bar);
488
489/* some comment */
490
491perl_eval_pv();
492grok_bin();
493Perl_grok_bin(bar, sv_no);
494
495---------------------------- mod1.c -------------------------------------------
496
497#include "EXTERN.h"
498#include "perl.h"
499#include "XSUB.h"
500
501#define NEED_grok_bin_GLOBAL
502#define NEED_newCONSTSUB
503#include "ppport.h"
504
505newCONSTSUB();
506grok_bin();
507{
508  Perl_croak ("foo");
509  Perl_sv_catpvf();  /* I know it's wrong ;-) */
510}
511
512---------------------------- mod2.c -------------------------------------------
513
514#include "EXTERN.h"
515#include "perl.h"
516#include "XSUB.h"
517
518#define NEED_eval_pv
519#include "ppport.h"
520
521newSViv();
522
523/*
524   eval_pv();
525*/
526
527---------------------------- mod3.c -------------------------------------------
528
529#include "EXTERN.h"
530#include "perl.h"
531#include "XSUB.h"
532
533grok_oct();
534eval_pv();
535
536---------------------------- mod4.c -------------------------------------------
537
538#include "EXTERN.h"
539#include "perl.h"
540#include "XSUB.h"
541
542START_MY_CXT;
543
544---------------------------- mod5.c -------------------------------------------
545
546#include "EXTERN.h"
547#include "perl.h"
548#include "XSUB.h"
549
550#include "ppport.h"
551call_pv();
552
553---------------------------- main.xsr -----------------------------------------
554
555#include "EXTERN.h"
556#include "perl.h"
557#include "XSUB.h"
558
559#define NEED_eval_pv_GLOBAL
560#define NEED_grok_hex
561#define NEED_newCONSTSUB_GLOBAL
562#include "ppport.h"
563
564newCONSTSUB();
565grok_hex();
566grok_bin(foo, bar);
567
568/* some comment */
569
570eval_pv();
571grok_bin();
572grok_bin(bar, PL_sv_no);
573
574---------------------------- mod1.cr ------------------------------------------
575
576#include "EXTERN.h"
577#include "perl.h"
578#include "XSUB.h"
579
580#define NEED_grok_bin_GLOBAL
581#include "ppport.h"
582
583newCONSTSUB();
584grok_bin();
585{
586  Perl_croak (aTHX_ "foo");
587  Perl_sv_catpvf(aTHX);  /* I know it's wrong ;-) */
588}
589
590---------------------------- mod2.cr ------------------------------------------
591
592#include "EXTERN.h"
593#include "perl.h"
594#include "XSUB.h"
595
596
597newSViv();
598
599/*
600   eval_pv();
601*/
602
603---------------------------- mod3.cr ------------------------------------------
604
605#include "EXTERN.h"
606#include "perl.h"
607#include "XSUB.h"
608#define NEED_grok_oct
609#include "ppport.h"
610
611grok_oct();
612eval_pv();
613
614---------------------------- mod4.cr ------------------------------------------
615
616#include "EXTERN.h"
617#include "perl.h"
618#include "XSUB.h"
619#include "ppport.h"
620
621START_MY_CXT;
622
623===============================================================================
624
625my $o = ppport(qw(--nochanges));
626ok($o =~ /Uses grok_hex/m);
627ok($o !~ /Looks good/m);
628
629$o = ppport(qw(--nochanges --compat-version=5.8.0));
630ok($o !~ /Uses grok_hex/m);
631ok($o =~ /Looks good/m);
632
633---------------------------- FooBar.xs ----------------------------------------
634
635grok_hex();
636
637===============================================================================
638
639my $o = ppport(qw(--nochanges));
640ok($o =~ /Uses SvPVutf8_force, which may not be portable/m);
641
642$o = ppport(qw(--nochanges --compat-version=5.5.3));
643ok($o =~ /Uses SvPVutf8_force, which may not be portable/m);
644
645$o = ppport(qw(--nochanges --compat-version=5.005_03));
646ok($o =~ /Uses SvPVutf8_force, which may not be portable/m);
647
648$o = ppport(qw(--nochanges --compat-version=5.6.0));
649ok($o !~ /Uses SvPVutf8_force/m);
650
651$o = ppport(qw(--nochanges --compat-version=5.006));
652ok($o !~ /Uses SvPVutf8_force/m);
653
654$o = ppport(qw(--nochanges --compat-version=5.999.999));
655ok($o !~ /Uses SvPVutf8_force/m);
656
657$o = ppport(qw(--nochanges --compat-version=8.0.0));
658ok($o =~ /Only Perl \[57\] are supported/m);
659
660$o = ppport(qw(--nochanges --compat-version=5.1000.999));
661ok($o =~ /Invalid version number: 5.1000.999/m);
662
663$o = ppport(qw(--nochanges --compat-version=5.999.1000));
664ok($o =~ /Invalid version number: 5.999.1000/m);
665
666---------------------------- FooBar.xs ----------------------------------------
667
668SvPVutf8_force();
669
670===============================================================================
671
672my $o = ppport(qw(--nochanges));
673ok($o !~ /potentially required change/);
674is(matches($o, '^Looks good', 'm'), 2);
675
676---------------------------- FooBar.xs ----------------------------------------
677
678#define NEED_grok_numeric_radix
679#define NEED_grok_number
680#include "ppport.h"
681
682GROK_NUMERIC_RADIX();
683grok_number();
684
685---------------------------- foo.c --------------------------------------------
686
687#include "ppport.h"
688
689call_pv();
690
691===============================================================================
692
693# check --api-info option
694
695my $o = ppport(qw(--api-info=INT2PTR));
696my %found = map {($_ => 1)} $o =~ /^===\s+(\w+)\s+===/mg;
697is(scalar keys %found, 1, "found 1 key");
698ok(exists $found{INT2PTR});
699is(matches($o, '^Supported at least since perl-5\.6\.0', 'm'), 1, "INT2PTR supported without ppport.h to 5.6.0");
700is(matches($o, '^ppport.h additionally provides support at least back to perl-5\.003', 'm'), 1, "INT2PTR supported with ppport.h to 5.003");
701
702$o = ppport(qw(--api-info=Zero));
703%found = map {($_ => 1)} $o =~ /^===\s+(\w+)\s+===/mg;
704is(scalar keys %found, 1, "found 1 key");
705ok(exists $found{Zero});
706is(matches($o, '^Supported at least since perl-5.003', 'm'), 1, "Zero supported to 5.003");
707
708$o = ppport(qw(--api-info=/Zero/));
709%found = map {($_ => 1)} $o =~ /^===\s+(\w+)\s+===/mg;
710is(scalar keys %found, 2, "found 2 keys");
711ok(exists $found{Zero});
712ok(exists $found{ZeroD});
713
714===============================================================================
715
716# check --list-provided option
717
718my @o = ppport(qw(--list-provided));
719my %p;
720my $fail = 0;
721for (@o) {
722  my($name, $flags) = /^(\w+)(?:\s+\[(\w+(?:,\s+\w+)*)\])?$/ or $fail++;
723  {
724    'warnings'->unimport('uninitialized') if ivers($]) > ivers('5.006');
725    exists $p{$name} and $fail++;
726  }
727  $p{$name} = defined $flags ? { map { ($_ => 1) } $flags =~ /(\w+)/g } : '';
728}
729ok(@o > 100);
730is($fail, 0);
731
732ok(exists $p{call_pv});
733ok(not ref $p{call_pv});
734
735ok(exists $p{grok_bin});
736is(ref $p{grok_bin}, 'HASH');
737is(scalar keys %{$p{grok_bin}}, 2);
738ok($p{grok_bin}{explicit});
739ok($p{grok_bin}{depend});
740
741ok(exists $p{gv_stashpvn});
742is(ref $p{gv_stashpvn}, 'HASH');
743is(scalar keys %{$p{gv_stashpvn}}, 2);
744ok($p{gv_stashpvn}{depend});
745ok($p{gv_stashpvn}{hint});
746
747ok(exists $p{sv_catpvf_mg});
748is(ref $p{sv_catpvf_mg}, 'HASH');
749is(scalar keys %{$p{sv_catpvf_mg}}, 2);
750ok($p{sv_catpvf_mg}{explicit});
751ok($p{sv_catpvf_mg}{depend});
752
753ok(exists $p{PL_signals});
754is(ref $p{PL_signals}, 'HASH');
755is(scalar keys %{$p{PL_signals}}, 1);
756ok($p{PL_signals}{explicit});
757
758===============================================================================
759
760# check --list-unsupported option
761
762my @o = ppport(qw(--list-unsupported));
763my %p;
764my $fail = 0;
765for (@o) {
766  my($name, $ver) = /^(\w+)\s*\.*\s*([\d._]+)$/ or $fail++;
767  { exists $p{$name} and $fail++; }
768  $p{$name} = $ver;
769}
770ok(@o > 100);
771is($fail, 0);
772
773ok(exists $p{utf8_distance});
774is($p{utf8_distance}, '5.6.0');
775
776ok(exists $p{save_generic_svref});
777is($p{save_generic_svref}, '5.005_03');
778
779===============================================================================
780
781# check --nofilter option
782
783my $o = ppport(qw(--nochanges));
784ok($o =~ /^Scanning.*foo\.cpp/mi);
785ok($o =~ /Analyzing.*foo\.cpp/mi);
786is(matches($o, '^Scanning', 'm'), 1);
787is(matches($o, 'Analyzing', 'm'), 1);
788
789$o = ppport(qw(--nochanges foo.cpp foo.o Makefile.PL));
790ok($o =~ /Skipping the following files \(use --nofilter to avoid this\):/m);
791is(matches($o, '^\|\s+foo\.o', 'mi'), 1);
792is(matches($o, '^\|\s+Makefile\.PL', 'mi'), 1);
793ok($o =~ /^Scanning.*foo\.cpp/mi);
794ok($o =~ /Analyzing.*foo\.cpp/mi);
795is(matches($o, '^Scanning', 'm'), 1);
796is(matches($o, 'Analyzing', 'm'), 1);
797
798$o = ppport(qw(--nochanges --nofilter foo.cpp foo.o Makefile.PL));
799ok($o =~ /^Scanning.*foo\.cpp/mi);
800ok($o =~ /Analyzing.*foo\.cpp/mi);
801ok($o =~ /^Scanning.*foo\.o/mi);
802ok($o =~ /Analyzing.*foo\.o/mi);
803ok($o =~ /^Scanning.*Makefile/mi);
804ok($o =~ /Analyzing.*Makefile/mi);
805is(matches($o, '^Scanning', 'm'), 3);
806is(matches($o, 'Analyzing', 'm'), 3);
807
808---------------------------- foo.cpp ------------------------------------------
809
810newSViv();
811
812---------------------------- foo.o --------------------------------------------
813
814newSViv();
815
816---------------------------- Makefile.PL --------------------------------------
817
818newSViv();
819
820===============================================================================
821
822# check if explicit variables are handled propery
823
824my $o = ppport(qw(--copy=a));
825ok($o =~ /^Needs to include.*ppport\.h/m);
826ok($o =~ /^Uses PL_signals/m);
827ok($o =~ /^File needs PL_signals, adding static request/m);
828ok(eq_files('MyExt.xsa', 'MyExt.ra'));
829
830unlink qw(MyExt.xsa);
831
832---------------------------- MyExt.xs -----------------------------------------
833
834PL_signals = 123;
835if (PL_signals == 42)
836  foo();
837
838---------------------------- MyExt.ra -----------------------------------------
839
840#define NEED_PL_signals
841#include "ppport.h"
842PL_signals = 123;
843if (PL_signals == 42)
844  foo();
845
846===============================================================================
847
848my $o = ppport(qw(--nochanges file.xs));
849ok($o =~ /^Uses PL_copline/m);
850ok($o =~ /WARNING: PL_copline/m);
851ok($o =~ /^Uses SvUOK/m);
852ok($o =~ /WARNING: Uses SvUOK, which may not be portable/m);
853ok($o =~ /^Analysis completed \(2 warnings\)/m);
854ok($o =~ /^Looks good/m);
855
856$o = ppport(qw(--nochanges --compat-version=5.8.0 file.xs));
857ok($o =~ /^Uses PL_copline/m);
858ok($o =~ /WARNING: PL_copline/m);
859ok($o !~ /WARNING: Uses SvUOK, which may not be portable/m);
860ok($o =~ /^Analysis completed \(1 warning\)/m);
861ok($o =~ /^Looks good/m);
862
863---------------------------- file.xs -----------------------------------------
864
865#define NEED_PL_parser
866#include "ppport.h"
867SvUOK
868PL_copline
869
870===============================================================================
871
872my $o = ppport(qw(--copy=f));
873
874for (qw(file.xs)) {
875  ok($o =~ /^Writing copy of.*\Q$_\E.*with changes/mi);
876  ok(-e "${_}f");
877  ok(eq_files("${_}f", "${_}r"));
878  unlink "${_}f";
879}
880
881---------------------------- file.xs -----------------------------------------
882
883a_string = "sv_undef"
884a_char = 'sv_yes'
885#define SOMETHING defgv
886/* C-comment: sv_tainted */
887#
888# This is just a big XS comment using sv_no
889#
890/* The following, is NOT an XS comment! */
891#  define SOMETHING_ELSE defgv + \
892                         sv_undef
893
894---------------------------- file.xsr -----------------------------------------
895
896#include "ppport.h"
897a_string = "sv_undef"
898a_char = 'sv_yes'
899#define SOMETHING PL_defgv
900/* C-comment: sv_tainted */
901#
902# This is just a big XS comment using sv_no
903#
904/* The following, is NOT an XS comment! */
905#  define SOMETHING_ELSE PL_defgv + \
906                         PL_sv_undef
907
908===============================================================================
909
910my $o = ppport(qw(--copy=f));
911
912for (qw(file.xs)) {
913  ok($o =~ /^Writing copy of.*\Q$_\E.*with changes/mi);
914  ok(-e "${_}f");
915  ok(eq_files("${_}f", "${_}r"));
916  unlink "${_}f";
917}
918
919---------------------------- file.xs -----------------------------------------
920
921#define NEED_warner
922#include "ppport.h"
923Perl_croak_nocontext("foo");
924Perl_croak("bar");
925croak("foo");
926croak_nocontext("foo");
927Perl_warner_nocontext("foo");
928Perl_warner("foo");
929warner_nocontext("foo");
930warner("foo");
931
932---------------------------- file.xsr -----------------------------------------
933
934#define NEED_warner
935#include "ppport.h"
936Perl_croak_nocontext("foo");
937Perl_croak(aTHX_ "bar");
938croak("foo");
939croak_nocontext("foo");
940Perl_warner_nocontext("foo");
941Perl_warner(aTHX_ "foo");
942warner_nocontext("foo");
943warner("foo");
944
945