# Before `make install' is performed this script should be runnable with
# `make test'. After `make install' it should work as `perl test.pl'

######################### We start with some black magic to print on failure.

use strict;
use Test;
my $loaded;

BEGIN {
    $| = 1; plan tests =>5;
}
END {print "not ok 1\n" unless $loaded;}

use Hash::Layered;

### test: modules load
$loaded = 1;
ok(1);

######################### End of black magic.
#(['w', k, v], # write v to k
# ['m', v], # set mode to v
# ['d', v], # set mode default to v
# ['r', k, v], # read from k, expect v
# 'push', 'pop',
#)

my @plan1 = (['d', 'opaque'],
             ['w', 'a', 1],
             ['w', 'b', 2],
             ['w', 'c', 3],
             'push',
             ['w', 'a', 4],
             ['w', 'b', 5],
             ['r', 'c', undef],
             ['r', 'a', 4],
             'pop',
             ['r', 'a', 1],
             ['r', 'b', 2],
             ['r', 'c', 3],
             'push',
             ['w', 'a', 6],
             ['w', 'b', 7],
             ['r', 'c', undef],
             ['r', 'a', 6],
             );
my @plan1_end = (['r', 'a', 6],
                 ['r', 'b', 7],
                 ['r', 'c', undef],
                 ['r', 'd', undef],
                 );
my @plan2 = (['d', 'cascade'],
             ['w', 'a', 21],
             ['w', 'b', 22],
             ['w', 'c', 23],
             'push',
             ['w', 'a', 24],
             ['w', 'b', 25],
             ['r', 'c', 23],
             ['r', 'a', 24],
             'pop',
             ['r', 'a', 24],
             ['r', 'b', 25],
             ['r', 'c', 23],
             'push',
             ['w', 'a', 26],
             ['w', 'b', 27],
             ['r', 'c', 23],
             ['r', 'a', 26],
             );

my @plan3 = (['d', 'cascade'],
             ['r', 'a', undef],
             ['r', 'b', undef],
             ['r', 'c', undef],
             ['w', 'a', 31],
             ['w', 'b', 32],
             ['w', 'c', 33],
             'push',
             ['r', 'a', 31],
             ['m', 'opaque'],
             ['r', 'a', undef],
             ['w', 'c', 34],
             ['w', 'd', 35],
             ['m', 'default'],
             ['r', 'a', 31],
             ['r', 'b', 32],
             ['r', 'c', 34],
             ['r', 'd', 35],
             'push',
             ['w', 'a', 36],
             ['m', 'oneway'],
             ['w', 'e', 37],
             ['w', 'a', 38],
             ['r', 'a', 38],
             ['r', 'b', 32],
             ['r', 'e', 37],
             'pop',
             ['r', 'e', undef],
             'pop',
             ['r', 'a', 36],
             ['r', 'b', 32],
             ['r', 'c', 33],
             ['r', 'd', undef],
             );


my $h1 = Hash::Layered->new();
ok(0 == ex_test_plan($h1, \@plan1));

my $h2 = Hash::Layered->new();
ok(0 == ex_test_plan($h2, \@plan2));

# make sure objects are seperate
ok(0 == ex_test_plan($h1, \@plan1_end));

%$h2 = ();
ok (0 == ex_test_plan($h2, \@plan3));


exit 0;

sub ex_test_plan {
    my ($h,$plan) = @_;
    #warn "# begin test run\n";
    my $errors = 0;
    foreach my $cmdset (@$plan) {
        my $cmd = ref($cmdset) ? $cmdset->[0] : $cmdset;
        if ($cmd eq 'w') {
            $h->{$cmdset->[1]} = $cmdset->[2];
        } elsif ($cmd eq 'r') {
            my $e = $cmdset->[2];
            my $v = $h->{$cmdset->[1]};
            if ((!defined($e) && !defined($v)) || $v == $e) {
                # ok
            } else {
                $errors += 1;
                warn "# exp[".$e."]  got[".$v."]\n";
            }
        } elsif ($cmd eq 'm') {
            $h->set_layer($cmdset->[1]);
        } elsif ($cmd eq 'd') {
            $h->set_default($cmdset->[1]);
        } elsif ($cmd eq 'push') {
            $h->push();
        } elsif ($cmd eq 'pop') {
            $h->pop();
        }
    }
    #warn "# end test run\n";
    return $errors;
}





1;