File Coverage

blib/lib/Test/Fork.pm
Criterion Covered Total %
statement 44 44 100.0
branch 11 14 78.5
condition 3 3 100.0
subroutine 8 8 100.0
pod 1 2 50.0
total 67 71 94.3


line stmt bran cond sub pod time code
1             package Test::Fork;
2              
3 6     6   128488 use strict;
  6         14  
  6         239  
4 6     6   33 use warnings;
  6         12  
  6         320  
5              
6             our $VERSION = '0.02';
7              
8 6     6   35 use base 'Test::Builder::Module';
  6         17  
  6         4799  
9             our @EXPORT = qw(fork_ok);
10              
11             my $CLASS = __PACKAGE__;
12              
13              
14             sub note {
15 10     10 0 77 my $msg = shift;
16 10         130 my $fh = $CLASS->builder->output;
17              
18 10         4403 print $fh "# $msg\n";
19             }
20              
21              
22             =head1 NAME
23              
24             Test::Fork - test code which forks
25              
26             =head1 SYNOPSIS
27              
28             use Test::More tests => 4;
29             use Test::Fork;
30            
31             fork_ok(2, sub{
32             pass("Test in the child process");
33             pass("Another test in the child process");
34             });
35            
36             pass("Test in the parent");
37              
38             =head1 DESCRIPTION
39              
40             B The implementation is unreliable and the interface
41             is subject to change.
42              
43             Because each test has a number associated with it, testing code which forks
44             is problematic. Coordinating the test number amongst the parent and child
45             processes is complicated. Test::Fork provides a function to smooth over
46             the complications.
47              
48             =head2 Functions
49              
50             Each function is exported by default.
51              
52             =head3 B
53              
54             my $child_pid = fork_ok( $num_tests, sub {
55             ...child test code...
56             });
57              
58             Runs the given child test code in a forked process. Returns the pid of the
59             forked child process, or false if the fork fails.
60              
61             $num_tests is the number of tests in your child test code.
62             Consider it to be a sub-plan.
63              
64             fork_ok() itself is a test, if the fork fails it will fail. fork_ok()
65             test does not count towards your $num_tests.
66              
67             # This is three tests.
68             fork_ok( 2, sub {
69             is $foo, $bar;
70             ok Something->method;
71             });
72              
73             The children are automatically reaped.
74              
75             =cut
76              
77             my %Reaped;
78             my %Running_Children;
79             my $Is_Child = 0;
80              
81             sub fork_ok ($&) {
82 8     8 1 5919 my($num_tests, $child_sub) = @_;
83            
84 8         73 my $tb = $CLASS->builder;
85 8         7913 my $pid = fork;
86              
87             # Failed fork
88 8 100       2879 if( !defined $pid ) {
    100          
89 1         8 return $tb->ok(0, "fork() failed: $!");
90             }
91             # Parent
92             elsif( $pid ) {
93             # Avoid race condition where child has run and is reaped before
94             # parent even runs.
95 4 50       199 $Running_Children{$pid} = 1 unless $Reaped{$pid};
96              
97 4         233 $tb->use_numbers(0);
98 4         187 $tb->current_test($tb->current_test + $num_tests);
99              
100 4         763 $tb->ok(1, "fork() succeeded, child pid $pid");
101 4         3658 return $pid;
102             }
103              
104             # Child
105 3         76 $Is_Child = 1;
106              
107 3         214 $tb->use_numbers(0);
108 3         218 $tb->no_ending(1);
109            
110 3         254 note("Running child pid $$");
111 3         52 $child_sub->();
112 3         5608 exit;
113             }
114              
115             END {
116 3   100 3   2355 while( !$Is_Child and keys %Running_Children ) {
117 1         11 note("reaper($$) waiting on @{[keys %Running_Children]}");
  1         8  
118 1         25 _check_kids();
119 1         4 _reaper();
120             }
121             }
122              
123             sub _check_kids {
124 1     1   4 for my $child (keys %Running_Children) {
125 1 50       4 delete $Running_Children{$child} if $Reaped{$child};
126 1 50       37 delete $Running_Children{$child} unless kill 0, $child;
127 1         5 note("Child $child already reaped");
128             }
129             }
130              
131             sub _reaper {
132 5     5   587 local $?; # wait sets $?
133              
134 5         805124 my $child_pid = wait;
135 5         87 $Reaped{$child_pid}++;
136 5         25 delete $Running_Children{$child_pid};
137              
138 5         39 note("child $child_pid reaped");
139              
140 5 100       61 $CLASS->builder->use_numbers(1) unless keys %Running_Children;
141              
142 5 100       128 return $child_pid == -1 ? 0 : 1;
143             }
144              
145             $SIG{CHLD} = \&_reaper;
146              
147              
148             =head1 CAVEATS
149              
150             The failure of tests in a child process cannot be detected by the parent.
151             Therefore, the normal end-of-test reporting done by Test::Builder will
152             not notice failed child tests.
153              
154             Test::Fork turns off test numbering in order to avoid test counter
155             coordination issues. It turns it back on once the children are done
156             running.
157              
158             Test::Fork will wait for all your child processes to complete at the end of
159             the parent process.
160              
161             =head1 SEE ALSO
162              
163             L
164              
165              
166             =head1 AUTHOR
167              
168             Michael G Schwern Eschwern@pobox.comE
169              
170              
171             =head1 BUGS and FEEDBACK
172              
173             Please send all bugs and feature requests to
174             I at I or use the web interface via
175             L.
176              
177             If you use it, please send feedback. I like getting feedback.
178              
179              
180             =head1 COPYRIGHT and LICENSE
181              
182             Copyright 2007-2008 by Michael G Schwern Eschwern@pobox.comE.
183              
184             This program is free software; you can redistribute it and/or
185             modify it under the same terms as Perl itself.
186              
187             See F
188              
189             =cut
190              
191             42;