File Coverage

blib/lib/Test/Alien/Build.pm
Criterion Covered Total %
statement 305 333 91.5
branch 71 100 71.0
condition 38 67 56.7
subroutine 35 37 94.5
pod 13 14 92.8
total 462 551 83.8


line stmt bran cond sub pod time code
1             package Test::Alien::Build;
2              
3 55     55   10553422 use strict;
  55         398  
  55         1581  
4 55     55   262 use warnings;
  55         100  
  55         1235  
5 55     55   1499 use 5.008004;
  55         192  
6 55     55   278 use Exporter qw( import );
  55         113  
  55         1954  
7 55     55   37481 use Path::Tiny qw( path );
  55         521357  
  55         3555  
8 55     55   457 use Carp qw( croak );
  55         109  
  55         2415  
9 55     55   300 use Test2::API qw( context run_subtest );
  55         105  
  55         2513  
10 55     55   27482 use Capture::Tiny qw( capture_merged );
  55         1219870  
  55         3794  
11 55     55   22701 use Alien::Build::Util qw( _mirror );
  55         133  
  55         3422  
12 55     55   376 use List::Util 1.33 qw( any );
  55         1052  
  55         3090  
13 55     55   20983 use Alien::Build::Temp;
  55         128  
  55         107505  
14              
15             our @EXPORT = qw(
16             alienfile
17             alienfile_ok
18             alienfile_skip_if_missing_prereqs
19             alien_download_ok
20             alien_extract_ok
21             alien_build_ok
22             alien_build_clean
23             alien_clean_install
24             alien_install_type_is
25             alien_checkpoint_ok
26             alien_resume_ok
27             alien_subtest
28             alien_rc
29             );
30              
31             # ABSTRACT: Tools for testing Alien::Build + alienfile
32             our $VERSION = '2.45'; # VERSION
33              
34              
35             my $build;
36             my $build_alienfile;
37             my $build_root;
38             my $build_targ;
39              
40             sub alienfile::targ
41             {
42 1     1 0 13 $build_targ;
43             }
44              
45             sub alienfile
46             {
47 295     295 1 666684 my($package, $filename, $line) = caller;
48 295 100       2133 ($package, $filename, $line) = caller(2) if $package eq __PACKAGE__;
49 295         1635 $filename = path($filename)->absolute;
50 295 100       41372 my %args = @_ == 0 ? (filename => 'alienfile') : @_ % 2 ? ( source => do { '# line '. $line . ' "' . path($filename)->absolute . qq("\n) . $_[0] }) : @_;
  236 50       1099  
51              
52 295         35648 require alienfile;
53 295 100   7625   2979 push @alienfile::EXPORT, 'targ' unless any { /^targ$/ } @alienfile::EXPORT;
  7625         10869  
54              
55 295         3141 my $temp = Alien::Build::Temp->newdir;
56 295         143654 my $get_temp_root = do{
57 295         652 my $root; # may be undef;
58             sub {
59 1122   66 1122   5122 $root ||= Path::Tiny->new($temp);
60              
61 1122 100       17884 if(@_)
62             {
63 885         2585 my $path = $root->child(@_);
64 885         35666 $path->mkpath;
65 885         151224 $path;
66             }
67             else
68             {
69 237         866 return $root;
70             }
71 295         2049 };
72             };
73              
74 295 100       1248 if($args{source})
75             {
76 237         681 my $file = $get_temp_root->()->child('alienfile');
77 237         8578 $file->spew_utf8($args{source});
78 237         164205 $args{filename} = $file->stringify;
79             }
80             else
81             {
82 58 50       222 unless(defined $args{filename})
83             {
84 0         0 croak "You must specify at least one of filename or source";
85             }
86 58         279 $args{filename} = path($args{filename})->absolute->stringify;
87             }
88              
89 295   33     8871 $args{stage} ||= $get_temp_root->('stage')->stringify;
90 295   33     3309 $args{prefix} ||= $get_temp_root->('prefix')->stringify;
91 295   33     3130 $args{root} ||= $get_temp_root->('root')->stringify;
92              
93 295         4340 require Alien::Build;
94              
95 295         1359 _alienfile_clear();
96             my $out = capture_merged {
97 295     295   341382 $build_targ = $args{targ};
98 295         2585 $build = Alien::Build->load($args{filename}, root => $args{root});
99 280         2239 $build->set_stage($args{stage});
100 280         1653 $build->set_prefix($args{prefix});
101 295         12070 };
102              
103 280         247243 my $ctx = context();
104 280 100       57721 $ctx->note($out) if $out;
105 280         4091 $ctx->release;
106              
107 280         8142 $build_alienfile = $args{filename};
108 280         549 $build_root = $temp;
109 280         1198 $build
110             }
111              
112             sub _alienfile_clear
113             {
114 401 100 66 401   822 eval { defined $build_root && -d $build_root && path($build_root)->remove_tree };
  401         2425  
115 401         293707 undef $build;
116 401         960 undef $build_alienfile;
117 401         1624 undef $build_root;
118 401         13554 undef $build_targ;
119             }
120              
121              
122             sub alienfile_ok
123             {
124 162     162 1 799876 my $build;
125             my $name;
126 162         0 my $error;
127              
128 162 100 100     1645 if(@_ == 1 && ! defined $_[0])
    100 100        
129             {
130 1         4 $build = $_[0];
131 1         2 $error = 'no alienfile given';
132 1         2 $name = 'alienfile compiled';
133             }
134 159         2146 elsif(@_ == 1 && eval { $_[0]->isa('Alien::Build') })
135             {
136 1         3 $build = $_[0];
137 1         2 $name = 'alienfile compiled';
138             }
139             else
140             {
141 160         375 $build = eval { alienfile(@_) };
  160         707  
142 160         4672 $error = $@;
143 160         388 $name = 'alienfile compiles';
144             }
145              
146 162         463 my $ok = !! $build;
147              
148 162         535 my $ctx = context();
149 162         13960 $ctx->ok($ok, $name);
150 162 100       31047 $ctx->diag("error: $error") if $error;
151 162         1000 $ctx->release;
152              
153 162         4113 $build;
154             }
155              
156              
157             sub alienfile_skip_if_missing_prereqs
158             {
159 12     12 1 5746 my($phase) = @_;
160              
161 12 50       48 if($build)
162             {
163 12         22 eval { $build->load_requires('configure', 1) };
  12         77  
164 12 100       44 if(my $error = $@)
165             {
166 2         8 my $reason = "Missing configure prereq";
167 2 50       23 if($error =~ /Required (.*) (.*),/)
168             {
169 2         11 $reason .= ": $1 $2";
170             }
171 2         7 my $ctx = context();
172 2         227 $ctx->plan(0, SKIP => $reason);
173 0         0 $ctx->release;
174 0         0 return;
175             }
176 10   66     72 $phase ||= $build->install_type;
177 10         777 eval { $build->load_requires($phase, 1) };
  10         39  
178 10 100       55 if(my $error = $@)
179             {
180 7         23 my $reason = "Missing $phase prereq";
181 7 50       72 if($error =~ /Required (.*) (.*),/)
182             {
183 7         34 $reason .= ": $1 $2";
184             }
185 7         26 my $ctx = context();
186 7         757 $ctx->plan(0, SKIP => $reason);
187 0         0 $ctx->release;
188 0         0 return;
189             }
190             }
191             }
192              
193              
194             sub alien_install_type_is
195             {
196 38     38 1 8221 my($type, $name) = @_;
197              
198 38 50 33     584 croak "invalid install type" unless defined $type && $type =~ /^(system|share)$/;
199 38   66     265 $name ||= "alien install type is $type";
200              
201 38         75 my $ok = 0;
202 38         70 my @diag;
203              
204 38 100       117 if($build)
205             {
206             my($out, $actual) = capture_merged {
207 37     37   40542 $build->load_requires('configure');
208 37         228 $build->install_type;
209 37         1256 };
210 37 100       32697 if($type eq $actual)
211             {
212 35         102 $ok = 1;
213             }
214             else
215             {
216 2         12 push @diag, "expected install type of $type, but got $actual";
217             }
218             }
219             else
220             {
221 1         4 push @diag, 'no alienfile'
222             }
223              
224 38         188 my $ctx = context();
225 38         4614 $ctx->ok($ok, $name);
226 38         6751 $ctx->diag($_) for @diag;
227 38         732 $ctx->release;
228              
229 38         1143 $ok;
230             }
231              
232              
233             sub alien_download_ok
234             {
235 4     4 1 403 my($name) = @_;
236              
237 4   50     29 $name ||= 'alien download';
238              
239 4         17 my $ok;
240             my $file;
241 4         0 my @diag;
242 4         0 my @note;
243              
244 4 50       13 if($build)
245             {
246             my($out, $error) = capture_merged {
247 4     4   4407 eval {
248 4         54 $build->load_requires('configure');
249 4         26 $build->load_requires($build->install_type);
250 4         39 $build->download;
251             };
252 4         476 $@;
253 4         172 };
254 4 100       3534 if($error)
255             {
256 1         4 $ok = 0;
257 1 50       8 push @diag, $out if defined $out;
258 1         5 push @diag, "extract threw exception: $error";
259             }
260             else
261             {
262 3         17 $file = $build->install_prop->{download};
263 3 50 33     94 if(-d $file || -f $file)
264             {
265 3         12 $ok = 1;
266 3 50       17 push @note, $out if defined $out;
267             }
268             else
269             {
270 0         0 $ok = 0;
271 0 0       0 push @diag, $out if defined $out;
272 0         0 push @diag, 'no file or directory';
273             }
274             }
275             }
276             else
277             {
278 0         0 $ok = 0;
279 0         0 push @diag, 'no alienfile';
280             }
281              
282 4         23 my $ctx = context();
283 4         528 $ctx->ok($ok, $name);
284 4         993 $ctx->note($_) for @note;
285 4         794 $ctx->diag($_) for @diag;
286 4         376 $ctx->release;
287              
288 4         122 $file;
289             }
290              
291              
292             sub alien_extract_ok
293             {
294 6     6 1 459 my($archive, $name) = @_;
295              
296 6 50 33     61 $name ||= $archive ? "alien extraction of $archive" : 'alien extraction';
297 6         21 my $ok;
298             my $dir;
299 6         0 my @diag;
300              
301 6 50       25 if($build)
302             {
303 6         13 my($out, $error);
304             ($out, $dir, $error) = capture_merged {
305 6     6   6391 my $dir = eval {
306 6         86 $build->load_requires('configure');
307 6         53 $build->load_requires($build->install_type);
308 6         60 $build->download;
309 6         932 $build->extract($archive);
310             };
311 6         804 ($dir, $@);
312 6         255 };
313 6 100       5675 if($error)
314             {
315 1         4 $ok = 0;
316 1 50       8 push @diag, $out if defined $out;
317 1         6 push @diag, "extract threw exception: $error";
318             }
319             else
320             {
321 5 50       143 if(-d $dir)
322             {
323 5         208 $ok = 1;
324             }
325             else
326             {
327 0         0 $ok = 0;
328 0         0 push @diag, 'no directory';
329             }
330             }
331             }
332             else
333             {
334 0         0 $ok = 0;
335 0         0 push @diag, 'no alienfile';
336             }
337              
338 6         74 my $ctx = context();
339 6         1129 $ctx->ok($ok, $name);
340 6         1577 $ctx->diag($_) for @diag;
341 6         422 $ctx->release;
342              
343 6         205 $dir;
344             }
345              
346              
347             my $count = 1;
348              
349             sub alien_build_ok
350             {
351 29 50 66 29 1 4762 my $opt = defined $_[0] && ref($_[0]) eq 'HASH'
352             ? shift : { class => 'Alien::Base' };
353              
354 29         85 my($name) = @_;
355              
356 29   100     217 $name ||= 'alien builds okay';
357 29         130 my $ok;
358             my @diag;
359 29         0 my @note;
360 29         0 my $alien;
361              
362 29 100       105 if($build)
363             {
364             my($out,$error) = capture_merged {
365 28     28   28487 eval {
366 28         300 $build->load_requires('configure');
367 28         219 $build->load_requires($build->install_type);
368 28         267 $build->download;
369 27         1980 $build->build;
370             };
371 28         518 $@;
372 28         882 };
373 28 100       25506 if($error)
374             {
375 1         3 $ok = 0;
376 1 50       6 push @diag, $out if defined $out;
377 1         5 push @diag, "build threw exception: $error";
378             }
379             else
380             {
381 27         86 $ok = 1;
382              
383 27 50       238 push @note, $out if defined $out;
384              
385 27         4288 require Alien::Base;
386              
387 27         172 my $prefix = $build->runtime_prop->{prefix};
388 27         108 my $stage = $build->install_prop->{stage};
389 27         76 my %prop = %{ $build->runtime_prop };
  27         113  
390              
391 27         133 $prop{distdir} = $prefix;
392              
393 27         209 _mirror $stage, $prefix;
394              
395             my $dist_dir = sub {
396 0     0   0 $prefix;
397 27         280 };
398              
399             my $runtime_prop = sub {
400 11     11   1024 \%prop;
401 27         124 };
402              
403 27         226 $alien = sprintf 'Test::Alien::Build::Faux%04d', $count++;
404             {
405 55     55   568 no strict 'refs';
  55         145  
  55         59059  
  27         55  
406 27         82 @{ "${alien}::ISA" } = $opt->{class};
  27         942  
407 27         97 *{ "${alien}::dist_dir" } = $dist_dir;
  27         216  
408 27         92 *{ "${alien}::runtime_prop" } = $runtime_prop;
  27         192  
409             }
410             }
411             }
412             else
413             {
414 1         3 $ok = 0;
415 1         3 push @diag, 'no alienfile';
416             }
417              
418 29         229 my $ctx = context();
419 29         4441 $ctx->ok($ok, $name);
420 29         6231 $ctx->diag($_) for @diag;
421 29         789 $ctx->note($_) for @note;
422 29         8153 $ctx->release;
423              
424 29         926 $alien;
425             }
426              
427              
428             sub alien_build_clean
429             {
430 0     0 1 0 my $ctx = context();
431 0 0       0 if($build_root)
432             {
433 0         0 foreach my $child (path($build_root)->children)
434             {
435 0 0       0 next if $child->basename eq 'prefix';
436 0         0 $ctx->note("clean: rm: $child");
437 0         0 $child->remove_tree;
438             }
439             }
440             else
441             {
442 0         0 $ctx->note("no build to clean");
443             }
444 0         0 $ctx->release;
445             }
446              
447              
448             sub alien_clean_install
449             {
450 3     3 1 3829 my($name) = @_;
451              
452 3   50     18 $name ||= "run clean_install";
453              
454 3         9 my $ok;
455             my @diag;
456 3         0 my @note;
457              
458 3 50       10 if($build)
459             {
460             my($out,$error) = capture_merged {
461 3     3   2839 eval {
462 3         27 $build->clean_install;
463             };
464 3         89 $@;
465 3         83 };
466 3 50       2142 if($error)
467             {
468 0         0 $ok = 0;
469 0 0 0     0 push @diag, $out if defined $out && $out ne '';
470 0         0 push @diag, "build threw exception: $error";
471             }
472             else
473             {
474 3         8 $ok = 1;
475 3 100 66     20 push @note, $out if defined $out && $out ne '';
476             }
477             }
478             else
479             {
480 0         0 $ok = 0;
481 0         0 push @diag, 'no alienfile';
482             }
483              
484 3         14 my $ctx = context();
485 3         274 $ctx->ok($ok, $name);
486 3         412 $ctx->diag($_) for @diag;
487 3         9 $ctx->note($_) for @note;
488 3         342 $ctx->release;
489             }
490              
491              
492             sub alien_checkpoint_ok
493             {
494 18     18 1 2623 my($name) = @_;
495              
496 18   50     149 $name ||= "alien checkpoint ok";
497 18         42 my $ok;
498             my @diag;
499              
500 18 100       99 if($build)
501             {
502 17         34 eval { $build->checkpoint };
  17         159  
503 17 100       90 if($@)
504             {
505 1         5 push @diag, "error in checkpoint: $@";
506 1         3 $ok = 0;
507             }
508             else
509             {
510 16         45 $ok = 1;
511             }
512 17         238 undef $build;
513             }
514             else
515             {
516 1         3 push @diag, "no build to checkpoint";
517 1         2 $ok = 0;
518             }
519              
520 18         75 my $ctx = context();
521 18         1908 $ctx->ok($ok, $name);
522 18         2883 $ctx->diag($_) for @diag;
523 18         427 $ctx->release;
524              
525 18         497 $ok;
526             }
527              
528              
529             sub alien_resume_ok
530             {
531 17     17 1 1706 my($name) = @_;
532              
533 17   50     137 $name ||= "alien resume ok";
534 17         41 my $ok;
535             my @diag;
536              
537 17 100 66     130 if($build_alienfile && $build_root && !defined $build)
      100        
538             {
539 15         224 $build = eval { Alien::Build->resume($build_alienfile, "$build_root/root") };
  15         55  
540 15 100       72 if($@)
541             {
542 1         4 push @diag, "error in resume: $@";
543 1         3 $ok = 0;
544             }
545             else
546             {
547 14         37 $ok = 1;
548             }
549             }
550             else
551             {
552 2 100       19 if($build)
553             {
554 1         4 push @diag, "build has not been checkpointed";
555             }
556             else
557             {
558 1         3 push @diag, "no build to resume";
559             }
560 2         4 $ok = 0;
561             }
562              
563 17         67 my $ctx = context();
564 17         1808 $ctx->ok($ok, $name);
565 17         3232 $ctx->diag($_) for @diag;
566 17         611 $ctx->release;
567              
568 17 100 66     576 ($ok && $build) || $ok;
569             }
570              
571              
572             my $alien_rc_root;
573              
574             sub alien_rc
575             {
576 1     1 1 8425 my($code) = @_;
577              
578 1 50       5 croak "passed in undef rc" unless defined $code;
579 1 50       5 croak "looks like you have already defined a rc.pl file" if $ENV{ALIEN_BUILD_RC} ne '-';
580              
581 1         4 my(undef, $filename, $line) = caller;
582 1         8 my $code2 = "use strict; use warnings;\n" .
583             '# line ' . $line . ' "' . path($filename)->absolute . "\n$code";
584              
585 1   33     139 $alien_rc_root ||= Alien::Build::Temp->newdir;
586              
587 1         397 my $rc = path($alien_rc_root)->child('rc.pl');
588 1         83 $rc->spew_utf8($code2);
589 1         511 $ENV{ALIEN_BUILD_RC} = "$rc";
590 1         12 return 1;
591             }
592              
593              
594             sub alien_subtest
595             {
596 53     53 1 76395 my($name, $code, @args) = @_;
597              
598 53         210 _alienfile_clear;
599              
600 53         210 my $ctx = context();
601 53         11556 my $pass = run_subtest($name, $code, { buffered => 1 }, @args);
602 53         125843 $ctx->release;
603              
604 53         1577 _alienfile_clear;
605              
606 53         253 $pass;
607             }
608              
609             delete $ENV{$_} for qw( ALIEN_BUILD_LOG ALIEN_BUILD_PRELOAD ALIEN_BUILD_POSTLOAD ALIEN_INSTALL_TYPE PKG_CONFIG_PATH ALIEN_BUILD_PKG_CONFIG );
610             $ENV{ALIEN_BUILD_RC} = '-';
611              
612             1;
613              
614             __END__