Data-HashMap
view release on metacpan or search on metacpan
t/20-new-features.t view on Meta::CPAN
# ============================================================
# put_ttl (per-key TTL)
# ============================================================
# keyword put_ttl - entry expires independently
{
my $m = Data::HashMap::II->new();
hm_ii_put_ttl $m, 1, 10, 1;
hm_ii_put $m, 2, 20;
my $v1 = hm_ii_get $m, 1;
is($v1, 10, 'II put_ttl before expiry');
my $v2 = hm_ii_get $m, 2;
is($v2, 20, 'II no-ttl before expiry');
sleep 2;
$v1 = hm_ii_get $m, 1;
is($v1, undef, 'II put_ttl expired');
$v2 = hm_ii_get $m, 2;
is($v2, 20, 'II no-ttl survives');
}
# keyword put_ttl - string/string
{
my $m = Data::HashMap::SS->new();
hm_ss_put_ttl $m, "a", "b", 1;
hm_ss_put $m, "c", "d";
sleep 2;
my $v1 = hm_ss_get $m, "a";
is($v1, undef, 'SS put_ttl expired');
my $v2 = hm_ss_get $m, "c";
is($v2, "d", 'SS no-ttl survives');
}
# keyword put_ttl - int/SV*
{
my $m = Data::HashMap::IA->new();
hm_ia_put_ttl $m, 1, [1], 1;
sleep 2;
my $v = hm_ia_get $m, 1;
is($v, undef, 'IA put_ttl expired');
}
# keyword put_ttl - string/SV*
{
my $m = Data::HashMap::SA->new();
hm_sa_put_ttl $m, "k", {a=>1}, 1;
sleep 2;
my $v = hm_sa_get $m, "k";
is($v, undef, 'SA put_ttl expired');
}
# put_ttl on map with default_ttl - per-key overrides default
{
my $m = Data::HashMap::II->new(0, 60);
hm_ii_put_ttl $m, 1, 10, 1;
hm_ii_put $m, 2, 20;
sleep 2;
my $v1 = hm_ii_get $m, 1;
is($v1, undef, 'II put_ttl overrides default TTL (expired)');
my $v2 = hm_ii_get $m, 2;
is($v2, 20, 'II default TTL still alive');
}
# put_ttl with LRU
{
my $m = Data::HashMap::II->new(10);
hm_ii_put_ttl $m, 1, 10, 1;
sleep 2;
my $v = hm_ii_get $m, 1;
is($v, undef, 'II put_ttl with LRU expired');
}
# method put_ttl
{
my $m = Data::HashMap::I32->new();
$m->put_ttl(1, 10, 1);
is($m->get(1), 10, 'I32 method put_ttl before expiry');
sleep 2;
is($m->get(1), undef, 'I32 method put_ttl expired');
}
# to_hash skips put_ttl expired entries
{
my $m = Data::HashMap::II->new();
hm_ii_put_ttl $m, 1, 10, 1;
hm_ii_put $m, 2, 20;
sleep 2;
my $h = hm_ii_to_hash $m;
is_deeply($h, {2 => 20}, 'II to_hash skips put_ttl expired');
}
# ============================================================
# get_or_set
# ============================================================
# keyword get_or_set - inserts if missing
{
my $m = Data::HashMap::II->new();
my $v = hm_ii_get_or_set $m, 1, 42;
is($v, 42, 'II get_or_set inserts default');
my $v2 = hm_ii_get $m, 1;
is($v2, 42, 'II get_or_set value stored');
}
# keyword get_or_set - returns existing
{
my $m = Data::HashMap::II->new();
hm_ii_put $m, 1, 10;
my $v = hm_ii_get_or_set $m, 1, 99;
is($v, 10, 'II get_or_set returns existing');
my $v2 = hm_ii_get $m, 1;
is($v2, 10, 'II get_or_set does not overwrite');
}
# keyword get_or_set - string/string
{
my $m = Data::HashMap::SS->new();
my $v = hm_ss_get_or_set $m, "k", "default";
is($v, "default", 'SS get_or_set inserts');
my $v2 = hm_ss_get_or_set $m, "k", "other";
is($v2, "default", 'SS get_or_set returns existing');
t/20-new-features.t view on Meta::CPAN
# take on expired TTL entry returns undef
{
my $m = Data::HashMap::II->new(0, 1);
hm_ii_put $m, 1, 42;
sleep 2;
is(hm_ii_take $m, 1, undef, 'II take on expired entry returns undef');
}
# I16/I32 variants
{
my $m = Data::HashMap::I32->new();
hm_i32_put $m, 1, 99;
is(hm_i32_take $m, 1, 99, 'I32 take');
my $m2 = Data::HashMap::I16->new();
hm_i16_put $m2, 1, 42;
is(hm_i16_take $m2, 1, 42, 'I16 take');
}
# ============================================================
# drain (batch remove + return)
# ============================================================
{
my $m = Data::HashMap::II->new();
hm_ii_put $m, $_, $_ * 10 for 1..10;
my @batch = hm_ii_drain $m, 3;
is(scalar @batch, 6, 'II drain: 3 pairs = 6 elements');
is(hm_ii_size $m, 7, 'II drain: 7 remain');
my @rest = hm_ii_drain $m, 100;
is(scalar @rest, 14, 'II drain: rest = 7 pairs');
is(hm_ii_size $m, 0, 'II drain: empty');
my @empty = hm_ii_drain $m, 5;
is(scalar @empty, 0, 'II drain empty map');
}
{
my $m = Data::HashMap::SS->new();
hm_ss_put $m, "k$_", "v$_" for 1..5;
my @pairs = hm_ss_drain $m, 2;
is(scalar @pairs, 4, 'SS drain: 2 pairs');
is(hm_ss_size $m, 3, 'SS drain: 3 remain');
}
{
my $m = Data::HashMap::IA->new();
hm_ia_put $m, $_, [$_] for 1..3;
my @pairs = hm_ia_drain $m, 2;
is(scalar @pairs, 4, 'IA drain: 2 pairs');
is(hm_ia_size $m, 1, 'IA drain: 1 remains');
is_deeply($pairs[1], [$pairs[0]], 'IA drain: value intact');
}
# drain respects TTL
{
my $m = Data::HashMap::II->new(0, 1);
hm_ii_put $m, $_, $_ for 1..5;
sleep 2;
hm_ii_put $m, 6, 6; # only this one is alive
my @pairs = hm_ii_drain $m, 100;
is(scalar @pairs, 2, 'II drain: only non-expired returned');
is($pairs[1], 6, 'II drain: correct value');
}
# ============================================================
# pop (LRU tail / iter forward) and shift (LRU head / iter backward)
# ============================================================
# LRU pop = take from tail (least recently used)
{
my $m = Data::HashMap::II->new(100);
hm_ii_put $m, $_, $_ * 10 for 1..5;
hm_ii_get $m, 3; # promote 3 to MRU
my ($k, $v) = hm_ii_pop $m;
is($k, 1, 'II LRU pop: key is LRU tail');
is($v, 10, 'II LRU pop: correct value');
is(hm_ii_size $m, 4, 'II LRU pop: size decremented');
}
# LRU shift = take from head (most recently used)
{
my $m = Data::HashMap::II->new(100);
hm_ii_put $m, $_, $_ * 10 for 1..5;
hm_ii_get $m, 2; # promote 2 to MRU
my ($k, $v) = hm_ii_shift $m;
is($k, 2, 'II LRU shift: key is MRU head');
is($v, 20, 'II LRU shift: correct value');
}
# Non-LRU pop (iter forward) exhausts map
{
my $m = Data::HashMap::II->new();
hm_ii_put $m, $_, $_ for 1..3;
my @all;
while (my @kv = hm_ii_pop $m) { push @all, @kv; }
is(scalar @all, 6, 'II non-LRU pop: all 3 pairs consumed');
is(hm_ii_size $m, 0, 'II non-LRU pop: map empty');
}
# Non-LRU shift (iter backward) exhausts map
{
my $m = Data::HashMap::II->new();
hm_ii_put $m, $_, $_ for 1..3;
my @all;
while (my @kv = hm_ii_shift $m) { push @all, @kv; }
is(scalar @all, 6, 'II non-LRU shift: all 3 pairs consumed');
is(hm_ii_size $m, 0, 'II non-LRU shift: map empty');
}
# SS pop
{
my $m = Data::HashMap::SS->new(10);
hm_ss_put $m, "a", "1";
hm_ss_put $m, "b", "2";
my ($k, $v) = hm_ss_pop $m;
is($v, "1", 'SS LRU pop: returns LRU tail value');
}
# IA pop with SV* values
( run in 1.170 second using v1.01-cache-2.11-cpan-39bf76dae61 )