Data-SortedSet-Shared
view release on metacpan or search on metacpan
t/01-basic.t view on Meta::CPAN
use strict;
use warnings;
use Test::More;
use Data::SortedSet::Shared;
# anonymous
my $s = Data::SortedSet::Shared->new(undef, 1000);
isa_ok $s, 'Data::SortedSet::Shared';
is $s->count, 0, 'fresh anon count == 0';
is $s->max_entries, 1000, 'max_entries';
ok !defined($s->path), 'anonymous path is undef';
$s->clear;
is $s->count, 0, 'clear keeps an empty set empty';
# memfd round-trip
my $m = Data::SortedSet::Shared->new_memfd('ss', 50);
my $fd = $m->memfd;
cmp_ok $fd, '>=', 0, 'memfd fd >= 0';
my $m2 = Data::SortedSet::Shared->new_from_fd($fd);
is $m2->max_entries, 50, 'reopened memfd max_entries';
is $m2->count, 0, 'reopened memfd count';
# file-backed reopen: stored header wins
my $path = "/tmp/ss-basic-$$.bin";
unlink $path;
{
my $w = Data::SortedSet::Shared->new($path, 100);
is $w->path, $path, 'file-backed path';
$w->sync;
}
{
my $r = Data::SortedSet::Shared->new($path, 999); # caller arg ignored on reopen
is $r->max_entries, 100, 'reopen: stored max_entries wins';
is $r->count, 0, 'reopen count == 0';
}
# validation
ok !eval { Data::SortedSet::Shared->new(undef, 0); 1 }, 'max_entries 0 rejected';
{ open my $fh, '>', $path or die $!; print $fh "junk"; close $fh; }
ok !eval { Data::SortedSet::Shared->new($path, 100); 1 }, 'too-small/corrupt file rejected';
unlink $path;
# opt-in file mode: applied exactly at create (fchmod after the O_EXCL create,
# so an explicit mode is honored regardless of umask); ignored when attaching
{
my $mp = "/tmp/ss-mode-$$.bin";
unlink $mp;
{ my $w = Data::SortedSet::Shared->new($mp, 10, 0660); }
is +((stat $mp)[2] & 07777), 0660, 'explicit mode honored at create';
{ my $r = Data::SortedSet::Shared->new($mp, 10, 0644); }
is +((stat $mp)[2] & 07777), 0660, 'mode ignored when attaching an existing file';
unlink $mp;
{ my $d = Data::SortedSet::Shared->new($mp, 10); }
is +((stat $mp)[2] & 07777), 0600, 'default mode is 0600';
unlink $mp;
}
# eventfd
my $e = Data::SortedSet::Shared->new(undef, 10);
my $efd = $e->eventfd;
cmp_ok $efd, '>=', 0, 'eventfd created';
ok $e->notify, 'notify writes';
is $e->fileno, $efd, 'fileno returns the eventfd descriptor';
is $e->eventfd_consume, 1, 'eventfd_consume reads the count';
my $ne = Data::SortedSet::Shared->new(undef, 10);
is $ne->fileno, -1, 'fileno is -1 before any eventfd is created';
# class-method unlink
my $cu = "/tmp/ss-classunlink-$$.bin";
unlink $cu;
{ my $w = Data::SortedSet::Shared->new($cu, 10); $w->add(1, 1); $w->sync; }
ok -e $cu, 'backing file exists';
Data::SortedSet::Shared->unlink($cu);
ok !-e $cu, 'class-method unlink removed the file';
# DESTROY nulls the handle: use-after-destroy croaks cleanly instead of a use-after-free,
# and the implicit second DESTROY at scope exit is a safe no-op.
{
my $z = Data::SortedSet::Shared->new(undef, 10);
$z->add(1, 1.0);
$z->DESTROY;
eval { $z->count };
like $@, qr/destroyed/, 'use after DESTROY croaks (not a use-after-free)';
}
pass 'double DESTROY did not crash';
done_testing;
( run in 1.435 second using v1.01-cache-2.11-cpan-600a1bdf6e4 )