Skip to content

Instantly share code, notes, and snippets.

@renormalist
Last active September 13, 2019 14:54
Show Gist options
  • Save renormalist/6fca277d079f1eaf20ad653a962681a6 to your computer and use it in GitHub Desktop.
Save renormalist/6fca277d079f1eaf20ad653a962681a6 to your computer and use it in GitHub Desktop.
Comparing YAML parsers for edge cases between hash and scalar with empty value
use strict;
use warnings;
use Test::More;
use Test::Deep 'cmp_deeply', 'any';
use Iterator::Simple 'iter';
use TAP::Parser::YAMLish::Reader;
use Data::YAML::Reader;
use YAML::Tiny;
use YAML::Syck;
use YAML::Old;
use YAML::XS;
use YAML::PP;
use Data::Dumper;
my @yaml_snippets = (
{
# normal behaviour
description => 'nested hash with correct indentation',
lines => [
'---',
'one:',
' two:',
' three: 3',
' four: 4',
' five: 5',
'six: 6',
'...',
],
expected => {
one => {
two => {
three => 3,
four => 4,
},
five => 5,
},
six => 6,
},
},
{
# normal behaviour
description => 'flat hash',
lines => [
'---',
'one:',
' two: 2',
' three: 3',
' four: 4',
' five: 5',
'six: 6',
'...',
],
expected => {
one => {
two => 2,
three => 3,
four => 4,
five => 5,
},
six => 6,
},
},
{
# The Trouble behaviour in TAP::Parser::YAMLish (and its spin-off
# Data::YAML::Reader)
#
# Missing value should NOT introduce new nesting, only indentation
# of next lines would, as in first snippet above.
description => 'flat hash with a missing value',
lines => [
'---',
'one:',
' two:',
' three: 3',
' four: 4',
' five: 5',
'six: 6',
'...',
],
expected => {
one => {
# ::Old, ::Syck, and ::XS gets undef
# (which fits yaml 1.2/1.1 spec),
# other modules get ''.
# I'm fine with both.
two => any(undef, ''),
three => 3,
four => 4,
five => 5,
},
six => 6,
},
},
);
sub compare {
my ($data, $y, $hint) = @_;
my $ok = cmp_deeply ($data, $y->{expected}, $y->{description}." - $hint");
diag "data: ".Dumper($data) if !$ok;
}
sub test_TAP_PARSER_YAMLish_Reader {
my ($y) = @_;
my $yaml = TAP::Parser::YAMLish::Reader->new();
my $iterator = iter ($y->{lines});
my $reader = sub { $iterator->next };
my $data = $yaml->read($reader);
compare ($data, $y, "TAP::Parser::YAMLish::Reader");
}
sub test_Data_YAML_Reader {
my ($y) = @_;
my $yaml = Data::YAML::Reader->new;
my @copy = @{$y->{lines}}; # the read() below eats up its input
my $data = $yaml->read(\@copy);
compare ($data, $y, "Data::YAML::Reader");
}
sub test_YAML_Tiny {
my ($y) = @_;
my $data = YAML::Tiny->read_string(join("\n", @{$y->{lines}}));
compare ($data->[0], $y, "YAML::Tiny");
}
sub test_YAML_Syck {
my ($y) = @_;
my $data = YAML::Syck::Load(join("\n",
grep { $_ ne '...' }
@{$y->{lines}}));
compare ($data, $y, "YAML::Syck");
}
sub test_YAML_Old {
my ($y) = @_;
my $data = YAML::Old::Load(join("\n",
grep { $_ ne '...' }
@{$y->{lines}}));
compare ($data, $y, "YAML::Old");
}
sub test_YAML_XS {
my ($y) = @_;
my $data = YAML::XS::Load(join("\n", @{$y->{lines}}));
compare ($data, $y, "YAML::XS");
}
sub test_YAML_PP {
my ($y) = @_;
my $ypp = YAML::PP->new;
my $data = $ypp->load_string(join("\n", @{$y->{lines}}));
compare ($data, $y, "YAML::PP");
}
foreach my $y (@yaml_snippets) {
test_TAP_PARSER_YAMLish_Reader ($y);
test_Data_YAML_Reader ($y);
test_YAML_Tiny ($y);
test_YAML_Syck ($y);
test_YAML_Old ($y);
test_YAML_XS ($y);
test_YAML_PP ($y);
}
done_testing();
@renormalist
Copy link
Author

Ewww, how strange. I will update the gist if I can. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment