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 )