BEGIN {
$| = 1;
binmode
(Test::More->builder->
$_
,
":utf8"
)
for
qw/output failure_output todo_output/
;
}
our
@ISA
=
qw{ Exporter }
;
our
@EXPORT
=
qw{
run_all_testml_files
run_testml_file
test_yaml_roundtrip
test_perl_to_yaml
test_dump_error
test_load_error
test_load_warning
test_yaml_json
test_code_point
error_like
cmp_deeply
_testml_has_points
}
;
my
%ERROR
= (
E_CIRCULAR
=>
qr{\QYAML::As::Parsed does not support circular references}
,
E_FEATURE
=>
qr{\QYAML::As::Parsed does not support a feature}
,
E_PLAIN
=>
qr{\QYAML::As::Parsed found illegal characters in plain scalar}
,
E_CLASSIFY
=>
qr{\QYAML::As::Parsed failed to classify the line}
,
);
my
%WARN
= (
E_DUPKEY
=>
qr{\QYAML::As::Parsed found a duplicate key}
,
);
sub
run_all_testml_files {
my
(
$label
,
$dir
,
$bridge
,
@args
) =
@_
;
my
$code
=
sub
{
my
(
$file
,
$blocks
) =
@_
;
subtest
"$label: $file"
=>
sub
{
$bridge
->(
$_
,
@args
)
for
@$blocks
;
};
};
my
@files
= find_tml_files(
$dir
);
run_testml_file(
$_
,
$code
)
for
sort
@files
;
}
sub
run_testml_file {
my
(
$file
,
$code
) =
@_
;
my
$blocks
= TestML::Tiny->new(
testml
=>
$file
,
version
=>
'0.1.0'
,
)->{function}{data};
$code
->(
$file
,
$blocks
);
}
sub
_testml_has_points {
my
(
$block
,
@points
) =
@_
;
my
@values
;
for
my
$point
(
@points
) {
defined
$block
->{
$point
} or
return
;
push
@values
,
$block
->{
$point
};
}
push
@values
,
$block
->{Label};
return
@values
;
}
sub
test_yaml_roundtrip {
my
(
$block
) =
@_
;
my
(
$yaml
,
$perl
,
$label
) =
_testml_has_points(
$block
,
qw(yaml perl)
) or
return
;
my
%options
= ();
for
(
qw(serializes)
) {
if
(
defined
(
$block
->{
$_
})) {
$options
{
$_
} = 1;
}
}
my
$expected
=
eval
$perl
;
die
$@
if
$@;
bless
$expected
,
'YAML::As::Parsed'
;
subtest
$label
,
sub
{
my
$yaml_copy
=
$yaml
;
my
$got
=
eval
{ YAML::As::Parsed->read_string(
$yaml_copy
); };
is( $@,
''
,
"YAML::As::Parsed parses without error"
);
is(
$yaml_copy
,
$yaml
,
"YAML::As::Parsed does not modify the input string"
);
SKIP: {
skip(
"Shortcutting after failure"
, 2 )
if
$@;
isa_ok(
$got
,
'YAML::As::Parsed'
);
cmp_deeply(
$got
,
$expected
,
"YAML::As::Parsed parses correctly"
)
or diag
"ERROR: $YAML::As::Parsed::errstr\n\nYAML:$yaml"
;
}
my
$output
=
eval
{
$expected
->write_string };
is( $@,
''
,
"YAML::As::Parsed serializes without error"
);
SKIP: {
skip(
"Shortcutting after failure"
, 5 )
if
$@;
ok(
!!(
defined
$output
and !
ref
$output
),
"YAML::As::Parsed serializes to scalar"
,
);
my
$roundtrip
=
eval
{ YAML::As::Parsed->read_string(
$output
) };
is( $@,
''
,
"YAML::As::Parsed round-trips without error"
);
skip(
"Shortcutting after failure"
, 2 )
if
$@;
isa_ok(
$roundtrip
,
'YAML::As::Parsed'
);
cmp_deeply(
$roundtrip
,
$expected
,
"YAML::As::Parsed round-trips correctly"
);
skip(
"Shortcutting perfect serialization tests"
, 1 )
unless
$options
{serializes};
is(
$output
,
$yaml
,
'Serializes ok'
);
}
};
}
sub
test_perl_to_yaml {
my
(
$block
) =
@_
;
my
(
$perl
,
$yaml
,
$label
) =
_testml_has_points(
$block
,
qw(perl yaml)
) or
return
;
my
$input
=
eval
"no strict; $perl"
;
die
$@
if
$@;
subtest
$label
,
sub
{
my
$result
=
eval
{ YAML::As::Parsed->new(
@$input
)->write_string };
is( $@,
''
,
"write_string lives"
);
is(
$result
,
$yaml
,
"dumped YAML correct"
);
};
}
sub
test_dump_error {
my
(
$block
) =
@_
;
my
(
$perl
,
$error
,
$label
) =
_testml_has_points(
$block
,
qw(perl error)
) or
return
;
my
$input
=
eval
"no strict; $perl"
;
die
$@
if
$@;
chomp
$error
;
my
$expected
=
$ERROR
{
$error
};
subtest
$label
,
sub
{
my
$result
=
eval
{ YAML::As::Parsed->new(
@$input
)->write_string };
ok( !
$result
,
"returned false"
);
error_like(
$expected
,
"Got expected error"
);
};
}
sub
test_load_error {
my
(
$block
) =
@_
;
my
(
$yaml
,
$error
,
$label
) =
_testml_has_points(
$block
,
qw(yaml error)
) or
return
;
chomp
$error
;
my
$expected
=
$ERROR
{
$error
};
subtest
$label
,
sub
{
my
$result
=
eval
{ YAML::As::Parsed->read_string(
$yaml
) };
is(
$result
,
undef
,
'read_string returns undef'
);
error_like(
$expected
,
"Got expected error"
)
or diag
"YAML:\n$yaml"
;
};
}
sub
test_load_warning {
my
(
$block
) =
@_
;
my
(
$yaml
,
$warning
,
$label
) =
_testml_has_points(
$block
,
qw(yaml warning)
) or
return
;
chomp
$warning
;
my
$expected
=
$WARN
{
$warning
};
subtest
$label
,
sub
{
my
@warnings
;
local
$SIG
{__WARN__} =
sub
{
push
@warnings
,
shift
; };
my
$result
=
eval
{ YAML::As::Parsed->read_string(
$yaml
) };
is(
scalar
(
@warnings
), 1,
'got exactly one warning'
);
like(
$warnings
[0],
$expected
,
'Got expected warning'
,
) or diag
"YAML:\n$yaml\n"
,
'warning: '
, explain(\
@warnings
);
};
}
sub
test_yaml_json {
my
(
$block
,
$json_lib
) =
@_
;
$json_lib
||=
do
{
require
JSON::PP;
'JSON::PP'
};
my
(
$yaml
,
$json
,
$label
) =
_testml_has_points(
$block
,
qw(yaml json)
) or
return
;
subtest
"$label"
,
sub
{
my
$object
=
eval
{
YAML::As::Parsed::Load(
$yaml
);
};
my
$err
= $@;
ok !
$err
,
"YAML loads"
;
return
if
$err
;
my
$want
=
$json_lib
->new->encode(
$json_lib
->new->decode(
$json
)
);
my
$got
=
$json_lib
->new->encode(
$object
);
is
$got
,
$want
,
"Load is accurate"
;
};
}
sub
test_code_point {
my
(
$block
) =
@_
;
my
(
$code
,
$yaml
,
$label
) =
_testml_has_points(
$block
,
qw(code yaml)
) or
return
;
subtest
"$label - Unicode map key/value test"
=>
sub
{
my
$data
= {
chr
(
$code
) =>
chr
(
$code
) };
my
$dump
= YAML::As::Parsed::Dump(
$data
);
$dump
=~ s/^---\n//;
is
$dump
,
$yaml
,
"Dump key and value of code point char $code"
;
my
$yny
= YAML::As::Parsed::Dump(YAML::As::Parsed::Load(
$yaml
));
$yny
=~ s/^---\n//;
is
$yny
,
$yaml
,
"YAML for code point $code YNY roundtrips"
;
my
$nyn
= YAML::As::Parsed::Load(YAML::As::Parsed::Dump(
$data
));
cmp_deeply(
$nyn
,
$data
,
"YAML for code point $code NYN roundtrips"
);
}
}
sub
error_like {
my
(
$regex
,
$label
) =
@_
;
$label
=
"Got expected error"
unless
defined
$label
;
local
$Test::Builder::Level
=
$Test::Builder::Level
+ 1;
my
$ok
= like( $@,
$regex
,
$label
);
return
$ok
;
}
sub
cmp_deeply {
my
(
$got
,
$want
,
$label
) =
@_
;
local
$Test::Builder::Level
=
$Test::Builder::Level
+ 1;
is_deeply(
$got
,
$want
,
$label
)
or diag
"GOT:\n"
, explain(
$got
),
"\nWANTED:\n"
, explain(
$want
);
}
1;