%PDF- %PDF-
| Direktori : /home/opti/optisoftcom/.cpanm/work/1544535406.20768/BSON-v1.10.2/t/lib/ |
| Current File : /home/opti/optisoftcom/.cpanm/work/1544535406.20768/BSON-v1.10.2/t/lib/CorpusTest.pm |
use 5.010001;
use strict;
use warnings;
use Test::More 0.96;
use Test::Deep qw/!blessed/;
# Hijack the JSON::PP::USE_B constant to enable svtype detection
BEGIN {
no warnings 'redefine';
require constant;
my $orig = constant->can('import');
local *constant::import = sub {
if ($_[1] eq 'USE_B') {
pop(@_);
push(@_, 1)
}
goto &$orig;
};
require JSON::PP;
die "TOO LATE"
unless JSON::PP::USE_B();
}
use JSON::PP 2.97001;
use BSON;
use BSON::Types ':all';
use Config;
use Path::Tiny 0.054; # better basename
use Data::Dumper;
# from t/lib
use TestUtils;
use constant {
IS_JSON_PP => 1,
};
use base 'Exporter';
our @EXPORT = qw/test_corpus_file/;
binmode( Test::More->builder->$_, ":utf8" )
for qw/output failure_output todo_output/;
# overridden to allow Tie::IxHash hashes to be created by JSON::PP
my $orig = JSON::PP->can("object")
or die "Unable to find JSON::PP::object to override";
do {
no warnings 'redefine';
*JSON::PP::object = sub {
tie my %hash, 'Tie::IxHash';
my $value = $orig->(\%hash);
return $value;
};
};
my $JSON = JSON::PP
->new
->ascii
->allow_bignum
->allow_blessed
->convert_blessed;
sub test_corpus_file {
my ($file) = @_;
local $Test::Builder::Level = $Test::Builder::Level + 1;
my $f = path( "corpus", $file );
my $base = $f->basename;
my $json = eval { decode_json( $f->slurp ) };
if ( my $err = $@ ) {
fail("$base failed to load");
diag($err);
return;
}
subtest 'JSON::PP Tie::IxHash injection' => sub {
my $data = $JSON->decode('{"x":23}');
ok defined(tied %$data), 'JSON::PP returns tied objects';
};
_validity_tests($json);
_decode_error_tests($json);
_parse_error_tests($json);
}
sub _validity_tests {
my ($json) = @_;
local $Test::Builder::Level = $Test::Builder::Level + 1;
# suppress caching that throws off Test::Deep
local $BSON::Types::NoCache = 1;
my $bson_type = $json->{bson_type};
my $deprecated = $json->{deprecated};
for my $case ( @{ $json->{valid} } ) {
subtest 'case: '.$case->{description} => sub {
local $Data::Dumper::Useqq = 1;
my $wrap = $bson_type =~ /\A(?:0x00|0x01|0x10|0x12)\z/;
my $codec = BSON->new( prefer_numeric => 1, wrap_numbers => $wrap, ordered => 1 );
my $lossy = $case->{lossy};
my $canonical_bson = $case->{canonical_bson};
my $converted_bson = $case->{converted_bson};
my $degenerate_bson = $case->{degenerate_bson};
$canonical_bson = pack('H*', $canonical_bson);
$converted_bson = pack('H*', $converted_bson)
if defined $converted_bson;
$degenerate_bson = pack('H*', $degenerate_bson)
if defined $degenerate_bson;
my $canonical_json = $case->{canonical_extjson};
my $converted_json = $case->{converted_extjson};
my $degenerate_json = $case->{degenerate_extjson};
my $relaxed_json = $case->{relaxed_extjson};
$canonical_json = _normalize(
$canonical_json,
'$desc: normalizing canonical extjson',
);
$converted_json = _normalize(
$converted_json,
'$desc: normalizing converted extjson',
);
$degenerate_json = _normalize(
$degenerate_json,
'$desc: normalizing degenerate extjson',
);
$relaxed_json = _normalize(
$relaxed_json,
'$desc: normalizing relaxed extjson',
);
##
## for cB input (canonical BSON)
##
bytes_are(
_native_to_bson($codec,
_bson_to_native($codec, $canonical_bson),
),
$deprecated
? $converted_bson
: $canonical_bson,
'native_to_bson(bson_to_native(cB)) = cB',
);
is(
_normalize_numbers(
_native_to_canonical_extended_json($codec,
_bson_to_native($codec, $canonical_bson),
)
),
_normalize_numbers(
$deprecated
? $converted_json
: $canonical_json,
),
'native_to_canonical_extended_json(bson_to_native(cB)) = cEJ',
);
is(
_normalize_numbers(
_native_to_relaxed_extended_json($codec,
_bson_to_native($codec, $canonical_bson),
)
),
_normalize_numbers($relaxed_json),
'native_to_relaxed_extended_json(bson_to_native(cB)) = rEJ',
) unless not defined $relaxed_json;
##
## for cEJ input (canonical Extended JSON)
##
is(
_normalize_numbers(
_native_to_canonical_extended_json($codec,
_extjson_to_native($codec, $canonical_json),
)
),
_normalize_numbers(
$deprecated
? $converted_json
: $canonical_json,
),
'native_to_canonical_extended_json(json_to_native(cEJ)) = cEJ',
);
bytes_are(
_native_to_bson($codec,
_extjson_to_native($codec, $canonical_json),
),
$deprecated
? $converted_bson
: $canonical_bson,
'native_to_bson(json_to_native(cEJ)) = cB'
) unless $lossy;
##
## for dB input (degenerate BSON)
##
if (defined $degenerate_bson) {
bytes_are(
_native_to_bson($codec,
_bson_to_native($codec, $degenerate_bson),
),
$canonical_bson,
'native_to_bson(bson_to_native(dB)) = cB',
)
}
##
## for dEJ input (degenerate Extended JSON)
##
if (defined $degenerate_json) {
is(
_normalize_numbers(
_native_to_canonical_extended_json($codec,
_extjson_to_native($codec, $degenerate_json),
)
),
_normalize_numbers(
$deprecated
? $converted_json
: $canonical_json,
),
'native_to_canonical_extended_json(json_to_native(dEJ)) = cEJ',
);
bytes_are(
_native_to_bson($codec,
_extjson_to_native($codec, $degenerate_json),
),
$deprecated
? $converted_bson
: $canonical_bson,
'native_to_bson(json_to_native(dEJ)) = cB'
) unless $lossy;
}
##
## for rEJ input (relaxed Extended JSON)
##
if (defined $relaxed_json) {
is(
_normalize_numbers(
_native_to_relaxed_extended_json($codec,
_extjson_to_native($codec, $relaxed_json),
)
),
_normalize_numbers($relaxed_json),
'native_to_relaxed_extended_json(json_to_native(rEJ)) = rEJ',
);
}
};
}
return;
}
sub _normalize {
my ($json, $desc) = @_;
return unless defined $json;
try_or_fail(
sub {
$json = to_myjson( $JSON->decode( $json ) );
},
$desc
) or next;
return $json;
}
sub _normalize_numbers {
my ($value) = @_;
return undef unless defined $value;
$value =~ s{"0.0"}{"0"}g;
$value =~ s{"-0.0"}{"0"}g;
$value =~ s{"-0"}{"0"}g;
$value =~ s{"1.0"}{"1"}g;
$value =~ s{"-1.0"}{"-1"}g;
$value =~ s[{"d":-0.0}][{"d":0}]g;
$value =~ s[{"d":-0}][{"d":0}]g;
$value =~ s[{"d":0.0}][{"d":0}]g;
$value =~ s[(-?)1\.2345\d+(?:[eE]\+\d+)?][${1}1234567890...]g;
$value =~ s[-1234567890123456768][-1234567890...]g;
$value =~ s[1234567890123456768][1234567890...]g;
# Power8 specific normalization
$value =~ s[-1234567890123456770][-1234567890...]g;
$value =~ s[1234567890123456770][1234567890...]g;
return $value;
}
sub _native_to_bson {
my ($codec, $native) = @_;
my $bson;
try_or_fail(
sub { $bson = $codec->encode_one($native) },
q{Couldn't convert from native Perl to BSON},
) or return undef;
return $bson;
}
sub _bson_to_native {
my ($codec, $bson) = @_;
my $native;
try_or_fail(
sub { $native = $codec->decode_one($bson) },
q{Couldn't convert from BSON to native Perl},
) or return undef;
return $native;
}
sub _extjson_to_native {
my ($codec, $extjson) = @_;
my $native_extjson;
try_or_fail(
sub { $native_extjson = $JSON->decode($extjson) },
q{Couldn't decode JSON to native ExtJSON},
) or return undef;
my $native;
try_or_fail(
sub { $native = $codec->extjson_to_perl($native_extjson) },
q{Couldn't convert from native ExtJSON to native Perl},
) or return undef;
return $native;
}
sub _native_to_relaxed_extended_json {
my ($codec, $native) = @_;
my $native_extjson;
try_or_fail(
sub { $native_extjson = $codec->perl_to_extjson($native, {relaxed => 1}) },
q{Couldn't convert from native Perl to native relaxed ExtJSON},
) or return undef;
my $extjson;
try_or_fail(
sub { $extjson = $JSON->encode($native_extjson) },
q{Couldn't encode native ExtJSON as JSON},
) or return undef;
return $extjson;
}
sub _native_to_canonical_extended_json {
my ($codec, $native) = @_;
my $native_extjson;
try_or_fail(
sub { $native_extjson = $codec->perl_to_extjson($native, {relaxed => 0}) },
q{Couldn't convert from native Perl to native canonical ExtJSON},
) or return undef;
my $extjson;
try_or_fail(
sub { $extjson = $JSON->encode($native_extjson) },
q{Couldn't encode native ExtJSON as JSON},
) or return undef;
return $extjson;
}
sub _decode_error_tests {
my ($json) = @_;
local $Test::Builder::Level = $Test::Builder::Level + 1;
return unless $json->{decodeErrors};
for my $case ( @{ $json->{decodeErrors} } ) {
my $desc = $case->{description};
my $bson = pack( "H*", $case->{bson} );
eval { BSON::decode($bson) };
ok( length($@), "Decode error: $desc:" );
}
}
my %PARSER = (
'0x00' => sub { bson_doc(shift) },
'0x13' => sub { bson_decimal128(shift) },
);
sub _parse_error_tests {
my ($json) = @_;
local $Test::Builder::Level = $Test::Builder::Level + 1;
my $parser = $PARSER{$json->{bson_type}};
if ( $json->{parseErrors} && !$parser ) {
BAIL_OUT("No parseError parser available for $json->{bson_type}");
}
for my $case ( @{ $json->{parseErrors} } ) {
eval { $parser->($case->{string}) };
ok( $@, "$case->{description}: parse should throw an error " )
or diag "Input was: $case->{string}";
}
}
1;
#
# This file is part of BSON
#
# This software is Copyright (c) 2018 by Stefan G. and MongoDB, Inc.
#
# This is free software, licensed under:
#
# The Apache License, Version 2.0, January 2004
#
# vim: set ts=4 sts=4 sw=4 et tw=75: