Hi all,

I'm at wit's end about this and any guidance would be appreciated.

I have a class which needs to maintain state based on pid.  So how do I test 
that?  I fork, of course (can't use threads as our Perl is built without thread 
support).  That's when things go bad.  As far as I can tell, Tassilo von 
Parseval's patch for making Test::More work with across forks hasn't been 
implemented:

    http://www.nntp.perl.org/group/perl.qa/2006/03/msg5651.html    
    http://tinyurl.com/yp69e3

So I have the following simple test case:

    #!/usr/bin/perl

    use strict;
    use warnings;

    use Test::More 'no_plan';
    use Test::Builder;
    use IPC::SysV qw< IPC_PRIVATE IPC_RMID S_IRWXU >;

    ok 1, 'mytest called';
    my $test = Test::Builder->new;
    my $id = shmget( IPC_PRIVATE, 2000, S_IRWXU ) or die $!;
    my $test_num;

    if ( !defined( my $child_pid = fork() ) ) {
        diag "Cannot fork: $!";
    }
    elsif ( !$child_pid ) {
        ok 1, 'in the child';
        shmwrite( $id, $test->current_test, 0, 60 ) or die $!;
    }
    else {
        waitpid( $child_pid, 0 );
        shmread( $id, $test_num, 0, 60 ) or die $!;
        $test->current_test($test_num);
        ok 1, 'in the parent';
    }

Basically, if I fork a child, when we return, Test::Builder will not have the 
new test count, so I explicitly use shared memory [1].  While the above runs 
just fine with prove, runtests (from the TAP::Parser distribution), fails with 
the following:

  ok 1 - mytest called
  ok 2 - in the child
  ok 3  - in the parent
  1..3
   All 3 subtests passed 

  Test Summary Report
  -------------------
  forkingtest.pl (Wstat: 0 Tests: 3 Failed: 0)
    Parse errors: No plan found in TAP output
  Files=1, Tests=3,  0 wallclock secs ( 0.05 cusr +  0.02 csys =  0.07 CPU)

However, both prove and runtests fail if I use this in Test::Class:

    #!/usr/bin/perl

    use strict;
    use warnings;

    {
        package TestBase;
        use base 'Test::Class';
        INIT { Test::Class->runtests }
    }
    {
        package My::Test::Class;

        use Test::More;
        use Test::Builder;
        use IPC::SysV qw< IPC_PRIVATE IPC_RMID S_IRWXU >;

        BEGIN { @My::Test::Class::ISA = 'TestBase' }

        sub mytest : Tests(3) {
            ok 1, 'mytest called';
            my $test = Test::Builder->new;
            my $id = shmget(IPC_PRIVATE, 2000, S_IRWXU) or die $!;
            my $test_num;

            if ( !defined( my $child_pid = fork() ) ) {
                diag "Cannot fork: $!";
            }
            elsif ( !$child_pid ) {
                ok 1, 'in the child';
                shmwrite( $id, $test->current_test, 0, 60 ) or die $!;
            }
            else {
                waitpid( $child_pid, 0 );
                shmread( $id, $test_num, 0, 60 ) or die $!;
                $test->current_test($test_num);
                ok 1, 'in the parent';
            }

        }
    }

    1;

Both of them give results like this (note the spurious SKIP):

  TestBase....# 
  # My::Test::Class->mytest
  1..3
  ok 1 - mytest called
  ok 2 - in the child
  ok 3 # skip 1
  ok 3 - in the parent
  Don't know which tests failed: got 4 ok, expected 3
  Failed Test Stat Wstat Total Fail  List of Failed
  
-------------------------------------------------------------------------------
  TestBase.pm                3   ??  ??
  1 subtest skipped.
  Failed 1/1 test scripts. -1/3 subtests failed.
  Files=1, Tests=3,  1 wallclock secs ( 0.12 cusr +  0.02 csys =  0.14 CPU)
  Failed 1/1 test programs. -1/3 subtests failed.

Am I doing something really stupid here?  Could I be using shared memory 
incorrectly?

Cheers,
Ovid

[1] I don't use IPC::Shareable because it won't build due to a bug that's been 
reported for over a year.  http://rt.cpan.org/Public/Bug/Display.html?id=19169
--
Buy the book  - http://www.oreilly.com/catalog/perlhks/
Perl and CGI  - http://users.easystreet.com/ovid/cgi_course/
Personal blog - http://publius-ovidius.livejournal.com/
Tech blog     - http://use.perl.org/~Ovid/journal/


Reply via email to