Protocol Buffers - Google's data interchange format (grpc依赖)
https://developers.google.com/protocol-buffers/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
239 lines
7.4 KiB
239 lines
7.4 KiB
#!/usr/bin/ruby |
|
|
|
# generated_code.rb is in the same directory as this test. |
|
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) |
|
|
|
require 'basic_test_proto2_pb' |
|
require 'generated_code_pb' |
|
require 'google/protobuf/well_known_types' |
|
require 'test/unit' |
|
|
|
module CaptureWarnings |
|
@@warnings = nil |
|
|
|
module_function |
|
|
|
def warn(message, category: nil, **kwargs) |
|
if @@warnings |
|
@@warnings << message |
|
else |
|
super |
|
end |
|
end |
|
|
|
def capture |
|
@@warnings = [] |
|
yield |
|
@@warnings |
|
ensure |
|
@@warnings = nil |
|
end |
|
end |
|
|
|
Warning.extend CaptureWarnings |
|
|
|
def hex2bin(s) |
|
s.scan(/../).map { |x| x.hex.chr }.join |
|
end |
|
|
|
class NonConformantNumericsTest < Test::Unit::TestCase |
|
def test_empty_json_numerics |
|
if defined? JRUBY_VERSION and Google::Protobuf::IMPLEMENTATION != :FFI |
|
# In a future version, CRuby and JRuby FFI will also have this behavior. |
|
assert_raises Google::Protobuf::ParseError do |
|
msg = ::BasicTestProto2::TestMessage.decode_json('{"optionalInt32":""}') |
|
end |
|
else |
|
warnings = CaptureWarnings.capture { |
|
msg = ::BasicTestProto2::TestMessage.decode_json('{"optionalInt32":""}') |
|
assert_equal 0, msg.optional_int32 |
|
assert msg.has_optional_int32? |
|
} |
|
assert_equal 1, warnings.size |
|
assert_match "Empty string is not a valid number (field: basic_test_proto2.TestMessage.optional_int32)", warnings[0] |
|
end |
|
end |
|
|
|
def test_trailing_non_numeric_characters |
|
if defined? JRUBY_VERSION and Google::Protobuf::IMPLEMENTATION != :FFI |
|
# In a future version, CRuby and JRuby FFI will also have this behavior. |
|
assert_raises Google::Protobuf::ParseError do |
|
msg = ::BasicTestProto2::TestMessage.decode_json('{"optionalDouble":"123abc"}') |
|
end |
|
else |
|
warnings = CaptureWarnings.capture { |
|
msg = ::BasicTestProto2::TestMessage.decode_json('{"optionalDouble":"123abc"}') |
|
assert_equal 123, msg.optional_double |
|
assert msg.has_optional_double? |
|
} |
|
assert_equal 1, warnings.size |
|
assert_match "Non-number characters in quoted number (field: basic_test_proto2.TestMessage.optional_double)", warnings[0] |
|
end |
|
end |
|
end |
|
|
|
class EncodeDecodeTest < Test::Unit::TestCase |
|
def test_discard_unknown |
|
# Test discard unknown in message. |
|
unknown_msg = A::B::C::TestUnknown.new(:unknown_field => 1) |
|
from = A::B::C::TestUnknown.encode(unknown_msg) |
|
m = A::B::C::TestMessage.decode(from) |
|
Google::Protobuf.discard_unknown(m) |
|
to = A::B::C::TestMessage.encode(m) |
|
assert_empty to |
|
# Test discard unknown for singular message field. |
|
unknown_msg = A::B::C::TestUnknown.new( |
|
:optional_unknown => |
|
A::B::C::TestUnknown.new(:unknown_field => 1)) |
|
from = A::B::C::TestUnknown.encode(unknown_msg) |
|
m = A::B::C::TestMessage.decode(from) |
|
Google::Protobuf.discard_unknown(m) |
|
to = A::B::C::TestMessage.encode(m.optional_msg) |
|
assert_empty to |
|
# Test discard unknown for repeated message field. |
|
unknown_msg = A::B::C::TestUnknown.new( |
|
:repeated_unknown => |
|
[A::B::C::TestUnknown.new(:unknown_field => 1)]) |
|
from = A::B::C::TestUnknown.encode(unknown_msg) |
|
m = A::B::C::TestMessage.decode(from) |
|
Google::Protobuf.discard_unknown(m) |
|
to = A::B::C::TestMessage.encode(m.repeated_msg[0]) |
|
assert_empty to |
|
# Test discard unknown for map value message field. |
|
unknown_msg = A::B::C::TestUnknown.new( |
|
:map_unknown => |
|
{"" => A::B::C::TestUnknown.new(:unknown_field => 1)}) |
|
from = A::B::C::TestUnknown.encode(unknown_msg) |
|
m = A::B::C::TestMessage.decode(from) |
|
Google::Protobuf.discard_unknown(m) |
|
to = A::B::C::TestMessage.encode(m.map_string_msg['']) |
|
assert_empty to |
|
# Test discard unknown for oneof message field. |
|
unknown_msg = A::B::C::TestUnknown.new( |
|
:oneof_unknown => |
|
A::B::C::TestUnknown.new(:unknown_field => 1)) |
|
from = A::B::C::TestUnknown.encode(unknown_msg) |
|
m = A::B::C::TestMessage.decode(from) |
|
Google::Protobuf.discard_unknown(m) |
|
to = A::B::C::TestMessage.encode(m.oneof_msg) |
|
assert_empty to |
|
end |
|
|
|
def test_encode_json |
|
msg = A::B::C::TestMessage.new({ optional_int32: 22 }) |
|
json = msg.to_json |
|
|
|
to = A::B::C::TestMessage.decode_json(json) |
|
assert_equal 22, to.optional_int32 |
|
msg = A::B::C::TestMessage.new({ optional_int32: 22 }) |
|
json = msg.to_json({ preserve_proto_fieldnames: true }) |
|
|
|
assert_match 'optional_int32', json |
|
|
|
to = A::B::C::TestMessage.decode_json(json) |
|
assert_equal 22, to.optional_int32 |
|
|
|
msg = A::B::C::TestMessage.new({ optional_int32: 22 }) |
|
json = A::B::C::TestMessage.encode_json( |
|
msg, |
|
{ preserve_proto_fieldnames: true, emit_defaults: true } |
|
) |
|
|
|
assert_match 'optional_int32', json |
|
|
|
|
|
# Test for enums printing as ints. |
|
msg = A::B::C::TestMessage.new({ optional_enum: 1 }) |
|
json = A::B::C::TestMessage.encode_json( |
|
msg, |
|
{ :format_enums_as_integers => true } |
|
) |
|
|
|
assert_match '"optionalEnum":1', json |
|
|
|
# Test for default enum being printed as int. |
|
msg = A::B::C::TestMessage.new({ optional_enum: 0 }) |
|
json = A::B::C::TestMessage.encode_json( |
|
msg, |
|
{ :format_enums_as_integers => true, :emit_defaults => true } |
|
) |
|
|
|
assert_match '"optionalEnum":0', json |
|
|
|
# Test for repeated enums printing as ints. |
|
msg = A::B::C::TestMessage.new({ repeated_enum: [0,1,2,3] }) |
|
json = A::B::C::TestMessage.encode_json( |
|
msg, |
|
{ :format_enums_as_integers => true } |
|
) |
|
|
|
assert_match '"repeatedEnum":[0,1,2,3]', json |
|
end |
|
|
|
def test_encode_wrong_msg |
|
assert_raises ::ArgumentError do |
|
m = A::B::C::TestMessage.new( |
|
:optional_int32 => 1, |
|
) |
|
Google::Protobuf::Any.encode(m) |
|
end |
|
end |
|
|
|
def test_json_name |
|
msg = A::B::C::TestJsonName.new(:value => 42) |
|
json = msg.to_json |
|
assert_match json, "{\"CustomJsonName\":42}" |
|
end |
|
|
|
def test_decode_depth_limit |
|
msg = A::B::C::TestMessage.new( |
|
optional_msg: A::B::C::TestMessage.new( |
|
optional_msg: A::B::C::TestMessage.new( |
|
optional_msg: A::B::C::TestMessage.new( |
|
optional_msg: A::B::C::TestMessage.new( |
|
optional_msg: A::B::C::TestMessage.new( |
|
) |
|
) |
|
) |
|
) |
|
) |
|
) |
|
msg_encoded = A::B::C::TestMessage.encode(msg) |
|
msg_out = A::B::C::TestMessage.decode(msg_encoded) |
|
assert_match msg.to_json, msg_out.to_json |
|
|
|
assert_raises Google::Protobuf::ParseError do |
|
A::B::C::TestMessage.decode(msg_encoded, { recursion_limit: 4 }) |
|
end |
|
|
|
msg_out = A::B::C::TestMessage.decode(msg_encoded, { recursion_limit: 5 }) |
|
assert_match msg.to_json, msg_out.to_json |
|
end |
|
|
|
def test_encode_depth_limit |
|
msg = A::B::C::TestMessage.new( |
|
optional_msg: A::B::C::TestMessage.new( |
|
optional_msg: A::B::C::TestMessage.new( |
|
optional_msg: A::B::C::TestMessage.new( |
|
optional_msg: A::B::C::TestMessage.new( |
|
optional_msg: A::B::C::TestMessage.new( |
|
) |
|
) |
|
) |
|
) |
|
) |
|
) |
|
msg_encoded = A::B::C::TestMessage.encode(msg) |
|
msg_out = A::B::C::TestMessage.decode(msg_encoded) |
|
assert_match msg.to_json, msg_out.to_json |
|
|
|
assert_raises RuntimeError do |
|
A::B::C::TestMessage.encode(msg, { recursion_limit: 5 }) |
|
end |
|
|
|
msg_encoded = A::B::C::TestMessage.encode(msg, { recursion_limit: 6 }) |
|
msg_out = A::B::C::TestMessage.decode(msg_encoded) |
|
assert_match msg.to_json, msg_out.to_json |
|
end |
|
|
|
end
|
|
|