blob: 2db5bfd03ec86197c71032488343aadde8832179 [file]
<?php
/**
* 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
*
* https://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.
*/
declare(strict_types=1);
namespace Apache\Avro\Tests;
use Apache\Avro\AvroException;
use Apache\Avro\Schema\AvroSchema;
use Apache\Avro\Schema\AvroSchemaParseException;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
class SchemaExample
{
public string $name;
public string $normalizedSchemaString;
public function __construct(
public string $schemaString,
public bool $isValid,
?string $normalizedSchemaString = null,
?string $name = null,
public ?string $comment = null
) {
$this->name = $name ?: $this->schemaString;
$this->normalizedSchemaString = $normalizedSchemaString ?: json_encode(json_decode((string) $this->schemaString, true));
}
}
class SchemaTest extends TestCase
{
/** @var array<SchemaExample> */
private static array $examples = [];
public function test_json_decode(): void
{
$this->assertEquals(null, json_decode('null', true));
$this->assertEquals(32, json_decode('32', true));
$this->assertEquals('32', json_decode('"32"', true));
$this->assertEquals(["foo" => 27], (array) json_decode('{"foo": 27}'));
$this->assertIsArray(json_decode('{"foo": 27}', true));
$this->assertEquals(["foo" => 27], json_decode('{"foo": 27}', true));
$this->assertEquals(
["bar", "baz", "blurfl"],
json_decode('["bar", "baz", "blurfl"]', true)
);
$this->assertIsNotArray(json_decode('null', true));
$this->assertEquals(["type" => 'null'], json_decode('{"type": "null"}', true));
// PHP now only accept lowercase true, and rejects TRUE etc.
// https://php.net/manual/en/migration56.incompatible.php#migration56.incompatible.json-decode
$this->assertEquals(true, json_decode('true', true), 'true');
$this->assertEquals('boolean', json_decode('"boolean"'));
}
/**
* @return array<array<SchemaExample>>
*/
public static function schema_examples_provider(): array
{
self::make_examples();
$ary = [];
foreach (self::$examples as $example) {
$ary[] = [$example];
}
return $ary;
}
#[DataProvider('schema_examples_provider')]
public function test_parse(SchemaExample $example): void
{
$schema_string = $example->schemaString;
try {
$normalized_schema_string = $example->normalizedSchemaString;
$schema = AvroSchema::parse($schema_string);
$this->assertTrue(
$example->isValid,
sprintf(
"schema_string: %s\n",
$schema_string
)
);
$this->assertEquals($normalized_schema_string, (string) $schema);
} catch (AvroSchemaParseException $e) {
$this->assertFalse(
$example->isValid,
sprintf(
"schema_string: %s\n%s",
$schema_string,
$e->getMessage()
)
);
}
}
public function test_to_avro_includes_aliases(): void
{
$hash = <<<SCHEMA
{
"type": "record",
"name": "test_record",
"aliases": ["alt_record"],
"fields": [
{ "name": "f", "type": { "type": "fixed", "size": 2, "name": "test_fixed", "aliases": ["alt_fixed"] } },
{ "name": "e", "type": { "type": "enum", "symbols": ["A", "B"], "name": "test_enum", "aliases": ["alt_enum"] } }
]
}
SCHEMA;
$schema = AvroSchema::parse($hash);
$this->assertEquals($schema->toAvro(), json_decode($hash, true));
}
public function test_validate_field_aliases(): void
{
$this->expectException(AvroSchemaParseException::class);
$this->expectExceptionMessage('Invalid aliases value. Must be an array of strings.');
AvroSchema::parse(
<<<JSON
{
"type": "record",
"name": "fruits",
"fields": [
{
"name": "banana",
"type": "string",
"aliases": "banane"
}
]
}
JSON
);
}
public function test_validate_record_aliases(): void
{
$this->expectException(AvroSchemaParseException::class);
$this->expectExceptionMessage('Invalid aliases value. Must be an array of strings.');
AvroSchema::parse(
<<<JSON
{
"type": "record",
"name": "fruits",
"aliases": ["foods", 2],
"fields": []
}
JSON
);
}
public function test_validate_fixed_aliases(): void
{
$this->expectException(AvroSchemaParseException::class);
$this->expectExceptionMessage('Invalid aliases value. Must be an array of strings.');
AvroSchema::parse(
<<<JSON
{
"type": "fixed",
"name": "uuid",
"size": 36,
"aliases": "unique_id"
}
JSON
);
}
public function test_validate_enum_aliases(): void
{
$this->expectException(AvroSchemaParseException::class);
$this->expectExceptionMessage('Invalid aliases value. Must be an array of strings.');
AvroSchema::parse(<<<SCHEMA
{
"type": "enum",
"name": "vowels",
"aliases": [1, 2],
"symbols": ["A", "E", "I", "O", "U"]
}
SCHEMA);
}
public function test_validate_same_alias_multiple_fields(): void
{
$this->expectException(AvroSchemaParseException::class);
$this->expectExceptionMessage('Alias already in use');
AvroSchema::parse(<<<SCHEMA
{
"type": "record",
"name": "fruits",
"fields": [
{"name": "banana", "type": "string", "aliases": [ "yellow" ]},
{"name": "lemo", "type": "string", "aliases": [ "yellow" ]}
]
}
SCHEMA);
}
public function test_validate_repeated_aliases(): void
{
$this->expectNotToPerformAssertions();
AvroSchema::parse(
<<<JSON
{
"type": "record",
"name": "fruits",
"fields": [
{
"name": "banana",
"type": "string",
"aliases": [
"yellow",
"yellow"
]
}
]
}
JSON
);
}
public function test_doc_attribute_on_primitive_fields(): void
{
$schemaJson = <<<JSON
{
"type": "record",
"name": "fruits",
"fields": [
{
"name": "banana",
"type": "string",
"doc": "This is a banana"
}
]
}
JSON;
$schema = AvroSchema::parse($schemaJson);
self::assertEquals(json_decode($schemaJson, associative: true), $schema->toAvro());
}
public function test_invalid_doc_attribute_on_field_throws_an_exception(): void
{
$schemaJson = <<<JSON
{
"type": "record",
"name": "fruits",
"fields": [
{
"name": "banana",
"type": "string",
"doc": 1
}
]
}
JSON;
$this->expectException(AvroSchemaParseException::class);
AvroSchema::parse($schemaJson);
}
public function test_logical_types_in_record(): void
{
$avro = <<<JSON
{
"type": "record",
"name": "fruits",
"fields": [
{
"name": "UUID",
"type": {
"type": "string",
"logicalType": "uuid"
}
},
{
"name": "decimal",
"type": {
"type": "bytes",
"logicalType": "decimal",
"precision": 6,
"scale": 2
}
},
{
"name": "date",
"type": {
"type": "int",
"logicalType": "date"
}
},
{
"name": "timeMillis",
"type": {
"type": "int",
"logicalType": "time-millis"
}
},
{
"name": "timeMicros",
"type": {
"type": "long",
"logicalType": "time-micros"
}
},
{
"name": "timestampMillis",
"type": {
"type": "long",
"logicalType": "timestamp-millis"
}
},
{
"name": "timestampMicros",
"type": {
"type": "long",
"logicalType": "timestamp-micros"
}
},
{
"name": "localTimestampMillis",
"type": {
"type": "long",
"logicalType": "local-timestamp-millis"
}
},
{
"name": "localTimestampMicros",
"type": {
"type": "long",
"logicalType": "local-timestamp-micros"
}
},
{
"name": "duration",
"type": {
"name": "inner_fixed",
"type": "fixed",
"size": 12,
"logicalType": "duration"
}
}
]
}
JSON;
$schema = AvroSchema::parse($avro);
self::assertEquals($schema->toAvro(), json_decode($avro, true));
}
public static function invalidDecimalLogicalTypeDataProvider(): array
{
return [
'bytes - invalid precision' => [
'{"type": "bytes", "logicalType": "decimal", "precision": -1, "scale": 2}',
new AvroException("Precision '-1' is invalid. It must be a positive integer."),
],
'bytes - invalid value for precision (float)' => [
'{"type": "bytes", "logicalType": "decimal", "precision": 11.23, "scale": 2}',
new AvroException("Invalid value '11.23' for 'precision' attribute of decimal logical type."),
],
'bytes - invalid value for precision (string)' => [
'{"type": "bytes", "logicalType": "decimal", "precision": "banana", "scale": 2}',
new AvroException("Invalid value 'banana' for 'precision' attribute of decimal logical type."),
],
'bytes - invalid scale' => [
'{"type": "bytes", "logicalType": "decimal", "precision": 2, "scale": -1}',
new AvroException("Scale '-1' is invalid. It must be a non-negative integer."),
],
'bytes - invalid scale for precision' => [
'{"type": "bytes", "logicalType": "decimal", "precision": 2, "scale": 2}',
new AvroException("Scale must be a lower than precision (scale='2', precision='2')."),
],
'bytes - invalid value for scale (float)' => [
'{"type": "bytes", "logicalType": "decimal", "precision": 2, "scale": 9.12}',
new AvroException("Invalid value '9.12' for 'scale' attribute of decimal logical type."),
],
'bytes - invalid value for scale (string)' => [
'{"type": "bytes", "logicalType": "decimal", "precision": 2, "scale": "two"}',
new AvroException("Invalid value 'two' for 'scale' attribute of decimal logical type."),
],
'fixed - invalid precision' => [
'{"name": "fixed_decimal", "type": "fixed", "logicalType": "decimal", "size": 2, "precision": -1, "scale": 2}',
new AvroException("Precision '-1' is invalid. It must be a positive integer."),
],
'fixed - invalid value for precision with specified size' => [
'{"name": "fixed_decimal", "type": "fixed", "logicalType": "decimal", "size": 2, "precision": 6, "scale": 2}',
new AvroException("Invalid precision for specified fixed size (size='2', precision='6')."),
],
];
}
#[DataProvider('invalidDecimalLogicalTypeDataProvider')]
public function test_decimal_logical_type_with_invalid_parameters(string $schema, AvroException $exception): void
{
$this->expectException($exception::class);
$this->expectExceptionMessage($exception->getMessage());
AvroSchema::parse($schema);
}
protected static function make_examples(): void
{
$primitive_examples = array_merge(
[
new SchemaExample(
'"True"',
false
),
new SchemaExample(
'{"no_type": "test"}',
false
),
new SchemaExample(
'{"type": "panther"}',
false
),
],
self::makePrimitiveExamples()
);
$array_examples = [
new SchemaExample('{"type": "array", "items": "long"}', true),
new SchemaExample(
<<<JSON
{
"type":"array",
"items":{
"type":"enum",
"name":"Test",
"symbols":[
"A",
"B"
]
}
}
JSON,
true
),
];
$map_examples = [
new SchemaExample(
'{"type": "map", "values": "long"}',
true
),
new SchemaExample(
<<<JSON
{
"type":"map",
"values":{
"type":"enum",
"name":"Test",
"symbols":[
"A",
"B"
]
}
}
JSON,
true
),
];
$union_examples = [
new SchemaExample('["string", "null", "long"]', true),
new SchemaExample('["null", "null"]', false),
new SchemaExample('["long", "long"]', false),
new SchemaExample(
'[{"type": "array", "items": "long"} {"type": "array", "items": "string"}]',
false
),
new SchemaExample(
'["long", {"type": "long"}, "int"]',
false
),
new SchemaExample(
<<<JSON
[
"long",
{
"type":"array",
"items":"long"
},
{
"type":"map",
"values":"long"
},
"int"
]
JSON,
true
),
new SchemaExample(
'["long", ["string", "null"], "int"]',
false
),
new SchemaExample(
'["long", ["string", "null"], "int"]',
false
),
new SchemaExample(
<<<JSON
[
"null",
"boolean",
"int",
"long",
"float",
"double",
"string",
"bytes",
{
"type":"array",
"items":"int"
},
{
"type":"map",
"values":"int"
},
{
"name":"bar",
"type":"record",
"fields":[
{
"name":"label",
"type":"string"
}
]
},
{
"name":"foo",
"type":"fixed",
"size":16
},
{
"name":"baz",
"type":"enum",
"symbols":[
"A",
"B",
"C"
]
}
]
JSON,
true,
'["null","boolean","int","long","float","double","string","bytes",{"type":"array","items":"int"},{"type":"map","values":"int"},{"type":"record","name":"bar","fields":[{"name":"label","type":"string"}]},{"type":"fixed","name":"foo","size":16},{"type":"enum","name":"baz","symbols":["A","B","C"]}]'
),
new SchemaExample(
<<<JSON
[
{
"name":"subtract",
"namespace":"com.example",
"type":"record",
"fields":[
{
"name":"minuend",
"type":"int"
},
{
"name":"subtrahend",
"type":"int"
}
]
},
{
"name":"divide",
"namespace":"com.example",
"type":"record",
"fields":[
{
"name":"quotient",
"type":"int"
},
{
"name":"dividend",
"type":"int"
}
]
},
{
"type":"array",
"items":"string"
}
]
JSON,
true,
'[{"type":"record","name":"subtract","namespace":"com.example","fields":[{"name":"minuend","type":"int"},{"name":"subtrahend","type":"int"}]},{"type":"record","name":"divide","namespace":"com.example","fields":[{"name":"quotient","type":"int"},{"name":"dividend","type":"int"}]},{"type":"array","items":"string"}]'
),
];
$fixed_examples = [
new SchemaExample(
'{"type": "fixed", "name": "Test", "size": 1}',
true
),
new SchemaExample(
<<<JSON
{
"type":"fixed",
"name":"MyFixed",
"namespace":"org.apache.hadoop.avro",
"size":1
}
JSON,
true
),
new SchemaExample(
'{"type": "fixed", "name": "Missing size"}',
false
),
new SchemaExample(
'{"type": "fixed", "size": 314}',
false
),
new SchemaExample(
'{"type":"fixed","name":"ex","doc":"this shouldn\'t be ignored","size": 314}',
true,
'{"type":"fixed","name":"ex","doc":"this shouldn\'t be ignored","size":314}'
),
new SchemaExample(
'{"name": "bar", "namespace": "com.example", "type": "fixed", "size": 32 }',
true,
'{"type":"fixed","name":"bar","namespace":"com.example","size":32}'
),
new SchemaExample(
'{"name": "com.example.bar", "type": "fixed", "size": 32}',
true,
'{"type":"fixed","name":"bar","namespace":"com.example","size":32}'
),
];
$fixed_examples[] = new SchemaExample(
'{"type":"fixed","name":"_x.bar","size":4}',
true,
'{"type":"fixed","name":"bar","namespace":"_x","size":4}'
);
$fixed_examples[] = new SchemaExample(
'{"type":"fixed","name":"baz._x","size":4}',
true,
'{"type":"fixed","name":"_x","namespace":"baz","size":4}'
);
$fixed_examples[] = new SchemaExample(
'{"type":"fixed","name":"baz.3x","size":4}',
false
);
$fixed_examples[] = new SchemaExample(
'{"type":"fixed", "name":"Fixed2", "aliases":["Fixed1"], "size": 2}',
true
);
$enum_examples = [
new SchemaExample(
'{"type": "enum", "name": "Test", "symbols": ["A", "B"]}',
true
),
new SchemaExample(
'{"type": "enum", "name": "Status", "symbols": "Normal Caution Critical"}',
false
),
new SchemaExample(
'{"type": "enum", "name": [ 0, 1, 1, 2, 3, 5, 8 ], "symbols": ["Golden", "Mean"]}',
false
),
new SchemaExample(
'{"type": "enum", "symbols" : ["I", "will", "fail", "no", "name"]}',
false
),
new SchemaExample(
'{"type": "enum", "name": "Test" "symbols" : ["AA", "AA"]}',
false
),
new SchemaExample(
'{"type":"enum","name":"Test","symbols":["AA", 16]}',
false
),
new SchemaExample(
<<<JSON
{
"type":"enum",
"name":"blood_types",
"doc":"AB is freaky.",
"symbols":[
"A",
"AB",
"B",
"O"
]
}
JSON,
true
),
new SchemaExample(
<<<JSON
{
"type":"enum",
"name":"blood-types",
"doc":16,
"symbols":[
"A",
"AB",
"B",
"O"
]
}
JSON,
false
),
];
$record_examples = [];
$record_examples[] = new SchemaExample(
<<<JSON
{
"type":"record",
"name":"Test",
"fields":[
{
"name":"f",
"type":"long"
}
]
}
JSON,
true
);
$record_examples[] = new SchemaExample(
<<<JSON
{
"type":"error",
"name":"Test",
"fields":[
{
"name":"f",
"type":"long"
}
]
}
JSON,
true
);
$record_examples[] = new SchemaExample(
<<<JSON
{
"type":"record",
"name":"Node",
"fields":[
{
"name":"label",
"type":"string"
},
{
"name":"children",
"type":{
"type":"array",
"items":"Node"
}
}
]
}
JSON,
true
);
$record_examples[] = new SchemaExample(
<<<JSON
{
"type":"record",
"name":"ListLink",
"fields":[
{
"name":"car",
"type":"int"
},
{
"name":"cdr",
"type":"ListLink"
}
]
}
JSON,
true
);
$record_examples[] = new SchemaExample(
<<<JSON
{
"type":"record",
"name":"Lisp",
"fields":[
{
"name":"value",
"type":[
"null",
"string"
]
}
]
}
JSON,
true
);
$record_examples[] = new SchemaExample(
<<<JSON
{
"type":"record",
"name":"Lisp",
"fields":[
{
"name":"value",
"type":[
"null",
"string",
{
"type":"record",
"name":"Cons",
"fields":[
{
"name":"car",
"type":"string"
},
{
"name":"cdr",
"type":"string"
}
]
}
]
}
]
}
JSON,
true
);
$record_examples[] = new SchemaExample(
<<<JSON
{
"type":"record",
"name":"Lisp",
"fields":[
{
"name":"value",
"type":[
"null",
"string",
{
"type":"record",
"name":"Cons",
"fields":[
{
"name":"car",
"type":"Lisp"
},
{
"name":"cdr",
"type":"Lisp"
}
]
}
]
}
]
}
JSON,
true
);
$record_examples[] = new SchemaExample(
<<<JSON
{
"type":"record",
"name":"HandshakeRequest",
"namespace":"org.apache.avro.ipc",
"fields":[
{
"name":"clientHash",
"type":{
"type":"fixed",
"name":"MD5",
"size":16
}
},
{
"name":"meta",
"type":[
"null",
{
"type":"map",
"values":"bytes"
}
]
}
]
}
JSON,
true
);
$record_examples[] = new SchemaExample(
<<<JSON
{
"type":"record",
"name":"HandshakeRequest",
"namespace":"org.apache.avro.ipc",
"fields":[
{
"name":"clientHash",
"type":{
"type":"fixed",
"name":"MD5",
"size":16
}
},
{
"name":"clientProtocol",
"type":[
"null",
"string"
]
},
{
"name":"serverHash",
"type":"MD5"
},
{
"name":"meta",
"type":[
"null",
{
"type":"map",
"values":"bytes"
}
]
}
]
}
JSON,
true
);
$record_examples[] = new SchemaExample(
<<<JSON
{
"type":"record",
"name":"HandshakeResponse",
"namespace":"org.apache.avro.ipc",
"fields":[
{
"name":"match",
"type":{
"type":"enum",
"name":"HandshakeMatch",
"symbols":[
"BOTH",
"CLIENT",
"NONE"
]
}
},
{
"name":"serverProtocol",
"type":[
"null",
"string"
]
},
{
"name":"serverHash",
"type":[
"null",
{
"name":"MD5",
"size":16,
"type":"fixed"
}
]
},
{
"name":"meta",
"type":[
"null",
{
"type":"map",
"values":"bytes"
}
]
}
]
}
JSON,
true,
'{"type":"record","name":"HandshakeResponse","namespace":"org.apache.avro.ipc","fields":[{"name":"match","type":{"type":"enum","name":"HandshakeMatch","symbols":["BOTH","CLIENT","NONE"]}},{"name":"serverProtocol","type":["null","string"]},{"name":"serverHash","type":["null",{"type":"fixed","name":"MD5","size":16}]},{"name":"meta","type":["null",{"type":"map","values":"bytes"}]}]}'
);
$record_examples[] = new SchemaExample(
<<<JSON
{
"type":"record",
"namespace":"org.apache.avro",
"name":"Interop",
"fields":[
{
"type":{
"fields":[
{
"type":{
"items":"org.apache.avro.Node",
"type":"array"
},
"name":"children"
}
],
"type":"record",
"name":"Node"
},
"name":"recordField"
}
]
}
JSON,
true,
'{"type":"record","name":"Interop","namespace":"org.apache.avro","fields":[{"name":"recordField","type":{"type":"record","name":"Node","fields":[{"name":"children","type":{"type":"array","items":"Node"}}]}}]}'
);
$record_examples[] = new SchemaExample(
<<<JSON
{
"type":"record",
"namespace":"org.apache.avro",
"name":"Interop",
"fields":[
{
"type":{
"symbols":[
"A",
"B",
"C"
],
"type":"enum",
"name":"Kind"
},
"name":"enumField"
},
{
"type":{
"fields":[
{
"type":"string",
"name":"label"
},
{
"type":{
"items":"org.apache.avro.Node",
"type":"array"
},
"name":"children"
}
],
"type":"record",
"name":"Node"
},
"name":"recordField"
}
]
}
JSON,
true,
'{"type":"record","name":"Interop","namespace":"org.apache.avro","fields":[{"name":"enumField","type":{"type":"enum","name":"Kind","symbols":["A","B","C"]}},{"name":"recordField","type":{"type":"record","name":"Node","fields":[{"name":"label","type":"string"},{"name":"children","type":{"type":"array","items":"Node"}}]}}]}'
);
$record_examples[] = new SchemaExample(
<<<JSON
{
"type":"record",
"name":"Interop",
"namespace":"org.apache.avro",
"fields":[
{
"name":"intField",
"type":"int"
},
{
"name":"longField",
"type":"long"
},
{
"name":"stringField",
"type":"string"
},
{
"name":"boolField",
"type":"boolean"
},
{
"name":"floatField",
"type":"float"
},
{
"name":"doubleField",
"type":"double"
},
{
"name":"bytesField",
"type":"bytes"
},
{
"name":"nullField",
"type":"null"
},
{
"name":"arrayField",
"type":{
"type":"array",
"items":"double"
}
},
{
"name":"mapField",
"type":{
"type":"map",
"values":{
"name":"Foo",
"type":"record",
"fields":[
{
"name":"label",
"type":"string"
}
]
}
}
},
{
"name":"unionField",
"type":[
"boolean",
"double",
{
"type":"array",
"items":"bytes"
}
]
},
{
"name":"enumField",
"type":{
"type":"enum",
"name":"Kind",
"symbols":[
"A",
"B",
"C"
]
}
},
{
"name":"fixedField",
"type":{
"type":"fixed",
"name":"MD5",
"size":16
}
},
{
"name":"recordField",
"type":{
"type":"record",
"name":"Node",
"fields":[
{
"name":"label",
"type":"string"
},
{
"name":"children",
"type":{
"type":"array",
"items":"Node"
}
}
]
}
}
]
}
JSON,
true,
'{"type":"record","name":"Interop","namespace":"org.apache.avro","fields":[{"name":"intField","type":"int"},{"name":"longField","type":"long"},{"name":"stringField","type":"string"},{"name":"boolField","type":"boolean"},{"name":"floatField","type":"float"},{"name":"doubleField","type":"double"},{"name":"bytesField","type":"bytes"},{"name":"nullField","type":"null"},{"name":"arrayField","type":{"type":"array","items":"double"}},{"name":"mapField","type":{"type":"map","values":{"type":"record","name":"Foo","fields":[{"name":"label","type":"string"}]}}},{"name":"unionField","type":["boolean","double",{"type":"array","items":"bytes"}]},{"name":"enumField","type":{"type":"enum","name":"Kind","symbols":["A","B","C"]}},{"name":"fixedField","type":{"type":"fixed","name":"MD5","size":16}},{"name":"recordField","type":{"type":"record","name":"Node","fields":[{"name":"label","type":"string"},{"name":"children","type":{"type":"array","items":"Node"}}]}}]}'
);
$record_examples[] = new SchemaExample(
<<<JSON
{
"type":"record",
"namespace":"org.apache.avro",
"name":"Interop",
"fields":[
{
"type":"int",
"name":"intField"
},
{
"type":"long",
"name":"longField"
},
{
"type":"string",
"name":"stringField"
},
{
"type":"boolean",
"name":"boolField"
},
{
"type":"float",
"name":"floatField"
},
{
"type":"double",
"name":"doubleField"
},
{
"type":"bytes",
"name":"bytesField"
},
{
"type":"null",
"name":"nullField"
},
{
"type":{
"items":"double",
"type":"array"
},
"name":"arrayField"
},
{
"type":{
"type":"map",
"values":{
"fields":[
{
"type":"string",
"name":"label"
}
],
"type":"record",
"name":"Foo"
}
},
"name":"mapField"
},
{
"type":[
"boolean",
"double",
{
"items":"bytes",
"type":"array"
}
],
"name":"unionField"
},
{
"type":{
"symbols":[
"A",
"B",
"C"
],
"type":"enum",
"name":"Kind"
},
"name":"enumField"
},
{
"type":{
"type":"fixed",
"name":"MD5",
"size":16
},
"name":"fixedField"
},
{
"type":{
"fields":[
{
"type":"string",
"name":"label"
},
{
"type":{
"items":"org.apache.avro.Node",
"type":"array"
},
"name":"children"
}
],
"type":"record",
"name":"Node"
},
"name":"recordField"
}
]
}
JSON,
true,
'{"type":"record","name":"Interop","namespace":"org.apache.avro","fields":[{"name":"intField","type":"int"},{"name":"longField","type":"long"},{"name":"stringField","type":"string"},{"name":"boolField","type":"boolean"},{"name":"floatField","type":"float"},{"name":"doubleField","type":"double"},{"name":"bytesField","type":"bytes"},{"name":"nullField","type":"null"},{"name":"arrayField","type":{"type":"array","items":"double"}},{"name":"mapField","type":{"type":"map","values":{"type":"record","name":"Foo","fields":[{"name":"label","type":"string"}]}}},{"name":"unionField","type":["boolean","double",{"type":"array","items":"bytes"}]},{"name":"enumField","type":{"type":"enum","name":"Kind","symbols":["A","B","C"]}},{"name":"fixedField","type":{"type":"fixed","name":"MD5","size":16}},{"name":"recordField","type":{"type":"record","name":"Node","fields":[{"name":"label","type":"string"},{"name":"children","type":{"type":"array","items":"Node"}}]}}]}'
);
$record_examples[] = new SchemaExample(
<<<JSON
{
"type":"record",
"name":"ipAddr",
"fields":[
{
"name":"addr",
"type":[
{
"name":"IPv6",
"type":"fixed",
"size":16
},
{
"name":"IPv4",
"type":"fixed",
"size":4
}
]
}
]
}
JSON,
true,
'{"type":"record","name":"ipAddr","fields":[{"name":"addr","type":[{"type":"fixed","name":"IPv6","size":16},{"type":"fixed","name":"IPv4","size":4}]}]}'
);
$record_examples[] = new SchemaExample(
<<<JSON
{
"type":"record",
"name":"Address",
"fields":[
{
"type":"string"
},
{
"type":"string",
"name":"City"
}
]
}
JSON,
false
);
$record_examples[] = new SchemaExample(
<<<JSON
{
"type":"record",
"name":"Event",
"fields":[
{
"name":"Sponsor"
},
{
"name":"City",
"type":"string"
}
]
}
JSON,
false
);
$record_examples[] = new SchemaExample(
<<<JSON
{
"type": "record",
"fields": "His vision, from the constantly passing bars,"
"name",
"Rainer"
}
JSON,
false
);
$record_examples[] = new SchemaExample(
<<<JSON
{
"name":[
"Tom",
"Jerry"
],
"type":"record",
"fields":[
{
"name":"name",
"type":"string"
}
]
}
JSON,
false
);
$record_examples[] = new SchemaExample(
<<<JSON
{
"type":"record",
"name":"foo",
"doc":"doc string",
"fields":[
{
"name":"bar",
"type":"int",
"order":"ascending",
"default":1
}
]
}
JSON,
true,
'{"type":"record","name":"foo","doc":"doc string","fields":[{"name":"bar","type":"int","default":1,"order":"ascending"}]}'
);
$record_examples[] = new SchemaExample(
<<<JSON
{
"type":"record",
"name":"foo",
"doc":"doc string",
"fields":[
{
"name":"bar",
"type":"int",
"order":"bad"
}
]
}
JSON,
false
);
$record_examples[] = new SchemaExample(
'{"type":"record", "name":"Record2", "aliases":["Record1"]}',
false
);
self::$examples = array_merge(
$primitive_examples,
$fixed_examples,
$enum_examples,
$array_examples,
$map_examples,
$union_examples,
$record_examples
);
}
protected static function makePrimitiveExamples(): array
{
$examples = [];
foreach ([
'null',
'boolean',
'int',
'long',
'float',
'double',
'bytes',
'string',
] as $type) {
$examples[] = new SchemaExample(sprintf('"%s"', $type), true);
$examples[] = new SchemaExample(sprintf('{"type": "%s"}', $type), true, sprintf('"%s"', $type));
}
return $examples;
}
}