Commit 997bd354 authored by Sorah Fukumori's avatar Sorah Fukumori Committed by Paul Yang

Fix TypeError on decoding enum map values in Ruby (#6262)

value_field_typeclass should be a enum module, not EnumDescriptor
object.

Also expanding tests for enum valued maps.

Fixes #4580
Signed-off-by: 's avatarSorah Fukumori <her@sorah.jp>
parent e5f246d3
...@@ -389,6 +389,9 @@ static bool endmap_handler(void *closure, const void *hd, upb_status* s) { ...@@ -389,6 +389,9 @@ static bool endmap_handler(void *closure, const void *hd, upb_status* s) {
if (mapdata->value_field_type == UPB_TYPE_MESSAGE || if (mapdata->value_field_type == UPB_TYPE_MESSAGE ||
mapdata->value_field_type == UPB_TYPE_ENUM) { mapdata->value_field_type == UPB_TYPE_ENUM) {
value_field_typeclass = get_def_obj(mapdata->value_field_subdef); value_field_typeclass = get_def_obj(mapdata->value_field_subdef);
if (mapdata->value_field_type == UPB_TYPE_ENUM) {
value_field_typeclass = EnumDescriptor_enummodule(value_field_typeclass);
}
} }
value = native_slot_get( value = native_slot_get(
......
...@@ -170,10 +170,12 @@ module BasicTest ...@@ -170,10 +170,12 @@ module BasicTest
m = MapMessage.new( m = MapMessage.new(
:map_string_int32 => {"a" => 1, "b" => 2}, :map_string_int32 => {"a" => 1, "b" => 2},
:map_string_msg => {"a" => TestMessage2.new(:foo => 1), :map_string_msg => {"a" => TestMessage2.new(:foo => 1),
"b" => TestMessage2.new(:foo => 2)}) "b" => TestMessage2.new(:foo => 2)},
:map_string_enum => {"a" => :A, "b" => :B})
assert m.map_string_int32.keys.sort == ["a", "b"] assert m.map_string_int32.keys.sort == ["a", "b"]
assert m.map_string_int32["a"] == 1 assert m.map_string_int32["a"] == 1
assert m.map_string_msg["b"].foo == 2 assert m.map_string_msg["b"].foo == 2
assert m.map_string_enum["a"] == :A
m.map_string_int32["c"] = 3 m.map_string_int32["c"] = 3
assert m.map_string_int32["c"] == 3 assert m.map_string_int32["c"] == 3
...@@ -206,8 +208,9 @@ module BasicTest ...@@ -206,8 +208,9 @@ module BasicTest
m = MapMessage.new( m = MapMessage.new(
:map_string_int32 => {"a" => 1, "b" => 2}, :map_string_int32 => {"a" => 1, "b" => 2},
:map_string_msg => {"a" => TestMessage2.new(:foo => 1), :map_string_msg => {"a" => TestMessage2.new(:foo => 1),
"b" => TestMessage2.new(:foo => 2)}) "b" => TestMessage2.new(:foo => 2)},
expected = "<BasicTest::MapMessage: map_string_int32: {\"b\"=>2, \"a\"=>1}, map_string_msg: {\"b\"=><BasicTest::TestMessage2: foo: 2>, \"a\"=><BasicTest::TestMessage2: foo: 1>}>" :map_string_enum => {"a" => :A, "b" => :B})
expected = "<BasicTest::MapMessage: map_string_int32: {\"b\"=>2, \"a\"=>1}, map_string_msg: {\"b\"=><BasicTest::TestMessage2: foo: 2>, \"a\"=><BasicTest::TestMessage2: foo: 1>}, map_string_enum: {\"b\"=>:B, \"a\"=>:A}>"
assert_equal expected, m.inspect assert_equal expected, m.inspect
end end
...@@ -237,7 +240,8 @@ module BasicTest ...@@ -237,7 +240,8 @@ module BasicTest
m = MapMessage.new( m = MapMessage.new(
:map_string_int32 => {"a" => 1, "b" => 2}, :map_string_int32 => {"a" => 1, "b" => 2},
:map_string_msg => {"a" => TestMessage2.new(:foo => 1), :map_string_msg => {"a" => TestMessage2.new(:foo => 1),
"b" => TestMessage2.new(:foo => 2)}) "b" => TestMessage2.new(:foo => 2)},
:map_string_enum => {"a" => :A, "b" => :B})
m2 = MapMessage.decode(MapMessage.encode(m)) m2 = MapMessage.decode(MapMessage.encode(m))
assert m == m2 assert m == m2
...@@ -298,10 +302,12 @@ module BasicTest ...@@ -298,10 +302,12 @@ module BasicTest
m = MapMessage.new( m = MapMessage.new(
:map_string_int32 => {"a" => 1, "b" => 2}, :map_string_int32 => {"a" => 1, "b" => 2},
:map_string_msg => {"a" => TestMessage2.new(:foo => 1), :map_string_msg => {"a" => TestMessage2.new(:foo => 1),
"b" => TestMessage2.new(:foo => 2)}) "b" => TestMessage2.new(:foo => 2)},
:map_string_enum => {"a" => :A, "b" => :B})
expected_result = { expected_result = {
:map_string_int32 => {"a" => 1, "b" => 2}, :map_string_int32 => {"a" => 1, "b" => 2},
:map_string_msg => {"a" => {:foo => 1}, "b" => {:foo => 2}} :map_string_msg => {"a" => {:foo => 1}, "b" => {:foo => 2}},
:map_string_enum => {"a" => :A, "b" => :B}
} }
assert_equal expected_result, m.to_h assert_equal expected_result, m.to_h
end end
...@@ -311,26 +317,26 @@ module BasicTest ...@@ -311,26 +317,26 @@ module BasicTest
# TODO: Fix JSON in JRuby version. # TODO: Fix JSON in JRuby version.
return if RUBY_PLATFORM == "java" return if RUBY_PLATFORM == "java"
m = MapMessage.new(:map_string_int32 => {"a" => 1}) m = MapMessage.new(:map_string_int32 => {"a" => 1})
expected = {mapStringInt32: {a: 1}, mapStringMsg: {}} expected = {mapStringInt32: {a: 1}, mapStringMsg: {}, mapStringEnum: {}}
expected_preserve = {map_string_int32: {a: 1}, map_string_msg: {}} expected_preserve = {map_string_int32: {a: 1}, map_string_msg: {}, map_string_enum: {}}
assert JSON.parse(MapMessage.encode_json(m), :symbolize_names => true) == expected assert_equal JSON.parse(MapMessage.encode_json(m), :symbolize_names => true), expected
json = MapMessage.encode_json(m, :preserve_proto_fieldnames => true) json = MapMessage.encode_json(m, :preserve_proto_fieldnames => true)
assert JSON.parse(json, :symbolize_names => true) == expected_preserve assert_equal JSON.parse(json, :symbolize_names => true), expected_preserve
m2 = MapMessage.decode_json(MapMessage.encode_json(m)) m2 = MapMessage.decode_json(MapMessage.encode_json(m))
assert m == m2 assert_equal m, m2
end end
def test_json_maps_emit_defaults_submsg def test_json_maps_emit_defaults_submsg
# TODO: Fix JSON in JRuby version. # TODO: Fix JSON in JRuby version.
return if RUBY_PLATFORM == "java" return if RUBY_PLATFORM == "java"
m = MapMessage.new(:map_string_msg => {"a" => TestMessage2.new}) m = MapMessage.new(:map_string_msg => {"a" => TestMessage2.new})
expected = {mapStringInt32: {}, mapStringMsg: {a: {foo: 0}}} expected = {mapStringInt32: {}, mapStringMsg: {a: {foo: 0}}, mapStringEnum: {}}
actual = MapMessage.encode_json(m, :emit_defaults => true) actual = MapMessage.encode_json(m, :emit_defaults => true)
assert JSON.parse(actual, :symbolize_names => true) == expected assert_equal JSON.parse(actual, :symbolize_names => true), expected
end end
def test_respond_to def test_respond_to
......
...@@ -80,6 +80,7 @@ message Recursive2 { ...@@ -80,6 +80,7 @@ message Recursive2 {
message MapMessage { message MapMessage {
map<string, int32> map_string_int32 = 1; map<string, int32> map_string_int32 = 1;
map<string, TestMessage2> map_string_msg = 2; map<string, TestMessage2> map_string_msg = 2;
map<string, TestEnum> map_string_enum = 3;
} }
message MapMessageWireEquiv { message MapMessageWireEquiv {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment