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   9681808 use strict;
  55         397  
  55         1479  
4 55     55   253 use warnings;
  55         94  
  55         1151  
5 55     55   1359 use 5.008004;
  55         168  
6 55     55   260 use Exporter qw( import );
  55         93  
  55         1722  
7 55     55   33834 use Path::Tiny qw( path );
  55         497192  
  55         3467  
8 55     55   438 use Carp qw( croak );
  55         112  
  55         2286  
9 55     55   320 use Test2::API qw( context run_subtest );
  55         117  
  55         2458  
10 55     55   25558 use Capture::Tiny qw( capture_merged );
  55         1016282  
  55         3197  
11 55     55   21468 use Alien::Build::Util qw( _mirror );
  55         137  
  55         3175  
12 55     55   351 use List::Util 1.33 qw( any );
  55         958  
  55         2967  
13 55     55   19145 use Alien::Build::Temp;
  55         133  
  55         97566  
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.47'; # 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 10 $build_targ;
43             }
44              
45             sub alienfile
46             {
47 295     295 1 629021 my($package, $filename, $line) = caller;
48 295 100       1891 ($package, $filename, $line) = caller(2) if $package eq __PACKAGE__;
49 295         1322 $filename = path($filename)->absolute;
50 295 100       36474 my %args = @_ == 0 ? (filename => 'alienfile') : @_ % 2 ? ( source => do { '# line '. $line . ' "' . path($filename)->absolute . qq("\n) . $_[0] }) : @_;
  236 50       917  
51              
52 295         31395 require alienfile;
53 295 100   7625   2986 push @alienfile::EXPORT, 'targ' unless any { /^targ$/ } @alienfile::EXPORT;
  7625         9544  
54              
55 295         2736 my $temp = Alien::Build::Temp->newdir;
56 295         118657 my $get_temp_root = do{
57 295         550 my $root; # may be undef;
58             sub {
59 1122   66 1122   4392 $root ||= Path::Tiny->new($temp);
60              
61 1122 100       15592 if(@_)
62             {
63 885         2160 my $path = $root->child(@_);
64 885         30489 $path->mkpath;
65 885         126003 $path;
66             }
67             else
68             {
69 237         730 return $root;
70             }
71 295         1742 };
72             };
73              
74 295 100       1086 if($args{source})
75             {
76 237         528 my $file = $get_temp_root->()->child('alienfile');
77 237         7658 $file->spew_utf8($args{source});
78 237         136495 $args{filename} = $file->stringify;
79             }
80             else
81             {
82 58 50       273 unless(defined $args{filename})
83             {
84 0         0 croak "You must specify at least one of filename or source";
85             }
86 58         263 $args{filename} = path($args{filename})->absolute->stringify;
87             }
88              
89 295   33     8330 $args{stage} ||= $get_temp_root->('stage')->stringify;
90 295   33     2794 $args{prefix} ||= $get_temp_root->('prefix')->stringify;
91 295   33     2848 $args{root} ||= $get_temp_root->('root')->stringify;
92              
93 295         3575 require Alien::Build;
94              
95 295         1095 _alienfile_clear();
96             my $out = capture_merged {
97 295     295   297554 $build_targ = $args{targ};
98 295         2182 $build = Alien::Build->load($args{filename}, root => $args{root});
99 280         1991 $build->set_stage($args{stage});
100 280         1457 $build->set_prefix($args{prefix});
101 295         10132 };
102              
103 280         214481 my $ctx = context();
104 280 100       51026 $ctx->note($out) if $out;
105 280         3870 $ctx->release;
106              
107 280         7210 $build_alienfile = $args{filename};
108 280         492 $build_root = $temp;
109 280         1042 $build
110             }
111              
112             sub _alienfile_clear
113             {
114 401 100 66 401   771 eval { defined $build_root && -d $build_root && path($build_root)->remove_tree };
  401         2065  
115 401         253018 undef $build;
116 401         834 undef $build_alienfile;
117 401         1388 undef $build_root;
118 401         11556 undef $build_targ;
119             }
120              
121              
122             sub alienfile_ok
123             {
124 162     162 1 688731 my $build;
125             my $name;
126 162         0 my $error;
127              
128 162 100 100     1406 if(@_ == 1 && ! defined $_[0])
    100 100        
129             {
130 1         3 $build = $_[0];
131 1         4 $error = 'no alienfile given';
132 1         2 $name = 'alienfile compiled';
133             }
134 159         1863 elsif(@_ == 1 && eval { $_[0]->isa('Alien::Build') })
135             {
136 1         4 $build = $_[0];
137 1         3 $name = 'alienfile compiled';
138             }
139             else
140             {
141 160         337 $build = eval { alienfile(@_) };
  160         580  
142 160         3774 $error = $@;
143 160         346 $name = 'alienfile compiles';
144             }
145              
146 162         407 my $ok = !! $build;
147              
148 162         430 my $ctx = context();
149 162         11936 $ctx->ok($ok, $name);
150 162 100       25646 $ctx->diag("error: $error") if $error;
151 162         833 $ctx->release;
152              
153 162         3635 $build;
154             }
155              
156              
157             sub alienfile_skip_if_missing_prereqs
158             {
159 12     12 1 4650 my($phase) = @_;
160              
161 12 50       33 if($build)
162             {
163 12         18 eval { $build->load_requires('configure', 1) };
  12         66  
164 12 100       42 if(my $error = $@)
165             {
166 2         6 my $reason = "Missing configure prereq";
167 2 50       17 if($error =~ /Required (.*) (.*),/)
168             {
169 2         10 $reason .= ": $1 $2";
170             }
171 2         6 my $ctx = context();
172 2         192 $ctx->plan(0, SKIP => $reason);
173 0         0 $ctx->release;
174 0         0 return;
175             }
176 10   66     53 $phase ||= $build->install_type;
177 10         659 eval { $build->load_requires($phase, 1) };
  10         33  
178 10 100       39 if(my $error = $@)
179             {
180 7         29 my $reason = "Missing $phase prereq";
181 7 50       72 if($error =~ /Required (.*) (.*),/)
182             {
183 7         28 $reason .= ": $1 $2";
184             }
185 7         24 my $ctx = context();
186 7         682 $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 6398 my($type, $name) = @_;
197              
198 38 50 33     482 croak "invalid install type" unless defined $type && $type =~ /^(system|share)$/;
199 38   66     252 $name ||= "alien install type is $type";
200              
201 38         70 my $ok = 0;
202 38         60 my @diag;
203              
204 38 100       98 if($build)
205             {
206             my($out, $actual) = capture_merged {
207 37     37   35568 $build->load_requires('configure');
208 37         235 $build->install_type;
209 37         1140 };
210 37 100       28266 if($type eq $actual)
211             {
212 35         90 $ok = 1;
213             }
214             else
215             {
216 2         11 push @diag, "expected install type of $type, but got $actual";
217             }
218             }
219             else
220             {
221 1         3 push @diag, 'no alienfile'
222             }
223              
224 38         171 my $ctx = context();
225 38         3939 $ctx->ok($ok, $name);
226 38         5756 $ctx->diag($_) for @diag;
227 38         624 $ctx->release;
228              
229 38         1002 $ok;
230             }
231              
232              
233             sub alien_download_ok
234             {
235 4     4 1 310 my($name) = @_;
236              
237 4   50     26 $name ||= 'alien download';
238              
239 4         20 my $ok;
240             my $file;
241 4         0 my @diag;
242 4         0 my @note;
243              
244 4 50       10 if($build)
245             {
246             my($out, $error) = capture_merged {
247 4     4   4243 eval {
248 4         51 $build->load_requires('configure');
249 4         26 $build->load_requires($build->install_type);
250 4         33 $build->download;
251             };
252 4         499 $@;
253 4         189 };
254 4 100       3237 if($error)
255             {
256 1         4 $ok = 0;
257 1 50       5 push @diag, $out if defined $out;
258 1         4 push @diag, "extract threw exception: $error";
259             }
260             else
261             {
262 3         17 $file = $build->install_prop->{download};
263 3 50 33     88 if(-d $file || -f $file)
264             {
265 3         11 $ok = 1;
266 3 50       16 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         26 my $ctx = context();
283 4         552 $ctx->ok($ok, $name);
284 4         864 $ctx->note($_) for @note;
285 4         769 $ctx->diag($_) for @diag;
286 4         325 $ctx->release;
287              
288 4         114 $file;
289             }
290              
291              
292             sub alien_extract_ok
293             {
294 6     6 1 356 my($archive, $name) = @_;
295              
296 6 50 33     58 $name ||= $archive ? "alien extraction of $archive" : 'alien extraction';
297 6         18 my $ok;
298             my $dir;
299 6         0 my @diag;
300              
301 6 50       23 if($build)
302             {
303 6         14 my($out, $error);
304             ($out, $dir, $error) = capture_merged {
305 6     6   5809 my $dir = eval {
306 6         79 $build->load_requires('configure');
307 6         57 $build->load_requires($build->install_type);
308 6         55 $build->download;
309 6         777 $build->extract($archive);
310             };
311 6         1030 ($dir, $@);
312 6         241 };
313 6 100       5227 if($error)
314             {
315 1         4 $ok = 0;
316 1 50       5 push @diag, $out if defined $out;
317 1         5 push @diag, "extract threw exception: $error";
318             }
319             else
320             {
321 5 50       96 if(-d $dir)
322             {
323 5         199 $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         67 my $ctx = context();
339 6         1066 $ctx->ok($ok, $name);
340 6         1430 $ctx->diag($_) for @diag;
341 6         351 $ctx->release;
342              
343 6         195 $dir;
344             }
345              
346              
347             my $count = 1;
348              
349             sub alien_build_ok
350             {
351 29 50 66 29 1 3821 my $opt = defined $_[0] && ref($_[0]) eq 'HASH'
352             ? shift : { class => 'Alien::Base' };
353              
354 29         94 my($name) = @_;
355              
356 29   100     187 $name ||= 'alien builds okay';
357 29         105 my $ok;
358             my @diag;
359 29         0 my @note;
360 29         0 my $alien;
361              
362 29 100       89 if($build)
363             {
364             my($out,$error) = capture_merged {
365 28     28   25753 eval {
366 28         258 $build->load_requires('configure');
367 28         145 $build->load_requires($build->install_type);
368 28         232 $build->download;
369 27         1632 $build->build;
370             };
371 28         445 $@;
372 28         879 };
373 28 100       21874 if($error)
374             {
375 1         4 $ok = 0;
376 1 50       4 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       179 push @note, $out if defined $out;
384              
385 27         4099 require Alien::Base;
386              
387 27         135 my $prefix = $build->runtime_prop->{prefix};
388 27         119 my $stage = $build->install_prop->{stage};
389 27         65 my %prop = %{ $build->runtime_prop };
  27         85  
390              
391 27         96 $prop{distdir} = $prefix;
392              
393 27         193 _mirror $stage, $prefix;
394              
395             my $dist_dir = sub {
396 0     0   0 $prefix;
397 27         216 };
398              
399             my $runtime_prop = sub {
400 11     11   878 \%prop;
401 27         128 };
402              
403 27         209 $alien = sprintf 'Test::Alien::Build::Faux%04d', $count++;
404             {
405 55     55   560 no strict 'refs';
  55         132  
  55         53588  
  27         66  
406 27         67 @{ "${alien}::ISA" } = $opt->{class};
  27         909  
407 27         84 *{ "${alien}::dist_dir" } = $dist_dir;
  27         216  
408 27         66 *{ "${alien}::runtime_prop" } = $runtime_prop;
  27         161  
409             }
410             }
411             }
412             else
413             {
414 1         2 $ok = 0;
415 1         4 push @diag, 'no alienfile';
416             }
417              
418 29         214 my $ctx = context();
419 29         4003 $ctx->ok($ok, $name);
420 29         5496 $ctx->diag($_) for @diag;
421 29         605 $ctx->note($_) for @note;
422 29         7047 $ctx->release;
423              
424 29         833 $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 3478 my($name) = @_;
451              
452 3   50     17 $name ||= "run clean_install";
453              
454 3         7 my $ok;
455             my @diag;
456 3         0 my @note;
457              
458 3 50       6 if($build)
459             {
460             my($out,$error) = capture_merged {
461 3     3   2547 eval {
462 3         20 $build->clean_install;
463             };
464 3         75 $@;
465 3         76 };
466 3 50       1913 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         6 $ok = 1;
475 3 100 66     14 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         10 my $ctx = context();
485 3         239 $ctx->ok($ok, $name);
486 3         329 $ctx->diag($_) for @diag;
487 3         8 $ctx->note($_) for @note;
488 3         266 $ctx->release;
489             }
490              
491              
492             sub alien_checkpoint_ok
493             {
494 18     18 1 2040 my($name) = @_;
495              
496 18   50     99 $name ||= "alien checkpoint ok";
497 18         31 my $ok;
498             my @diag;
499              
500 18 100       40 if($build)
501             {
502 17         24 eval { $build->checkpoint };
  17         117  
503 17 100       92 if($@)
504             {
505 1         4 push @diag, "error in checkpoint: $@";
506 1         2 $ok = 0;
507             }
508             else
509             {
510 16         34 $ok = 1;
511             }
512 17         172 undef $build;
513             }
514             else
515             {
516 1         4 push @diag, "no build to checkpoint";
517 1         2 $ok = 0;
518             }
519              
520 18         56 my $ctx = context();
521 18         1517 $ctx->ok($ok, $name);
522 18         2426 $ctx->diag($_) for @diag;
523 18         431 $ctx->release;
524              
525 18         396 $ok;
526             }
527              
528              
529             sub alien_resume_ok
530             {
531 17     17 1 1359 my($name) = @_;
532              
533 17   50     107 $name ||= "alien resume ok";
534 17         41 my $ok;
535             my @diag;
536              
537 17 100 66     86 if($build_alienfile && $build_root && !defined $build)
      100        
538             {
539 15         161 $build = eval { Alien::Build->resume($build_alienfile, "$build_root/root") };
  15         36  
540 15 100       50 if($@)
541             {
542 1         4 push @diag, "error in resume: $@";
543 1         3 $ok = 0;
544             }
545             else
546             {
547 14         19 $ok = 1;
548             }
549             }
550             else
551             {
552 2 100       15 if($build)
553             {
554 1         3 push @diag, "build has not been checkpointed";
555             }
556             else
557             {
558 1         3 push @diag, "no build to resume";
559             }
560 2         3 $ok = 0;
561             }
562              
563 17         46 my $ctx = context();
564 17         1459 $ctx->ok($ok, $name);
565 17         2600 $ctx->diag($_) for @diag;
566 17         505 $ctx->release;
567              
568 17 100 66     443 ($ok && $build) || $ok;
569             }
570              
571              
572             my $alien_rc_root;
573              
574             sub alien_rc
575             {
576 1     1 1 6209 my($code) = @_;
577              
578 1 50       4 croak "passed in undef rc" unless defined $code;
579 1 50       4 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         6 my $code2 = "use strict; use warnings;\n" .
583             '# line ' . $line . ' "' . path($filename)->absolute . "\n$code";
584              
585 1   33     160 $alien_rc_root ||= Alien::Build::Temp->newdir;
586              
587 1         298 my $rc = path($alien_rc_root)->child('rc.pl');
588 1         64 $rc->spew_utf8($code2);
589 1         349 $ENV{ALIEN_BUILD_RC} = "$rc";
590 1         10 return 1;
591             }
592              
593              
594             sub alien_subtest
595             {
596 53     53 1 89225 my($name, $code, @args) = @_;
597              
598 53         155 _alienfile_clear;
599              
600 53         165 my $ctx = context();
601 53         9623 my $pass = run_subtest($name, $code, { buffered => 1 }, @args);
602 53         112242 $ctx->release;
603              
604 53         1304 _alienfile_clear;
605              
606 53         187 $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__