Implement respond_to?
in RubyMessage (#9677)
All synthetic methods implemented by `method_missing` are now supported by `respond_to?`. Fixes issue #9202. * Fix null pointer exceptions exposed by new regression tests. * Fix clear_ on oneofs so that it is safe to call repeatedly and so that respond_to? does not depend on whether the oneof is currently cleared. * Code cleanup: reenable more tests on JRuby. * Align JRuby behavior with CRuby by throwing a RuntimeError when attempting to assign to a oneof.
This commit is contained in:
parent
b5a35bcc7e
commit
8e7f936696
@ -209,6 +209,8 @@ public class RubyDescriptor extends RubyObject {
|
||||
klass.include(new IRubyObject[] {messageExts});
|
||||
klass.instance_variable_set(runtime.newString(Utils.DESCRIPTOR_INSTANCE_VAR), this);
|
||||
klass.defineAnnotatedMethods(RubyMessage.class);
|
||||
// Workaround for https://github.com/jruby/jruby/issues/7154
|
||||
klass.searchMethod("respond_to?").setIsBuiltin(false);
|
||||
return klass;
|
||||
}
|
||||
|
||||
|
@ -260,6 +260,86 @@ public class RubyMessage extends RubyObject {
|
||||
return runtime.getTrue();
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* Message.respond_to?(method_name, search_private_and_protected) => boolean
|
||||
*
|
||||
* Parallels method_missing, returning true when this object implements a method with the given
|
||||
* method_name.
|
||||
*/
|
||||
@JRubyMethod(name="respond_to?", required = 1, optional = 1)
|
||||
public IRubyObject respondTo(ThreadContext context, IRubyObject [] args) {
|
||||
String methodName = args[0].asJavaString();
|
||||
if (descriptor.findFieldByName(methodName) != null) {
|
||||
return context.runtime.getTrue();
|
||||
}
|
||||
RubyDescriptor rubyDescriptor = (RubyDescriptor) getDescriptor(context, metaClass);
|
||||
IRubyObject oneofDescriptor = rubyDescriptor.lookupOneof(context, args[0]);
|
||||
if (!oneofDescriptor.isNil()) {
|
||||
return context.runtime.getTrue();
|
||||
}
|
||||
if (methodName.startsWith(CLEAR_PREFIX)) {
|
||||
String strippedMethodName = methodName.substring(6);
|
||||
oneofDescriptor = rubyDescriptor.lookupOneof(context, context.runtime.newSymbol(strippedMethodName));
|
||||
if (!oneofDescriptor.isNil()) {
|
||||
return context.runtime.getTrue();
|
||||
}
|
||||
|
||||
if (descriptor.findFieldByName(strippedMethodName) != null) {
|
||||
return context.runtime.getTrue();
|
||||
}
|
||||
}
|
||||
if (methodName.startsWith(HAS_PREFIX) && methodName.endsWith(QUESTION_MARK)) {
|
||||
String strippedMethodName = methodName.substring(4, methodName.length() - 1);
|
||||
FieldDescriptor fieldDescriptor = descriptor.findFieldByName(strippedMethodName);
|
||||
if (fieldDescriptor != null &&
|
||||
(!proto3 || fieldDescriptor.getContainingOneof() == null || fieldDescriptor
|
||||
.getContainingOneof().isSynthetic()) &&
|
||||
fieldDescriptor.hasPresence()) {
|
||||
return context.runtime.getTrue();
|
||||
}
|
||||
oneofDescriptor = rubyDescriptor.lookupOneof(context, RubyString.newString(context.runtime, strippedMethodName));
|
||||
if (!oneofDescriptor.isNil()) {
|
||||
return context.runtime.getTrue();
|
||||
}
|
||||
}
|
||||
if (methodName.endsWith(AS_VALUE_SUFFIX)) {
|
||||
FieldDescriptor fieldDescriptor = descriptor.findFieldByName(
|
||||
methodName.substring(0, methodName.length() - 9));
|
||||
if (fieldDescriptor != null && isWrappable(fieldDescriptor)) {
|
||||
return context.runtime.getTrue();
|
||||
}
|
||||
}
|
||||
if (methodName.endsWith(CONST_SUFFIX)) {
|
||||
FieldDescriptor fieldDescriptor = descriptor.findFieldByName(
|
||||
methodName.substring(0, methodName.length() - 6));
|
||||
if (fieldDescriptor != null) {
|
||||
if (fieldDescriptor.getType() == FieldDescriptor.Type.ENUM) {
|
||||
return context.runtime.getTrue();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (methodName.endsWith(Utils.EQUAL_SIGN)) {
|
||||
String strippedMethodName = methodName.substring(0, methodName.length() - 1);
|
||||
FieldDescriptor fieldDescriptor = descriptor.findFieldByName(strippedMethodName);
|
||||
if (fieldDescriptor != null) {
|
||||
return context.runtime.getTrue();
|
||||
}
|
||||
if (strippedMethodName.endsWith(AS_VALUE_SUFFIX)) {
|
||||
strippedMethodName = methodName.substring(0, strippedMethodName.length() - 9);
|
||||
fieldDescriptor = descriptor.findFieldByName(strippedMethodName);
|
||||
if (fieldDescriptor != null && isWrappable(fieldDescriptor)) {
|
||||
return context.runtime.getTrue();
|
||||
}
|
||||
}
|
||||
}
|
||||
boolean includePrivate = false;
|
||||
if (args.length == 2) {
|
||||
includePrivate = context.runtime.getTrue().equals(args[1]);
|
||||
}
|
||||
return metaClass.respondsToMethod(methodName, includePrivate) ? context.runtime.getTrue() : context.runtime.getFalse();
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* Message.method_missing(*args)
|
||||
@ -291,10 +371,9 @@ public class RubyMessage extends RubyObject {
|
||||
public IRubyObject methodMissing(ThreadContext context, IRubyObject[] args) {
|
||||
Ruby runtime = context.runtime;
|
||||
String methodName = args[0].asJavaString();
|
||||
RubyDescriptor rubyDescriptor = (RubyDescriptor) getDescriptor(context, metaClass);
|
||||
|
||||
if (args.length == 1) {
|
||||
RubyDescriptor rubyDescriptor = (RubyDescriptor) getDescriptor(context, metaClass);
|
||||
|
||||
// If we find a Oneof return it's name (use lookupOneof because it has an index)
|
||||
IRubyObject oneofDescriptor = rubyDescriptor.lookupOneof(context, args[0]);
|
||||
|
||||
@ -331,9 +410,12 @@ public class RubyMessage extends RubyObject {
|
||||
if (methodName.startsWith(CLEAR_PREFIX)) {
|
||||
methodName = methodName.substring(6);
|
||||
oneofDescriptor = rubyDescriptor.lookupOneof(context, runtime.newSymbol(methodName));
|
||||
|
||||
if (!oneofDescriptor.isNil()) {
|
||||
fieldDescriptor = oneofCases.get(((RubyOneofDescriptor) oneofDescriptor).getDescriptor());
|
||||
if (fieldDescriptor == null) {
|
||||
// Clearing an already cleared oneof; return here to avoid NoMethodError.
|
||||
return context.nil;
|
||||
}
|
||||
}
|
||||
|
||||
if (fieldDescriptor == null) {
|
||||
@ -379,8 +461,7 @@ public class RubyMessage extends RubyObject {
|
||||
} else if (methodName.endsWith(CONST_SUFFIX)) {
|
||||
methodName = methodName.substring(0, methodName.length() - 6);
|
||||
fieldDescriptor = descriptor.findFieldByName(methodName);
|
||||
|
||||
if (fieldDescriptor.getType() == FieldDescriptor.Type.ENUM) {
|
||||
if (fieldDescriptor != null && fieldDescriptor.getType() == FieldDescriptor.Type.ENUM) {
|
||||
IRubyObject enumValue = getFieldInternal(context, fieldDescriptor);
|
||||
|
||||
if (!enumValue.isNil()) {
|
||||
@ -404,17 +485,21 @@ public class RubyMessage extends RubyObject {
|
||||
|
||||
methodName = methodName.substring(0, methodName.length() - 1); // Trim equals sign
|
||||
FieldDescriptor fieldDescriptor = descriptor.findFieldByName(methodName);
|
||||
|
||||
if (fieldDescriptor != null) {
|
||||
return setFieldInternal(context, fieldDescriptor, args[1]);
|
||||
}
|
||||
|
||||
IRubyObject oneofDescriptor = rubyDescriptor.lookupOneof(context, RubyString.newString(context.runtime, methodName));
|
||||
if (!oneofDescriptor.isNil()) {
|
||||
throw runtime.newRuntimeError("Oneof accessors are read-only.");
|
||||
}
|
||||
|
||||
if (methodName.endsWith(AS_VALUE_SUFFIX)) {
|
||||
methodName = methodName.substring(0, methodName.length() - 9);
|
||||
|
||||
fieldDescriptor = descriptor.findFieldByName(methodName);
|
||||
|
||||
if (fieldDescriptor != null) {
|
||||
if (fieldDescriptor != null && isWrappable(fieldDescriptor)) {
|
||||
if (args[1].isNil()) {
|
||||
return setFieldInternal(context, fieldDescriptor, args[1]);
|
||||
}
|
||||
|
@ -66,8 +66,11 @@ module BasicTest
|
||||
def test_issue_8559_crash
|
||||
msg = TestMessage.new
|
||||
msg.repeated_int32 = ::Google::Protobuf::RepeatedField.new(:int32, [1, 2, 3])
|
||||
# TODO: Remove the platform check once https://github.com/jruby/jruby/issues/6818 is released in JRuby 9.3.0.0
|
||||
GC.start(full_mark: true, immediate_sweep: true) unless RUBY_PLATFORM == "java"
|
||||
|
||||
# https://github.com/jruby/jruby/issues/6818 was fixed in JRuby 9.3.0.0
|
||||
if cruby_or_jruby_9_3_or_higher?
|
||||
GC.start(full_mark: true, immediate_sweep: true)
|
||||
end
|
||||
TestMessage.encode(msg)
|
||||
end
|
||||
|
||||
@ -99,7 +102,7 @@ module BasicTest
|
||||
|
||||
begin
|
||||
encoded = msgclass.encode(m)
|
||||
rescue java.lang.NullPointerException => e
|
||||
rescue java.lang.NullPointerException
|
||||
flunk "NPE rescued"
|
||||
end
|
||||
decoded = msgclass.decode(encoded)
|
||||
@ -173,7 +176,7 @@ module BasicTest
|
||||
m = TestSingularFields.new
|
||||
|
||||
m.singular_int32 = -42
|
||||
assert_equal -42, m.singular_int32
|
||||
assert_equal( -42, m.singular_int32 )
|
||||
m.clear_singular_int32
|
||||
assert_equal 0, m.singular_int32
|
||||
|
||||
@ -568,8 +571,6 @@ module BasicTest
|
||||
|
||||
|
||||
def test_json_maps
|
||||
# TODO: Fix JSON in JRuby version.
|
||||
return if RUBY_PLATFORM == "java"
|
||||
m = MapMessage.new(:map_string_int32 => {"a" => 1})
|
||||
expected = {mapStringInt32: {a: 1}, mapStringMsg: {}, mapStringEnum: {}}
|
||||
expected_preserve = {map_string_int32: {a: 1}, map_string_msg: {}, map_string_enum: {}}
|
||||
@ -583,8 +584,6 @@ module BasicTest
|
||||
end
|
||||
|
||||
def test_json_maps_emit_defaults_submsg
|
||||
# TODO: Fix JSON in JRuby version.
|
||||
return if RUBY_PLATFORM == "java"
|
||||
m = MapMessage.new(:map_string_msg => {"a" => TestMessage2.new(foo: 0)})
|
||||
expected = {mapStringInt32: {}, mapStringMsg: {a: {foo: 0}}, mapStringEnum: {}}
|
||||
|
||||
@ -594,8 +593,6 @@ module BasicTest
|
||||
end
|
||||
|
||||
def test_json_emit_defaults_submsg
|
||||
# TODO: Fix JSON in JRuby version.
|
||||
return if RUBY_PLATFORM == "java"
|
||||
m = TestSingularFields.new(singular_msg: proto_module::TestMessage2.new)
|
||||
|
||||
expected = {
|
||||
@ -618,8 +615,6 @@ module BasicTest
|
||||
end
|
||||
|
||||
def test_respond_to
|
||||
# This test fails with JRuby 1.7.23, likely because of an old JRuby bug.
|
||||
return if RUBY_PLATFORM == "java"
|
||||
msg = MapMessage.new
|
||||
assert msg.respond_to?(:map_string_int32)
|
||||
assert !msg.respond_to?(:bacon)
|
||||
@ -694,5 +689,51 @@ module BasicTest
|
||||
m2 = proto_module::TestMessage.decode(proto_module::TestMessage.encode(m))
|
||||
assert_equal m2, m
|
||||
end
|
||||
|
||||
def test_map_fields_respond_to? # regression test for issue 9202
|
||||
msg = proto_module::MapMessage.new
|
||||
assert msg.respond_to?(:map_string_int32=)
|
||||
msg.map_string_int32 = Google::Protobuf::Map.new(:string, :int32)
|
||||
assert msg.respond_to?(:map_string_int32)
|
||||
assert_equal( Google::Protobuf::Map.new(:string, :int32), msg.map_string_int32 )
|
||||
assert msg.respond_to?(:clear_map_string_int32)
|
||||
msg.clear_map_string_int32
|
||||
|
||||
assert !msg.respond_to?(:has_map_string_int32?)
|
||||
assert_raise NoMethodError do
|
||||
msg.has_map_string_int32?
|
||||
end
|
||||
assert !msg.respond_to?(:map_string_int32_as_value)
|
||||
assert_raise NoMethodError do
|
||||
msg.map_string_int32_as_value
|
||||
end
|
||||
assert !msg.respond_to?(:map_string_int32_as_value=)
|
||||
assert_raise NoMethodError do
|
||||
msg.map_string_int32_as_value = :boom
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_oneof_fields_respond_to? # regression test for issue 9202
|
||||
msg = proto_module::OneofMessage.new
|
||||
# `has_` prefix + "?" suffix actions should only work for oneofs fields.
|
||||
assert msg.has_my_oneof?
|
||||
assert msg.respond_to? :has_my_oneof?
|
||||
assert !msg.respond_to?( :has_a? )
|
||||
assert_raise NoMethodError do
|
||||
msg.has_a?
|
||||
end
|
||||
assert !msg.respond_to?( :has_b? )
|
||||
assert_raise NoMethodError do
|
||||
msg.has_b?
|
||||
end
|
||||
assert !msg.respond_to?( :has_c? )
|
||||
assert_raise NoMethodError do
|
||||
msg.has_c?
|
||||
end
|
||||
assert !msg.respond_to?( :has_d? )
|
||||
assert_raise NoMethodError do
|
||||
msg.has_d?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -142,7 +142,7 @@ module BasicTestProto2
|
||||
m = TestMessageDefaults.new
|
||||
|
||||
m.optional_int32 = -42
|
||||
assert_equal -42, m.optional_int32
|
||||
assert_equal( -42, m.optional_int32 )
|
||||
assert m.has_optional_int32?
|
||||
m.clear_optional_int32
|
||||
assert_equal 1, m.optional_int32
|
||||
@ -255,5 +255,20 @@ module BasicTestProto2
|
||||
assert_equal "tests/basic_test_proto2.proto", file_descriptor.name
|
||||
assert_equal :proto2, file_descriptor.syntax
|
||||
end
|
||||
|
||||
def test_oneof_fields_respond_to? # regression test for issue 9202
|
||||
msg = proto_module::OneofMessage.new(a: "foo")
|
||||
# `has_` prefix + "?" suffix actions should only work for oneofs fields.
|
||||
assert msg.respond_to? :has_my_oneof?
|
||||
assert msg.has_my_oneof?
|
||||
assert msg.respond_to? :has_a?
|
||||
assert msg.has_a?
|
||||
assert msg.respond_to? :has_b?
|
||||
assert !msg.has_b?
|
||||
assert msg.respond_to? :has_c?
|
||||
assert !msg.has_c?
|
||||
assert msg.respond_to? :has_d?
|
||||
assert !msg.has_d?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -796,7 +796,7 @@ module CommonTests
|
||||
m.repeated_string += %w[two three]
|
||||
assert_equal %w[one two three], m.repeated_string
|
||||
|
||||
m.repeated_string.push *['four', 'five']
|
||||
m.repeated_string.push( *['four', 'five'] )
|
||||
assert_equal %w[one two three four five], m.repeated_string
|
||||
|
||||
m.repeated_string.push 'six', 'seven'
|
||||
@ -1085,8 +1085,6 @@ module CommonTests
|
||||
end
|
||||
|
||||
def test_json
|
||||
# TODO: Fix JSON in JRuby version.
|
||||
return if RUBY_PLATFORM == "java"
|
||||
m = proto_module::TestMessage.new(:optional_int32 => 1234,
|
||||
:optional_int64 => -0x1_0000_0000,
|
||||
:optional_uint32 => 0x8000_0000,
|
||||
@ -1288,6 +1286,7 @@ module CommonTests
|
||||
m2 = proto_module::Wrapper.decode(m.to_proto)
|
||||
run_asserts.call(m2)
|
||||
m3 = proto_module::Wrapper.decode_json(m.to_json)
|
||||
run_asserts.call(m3)
|
||||
end
|
||||
|
||||
def test_wrapper_getters
|
||||
@ -1539,8 +1538,6 @@ module CommonTests
|
||||
assert_nil m.bytes_as_value
|
||||
}
|
||||
|
||||
m = proto_module::Wrapper.new
|
||||
|
||||
m2 = proto_module::Wrapper.new(
|
||||
double: Google::Protobuf::DoubleValue.new(value: 2.0),
|
||||
float: Google::Protobuf::FloatValue.new(value: 4.0),
|
||||
@ -1787,27 +1784,200 @@ module CommonTests
|
||||
assert_nil h[m2]
|
||||
end
|
||||
|
||||
def cruby_or_jruby_9_3_or_higher?
|
||||
# https://github.com/jruby/jruby/issues/6818 was fixed in JRuby 9.3.0.0
|
||||
match = RUBY_PLATFORM == "java" &&
|
||||
JRUBY_VERSION.match(/^(\d+)\.(\d+)\.\d+\.\d+$/)
|
||||
match && (match[1].to_i > 9 || (match[1].to_i == 9 && match[2].to_i >= 3))
|
||||
end
|
||||
|
||||
def test_object_gc
|
||||
m = proto_module::TestMessage.new(optional_msg: proto_module::TestMessage2.new)
|
||||
m.optional_msg
|
||||
# TODO: Remove the platform check once https://github.com/jruby/jruby/issues/6818 is released in JRuby 9.3.0.0
|
||||
GC.start(full_mark: true, immediate_sweep: true) unless RUBY_PLATFORM == "java"
|
||||
# https://github.com/jruby/jruby/issues/6818 was fixed in JRuby 9.3.0.0
|
||||
GC.start(full_mark: true, immediate_sweep: true) if cruby_or_jruby_9_3_or_higher?
|
||||
m.optional_msg.inspect
|
||||
end
|
||||
|
||||
def test_object_gc_freeze
|
||||
m = proto_module::TestMessage.new
|
||||
m.repeated_float.freeze
|
||||
# TODO: Remove the platform check once https://github.com/jruby/jruby/issues/6818 is released in JRuby 9.3.0.0
|
||||
GC.start(full_mark: true) unless RUBY_PLATFORM == "java"
|
||||
# https://github.com/jruby/jruby/issues/6818 was fixed in JRuby 9.3.0.0
|
||||
GC.start(full_mark: true) if cruby_or_jruby_9_3_or_higher?
|
||||
|
||||
# Make sure we remember that the object is frozen.
|
||||
# The wrapper object contains this information, so we need to ensure that
|
||||
# the previous GC did not collect it.
|
||||
assert m.repeated_float.frozen?
|
||||
|
||||
# TODO: Remove the platform check once https://github.com/jruby/jruby/issues/6818 is released in JRuby 9.3.0.0
|
||||
GC.start(full_mark: true, immediate_sweep: true) unless RUBY_PLATFORM == "java"
|
||||
# https://github.com/jruby/jruby/issues/6818 was fixed in JRuby 9.3.0.0
|
||||
GC.start(full_mark: true, immediate_sweep: true) if cruby_or_jruby_9_3_or_higher?
|
||||
assert m.repeated_float.frozen?
|
||||
end
|
||||
|
||||
def test_optional_fields_respond_to? # regression test for issue 9202
|
||||
msg = proto_module::TestMessage.new
|
||||
assert msg.respond_to? :optional_int32=
|
||||
msg.optional_int32 = 42
|
||||
|
||||
assert msg.respond_to? :optional_int32
|
||||
assert_equal 42, msg.optional_int32
|
||||
|
||||
assert msg.respond_to? :clear_optional_int32
|
||||
msg.clear_optional_int32
|
||||
assert_equal 0, msg.optional_int32
|
||||
|
||||
assert msg.respond_to? :has_optional_int32?
|
||||
assert !msg.has_optional_int32?
|
||||
|
||||
assert !msg.respond_to?( :optional_int32_as_value= )
|
||||
assert_raise NoMethodError do
|
||||
msg.optional_int32_as_value = 42
|
||||
end
|
||||
|
||||
assert !msg.respond_to?( :optional_int32_as_value )
|
||||
assert_raise NoMethodError do
|
||||
msg.optional_int32_as_value
|
||||
end
|
||||
|
||||
assert msg.respond_to? :optional_enum_const
|
||||
assert_equal 0, msg.optional_enum_const
|
||||
|
||||
assert !msg.respond_to?( :foo )
|
||||
assert_raise NoMethodError do
|
||||
msg.foo
|
||||
end
|
||||
|
||||
assert !msg.respond_to?( :foo_const )
|
||||
assert_raise NoMethodError do
|
||||
msg.foo_const
|
||||
end
|
||||
|
||||
assert !msg.respond_to?( :optional_int32_const )
|
||||
assert_raise NoMethodError do
|
||||
msg.optional_int32_const
|
||||
end
|
||||
end
|
||||
|
||||
def test_oneof_fields_respond_to? # regression test for issue 9202
|
||||
msg = proto_module::OneofMessage.new
|
||||
|
||||
# names of the elements of a oneof and the oneof itself are valid actions.
|
||||
assert msg.respond_to? :my_oneof
|
||||
assert_nil msg.my_oneof
|
||||
assert msg.respond_to? :a
|
||||
assert_equal "", msg.a
|
||||
assert msg.respond_to? :b
|
||||
assert_equal 0, msg.b
|
||||
assert msg.respond_to? :c
|
||||
assert_nil msg.c
|
||||
assert msg.respond_to? :d
|
||||
assert_equal :Default, msg.d
|
||||
|
||||
# `clear` prefix actions work on elements of a oneof and the oneof itself.
|
||||
assert msg.respond_to? :clear_my_oneof
|
||||
msg.clear_my_oneof
|
||||
# Repeatedly clearing a oneof used to cause a NoMethodError under JRuby
|
||||
msg.clear_my_oneof
|
||||
assert msg.respond_to? :clear_a
|
||||
msg.clear_a
|
||||
assert msg.respond_to? :clear_b
|
||||
msg.clear_b
|
||||
assert msg.respond_to? :clear_c
|
||||
msg.clear_c
|
||||
assert msg.respond_to? :clear_d
|
||||
msg.clear_d
|
||||
|
||||
# `=` suffix actions should work on elements of a oneof but not the oneof itself.
|
||||
assert !msg.respond_to?( :my_oneof= )
|
||||
error = assert_raise RuntimeError do
|
||||
msg.my_oneof = nil
|
||||
end
|
||||
assert_equal "Oneof accessors are read-only.", error.message
|
||||
assert msg.respond_to? :a=
|
||||
msg.a = "foo"
|
||||
assert msg.respond_to? :b=
|
||||
msg.b = 42
|
||||
assert msg.respond_to? :c=
|
||||
msg.c = proto_module::TestMessage2.new
|
||||
assert msg.respond_to? :d=
|
||||
msg.d = :Default
|
||||
|
||||
# `has_` prefix + "?" suffix actions work for oneofs fields.
|
||||
assert msg.respond_to? :has_my_oneof?
|
||||
assert msg.has_my_oneof?
|
||||
|
||||
# `_as_value` suffix actions should only work for wrapped fields.
|
||||
assert !msg.respond_to?( :my_oneof_as_value )
|
||||
assert_raise NoMethodError do
|
||||
msg.my_oneof_as_value
|
||||
end
|
||||
assert !msg.respond_to?( :a_as_value )
|
||||
assert_raise NoMethodError do
|
||||
msg.a_as_value
|
||||
end
|
||||
assert !msg.respond_to?( :b_as_value )
|
||||
assert_raise NoMethodError do
|
||||
msg.b_as_value
|
||||
end
|
||||
assert !msg.respond_to?( :c_as_value )
|
||||
assert_raise NoMethodError do
|
||||
msg.c_as_value
|
||||
end
|
||||
assert !msg.respond_to?( :d_as_value )
|
||||
assert_raise NoMethodError do
|
||||
msg.d_as_value
|
||||
end
|
||||
|
||||
# `_as_value=` suffix actions should only work for wrapped fields.
|
||||
assert !msg.respond_to?( :my_oneof_as_value= )
|
||||
assert_raise NoMethodError do
|
||||
msg.my_oneof_as_value = :boom
|
||||
end
|
||||
assert !msg.respond_to?( :a_as_value= )
|
||||
assert_raise NoMethodError do
|
||||
msg.a_as_value = ""
|
||||
end
|
||||
assert !msg.respond_to?( :b_as_value= )
|
||||
assert_raise NoMethodError do
|
||||
msg.b_as_value = 42
|
||||
end
|
||||
assert !msg.respond_to?( :c_as_value= )
|
||||
assert_raise NoMethodError do
|
||||
msg.c_as_value = proto_module::TestMessage2.new
|
||||
end
|
||||
assert !msg.respond_to?( :d_as_value= )
|
||||
assert_raise NoMethodError do
|
||||
msg.d_as_value = :Default
|
||||
end
|
||||
|
||||
# `_const` suffix actions should only work for enum fields.
|
||||
assert !msg.respond_to?( :my_oneof_const )
|
||||
assert_raise NoMethodError do
|
||||
msg.my_oneof_const
|
||||
end
|
||||
assert !msg.respond_to?( :a_const )
|
||||
assert_raise NoMethodError do
|
||||
msg.a_const
|
||||
end
|
||||
assert !msg.respond_to?( :b_const )
|
||||
assert_raise NoMethodError do
|
||||
msg.b_const
|
||||
end
|
||||
assert !msg.respond_to?( :c_const )
|
||||
assert_raise NoMethodError do
|
||||
msg.c_const
|
||||
end
|
||||
assert msg.respond_to? :d_const
|
||||
assert_equal 0, msg.d_const
|
||||
end
|
||||
|
||||
def test_wrapped_fields_respond_to? # regression test for issue 9202
|
||||
msg = proto_module::Wrapper.new
|
||||
assert msg.respond_to?( :double_as_value= )
|
||||
msg.double_as_value = 42
|
||||
assert msg.respond_to?( :double_as_value )
|
||||
assert_equal 42, msg.double_as_value
|
||||
assert_equal Google::Protobuf::DoubleValue.new(value: 42), msg.double
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user