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