Right now Test::Builder::_ending() is executed only if the
        current process id is the one it had when it started. This
        prevents a child process from completing the test with the
        "1..N" header.

        I introduced a new method, reporting_pid(), that allows the
        user to control which process should execute _ending().

        With the change I can have a single test file that includes
        a fork. Then I can run it twice, once verifying the parent
        and a second time verifying the child.

        For example, the new tests included in the patch below
        allow the following:

                % perl t/reporting_pid_parent.t
                ok 1 - common test
                ok 2 - parent test 1
                ok 3 - parent test 2
                1..3

                % env TEST_CHILD=1 perl t/reporting_pid_parent.t
                ok 1 - common test
                ok 2 - child test 1
                ok 3 - child test 2
                ok 4 - child test 3
                ok 5 - child test 4
                ok 6 - child test 5
                1..6

                crag% cat t/reporting_pid_child.t 
                $ENV{TEST_CHILD} = 1;

                my $parent = $0;
                $parent =~ s/_child.t/_parent.t/;
                do $parent;

                % perl t/reporting_pid_child.t
                ok 1 - common test
                ok 2 - child test 1
                ok 3 - child test 2
                ok 4 - child test 3
                ok 5 - child test 4
                ok 6 - child test 5
                1..6

        Please include this code in the next release of Test::Builder.

           Thank you,

                Scott

diff -ru --new-file Test-Simple-0.47/lib/Test/Builder.pm 
Test-Simple-0.47-patched/lib/Test/Builder.pm
--- Test-Simple-0.47/lib/Test/Builder.pm        Mon Aug 26 05:50:27 2002
+++ Test-Simple-0.47-patched/lib/Test/Builder.pm        Sun Mar 28 16:24:12 2004
@@ -30,7 +30,7 @@
 use vars qw($Level);
 my($Test_Died) = 0;
 my($Have_Plan) = 0;
-my $Original_Pid = $$;
+my $Reporting_Pid = $$;
 my $Curr_Test = 0;      share($Curr_Test);
 my @Test_Results = ();  share(@Test_Results);
 my @Test_Details = ();  share(@Test_Details);
@@ -1044,6 +1044,36 @@
     select $old_fh;
 }
 
+=item B<reporting_pid>
+
+    $Test->reporting_pid($pid);
+
+Select which process should do final reporting. That report
+includes the 1..N header when it was not generated at the start
+of execution.
+
+Defaults to the initial parent process.
+
+Typically used to check both the parent and child branches of tests
+that fork().  The branch that is not going to be verified during
+one run can discard its test results via $self->output("/dev/null")
+and $self->failure_output("/dev/null") while the verified branch
+uses reporting_pid($$). Then, during the next run, the two
+branches switch roles.
+
+See t/reporting_pid_*.t in the source code for examples.
+
+=cut
+
+sub reporting_pid {
+    my($self, $pid) = @_;
+
+    if( defined $pid ) {
+        $Reporting_Pid = $pid;
+    }
+    return $Reporting_Pid;
+}
+
 
 =back
 
@@ -1301,7 +1331,7 @@
 
     # Don't bother with an ending if this is a forked copy.  Only the parent
     # should do the ending.
-    do{ _my_exit($?) && return } if $Original_Pid != $$;
+    do{ _my_exit($?) && return } if $Reporting_Pid != $$;
 
     # Bailout if plan() was never called.  This is so
     # "require Test::Simple" doesn't puke.
diff -ru --new-file Test-Simple-0.47/t/reporting_pid_child.t 
Test-Simple-0.47-patched/t/reporting_pid_child.t
--- Test-Simple-0.47/t/reporting_pid_child.t    Wed Dec 31 18:00:00 1969
+++ Test-Simple-0.47-patched/t/reporting_pid_child.t    Sun Mar 28 16:29:55 2004
@@ -0,0 +1,5 @@
+$ENV{TEST_CHILD} = 1;
+
+my $parent = $0;
+$parent =~ s/_child.t/_parent.t/;
+do $parent;
diff -ru --new-file Test-Simple-0.47/t/reporting_pid_parent.t 
Test-Simple-0.47-patched/t/reporting_pid_parent.t
--- Test-Simple-0.47/t/reporting_pid_parent.t   Wed Dec 31 18:00:00 1969
+++ Test-Simple-0.47-patched/t/reporting_pid_parent.t   Sun Mar 28 16:30:11 2004
@@ -0,0 +1,59 @@
+use strict;
+use Test::Builder;
+use Test::More qw(no_plan);
+
+my $Test = Test::Builder->new();
+ok(defined($Test), "common test");
+
+#
+# Split into a parent and a child.
+#
+my $pid = fork;
+$Test->BAILOUT("Failed to fork: $!")   unless defined($pid);
+
+#
+# Using $ENV{TEST_CHILD} as our guide, decide which output messages are
+# going to be discarded. Also make sure that the proper branch, parent
+# or child, will do the end of run reporting in
+# Test::Builder::_ending().
+#
+if ($pid) {
+       #
+       # Parent
+       #
+       if ($ENV{TEST_CHILD}) {
+               $Test->reporting_pid($pid);
+
+               my($discard);
+               open($discard, '+>', undef);
+               $Test->output($discard);
+               $Test->failure_output($discard);
+       }
+} else {
+       #
+       # Child
+       #
+       if ($ENV{TEST_CHILD}) {
+               $Test->reporting_pid($$);
+       } else {
+               my($discard);
+               open($discard, '+>', undef);
+               $Test->output($discard);
+               $Test->failure_output($discard);
+       }
+}
+
+#
+# This is were the real tests could be run and results verified.
+#
+if ($pid) {
+       ok(42, "parent test 1");
+       ok(24, "parent test 2");
+       waitpid($pid, 0);
+} else {
+       ok(111, "child test 1");
+       ok(222, "child test 2");
+       ok(333, "child test 3");
+       ok(444, "child test 4");
+       ok(555, "child test 5");
+}

Reply via email to