Upgrade to Devel::PPPort 3.00.
[p5sagit/p5-mst-13.2.git] / ext / Devel / PPPort / t / ppphtest.t
CommitLineData
adfe19db 1################################################################################
2#
3# !!!!! Do NOT edit this file directly! !!!!!
4#
5# Edit mktests.PL and/or parts/inc/ppphtest instead.
6#
7################################################################################
8
9BEGIN {
10 if ($ENV{'PERL_CORE'}) {
11 chdir 't' if -d 't';
12 @INC = ('../lib', '../ext/Devel/PPPort/t') if -d '../lib' && -d '../ext';
13 require Config; import Config;
14 use vars '%Config';
15 if (" $Config{'extensions'} " !~ m[ Devel/PPPort ] ) {
16 print "1..0 # Skip -- Perl configured without Devel::PPPort module\n";
17 exit 0;
18 }
19 }
20 else {
21 unshift @INC, 't';
22 }
23
24 eval "use Test";
25 if ($@) {
26 require 'testutil.pl';
27 print "1..131\n";
28 }
29 else {
30 plan(tests => 131);
31 }
32}
33
34use Devel::PPPort;
35use strict;
36$^W = 1;
37
38use File::Path qw/rmtree mkpath/;
39
40my $tmp = 'ppptmp';
41
42rmtree($tmp) if -d $tmp;
43mkpath($tmp) or die "mkpath $tmp: $!\n";
44chdir($tmp) or die "chdir $tmp: $!\n";
45
46my $inc = '';
47if ($ENV{'PERL_CORE'}) {
48 $inc = '-I../../lib' if -d '../../lib';
49}
50
51END {
52 chdir("..") if !-d $tmp && -d "../$tmp";
53 rmtree($tmp);
54}
55
56ok(&Devel::PPPort::WriteFile("ppport.h"));
57
58sub ppport
59{
60 my @args = @_;
61 print "# *** running $^X $inc ppport.h @args ***\n";
62 my $out = join '', `$^X $inc ppport.h @args`;
63 my $copy = $out;
64 $copy =~ s/^/# | /mg;
65 print "$copy\n";
66 return $out;
67}
68
69sub matches
70{
71 my($str, $re, $mod) = @_;
72 my @n;
73 eval "\@n = \$str =~ /$re/g$mod;";
74 if ($@) {
75 my $err = $@;
76 $err =~ s/^/# *** /mg;
77 print "# *** ERROR ***\n$err\n";
78 }
79 return $@ ? -42 : scalar @n;
80}
81
82sub eq_files
83{
84 my($f1, $f2) = @_;
85 return 0 unless -e $f1 && -e $f2;
86 local *F;
87 for ($f1, $f2) {
88 print "# File: $_\n";
89 unless (open F, $_) {
90 print "# couldn't open $_: $!\n";
91 return 0;
92 }
93 $_ = do { local $/; <F> };
94 close F;
95 my $copy = $_;
96 $copy =~ s/^/# | /mg;
97 print "$copy\n";
98 }
99 return $f1 eq $f2;
100}
101
102my @tests;
103
104for (split /\s*={70,}\s*/, do { local $/; <DATA> }) {
105 s/^\s+//; s/\s+$//;
106 my($c, %f);
107 ($c, @f{m/-{20,}\s+(\S+)\s+-{20,}/g}) = split /\s*-{20,}\s+\S+\s+-{20,}\s*/;
108 push @tests, { code => $c, files => \%f };
109}
110
111my $t;
112for $t (@tests) {
113 my $f;
114 for $f (keys %{$t->{files}}) {
115 my @f = split /\//, $f;
116 if (@f > 1) {
117 pop @f;
118 my $path = join '/', @f;
119 mkpath($path) or die "mkpath('$path'): $!\n";
120 }
121 my $txt = $t->{files}{$f};
122 local *F;
123 open F, ">$f" or die "open $f: $!\n";
124 print F "$txt\n";
125 close F;
126 $txt =~ s/^/# | /mg;
127 print "# *** writing $f ***\n$txt\n";
128 }
129
130 eval $t->{code};
131 if ($@) {
132 my $err = $@;
133 $err =~ s/^/# *** /mg;
134 print "# *** ERROR ***\n$err\n";
135 }
136 ok($@, '');
137
138 for (keys %{$t->{files}}) {
139 unlink $_ or die "unlink('$_'): $!\n";
140 }
141}
142
143__DATA__
144
145my $o = ppport(qw(--help));
146ok($o =~ /^Usage:.*ppport\.h/m);
147ok($o =~ /--help/m);
148
149$o = ppport(qw(--nochanges));
150ok($o =~ /^scanning.*test\.xs/mi);
151ok($o =~ /analyzing.*test\.xs/mi);
152ok(matches($o, '^scanning', 'mi'), 1);
153ok(matches($o, 'analyzing', 'mi'), 1);
154ok($o =~ /Uses Perl_newSViv instead of newSViv/);
155
156$o = ppport(qw(--quiet --nochanges));
157ok($o =~ /^\s*$/);
158
159---------------------------- test.xs ------------------------------------------
160
161Perl_newSViv();
162
163===============================================================================
164
165# check if C and C++ comments are filtered correctly
166
167my $o = ppport(qw(--copy=a));
168ok($o =~ /^scanning.*MyExt\.xs/mi);
169ok($o =~ /analyzing.*MyExt\.xs/mi);
170ok(matches($o, '^scanning', 'mi'), 1);
171ok($o =~ /^Needs to include.*ppport\.h/m);
172ok($o !~ /^Uses grok_bin/m);
173ok($o !~ /^Uses newSVpv/m);
174ok($o =~ /Uses 1 C\+\+ style comment/m);
175ok(eq_files('MyExt.xsa', 'MyExt.ra'));
176
177# check if C++ are left untouched with --cplusplus
178
179$o = ppport(qw(--copy=b --cplusplus));
180ok($o =~ /^scanning.*MyExt\.xs/mi);
181ok($o =~ /analyzing.*MyExt\.xs/mi);
182ok(matches($o, '^scanning', 'mi'), 1);
183ok($o =~ /^Needs to include.*ppport\.h/m);
184ok($o !~ /^Uses grok_bin/m);
185ok($o !~ /^Uses newSVpv/m);
186ok($o !~ /Uses \d+ C\+\+ style comment/m);
187ok(eq_files('MyExt.xsb', 'MyExt.rb'));
188
189unlink qw(MyExt.xsa MyExt.xsb);
190
191---------------------------- MyExt.xs -----------------------------------------
192
193newSVuv();
194 // newSVpv();
195 XPUSHs(foo);
196/* grok_bin(); */
197
198---------------------------- MyExt.ra -----------------------------------------
199
200#include "ppport.h"
201newSVuv();
202 /* newSVpv(); */
203 XPUSHs(foo);
204/* grok_bin(); */
205
206---------------------------- MyExt.rb -----------------------------------------
207
208#include "ppport.h"
209newSVuv();
210 // newSVpv();
211 XPUSHs(foo);
212/* grok_bin(); */
213
214===============================================================================
215
216my $o = ppport(qw(--nochanges file1.xs));
217ok($o =~ /^scanning.*file1\.xs/mi);
218ok($o =~ /analyzing.*file1\.xs/mi);
219ok($o !~ /^scanning.*file2\.xs/mi);
220ok($o =~ /^Uses newCONSTSUB/m);
221ok($o =~ /^Uses SvPV_nolen.*depends.*sv_2pv_nolen/m);
222ok($o =~ /hint for newCONSTSUB/m);
223ok($o !~ /hint for sv_2pv_nolen/m);
224ok($o =~ /^Looks good/m);
225
226$o = ppport(qw(--nochanges --nohints file1.xs));
227ok($o =~ /^scanning.*file1\.xs/mi);
228ok($o =~ /analyzing.*file1\.xs/mi);
229ok($o !~ /^scanning.*file2\.xs/mi);
230ok($o =~ /^Uses newCONSTSUB/m);
231ok($o =~ /^Uses SvPV_nolen.*depends.*sv_2pv_nolen/m);
232ok($o !~ /hint for newCONSTSUB/m);
233ok($o !~ /hint for sv_2pv_nolen/m);
234ok($o =~ /^Looks good/m);
235
236$o = ppport(qw(--nochanges --nohints --nodiag file1.xs));
237ok($o =~ /^scanning.*file1\.xs/mi);
238ok($o =~ /analyzing.*file1\.xs/mi);
239ok($o !~ /^scanning.*file2\.xs/mi);
240ok($o !~ /^Uses newCONSTSUB/m);
241ok($o !~ /^Uses SvPV_nolen/m);
242ok($o !~ /hint for newCONSTSUB/m);
243ok($o !~ /hint for sv_2pv_nolen/m);
244ok($o =~ /^Looks good/m);
245
246$o = ppport(qw(--nochanges --quiet file1.xs));
247ok($o =~ /^\s*$/);
248
249$o = ppport(qw(--nochanges file2.xs));
250ok($o =~ /^scanning.*file2\.xs/mi);
251ok($o =~ /analyzing.*file2\.xs/mi);
252ok($o !~ /^scanning.*file1\.xs/mi);
253ok($o =~ /^Uses mXPUSHp/m);
254ok($o =~ /^Needs to include.*ppport\.h/m);
255ok($o !~ /^Looks good/m);
256ok($o =~ /^1 potentially required change detected/m);
257
258$o = ppport(qw(--nochanges --nohints file2.xs));
259ok($o =~ /^scanning.*file2\.xs/mi);
260ok($o =~ /analyzing.*file2\.xs/mi);
261ok($o !~ /^scanning.*file1\.xs/mi);
262ok($o =~ /^Uses mXPUSHp/m);
263ok($o =~ /^Needs to include.*ppport\.h/m);
264ok($o !~ /^Looks good/m);
265ok($o =~ /^1 potentially required change detected/m);
266
267$o = ppport(qw(--nochanges --nohints --nodiag file2.xs));
268ok($o =~ /^scanning.*file2\.xs/mi);
269ok($o =~ /analyzing.*file2\.xs/mi);
270ok($o !~ /^scanning.*file1\.xs/mi);
271ok($o !~ /^Uses mXPUSHp/m);
272ok($o !~ /^Needs to include.*ppport\.h/m);
273ok($o !~ /^Looks good/m);
274ok($o =~ /^1 potentially required change detected/m);
275
276$o = ppport(qw(--nochanges --quiet file2.xs));
277ok($o =~ /^\s*$/);
278
279---------------------------- file1.xs -----------------------------------------
280
281#define NEED_newCONSTSUB
282#define NEED_sv_2pv_nolen
283#include "ppport.h"
284
285newCONSTSUB();
286SvPV_nolen();
287
288---------------------------- file2.xs -----------------------------------------
289
290mXPUSHp(foo);
291
292===============================================================================
293
294my $o = ppport(qw(--nochanges));
295ok($o =~ /^scanning.*FooBar\.xs/mi);
296ok($o =~ /analyzing.*FooBar\.xs/mi);
297ok(matches($o, '^scanning', 'mi'), 1);
298ok($o !~ /^Looks good/m);
299ok($o =~ /^Uses grok_bin/m);
300
301---------------------------- FooBar.xs ----------------------------------------
302
303newSViv();
304XPUSHs(foo);
305grok_bin();
306
307===============================================================================
308
309my $o = ppport(qw(--nochanges));
310ok($o =~ /^scanning.*First\.xs/mi);
311ok($o =~ /analyzing.*First\.xs/mi);
312ok($o =~ /^scanning.*second\.h/mi);
313ok($o =~ /analyzing.*second\.h/mi);
314ok($o =~ /^scanning.*sub.*third\.c/mi);
315ok($o =~ /analyzing.*sub.*third\.c/mi);
316ok($o !~ /^scanning.*foobar/mi);
317ok(matches($o, '^scanning', 'mi'), 3);
318
319---------------------------- First.xs -----------------------------------------
320
321one
322
323---------------------------- foobar.xyz ---------------------------------------
324
325two
326
327---------------------------- second.h -----------------------------------------
328
329three
330
331---------------------------- sub/third.c --------------------------------------
332
333four
334
335===============================================================================
336
337my $o = ppport(qw(--nochanges));
338ok($o =~ /Possibly wrong #define NEED_foobar in.*test.xs/i);
339
340---------------------------- test.xs ------------------------------------------
341
342#define NEED_foobar
343
344===============================================================================
345
346# And now some complex "real-world" example
347
348my $o = ppport(qw(--copy=f));
349for (qw(main.xs mod1.c mod2.c mod3.c mod4.c mod5.c)) {
350 ok($o =~ /^scanning.*\Q$_\E/mi);
351 ok($o =~ /analyzing.*\Q$_\E/i);
352}
353ok(matches($o, '^scanning', 'mi'), 6);
354
355ok(matches($o, '^Writing copy of', 'mi'), 5);
356ok(!-e "mod5.cf");
357
358for (qw(main.xs mod1.c mod2.c mod3.c mod4.c)) {
359 ok($o =~ /^Writing copy of.*\Q$_\E.*with changes/mi);
360 ok(-e "${_}f");
361 ok(eq_files("${_}f", "${_}r"));
362 unlink "${_}f";
363}
364
365---------------------------- main.xs ------------------------------------------
366
367#include "EXTERN.h"
368#include "perl.h"
369#include "XSUB.h"
370
371#define NEED_newCONSTSUB
372#define NEED_grok_hex_GLOBAL
373#include "ppport.h"
374
375newCONSTSUB();
376grok_hex();
377Perl_grok_bin(aTHX_ foo, bar);
378
379/* some comment */
380
381perl_eval_pv();
382grok_bin();
383Perl_grok_bin(bar, sv_no);
384
385---------------------------- mod1.c -------------------------------------------
386
387#include "EXTERN.h"
388#include "perl.h"
389#include "XSUB.h"
390
391#define NEED_grok_bin_GLOBAL
392#define NEED_newCONSTSUB
393#include "ppport.h"
394
395newCONSTSUB();
396grok_bin();
397{
398 Perl_croak ("foo");
399 Perl_sv_catpvf(); /* I know it's wrong ;-) */
400}
401
402---------------------------- mod2.c -------------------------------------------
403
404#include "EXTERN.h"
405#include "perl.h"
406#include "XSUB.h"
407
408#define NEED_eval_pv
409#include "ppport.h"
410
411newSViv();
412
413/*
414 eval_pv();
415*/
416
417---------------------------- mod3.c -------------------------------------------
418
419#include "EXTERN.h"
420#include "perl.h"
421#include "XSUB.h"
422
423grok_oct();
424eval_pv();
425
426---------------------------- mod4.c -------------------------------------------
427
428#include "EXTERN.h"
429#include "perl.h"
430#include "XSUB.h"
431
432START_MY_CXT;
433
434---------------------------- mod5.c -------------------------------------------
435
436#include "EXTERN.h"
437#include "perl.h"
438#include "XSUB.h"
439
440#include "ppport.h"
441call_pv();
442
443---------------------------- main.xsr -----------------------------------------
444
445#include "EXTERN.h"
446#include "perl.h"
447#include "XSUB.h"
448
449#define NEED_eval_pv_GLOBAL
450#define NEED_grok_hex
451#define NEED_newCONSTSUB_GLOBAL
452#include "ppport.h"
453
454newCONSTSUB();
455grok_hex();
456grok_bin(foo, bar);
457
458/* some comment */
459
460eval_pv();
461grok_bin();
462grok_bin(bar, PL_sv_no);
463
464---------------------------- mod1.cr ------------------------------------------
465
466#include "EXTERN.h"
467#include "perl.h"
468#include "XSUB.h"
469
470#define NEED_grok_bin_GLOBAL
471#include "ppport.h"
472
473newCONSTSUB();
474grok_bin();
475{
476 Perl_croak (aTHX_ "foo");
477 Perl_sv_catpvf(aTHX); /* I know it's wrong ;-) */
478}
479
480---------------------------- mod2.cr ------------------------------------------
481
482#include "EXTERN.h"
483#include "perl.h"
484#include "XSUB.h"
485
486
487newSViv();
488
489/*
490 eval_pv();
491*/
492
493---------------------------- mod3.cr ------------------------------------------
494
495#include "EXTERN.h"
496#include "perl.h"
497#include "XSUB.h"
498#define NEED_grok_oct
499#include "ppport.h"
500
501grok_oct();
502eval_pv();
503
504---------------------------- mod4.cr ------------------------------------------
505
506#include "EXTERN.h"
507#include "perl.h"
508#include "XSUB.h"
509#include "ppport.h"
510
511START_MY_CXT;
512
513===============================================================================
514
515my $o = ppport(qw(--nochanges));
516ok($o =~ /Uses grok_hex/m);
517ok($o !~ /Looks good/m);
518
519$o = ppport(qw(--nochanges --compat-version=5.8.0));
520ok($o !~ /Uses grok_hex/m);
521ok($o =~ /Looks good/m);
522
523---------------------------- FooBar.xs ----------------------------------------
524
525grok_hex();
526
527===============================================================================
528
529my $o = ppport(qw(--nochanges));
530ok($o =~ /Uses SvPVutf8_force, which may not be portable/m);
531
532$o = ppport(qw(--nochanges --compat-version=5.6.0));
533ok($o !~ /Uses SvPVutf8_force/m);
534
535---------------------------- FooBar.xs ----------------------------------------
536
537SvPVutf8_force();
538