#!/usr/bin/perl -T

use Test::More tests => 19;
use Paranoid;
use Paranoid::Debug;
use Paranoid::BerkeleyDB;

use strict;
use warnings;

psecureEnv();

my ( $rv, $db, $adb, $pid, $prv, %test, @keys, @c, $k, $v );

mkdir './t/db';

# OO invocation tests
$db = new Paranoid::BerkeleyDB;
ok( !defined $db, 'invalid invocation - 1' );
$db = new Paranoid::BerkeleyDB
    Env => { '-Home'     => './t/db' },
    Db  => { '-Filename' => 'test.db' };
ok( defined $db, 'good invocation - 2' );
$db = new Paranoid::BerkeleyDB
    'Home'     => './t/db',
    'Filename' => 'test.db';
ok( defined $db, 'good invocation - 3' );
my $env = new Paranoid::BerkeleyDB::Env '-Home' => './t/db';
$db = new Paranoid::BerkeleyDB
    'Env'      => $env,
    'Filename' => 'test.db';
ok( defined $db, 'good invocation - 4' );
$env = $db = undef;

# tie tests
$rv = tie %test, 'Paranoid::BerkeleyDB',
    'Home'     => './t/db',
    'Filename' => 'test.db';
ok( $rv,                'tie - 5' );
ok( !exists $test{foo}, 'tie exist - 6' );
$test{foo} = "bar";
$test{roo} = "foo";
ok( exists $test{foo}, 'tie store/exist - 7' );
ok( exists $test{roo}, 'tie store/exist - 8' );
is( $test{foo}, 'bar', 'tie fetch - 9' );
is( $test{roo}, 'foo', 'tie fetch - 10' );

@keys = keys %test;
is( @keys, 2, 'tie first/next key - 11' );
while ( ( $k, $v ) = each %test ) {
    push @c, $k, $v;
}
is( @c,           4, 'tie first/next key/value - 12' );
is( scalar %test, 1, 'tie scalar - 13' );
%test = ();
is( scalar %test, 0, 'tie clear/scalar - 14' );

%test = ();
$rv   = untie %test;
ok( $rv, 'untie - 15' );

# forked tests

# Prep
@c = ();
foreach ( 1 .. 4 ) {
    push @c, [];
    @keys = ( 0 .. 10000 );
    while (@keys) {
        push @{ $c[-1] }, splice @keys, int rand @keys, 1;
    }
}

#PDEBUG = 20;

while (@c) {
    @keys = @{ shift @c };
    unless ( $pid = fork ) {

        # Child process
        $rv = tie %test, 'Paranoid::BerkeleyDB',
            'Home'     => './t/db',
            'Filename' => 'test.db';
        foreach (@keys) {
            my $dref = tied %test;
            my $lock = $dref->cds_lock;
            $test{$_} = "$_-$$";
            $lock->cds_unlock;
        }
        untie %test;
        exit 0;
    }
}

for ( 1 .. 4 ) {
    wait;
    $prv = $?;
    is( $prv, 0, 'clean exit in child' );
}

# Cleanup
system 'rm -rf t/db';

