File Coverage

blib/lib/Test/Run/Core.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package Test::Run::Core;
2              
3 8     8   11123 use strict;
  8         24  
  8         279  
4 8     8   44 use warnings;
  8         14  
  8         208  
5              
6 8     8   10197 use Moose;
  0            
  0            
7              
8             extends('Test::Run::Base::PlugHelpers');
9              
10              
11             use vars qw($VERSION);
12              
13             use MRO::Compat;
14              
15             use List::MoreUtils ();
16              
17             use Fatal qw(opendir);
18              
19             use Time::HiRes ();
20             use List::Util ();
21              
22             use File::Spec;
23              
24             use Test::Run::Assert;
25             use Test::Run::Obj::Error;
26             use Test::Run::Straps;
27             use Test::Run::Obj::IntOrUnknown;
28              
29             =head1 NAME
30              
31             Test::Run::Core - Base class to run standard TAP scripts.
32              
33             =head1 VERSION
34              
35             Version 0.0302
36              
37             =cut
38              
39             $VERSION = '0.0302';
40              
41             $ENV{HARNESS_ACTIVE} = 1;
42             $ENV{HARNESS_NG_VERSION} = $VERSION;
43              
44             END
45             {
46             # For VMS.
47             delete $ENV{HARNESS_ACTIVE};
48             delete $ENV{HARNESS_NG_VERSION};
49             }
50              
51             has "_bonusmsg" => (is => "rw", isa => "Str");
52             has "dir_files" => (is => "rw", isa => "ArrayRef", lazy => 1,
53             default => sub { [] },
54             );
55             has "_new_dir_files" => (is => "rw", isa => "Maybe[ArrayRef]");
56             has "failed_tests" => (is => "rw", isa => "HashRef");
57             has "format_columns" => (is => "rw", isa => "Num");
58             has "last_test_elapsed" => (is => "rw", isa => "Str");
59             has "last_test_obj" => (is => "rw", isa => "Test::Run::Obj::TestObj");
60             has "last_test_results" => (is => "rw", isa => "Test::Run::Straps::StrapsTotalsObj");
61             has "list_len" => (is => "rw", isa => "Num", default => 0);
62             has "max_namelen" => (is => "rw", isa => "Num");
63              
64             # I don't know for sure what output is. It is Test::Run::Output in
65             # Test::Run::Plugin::CmdLine::Output but could be different elsewhere.
66             has "output" => (is => "rw", isa => "Ref");
67             has "_start_time" => (is => "rw", isa => "Num");
68             has "Strap" => (is => "rw", isa => "Test::Run::Straps",
69             lazy => 1, builder => "_get_new_strap"
70             );
71             has "tot" => (is => "rw", isa => "Test::Run::Obj::TotObj");
72             has "width" => (is => "rw", isa => "Num");
73              
74             # Private Simple Params of _get_private_simple_params
75             has "Columns" => (is => "rw", isa => "Num", default => "80");
76             has "Debug" => (is => "rw", isa => "Bool");
77             has "Leaked_Dir" => (is => "rw", isa => "Str");
78             has "NoTty" => (is => "rw", isa => "Bool");
79             has "Switches" => (is => "rw", isa => "Maybe[Str]", default => "-w",);
80             has "Switches_Env" => (is => "rw", isa => "Maybe[Str]");
81             has "test_files" => (is => "rw", isa => "ArrayRef");
82             has "test_files_data" => (is => "rw", isa => "HashRef",
83             default => sub { +{} },
84             );
85             has "Test_Interpreter" => (is => "rw", isa => "Maybe[Str]");
86             has "Timer" => (is => "rw", isa => "Bool");
87             has "Verbose" => (is => "rw", isa => "Bool");
88              
89             sub _get_new_strap
90             {
91             my $self = shift;
92              
93             return $self->create_pluggable_helper_obj(
94             {
95             id => "straps",
96             args => {},
97             }
98             );
99             }
100              
101             =head2 BUILD
102              
103             For Moose.
104              
105             =cut
106              
107             sub BUILD
108             {
109             my $self = shift;
110              
111             $self->register_pluggable_helper(
112             {
113             id => "straps",
114             base => "Test::Run::Straps",
115             collect_plugins_method => "private_straps_plugins",
116             },
117             );
118              
119             $self->register_pluggable_helper(
120             {
121             id => "failed",
122             base => "Test::Run::Obj::FailedObj",
123             collect_plugins_method => "private_failed_obj_plugins",
124             },
125             );
126              
127             $self->register_pluggable_helper(
128             {
129             id => "test",
130             base => "Test::Run::Obj::TestObj",
131             collect_plugins_method => "private_test_obj_plugins",
132             },
133             );
134              
135             $self->register_pluggable_helper(
136             {
137             id => "tot",
138             base => "Test::Run::Obj::TotObj",
139             collect_plugins_method => "private_tot_obj_plugins",
140             },
141             );
142              
143             $self->register_pluggable_helper(
144             {
145             id => "canon_failed",
146             base => "Test::Run::Obj::CanonFailedObj",
147             collect_plugins_method => "private_canon_failed_obj_plugins",
148             },
149             );
150              
151             $self->_register_obj_formatter(
152             {
153             name => "fail_other_except",
154             format => "Failed %(_get_fail_test_scripts_string)s%(_get_fail_tests_good_percent_string)s.%(_get_sub_percent_msg)s\n"
155             },
156             );
157              
158             return 0;
159             }
160              
161             =head2 $self->helpers_base_namespace()
162              
163             See L<Test::Run::Base::PlugHelpers>.
164              
165             =cut
166              
167             sub helpers_base_namespace
168             {
169             my $self = shift;
170              
171             return "Test::Run::Core::__HelperObjects";
172             }
173              
174             =head2 Object Parameters
175              
176             These parameters are accessors. They can be set at object creation by passing
177             their name along with a value on the constructor (along with the compulsory
178             C<'test_files'> argument):
179              
180             my $tester = Test::Run::Obj->new(
181             {
182             'test_files' => \@mytests,
183             'Verbose' => 1,
184             }
185             );
186              
187             Alternatively, before C<runtests()> is called, they can be set by passing a
188             value to their accessor:
189              
190             $tester->Verbose(1);
191              
192             =over 4
193              
194             =item C<$self-E<gt>Verbose()>
195              
196             The object variable C<$self-E<gt>Verbose()> can be used to let C<runtests()>
197             display the standard output of the script without altering the behavior
198             otherwise. The F<runprove> utility's C<-v> flag will set this.
199              
200             =item C<$self-E<gt>Leaked_Dir()>
201              
202             When set to the name of a directory, C<$tester> will check after each
203             test whether new files appeared in that directory, and report them as
204              
205             LEAKED FILES: scr.tmp 0 my.db
206              
207             If relative, directory name is with respect to the current directory at
208             the moment C<$tester-E<gt>runtests()> was called. Putting the absolute path
209             into C<Leaked_Dir> will give more predictable results.
210              
211             =item C<$self-E<gt>Debug()>
212              
213             If C<$self-E<gt>Debug()> is true, Test::Run will print debugging information
214             about itself as it runs the tests. This is different from
215             C<$self-E<gt>Verbose()>, which prints the output from the test being run.
216              
217             =item C<$self-E<gt>Columns()>
218              
219             This value will be used for the width of the terminal. If it is not
220             set then it will default to 80.
221              
222             =item C<$self-E<gt>Timer()>
223              
224             If set to true, and C<Time::HiRes> is available, print elapsed seconds
225             after each test file.
226              
227             =item C<$self-E<gt>NoTty()>
228              
229             When set to a true value, forces it to behave as though STDOUT were
230             not a console. You may need to set this if you don't want harness to
231             output more frequent progress messages using carriage returns. Some
232             consoles may not handle carriage returns properly (which results in a
233             somewhat messy output).
234              
235             =item C<$self-E<gt>Test_Interprter()>
236              
237             Usually your tests will be run by C<$^X>, the currently-executing Perl.
238             However, you may want to have it run by a different executable, such as
239             a threading perl, or a different version.
240              
241             =item C<$self-E<gt>Switches()> and C<$self-E<gt>Switches_Env()>
242              
243             These two values will be prepended to the switches used to invoke perl on
244             each test. For example, setting one of them to C<-W> will
245             run all tests with all warnings enabled.
246              
247             The difference between them is that C<Switches_Env()> is expected to be
248             filled in by the environment and C<Switches()> from other sources (like the
249             programmer).
250              
251             =back
252              
253             =head2 METHODS
254              
255             Test::Run currently has only one interface method.
256              
257             =head2 $tester->runtests()
258              
259             my $all_ok = $tester->runtests()
260              
261             Runs the tests, see if they are OK. Returns true if they are OK, or
262             throw an exception otherwise.
263              
264             =cut
265              
266             =head2 $self->_report_leaked_files({leaked_files => [@files]})
267              
268             [This is a method that needs to be over-rided.]
269              
270             Should report (or ignore) the files that were leaked in the directories
271             that were specifies as leaking directories.
272              
273             =cut
274              
275             =head2 $self->_report_failed_with_results_seen({%args})
276              
277             [This is a method that needs to be over-rided.]
278              
279             Should report (or ignore) the failed tests in the test file.
280              
281             Arguments are:
282              
283             =over 4
284              
285             =item * test_struct
286              
287             The test struct as returned by straps.
288              
289             =item * filename
290              
291             The filename
292              
293             =item * estatus
294              
295             Exit status.
296              
297             =item * wstatus
298              
299             Wait status.
300              
301             =item * results
302              
303             The results of the test.
304              
305             =back
306              
307             =cut
308              
309             =head2 $self->_recheck_dir_files()
310              
311             Called to recheck that the dir files is OK.
312              
313             =cut
314              
315             sub _recheck_dir_files
316             {
317             my $self = shift;
318              
319             if (defined($self->Leaked_Dir()))
320             {
321             return $self->_real_recheck_dir_files();
322             }
323             }
324              
325             sub _calc_leaked_files_since_last_update
326             {
327             my $self = shift;
328              
329             my %found;
330              
331             @found{@{$self->_new_dir_files()}} = (1) x @{$self->_new_dir_files()};
332              
333             delete(@found{@{$self->dir_files()}});
334              
335             return [sort keys(%found)];
336             }
337              
338             sub _real_recheck_dir_files
339             {
340             my $self = shift;
341              
342             $self->_new_dir_files($self->_get_dir_files());
343              
344             $self->_report_leaked_files(
345             {
346             leaked_files => $self->_calc_leaked_files_since_last_update()
347             }
348             );
349             $self->_update_dir_files();
350             }
351              
352             sub _update_dir_files
353             {
354             my $self = shift;
355              
356             $self->dir_files($self->_new_dir_files());
357              
358             # Reset it to prevent dangerous behaviour.
359             $self->_new_dir_files(undef);
360              
361             return;
362             }
363              
364             sub _glob_dir
365             {
366             my ($self, $dirname) = @_;
367              
368             my $dir;
369             opendir $dir, $dirname;
370             my @contents = readdir($dir);
371             closedir($dir);
372              
373             return [File::Spec->no_upwards(@contents)];
374             }
375              
376             sub _get_num_tests_files
377             {
378             my $self = shift;
379              
380             return scalar(@{$self->test_files()});
381             }
382              
383             sub _get_tot_counter_tests
384             {
385             my $self = shift;
386              
387             return [ tests => $self->_get_num_tests_files() ];
388             }
389              
390             sub _init_tot_obj_instance
391             {
392             my $self = shift;
393             return $self->create_pluggable_helper_obj(
394             {
395             id => "tot",
396             args => { @{$self->_get_tot_counter_tests()} },
397             }
398             );
399             }
400              
401             sub _init_tot
402             {
403             my $self = shift;
404             $self->tot(
405             $self->_init_tot_obj_instance()
406             );
407             }
408              
409             sub _tot_inc
410             {
411             my ($self, $field) = @_;
412              
413             $self->tot()->inc($field);
414             }
415              
416             sub _tot_add_results
417             {
418             my ($self, $results) = @_;
419              
420             return $self->tot->add_results($results);
421             }
422              
423             sub _create_failed_obj_instance
424             {
425             my $self = shift;
426             my $args = shift;
427             return $self->create_pluggable_helper_obj(
428             {
429             id => "failed",
430             args => $args,
431             }
432             );
433             }
434              
435             sub _create_test_obj_instance
436             {
437             my ($self, $args) = @_;
438             return $self->create_pluggable_helper_obj(
439             {
440             id => "test",
441             args => $args,
442             }
443             );
444             }
445              
446             sub _is_failed_and_max
447             {
448             my $self = shift;
449              
450             return $self->last_test_obj->is_failed_and_max();
451             }
452              
453             sub _strap_test_handler
454             {
455             my ($self, $args) = @_;
456              
457             $args->{totals}->update_based_on_last_detail();
458              
459             $self->_report_test_progress($args);
460              
461             return;
462             }
463              
464             sub _strap_header_handler
465             {
466             my ($self, $args) = @_;
467              
468             my $totals = $args->{totals};
469              
470             if ($self->Strap()->_seen_header())
471             {
472             warn "Test header seen more than once!\n";
473             }
474              
475             $self->Strap()->_inc_seen_header();
476              
477             if ($totals->in_the_middle())
478             {
479             warn "1..M can only appear at the beginning or end of tests\n";
480             }
481              
482             return;
483             }
484              
485              
486             sub _tap_event_strap_callback
487             {
488             my ($self, $args) = @_;
489              
490             $self->_report_tap_event($args);
491              
492             return $self->_tap_event_handle_strap($args);
493             }
494              
495             sub _tap_event__calc_conds
496             {
497             my $self = shift;
498              
499             return
500             [
501             { cond => "is_plan", handler => "_strap_header_handler", },
502             { cond => "is_bailout", handler => "_strap_bailout_handler", },
503             { cond => "is_test", handler => "_strap_test_handler"},
504             ];
505             }
506              
507             sub _tap_event_handle_strap
508             {
509             my ($self, $args) = @_;
510             my $event = $args->{event};
511              
512             foreach my $c (@{$self->_tap_event__calc_conds()})
513             {
514             my $cond = $c->{cond};
515             my $handler = $c->{handler};
516              
517             if ($event->$cond())
518             {
519             return $self->$handler($args);
520             }
521             }
522             return;
523             }
524              
525             =begin _private
526              
527             =over 4
528              
529             =item B<_all_ok>
530              
531             my $ok = $self->_all_ok();
532              
533             Tells you if the current test run is OK or not.
534              
535             =cut
536              
537             sub _all_ok
538             {
539             my $self = shift;
540             return $self->tot->all_ok();
541             }
542              
543             =back
544              
545             =cut
546              
547             sub _get_dir_files
548             {
549             my $self = shift;
550              
551             return $self->_glob_dir($self->Leaked_Dir());
552             }
553              
554             sub _calc_strap_callback_map
555             {
556             return
557             {
558             "tap_event" => "_tap_event_strap_callback",
559             "report_start_env" => "_report_script_start_environment",
560             "could_not_run_script" => "_report_could_not_run_script",
561             "test_file_opening_error" => "_handle_test_file_opening_error",
562             "test_file_closing_error" => "_handle_test_file_closing_error",
563             };
564             }
565              
566             sub _strap_callback
567             {
568             my ($self, $args) = @_;
569              
570             my $type = $args->{type};
571             my $cb = $self->_calc_strap_callback_map()->{$type};
572              
573             return $self->$cb($args);
574             }
575              
576             sub _inc_bad
577             {
578             my $self = shift;
579              
580             $self->_tot_inc('bad');
581              
582             return;
583             }
584              
585             sub _ser_failed_results
586             {
587             my $self = shift;
588              
589             return $self->_canonfailed()->get_ser_results();
590             }
591              
592             sub _get_current_time
593             {
594             my $self = shift;
595              
596             return Time::HiRes::time();
597             }
598              
599             sub _set_start_time
600             {
601             my $self = shift;
602              
603             if ($self->Timer())
604             {
605             $self->_start_time($self->_get_current_time());
606             }
607             }
608              
609             sub _get_failed_with_results_seen_msg
610             {
611             my $self = shift;
612              
613             return
614             $self->_is_failed_and_max()
615             ? $self->_get_failed_and_max_msg()
616             : $self->_get_dont_know_which_tests_failed_msg()
617             ;
618             }
619              
620             sub _get_dont_know_which_tests_failed_msg
621             {
622             my $self = shift;
623              
624             return $self->last_test_obj->_get_dont_know_which_tests_failed_msg();
625             }
626              
627             sub _get_elapsed
628             {
629             my $self = shift;
630              
631             if ($self->Timer())
632             {
633             return sprintf(" %8.3fs",
634             $self->_get_current_time() - $self->_start_time()
635             );
636             }
637             else
638             {
639             return "";
640             }
641             }
642              
643             sub _set_last_test_elapsed
644             {
645             my $self = shift;
646              
647             $self->last_test_elapsed($self->_get_elapsed());
648             }
649              
650             sub _get_copied_strap_fields
651             {
652             return [qw(Debug Test_Interpreter Switches Switches_Env)];
653             }
654              
655             sub _init_strap
656             {
657             my ($self, $args) = @_;
658              
659             $self->Strap()->copy_from($self, $self->_get_copied_strap_fields());
660             }
661              
662             sub _get_sub_percent_msg
663             {
664             my $self = shift;
665              
666             return $self->tot->get_sub_percent_msg();
667             }
668              
669             sub _handle_passing_test
670             {
671             my $self = shift;
672              
673             $self->_process_passing_test();
674             $self->_tot_inc('good');
675             }
676              
677             sub _does_test_have_some_oks
678             {
679             my $self = shift;
680              
681             return $self->last_test_obj->max();
682             }
683              
684             sub _process_passing_test
685             {
686             my $self = shift;
687              
688             if ($self->_does_test_have_some_oks())
689             {
690             $self->_process_test_with_some_oks();
691             }
692             else
693             {
694             $self->_process_all_skipped_test();
695             }
696             }
697              
698             sub _process_test_with_some_oks
699             {
700             my $self = shift;
701              
702             if ($self->last_test_obj->skipped_or_bonus())
703             {
704             return $self->_process_skipped_test();
705             }
706             else
707             {
708             return $self->_process_all_ok_test();
709             }
710             }
711              
712             sub _process_all_ok_test
713             {
714             my ($self) = @_;
715             return $self->_report_all_ok_test();
716             }
717              
718             sub _process_all_skipped_test
719             {
720             my $self = shift;
721              
722             $self->_report_all_skipped_test();
723             $self->_tot_inc('skipped');
724              
725             return;
726             }
727              
728             sub _fail_other_get_script_names
729             {
730             my $self = shift;
731              
732             return [ sort { $a cmp $b } (keys(%{$self->failed_tests()})) ];
733             }
734              
735             sub _fail_other_print_all_tests
736             {
737             my $self = shift;
738              
739             for my $script (@{$self->_fail_other_get_script_names()})
740             {
741             $self->_fail_other_report_test($script);
742             }
743             }
744              
745             sub _fail_other_throw_exception
746             {
747             my $self = shift;
748              
749             die Test::Run::Obj::Error::TestsFail::Other->new(
750             {text => $self->_get_fail_other_exception_text(),},
751             );
752             }
753              
754             sub _process_skipped_test
755             {
756             my ($self) = @_;
757              
758             return $self->_report_skipped_test();
759             }
760              
761              
762              
763             sub _time_single_test
764             {
765             my ($self, $args) = @_;
766              
767             $self->_set_start_time($args);
768              
769             $self->_init_strap($args);
770              
771             $self->Strap->callback(sub { return $self->_strap_callback(@_); });
772              
773             # We trap exceptions so we can nullify the callback to avoid memory
774             # leaks.
775             my $results;
776             eval
777             {
778             if (! ($results = $self->Strap()->analyze_file($args->{test_file})))
779             {
780             do
781             {
782             warn $self->Strap()->error(), "\n";
783             next;
784             }
785             }
786             };
787              
788             # To avoid circular references
789             $self->Strap->callback(undef);
790              
791             if ($@ ne "")
792             {
793             die $@;
794             }
795             $self->_set_last_test_elapsed($args);
796              
797             $self->last_test_results($results);
798              
799             return;
800             }
801              
802             sub _fail_no_tests_output
803             {
804             my $self = shift;
805             die Test::Run::Obj::Error::TestsFail::NoOutput->new(
806             {text => $self->_get_fail_no_tests_output_text(),},
807             );
808             }
809              
810             sub _failed_canon
811             {
812             my $self = shift;
813              
814             return $self->_canonfailed()->canon();
815             }
816              
817             sub _get_failed_and_max_msg
818             {
819             my $self = shift;
820              
821             return $self->last_test_obj->ml()
822             . $self->_ser_failed_results();
823             }
824              
825             sub _canonfailed
826             {
827             my $self = shift;
828              
829             my $canon_obj = $self->_canonfailed_get_canon();
830              
831             $canon_obj->add_Failed_and_skipped($self->last_test_obj);
832              
833             return $canon_obj;
834             # Originally returning get_ser_results, canon
835             }
836              
837              
838             sub _filter_failed
839             {
840             my ($self, $failed_ref) = @_;
841             return [ List::MoreUtils::uniq(sort { $a <=> $b } @$failed_ref) ];
842             }
843              
844             sub _canonfailed_get_failed
845             {
846             my $self = shift;
847              
848             return $self->_filter_failed($self->_get_failed_list());
849             }
850              
851             =head2 $self->_calc_test_struct_ml($results)
852              
853             Calculates the ml(). (See L<Test::Run::Output>) for the test.
854              
855             =cut
856              
857             sub _calc_test_struct_ml
858             {
859             my $self = shift;
860              
861             return "";
862             }
863              
864             sub _calc_last_test_obj_params
865             {
866             my $self = shift;
867              
868             my $results = $self->last_test_results;
869              
870             return
871             [
872             (
873             map { $_ => $results->$_(), }
874             (qw(bonus max ok skip_reason skip_all))
875             ),
876             skipped => $results->skip(),
877             'next' => $self->Strap->next_test_num(),
878             failed => $results->_get_failed_details(),
879             ml => $self->_calc_test_struct_ml($results),
880             ];
881             }
882              
883             sub _get_fail_no_tests_run_text
884             {
885             return "FAILED--no tests were run for some reason.\n"
886             }
887              
888             sub _get_fail_no_tests_output_text
889             {
890             my $self = shift;
891              
892             return $self->tot->_get_fail_no_tests_output_text();
893             }
894              
895             sub _get_success_msg
896             {
897             my $self = shift;
898             return "All tests successful" . $self->_get_bonusmsg() . ".";
899             }
900              
901             sub _fail_no_tests_run
902             {
903             my $self = shift;
904             die Test::Run::Obj::Error::TestsFail::NoTestsRun->new(
905             {text => $self->_get_fail_no_tests_run_text(),},
906             );
907             }
908              
909             sub _calc_test_struct
910             {
911             my $self = shift;
912              
913             my $results = $self->last_test_results;
914              
915             $self->_tot_add_results($results);
916              
917             return $self->last_test_obj(
918             $self->_create_test_obj_instance(
919             {
920             @{$self->_calc_last_test_obj_params()},
921             }
922             )
923             );
924             }
925              
926             sub _get_failed_list
927             {
928             my $self = shift;
929              
930             return $self->last_test_obj->failed;
931             }
932              
933             sub _get_premature_test_dubious_summary
934             {
935             my $self = shift;
936              
937             $self->last_test_obj->add_next_to_failed();
938              
939             $self->_report_premature_test_dubious_summary();
940              
941             return $self->_get_failed_and_max_params();
942             }
943              
944             sub _failed_before_any_test_output
945             {
946             my $self = shift;
947              
948             $self->_report_failed_before_any_test_output();
949              
950             $self->_inc_bad();
951              
952             return $self->_calc_failed_before_any_test_obj();
953             }
954              
955             sub _max_len
956             {
957             my ($self, $array_ref) = @_;
958              
959             return List::Util::max(map { length($_) } @$array_ref);
960             }
961              
962             # TODO : Add _leader_width here.
963              
964              
965             sub _get_fn_fn
966             {
967             my ($self, $fn) = @_;
968              
969             return $fn;
970             }
971              
972             sub _get_fn_ext
973             {
974             my ($self, $fn) = @_;
975              
976             return (($fn =~ /\.(\w+)\z/) ? $1 : "");
977             }
978              
979             sub _get_filename_map_max_len
980             {
981             my ($self, $cb) = @_;
982              
983             return $self->_max_len(
984             [ map { $self->$cb($self->_get_test_file_display_path($_)) }
985             @{$self->test_files()}
986             ]
987             );
988             }
989              
990             sub _get_max_ext_len
991             {
992             my $self = shift;
993              
994             return $self->_get_filename_map_max_len("_get_fn_ext");
995             }
996              
997             sub _get_max_filename_len
998             {
999             my $self = shift;
1000              
1001             return $self->_get_filename_map_max_len("_get_fn_fn");
1002             }
1003              
1004             =head2 $self->_leader_width()
1005              
1006             Calculates how long the leader should be based on the length of the
1007             maximal test filename.
1008              
1009             =cut
1010              
1011             sub _leader_width
1012             {
1013             my $self = shift;
1014              
1015             return $self->_get_max_filename_len() + 3 - $self->_get_max_ext_len();
1016             }
1017              
1018             sub _strap_bailout_handler
1019             {
1020             my ($self, $args) = @_;
1021              
1022             die Test::Run::Obj::Error::TestsFail::Bailout->new(
1023             {
1024             bailout_reason => $self->Strap->bailout_reason(),
1025             text => "FOOBAR",
1026             }
1027             );
1028             }
1029              
1030             sub _calc_failed_before_any_test_obj
1031             {
1032             my $self = shift;
1033              
1034             return $self->_create_failed_obj_instance(
1035             {
1036             (map
1037             { $_ => Test::Run::Obj::IntOrUnknown->create_unknown() }
1038             qw(max failed)
1039             ),
1040             canon => "??",
1041             (map { $_ => "", } qw(estat wstat)),
1042             percent => undef,
1043             name => $self->_get_last_test_filename(),
1044             },
1045             );
1046             }
1047              
1048             sub _show_results
1049             {
1050             my($self) = @_;
1051              
1052             $self->_show_success_or_failure();
1053              
1054             $self->_report_final_stats();
1055             }
1056              
1057             sub _is_last_test_seen
1058             {
1059             return shift->last_test_results->seen;
1060             }
1061              
1062             sub _is_test_passing
1063             {
1064             my $self = shift;
1065              
1066             return $self->last_test_results->passing;
1067             }
1068              
1069             sub _get_failed_and_max_params
1070             {
1071             my $self = shift;
1072              
1073             my $last_test = $self->last_test_obj;
1074              
1075             return
1076             [
1077             canon => $self->_failed_canon(),
1078             failed => Test::Run::Obj::IntOrUnknown->create_int($last_test->num_failed()),
1079             percent => $last_test->calc_percent(),
1080             ];
1081             }
1082              
1083             # The test program exited with a bad exit status.
1084             sub _dubious_return
1085             {
1086             my $self = shift;
1087              
1088             $self->_report_dubious();
1089              
1090             $self->_inc_bad();
1091              
1092             return $self->_calc_dubious_return_ret_value();
1093             }
1094              
1095             sub _get_fail_test_scripts_string
1096             {
1097             my $self = shift;
1098              
1099             return $self->tot->fail_test_scripts_string();
1100             }
1101              
1102             sub _get_undef_tests_params
1103             {
1104             my $self = shift;
1105              
1106             return
1107             [
1108             canon => "??",
1109             failed => Test::Run::Obj::IntOrUnknown->create_unknown(),
1110             percent => undef,
1111             ];
1112             }
1113              
1114             sub _get_fail_tests_good_percent_string
1115             {
1116             my $self = shift;
1117              
1118             return $self->tot->fail_tests_good_percent_string();
1119             }
1120              
1121             sub _get_FWRS_tests_existence_params
1122             {
1123             my ($self) = @_;
1124              
1125             return
1126             [
1127             $self->_is_failed_and_max()
1128             ? (@{$self->_get_failed_and_max_params()})
1129             : (@{$self->_get_undef_tests_params()})
1130             ]
1131             }
1132              
1133             sub _handle_runtests_error_text
1134             {
1135             my $self = shift;
1136             my $args = shift;
1137              
1138             my $text = $args->{'text'};
1139              
1140             die $text;
1141             }
1142              
1143             sub _is_error_object
1144             {
1145             my $self = shift;
1146             my $error = shift;
1147              
1148             return
1149             (
1150             Scalar::Util::blessed($error) &&
1151             $error->isa("Test::Run::Obj::Error::TestsFail")
1152             );
1153             }
1154              
1155             sub _get_runtests_error_text
1156             {
1157             my $self = shift;
1158             my $error = shift;
1159              
1160             return
1161             ($self->_is_error_object($error)
1162             ? $error->stringify()
1163             : $error
1164             );
1165             }
1166              
1167             sub _is_no_tests_run
1168             {
1169             my $self = shift;
1170              
1171             return (! $self->tot->tests());
1172             }
1173              
1174             sub _is_no_tests_output
1175             {
1176             my $self = shift;
1177              
1178             return (! $self->tot->max());
1179             }
1180              
1181             sub _report_success
1182             {
1183             my $self = shift;
1184             $self->_report(
1185             {
1186             'channel' => "success",
1187             'event' => { 'type' => "success", },
1188             }
1189             );
1190              
1191             return;
1192             }
1193              
1194             sub _fail_other_if_bad
1195             {
1196             my $self = shift;
1197              
1198             if ($self->tot->bad)
1199             {
1200             $self->_fail_other_print_bonus_message();
1201             $self->_fail_other_throw_exception();
1202             }
1203              
1204             return;
1205             }
1206              
1207             sub _calc__fail_other__callbacks
1208             {
1209             my $self = shift;
1210              
1211             return [qw(
1212             _create_fmts
1213             _fail_other_print_top
1214             _fail_other_print_all_tests
1215             _fail_other_if_bad
1216             )];
1217             }
1218              
1219             sub _fail_other
1220             {
1221             shift->_run_sequence();
1222              
1223             return;
1224             }
1225              
1226             sub _show_success_or_failure
1227             {
1228             my $self = shift;
1229              
1230             if ($self->_all_ok())
1231             {
1232             return $self->_report_success();
1233             }
1234             elsif ($self->_is_no_tests_run())
1235             {
1236             return $self->_fail_no_tests_run();
1237             }
1238             elsif ($self->_is_no_tests_output())
1239             {
1240             return $self->_fail_no_tests_output();
1241             }
1242             else
1243             {
1244             return $self->_fail_other();
1245             }
1246             }
1247              
1248             sub _handle_runtests_error
1249             {
1250             my $self = shift;
1251             my $args = shift;
1252             my $error = $args->{'error'};
1253              
1254             $self->_handle_runtests_error_text(
1255             {
1256             'text' => $self->_get_runtests_error_text($error),
1257             },
1258             );
1259             }
1260              
1261             sub _get_canonfailed_params
1262             {
1263             my $self = shift;
1264              
1265             return [failed => $self->_canonfailed_get_failed(),];
1266             }
1267              
1268             sub _create_canonfailed_obj_instance
1269             {
1270             my ($self, $args) = @_;
1271              
1272             return $self->create_pluggable_helper_obj(
1273             {
1274             id => "canon_failed",
1275             args => $args,
1276             }
1277             );
1278             }
1279              
1280             sub _canonfailed_get_canon
1281             {
1282             my ($self) = @_;
1283              
1284             return $self->_create_canonfailed_obj_instance(
1285             {
1286             @{$self->_get_canonfailed_params()},
1287             }
1288             );
1289             }
1290              
1291             sub _prepare_for_single_test_run
1292             {
1293             my ($self, $args) = @_;
1294              
1295             $self->_tot_inc('files');
1296              
1297             $self->Strap()->_seen_header(0);
1298              
1299             $self->_report_single_test_file_start($args);
1300              
1301             return;
1302             }
1303              
1304              
1305             sub _calc__run_single_test__callbacks
1306             {
1307             my $self = shift;
1308              
1309             return [qw(
1310             _prepare_for_single_test_run
1311             _time_single_test
1312             _calc_test_struct
1313             _process_test_file_results
1314             _recheck_dir_files
1315             )];
1316             }
1317              
1318             sub _run_single_test
1319             {
1320             my ($self, $args) = @_;
1321              
1322             $self->_run_sequence([$args]);
1323              
1324             return;
1325             }
1326              
1327             sub _list_tests_as_failures
1328             {
1329             my $self = shift;
1330              
1331             return
1332             $self->last_test_obj->list_tests_as_failures(
1333             $self->last_test_results->details()
1334             );
1335             }
1336              
1337             sub _process_test_file_results
1338             {
1339             my ($self) = @_;
1340              
1341             if ($self->_is_test_passing())
1342             {
1343             $self->_handle_passing_test();
1344             }
1345             else
1346             {
1347             $self->_list_tests_as_failures();
1348             $self->_add_to_failed_tests();
1349             }
1350              
1351             return;
1352             }
1353              
1354             sub _check_for_ok
1355             {
1356             my $self = shift;
1357              
1358             assert( ($self->_all_ok() xor keys(%{$self->failed_tests()})),
1359             q{$ok is mutually exclusive with %$failed_tests}
1360             );
1361              
1362             return;
1363              
1364             }
1365              
1366             sub _calc_test_file_data_display_path
1367             {
1368             my ($self, $idx, $test_file) = @_;
1369              
1370             return $test_file;
1371             }
1372              
1373             sub _get_test_file_display_path
1374             {
1375             my ($self, $test_file) = @_;
1376              
1377             return $self->test_files_data()->{$test_file}->{display_path};
1378             }
1379              
1380             sub _calc_test_file_data_struct
1381             {
1382             my ($self, $idx, $test_file) = @_;
1383              
1384             return
1385             {
1386             idx => $idx,
1387             real_path => $test_file,
1388             display_path => $self->_calc_test_file_data_display_path($idx, $test_file),
1389             };
1390             }
1391              
1392             sub _prepare_test_files_data
1393             {
1394             my $self = shift;
1395              
1396             foreach my $idx (0 .. $#{$self->test_files()})
1397             {
1398             my $test_file = $self->test_files()->[$idx];
1399              
1400             $self->test_files_data()->{$test_file} =
1401             $self->_calc_test_file_data_struct($idx, $test_file);
1402             }
1403             }
1404              
1405             sub _calc__real_runtests__callbacks
1406             {
1407             my $self = shift;
1408              
1409             return
1410             [qw(
1411             _run_all_tests
1412             _show_results
1413             _check_for_ok
1414             )];
1415             }
1416              
1417             sub _real_runtests
1418             {
1419             shift->_run_sequence();
1420              
1421             return;
1422             }
1423              
1424             sub runtests
1425             {
1426             my $self = shift;
1427              
1428             local ($\, $,);
1429              
1430             eval { $self->_real_runtests(@_) };
1431              
1432             my $error = $@;
1433              
1434             my $ok = $self->_all_ok();
1435              
1436             if ($error)
1437             {
1438             return $self->_handle_runtests_error(
1439             {
1440             ok => $ok,
1441             error => $error,
1442             }
1443             );
1444             }
1445             else
1446             {
1447             return $ok;
1448             }
1449             }
1450              
1451             sub _get_bonusmsg
1452             {
1453             my $self = shift;
1454              
1455             if (! defined($self->_bonusmsg()))
1456             {
1457             $self->_bonusmsg($self->tot()->get_bonusmsg());
1458             }
1459              
1460             return $self->_bonusmsg();
1461             }
1462              
1463             sub _autoflush_file_handles
1464             {
1465             my $self = shift;
1466              
1467             STDOUT->autoflush(1);
1468             STDERR->autoflush(1);
1469             }
1470              
1471             sub _init_failed_tests
1472             {
1473             my $self = shift;
1474              
1475             $self->failed_tests({});
1476             }
1477              
1478             sub _prepare_run_all_tests
1479             {
1480             my $self = shift;
1481              
1482             $self->_prepare_test_files_data();
1483              
1484             $self->_autoflush_file_handles();
1485              
1486             $self->_init_failed_tests();
1487              
1488             $self->_init_tot();
1489              
1490             $self->_init_dir_files();
1491              
1492             return;
1493             }
1494              
1495             # FWRS == failed_with_results_seen
1496             sub _get_common_FWRS_params
1497             {
1498             my $self = shift;
1499              
1500             return
1501             [
1502             max => Test::Run::Obj::IntOrUnknown->create_int(
1503             $self->last_test_obj->max()
1504             ),
1505             name => $self->_get_last_test_filename(),
1506             estat => "",
1507             wstat => "",
1508             list_len => $self->list_len(),
1509             ];
1510             }
1511              
1512             sub _get_failed_with_results_seen_params
1513             {
1514             my ($self) = @_;
1515              
1516             return
1517             {
1518             @{$self->_get_common_FWRS_params()},
1519             @{$self->_get_FWRS_tests_existence_params()},
1520             }
1521             }
1522              
1523             sub _failed_with_results_seen
1524             {
1525             my $self = shift;
1526              
1527             $self->_inc_bad();
1528              
1529             $self->_report_failed_with_results_seen();
1530              
1531             return
1532             $self->_create_failed_obj_instance(
1533             $self->_get_failed_with_results_seen_params(),
1534             );
1535             }
1536              
1537             sub _get_failed_struct
1538             {
1539             my ($self) = @_;
1540              
1541             if ($self->_get_wstatus())
1542             {
1543             return $self->_dubious_return();
1544             }
1545             elsif($self->_is_last_test_seen())
1546             {
1547             return $self->_failed_with_results_seen();
1548             }
1549             else
1550             {
1551             return $self->_failed_before_any_test_output();
1552             }
1553             }
1554              
1555             sub _add_to_failed_tests
1556             {
1557             my $self = shift;
1558              
1559             $self->failed_tests()->{$self->_get_last_test_filename()} =
1560             $self->_get_failed_struct();
1561              
1562             return;
1563             }
1564              
1565             sub _get_last_test_filename
1566             {
1567             my $self = shift;
1568              
1569             return $self->last_test_results->filename();
1570             }
1571              
1572             sub _init_dir_files
1573             {
1574             my $self = shift;
1575              
1576             if (defined($self->Leaked_Dir()))
1577             {
1578             $self->dir_files($self->_get_dir_files());
1579             }
1580             }
1581              
1582             sub _run_all_tests_loop
1583             {
1584             my $self = shift;
1585              
1586             foreach my $test_file_path (@{$self->test_files()})
1587             {
1588             $self->_run_single_test({ test_file => $test_file_path});
1589             }
1590             }
1591              
1592             sub _run_all_tests__run_loop
1593             {
1594             my $self = shift;
1595              
1596             $self->tot->benchmark_callback(
1597             sub {
1598             $self->width($self->_leader_width());
1599             $self->_run_all_tests_loop();
1600             }
1601             );
1602             }
1603              
1604             sub _finalize_run_all_tests
1605             {
1606             my $self = shift;
1607              
1608             $self->Strap()->_restore_PERL5LIB();
1609             }
1610              
1611             sub _calc__run_all_tests__callbacks
1612             {
1613             my $self = shift;
1614              
1615             return
1616             [qw(
1617             _prepare_run_all_tests
1618             _run_all_tests__run_loop
1619             _finalize_run_all_tests
1620             )];
1621             }
1622              
1623             sub _run_all_tests {
1624             shift->_run_sequence();
1625              
1626             return;
1627             }
1628              
1629              
1630             sub _get_dubious_summary_all_subtests_successful
1631             {
1632             my ($self, $args) = @_;
1633              
1634             $self->_report_dubious_summary_all_subtests_successful();
1635              
1636             return
1637             [
1638             failed => Test::Run::Obj::IntOrUnknown->zero(),
1639             percent => 0,
1640             canon => "??",
1641             ];
1642             }
1643              
1644             sub _get_no_tests_summary
1645             {
1646             my ($self, $args) = @_;
1647              
1648             return
1649             [
1650             failed => Test::Run::Obj::IntOrUnknown->create_unknown(),
1651             canon => "??",
1652             percent => undef(),
1653             ];
1654             }
1655              
1656             sub _get_dubious_summary
1657             {
1658             my ($self, $args) = @_;
1659              
1660             my $method = $self->last_test_obj->get_dubious_summary_main_obj_method();
1661              
1662             return $self->$method($args);
1663             }
1664              
1665             sub _get_skipped_bonusmsg
1666             {
1667             my $self = shift;
1668              
1669             return $self->tot->_get_skipped_bonusmsg();
1670             }
1671              
1672             sub _get_wstatus
1673             {
1674             my $self = shift;
1675              
1676             return $self->last_test_results->wait;
1677             }
1678              
1679             sub _get_estatus
1680             {
1681             my $self = shift;
1682              
1683             return $self->last_test_results->exit;
1684             }
1685              
1686             sub _get_format_failed_str
1687             {
1688             my $self = shift;
1689              
1690             return "Failed Test";
1691             }
1692              
1693             sub _get_format_failed_str_len
1694             {
1695             my $self = shift;
1696              
1697             return length($self->_get_format_failed_str());
1698             }
1699              
1700             sub _get_num_columns
1701             {
1702             my $self = shift;
1703              
1704             # Some shells don't handle a full line of text well so we increment
1705             # 1.
1706             return ($self->Columns() - 1);
1707             }
1708              
1709             # Find the maximal name length among the failed_tests().
1710             sub _calc_initial_max_namelen
1711             {
1712             my $self = shift;
1713              
1714             my $max = $self->_get_format_failed_str_len();
1715              
1716             while (my ($k, $v) = each(%{$self->failed_tests()}))
1717             {
1718             my $l = length($v->{name});
1719              
1720             if ($l > $max)
1721             {
1722             $max = $l;
1723             }
1724             }
1725              
1726             $self->max_namelen($max);
1727              
1728             return;
1729             }
1730              
1731             sub _calc_len_subtraction
1732             {
1733             my ($self, $field) = @_;
1734              
1735             return $self->format_columns()
1736             - $self->_get_fmt_mid_str_len()
1737             - $self->$field()
1738             ;
1739             }
1740              
1741             sub _calc_initial_list_len
1742             {
1743             my $self = shift;
1744              
1745             $self->format_columns($self->_get_num_columns());
1746              
1747             $self->list_len(
1748             $self->_calc_len_subtraction("max_namelen")
1749             );
1750              
1751             return;
1752             }
1753              
1754             sub _calc_updated_lens
1755             {
1756             my $self = shift;
1757              
1758             $self->list_len($self->_get_fmt_list_str_len);
1759             $self->max_namelen($self->_calc_len_subtraction("list_len"));
1760             }
1761              
1762             sub _calc_more_updated_lens
1763             {
1764             my $self = shift;
1765              
1766             $self->max_namelen($self->_get_format_failed_str_len());
1767              
1768             $self->format_columns(
1769             $self->max_namelen()
1770             + $self->_get_fmt_mid_str_len()
1771             + $self->list_len()
1772             );
1773             }
1774              
1775             sub _calc_fmt_list_len
1776             {
1777             my $self = shift;
1778              
1779             $self->_calc_initial_list_len();
1780              
1781             if ($self->list_len() < $self->_get_fmt_list_str_len()) {
1782             $self->_calc_updated_lens();
1783             if ($self->max_namelen() < $self->_get_format_failed_str_len())
1784             {
1785             $self->_calc_more_updated_lens();
1786             }
1787             }
1788              
1789             return;
1790             }
1791              
1792             sub _calc_format_widths
1793             {
1794             my $self = shift;
1795              
1796             $self->_calc_initial_max_namelen();
1797              
1798             $self->_calc_fmt_list_len();
1799              
1800             return;
1801             }
1802              
1803             sub _get_format_middle_str
1804             {
1805             my $self = shift;
1806              
1807             return " Stat Wstat Total Fail Failed ";
1808             }
1809              
1810             sub _get_fmt_mid_str_len
1811             {
1812             my $self = shift;
1813              
1814             return length($self->_get_format_middle_str());
1815             }
1816              
1817             sub _get_fmt_list_str_len
1818             {
1819             my $self = shift;
1820              
1821             return length($self->_get_format_list_str());
1822             }
1823              
1824             sub _get_format_list_str
1825             {
1826             my $self = shift;
1827              
1828             return "List of Failed";
1829             }
1830              
1831             sub _create_fmts
1832             {
1833             my $self = shift;
1834              
1835             $self->_calc_format_widths();
1836              
1837             return;
1838             }
1839              
1840             sub _get_fail_other_exception_text
1841             {
1842             my $self = shift;
1843              
1844             return $self->_format_self("fail_other_except");
1845             }
1846              
1847             sub _calc_dubious_return_ret_value
1848             {
1849             my $self = shift;
1850              
1851             return $self->_create_failed_obj_instance(
1852             $self->_calc_dubious_return_failed_obj_params(),
1853             );
1854             }
1855              
1856             sub _calc_dubious_return_failed_obj_params
1857             {
1858             my $self = shift;
1859              
1860             return
1861             {
1862             @{$self->_get_dubious_summary()},
1863             @{$self->last_test_obj->get_failed_obj_params()},
1864             @{$self->last_test_results->get_failed_obj_params()},
1865             };
1866             }
1867              
1868             =head2 $self->_report_failed_before_any_test_output();
1869              
1870             [This is a method that needs to be over-rided.]
1871              
1872             =cut
1873              
1874             =head2 $self->_report_skipped_test()
1875              
1876             [This is a method that needs to be over-rided.]
1877              
1878             Should report the skipped test.
1879              
1880             =cut
1881              
1882             =head2 $self->_report_all_ok_test()
1883              
1884             [This is a method that needs to be over-rided.]
1885              
1886             Should report the all OK test.
1887              
1888             =cut
1889              
1890             =head2 $self->_report_all_skipped_test()
1891              
1892             [This is a method that needs to be over-rided.]
1893              
1894             Should report the all-skipped test.
1895              
1896             =cut
1897              
1898             =head2 $self->_report_single_test_file_start({test_file => "t/my_test_file.t"})
1899              
1900             [This is a method that needs to be over-rided.]
1901              
1902             Should start the report for the C<test_file> file.
1903              
1904             =cut
1905              
1906             =head2 $self->_report('channel' => $channel, 'event' => $event_handle);
1907              
1908             [This is a method that needs to be over-rided.]
1909              
1910             Reports the C<$event_handle> event to channel C<$channel>. This should be
1911             overrided by derived classes to do alternate functionality besides calling
1912             output()->print_message(), also different based on the channel.
1913              
1914             Currently available channels are:
1915              
1916             =over 4
1917              
1918             =item 'success'
1919              
1920             The success report.
1921              
1922             =back
1923              
1924             An event is a hash ref that should contain a 'type' property. Currently
1925             supported types are:
1926              
1927             =over 4
1928              
1929             =item * success
1930              
1931             A success type.
1932              
1933             =back
1934              
1935             =cut
1936              
1937             =head2 $self->_report_final_stats()
1938              
1939             [This is a method that needs to be over-rided.]
1940              
1941             Reports the final statistics.
1942              
1943             =cut
1944              
1945             =head2 $self->_fail_other_print_top()
1946              
1947             [This is a method that needs to be over-rided.]
1948              
1949             Prints the header of the files that failed.
1950              
1951             =cut
1952              
1953             =head2 $self->_fail_other_report_test($script_name)
1954              
1955             [This is a method that needs to be over-rided.]
1956              
1957             In case of failure from a different reason - report that test script.
1958             Test::Run iterates over all the scripts and reports them one by one.
1959              
1960             =cut
1961              
1962              
1963             =head2 $self->_fail_other_print_bonus_message()
1964              
1965             [This is a method that needs to be over-rided.]
1966              
1967             Should report the bonus message in case of failure from a different
1968             reason.
1969              
1970             =cut
1971              
1972             =head2 $self->_report_tap_event($args)
1973              
1974             [This is a method that needs to be over-rided.]
1975              
1976             =head2 $self->_report_script_start_environment()
1977              
1978             [This is a method that needs to be over-rided.]
1979              
1980             Should report the environment of the script at its beginning.
1981              
1982             =head2 $self->_handle_test_file_opening_error($args)
1983              
1984             [This is a method that needs to be over-rided.]
1985              
1986             Should handle the case where the test file cannot be opened.
1987              
1988             =cut
1989              
1990             =head2 $self->_report_test_progress($args)
1991              
1992             [This is a method that needs to be over-rided.]
1993              
1994             Report the text progress. In the command line it would be a ok $curr/$total
1995             or NOK.
1996              
1997             =cut
1998             =head2 The common test-context $args param
1999              
2000             Contains:
2001              
2002             =over 4
2003              
2004             =item 'test_struct' => $test
2005              
2006             A reference to the test summary object.
2007              
2008             =item estatus
2009              
2010             The exit status of the test file.
2011              
2012             =back
2013              
2014             =head2 $test_run->_report_dubious($args)
2015              
2016             [This is a method that needs to be over-rided.]
2017              
2018             Is called to report the "dubious" error, when the test returns a non-true
2019             error code.
2020              
2021             $args are the test-context - see above.
2022              
2023             =cut
2024              
2025             =head2 $test_run->_report_dubious_summary_all_subtests_successful($args)
2026              
2027             [This is a method that needs to be over-rided.]
2028              
2029             $args are the test-context - see above.
2030              
2031             =head2 $test_run->_report_premature_test_dubious_summary($args)
2032              
2033             [This is a method that needs to be over-rided.]
2034              
2035             $args are the test-context - see above.
2036              
2037             =head2 opendir
2038              
2039             This method is placed in the namespace by Fatal.pm. This entry is here just
2040             to settle Pod::Coverage.
2041              
2042             =cut
2043              
2044             1;
2045              
2046             =head1 AUTHOR
2047              
2048             Test::Run::Core is based on L<Test::Harness>, and has later been spinned off
2049             as a separate module.
2050              
2051             =head2 Test:Harness Authors
2052              
2053             Either Tim Bunce or Andreas Koenig, we don't know. What we know for
2054             sure is, that it was inspired by Larry Wall's TEST script that came
2055             with perl distributions for ages. Numerous anonymous contributors
2056             exist. Andreas Koenig held the torch for many years, and then
2057             Michael G Schwern.
2058              
2059             Test::Harness was then maintained by Andy Lester C<< <andy at petdance.com> >>.
2060              
2061             =head2 Test::Run::Obj Authors
2062              
2063             Shlomi Fish C<< <shlomif@iglu.org.il> >>
2064              
2065             Note: this file is a rewrite of the original Test::Run code in order to
2066             change to a more liberal license.
2067              
2068             =head1 BUGS
2069              
2070             Please report any bugs or feature requests to
2071             C<bug-test-run at rt.cpan.org>, or through the web interface at
2072             L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Test::Run>.
2073             I will be notified, and then you'll automatically be notified of progress on
2074             your bug as I make changes.
2075              
2076             =head1 SUPPORT
2077              
2078             You can find documentation for this module with the perldoc command.
2079              
2080             perldoc Test::Run::Core
2081              
2082             You can also look for information at:
2083              
2084             =over 4
2085              
2086             =item * AnnoCPAN: Annotated CPAN documentation
2087              
2088             L<http://annocpan.org/dist/Test::Run::Core>
2089              
2090             =item * CPAN Ratings
2091              
2092             L<http://cpanratings.perl.org/d/Test::Run::Core>
2093              
2094             =item * RT: CPAN's request tracker
2095              
2096             L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Test::Run>
2097              
2098             =item * Search CPAN
2099              
2100             L<http://search.cpan.org/dist/Test::Run>
2101              
2102             =back
2103              
2104             =head1 SOURCE AVAILABILITY
2105              
2106             The latest source of Test::Run is available from its BerliOS Subversion
2107             repository:
2108              
2109             L<https://svn.berlios.de/svnroot/repos/web-cpan/Test-Harness-NG/>
2110              
2111             =head1 LICENSE
2112              
2113             This file is licensed under the MIT X11 License:
2114              
2115             http://www.opensource.org/licenses/mit-license.php
2116              
2117             =cut