This is an automated email from the ASF dual-hosted git repository.
fokko pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/avro.git
The following commit(s) were added to refs/heads/master by this push:
new 3950008 AVRO-2039: Ruby encoding performance improvements (#230)
3950008 is described below
commit 39500088491512aeccf3e9dc7b76d99b91a82436
Author: Tim Perkins <[email protected]>
AuthorDate: Tue Nov 20 04:31:46 2018 -0500
AVRO-2039: Ruby encoding performance improvements (#230)
---
lang/ruby/lib/avro/io.rb | 13 ++--
lang/ruby/lib/avro/schema.rb | 4 +-
lang/ruby/lib/avro/schema_validator.rb | 108 ++++++++++++++++++++-----------
lang/ruby/test/test_io.rb | 21 ++++++
lang/ruby/test/test_schema_validator.rb | 110 ++++++++++++++++++++++++--------
5 files changed, 186 insertions(+), 70 deletions(-)
diff --git a/lang/ruby/lib/avro/io.rb b/lang/ruby/lib/avro/io.rb
index 26bda97..958159c 100644
--- a/lang/ruby/lib/avro/io.rb
+++ b/lang/ruby/lib/avro/io.rb
@@ -5,9 +5,9 @@
# 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.
@@ -45,7 +45,7 @@ module Avro
def byte!
@reader.read(1).unpack('C').first
end
-
+
def read_null
# null is written as zero byte's
nil
@@ -159,7 +159,7 @@ module Avro
nil
end
- # a boolean is written as a single byte
+ # a boolean is written as a single byte
# whose value is either 0 (false) or 1 (true).
def write_boolean(datum)
on_disk = datum ? 1.chr : 0.chr
@@ -504,7 +504,7 @@ module Avro
def write_data(writers_schema, logical_datum, encoder)
datum = writers_schema.type_adapter.encode(logical_datum)
- unless Schema.validate(writers_schema, datum, encoded = true)
+ unless Schema.validate(writers_schema, datum, { recursive: false,
encoded: true })
raise AvroTypeError.new(writers_schema, datum)
end
@@ -539,6 +539,7 @@ module Avro
end
def write_array(writers_schema, datum, encoder)
+ raise AvroTypeError.new(writers_schema, datum) unless
datum.is_a?(Array)
if datum.size > 0
encoder.write_long(datum.size)
datum.each do |item|
@@ -549,6 +550,7 @@ module Avro
end
def write_map(writers_schema, datum, encoder)
+ raise AvroTypeError.new(writers_schema, datum) unless datum.is_a?(Hash)
if datum.size > 0
encoder.write_long(datum.size)
datum.each do |k,v|
@@ -571,6 +573,7 @@ module Avro
end
def write_record(writers_schema, datum, encoder)
+ raise AvroTypeError.new(writers_schema, datum) unless datum.is_a?(Hash)
writers_schema.fields.each do |field|
write_data(field.type, datum[field.name], encoder)
end
diff --git a/lang/ruby/lib/avro/schema.rb b/lang/ruby/lib/avro/schema.rb
index 3acd07b..c1b150e 100644
--- a/lang/ruby/lib/avro/schema.rb
+++ b/lang/ruby/lib/avro/schema.rb
@@ -96,8 +96,8 @@ module Avro
end
# Determine if a ruby datum is an instance of a schema
- def self.validate(expected_schema, logical_datum, encoded = false)
- SchemaValidator.validate!(expected_schema, logical_datum, encoded)
+ def self.validate(expected_schema, logical_datum, options = { recursive:
true, encoded: false })
+ SchemaValidator.validate!(expected_schema, logical_datum, options)
true
rescue SchemaValidator::ValidationError
false
diff --git a/lang/ruby/lib/avro/schema_validator.rb
b/lang/ruby/lib/avro/schema_validator.rb
index 2117e92..28022a8 100644
--- a/lang/ruby/lib/avro/schema_validator.rb
+++ b/lang/ruby/lib/avro/schema_validator.rb
@@ -20,7 +20,8 @@ module Avro
PATH_SEPARATOR = '.'.freeze
INT_RANGE = Schema::INT_MIN_VALUE..Schema::INT_MAX_VALUE
LONG_RANGE = Schema::LONG_MIN_VALUE..Schema::LONG_MAX_VALUE
- COMPLEX_TYPES = [:array, :error, :map, :record, :request]
+ COMPLEX_TYPES = [:array, :error, :map, :record, :request].freeze
+ BOOLEAN_VALUES = [true, false].freeze
class Result
attr_reader :errors
@@ -62,27 +63,54 @@ module Avro
TypeMismatchError = Class.new(ValidationError)
class << self
- def validate!(expected_schema, logical_datum, encoded = false)
+ def validate!(expected_schema, logical_datum, options = { recursive:
true, encoded: false })
+ options ||= {}
+ options[:recursive] = true unless options.key?(:recursive)
+
result = Result.new
- validate_recursive(expected_schema, logical_datum, ROOT_IDENTIFIER,
result, encoded)
+ if options[:recursive]
+ validate_recursive(expected_schema, logical_datum, ROOT_IDENTIFIER,
result, options)
+ else
+ validate_simple(expected_schema, logical_datum, ROOT_IDENTIFIER,
result, options)
+ end
fail ValidationError, result if result.failure?
result
end
private
- def validate_recursive(expected_schema, logical_datum, path, result,
encoded = false)
- datum = if encoded
- logical_datum
- else
- expected_schema.type_adapter.encode(logical_datum) rescue nil
- end
+ def validate_recursive(expected_schema, logical_datum, path, result,
options = {})
+ datum = resolve_datum(expected_schema, logical_datum,
options[:encoded])
+
+ validate_simple(expected_schema, datum, path, result, encoded: true)
+
+ case expected_schema.type_sym
+ when :array
+ validate_array(expected_schema, datum, path, result)
+ when :map
+ validate_map(expected_schema, datum, path, result)
+ when :union
+ validate_union(expected_schema, datum, path, result)
+ when :record, :error, :request
+ fail TypeMismatchError unless datum.is_a?(Hash)
+ expected_schema.fields.each do |field|
+ deeper_path = deeper_path_for_hash(field.name, path)
+ validate_recursive(field.type, datum[field.name], deeper_path,
result)
+ end
+ end
+ rescue TypeMismatchError
+ result.add_error(path, "expected type #{expected_schema.type_sym}, got
#{actual_value_message(datum)}")
+ end
+
+ def validate_simple(expected_schema, logical_datum, path, result,
options = {})
+ datum = resolve_datum(expected_schema, logical_datum,
options[:encoded])
+ validate_type(expected_schema)
case expected_schema.type_sym
when :null
fail TypeMismatchError unless datum.nil?
when :boolean
- fail TypeMismatchError unless [true, false].include?(datum)
+ fail TypeMismatchError unless BOOLEAN_VALUES.include?(datum)
when :string, :bytes
fail TypeMismatchError unless datum.is_a?(String)
when :int
@@ -92,36 +120,42 @@ module Avro
fail TypeMismatchError unless datum.is_a?(Integer)
result.add_error(path, "out of bound value #{datum}") unless
LONG_RANGE.cover?(datum)
when :float, :double
- fail TypeMismatchError unless [Float,
Integer].any?(&datum.method(:is_a?))
+ fail TypeMismatchError unless datum.is_a?(Float) ||
datum.is_a?(Integer)
when :fixed
if datum.is_a? String
- message = "expected fixed with size #{expected_schema.size}, got
\"#{datum}\" with size #{datum.size}"
- result.add_error(path, message) unless datum.bytesize ==
expected_schema.size
+ result.add_error(path, fixed_string_message(expected_schema.size,
datum)) unless datum.bytesize == expected_schema.size
else
result.add_error(path, "expected fixed with size
#{expected_schema.size}, got #{actual_value_message(datum)}")
end
when :enum
- message = "expected enum with values #{expected_schema.symbols}, got
#{actual_value_message(datum)}"
- result.add_error(path, message) unless
expected_schema.symbols.include?(datum)
- when :array
- validate_array(expected_schema, datum, path, result)
- when :map
- validate_map(expected_schema, datum, path, result)
- when :union
- validate_union(expected_schema, datum, path, result)
- when :record, :error, :request
- fail TypeMismatchError unless datum.is_a?(Hash)
- expected_schema.fields.each do |field|
- deeper_path = deeper_path_for_hash(field.name, path)
- validate_recursive(field.type, datum[field.name], deeper_path,
result)
- end
- else
- fail "Unexpected schema type #{expected_schema.type_sym}
#{expected_schema.inspect}"
+ result.add_error(path, enum_message(expected_schema.symbols, datum))
unless expected_schema.symbols.include?(datum)
end
rescue TypeMismatchError
result.add_error(path, "expected type #{expected_schema.type_sym}, got
#{actual_value_message(datum)}")
end
+ def resolve_datum(expected_schema, logical_datum, encoded)
+ if encoded
+ logical_datum
+ else
+ expected_schema.type_adapter.encode(logical_datum) rescue nil
+ end
+ end
+
+ def validate_type(expected_schema)
+ unless Avro::Schema::VALID_TYPES_SYM.include?(expected_schema.type_sym)
+ fail "Unexpected schema type #{expected_schema.type_sym}
#{expected_schema.inspect}"
+ end
+ end
+
+ def fixed_string_message(size, datum)
+ "expected fixed with size #{size}, got \"#{datum}\" with size
#{datum.size}"
+ end
+
+ def enum_message(symbols, datum)
+ "expected enum with values #{symbols}, got
#{actual_value_message(datum)}"
+ end
+
def validate_array(expected_schema, datum, path, result)
fail TypeMismatchError unless datum.is_a?(Array)
datum.each_with_index do |d, i|
@@ -145,9 +179,10 @@ module Avro
validate_recursive(expected_schema.schemas.first, datum, path,
result)
return
end
- types_and_results = validate_possible_types(datum, expected_schema,
path)
- failures, successes = types_and_results.partition { |r|
r[:result].failure? }
- return if successes.any?
+ failures = []
+ compatible_type = first_compatible_type(datum, expected_schema, path,
failures)
+ return unless compatible_type.nil?
+
complex_type_failed = failures.detect { |r|
COMPLEX_TYPES.include?(r[:type]) }
if complex_type_failed
complex_type_failed[:result].errors.each { |error| result << error }
@@ -157,11 +192,12 @@ module Avro
end
end
- def validate_possible_types(datum, expected_schema, path)
- expected_schema.schemas.map do |schema|
+ def first_compatible_type(datum, expected_schema, path, failures)
+ expected_schema.schemas.find do |schema|
result = Result.new
validate_recursive(schema, datum, path, result)
- { type: schema.type_sym, result: result }
+ failures << { type: schema.type_sym, result: result } if
result.failure?
+ !result.failure?
end
end
@@ -169,8 +205,6 @@ module Avro
"#{path}#{PATH_SEPARATOR}#{sub_key}".squeeze(PATH_SEPARATOR)
end
- private
-
def actual_value_message(value)
avro_type = if value.is_a?(Integer)
ruby_integer_to_avro_type(value)
diff --git a/lang/ruby/test/test_io.rb b/lang/ruby/test/test_io.rb
index 70bb4d6..b518708 100644
--- a/lang/ruby/test/test_io.rb
+++ b/lang/ruby/test/test_io.rb
@@ -158,6 +158,27 @@ EOS
check_default(fixed_schema, '"a"', "a")
end
+ def test_record_with_nil
+ schema = Avro::Schema.parse('{"type":"record", "name":"rec",
"fields":[{"type":"int", "name":"i"}]}')
+ assert_raise(Avro::IO::AvroTypeError) do
+ write_datum(nil, schema)
+ end
+ end
+
+ def test_array_with_nil
+ schema = Avro::Schema.parse('{"type":"array", "items":"int"}')
+ assert_raise(Avro::IO::AvroTypeError) do
+ write_datum(nil, schema)
+ end
+ end
+
+ def test_map_with_nil
+ schema = Avro::Schema.parse('{"type":"map", "values":"long"}')
+ assert_raise(Avro::IO::AvroTypeError) do
+ write_datum(nil, schema)
+ end
+ end
+
def test_enum_with_duplicate
str = '{"type": "enum", "name": "Test","symbols" : ["AA", "AA"]}'
assert_raises(Avro::SchemaParseError) do
diff --git a/lang/ruby/test/test_schema_validator.rb
b/lang/ruby/test/test_schema_validator.rb
index e77569a..c4759da 100644
--- a/lang/ruby/test/test_schema_validator.rb
+++ b/lang/ruby/test/test_schema_validator.rb
@@ -21,6 +21,10 @@ class TestSchema < Test::Unit::TestCase
Avro::SchemaValidator.validate!(schema, value)
end
+ def validate_simple!(schema, value)
+ Avro::SchemaValidator.validate!(schema, value, recursive: false)
+ end
+
def hash_to_schema(hash)
Avro::Schema.parse(hash.to_json)
end
@@ -36,13 +40,16 @@ class TestSchema < Test::Unit::TestCase
assert_equal(assert_messages.size, result_errors.size)
end
- def assert_valid_schema(schema, valid, invalid)
+ def assert_valid_schema(schema, valid, invalid, simple = false)
valid.each do |value|
assert_nothing_raised { Avro::SchemaValidator.validate!(schema, value) }
+ assert_nothing_raised { Avro::SchemaValidator.validate!(schema, value,
recursive: false) } if simple
end
invalid.each do |value|
assert_raise { Avro::SchemaValidator.validate!(schema, value) }
+ assert_raise { Avro::SchemaValidator.validate!(schema, value, recursive:
false) } if simple
+ assert_nothing_raised { Avro::SchemaValidator.validate!(schema, value,
recursive: false) } unless simple
end
end
@@ -50,10 +57,15 @@ class TestSchema < Test::Unit::TestCase
schema = hash_to_schema(type: 'null', name: 'name')
assert_nothing_raised { validate!(schema, nil) }
+ assert_nothing_raised { validate_simple!(schema, nil) }
assert_failed_validation('at . expected type null, got int with value 1')
do
validate!(schema, 1)
end
+
+ assert_failed_validation('at . expected type null, got int with value 1')
do
+ validate_simple!(schema, 1)
+ end
end
def test_validate_boolean
@@ -61,52 +73,67 @@ class TestSchema < Test::Unit::TestCase
assert_nothing_raised { validate!(schema, true) }
assert_nothing_raised { validate!(schema, false) }
+ assert_nothing_raised { validate_simple!(schema, true) }
+ assert_nothing_raised { validate_simple!(schema, false) }
assert_failed_validation('at . expected type boolean, got int with value
1') do
validate!(schema, 1)
end
+ assert_failed_validation('at . expected type boolean, got int with value
1') do
+ validate_simple!(schema, 1)
+ end
assert_failed_validation('at . expected type boolean, got null') do
validate!(schema, nil)
end
+ assert_failed_validation('at . expected type boolean, got null') do
+ validate_simple!(schema, nil)
+ end
end
def test_fixed_size_string
schema = hash_to_schema(type: 'fixed', name: 'some', size: 3)
assert_nothing_raised { validate!(schema, 'baf') }
+ assert_nothing_raised { validate_simple!(schema, 'baf') }
assert_failed_validation('at . expected fixed with size 3, got "some" with
size 4') do
validate!(schema, 'some')
end
+ assert_failed_validation('at . expected fixed with size 3, got "some" with
size 4') do
+ validate_simple!(schema, 'some')
+ end
assert_failed_validation('at . expected fixed with size 3, got null') do
validate!(schema, nil)
end
+ assert_failed_validation('at . expected fixed with size 3, got null') do
+ validate_simple!(schema, nil)
+ end
end
def test_original_validate_nil
schema = hash_to_schema(type: 'null', name: 'name')
- assert_valid_schema(schema, [nil], ['something'])
+ assert_valid_schema(schema, [nil], ['something'], true)
end
def test_original_validate_boolean
schema = hash_to_schema(type: 'boolean', name: 'name')
- assert_valid_schema(schema, [true, false], [nil, 1])
+ assert_valid_schema(schema, [true, false], [nil, 1], true)
end
def test_validate_string
schema = hash_to_schema(type: 'string', name: 'name')
- assert_valid_schema(schema, ['string'], [nil, 1])
+ assert_valid_schema(schema, ['string'], [nil, 1], true)
end
def test_validate_bytes
schema = hash_to_schema(type: 'bytes', name: 'name')
- assert_valid_schema(schema, ['string'], [nil, 1])
+ assert_valid_schema(schema, ['string'], [nil, 1], true)
end
def test_validate_int
@@ -115,41 +142,45 @@ class TestSchema < Test::Unit::TestCase
assert_valid_schema(
schema,
[Avro::Schema::INT_MIN_VALUE, Avro::Schema::INT_MAX_VALUE, 1],
- [Avro::Schema::LONG_MIN_VALUE, Avro::Schema::LONG_MAX_VALUE, 'string']
+ [Avro::Schema::LONG_MIN_VALUE, Avro::Schema::LONG_MAX_VALUE, 'string'],
+ true
)
assert_failed_validation('at . out of bound value 9223372036854775807') do
validate!(schema, Avro::Schema::LONG_MAX_VALUE)
end
+ assert_failed_validation('at . out of bound value 9223372036854775807') do
+ validate_simple!(schema, Avro::Schema::LONG_MAX_VALUE)
+ end
end
def test_validate_long
schema = hash_to_schema(type: 'long', name: 'name')
- assert_valid_schema(schema, [Avro::Schema::LONG_MIN_VALUE,
Avro::Schema::LONG_MAX_VALUE, 1], [1.1, 'string'])
+ assert_valid_schema(schema, [Avro::Schema::LONG_MIN_VALUE,
Avro::Schema::LONG_MAX_VALUE, 1], [1.1, 'string'], true)
end
def test_validate_float
schema = hash_to_schema(type: 'float', name: 'name')
- assert_valid_schema(schema, [1.1, 1, Avro::Schema::LONG_MAX_VALUE],
['string'])
+ assert_valid_schema(schema, [1.1, 1, Avro::Schema::LONG_MAX_VALUE],
['string'], true)
end
def test_validate_double
schema = hash_to_schema(type: 'double', name: 'name')
- assert_valid_schema(schema, [1.1, 1, Avro::Schema::LONG_MAX_VALUE],
['string'])
+ assert_valid_schema(schema, [1.1, 1, Avro::Schema::LONG_MAX_VALUE],
['string'], true)
end
def test_validate_fixed
schema = hash_to_schema(type: 'fixed', name: 'name', size: 3)
- assert_valid_schema(schema, ['abc'], ['ab', 1, 1.1, true])
+ assert_valid_schema(schema, ['abc'], ['ab', 1, 1.1, true], true)
end
def test_validate_original_num
schema = hash_to_schema(type: 'enum', name: 'name', symbols: %w(a b))
- assert_valid_schema(schema, ['a', 'b'], ['c'])
+ assert_valid_schema(schema, ['a', 'b'], ['c'], true)
end
def test_validate_record
@@ -164,22 +195,22 @@ class TestSchema < Test::Unit::TestCase
)
assert_nothing_raised { validate!(schema, 'sub' => 1) }
+ assert_nothing_raised { validate_simple!(schema, 'sub' => 1) }
assert_failed_validation('at .sub expected type int, got null') do
validate!(schema, {})
end
+ assert_nothing_raised { validate_simple!(schema, {}) }
assert_failed_validation('at . expected type record, got float with value
1.2') do
validate!(schema, 1.2)
end
+ assert_nothing_raised { validate_simple!(schema, 1.2) }
assert_failed_validation('at .sub expected type int, got float with value
1.2') do
validate!(schema, 'sub' => 1.2)
end
-
- assert_failed_validation('at .sub expected type int, got null') do
- validate!(schema, {})
- end
+ assert_nothing_raised { validate_simple!(schema, 'sub' => 1.2) }
end
def test_validate_array
@@ -188,18 +219,22 @@ class TestSchema < Test::Unit::TestCase
items: [{ type: 'int', name: 'height' }])
assert_nothing_raised { validate!(schema, []) }
+ assert_nothing_raised { validate_simple!(schema, []) }
assert_failed_validation 'at . expected type array, got null' do
validate!(schema, nil)
end
+ assert_nothing_raised { validate_simple!(schema, nil) }
assert_failed_validation('at .[0] expected type int, got null') do
validate!(schema, [nil])
end
+ assert_nothing_raised { validate_simple!(schema, [nil]) }
assert_failed_validation('at .[3] expected type int, got string with value
"so wrong"') do
validate!(schema, [1, 3, 9, 'so wrong'])
end
+ assert_nothing_raised { validate_simple!(schema, [1, 3, 9, 'so wrong']) }
end
def test_validate_enum
@@ -208,10 +243,14 @@ class TestSchema < Test::Unit::TestCase
symbols: %w(one two three))
assert_nothing_raised { validate!(schema, 'one') }
+ assert_nothing_raised { validate_simple!(schema, 'one') }
assert_failed_validation('at . expected enum with values ["one", "two",
"three"], got string with value "five"') do
validate!(schema, 'five')
end
+ assert_failed_validation('at . expected enum with values ["one", "two",
"three"], got string with value "five"') do
+ validate_simple!(schema, 'five')
+ end
end
def test_validate_union_on_primitive_types
@@ -226,6 +265,7 @@ class TestSchema < Test::Unit::TestCase
assert_failed_validation('at .what_ever expected union of [\'long\',
\'string\'], got null') {
validate!(schema, 'what_ever' => nil)
}
+ assert_nothing_raised { validate_simple!(schema, 'what_ever' => nil) }
end
def test_validate_union_of_nil_and_record_inside_array
@@ -267,22 +307,27 @@ class TestSchema < Test::Unit::TestCase
assert_failed_validation('at .person expected type record, got null') {
validate!(schema, 'not at all' => nil)
}
+ assert_nothing_raised { validate_simple!(schema, 'person' => {}) }
+
assert_nothing_raised { validate!(schema, 'person' => {}) }
assert_nothing_raised { validate!(schema, 'person' => { houses: [] }) }
assert_nothing_raised { validate!(schema, 'person' => { 'houses' => [{
'number_of_rooms' => 1 }] }) }
+ assert_nothing_raised { validate_simple!(schema, 'person' => {}) }
+ assert_nothing_raised { validate_simple!(schema, 'person' => { houses: []
}) }
+ assert_nothing_raised { validate_simple!(schema, 'person' => { 'houses' =>
[{ 'number_of_rooms' => 1 }] }) }
+
message = 'at .person.houses[1].number_of_rooms expected type long, got
string with value "not valid at all"'
- assert_failed_validation(message) do
- validate!(
- schema,
- 'person' => {
- 'houses' => [
- { 'number_of_rooms' => 2 },
- { 'number_of_rooms' => 'not valid at all' }
- ]
- }
- )
- end
+ datum = {
+ 'person' => {
+ 'houses' => [
+ { 'number_of_rooms' => 2 },
+ { 'number_of_rooms' => 'not valid at all' }
+ ]
+ }
+ }
+ assert_failed_validation(message) { validate!(schema, datum) }
+ assert_nothing_raised { validate_simple!(schema, datum) }
end
def test_validate_map
@@ -293,18 +338,22 @@ class TestSchema < Test::Unit::TestCase
])
assert_nothing_raised { validate!(schema, 'some' => 1) }
+ assert_nothing_raised { validate_simple!(schema, 'some' => 1) }
assert_failed_validation('at .some expected type int, got string with
value "nope"') do
validate!(schema, 'some' => 'nope')
end
+ assert_nothing_raised { validate_simple!(schema, 'some' => 'nope')}
assert_failed_validation("at . unexpected key type 'Symbol' in map") do
validate!(schema, some: 1)
end
+ assert_nothing_raised { validate_simple!(schema, some: 1) }
assert_failed_validation('at . expected type map, got null') do
validate!(schema, nil)
end
+ assert_nothing_raised { validate_simple!(schema, nil) }
end
def test_validate_deep_record
@@ -336,22 +385,27 @@ class TestSchema < Test::Unit::TestCase
])
assert_nothing_raised { validate!(schema, 'head' => { 'hair' => { 'color'
=> 'black' } }) }
+ assert_nothing_raised { validate_simple!(schema, 'head' => { 'hair' => {
'color' => 'black' } }) }
assert_failed_validation('at .head.hair.color expected type string, got
null') do
validate!(schema, 'head' => { 'hair' => { 'color' => nil } })
end
+ assert_nothing_raised { validate_simple!(schema, 'head' => { 'hair' => {
'color' => nil } }) }
assert_failed_validation('at .head.hair.color expected type string, got
null') do
validate!(schema, 'head' => { 'hair' => {} })
end
+ assert_nothing_raised { validate_simple!(schema, 'head' => { 'hair' => {}
}) }
assert_failed_validation('at .head.hair expected type record, got null') do
validate!(schema, 'head' => {})
end
+ assert_nothing_raised { validate_simple!(schema, 'head' => {}) }
assert_failed_validation('at . expected type record, got null') do
validate!(schema, nil)
end
+ assert_nothing_raised { validate_simple!(schema, nil) }
end
def test_validate_deep_record_with_array
@@ -377,14 +431,17 @@ class TestSchema < Test::Unit::TestCase
}
])
assert_nothing_raised { validate!(schema, 'fruits' => [{ 'name' =>
'apple', 'weight' => 30.2 }]) }
+ assert_nothing_raised { validate_simple!(schema, 'fruits' => [{ 'name' =>
'apple', 'weight' => 30.2 }]) }
assert_failed_validation('at .fruits[0].name expected type string, got
null') do
validate!(schema, 'fruits' => [{ 'name' => nil, 'weight' => 30.2 }])
end
+ assert_nothing_raised { validate_simple!(schema, 'fruits' => [{ 'name' =>
nil, 'weight' => 30.2 }]) }
assert_failed_validation('at .fruits expected type array, got int with
value 1') do
validate!(schema, 'fruits' => 1)
end
+ assert_nothing_raised { validate_simple!(schema, 'fruits' => 1) }
end
def test_validate_multiple_errors
@@ -397,6 +454,7 @@ class TestSchema < Test::Unit::TestCase
exception = assert_raise(Avro::SchemaValidator::ValidationError) do
validate!(schema, [nil, 'e'])
end
+ assert_nothing_raised { validate_simple!(schema, [nil, 'e']) }
assert_equal 2, exception.result.errors.size
assert_equal(
"at .[0] expected type int, got null\nat .[1] expected type int, got
string with value \"e\"",