File Coverage

blib/lib/Test/Reporter.pm
Criterion Covered Total %
statement 318 455 69.8
branch 120 282 42.5
condition 15 77 19.4
subroutine 39 48 81.2
pod 16 16 100.0
total 508 878 57.8


line stmt bran cond sub pod time code
1 4     4   147928 use 5.006;
  4         15  
  4         196  
2 4     4   24 use strict;
  4         8  
  4         173  
3 4     4   23 use warnings;
  4         9  
  4         258  
4             package Test::Reporter;
5             our $VERSION = '1.60'; # VERSION
6              
7 4     4   28 use Cwd;
  4         6  
  4         301  
8 4     4   23 use Config;
  4         8  
  4         154  
9 4     4   21 use Carp;
  4         7  
  4         252  
10 4     4   4527 use FileHandle;
  4         9256  
  4         28  
11 4     4   4203 use File::Temp;
  4         119894  
  4         489  
12 4     4   7615 use Sys::Hostname;
  4         6378  
  4         307  
13 4     4   4254 use Time::Local ();
  4         9404  
  4         134  
14 4     4   30 use vars qw($AUTOLOAD $Tempfile $Report $DNS $Domain $Send);
  4         7  
  4         398  
15 4     4   20 use constant FAKE_NO_NET_DNS => 0; # for debugging only
  4         8  
  4         175  
16 4     4   19 use constant FAKE_NO_NET_DOMAIN => 0; # for debugging only
  4         8  
  4         154  
17 4     4   18 use constant FAKE_NO_MAIL_SEND => 0; # for debugging only
  4         7  
  4         18278  
18              
19             local $^W = 1;
20              
21             sub new {
22 12     12 1 4008 my $type = shift;
23 12   33     146 my $class = ref($type) || $type;
24 12         738 my $self = {
25             '_grade' => undef,
26             '_distribution' => undef,
27             # XXX distfile => undef would break old clients :-( -- dagolden, 2009-03-30
28             '_distfile' => '',
29             '_report' => undef,
30             '_subject' => undef,
31             '_from' => undef,
32             '_comments' => '',
33             '_errstr' => '',
34             '_via' => '',
35             '_timeout' => 120,
36             '_debug' => 0,
37             '_dir' => '',
38             '_subject_lock' => 0,
39             '_report_lock' => 0,
40             '_perl_version' => {
41             '_archname' => $Config{archname},
42             '_osvers' => $Config{osvers},
43             },
44             '_transport' => '',
45             '_transport_args' => [],
46             # DEPRECATED ARGS
47             '_address' => 'cpan-testers@perl.org',
48             '_mx' => ['mx.develooper.com'],
49             '_mail_send_args' => '',
50             };
51              
52 12         61 bless $self, $class;
53              
54 12         50 $self->{_perl_version}{_myconfig} = $self->_get_perl_V;
55 12         331 $self->{_perl_version}{_version} = $self->_normalize_perl_version;
56              
57 108         1112 $self->{_attr} = {
58 12         159 map {$_ => 1} qw(
59             _address _distribution _distfile _comments _errstr _via _timeout _debug _dir
60             )
61             };
62              
63 12 50       137 warn __PACKAGE__, ": new\n" if $self->debug();
64 12 50       93 croak __PACKAGE__, ": new: even number of named arguments required"
65             unless scalar @_ % 2 == 0;
66              
67 12 100       137 $self->_process_params(@_) if @_;
68 12 100       121 $self->transport('Null') unless $self->transport();
69 12 50       92 $self->_get_mx(@_) if $self->_have_net_dns();
70              
71 12         181 return $self;
72             }
73              
74             sub debug {
75 254     254 1 396 my $self = shift;
76 254         2650 return $self->{_debug};
77             }
78              
79             sub _get_mx {
80 12     12   449722 my $self = shift;
81 12 50       63 warn __PACKAGE__, ": _get_mx\n" if $self->debug();
82              
83 12         52 my %params = @_;
84              
85 12 100       51 return if exists $params{'mx'};
86              
87 11   33     4134 my $dom = $params{'address'} || $self->address();
88 11         25 my @mx;
89              
90 11         106 $dom =~ s/^.+\@//;
91              
92 11         129 for my $mx (sort {$a->preference() <=> $b->preference()} Net::DNS::mx($dom)) {
  0         0  
93 11         97806 push @mx, $mx->exchange();
94             }
95              
96 11 50       1173 if (not @mx) {
97 0 0       0 warn __PACKAGE__,
98             ": _get_mx: unable to find MX's for $dom, using defaults\n" if
99             $self->debug();
100 0         0 return;
101             }
102              
103 11         148 $self->mx(\@mx);
104             }
105              
106             sub _process_params {
107 4     4   12 my $self = shift;
108 4 50       29 warn __PACKAGE__, ": _process_params\n" if $self->debug();
109              
110 4         119 my %params = @_;
111 4         65 my @defaults = qw(
112             mx address grade distribution distfile from comments via timeout debug dir perl_version transport_args transport );
113 4         14 my %defaults = map {$_ => 1} @defaults;
  56         284  
114              
115 4         42 for my $param (keys %params) {
116 19 50       82 croak __PACKAGE__, ": new: parameter '$param' is invalid." unless
117             exists $defaults{$param};
118             }
119              
120             # XXX need to process transport_args directly rather than through
121             # the following -- store array ref directly
122 4         18 for my $param (keys %params) {
123 19         651 $self->$param($params{$param});
124             }
125             }
126              
127             sub subject {
128 14     14 1 6329 my $self = shift;
129 14 50       48 warn __PACKAGE__, ": subject\n" if $self->debug();
130 14 50 33     138 croak __PACKAGE__, ": subject: grade and distribution must first be set"
131             if not defined $self->{_grade} or not defined $self->{_distribution};
132              
133 14 100       79 return $self->{_subject} if $self->{_subject_lock};
134              
135 10         229 my $subject = uc($self->{_grade}) . ' ' . $self->{_distribution} .
136             " $self->{_perl_version}->{_archname} $self->{_perl_version}->{_osvers}";
137              
138 10         56 return $self->{_subject} = $subject;
139             }
140              
141             sub report {
142 21     21 1 54 my $self = shift;
143 21 50       55 warn __PACKAGE__, ": report\n" if $self->debug();
144              
145 21 100       92 return $self->{_report} if $self->{_report_lock};
146              
147 15         25 my $report;
148 15         45 $report .= "This distribution has been tested as part of the CPAN Testers\n";
149 15         29 $report .= "project, supporting the Perl programming language. See\n";
150 15         72 $report .= "http://wiki.cpantesters.org/ for more information or email\n";
151 15         32 $report .= "questions to cpan-testers-discuss\@perl.org\n\n";
152              
153 15 100       59 if (not $self->{_comments}) {
154 9         24 $report .= "\n\n--\n\n";
155             }
156             else {
157 6         17 $report .= "\n--\n" . $self->{_comments} . "\n--\n\n";
158             }
159              
160 15         121 $report .= $self->{_perl_version}->{_myconfig};
161              
162 15         127 chomp $report;
163 15         19 chomp $report;
164              
165 15         116 return $self->{_report} = $report;
166             }
167              
168             sub grade {
169 18     18 1 5469 my ($self, $grade) = @_;
170 18 50       51 warn __PACKAGE__, ": grade\n" if $self->debug();
171              
172 18         200 my %grades = (
173             'pass' => "all tests passed",
174             'fail' => "one or more tests failed",
175             'na' => "distribution will not work on this platform",
176             'unknown' => "distribution did not include tests",
177             );
178              
179 18 100       143 return $self->{_grade} if scalar @_ == 1;
180              
181 8 50       29 croak __PACKAGE__, ":grade: '$grade' is invalid, choose from: " .
182             join ' ', keys %grades unless $grades{$grade};
183              
184 8         46 return $self->{_grade} = $grade;
185             }
186              
187             sub transport {
188 29     29 1 1821 my $self = shift;
189 29 50       85 warn __PACKAGE__, ": transport\n" if $self->debug();
190              
191 29 100       173 return $self->{_transport} unless scalar @_;
192              
193 15         35 my $transport = shift;
194              
195 15         76 my $transport_class = "Test::Reporter::Transport::$transport";
196 15 100       2863 unless ( eval "require $transport_class; 1" ) { ## no critic
197 1         2314 croak __PACKAGE__ . ": could not load '$transport_class'\n$@\n";
198             }
199              
200 14         293 my @args = @_;
201              
202             # XXX keep this for legacy support
203 14 50 66     243 if ( @args && $transport eq 'Mail::Send' && ref $args[0] eq 'ARRAY' ) {
    100 33        
204             # treat as old form of Mail::Send arguments and convert to list
205 0         0 $self->transport_args(@{$args[0]});
  0         0  
206             }
207             elsif ( @args ) {
208 2         16 $self->transport_args(@args);
209             }
210              
211 14         86 return $self->{_transport} = $transport;
212             }
213              
214             sub edit_comments {
215 0     0 1 0 my($self, %args) = @_;
216 0 0       0 warn __PACKAGE__, ": edit_comments\n" if $self->debug();
217              
218 0         0 my %tempfile_args = (
219             UNLINK => 1,
220             SUFFIX => '.txt',
221             EXLOCK => 0,
222             );
223              
224 0 0 0     0 if (exists $args{'suffix'} && defined $args{'suffix'} && length $args{'suffix'}) {
      0        
225 0         0 $tempfile_args{SUFFIX} = $args{'suffix'};
226             # prefix the extension with a period, if the user didn't.
227 0         0 $tempfile_args{SUFFIX} =~ s/^(?!\.)(?=.)/./;
228             }
229              
230 0         0 ($Tempfile, $Report) = File::Temp::tempfile(%tempfile_args);
231              
232 0         0 print $Tempfile $self->{_comments};
233              
234 0         0 $self->_start_editor();
235              
236 0         0 my $comments;
237             {
238 0         0 local $/;
  0         0  
239 0 0       0 open my $fh, "<", $Report or die __PACKAGE__, ": Can't open comment file '$Report': $!";
240 0         0 $comments = <$fh>;
241 0 0       0 close $fh or die __PACKAGE__, ": Can't close comment file '$Report': $!";
242             }
243              
244 0         0 chomp $comments;
245              
246 0         0 $self->{_comments} = $comments;
247              
248 0         0 return;
249             }
250              
251             sub send {
252 1     1 1 10 my ($self) = @_;
253 1 50       4 warn __PACKAGE__, ": send\n" if $self->debug();
254              
255 1         5 $self->from();
256 1         4 $self->report();
257 1         5 $self->subject();
258              
259 1 50       14 return unless $self->_verify();
260              
261 1 50       29 if ($self->_is_a_perl_release($self->distribution())) {
262 0         0 $self->errstr(__PACKAGE__ . ": use perlbug for reporting test " .
263             "results against perl itself");
264 0         0 return;
265             }
266              
267 1   50     6 my $transport_type = $self->transport() || 'Null';
268 1         5 my $transport_class = "Test::Reporter::Transport::$transport_type";
269 1         4 my $transport = $transport_class->new( $self->transport_args() );
270              
271 1 50       3 unless ( eval { $transport->send( $self ) } ) {
  1         4  
272 0         0 $self->errstr(__PACKAGE__ . ": error from '$transport_class:'\n$@\n");
273 0         0 return;
274             }
275              
276 1         20 return 1;
277             }
278              
279             sub _normalize_perl_version {
280 12     12   62 my $self = shift;
281 12         635 my $perl_version = sprintf("v%vd",$^V);
282 12         131 my $perl_V = $self->perl_version->{_myconfig};
283 12         378 my ($rc) = $perl_V =~ /Locally applied patches:\n\s+(RC\d+)/m;
284 12 50       83 $perl_version .= " $rc" if $rc;
285 12         89 return $perl_version;
286             }
287              
288             sub write {
289 3     3 1 4118 my $self = shift;
290 3 50       24 warn __PACKAGE__, ": write\n" if $self->debug();
291              
292 3         101 my $from = $self->from();
293 3         25 my $report = $self->report();
294 3         17 my $subject = $self->subject();
295 3         142 my $distribution = $self->distribution();
296 3         48 my $grade = $self->grade();
297 3   66     76 my $dir = $self->dir() || cwd;
298 3   50     94 my $distfile = $self->{_distfile} || '';
299 3         75 my $perl_version = $self->perl_version->{_version};
300              
301 3 50       48 return unless $self->_verify();
302              
303 3         24 $distribution =~ s/[^A-Za-z0-9\.\-]+//g;
304              
305 3 50       8 my($fh, $file); unless ($fh = $_[0]) {
  3         21  
306 3         23 $file = "$grade.$distribution.$self->{_perl_version}->{_archname}.$self->{_perl_version}->{_osvers}.${\(time)}.$$.rpt";
  3         50  
307              
308 3 50       72 if ($^O eq 'VMS') {
309 0         0 $file = "$grade.$distribution.$self->{_perl_version}->{_archname}";
310 0         0 my $ext = "$self->{_perl_version}->{_osvers}.${\(time)}.$$.rpt";
  0         0  
311             # only 1 period in filename
312             # we also only have 39.39 for filename
313 0         0 $file =~ s/\./_/g;
314 0         0 $ext =~ s/\./_/g;
315 0         0 $file = $file . '.' . $ext;
316             }
317              
318 3         164 $file = File::Spec->catfile($dir, $file);
319              
320 3 50       20 warn $file if $self->debug();
321 3         74 $fh = FileHandle->new();
322 3 50       1294 open $fh, ">", $file or die __PACKAGE__, ": Can't open report file '$file': $!";
323             }
324 3         75 print $fh "From: $from\n";
325 3 50       123 if ($distfile ne '') {
326 3         22 print $fh "X-Test-Reporter-Distfile: $distfile\n";
327             }
328 3         18 print $fh "X-Test-Reporter-Perl: $perl_version\n";
329 3         15 print $fh "Subject: $subject\n";
330 3         31 print $fh "Report: $report";
331 3 50       17 unless ($_[0]) {
332 3 50       214 close $fh or die __PACKAGE__, ": Can't close report file '$file': $!";
333 3 50       19 warn $file if $self->debug();
334 3         59 return $file;
335             } else {
336 0         0 return $fh;
337             }
338             }
339              
340             sub read {
341 3     3 1 15 my ($self, $file) = @_;
342 3 50       23 warn __PACKAGE__, ": read\n" if $self->debug();
343              
344             # unlock these; if not locked later, we have a parse error
345 3         11 $self->{_report_lock} = $self->{_subject_lock} = 0;
346              
347 3         13 my $buffer;
348              
349             {
350 3         8 local $/;
  3         28  
351 3 50       258 open my $fh, "<", $file or die __PACKAGE__, ": Can't open report file '$file': $!";
352 3         103 $buffer = <$fh>;
353 3 50       66 close $fh or die __PACKAGE__, ": Can't close report file '$file': $!";
354             }
355              
356             # convert line endings
357 3         22 my $CR = "\015";
358 3         10 my $LF = "\012";
359 3         99 $buffer =~ s{$CR$LF}{$LF}g;
360 3         43 $buffer =~ s{$CR}{$LF}g;
361              
362             # parse out headers
363 3         60 foreach my $line (split(/\n/, $buffer)) {
364 15 50       107 if ($line =~ /^(.+):\s(.+)$/) {
365 15         63 my ($header, $content) = ($1, $2);
366 15 100       87 if ($header eq "From") {
    100          
    100          
    100          
    50          
367 3         13 $self->{_from} = $content;
368             } elsif ($header eq "Subject") {
369 3         11 $self->{_subject} = $content;
370 3         35 my ($grade, $distribution, $archname) = (split /\s/, $content)[0..2];
371 3         37 $self->{_grade} = lc $grade;
372 3         58 $self->{_distribution} = $distribution;
373 3         19 $self->{_perl_version}{_archname} = $archname;
374 3         17 $self->{_subject_lock} = 1;
375             } elsif ($header eq "X-Test-Reporter-Distfile") {
376 3         23 $self->{_distfile} = $content;
377             } elsif ($header eq "X-Test-Reporter-Perl") {
378 3         18 $self->{_perl_version}{_version} = $content;
379             } elsif ($header eq "Report") {
380 3         9 last;
381             }
382             }
383             }
384              
385             # parse out body
386 3 50 33     54 if ( $self->{_from} && $self->{_subject} ) {
387 3         37 ($self->{_report}) = ($buffer =~ /^.+?Report:\s(.+)$/s);
388 3         31 my ($perlv) = $self->{_report} =~ /(^Summary of my perl5.*)\z/ms;
389 3 50       17 $self->{_perl_version}{_myconfig} = $perlv if $perlv;
390 3         13 $self->{_report_lock} = 1;
391             }
392              
393             # check that the full report was parsed
394 3 50       12 if ( ! $self->{_report_lock} ) {
395 0         0 die __PACKAGE__, ": Failed to parse report file '$file'\n";
396             }
397              
398 3         24 return $self;
399             }
400              
401             sub _verify {
402 4     4   21 my $self = shift;
403 4 50       21 warn __PACKAGE__, ": _verify\n" if $self->debug();
404              
405 4         16 my @undefined;
406              
407 4         18 for my $key (keys %{$self}) {
  4         247  
408 84 50       320 push @undefined, $key unless defined $self->{$key};
409             }
410              
411 0         0 $self->errstr(__PACKAGE__ . ": Missing values for: " .
412 4 50       32 join ', ', map {$_ =~ /^_(.+)$/} @undefined) if
413             scalar @undefined > 0;
414 4 50       159 return $self->errstr() ? return 0 : return 1;
415             }
416              
417             # Courtesy of Email::MessageID
418             sub message_id {
419 1     1 1 2 my $self = shift;
420 1 50       3 warn __PACKAGE__, ": message_id\n" if $self->debug();
421              
422 1         2 my $unique_value = 0;
423 1         10 my @CHARS = ('A'..'F','a'..'f',0..9);
424 1         2 my $length = 3;
425              
426 1         11 $length = rand(8) until $length > 3;
427              
428 1         14 my $pseudo_random = join '', (map $CHARS[rand $#CHARS], 0 .. $length), $unique_value++;
429 1         12 my $user = join '.', time, $pseudo_random, $$;
430              
431 1         18 return '<' . $user . '@' . Sys::Hostname::hostname() . '>';
432             }
433              
434             sub from {
435 15     15 1 105 my $self = shift;
436 15 50       52 warn __PACKAGE__, ": from\n" if $self->debug();
437              
438 15 100       69 if (@_) {
439 5         21 $self->{_from} = shift;
440 5         19 return $self->{_from};
441             }
442             else {
443 10 50 33     166 return $self->{_from} if defined $self->{_from} and $self->{_from};
444 0         0 $self->{_from} = $self->_mailaddress();
445 0         0 return $self->{_from};
446             }
447              
448             }
449              
450             sub mx {
451 15     15 1 40 my $self = shift;
452 15 50       66 warn __PACKAGE__, ": mx\n" if $self->debug();
453              
454 15 100       57 if (@_) {
455 13         24 my $mx = shift;
456 13 50       55 croak __PACKAGE__,
457             ": mx: array reference required" if ref $mx ne 'ARRAY';
458 13         46 $self->{_mx} = $mx;
459             }
460              
461 15         124 return $self->{_mx};
462             }
463              
464             # Deprecated, but kept for backwards compatibility
465             # Passes through to transport_args -- converting from array ref to list to
466             # store and converting from list to array ref to get
467             sub mail_send_args {
468 0     0 1 0 my $self = shift;
469 0 0       0 warn __PACKAGE__, ": mail_send_args\n" if $self->debug();
470 0 0       0 croak __PACKAGE__, ": mail_send_args cannot be called unless Mail::Send is installed\n"
471             unless $self->_have_mail_send();
472 0 0       0 if (@_) {
473 0         0 my $mail_send_args = shift;
474 0 0       0 croak __PACKAGE__, ": mail_send_args: array reference required\n"
475             if ref $mail_send_args ne 'ARRAY';
476 0         0 $self->transport_args(@$mail_send_args);
477             }
478 0         0 return [ $self->transport_args() ];
479             }
480              
481              
482              
483             sub transport_args {
484 4     4 1 9 my $self = shift;
485 4 50       13 warn __PACKAGE__, ": transport_args\n" if $self->debug();
486              
487 4 100       15 if (@_) {
488 2 50       18 $self->{_transport_args} = ref $_[0] eq 'ARRAY' ? $_[0] : [ @_ ];
489             }
490              
491 4         7 return @{ $self->{_transport_args} };
  4         20  
492             }
493              
494             # quote for command-line perl
495 15 50 33 15   322 sub _get_sh_quote { ( ($^O eq "MSWin32") || ($^O eq 'VMS') ) ? '"' : "'" }
496              
497              
498             sub perl_version {
499 22     22 1 3178 my $self = shift;
500 22 50       672 warn __PACKAGE__, ": perl_version\n" if $self->debug();
501              
502 22 100       117 if( @_) {
503 2         5 my $perl = shift;
504 2         14 my $q = $self->_get_sh_quote;
505 2         9 my $magick = int(rand(1000)); # just to check that we get a valid result back
506 2         9 my $cmd = "$perl -MConfig -e$q print qq{$magick\n\$Config{archname}\n\$Config{osvers}\n};$q";
507 2 50       9 if($^O eq 'VMS'){
508 0         0 my $sh = $Config{'sh'};
509 0         0 $cmd = "$sh $perl $q-MConfig$q -e$q print qq{$magick\\n\$Config{archname}\\n\$Config{osvers}\\n};$q";
510             }
511 2         42926 my $conf = `$cmd`;
512 2         37 chomp $conf;
513 2         9 my %conf;
514 2         61 ( @conf{ qw( magick _archname _osvers) } ) = split( /\n/, $conf, 3);
515 2 100       603 croak __PACKAGE__, ": cannot get perl version info from $perl: $conf" if( $conf{magick} ne $magick);
516 1         8 delete $conf{magick};
517 1         37 $conf{_myconfig} = $self->_get_perl_V($perl);
518 1         21 chomp $conf;
519 1         92 $self->{_perl_version} = \%conf;
520             }
521 21         129 return $self->{_perl_version};
522             }
523              
524             sub _get_perl_V {
525 13     13   40 my $self = shift;
526 13   66     105 my $perl = shift || $^X;
527 13         71 my $q = $self->_get_sh_quote;
528 13         55 my $cmdv = "$perl -V";
529 13 50       54 if($^O eq 'VMS'){
530 0         0 my $sh = $Config{'sh'};
531 0         0 $cmdv = "$sh $perl $q-V$q";
532             }
533 13         368251 my $perl_V = `$cmdv`;
534 13         251 chomp $perl_V;
535 13         821 return $perl_V;
536             }
537              
538             sub AUTOLOAD {
539 19     19   144 my $self = $_[0];
540 19         248 my ($package, $method) = ($AUTOLOAD =~ /(.*)::(.*)/);
541              
542 19 50       230 return if $method =~ /^DESTROY$/;
543              
544 19 50       415 unless ($self->{_attr}->{"_$method"}) {
545 0         0 croak __PACKAGE__, ": No such method: $method; aborting";
546             }
547              
548 19         66 my $code = q{
549             sub {
550             my $self = shift;
551             warn __PACKAGE__, ": METHOD\n" if $self->{_debug};
552             $self->{_METHOD} = shift if @_;
553             return $self->{_METHOD};
554             }
555             };
556              
557 19         158 $code =~ s/METHOD/$method/g;
558              
559             {
560 4     4   51 no strict 'refs';
  4         10  
  4         8370  
  19         38  
561 19 50   11   3687 *$AUTOLOAD = eval $code; ## no critic
  11 100       63  
  11 50       63  
  11 100       35  
  11 50       72  
  13 100       90  
  13 50       190  
  13 100       85  
  13 50       140  
  4 100       16  
  4 50       47  
  4 100       23  
  4 50       33  
  9 100       27  
  9 50       224  
  9 100       110  
  9         57  
  8         26  
  8         56  
  8         37  
  8         5656  
  3         10  
  3         23  
  3         13  
  3         6265  
  9         921  
  9         52  
  9         136  
  9         53  
  4         45  
  4         20  
  4         27  
  4         22  
562             }
563              
564 19         600 goto &$AUTOLOAD;
565             }
566              
567             sub _have_net_dns {
568 12     12   32 my $self = shift;
569 12 50       41 warn __PACKAGE__, ": _have_net_dns\n" if $self->debug();
570              
571 12 100       138 return $DNS if defined $DNS;
572 4         5 return 0 if FAKE_NO_NET_DNS;
573              
574 4         9 $DNS = eval {require Net::DNS};
  4         4777  
575             }
576              
577             sub _have_net_domain {
578 0     0   0 my $self = shift;
579 0 0       0 warn __PACKAGE__, ": _have_net_domain\n" if $self->debug();
580              
581 0 0       0 return $Domain if defined $Domain;
582 0         0 return 0 if FAKE_NO_NET_DOMAIN;
583              
584 0         0 $Domain = eval {require Net::Domain};
  0         0  
585             }
586              
587             sub _have_mail_send {
588 0     0   0 my $self = shift;
589 0 0       0 warn __PACKAGE__, ": _have_mail_send\n" if $self->debug();
590              
591 0 0       0 return $Send if defined $Send;
592 0         0 return 0 if FAKE_NO_MAIL_SEND;
593              
594 0         0 $Send = eval {require Mail::Send};
  0         0  
595             }
596              
597             sub _start_editor {
598 0     0   0 my $self = shift;
599 0 0       0 warn __PACKAGE__, ": _start_editor\n" if $self->debug();
600              
601 0   0     0 my $editor = $ENV{VISUAL} || $ENV{EDITOR} || $ENV{EDIT}
602             || ($^O eq 'VMS' and "edit/tpu")
603             || ($^O eq 'MSWin32' and "notepad")
604             || 'vi';
605              
606 0         0 $editor = $self->_prompt('Editor', $editor);
607              
608 0 0       0 die __PACKAGE__, ": The editor `$editor' could not be run on '$Report': $!" if system "$editor $Report";
609 0 0       0 die __PACKAGE__, ": Report has disappeared; terminated" unless -e $Report;
610 0 0       0 die __PACKAGE__, ": Empty report; terminated" unless -s $Report > 2;
611             }
612              
613             sub _prompt {
614 0     0   0 my $self = shift;
615 0 0       0 warn __PACKAGE__, ": _prompt\n" if $self->debug();
616              
617 0         0 my ($label, $default) = @_;
618              
619 0         0 printf "$label%s", (" [$default]: ");
620 0         0 my $input = scalar ;
621 0         0 chomp $input;
622              
623 0 0       0 return (length $input) ? $input : $default;
624             }
625              
626             # From Mail::Util 1.74 (c) 1995-2001 Graham Barr (c) 2002-2005 Mark Overmeer
627             {
628             # cache the mail domain, so we don't try to resolve this *every* time
629             # (thanks you kane)
630             my $domain;
631              
632             sub _maildomain {
633 0     0   0 my $self = shift;
634 0 0       0 warn __PACKAGE__, ": _maildomain\n" if $self->debug();
635              
636             # use cached value if set
637 0 0       0 return $domain if defined $domain;
638              
639             # prefer MAILDOMAIN if set
640 0 0       0 if ( defined $ENV{MAILDOMAIN} ) {
641 0         0 return $domain = $ENV{MAILDOMAIN};
642             }
643              
644 0         0 local $_;
645              
646 0         0 my @sendmailcf = qw(
647             /etc /etc/sendmail /etc/ucblib /etc/mail /usr/lib /var/adm/sendmail
648             );
649              
650 0         0 my $config = (grep(-r, map("$_/sendmail.cf", @sendmailcf)))[0];
651              
652 0 0 0     0 if (defined $config && open(my $cf, "<", $config)) {
653 0         0 my %var;
654 0         0 while (<$cf>) {
655 0 0       0 if (my ($v, $arg) = /^D([a-zA-Z])([\w.\$\-]+)/) {
656 0 0       0 $arg =~ s/\$([a-zA-Z])/exists $var{$1} ? $var{$1} : '$'.$1/eg;
  0         0  
657 0         0 $var{$v} = $arg;
658             }
659             }
660 0 0       0 close($cf) || die $!;
661 0 0       0 $domain = $var{j} if defined $var{j};
662 0 0       0 $domain = $var{M} if defined $var{M};
663              
664 0 0 0     0 $domain = $1
665             if ($domain && $domain =~ m/([A-Za-z0-9](?:[\.\-A-Za-z0-9]+))/);
666              
667 0 0 0     0 undef $domain if $^O eq 'darwin' && $domain =~ /\.local$/;
668              
669 0 0 0     0 return $domain if (defined $domain && $domain !~ /\$/);
670             }
671              
672 0 0       0 if (open(my $cf, "<", "/usr/lib/smail/config")) {
673 0         0 while (<$cf>) {
674 0 0       0 if (/\A\s*hostnames?\s*=\s*(\S+)/) {
675 0         0 $domain = (split(/:/,$1))[0];
676 0 0 0     0 undef $domain if $^O eq 'darwin' && $domain =~ /\.local$/;
677 0 0 0     0 last if defined $domain and $domain;
678             }
679             }
680 0 0       0 close($cf) || die $!;
681              
682 0 0       0 return $domain if defined $domain;
683             }
684              
685 0 0       0 if (eval {require Net::SMTP}) {
  0         0  
686 0         0 for my $host (qw(mailhost smtp localhost)) {
687              
688             # default timeout is 120, which is Very Very Long, so lower
689             # it to 5 seconds. Total slowdown will not be more than
690             # 15 seconds ( 5 x @hosts ) --kane
691 0         0 my $smtp = eval {Net::SMTP->new($host, Timeout => 5)};
  0         0  
692              
693 0 0       0 if (defined $smtp) {
694 0         0 $domain = $smtp->domain;
695 0         0 $smtp->quit;
696 0 0 0     0 undef $domain if $^O eq 'darwin' && $domain =~ /\.local$/;
697 0 0 0     0 last if defined $domain and $domain;
698             }
699             }
700             }
701              
702 0 0       0 unless (defined $domain) {
703 0 0       0 if ($self->_have_net_domain()) {
704             ###################################################################
705             # The below statement might possibly exhibit intermittent blocking
706             # behavior. Be advised!
707             ###################################################################
708 0         0 $domain = Net::Domain::domainname();
709 0 0 0     0 undef $domain if $^O eq 'darwin' && $domain =~ /\.local$/;
710             }
711             }
712              
713 0 0       0 $domain = "localhost" unless defined $domain;
714              
715 0         0 return $domain;
716             }
717             }
718              
719             # From Mail::Util 1.74 (c) 1995-2001 Graham Barr (c) 2002-2005 Mark Overmeer
720             sub _mailaddress {
721 0     0   0 my $self = shift;
722 0 0       0 warn __PACKAGE__, ": _mailaddress\n" if $self->debug();
723              
724 0         0 my $mailaddress = $ENV{MAILADDRESS};
725             $mailaddress ||= $ENV{USER} ||
726             $ENV{LOGNAME} ||
727 0   0     0 eval {getpwuid($>)} ||
      0        
728             "postmaster";
729 0 0       0 $mailaddress .= '@' . $self->_maildomain() unless $mailaddress =~ /\@/;
730 0         0 $mailaddress =~ s/(^.*<|>.*$)//g;
731              
732 0         0 my $realname = $self->_realname();
733 0 0       0 if ($realname) {
734 0         0 $mailaddress = "$mailaddress ($realname)";
735             }
736              
737 0         0 return $mailaddress;
738             }
739              
740             sub _realname {
741 0     0   0 my $self = shift;
742 0 0       0 warn __PACKAGE__, ": _realname\n" if $self->debug();
743              
744 0         0 my $realname = '';
745              
746             $realname =
747 0   0     0 eval {(split /,/, (getpwuid($>))[6])[0]} ||
748             $ENV{QMAILNAME} ||
749             $ENV{REALNAME} ||
750             $ENV{USER};
751              
752 0         0 return $realname;
753             }
754              
755             sub _is_a_perl_release {
756 55     55   1263 my $self = shift;
757 55 50       139 warn __PACKAGE__, ": _is_a_perl_release\n" if $self->debug();
758              
759 55         128 my $perl = shift;
760              
761 55         379 return $perl =~ /^perl-?\d\.\d/;
762             }
763              
764             1;
765              
766             # ABSTRACT: sends test results to cpan-testers@perl.org
767              
768             =pod
769              
770             =encoding UTF-8
771              
772             =head1 NAME
773              
774             Test::Reporter - sends test results to cpan-testers@perl.org
775              
776             =head1 VERSION
777              
778             version 1.60
779              
780             =head1 SYNOPSIS
781              
782             use Test::Reporter;
783              
784             my $reporter = Test::Reporter->new(
785             transport => 'File',
786             transport_args => [ '/tmp' ],
787             );
788              
789             $reporter->grade('pass');
790             $reporter->distribution('Mail-Freshmeat-1.20');
791             $reporter->send() || die $reporter->errstr();
792              
793             # or
794              
795             my $reporter = Test::Reporter->new(
796             transport => 'File',
797             transport_args => [ '/tmp' ],
798             );
799              
800             $reporter->grade('fail');
801             $reporter->distribution('Mail-Freshmeat-1.20');
802             $reporter->comments('output of a failed make test goes here...');
803             $reporter->edit_comments(); # if you want to edit comments in an editor
804             $reporter->send() || die $reporter->errstr();
805              
806             # or
807              
808             my $reporter = Test::Reporter->new(
809             transport => 'File',
810             transport_args => [ '/tmp' ],
811             grade => 'fail',
812             distribution => 'Mail-Freshmeat-1.20',
813             from => 'whoever@wherever.net (Whoever Wherever)',
814             comments => 'output of a failed make test goes here...',
815             via => 'CPANPLUS X.Y.Z',
816             );
817             $reporter->send() || die $reporter->errstr();
818              
819             =head1 DESCRIPTION
820              
821             Test::Reporter reports the test results of any given distribution to the CPAN
822             Testers project. Test::Reporter has wide support for various perl5's and
823             platforms.
824              
825             CPAN Testers no longer receives test reports by email, but reports still
826             resemble an email message. This module has numerous legacy "features"
827             left over from the days of email transport.
828              
829             =head2 Transport mechanism
830              
831             The choice of transport is set with the C argument. CPAN Testers
832             should usually install L and use
833             'Metabase' as the C. See that module for necessary transport
834             arguments. Advanced testers may wish to test on a machine different from the
835             one used to send reports. Consult the L
836             Wiki|http://wiki.cpantesters.org/> for examples using other transport classes.
837              
838             The legacy email-based transports have been split out into a separate
839             L distribution and methods solely
840             related to email have been deprecated.
841              
842             =head1 ATTRIBUTES
843              
844             =head2 Required attributes
845              
846             =over
847              
848             =item * B
849              
850             Gets or sets the name of the distribution you're working on, for example
851             Foo-Bar-0.01. There are no restrictions on what can be put here.
852              
853             =item * B
854              
855             Gets or sets the e-mail address of the individual submitting
856             the test report, i.e. "John Doe ".
857              
858             =item * B
859              
860             Gets or sets the success or failure of the distributions's 'make test'
861             result. This must be one of:
862              
863             grade meaning
864             ----- -------
865             pass all tests passed
866             fail one or more tests failed
867             na distribution will not work on this platform
868             unknown tests did not exist or could not be run
869              
870             =back
871              
872             =head2 Transport attributes
873              
874             =over
875              
876             =item * B
877              
878             Gets or sets the transport type. The transport type argument is
879             refers to a 'Test::Reporter::Transport' subclass. The default is 'Null',
880             which uses the L class and does
881             nothing when C is called.
882              
883             You can add additional arguments after the transport
884             selection. These will be passed to the constructor of the lower-level
885             transport. See C.
886              
887             $reporter->transport(
888             'File', '/tmp'
889             );
890              
891             This is not designed to be an extensible platform upon which to build
892             transport plugins. That functionality is planned for the next-generation
893             release of Test::Reporter, which will reside in the CPAN::Testers namespace.
894              
895             =item * B
896              
897             Optional. Gets or sets transport arguments that will used in the constructor
898             for the selected transport, as appropriate.
899              
900             =back
901              
902             =head2 Optional attributes
903              
904             =over
905              
906             =item * B
907              
908             Gets or sets the comments on the test report. This is most
909             commonly used for distributions that did not pass a 'make test'.
910              
911             =item * B
912              
913             Gets or sets the value that will turn debugging on or off.
914             Debug messages are sent to STDERR. 1 for on, 0 for off. Debugging
915             generates very verbose output and is useful mainly for finding bugs
916             in Test::Reporter itself.
917              
918             =item * B
919              
920             Defaults to the current working directory. This method specifies
921             the directory that write() writes test report files to.
922              
923             =item * B
924              
925             Gets or sets the timeout value for the submission of test
926             reports. Default is 120 seconds.
927              
928             =item * B
929              
930             Gets or sets the value that will be appended to
931             X-Reported-Via, generally this is useful for distributions that use
932             Test::Reporter to report test results. This would be something
933             like "CPANPLUS 0.036".
934              
935             =back
936              
937             =head2 Deprecated attributes
938              
939             CPAN Testers no longer uses email for submitting reports. These attributes
940             are deprecated.
941              
942             =over
943              
944             =item * B
945              
946             =item * B
947              
948             =item * B
949              
950             =back
951              
952             =head1 METHODS
953              
954             =over
955              
956             =item * B
957              
958             This constructor returns a Test::Reporter object.
959              
960             =item * B
961              
962             Returns a hashref containing _archname, _osvers, and _myconfig based upon the
963             perl that you are using. Alternatively, you may supply a different perl (path
964             to the binary) as an argument, in which case the supplied perl will be used as
965             the basis of the above data.
966              
967             =item * B
968              
969             Returns the subject line of a report, i.e.
970             "PASS Mail-Freshmeat-1.20 Darwin 6.0". 'grade' and 'distribution' must
971             first be specified before calling this method.
972              
973             =item * B
974              
975             Returns the actual content of a report, i.e.
976             "This distribution has been tested as part of the cpan-testers...".
977             'comments' must first be specified before calling this method, if you have
978             comments to make and expect them to be included in the report.
979              
980             =item * B
981              
982             Sends the test report to cpan-testers@perl.org via the defined C
983             mechanism. You must check errstr() on a send() in order to be guaranteed
984             delivery.
985              
986             =item * B
987              
988             Allows one to interactively edit the comments within a text
989             editor. comments() doesn't have to be first specified, but it will work
990             properly if it was. Accepts an optional hash of arguments:
991              
992             =over
993              
994             =item * B
995              
996             Optional. Allows one to specify the suffix ("extension") of the temp
997             file used by B. Defaults to '.txt'.
998              
999             =back
1000              
1001             =item * B
1002              
1003             Returns an error message describing why something failed. You must check
1004             errstr() on a send() in order to be guaranteed delivery.
1005              
1006             =item * B
1007              
1008             These methods are used in situations where you wish to save reports locally
1009             rather than transmitting them to CPAN Testers immediately. You use write() on
1010             the machine that you are testing from, transfer the written test reports from
1011             the testing machine to the sending machine, and use read() on the machine that
1012             you actually want to submit the reports from. write() will write a file in an
1013             internal format that contains 'From', 'Subject', and the content of the report.
1014             The filename will be represented as:
1015             grade.distribution.archname.osvers.seconds_since_epoch.pid.rpt. write() uses
1016             the value of dir() if it was specified, else the cwd.
1017              
1018             On the machine you are testing from:
1019              
1020             my $reporter = Test::Reporter->new
1021             (
1022             grade => 'pass',
1023             distribution => 'Test-Reporter-1.16',
1024             )->write();
1025              
1026             On the machine you are submitting from:
1027              
1028             # wrap in an opendir if you've a lot to submit
1029             my $reporter;
1030             $reporter = Test::Reporter->new()->read(
1031             'pass.Test-Reporter-1.16.i686-linux.2.2.16.1046685296.14961.rpt'
1032             )->send() || die $reporter->errstr();
1033              
1034             write() also accepts an optional filehandle argument:
1035              
1036             my $fh; open $fh, '>-'; # create a STDOUT filehandle object
1037             $reporter->write($fh); # prints the report to STDOUT
1038              
1039             =back
1040              
1041             =head2 Deprecated methods
1042              
1043             =over
1044              
1045             =item * B
1046              
1047             =back
1048              
1049             =head1 CAVEATS
1050              
1051             If you experience a long delay sending reports with Test::Reporter, you may be
1052             experiencing a wait as Test::Reporter attempts to determine your email
1053             address. Always use the C parameter to set your email address
1054             explicitly.
1055              
1056             =head1 SEE ALSO
1057              
1058             For more about CPAN Testers:
1059              
1060             =over 4
1061              
1062             =item *
1063              
1064             L
1065              
1066             =item *
1067              
1068             L
1069              
1070             =back
1071              
1072             =for :stopwords cpan testmatrix url annocpan anno bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan
1073              
1074             =head1 SUPPORT
1075              
1076             =head2 Bugs / Feature Requests
1077              
1078             Please report any bugs or feature requests through the issue tracker
1079             at L.
1080             You will be notified automatically of any progress on your issue.
1081              
1082             =head2 Source Code
1083              
1084             This is open source software. The code repository is available for
1085             public review and contribution under the terms of the license.
1086              
1087             L
1088              
1089             git clone https://github.com/cpan-testers/Test-Reporter.git
1090              
1091             =head1 AUTHORS
1092              
1093             =over 4
1094              
1095             =item *
1096              
1097             Adam J. Foxson
1098              
1099             =item *
1100              
1101             David Golden
1102              
1103             =item *
1104              
1105             Kirrily "Skud" Robert
1106              
1107             =item *
1108              
1109             Ricardo Signes
1110              
1111             =item *
1112              
1113             Richard Soderberg
1114              
1115             =item *
1116              
1117             Kurt Starsinic
1118              
1119             =back
1120              
1121             =head1 CONTRIBUTORS
1122              
1123             =over 4
1124              
1125             =item *
1126              
1127             Andreas Koenig
1128              
1129             =item *
1130              
1131             Tatsuhiko Miyagawa
1132              
1133             =item *
1134              
1135             Vincent Pit
1136              
1137             =back
1138              
1139             =head1 COPYRIGHT AND LICENSE
1140              
1141             This software is copyright (c) 2013 by Authors and Contributors.
1142              
1143             This is free software; you can redistribute it and/or modify it under
1144             the same terms as the Perl 5 programming language system itself.
1145              
1146             =cut
1147              
1148             __END__