Data-Fenwick-Shared
view release on metacpan or search on metacpan
t/03-frozen.t view on Meta::CPAN
}
# ---- new_readonly rejects a non-frozen file ----
{
my $u = "$dir/unsealed.fen";
{ my $f = Data::Fenwick::Shared->new($u, 10); $f->update(1, 1); }
like exception(sub { Data::Fenwick::Shared->new_readonly($u) }),
qr/not frozen/, 'new_readonly on an unsealed file croaks';
}
# ---- new_readonly error paths ----
like exception(sub { Data::Fenwick::Shared->new_readonly("$dir/does-not-exist.fen") }),
qr/open|No such/, 'new_readonly on a missing path croaks';
like exception(sub { Data::Fenwick::Shared->new_readonly(undef) }),
qr/required/, 'new_readonly requires a path';
# ---- range-mode tree: freeze + read-only range/prefix/point; range_add + update guarded ----
{
my $rpath = "$dir/frozen_range.fen";
my $rf = Data::Fenwick::Shared->new_range($rpath, $n);
$rf->range_add(3, 10, 5);
$rf->update(15, 2); # point update == range_add(15,15,2) in range mode
my $rtot = $rf->total;
my $rpre = $rf->prefix(10);
my $rrange = $rf->range(3, 10);
my $rpoint = $rf->point(3);
$rf->freeze;
ok $rf->frozen, 'range-mode tree frozen';
ok $rf->readonly, 'range-mode tree read-only after freeze';
like exception(sub { $rf->range_add(1, 2, 1) }), qr/frozen|read-only/, 'range_add on frozen range handle croaks';
like exception(sub { $rf->update(1, 1) }), qr/frozen|read-only/, 'update on frozen range handle croaks';
my $rro = Data::Fenwick::Shared->new_readonly($rpath);
ok $rro->is_range, 'read-only view reports range mode';
is $rro->total, $rtot, 'range total matches producer (lock-free)';
is $rro->prefix(10), $rpre, 'range prefix matches producer (lock-free)';
is $rro->range(3, 10), $rrange, 'range range matches producer (lock-free)';
is $rro->point(3), $rpoint, 'range point matches producer (lock-free)';
like exception(sub { $rro->find(1) }), qr/range-mode/, 'find still rejects range mode when read-only';
}
# ---- merge FROM a frozen (read-only) other into a mutable tree (lock-free o read) ----
{
my $mpath = "$dir/other.fen";
my $B = Data::Fenwick::Shared->new($mpath, $n);
$B->update(2, 5);
$B->update(9, 3);
$B->freeze;
my $Bro = Data::Fenwick::Shared->new_readonly($mpath);
my $A = Data::Fenwick::Shared->new(undef, $n); # same n
$A->update(2, 1);
$A->merge($Bro); # must read Bro's tree without locking its PROT_READ map
is $A->point(2), 6, 'merge target keeps + adds its own item (1+5)';
is $A->point(9), 3, 'merged-in position present after merge from frozen other';
}
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.859 second using v1.01-cache-2.11-cpan-54e63673c56 )