Group
Extension

Quiq/t/bin/Quiq/Hash.t

#!/usr/bin/env perl

package Quiq::Hash::Test;
use base qw/Quiq::Test::Class/;

use v5.10;
use strict;
use warnings;
use utf8;

# -----------------------------------------------------------------------------

sub test_loadClass : Init(1) {
    shift->useOk('Quiq::Hash');
}

# -----------------------------------------------------------------------------

sub test_new_keyVal : Test(5) {
    my $self = shift;

    my $h = Quiq::Hash->new(a=>1,b=>2,c=>3);
    $self->is(ref($h),'Quiq::Hash');
    $self->is($h->{'a'},1);
    $self->is($h->{'b'},2);
    $self->is($h->{'c'},3);
    $self->ok(!$h->exists('d'));
}

sub test_new_keys_vals : Test(5) {
    my $self = shift;

    my @keys = qw/a b c/;
    my @vals = qw/1 2 3/;

    my $h = Quiq::Hash->new(\@keys,\@vals);
    $self->is(ref($h),'Quiq::Hash');
    $self->is($h->{'a'},1);
    $self->is($h->{'b'},2);
    $self->is($h->{'c'},3);
    $self->ok(!$h->exists('d'));
}

sub test_new_keys_val : Test(5) {
    my $self = shift;

    my @keys = qw/a b c/;

    my $h = Quiq::Hash->new(\@keys,1);
    $self->is(ref($h),'Quiq::Hash');
    $self->is($h->{'a'},1);
    $self->is($h->{'b'},1);
    $self->is($h->{'c'},1);
    $self->ok(!$h->exists('d'));
}

sub test_new_hash : Test(5) {
    my $self = shift;

    my $h = Quiq::Hash->new({a=>1,b=>2,c=>3});
    $self->is(ref($h),'Quiq::Hash');
    $self->is($h->{'a'},1);
    $self->is($h->{'b'},2);
    $self->is($h->{'c'},3);
    $self->ok(!$h->exists('d'));
}

# -----------------------------------------------------------------------------

sub test_get : Test(5) {
    my $self = shift;

    my $h = Quiq::Hash->new(a=>1,b=>2,c=>3);

    my $val = $h->get('b');
    $self->is($val,2,'Skalarkontext');

    $val = $h->{'b'};
    $self->is($val,2,'Direkter Hashzugriff');

    my @arr = $h->get('b','a');
    $self->isDeeply(\@arr,[2,1],'Listkontext');

    @arr = @{$h}{'b','a'};
    $self->isDeeply(\@arr,[2,1],'Direkter Hashzugriff');

    $val = eval {$h->get('d')};
    $self->ok($@,'Unerlaubter Schlüssel -> Exception');
}

# -----------------------------------------------------------------------------

sub test_getRef : Test(1) {
    my $self = shift;

    my $h = Quiq::Hash->new(a=>1,b=>2,c=>3);

    my $valS = $h->getRef('b');
    $$valS .= 'a';
    $self->is($h->{'b'},'2a');
}

# -----------------------------------------------------------------------------

sub test_getArray : Test(2) {
    my $self = shift;

    my $h = Quiq::Hash->new(a=>1,b=>[1..5],c=>3);

    my $arr = $h->getArray('b');
    $self->isDeeply($arr,[1..5]);

    my @arr = $h->getArray('b');
    $self->isDeeply(\@arr,[1..5]);
}

# -----------------------------------------------------------------------------

sub test_try : Test(2) {
    my $self = shift;

    my $h = Quiq::Hash->new(a=>1,b=>2,c=>3);

    my $val = $h->try('b');
    $self->is($val,2,'Skalarkontext');
    
    my @arr = $h->try('b','a');
    $self->isDeeply(\@arr,[2,1],'Listkontext');
}

# -----------------------------------------------------------------------------

sub test_set : Test(5) {
    my $self = shift;

    my $h = Quiq::Hash->new(a=>1,b=>2,c=>3);

    $h->set(b=>5);
    $self->is($h->{'b'},5);

    $h->{'b'} = 5;
    $self->is($h->{'b'},5);

    @{$h}{'b','c'} = (6,7);
    $self->is($h->{'b'},6);
    $self->is($h->{'c'},7);

    eval {$h->set(d=>7)};
    $self->ok($@);
}

# -----------------------------------------------------------------------------

sub test_add : Test(2) {
    my $self = shift;

    my $h = Quiq::Hash->new(a=>1,b=>2,c=>3);

    $h->add(b=>5,d=>7);
    $self->is($h->{'b'},5,'Neuer Wert');
    $self->is($h->{'d'},7,'Neues Schlüssel/Wert-Paar');
}

# -----------------------------------------------------------------------------

sub test_memoize : Test(1) {
    my $self = shift;

    my $h = Quiq::Hash->new(a=>undef);
    my $val = $h->memoize('a',sub {5});
    $self->is($val,5);
}

# -----------------------------------------------------------------------------

sub test_compute : Test(1) {
    my $self = shift;

    my $h = Quiq::Hash->new(a=>1);

    my $val = $h->compute('a',sub {
        my ($h,$key) = @_;
        return ++$h->{$key};
    });
    $self->is($val,2);
}

# -----------------------------------------------------------------------------

sub test_AUTOLOAD : Test(3) {
    my $self = shift;

    my $h = Quiq::Hash->new(a=>1,b=>2,c=>3);

    my $val = $h->a;
    $self->is($val,1);

    $h->a = 3;
    $self->is($h->a,3);

    eval{$h->d};
    $self->like($@,qr/HASH-00001/);
}

# -----------------------------------------------------------------------------

sub test_keys : Test(3) {
    my $self = shift;

    my $h = Quiq::Hash->new(a=>1,b=>2,c=>3);

    my @keys = $h->keys;
    @keys = sort @keys;
    $self->isDeeply(\@keys,[qw/a b c/]);

    my $keyA = $h->keys;
    $self->is(ref($keyA),'ARRAY');
    @keys = sort @$keyA;
    $self->isDeeply(\@keys,[qw/a b c/]);
}

# -----------------------------------------------------------------------------

sub test_hashSize : Test(1) {
    my $self = shift;

    my $h = Quiq::Hash->new(a=>1,b=>2,c=>3);
    my $n = $h->hashSize;
    $self->is($n,3);
}

# -----------------------------------------------------------------------------

sub test_validate : Test(2) {
    my $self = shift;

    my $h = {a=>1,b=>2,c=>3};

    eval{Quiq::Hash->validate($h,[qw/a b c/])};
    $self->ok(!$@);

    eval{Quiq::Hash->validate($h,[qw/a b d/])};
    $self->ok($@);
}

# -----------------------------------------------------------------------------

sub test_copy : Test(2) {
    my $self = shift;

    my $h1 = Quiq::Hash->new(a=>1,b=>2,c=>3);

    my $h2 = $h1->copy;
    $self->isnt($h1,$h2,'Referenzen verschieden');
    $self->isDeeply($h1,$h2,'Gleiche Schlüssel/Wert-Paare');
}

# -----------------------------------------------------------------------------

sub test_join : Test(1) {
    my $self = shift;

    my $h = Quiq::Hash->new(a=>1,b=>2,c=>3);
    my %hash = (b=>4);
    my $expectedH = Quiq::Hash->new(a=>1,b=>4,c=>3);
    
    $h->join(\%hash);
    $self->isDeeply($h,$expectedH);
}

# -----------------------------------------------------------------------------

sub test_delete : Test(4) {
    my $self = shift;

    # Test-Hash erzeugen
    my $h = Quiq::Hash->new(a=>1,b=>2,c=>3);

    # Schlüssel entfernen

    $h->delete('a','c');
    my $keyA = $h->keys;
    $self->isDeeply($keyA,['b']);

    # Entfernte Schlüssel erneut setzen

    $h->set(a=>4,c=>5);
    my @arr = $h->get(qw/a b c/);
    $self->isDeeply(\@arr,[4,2,5]);

    # Mehrere Schlüssel auf konventionelle Weise entfernen

    delete @{$h}{'a','c'};
    $keyA = $h->keys;
    $self->isDeeply($keyA,['b']);

    # Neue Schlüssel können nicht hinzugeügt werden

    eval{$h->set(d=>6)};
    $self->ok($@);
}

# -----------------------------------------------------------------------------

sub test_clear : Test(2) {
    my $self = shift;

    my $h = Quiq::Hash->new(a=>1,b=>2,c=>3);

    # Fix: CPAN Testers

    my $n = $h->hashSize;
    $self->is($n,3);

    $h->clear;

    $n = $h->hashSize;
    $self->is($n,0);
}

# -----------------------------------------------------------------------------

sub test_exists : Test(2) {
    my $self = shift;

    my $h = Quiq::Hash->new(a=>1);

    my $bool = $h->exists('a');
    $self->ok($bool,'a existiert');

    $bool = $h->exists('b');
    $self->ok(!$bool,'b existiert nicht');
}

# -----------------------------------------------------------------------------

sub test_defined : Test(2) {
    my $self = shift;

    my $h = Quiq::Hash->new(a=>1,b=>undef);

    my $bool = $h->defined('a');
    $self->ok($bool,'a ist definiert');

    $bool = $h->defined('b');
    $self->ok(!$bool,'b ist nicht definiert');
}

# -----------------------------------------------------------------------------

sub test_isEmpty : Test(2) {
    my $self = shift;

    my $h = Quiq::Hash->new(a=>1,b=>2,c=>3);
    my $bool = $h->isEmpty;
    $self->ok(!$bool,'Nicht leer');

    $h->clear;
    $bool = $h->isEmpty;
    $self->ok($bool,'Leer');
}

# -----------------------------------------------------------------------------

sub test_isLocked : Test(3) {
    my $self = shift;

    # Leerer Hash

    my $h = Quiq::Hash->new;
    if ($] < 5.018) {
        # Bug in Perl-Versionen kleiner 5.18.0
        $self->is($h->isLocked,0,'Leerer Hash ist nicht gelocked');
    }
    else {
        $self->is($h->isLocked,1,'Leerer Hash ist gelocked');
    }

    # Nicht-Leerer Hash

    $h = Quiq::Hash->new(a=>1,b=>2,c=>3);

    my $isLocked = $h->isLocked;
    $self->is($isLocked,1,'Nicht-leerer Hash ist gelocked');

    $h->unlockKeys;
    $isLocked = $h->isLocked;
    $self->is($isLocked,0,'Lock ist aufgehoben');
}

# -----------------------------------------------------------------------------

sub test_lockKeys : Test(2) {
    my $self = shift;

    my $h = Quiq::Hash->new(a=>1,b=>2,c=>3);

    $h->lockKeys;

    my $val = $h->{'b'};
    $self->is($val,2,'Key b');

    $val = eval {$h->{'d'}};
    $self->like($@,qr/disallowed key 'd'/,'Key d - Exception');
}

# -----------------------------------------------------------------------------

sub test_unlockKeys : Test(3) {
    my $self = shift;

    my $h = Quiq::Hash->new(a=>1,b=>2,c=>3);
    $h->lockKeys;

    my $val = $h->{'b'};
    $self->is($val,2,'Key b');

    $val = eval { $h->{'d'} };
    $self->like($@,qr/disallowed key 'd'/,'Key d - Exception');

    $h->unlockKeys;

    $val = $h->{'d'};
    $self->is($val,undef,'Key d - undef');
}

# -----------------------------------------------------------------------------

sub test_arraySize : Test(3) {
    my $self = shift;

    my $h = Quiq::Hash->new(a=>[1..5],b=>undef,c=>{});

    my $n = $h->arraySize('a');
    $self->is($n,5);

    $n = $h->arraySize('b');
    $self->is($n,0);

    eval{$h->arraySize('c')};
    $self->like($@,qr/HASH-00005/);
}

# -----------------------------------------------------------------------------

sub test_setOrPush : Test(3) {
    my $self = shift;

    my $h = Quiq::Hash->new(a=>[1..5],b=>undef,c=>{});

    $h->setOrPush(a=>10);
    my $arr = $h->get('a');
    $self->isDeeply($arr,[1..5,10]);

    $h->setOrPush(a=>[20,30]);
    $self->isDeeply($arr,[1..5,10,20,30]);

    $h->setOrPush(b=>42);
    my $val = $h->get('b');
    $self->is($val,42);
}

# -----------------------------------------------------------------------------

sub test_push : Test(1) {
    my $self = shift;

    my $h = Quiq::Hash->new(a=>[1..5],b=>undef,c=>{});

    $h->push(a=>10);
    my $arr = $h->get('a');
    $self->isDeeply($arr,[1..5,10]);
}

# -----------------------------------------------------------------------------

sub test_addNumber : Test(1) {
    my $self = shift;

    my $h = Quiq::Hash->new(a=>1);

    my $y = $h->addNumber(a=>45.5);
    $self->is($y,46.5);
}

# -----------------------------------------------------------------------------

sub test_weaken : Test(2) {
    my $self = shift;

    my $child = Quiq::Hash->new;
    my $parent = Quiq::Hash->new(child=>$child);
    $parent->weaken('child');
    $self->ok($parent->get('child'),'Schwache Referenz');
    $child = undef;
    $self->is($parent->get('child'),undef,'Referenz entfernt');
}

# -----------------------------------------------------------------------------

sub test_buckets : Test(2) {
    my $self = shift;

    my $h = Quiq::Hash->new;
    my $n = $h->buckets(1000);
    $self->ok($n,'Positiver Wert'); # Fix: CPAN Testers
    $n = $h->hashSize;
    $self->is($n,0,'Hash ist leer');
}

# -----------------------------------------------------------------------------

sub test_bucketsUsed : Test(2) {
    my $self = shift;

    my $h = Quiq::Hash->new;
    my $n = $h->bucketsUsed;
    $self->is($n,0,'Hash ist leer');

    $h->add(a=>1,b=>2,c=>3);
    $n = $h->bucketsUsed;
    $self->ok($n,'Buckets vorhanden (Anzahl schwankt)');
}

# -----------------------------------------------------------------------------

package main;
Quiq::Hash::Test->runTests;

# eof


Powered by Groonga
Maintained by Kenichi Ishigaki <ishigaki@cpan.org>. If you find anything, submit it on GitHub.