File Coverage

blib/lib/Test/CPANpm/Fake.pm
Criterion Covered Total %
statement 91 180 50.5
branch 10 46 21.7
condition 0 3 0.0
subroutine 21 32 65.6
pod 0 13 0.0
total 122 274 44.5


line stmt bran cond sub pod time code
1             #!perl
2              
3             package Test::CPANpm::Fake;
4              
5 1     1   3 use strict;
  1         2  
  1         23  
6 1     1   4 use warnings;
  1         1  
  1         18  
7 1     1   74325 use CPAN;
  1         506420  
  1         591  
8 1     1   28 use Cwd qw(abs_path getcwd);
  1         9  
  1         210  
9 1     1   14 use File::Path qw(rmtree mkpath);
  1         7  
  1         236  
10 1     1   15033 use File::Temp qw(mktemp tempdir tempfile);
  1         24385  
  1         128  
11 1     1   13 use File::Basename;
  1         3  
  1         120  
12 1     1   7 use Exporter;
  1         2  
  1         45  
13 1     1   14 use base q(Exporter);
  1         2  
  1         142  
14 1     1   1405 use CPAN::FirstTime;
  1         73801  
  1         42  
15 1     1   14 use ExtUtils::MakeMaker ();
  1         2  
  1         184  
16              
17             our @EXPORT = qw(
18             cpan_config get_prereqs run_with_fake_modules dist_dir change_std
19             restore_std run_with_cpan_config
20             );
21              
22             sub run_with_cpan_config (&);
23             sub run_with_fake_modules (&@);
24             sub change_std;
25             sub restore_std;
26              
27             return 1;
28              
29             sub _wrap {
30 2     2   20 my($sub, $wrapper) = @_;
31 2         15 my $wrap_call;
32              
33             {
34 1     1   4 no strict 'refs';
  1         3  
  1         47  
  2         11  
35 1     1   6 no warnings 'redefine';
  1         1  
  1         2412  
36 2         4 my $sub_ref = \&{$sub};
  2         40  
37 2     0   19 $wrap_call = sub { $wrapper->($sub_ref, @_); };
  0         0  
38 2         10 *{$sub} = $wrap_call;
  2         14  
39             }
40              
41 2         5 return $wrap_call;
42             }
43              
44              
45             sub _unsat_prereq {
46 0     0   0 my($orig, $self) = @_;
47 0 0       0 if(my $prereq_pm = $self->prereq_pm) {
48             # The empty string prevents "make" from actually running
49 0         0 return('', keys(%$prereq_pm));
50             } else {
51 0         0 return;
52             }
53             }
54              
55             sub create_cpan_config {
56 0     0 0 0 local $ENV{PERL_MM_USE_DEFAULT} = 1;
57 0         0 $CPAN::Config = {
58             urllist => [ 'ftp://ftp.cpan.org/pub/CPAN' ],
59             cpan_home => tempdir(CLEANUP => 1)
60             };
61             my $wrapper = sub {
62 0     0   0 my($real, @args) = @_;
63 0 0       0 if($args[0] =~ m{manual config}) {
64 0         0 $args[1] = 'no';
65             }
66 0         0 $real->(@args);
67 0         0 };
68            
69 0         0 _wrap('ExtUtils::MakeMaker::prompt', $wrapper);
70 0         0 _wrap('CPAN::FirstTime::prompt', $wrapper);
71            
72 0         0 mkdir("$CPAN::Config->{cpan_home}/CPAN");
73            
74 0         0 CPAN::FirstTime::init(
75             "$CPAN::Config->{cpan_home}/CPAN/Config.pm",
76             autoconfig => 'yes'
77             );
78            
79 0 0       0 warn "Created config in ", $CPAN::Config->{cpan_home}
80             if $ENV{DEBUG_TEST_CPAN};
81 0         0 return $CPAN::Config;
82             }
83              
84             sub cpan_config {
85 1     1 0 498 eval "use CPAN::Config;";
  0     1   0  
  0         0  
  1         81  
86 1 50       5 if($CPAN::Config) {
87 1         5 return;
88             } else {
89 0         0 return create_cpan_config();
90             }
91             }
92              
93             sub run_with_cpan_config (&) {
94 1     1 0 3 my $cmd = shift;
95 1 50       3 if(my $config = cpan_config) {
96 0         0 my $perl5opt = $ENV{PERL5OPT};
97 0         0 local $ENV{PERL5OPT};
98 0 0       0 $ENV{PERL5OPT} = $perl5opt if($perl5opt);
99 0         0 unshift_inc($config->{cpan_home});
100 0         0 $cmd->();
101             } else {
102 1         4 $cmd->();
103             }
104             }
105            
106              
107             sub dist_dir_mb {
108 0     0 0 0 my $root = shift;
109 0         0 my $here = getcwd();
110 0         0 my $pre = mktemp("XXXXXX");
111 0         0 my $name = "$pre-0";
112 0         0 chdir($root);
113 0         0 system("./Build", "dist_name=$pre", "dist_version=0", "distdir");
114 0         0 chdir($here);
115 0         0 return "$root/$name";
116             }
117              
118             sub dist_dir_mm {
119 1     1 0 2 my $root = shift;
120 1         7 my $here = getcwd();
121 1         21 chdir($root);
122 1         6 my $name = mktemp("XXXXXXX") . "-0";
123 1         260 my $make = $CPAN::Config->{'make'};
124 1         4492 system($make, "DISTVNAME=$name", "distdir");
125 1         37 chdir($here);
126 1         209 return "$root/$name";
127             }
128              
129             sub dist_dir {
130 1     1 0 2 my $dir = shift;
131 1         9 $dir = abs_path($dir);
132 1 50       41 if(-e "$dir/Build") {
    50          
133 0         0 return dist_dir_mb($dir);
134             } elsif(-e "$dir/Makefile") {
135 1         3 return dist_dir_mm($dir);
136             } else {
137 0         0 die "There is no 'Build' or 'Makefile' script in $dir!";
138             }
139             }
140              
141             sub make_fake_module {
142 0     0 0 0 my($lib, $package, $good) = @_;
143            
144 0 0       0 $good = $good ? 1 : 0;
145 0         0 my $pathname = "$lib/$package.pm";
146 0         0 $pathname =~ s{::}{/}g;
147 0         0 my $dir = dirname($pathname);
148 0         0 mkpath($dir);
149 0 0       0 open(my $fh, ">$pathname") or die "write $pathname: $!";
150 0         0 print $fh "$good;\n";
151 0         0 close $fh;
152            
153 0 0       0 if($ENV{DEBUG_TEST_CPAN}) {
154 0         0 print "$package => $pathname\n";
155             }
156            
157 0         0 return $pathname;
158             }
159              
160             sub setup_fake_modules {
161 0     0 0 0 my %modules = @_;
162            
163 0         0 my $fake_dir = tempdir(CLEANUP => 1);
164            
165 0         0 while(my($k, $v) = each(%modules)) {
166 0         0 make_fake_module($fake_dir, $k, $v);
167             }
168              
169 0         0 return $fake_dir;
170             }
171              
172             sub unshift_inc {
173 0     0 0 0 my $fake_dir = shift;
174 0         0 @INC = ($fake_dir, @INC);
175            
176             # if we use PERL5LIB here, Module::Build usurps our changes...
177 0 0       0 if($ENV{PERL5OPT}) {
178 0         0 $ENV{PERL5OPT} .= " -I$fake_dir"
179             } else {
180 0         0 $ENV{PERL5OPT} = "-I$fake_dir";
181             }
182              
183 0 0       0 if($ENV{DEBUG_TEST_CPAN}) {
184 0         0 print "PERL5OPT = $ENV{PERL5OPT}";
185             }
186             }
187              
188             sub run_with_fake_modules (&@) {
189 0     0 0 0 my($run, %modules) = @_;
190              
191 0         0 my($out, $in) = change_std;
192            
193 0         0 my $fake_dir = setup_fake_modules(%modules);
194            
195 0         0 local @INC = @INC;
196 0         0 my $perl5opt = $ENV{PERL5OPT};
197 0         0 local $ENV{PERL5OPT};
198 0 0       0 $ENV{PERL5OPT} = $perl5opt if($perl5opt);
199 0         0 unshift_inc($fake_dir);
200            
201 0         0 my $rv = $run->();
202 0         0 restore_std($out, $in);
203 0         0 return $rv;
204             }
205              
206             sub change_std {
207 2     2 0 6 my($out, $in);
208            
209 2 50       11 open($in, "<&STDIN") if fileno(STDIN);
210 2 50       234 open($out, ">&STDOUT") if fileno(STDOUT);
211              
212 2 50       20 if($ENV{DEBUG_TEST_CPAN}) {
213 2         58 open(STDOUT, ">&STDERR");
214             } else {
215 0         0 my $o = scalar tempfile;
216 0         0 my $i = scalar tempfile;
217 0         0 my $on = fileno $o;
218 0         0 my $oi = fileno $i;
219 0         0 open(STDOUT, ">&=$on");
220 0         0 open(STDIN, "<&=$oi");
221             }
222            
223 2         7 return($out, $in);
224             }
225              
226             sub restore_std {
227 0     0 0 0 my($out, $in) = @_;
228 0 0       0 if(defined $in) {
229 0         0 my $inn = fileno $in;
230 0         0 open(STDIN, "<&=$inn");
231             }
232 0 0       0 if(defined $out) {
233 0         0 my $outn = fileno $out;
234 0         0 open(STDOUT, ">&=$outn");
235             }
236             }
237              
238             sub get_prereqs {
239 1 50   1 0 125 my $dist_dir = shift or die 'dist_dir is required!';
240 1         2 my @followed;
241              
242 1         10 my($out, $in) = change_std();
243              
244             {
245 1         6 local *CPAN::Distribution::follow_prereqs;
  1         17  
246 1         9 local *CPAN::Distribution::unsat_prereq;
247              
248             # this is paranoid... in case DEBUG_TEST_CPAN gets changed in here,
249             # we want our old one back when it's done.
250              
251 1         8 my $test_cpan = $ENV{DEBUG_TEST_CPAN};
252              
253 1         22 local $ENV{DEBUG_TEST_CPAN};
254              
255 1 50       12 if($test_cpan) {
256 1         7 $ENV{DEBUG_TEST_CPAN} = $test_cpan;
257             }
258              
259 1 50       10 if($ENV{DEBUG_TEST_CPAN}) {
260 1         69 warn "CPAN.pm version: $CPAN::VERSION\n";
261             }
262              
263 1     0   30 _wrap('CPAN::Distribution::follow_prereqs', sub { @followed = splice(@_, 3); });
  0         0  
264 1         5 _wrap('CPAN::Distribution::unsat_prereq', \&_unsat_prereq);
265            
266 1         15 my $here = getcwd();
267 1         36 chdir($dist_dir);
268            
269 1         28 my $d = CPAN::Distribution->new(
270             build_dir => $dist_dir,
271             ID => $dist_dir,
272             archived => 'Fake',
273             unwrapped => 'Yes'
274             );
275            
276 1         59 $d->make;
277 0           chdir($here);
278 0 0 0       rmtree($dist_dir) unless $ENV{DEBUG_TEST_CPAN} && $ENV{DEBUG_TEST_CPAN} != 2;
279             }
280              
281 0           restore_std($out, $in);
282 0           return @followed;
283             }
284              
285             # perl -MCPAN -e 'chdir("dev/DBIx-Transaction"); my $d = CPAN::Distribution->new(build_dir => "/home/faraway/dev/DBIx-Transaction", ID => "dev/DBIx-Transaction"); print $d->test'