Data-Histogram-Shared
view release on metacpan or search on metacpan
t/03-frozen.t view on Meta::CPAN
eval { $ro->sync };
ok !$@, 'sync on read-only view is a silent no-op';
like exception(sub { $ro->record(1) }), qr/read-only/, 'record on read-only view croaks';
like exception(sub { $ro->record_many([1]) }), qr/read-only/, 'record_many on read-only view croaks';
like exception(sub { $ro->reset }), qr/read-only/, 'reset on read-only view croaks';
like exception(sub { $ro->freeze }), qr/read-only/, 'freeze on read-only view croaks';
{
my $other = Data::Histogram::Shared->new(undef, 1, 1_000_000, 3);
like exception(sub { $ro->merge($other) }), qr/read-only/, 'merge on read-only view croaks';
}
}
# ---- two independent read-only views of the same file, concurrently ----
{
my $a = Data::Histogram::Shared->new_readonly($path);
my $b = Data::Histogram::Shared->new_readonly($path);
ok $a->total_count == $c && $b->total_count == $c, 'two read-only views query the same file';
}
# ---- refuse a read-write reopen of a sealed file ----
like exception(sub { Data::Histogram::Shared->new($path, 1, 1_000_000, 3) }),
qr/frozen|read-only/, 'read-write reopen of a sealed file is refused';
# ---- new_readonly rejects a non-frozen file ----
{
my $u = "$dir/unsealed.hist";
{ my $h = Data::Histogram::Shared->new($u, 1, 1_000_000, 3); $h->record(1); }
like exception(sub { Data::Histogram::Shared->new_readonly($u) }),
qr/not frozen/, 'new_readonly on an unsealed file croaks';
}
# ---- new_readonly error paths ----
like exception(sub { Data::Histogram::Shared->new_readonly("$dir/does-not-exist.hist") }),
qr/open|No such/, 'new_readonly on a missing path croaks';
like exception(sub { Data::Histogram::Shared->new_readonly(undef) }),
qr/required/, 'new_readonly requires a path';
# ---- merge FROM a frozen (read-only) other into a mutable histogram (lock-free o read) ----
{
my $m = "$dir/other.hist";
my $B = Data::Histogram::Shared->new($m, 1, 1_000_000, 3);
$B->record($_) for (50, 60, 70);
$B->freeze;
my $Bro = Data::Histogram::Shared->new_readonly($m);
my $A = Data::Histogram::Shared->new(undef, 1, 1_000_000, 3); # same geometry
$A->record(1000);
$A->merge($Bro); # must read Bro's counts without locking its PROT_READ map
is $A->total_count, 4, "merge target total_count includes its own record plus the frozen other's three";
is $A->min, 50, 'merge: min adopted from the frozen other';
is $A->max, 1000, 'merge: max stays the local value';
cmp_ok $A->count_at_value(1000), '>=', 1, 'merge target keeps its own item';
cmp_ok $A->count_at_value($_), '>=', 1, "merged-in value $_ present after merge from frozen other"
for (50, 60, 70);
}
done_testing;
# minimal exception helper (avoid a Test::Fatal dependency)
sub exception {
my $code = shift;
my $err;
{ local $@; eval { $code->(); 1 } or $err = $@; }
return $err;
}
( run in 0.598 second using v1.01-cache-2.11-cpan-54e63673c56 )