Char-Replace
view release on metacpan or search on metacpan
t/coderef-map.t view on Meta::CPAN
{
note "code ref returning single char (1:1 replacement)";
my @map = fresh_map();
$map[ ord('a') ] = sub { "X" };
is Char::Replace::replace( "aaa", \@map ), "XXX",
q[code ref: single-char return on repeated chars];
}
{
note "stateful code ref (counter)";
my $count = 0;
my @map = fresh_map();
$map[ ord('a') ] = sub { ++$count; "A$count" };
is Char::Replace::replace( "abab", \@map ), "A1bA2b",
q[stateful code ref: counter increments];
}
{
note "code ref with no map entries (identity behavior)";
my @map = fresh_map();
is Char::Replace::replace( "hello", \@map ), "hello",
q[no code ref entries: identity];
}
{
note "code ref at boundary: map index 0 (null byte)";
my @map = fresh_map();
$map[0] = sub { "NULL" };
my $input = "a\0b";
is Char::Replace::replace( $input, \@map ), "aNULLb",
q[code ref at index 0: null byte replaced];
}
{
note "code ref at boundary: map index 255";
my @map = fresh_map();
$map[255] = sub { "FF" };
my $input = "a" . chr(255) . "b";
utf8::downgrade($input);
is Char::Replace::replace( $input, \@map ), "aFFb",
q[code ref at index 255: high byte replaced];
}
{
note "code ref that dies propagates error cleanly";
my @map = fresh_map();
$map[ ord('a') ] = sub { die "callback error" };
my $died = !eval { Char::Replace::replace( "abc", \@map ); 1 };
ok $died, q[die in callback propagates to caller];
like $@, qr/callback error/, q[original error message preserved];
}
{
note "code ref die does not leak memory (no crash after many iterations)";
my @map = fresh_map();
$map[ ord('a') ] = sub { die "leak test" };
for (1..1000) {
eval { Char::Replace::replace( "abc", \@map ) };
}
pass q[1000 die-in-callback iterations: no crash or corruption];
}
done_testing;
( run in 1.484 second using v1.01-cache-2.11-cpan-96521ef73a4 )