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   11558641 use strict;
  55         481  
  55         1697  
4 55     55   290 use warnings;
  55         142  
  55         1409  
5 55     55   1534 use 5.008004;
  55         206  
6 55     55   319 use Exporter qw( import );
  55         121  
  55         2099  
7 55     55   40626 use Path::Tiny qw( path );
  55         571292  
  55         3713  
8 55     55   486 use Carp qw( croak );
  55         121  
  55         2621  
9 55     55   368 use Test2::API qw( context run_subtest );
  55         119  
  55         2905  
10 55     55   29817 use Capture::Tiny qw( capture_merged );
  55         1346414  
  55         4044  
11 55     55   25038 use Alien::Build::Util qw( _mirror );
  55         162  
  55         3761  
12 55     55   429 use List::Util 1.33 qw( any );
  55         1091  
  55         3393  
13 55     55   23322 use Alien::Build::Temp;
  55         137  
  55         118463  
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.46'; # 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 11 $build_targ;
43             }
44              
45             sub alienfile
46             {
47 295     295 1 672382 my($package, $filename, $line) = caller;
48 295 100       2067 ($package, $filename, $line) = caller(2) if $package eq __PACKAGE__;
49 295         1348 $filename = path($filename)->absolute;
50 295 100       39377 my %args = @_ == 0 ? (filename => 'alienfile') : @_ % 2 ? ( source => do { '# line '. $line . ' "' . path($filename)->absolute . qq("\n) . $_[0] }) : @_;
  236 50       1038  
51              
52 295         36774 require alienfile;
53 295 100   7625   2786 push @alienfile::EXPORT, 'targ' unless any { /^targ$/ } @alienfile::EXPORT;
  7625         10930  
54              
55 295         2951 my $temp = Alien::Build::Temp->newdir;
56 295         133210 my $get_temp_root = do{
57 295         719 my $root; # may be undef;
58             sub {
59 1122   66 1122   5047 $root ||= Path::Tiny->new($temp);
60              
61 1122 100       18021 if(@_)
62             {
63 885         2623 my $path = $root->child(@_);
64 885         36108 $path->mkpath;
65 885         148778 $path;
66             }
67             else
68             {
69 237         879 return $root;
70             }
71 295         1993 };
72             };
73              
74 295 100       1258 if($args{source})
75             {
76 237         651 my $file = $get_temp_root->()->child('alienfile');
77 237         8531 $file->spew_utf8($args{source});
78 237         156915 $args{filename} = $file->stringify;
79             }
80             else
81             {
82 58 50       245 unless(defined $args{filename})
83             {
84 0         0 croak "You must specify at least one of filename or source";
85             }
86 58         239 $args{filename} = path($args{filename})->absolute->stringify;
87             }
88              
89 295   33     9215 $args{stage} ||= $get_temp_root->('stage')->stringify;
90 295   33     3222 $args{prefix} ||= $get_temp_root->('prefix')->stringify;
91 295   33     3153 $args{root} ||= $get_temp_root->('root')->stringify;
92              
93 295         4157 require Alien::Build;
94              
95 295         1234 _alienfile_clear();
96             my $out = capture_merged {
97 295     295   339702 $build_targ = $args{targ};
98 295         2354 $build = Alien::Build->load($args{filename}, root => $args{root});
99 280         2147 $build->set_stage($args{stage});
100 280         1516 $build->set_prefix($args{prefix});
101 295         11135 };
102              
103 280         247327 my $ctx = context();
104 280 100       55507 $ctx->note($out) if $out;
105 280         3890 $ctx->release;
106              
107 280         7946 $build_alienfile = $args{filename};
108 280         515 $build_root = $temp;
109 280         1122 $build
110             }
111              
112             sub _alienfile_clear
113             {
114 401 100 66 401   815 eval { defined $build_root && -d $build_root && path($build_root)->remove_tree };
  401         2418  
115 401         306034 undef $build;
116 401         910 undef $build_alienfile;
117 401         1475 undef $build_root;
118 401         13013 undef $build_targ;
119             }
120              
121              
122             sub alienfile_ok
123             {
124 162     162 1 769980 my $build;
125             my $name;
126 162         0 my $error;
127              
128 162 100 100     1586 if(@_ == 1 && ! defined $_[0])
    100 100        
129             {
130 1         3 $build = $_[0];
131 1         2 $error = 'no alienfile given';
132 1         2 $name = 'alienfile compiled';
133             }
134 159         1957 elsif(@_ == 1 && eval { $_[0]->isa('Alien::Build') })
135             {
136 1         3 $build = $_[0];
137 1         1 $name = 'alienfile compiled';
138             }
139             else
140             {
141 160         351 $build = eval { alienfile(@_) };
  160         645  
142 160         4015 $error = $@;
143 160         359 $name = 'alienfile compiles';
144             }
145              
146 162         435 my $ok = !! $build;
147              
148 162         486 my $ctx = context();
149 162         14128 $ctx->ok($ok, $name);
150 162 100       27540 $ctx->diag("error: $error") if $error;
151 162         912 $ctx->release;
152              
153 162         4317 $build;
154             }
155              
156              
157             sub alienfile_skip_if_missing_prereqs
158             {
159 12     12 1 4776 my($phase) = @_;
160              
161 12 50       37 if($build)
162             {
163 12         15 eval { $build->load_requires('configure', 1) };
  12         67  
164 12 100       39 if(my $error = $@)
165             {
166 2         4 my $reason = "Missing configure prereq";
167 2 50       17 if($error =~ /Required (.*) (.*),/)
168             {
169 2         10 $reason .= ": $1 $2";
170             }
171 2         8 my $ctx = context();
172 2         182 $ctx->plan(0, SKIP => $reason);
173 0         0 $ctx->release;
174 0         0 return;
175             }
176 10   66     60 $phase ||= $build->install_type;
177 10         690 eval { $build->load_requires($phase, 1) };
  10         34  
178 10 100       47 if(my $error = $@)
179             {
180 7         17 my $reason = "Missing $phase prereq";
181 7 50       65 if($error =~ /Required (.*) (.*),/)
182             {
183 7         30 $reason .= ": $1 $2";
184             }
185 7         24 my $ctx = context();
186 7         689 $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 6848 my($type, $name) = @_;
197              
198 38 50 33     510 croak "invalid install type" unless defined $type && $type =~ /^(system|share)$/;
199 38   66     259 $name ||= "alien install type is $type";
200              
201 38         71 my $ok = 0;
202 38         81 my @diag;
203              
204 38 100       105 if($build)
205             {
206             my($out, $actual) = capture_merged {
207 37     37   39237 $build->load_requires('configure');
208 37         202 $build->install_type;
209 37         1062 };
210 37 100       33133 if($type eq $actual)
211             {
212 35         100 $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         3 push @diag, 'no alienfile'
222             }
223              
224 38         163 my $ctx = context();
225 38         3998 $ctx->ok($ok, $name);
226 38         5803 $ctx->diag($_) for @diag;
227 38         609 $ctx->release;
228              
229 38         1048 $ok;
230             }
231              
232              
233             sub alien_download_ok
234             {
235 4     4 1 407 my($name) = @_;
236              
237 4   50     26 $name ||= 'alien download';
238              
239 4         15 my $ok;
240             my $file;
241 4         0 my @diag;
242 4         0 my @note;
243              
244 4 50       12 if($build)
245             {
246             my($out, $error) = capture_merged {
247 4     4   3862 eval {
248 4         37 $build->load_requires('configure');
249 4         26 $build->load_requires($build->install_type);
250 4         31 $build->download;
251             };
252 4         458 $@;
253 4         113 };
254 4 100       3149 if($error)
255             {
256 1         2 $ok = 0;
257 1 50       7 push @diag, $out if defined $out;
258 1         5 push @diag, "extract threw exception: $error";
259             }
260             else
261             {
262 3         14 $file = $build->install_prop->{download};
263 3 50 33     92 if(-d $file || -f $file)
264             {
265 3         9 $ok = 1;
266 3 50       15 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         18 my $ctx = context();
283 4         388 $ctx->ok($ok, $name);
284 4         762 $ctx->note($_) for @note;
285 4         820 $ctx->diag($_) for @diag;
286 4         308 $ctx->release;
287              
288 4         101 $file;
289             }
290              
291              
292             sub alien_extract_ok
293             {
294 6     6 1 382 my($archive, $name) = @_;
295              
296 6 50 33     69 $name ||= $archive ? "alien extraction of $archive" : 'alien extraction';
297 6         26 my $ok;
298             my $dir;
299 6         0 my @diag;
300              
301 6 50       22 if($build)
302             {
303 6         14 my($out, $error);
304             ($out, $dir, $error) = capture_merged {
305 6     6   5879 my $dir = eval {
306 6         85 $build->load_requires('configure');
307 6         53 $build->load_requires($build->install_type);
308 6         61 $build->download;
309 6         940 $build->extract($archive);
310             };
311 6         892 ($dir, $@);
312 6         197 };
313 6 100       5436 if($error)
314             {
315 1         3 $ok = 0;
316 1 50       6 push @diag, $out if defined $out;
317 1         4 push @diag, "extract threw exception: $error";
318             }
319             else
320             {
321 5 50       106 if(-d $dir)
322             {
323 5         244 $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         91 my $ctx = context();
339 6         971 $ctx->ok($ok, $name);
340 6         1443 $ctx->diag($_) for @diag;
341 6         382 $ctx->release;
342              
343 6         180 $dir;
344             }
345              
346              
347             my $count = 1;
348              
349             sub alien_build_ok
350             {
351 29 50 66 29 1 4343 my $opt = defined $_[0] && ref($_[0]) eq 'HASH'
352             ? shift : { class => 'Alien::Base' };
353              
354 29         88 my($name) = @_;
355              
356 29   100     207 $name ||= 'alien builds okay';
357 29         123 my $ok;
358             my @diag;
359 29         0 my @note;
360 29         0 my $alien;
361              
362 29 100       100 if($build)
363             {
364             my($out,$error) = capture_merged {
365 28     28   29286 eval {
366 28         290 $build->load_requires('configure');
367 28         158 $build->load_requires($build->install_type);
368 28         257 $build->download;
369 27         2068 $build->build;
370             };
371 28         526 $@;
372 28         884 };
373 28 100       25547 if($error)
374             {
375 1         3 $ok = 0;
376 1 50       6 push @diag, $out if defined $out;
377 1         4 push @diag, "build threw exception: $error";
378             }
379             else
380             {
381 27         92 $ok = 1;
382              
383 27 50       174 push @note, $out if defined $out;
384              
385 27         4644 require Alien::Base;
386              
387 27         164 my $prefix = $build->runtime_prop->{prefix};
388 27         115 my $stage = $build->install_prop->{stage};
389 27         79 my %prop = %{ $build->runtime_prop };
  27         104  
390              
391 27         119 $prop{distdir} = $prefix;
392              
393 27         228 _mirror $stage, $prefix;
394              
395             my $dist_dir = sub {
396 0     0   0 $prefix;
397 27         224 };
398              
399             my $runtime_prop = sub {
400 11     11   1082 \%prop;
401 27         122 };
402              
403 27         207 $alien = sprintf 'Test::Alien::Build::Faux%04d', $count++;
404             {
405 55     55   580 no strict 'refs';
  55         172  
  55         66208  
  27         70  
406 27         80 @{ "${alien}::ISA" } = $opt->{class};
  27         933  
407 27         108 *{ "${alien}::dist_dir" } = $dist_dir;
  27         226  
408 27         68 *{ "${alien}::runtime_prop" } = $runtime_prop;
  27         190  
409             }
410             }
411             }
412             else
413             {
414 1         2 $ok = 0;
415 1         3 push @diag, 'no alienfile';
416             }
417              
418 29         213 my $ctx = context();
419 29         4596 $ctx->ok($ok, $name);
420 29         6519 $ctx->diag($_) for @diag;
421 29         651 $ctx->note($_) for @note;
422 29         8270 $ctx->release;
423              
424 29         974 $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 4625 my($name) = @_;
451              
452 3   50     22 $name ||= "run clean_install";
453              
454 3         11 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   3357 eval {
462 3         28 $build->clean_install;
463             };
464 3         105 $@;
465 3         108 };
466 3 50       2441 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         10 $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         306 $ctx->ok($ok, $name);
486 3         417 $ctx->diag($_) for @diag;
487 3         12 $ctx->note($_) for @note;
488 3         322 $ctx->release;
489             }
490              
491              
492             sub alien_checkpoint_ok
493             {
494 18     18 1 2132 my($name) = @_;
495              
496 18   50     130 $name ||= "alien checkpoint ok";
497 18         32 my $ok;
498             my @diag;
499              
500 18 100       58 if($build)
501             {
502 17         59 eval { $build->checkpoint };
  17         159  
503 17 100       78 if($@)
504             {
505 1         3 push @diag, "error in checkpoint: $@";
506 1         2 $ok = 0;
507             }
508             else
509             {
510 16         31 $ok = 1;
511             }
512 17         228 undef $build;
513             }
514             else
515             {
516 1         3 push @diag, "no build to checkpoint";
517 1         2 $ok = 0;
518             }
519              
520 18         74 my $ctx = context();
521 18         1793 $ctx->ok($ok, $name);
522 18         2654 $ctx->diag($_) for @diag;
523 18         389 $ctx->release;
524              
525 18         471 $ok;
526             }
527              
528              
529             sub alien_resume_ok
530             {
531 17     17 1 1405 my($name) = @_;
532              
533 17   50     122 $name ||= "alien resume ok";
534 17         35 my $ok;
535             my @diag;
536              
537 17 100 66     101 if($build_alienfile && $build_root && !defined $build)
      100        
538             {
539 15         196 $build = eval { Alien::Build->resume($build_alienfile, "$build_root/root") };
  15         44  
540 15 100       59 if($@)
541             {
542 1         4 push @diag, "error in resume: $@";
543 1         2 $ok = 0;
544             }
545             else
546             {
547 14         29 $ok = 1;
548             }
549             }
550             else
551             {
552 2 100       15 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         3 $ok = 0;
561             }
562              
563 17         54 my $ctx = context();
564 17         1736 $ctx->ok($ok, $name);
565 17         2886 $ctx->diag($_) for @diag;
566 17         501 $ctx->release;
567              
568 17 100 66     567 ($ok && $build) || $ok;
569             }
570              
571              
572             my $alien_rc_root;
573              
574             sub alien_rc
575             {
576 1     1 1 5166 my($code) = @_;
577              
578 1 50       5 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     108 $alien_rc_root ||= Alien::Build::Temp->newdir;
586              
587 1         314 my $rc = path($alien_rc_root)->child('rc.pl');
588 1         65 $rc->spew_utf8($code2);
589 1         361 $ENV{ALIEN_BUILD_RC} = "$rc";
590 1         10 return 1;
591             }
592              
593              
594             sub alien_subtest
595             {
596 53     53 1 67464 my($name, $code, @args) = @_;
597              
598 53         189 _alienfile_clear;
599              
600 53         187 my $ctx = context();
601 53         10565 my $pass = run_subtest($name, $code, { buffered => 1 }, @args);
602 53         116386 $ctx->release;
603              
604 53         1441 _alienfile_clear;
605              
606 53         257 $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__