#!/usr/bin/perl -w
BEGIN { use_ok(
'Data::Rmap'
); }
$Data::Dumper::Purity
=1;
our
$data
= {
'arrays'
=> [[
'shared'
,
'not_shared'
]],
'num'
=> 2,
'ref'
=> \
do
{
my
$a
=
'ref'
},
'hash'
=> {
'a'
=>
'vala'
,
'b'
=>
'valb'
,
'c'
=> {
qn
=>
'this'
},
},
'ref_to_hash'
=> \{
qn
=>
'that'
},
};
$data
->{share_ref} = \
$data
->{arrays}[0][0];
$data
->{another_obj} = \
do
{
my
$o
= ${
$data
->{ref_to_hash}}};
my
$orig_dump
= Dumper(
$data
);
rmap { }
$data
;
rmap_all { }
$data
;
rmap_scalar { }
$data
;
rmap_to { } HASH|ARRAY|SCALAR|REF|VALUE|GLOB,
$data
;
rmap_hash { }
$data
;
rmap_array { }
$data
;
ok(Dumper(
$data
) eq
$orig_dump
,
'nothing changed'
);
rmap {
$_
=
"#$_#"
; }
$data
; # all the leaves
ok(
$data
->{num} eq
'#2#'
,
"num #2#"
);
ok(
$data
->{arrays}[0][0] eq
'#shared#'
,
"done once #shared#"
);
ok(${
$data
->{
ref
}} eq
'#ref#'
,
"${$data->{ref}} eq '#ref#'"
);
ok(
$data
->{hash}{a} eq
'#vala#'
,
"nested hashes done #vala#"
);
ok(${
$data
->{ref_to_hash}}->{qn} eq
'#that#'
,
"ref_to_hash done #that#"
);
my
$count
= 1;
rmap_all {
cut
if
ref
(
$_
) eq
'ARRAY'
;
$_
=
"=\U$_="
if
!
ref
(
$_
);
$_
->{qnum} =
$count
++
if
ref
(
$_
) eq
'HASH'
&&
exists
$_
->{qn};
}
$data
;
ok(
$data
->{arrays}[0][1] eq
'#not_shared#'
,
'ARRAY cut'
);
ok(
$data
->{arrays}[0][0] eq
'=#SHARED#='
,
'cut one path only'
);
ok(
$data
->{hash}{a} eq
'=#VALA#='
,
'HASH not cut'
);
like(${
$data
->{ref_to_hash}}->{qnum},
qr/^=\d+=$/
,
'qnum added to qn'
);
$data
= [];
$data
->[0] =
"string"
;
$data
->[1] = \
$data
->[0];
$data
->[2] = \\
do
{
my
$s
=
"last"
};
rmap {
$_
=
"!$_"
}
$data
;
ok(
$data
->[0] eq
'!string'
,
"done once"
);
ok(${
$data
->[1]} eq
'!string'
,
"access via both paths"
);
ok(\
$data
->[0] == \${
$data
->[1]},
"still same ref"
);
ok($${
$data
->[2]} eq
'!last'
,
"got '!last'"
);
my
$ro_err
=
qr/^Modification of a read-only value attempted/
;
throws_ok { rmap {
$_
++ } 1 }
$ro_err
,
'read-only scalar'
;
throws_ok { rmap {
$_
++ } \1 }
$ro_err
,
'read-only scalar ref'
;
throws_ok { rmap {
$_
++ } [\1] }
$ro_err
,
'read-only scalar ref in array'
;
throws_ok { rmap {
$_
++ } {1,\1} }
$ro_err
,
'read-only scalar ref in hash'
;
*ro
= \1;
throws_ok { rmap {
$_
++ }
*ro
}
$ro_err
,
'read-only scalar ref in glob'
;
is_deeply([ rmap { ++
$_
} [1,2] ], [2,3],
'return altered pre-inc'
);
is_deeply([ rmap {
$_
++ } [1,2] ], [1,2],
'return not altered post-inc'
);
is(
scalar
(rmap { ++
$_
} [2..4]), 3,
'scalar context num items'
);
our
$rw
= 2;
is_deeply([ rmap { ++
$_
} [\
do
{
my
$a
= 1}, \
*rw
] ], [2,3],
'flattens return'
);
is_deeply([ rmap { ++
$_
} [1,[2]] ], [2,3],
'flattens 2'
);
is_deeply([ rmap_array { cut(
$_
->[0]) } [1,0],[2,0,[0]],[[3],0], {0,\[4]} ],
[ 1, 2, [3], 4 ],
'cut limits recursion'
);
is_deeply([ rmap { cut(++
$_
) } [1,2] ], [2,3],
'cut return altered pre-inc'
);
is_deeply([ rmap { ++
$_
; cut() } [1,2] ], [],
'cut can return nothing'
);
my
(
$array_dump
) = rmap_to {
return
$_
unless
ref
(
$_
);
'[ '
.
join
(
', '
,
$_
[0]->recurse() ) .
' ]'
;
} ARRAY|VALUE, [ 1, [ 2, [ [ 3 ], 4 ] ], 5 ];
is(
$array_dump
,
'[ 1, [ 2, [ [ 3 ], 4 ] ], 5 ]'
,
'dumper dumps'
);
my
$tree
= [
one
=>
two
=>
[
three_one
=>
three_two
=>
[
three_three_one
=>
],
three_four
=>
],
four
=>
[
[
five_one_one
=>
],
],
];
my
$got
=
''
;
our
@path
= (
'q'
);
rmap_to {
if
(
ref
$_
) {
local
(
@path
) = (
@path
, 1);
$_
[0]->recurse();
}
else
{
$got
.=
join
(
'.'
,
@path
) .
' '
;
}
$path
[-1]++;
} ARRAY|VALUE,
$tree
;
is(
$got
,
'q.1 q.2 q.3.1 q.3.2 q.3.3.1 q.3.4 q.4 q.5.1.1 '
,
'tree numbering w/ recurse'
);
local
*x
;
*x
= \3;
*x
=
sub
{};
*x
= {};
*x
= [];
my
@types
= (1, [], {}, \\2, \
*x
,
sub
{});
like(
join
(
' '
,
rmap {
$_
}
@types
),
qr/^1 2 3$/
,
'rmap types'
);
is(
join
(
' '
,
rmap_all { reftype(
$_
) ||
$_
}
@types
),
'1 ARRAY HASH REF SCALAR 2 GLOB SCALAR 3 ARRAY HASH'
,
'rmap_all types'
);
like(
join
(
' '
,
rmap_scalar {
$_
}
@types
),
qr/^1 (REF|SCALAR)\S+ SCALAR\S+ 2 SCALAR\S+ 3$/
,
'rmap_scalar types'
);
like(
join
(
' '
,
rmap_hash {
$_
}
@types
),
qr/^HASH\S+ HASH\S+$/
,
'rmap_hash types'
);
like(
join
(
' '
,
rmap_array {
$_
}
@types
),
qr/^ARRAY\S+ ARRAY\S+$/
,
'rmap_array types'
);
like(
join
(
' '
,
rmap_code {
$_
}
@types
),
qr/^CODE\S+ CODE\S+$/
,
'rmap_array types'
);
is(
join
(
' '
,
rmap_ref { reftype(
$_
) ||
$_
}
@types
),
'ARRAY HASH REF SCALAR SCALAR ARRAY HASH'
,
'rmap_ref types'
);
like(
join
(
' '
,
rmap_to {
$_
} GLOB|HASH,
@types
),
qr/^HASH\S+ GLOB\S+ HASH\S+$/
,
'rmap_to GLOB|HASH types'
);
like(
join
(
' '
,
rmap_to {
$_
} GLOB|CODE,
@types
),
qr/^GLOB\S+ CODE\S+ CODE\S+$/
,
'rmap_to GLOB|HASH types'
);