blob: e2f340bad9c3dabee4297505dca8e001725e56f3 [file] [log] [blame]
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#!/usr/bin/env perl
use strict;
use warnings;
use Avro::Schema;
use Avro::BinaryEncoder;
use Test::More;
use Test::Exception;
use IO::String;
use_ok 'Avro::BinaryDecoder';
## spec examples
{
my $enc = "\x06\x66\x6f\x6f";
my $schema = Avro::Schema->parse(q({ "type": "string" }));
my $reader = IO::String->new($enc);
my $dec = Avro::BinaryDecoder->decode(
writer_schema => $schema,
reader_schema => $schema,
reader => $reader,
);
is $dec, "foo", "Binary_Encodings.Primitive_Types";
$schema = Avro::Schema->parse(<<EOJ);
{
"type": "record",
"name": "test",
"fields" : [
{"name": "a", "type": "long"},
{"name": "b", "type": "string"}
]
}
EOJ
$reader = IO::String->new("\x36\x06\x66\x6f\x6f");
$dec = Avro::BinaryDecoder->decode(
writer_schema => $schema,
reader_schema => $schema,
reader => $reader,
);
is_deeply $dec, { a => 27, b => 'foo' },
"Binary_Encodings.Complex_Types.Records";
$reader = IO::String->new("\x04\x06\x36\x00");
$schema = Avro::Schema->parse(q({"type": "array", "items": "long"}));
$dec = Avro::BinaryDecoder->decode(
writer_schema => $schema,
reader_schema => $schema,
reader => $reader,
);
is_deeply $dec, [3, 27], "Binary_Encodings.Complex_Types.Arrays";
$reader = IO::String->new("\x02");
$schema = Avro::Schema->parse(q(["string","null"]));
$dec = Avro::BinaryDecoder->decode(
writer_schema => $schema,
reader_schema => $schema,
reader => $reader,
);
is $dec, undef, "Binary_Encodings.Complex_Types.Unions-null";
$reader = IO::String->new("\x00\x02\x61");
$dec = Avro::BinaryDecoder->decode(
writer_schema => $schema,
reader_schema => $schema,
reader => $reader,
);
is $dec, "a", "Binary_Encodings.Complex_Types.Unions-a";
}
## enum schema resolution
{
my $w_enum = Avro::Schema->parse(<<EOP);
{ "type": "enum", "name": "enum", "symbols": [ "a", "b", "c", "\$", "z" ] }
EOP
my $r_enum = Avro::Schema->parse(<<EOP);
{ "type": "enum", "name": "enum", "symbols": [ "\$", "b", "c", "d" ] }
EOP
ok ! !Avro::Schema->match( reader => $r_enum, writer => $w_enum ), "match";
my $enc;
for my $data (qw/b c $/) {
Avro::BinaryEncoder->encode(
schema => $w_enum,
data => $data,
emit_cb => sub { $enc = ${ $_[0] } },
);
my $dec = Avro::BinaryDecoder->decode(
writer_schema => $w_enum,
reader_schema => $r_enum,
reader => IO::String->new($enc),
);
is $dec, $data, "decoded!";
}
for my $data (qw/a z/) {
Avro::BinaryEncoder->encode(
schema => $w_enum,
data => $data,
emit_cb => sub { $enc = ${ $_[0] } },
);
throws_ok { Avro::BinaryDecoder->decode(
writer_schema => $w_enum,
reader_schema => $r_enum,
reader => IO::String->new($enc),
)} "Avro::Schema::Error::Mismatch", "schema problem";
}
}
## record resolution
{
my $w_schema = Avro::Schema->parse(<<EOJ);
{ "type": "record", "name": "test",
"fields" : [
{"name": "a", "type": "long"},
{"name": "bonus", "type": "string"} ]}
EOJ
my $r_schema = Avro::Schema->parse(<<EOJ);
{ "type": "record", "name": "test",
"fields" : [
{"name": "t", "type": "float", "default": 37.5 },
{"name": "a", "type": "long"} ]}
EOJ
my $data = { a => 1, bonus => "i" };
my $enc = '';
Avro::BinaryEncoder->encode(
schema => $w_schema,
data => $data,
emit_cb => sub { $enc .= ${ $_[0] } },
);
my $dec = Avro::BinaryDecoder->decode(
writer_schema => $w_schema,
reader_schema => $r_schema,
reader => IO::String->new($enc),
);
is $dec->{a}, 1, "easy";
ok ! exists $dec->{bonus}, "bonus extra field ignored";
is $dec->{t}, 37.5, "default t from reader used";
## delete the default for t
delete $r_schema->fields->[0]{default};
throws_ok {
Avro::BinaryDecoder->decode(
writer_schema => $w_schema,
reader_schema => $r_schema,
reader => IO::String->new($enc),
);
} "Avro::Schema::Error::Mismatch", "no default value!";
}
## union resolution
{
my $w_schema = Avro::Schema->parse(<<EOP);
[ "string", "null", { "type": "array", "items": "long" }]
EOP
my $r_schema = Avro::Schema->parse(<<EOP);
[ "boolean", "null", { "type": "array", "items": "double" }]
EOP
my $enc = '';
my $data = [ 1, 2, 3, 4, 5, 6 ];
Avro::BinaryEncoder->encode(
schema => $w_schema,
data => $data,
emit_cb => sub { $enc .= ${ $_[0] } },
);
my $dec = Avro::BinaryDecoder->decode(
writer_schema => $w_schema,
reader_schema => $r_schema,
reader => IO::String->new($enc),
);
is_deeply $dec, $data, "decoded!";
}
## map resolution
{
my $w_schema = Avro::Schema->parse(<<EOP);
{ "type": "map", "values": { "type": "array", "items": "string" } }
EOP
my $r_schema = Avro::Schema->parse(<<EOP);
{ "type": "map", "values": { "type": "array", "items": "int" } }
EOP
my $enc = '';
my $data = { "one" => [ "un", "one" ], two => [ "deux", "two" ] };
Avro::BinaryEncoder->encode(
schema => $w_schema,
data => $data,
emit_cb => sub { $enc .= ${ $_[0] } },
);
throws_ok {
Avro::BinaryDecoder->decode(
writer_schema => $w_schema,
reader_schema => $r_schema,
reader => IO::String->new($enc),
)
} "Avro::Schema::Error::Mismatch", "recursively... fails";
my $dec = Avro::BinaryDecoder->decode(
writer_schema => $w_schema,
reader_schema => $w_schema,
reader => IO::String->new($enc),
);
is_deeply $dec, $data, "decoded succeeded!";
}
## schema upgrade
{
my $w_schema = Avro::Schema->parse(<<EOP);
{ "type": "map", "values": { "type": "array", "items": "int" } }
EOP
my $r_schema = Avro::Schema->parse(<<EOP);
{ "type": "map", "values": { "type": "array", "items": "float" } }
EOP
my $enc = '';
my $data = { "one" => [ 1, 2 ], two => [ 1, 30 ] };
Avro::BinaryEncoder->encode(
schema => $w_schema,
data => $data,
emit_cb => sub { $enc .= ${ $_[0] } },
);
my $dec = Avro::BinaryDecoder->decode(
writer_schema => $w_schema,
reader_schema => $w_schema,
reader => IO::String->new($enc),
);
is_deeply $dec, $data, "decoded succeeded! +upgrade";
is $dec->{one}[0], 1.0, "kind of dumb test";
}
done_testing;