modules.t 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. # -*- cperl -*-
  2. # t/modules.t [OPTIONS] [t/mymodules]
  3. # check if some common CPAN modules exist and
  4. # can be compiled successfully. Only B::C is fatal,
  5. # CC and Bytecode optional. Use -all for all three (optional), and
  6. # -log for the reports (now default).
  7. #
  8. # OPTIONS:
  9. # -all - run also B::CC and B::Bytecode
  10. # -subset - run only random 10 of all modules. default if ! -d .svn
  11. # -no-subset - all 100 modules
  12. # -no-date - no date added at the logfile
  13. # -t - run also tests
  14. # -log - save log file. default on test10 and without subset
  15. # -keep - keep the source, perlcc -S
  16. #
  17. # The list in t/mymodules comes from two bigger projects.
  18. # Recommended general lists are Task::Kensho and http://ali.as/top100/
  19. # We are using 10 problematic modules from the latter.
  20. # We are NOT running the full module testsuite yet with -t, we can do that
  21. # in another author test to burn CPU for a few hours resp. days.
  22. #
  23. # Reports:
  24. # for p in 5.6.2 5.8.9 5.10.1 5.12.2; do make -S clean; perl$p Makefile.PL; make; perl$p -Mblib t/modules.t -log; done
  25. #
  26. # How to installed skip modules:
  27. # grep ^skip log.modules-bla|perl -lane'print $F[1]'| xargs perlbla -S cpan
  28. # or t/testm.sh -s
  29. use strict;
  30. use Test::More;
  31. use File::Temp;
  32. # Try some simple XS module which exists in 5.6.2 and blead
  33. # otherwise we'll get a bogus 40% failure rate
  34. my $staticxs = '';
  35. BEGIN {
  36. $staticxs = '--staticxs';
  37. # check whether linking with xs works at all. Try with and without --staticxs
  38. if ($^O eq 'darwin') { $staticxs = ''; goto BEGIN_END; }
  39. my $X = $^X =~ m/\s/ ? qq{"$^X"} : $^X;
  40. my $tmp = File::Temp->new(TEMPLATE => 'pccXXXXX');
  41. my $out = $tmp->filename;
  42. my $Mblib = $^O eq 'MSWin32' ? '-Iblib\arch -Iblib\lib' : "-Iblib/arch -Iblib/lib";
  43. my $result = `$X $Mblib blib/script/perlcc -O3 --staticxs -o$out -e"use Data::Dumper;"`;
  44. my $exe = $^O eq 'MSWin32' ? "$out.exe" : $out;
  45. unless (-e $exe or -e 'a.out') {
  46. my $cmd = qq($X $Mblib blib/script/perlcc -O3 -o$out -e"use Data::Dumper;");
  47. warn $cmd."\n" if $ENV{TEST_VERBOSE};
  48. my $result = `$cmd`;
  49. unless (-e $out or -e 'a.out') {
  50. plan skip_all => "perlcc cannot link XS module Data::Dumper. Most likely wrong ldopts.";
  51. unlink $out;
  52. exit;
  53. } else {
  54. $staticxs = '';
  55. }
  56. } else {
  57. diag "-O3 --staticxs ok";
  58. }
  59. BEGIN_END:
  60. unshift @INC, 't';
  61. }
  62. our %modules;
  63. our $log = 0;
  64. use modules;
  65. require "test.pl";
  66. my $opts_to_test = 1;
  67. my $do_test;
  68. $opts_to_test = 3 if grep /^-all$/, @ARGV;
  69. $do_test = 1 if grep /^-t$/, @ARGV;
  70. # Determine list of modules to action.
  71. our @modules = get_module_list();
  72. my $test_count = scalar @modules * $opts_to_test * ($do_test ? 5 : 4);
  73. # $test_count -= 4 * $opts_to_test * (scalar @modules - scalar(keys %modules));
  74. plan tests => $test_count;
  75. use Config;
  76. use B::C;
  77. use POSIX qw(strftime);
  78. eval { require IPC::Run; };
  79. my $have_IPC_Run = defined $IPC::Run::VERSION;
  80. log_diag("Warning: IPC::Run is not available. Error trapping will be limited, no timeouts.")
  81. unless $have_IPC_Run;
  82. my @opts = ("-O3"); # only B::C
  83. @opts = ("-O3", "-O", "-B") if grep /-all/, @ARGV; # all 3 compilers
  84. my $perlversion = perlversion();
  85. $log = 0 if @ARGV;
  86. $log = 1 if grep /top100$/, @ARGV;
  87. $log = 1 if grep /-log/, @ARGV or $ENV{TEST_LOG};
  88. my $nodate = 1 if grep /-no-date/, @ARGV;
  89. my $keep = 1 if grep /-keep/, @ARGV;
  90. if ($log) {
  91. $log = (@ARGV and !$nodate)
  92. ? "log.modules-$perlversion-".strftime("%Y%m%d-%H%M%S",localtime)
  93. : "log.modules-$perlversion";
  94. if (-e $log) {
  95. use File::Copy;
  96. copy $log, "$log.bak";
  97. }
  98. open(LOG, ">", "$log");
  99. close LOG;
  100. }
  101. unless (is_subset) {
  102. my $svnrev = "";
  103. if (-d '.svn') {
  104. local $ENV{LC_MESSAGES} = "C";
  105. $svnrev = `svn info|grep Revision:`;
  106. chomp $svnrev;
  107. $svnrev =~ s/Revision:\s+/r/;
  108. my $svnstat = `svn status lib/B/C.pm t/test.pl t/*.t`;
  109. chomp $svnstat;
  110. $svnrev .= " M" if $svnstat;
  111. } elsif (-d '.git') {
  112. local $ENV{LC_MESSAGES} = "C";
  113. $svnrev = `git log -1 --pretty=format:"%h %ad | %s" --date=short`;
  114. chomp $svnrev;
  115. my $gitdiff = `git diff lib/B/C.pm t/test.pl t/*.t`;
  116. chomp $gitdiff;
  117. $svnrev .= " M" if $gitdiff;
  118. }
  119. log_diag("B::C::VERSION = $B::C::VERSION $svnrev");
  120. log_diag("perlversion = $perlversion");
  121. log_diag("path = $^X");
  122. my $bits = 8 * $Config{ptrsize};
  123. log_diag("platform = $^O $bits"."bit ".(
  124. $Config{'useithreads'} ? "threaded"
  125. : $Config{'usemultiplicity'} ? "multi"
  126. : "non-threaded").
  127. ($Config{ccflags} =~ m/-DDEBUGGING/ ? " debug" : ""));
  128. }
  129. my $module_count = 0;
  130. my ($skip, $pass, $fail, $todo) = (0,0,0,0);
  131. my $Mblib = $^O eq 'MSWin32' ? '-Iblib\arch -Iblib\lib' : "-Iblib/arch -Iblib/lib";
  132. MODULE:
  133. for my $module (@modules) {
  134. $module_count++;
  135. local($\, $,); # guard against -l and other things that screw with
  136. # print
  137. # Possible binary files.
  138. my $name = $module;
  139. $name =~ s/::/_/g;
  140. $name =~ s{(install|setup|update)}{substr($1,0,4)}ie;
  141. my $out = 'pcc'.$name;
  142. my $out_c = "$out.c";
  143. my $out_pl = "$out.pl";
  144. $out = "$out.exe" if $^O eq 'MSWin32';
  145. SKIP: {
  146. # if is a special module that can't be required like others
  147. unless ($modules{$module}) {
  148. $skip++;
  149. log_pass("skip", "$module", 0);
  150. skip("$module not installed", 4 * scalar @opts);
  151. next MODULE;
  152. }
  153. if (is_skip($module)) { # !$have_IPC_Run is not really helpful here
  154. my $why = is_skip($module);
  155. $skip++;
  156. log_pass("skip", "$module #$why", 0);
  157. skip("$module $why", 4 * scalar @opts);
  158. next MODULE;
  159. }
  160. $module = 'if(1) => "Sys::Hostname"' if $module eq 'if';
  161. TODO: {
  162. my $s = is_todo($module);
  163. local $TODO = $s if $s;
  164. $todo++ if $TODO;
  165. open F, ">", $out_pl or die;
  166. print F "use $module;\nprint 'ok';\n" or die;
  167. close F or die;
  168. my ($result, $stdout, $err);
  169. my $module_passed = 1;
  170. my $runperl = $^X =~ m/\s/ ? qq{"$^X"} : $^X;
  171. foreach (0..$#opts) {
  172. my $opt = $opts[$_];
  173. $opt .= " --testsuite --no-spawn" if $module =~ /^Test::/ and $opt !~ / --testsuite/;
  174. $opt .= " -S" if $keep and $opt !~ / -S\b/;
  175. # TODO ./a often hangs but perlcc not
  176. my @cmd = grep {!/^$/}
  177. $runperl,split(/ /,$Mblib),"blib/script/perlcc",split(/ /,$opt),$staticxs,"-o$out","-r",$out_pl;
  178. my $cmd = join(" ", @cmd);
  179. #warn $cmd."\n" if $ENV{TEST_VERBOSE};
  180. # Esp. darwin-2level has insane link times
  181. ($result, $stdout, $err) = run_cmd(\@cmd, 720); # in secs.
  182. ok(-s $out,
  183. "$module_count: use $module generates non-zero binary")
  184. or $module_passed = 0;
  185. is($result, 0, "$module_count: use $module $opt exits with 0")
  186. or $module_passed = 0;
  187. $err =~ s/^Using .+blib\n//m if $] < 5.007;
  188. like($stdout, qr/ok$/ms, "$module_count: use $module $opt gives expected 'ok' output");
  189. #warn $stdout."\n" if $ENV{TEST_VERBOSE};
  190. #warn $err."\n" if $ENV{TEST_VERBOSE};
  191. unless ($stdout =~ /ok$/ms) { # crosscheck for a perlcc problem (XXX not needed anymore)
  192. warn "crosscheck without perlcc\n" if $ENV{TEST_VERBOSE};
  193. my ($r, $err1);
  194. $module_passed = 0;
  195. my $c_opt = $opts[$_];
  196. @cmd = ($runperl,split(/ /,$Mblib),"-MO=C,$c_opt,-o$out_c",$out_pl);
  197. #warn join(" ",@cmd."\n") if $ENV{TEST_VERBOSE};
  198. ($r, $stdout, $err1) = run_cmd(\@cmd, 60); # in secs
  199. @cmd = ($runperl,split(/ /,$Mblib),"script/cc_harness","-o$out",$out_c);
  200. #warn join(" ",@cmd."\n") if $ENV{TEST_VERBOSE};
  201. ($r, $stdout, $err1) = run_cmd(\@cmd, 360); # in secs
  202. @cmd = ($^O eq 'MSWin32' ? "$out" : "./$out");
  203. #warn join(" ",@cmd."\n") if $ENV{TEST_VERBOSE};
  204. ($r, $stdout, $err1) = run_cmd(\@cmd, 20); # in secs
  205. if ($stdout =~ /ok$/ms) {
  206. $module_passed = 1;
  207. diag "crosscheck that only perlcc $staticxs failed. With -MO=C + cc_harness => ok";
  208. }
  209. }
  210. log_pass($module_passed ? "pass" : "fail", $module, $TODO);
  211. if ($module_passed) {
  212. $pass++;
  213. } else {
  214. diag "Failed: $cmd -e 'use $module; print \"ok\"'";
  215. $fail++;
  216. }
  217. TODO: {
  218. local $TODO = 'STDERR from compiler warnings in work' if $err;
  219. is($err, '', "$module_count: use $module no error output compiling")
  220. && ($module_passed)
  221. or log_err($module, $stdout, $err)
  222. }
  223. }
  224. if ($do_test) {
  225. TODO: {
  226. local $TODO = 'all module tests';
  227. `$runperl $Mblib -It -MCPAN -Mmodules -e "CPAN::Shell->testcc("$module")"`;
  228. }
  229. }
  230. for ($out_pl, $out, $out_c, $out_c.".lst") {
  231. unlink $_ if -f $_ ;
  232. }
  233. }}
  234. }
  235. my $count = scalar @modules - $skip;
  236. log_diag("$count / $module_count modules tested with B-C-${B::C::VERSION} - perl-$perlversion");
  237. log_diag(sprintf("pass %3d / %3d (%s)", $pass, $count, percent($pass,$count)));
  238. log_diag(sprintf("fail %3d / %3d (%s)", $fail, $count, percent($fail,$count)));
  239. log_diag(sprintf("todo %3d / %3d (%s)", $todo, $fail, percent($todo,$fail)));
  240. log_diag(sprintf("skip %3d / %3d (%s not installed)\n",
  241. $skip, $module_count, percent($skip,$module_count)));
  242. exit;
  243. # t/todomod.pl
  244. # for t in $(cat t/top100); do perl -ne"\$ARGV=~s/log.modules-//;print \$ARGV,': ',\$_ if / $t\s/" t/modules.t `ls log.modules-5.0*|grep -v .err`; read; done
  245. sub is_todo {
  246. my $module = shift or die;
  247. my $DEBUGGING = ($Config{ccflags} =~ m/-DDEBUGGING/);
  248. # ---------------------------------------
  249. #foreach(qw(
  250. # ExtUtils::CBuilder
  251. #)) { return 'overlong linking time' if $_ eq $module; }
  252. if ($] < 5.007) { foreach(qw(
  253. Sub::Name
  254. Test::Simple
  255. Test::Exception
  256. Storable
  257. Test::Tester
  258. Test::NoWarnings
  259. Moose
  260. Test::Warn
  261. Test::Pod
  262. Test::Deep
  263. FCGI
  264. MooseX::Types
  265. DateTime::TimeZone
  266. DateTime
  267. )) { return '5.6' if $_ eq $module; }}
  268. if ($] >= 5.008004 and $] < 5.0080006) { foreach(qw(
  269. Module::Pluggable
  270. )) { return '5.8.5 CopFILE_set' if $_ eq $module; }}
  271. # PMOP quoting fixed with 1.45_14
  272. #if ($] < 5.010) { foreach(qw(
  273. # DateTime
  274. #)) { return '<5.10' if $_ eq $module; }}
  275. # restricted v_string hash?
  276. if ($] eq '5.010000') { foreach(qw(
  277. IO
  278. Path::Class
  279. DateTime::TimeZone
  280. )) { return '5.10.0 restricted hash/...' if $_ eq $module; }}
  281. # fixed between v5.15.6-210-g5343a61 and v5.15.6-233-gfb7aafe
  282. #if ($] > 5.015 and $] < 5.015006) { foreach(qw(
  283. # B::Hooks::EndOfScope
  284. #)) { return '> 5.15' if $_ eq $module; }}
  285. if ($] >= 5.018) { foreach(qw(
  286. ExtUtils::ParseXS
  287. )) { return '>= 5.18 #135 Eval-group not allowed at runtime' if $_ eq $module; }}
  288. # DateTime fixed with 1.52_13
  289. if ($] >= 5.018) { foreach(qw(
  290. Path::Class
  291. )) { return '>= 5.18 #219 overload stringify regression' if $_ eq $module; }}
  292. if ($] >= 5.023005) { foreach(qw(
  293. Attribute::Handlers
  294. MooseX::Types
  295. )) { return '>= 5.23.5' if $_ eq $module; }}
  296. # ---------------------------------------
  297. if ($Config{useithreads}) {
  298. if ($] >= 5.008008 and $] < 5.008009) { foreach(qw(
  299. Test::Tester
  300. )) { return '5.8.8 with threads' if $_ eq $module; }}
  301. if ($] >= 5.010 and $] < 5.011 and $DEBUGGING) { foreach(qw(
  302. Attribute::Handlers
  303. )) { return '5.10.1d with threads' if $_ eq $module; }}
  304. #if ($] >= 5.012 and $] < 5.014) { foreach(qw(
  305. # ExtUtils::CBuilder
  306. #)) { return '5.12 with threads' if $_ eq $module; }}
  307. if ($] >= 5.016 and $] < 5.020) { foreach(qw(
  308. Module::Build
  309. )) { return '5.16-5.20 (out of memory)' if $_ eq $module; }}
  310. if ($] >= 5.022) { foreach(qw(
  311. Pod::Parser
  312. Digest
  313. LWP
  314. Test::NoWarnings
  315. DBI
  316. CGI
  317. AppConfig
  318. Template::Stash
  319. )) { return '>= 5.22 with threads SEGV' if $_ eq $module; }}
  320. if ($] >= 5.022) { foreach(qw(
  321. Test::Harness
  322. ExtUtils::MakeMaker
  323. Pod::Text
  324. File::Temp
  325. ExtUtils::CBuilder
  326. Module::Build
  327. Encode
  328. )) { return '>= 5.22 with threads, no ok' if $_ eq $module; }}
  329. } else { #no threads --------------------------------
  330. #if ($] > 5.008008 and $] <= 5.009) { foreach(qw(
  331. # ExtUtils::CBuilder
  332. #)) { return '5.8.9 without threads' if $_ eq $module; }}
  333. # invalid free
  334. if ($] >= 5.016 and $] < 5.020) { foreach(qw(
  335. Module::Build
  336. )) { return '>= 5.16 without threads (invalid free)' if $_ eq $module; }}
  337. #if ($] > 5.019) { foreach(qw(
  338. # MooseX::Types
  339. #)) { return '5.19 without threads' if $_ eq $module; }}
  340. }
  341. # ---------------------------------------
  342. }
  343. sub is_skip {
  344. my $module = shift or die;
  345. if ($] >= 5.011004) {
  346. #foreach (qw(Attribute::Handlers)) {
  347. # return 'fails $] >= 5.011004' if $_ eq $module;
  348. #}
  349. if ($Config{useithreads}) { # hangs and crashes threaded since 5.12
  350. foreach (qw( )) {
  351. # Old: Recursive inheritance detected in package 'Moose::Object' at /usr/lib/perl5/5.13.10/i686-debug-cygwin/DynaLoader.pm line 103
  352. # Update: Moose works ok with r1013
  353. return 'hangs threaded, $] >= 5.011004' if $_ eq $module;
  354. }
  355. }
  356. }
  357. }