Data-HashMap-Shared
view release on metacpan or search on metacpan
t/10-edge-cases.t view on Meta::CPAN
my $child_map = Data::HashMap::Shared::II->new($path, 1000);
# Do a normal put to prove the child can access the map
shm_ii_put $child_map, 2, 99;
POSIX::_exit(0);
}
waitpid($pid, 0);
# Now manually corrupt the lock to simulate the child dying while holding it.
# The header is at the start of the mmap file. rwlock is at offset 128
# and encodes 0x80000000 | pid when write-locked. seq is at offset 64.
open my $fh, '+<:raw', $path or die "Cannot open $path: $!";
# Set rwlock = 0x80000000 | $pid (write-locked by dead child)
seek($fh, 128, 0);
print $fh pack('V', 0x80000000 | $pid);
# Set seq to odd (writer active)
seek($fh, 64, 0);
print $fh pack('V', 1);
close $fh;
# Re-open the map â the stale lock is now in the mmap
undef $map;
$map = Data::HashMap::Shared::II->new($path, 1000);
# This should recover after SHM_LOCK_TIMEOUT_SEC (2s) since $pid is dead
my $val = shm_ii_get $map, 1;
# The data written before corruption should still be readable
is($val, 42, 'recovered from stale lock without deadlock');
ok(shm_ii_stat_recoveries($map) > 0, 'stat_recoveries incremented after recovery');
unlink $path;
}
# error diagnostics: wrong variant gives informative message
{
my $path = tmpfile();
my $map = Data::HashMap::Shared::II->new($path, 100);
shm_ii_put $map, 1, 1;
undef $map;
eval { Data::HashMap::Shared::SS->new($path, 100) };
like($@, qr/variant mismatch/, 'variant mismatch gives diagnostic error');
like($@, qr/file=\d+, expected=\d+/, 'error includes variant IDs');
unlink $path;
}
# error diagnostics: bad path gives errno message
{
eval { Data::HashMap::Shared::II->new('/nonexistent/path/test.shm', 100) };
like($@, qr/No such file|Permission denied/, 'bad path gives errno in error');
}
# unlink: instance method
{
my $path = tmpfile();
my $map = Data::HashMap::Shared::II->new($path, 100);
shm_ii_put $map, 1, 42;
ok(-f $path, 'backing file exists');
ok($map->unlink, 'instance unlink returns true');
ok(!-f $path, 'backing file removed after unlink');
# map still works (mmap stays alive after unlink)
my $v = shm_ii_get $map, 1;
is($v, 42, 'map still readable after unlink');
}
# unlink: class method
{
my $path = tmpfile();
my $map = Data::HashMap::Shared::II->new($path, 100);
undef $map;
ok(-f $path, 'backing file exists before class unlink');
ok(Data::HashMap::Shared::II->unlink($path), 'class unlink returns true');
ok(!-f $path, 'backing file removed after class unlink');
}
# unlink: returns false for non-existent file
{
ok(!Data::HashMap::Shared::II->unlink('/tmp/nonexistent_shm_test_' . $$ . '.shm'),
'unlink returns false for non-existent file');
}
# lru_skip: probabilistic promotion skip reduces churn
{
my $path = tmpfile();
# max_size=100, ttl=0, lru_skip=90 (skip 90% of promotions)
my $map = Data::HashMap::Shared::II->new($path, 10000, 100, 0, 90);
# fill to capacity
shm_ii_put $map, $_, $_ for 1..100;
# repeatedly access a non-tail key â with 90% skip, most promotes are skipped
# but the entry should still be reachable and not evicted
shm_ii_get $map, 50 for 1..20;
my $v = shm_ii_get $map, 50;
is($v, 50, 'lru_skip: frequently accessed key still readable');
# insert more entries to trigger evictions
shm_ii_put $map, 100 + $_, 100 + $_ for 1..50;
is(shm_ii_size $map, 100, 'lru_skip: map stays at max_size');
ok(shm_ii_stat_evictions($map) >= 50, 'lru_skip: evictions occurred');
# tail entry (LRU victim) is never skip-protected â eviction still works
# the map should be functional and not corrupt
my $count = 0;
while (my ($k, $v) = shm_ii_each $map) { $count++ }
is($count, 100, 'lru_skip: iteration returns exactly max_size entries');
unlink $path;
}
# lru_skip=0 (default): strict LRU, same as before
{
my $path = tmpfile();
my $map = Data::HashMap::Shared::II->new($path, 10000, 5, 0, 0);
shm_ii_put $map, $_, $_ for 1..5;
# access key 1 to promote it
shm_ii_get $map, 1;
# insert one more â should evict key 2 (LRU), not key 1 (promoted)
shm_ii_put $map, 6, 6;
my $v2 = shm_ii_get $map, 2;
( run in 1.336 second using v1.01-cache-2.11-cpan-39bf76dae61 )