use strict;
use warnings;
use Test::More;
use MyNote;
use File::Temp;

use vars qw($tmpdir @dat @sem $I $N);

BEGIN {
    $I = 4;    # number for forks
    $N = 1000; # number of uuids / fork
    $tmpdir  = File::Temp->newdir(CLEANUP => 0);
    $dat[$_] = File::Temp::tempnam($tmpdir, 'UUID.dat.') for 0 .. $I-1;
    $sem[$_] = File::Temp::tempnam($tmpdir, 'UUID.sem.') for 0 .. $I-1;
    pass 'began';
}

use UUID 'uuid1';

my @kids = ();
my $seen = {};

# Comment this to simulate a prefork process that
# doesnt actually use UUID in the parent.
++$seen->{uuid1()} for 1 .. $N;

for my $i ( 0 .. $I-1 ) {
    my $kid;
    if (!defined($kid = fork)) {
        fail "fork$i";
    }
    else {
        if ($kid) {
            pass "fork$i";
            push @kids, $kid;
        }
        else {
            open my $fh, '>', $dat[$i] or err("open: $dat[$i]: $!");
            print $fh uuid1()."\n"
                for 1 .. $N;
            open $fh, '>', $sem[$i] or err("open: $sem[$i]: $!");
            exit 0;
        }
    }
}

my $timeout = 50;
{
    select undef, undef, undef, 0.1;
    my $seen = 0;
    for (0 .. $I-1) { $seen++ if -e $sem[$_] }
    last if $seen == $I;
    redo if --$timeout;
    warn "\n# only $seen sem files found\n";
}
ok $timeout > 0, 'timeout';

++$seen->{uuid1()} for 1 .. $N;

for my $i (0 .. $I-1) {
    open my $fh, '<', $dat[$i] or err("open: $dat[$i]: $!");
    ++$seen->{$_} for map{chomp;$_} <$fh>;
}

#use Data::Dumper;
#note "$_\n" for split /\n/, Dumper($seen);
{
    my $expected = ($I + 2) * $N;
    is scalar(keys %$seen), $expected, "seen $expected";
}

cleanup();
done_testing;

sub err {
    my $error = shift;
    my (undef, $F, $L) = caller;
    cleanup();
    die "$error at $F line $L\n";
}

sub cleanup {
    for my $i (0 .. $I-1) {
        unlink $dat[$i] if -e $dat[$i];
        unlink $sem[$i] if -e $sem[$i];
    }
    rmdir  $tmpdir if defined $tmpdir;
}
