google-protobuf 3.7.0 → 3.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of google-protobuf might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/ext/google/protobuf_c/convert.c +361 -0
- data/ext/google/protobuf_c/convert.h +75 -0
- data/ext/google/protobuf_c/defs.c +669 -1646
- data/ext/google/protobuf_c/defs.h +107 -0
- data/ext/google/protobuf_c/extconf.rb +13 -8
- data/ext/google/protobuf_c/map.c +330 -477
- data/ext/google/protobuf_c/map.h +66 -0
- data/ext/google/protobuf_c/message.c +1048 -379
- data/ext/google/protobuf_c/message.h +104 -0
- data/ext/google/protobuf_c/protobuf.c +413 -54
- data/ext/google/protobuf_c/protobuf.h +53 -546
- data/ext/google/protobuf_c/repeated_field.c +318 -315
- data/ext/google/protobuf_c/repeated_field.h +63 -0
- data/ext/google/protobuf_c/ruby-upb.c +11115 -0
- data/ext/google/protobuf_c/ruby-upb.h +5612 -0
- data/ext/google/protobuf_c/third_party/utf8_range/LICENSE +21 -0
- data/ext/google/protobuf_c/third_party/utf8_range/naive.c +92 -0
- data/ext/google/protobuf_c/third_party/utf8_range/range2-neon.c +157 -0
- data/ext/google/protobuf_c/third_party/utf8_range/range2-sse.c +170 -0
- data/ext/google/protobuf_c/third_party/utf8_range/utf8_range.h +9 -0
- data/ext/google/protobuf_c/wrap_memcpy.c +4 -3
- data/lib/google/protobuf/any_pb.rb +1 -1
- data/lib/google/protobuf/api_pb.rb +4 -3
- data/lib/google/protobuf/descriptor_dsl.rb +465 -0
- data/lib/google/protobuf/descriptor_pb.rb +269 -0
- data/lib/google/protobuf/duration_pb.rb +1 -1
- data/lib/google/protobuf/empty_pb.rb +1 -1
- data/lib/google/protobuf/field_mask_pb.rb +1 -1
- data/lib/google/protobuf/message_exts.rb +2 -2
- data/lib/google/protobuf/repeated_field.rb +15 -2
- data/lib/google/protobuf/source_context_pb.rb +1 -1
- data/lib/google/protobuf/struct_pb.rb +4 -4
- data/lib/google/protobuf/timestamp_pb.rb +1 -1
- data/lib/google/protobuf/type_pb.rb +9 -8
- data/lib/google/protobuf/well_known_types.rb +20 -4
- data/lib/google/protobuf/wrappers_pb.rb +9 -9
- data/lib/google/protobuf.rb +6 -4
- data/tests/basic.rb +455 -77
- data/tests/generated_code_test.rb +0 -0
- data/tests/stress.rb +1 -1
- metadata +27 -30
- data/ext/google/protobuf_c/encode_decode.c +0 -1574
- data/ext/google/protobuf_c/storage.c +0 -1019
- data/ext/google/protobuf_c/upb.c +0 -17318
- data/ext/google/protobuf_c/upb.h +0 -9755
data/tests/basic.rb
CHANGED
@@ -17,7 +17,6 @@ module BasicTest
|
|
17
17
|
add_message "BadFieldNames" do
|
18
18
|
optional :dup, :int32, 1
|
19
19
|
optional :class, :int32, 2
|
20
|
-
optional :"a.b", :int32, 3
|
21
20
|
end
|
22
21
|
end
|
23
22
|
|
@@ -32,12 +31,91 @@ module BasicTest
|
|
32
31
|
end
|
33
32
|
include CommonTests
|
34
33
|
|
34
|
+
def test_issue_8311_crash
|
35
|
+
Google::Protobuf::DescriptorPool.generated_pool.build do
|
36
|
+
add_file("inner.proto", :syntax => :proto3) do
|
37
|
+
add_message "Inner" do
|
38
|
+
# Removing either of these fixes the segfault.
|
39
|
+
optional :foo, :string, 1
|
40
|
+
optional :bar, :string, 2
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
Google::Protobuf::DescriptorPool.generated_pool.build do
|
46
|
+
add_file("outer.proto", :syntax => :proto3) do
|
47
|
+
add_message "Outer" do
|
48
|
+
repeated :inners, :message, 1, "Inner"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
outer = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("Outer").msgclass
|
54
|
+
|
55
|
+
outer.new(
|
56
|
+
inners: []
|
57
|
+
)['inners'].to_s
|
58
|
+
|
59
|
+
assert_raise Google::Protobuf::TypeError do
|
60
|
+
outer.new(
|
61
|
+
inners: [nil]
|
62
|
+
).to_s
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_issue_8559_crash
|
67
|
+
msg = TestMessage.new
|
68
|
+
msg.repeated_int32 = ::Google::Protobuf::RepeatedField.new(:int32, [1, 2, 3])
|
69
|
+
|
70
|
+
# https://github.com/jruby/jruby/issues/6818 was fixed in JRuby 9.3.0.0
|
71
|
+
if cruby_or_jruby_9_3_or_higher?
|
72
|
+
GC.start(full_mark: true, immediate_sweep: true)
|
73
|
+
end
|
74
|
+
TestMessage.encode(msg)
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_issue_9440
|
78
|
+
msg = HelloRequest.new
|
79
|
+
msg.id = 8
|
80
|
+
assert_equal 8, msg.id
|
81
|
+
msg.version = '1'
|
82
|
+
assert_equal 8, msg.id
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_issue_9507
|
86
|
+
pool = Google::Protobuf::DescriptorPool.new
|
87
|
+
pool.build do
|
88
|
+
add_message "NpeMessage" do
|
89
|
+
optional :type, :enum, 1, "TestEnum"
|
90
|
+
optional :other, :string, 2
|
91
|
+
end
|
92
|
+
add_enum "TestEnum" do
|
93
|
+
value :Something, 0
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
msgclass = pool.lookup("NpeMessage").msgclass
|
98
|
+
|
99
|
+
m = msgclass.new(
|
100
|
+
other: "foo" # must be set, but can be blank
|
101
|
+
)
|
102
|
+
|
103
|
+
begin
|
104
|
+
encoded = msgclass.encode(m)
|
105
|
+
rescue java.lang.NullPointerException
|
106
|
+
flunk "NPE rescued"
|
107
|
+
end
|
108
|
+
decoded = msgclass.decode(encoded)
|
109
|
+
decoded.inspect
|
110
|
+
decoded.to_proto
|
111
|
+
end
|
112
|
+
|
35
113
|
def test_has_field
|
36
|
-
m =
|
37
|
-
assert !m.
|
38
|
-
m.
|
39
|
-
assert m.
|
40
|
-
assert
|
114
|
+
m = TestSingularFields.new
|
115
|
+
assert !m.has_singular_msg?
|
116
|
+
m.singular_msg = TestMessage2.new
|
117
|
+
assert m.has_singular_msg?
|
118
|
+
assert TestSingularFields.descriptor.lookup('singular_msg').has?(m)
|
41
119
|
|
42
120
|
m = OneofMessage.new
|
43
121
|
assert !m.has_my_oneof?
|
@@ -46,32 +124,31 @@ module BasicTest
|
|
46
124
|
assert_raise NoMethodError do
|
47
125
|
m.has_a?
|
48
126
|
end
|
49
|
-
|
50
|
-
OneofMessage.descriptor.lookup('a').has?(m)
|
51
|
-
end
|
127
|
+
assert_true OneofMessage.descriptor.lookup('a').has?(m)
|
52
128
|
|
53
|
-
m =
|
129
|
+
m = TestSingularFields.new
|
54
130
|
assert_raise NoMethodError do
|
55
|
-
m.
|
131
|
+
m.has_singular_int32?
|
56
132
|
end
|
57
133
|
assert_raise ArgumentError do
|
58
|
-
|
134
|
+
TestSingularFields.descriptor.lookup('singular_int32').has?(m)
|
59
135
|
end
|
60
136
|
|
61
137
|
assert_raise NoMethodError do
|
62
|
-
m.
|
138
|
+
m.has_singular_string?
|
63
139
|
end
|
64
140
|
assert_raise ArgumentError do
|
65
|
-
|
141
|
+
TestSingularFields.descriptor.lookup('singular_string').has?(m)
|
66
142
|
end
|
67
143
|
|
68
144
|
assert_raise NoMethodError do
|
69
|
-
m.
|
145
|
+
m.has_singular_bool?
|
70
146
|
end
|
71
147
|
assert_raise ArgumentError do
|
72
|
-
|
148
|
+
TestSingularFields.descriptor.lookup('singular_bool').has?(m)
|
73
149
|
end
|
74
150
|
|
151
|
+
m = TestMessage.new
|
75
152
|
assert_raise NoMethodError do
|
76
153
|
m.has_repeated_msg?
|
77
154
|
end
|
@@ -80,40 +157,70 @@ module BasicTest
|
|
80
157
|
end
|
81
158
|
end
|
82
159
|
|
160
|
+
def test_no_presence
|
161
|
+
m = TestSingularFields.new
|
162
|
+
|
163
|
+
# Explicitly setting to zero does not cause anything to be serialized.
|
164
|
+
m.singular_int32 = 0
|
165
|
+
assert_equal "", TestSingularFields.encode(m)
|
166
|
+
|
167
|
+
# Explicitly setting to a non-zero value *does* cause serialization.
|
168
|
+
m.singular_int32 = 1
|
169
|
+
assert_not_equal "", TestSingularFields.encode(m)
|
170
|
+
|
171
|
+
m.singular_int32 = 0
|
172
|
+
assert_equal "", TestSingularFields.encode(m)
|
173
|
+
end
|
174
|
+
|
83
175
|
def test_set_clear_defaults
|
176
|
+
m = TestSingularFields.new
|
177
|
+
|
178
|
+
m.singular_int32 = -42
|
179
|
+
assert_equal( -42, m.singular_int32 )
|
180
|
+
m.clear_singular_int32
|
181
|
+
assert_equal 0, m.singular_int32
|
182
|
+
|
183
|
+
m.singular_int32 = 50
|
184
|
+
assert_equal 50, m.singular_int32
|
185
|
+
TestSingularFields.descriptor.lookup('singular_int32').clear(m)
|
186
|
+
assert_equal 0, m.singular_int32
|
187
|
+
|
188
|
+
m.singular_string = "foo bar"
|
189
|
+
assert_equal "foo bar", m.singular_string
|
190
|
+
m.clear_singular_string
|
191
|
+
assert_equal "", m.singular_string
|
192
|
+
|
193
|
+
m.singular_string = "foo"
|
194
|
+
assert_equal "foo", m.singular_string
|
195
|
+
TestSingularFields.descriptor.lookup('singular_string').clear(m)
|
196
|
+
assert_equal "", m.singular_string
|
197
|
+
|
198
|
+
m.singular_msg = TestMessage2.new(:foo => 42)
|
199
|
+
assert_equal TestMessage2.new(:foo => 42), m.singular_msg
|
200
|
+
assert m.has_singular_msg?
|
201
|
+
m.clear_singular_msg
|
202
|
+
assert_equal nil, m.singular_msg
|
203
|
+
assert !m.has_singular_msg?
|
204
|
+
|
205
|
+
m.singular_msg = TestMessage2.new(:foo => 42)
|
206
|
+
assert_equal TestMessage2.new(:foo => 42), m.singular_msg
|
207
|
+
TestSingularFields.descriptor.lookup('singular_msg').clear(m)
|
208
|
+
assert_equal nil, m.singular_msg
|
209
|
+
end
|
210
|
+
|
211
|
+
def test_import_proto2
|
84
212
|
m = TestMessage.new
|
213
|
+
assert !m.has_optional_proto2_submessage?
|
214
|
+
m.optional_proto2_submessage = ::FooBar::Proto2::TestImportedMessage.new
|
215
|
+
assert m.has_optional_proto2_submessage?
|
216
|
+
assert TestMessage.descriptor.lookup('optional_proto2_submessage').has?(m)
|
217
|
+
|
218
|
+
m.clear_optional_proto2_submessage
|
219
|
+
assert !m.has_optional_proto2_submessage?
|
220
|
+
end
|
85
221
|
|
86
|
-
|
87
|
-
|
88
|
-
m.clear_optional_int32
|
89
|
-
assert_equal 0, m.optional_int32
|
90
|
-
|
91
|
-
m.optional_int32 = 50
|
92
|
-
assert_equal 50, m.optional_int32
|
93
|
-
TestMessage.descriptor.lookup('optional_int32').clear(m)
|
94
|
-
assert_equal 0, m.optional_int32
|
95
|
-
|
96
|
-
m.optional_string = "foo bar"
|
97
|
-
assert_equal "foo bar", m.optional_string
|
98
|
-
m.clear_optional_string
|
99
|
-
assert_equal "", m.optional_string
|
100
|
-
|
101
|
-
m.optional_string = "foo"
|
102
|
-
assert_equal "foo", m.optional_string
|
103
|
-
TestMessage.descriptor.lookup('optional_string').clear(m)
|
104
|
-
assert_equal "", m.optional_string
|
105
|
-
|
106
|
-
m.optional_msg = TestMessage2.new(:foo => 42)
|
107
|
-
assert_equal TestMessage2.new(:foo => 42), m.optional_msg
|
108
|
-
assert m.has_optional_msg?
|
109
|
-
m.clear_optional_msg
|
110
|
-
assert_equal nil, m.optional_msg
|
111
|
-
assert !m.has_optional_msg?
|
112
|
-
|
113
|
-
m.optional_msg = TestMessage2.new(:foo => 42)
|
114
|
-
assert_equal TestMessage2.new(:foo => 42), m.optional_msg
|
115
|
-
TestMessage.descriptor.lookup('optional_msg').clear(m)
|
116
|
-
assert_equal nil, m.optional_msg
|
222
|
+
def test_clear_repeated_fields
|
223
|
+
m = TestMessage.new
|
117
224
|
|
118
225
|
m.repeated_int32.push(1)
|
119
226
|
assert_equal [1], m.repeated_int32
|
@@ -129,6 +236,7 @@ module BasicTest
|
|
129
236
|
m.a = "foo"
|
130
237
|
assert_equal "foo", m.a
|
131
238
|
assert m.has_my_oneof?
|
239
|
+
assert_equal :a, m.my_oneof
|
132
240
|
m.clear_a
|
133
241
|
assert !m.has_my_oneof?
|
134
242
|
|
@@ -144,7 +252,6 @@ module BasicTest
|
|
144
252
|
assert !m.has_my_oneof?
|
145
253
|
end
|
146
254
|
|
147
|
-
|
148
255
|
def test_initialization_map_errors
|
149
256
|
e = assert_raise ArgumentError do
|
150
257
|
TestMessage.new(:hello => "world")
|
@@ -154,12 +261,12 @@ module BasicTest
|
|
154
261
|
e = assert_raise ArgumentError do
|
155
262
|
MapMessage.new(:map_string_int32 => "hello")
|
156
263
|
end
|
157
|
-
assert_equal e.message, "Expected Hash object as initializer value for map field 'map_string_int32'."
|
264
|
+
assert_equal e.message, "Expected Hash object as initializer value for map field 'map_string_int32' (given String)."
|
158
265
|
|
159
266
|
e = assert_raise ArgumentError do
|
160
267
|
TestMessage.new(:repeated_uint32 => "hello")
|
161
268
|
end
|
162
|
-
assert_equal e.message, "Expected array as initializer value for repeated field 'repeated_uint32'."
|
269
|
+
assert_equal e.message, "Expected array as initializer value for repeated field 'repeated_uint32' (given String)."
|
163
270
|
end
|
164
271
|
|
165
272
|
def test_map_field
|
@@ -170,10 +277,12 @@ module BasicTest
|
|
170
277
|
m = MapMessage.new(
|
171
278
|
:map_string_int32 => {"a" => 1, "b" => 2},
|
172
279
|
:map_string_msg => {"a" => TestMessage2.new(:foo => 1),
|
173
|
-
"b" => TestMessage2.new(:foo => 2)}
|
280
|
+
"b" => TestMessage2.new(:foo => 2)},
|
281
|
+
:map_string_enum => {"a" => :A, "b" => :B})
|
174
282
|
assert m.map_string_int32.keys.sort == ["a", "b"]
|
175
283
|
assert m.map_string_int32["a"] == 1
|
176
284
|
assert m.map_string_msg["b"].foo == 2
|
285
|
+
assert m.map_string_enum["a"] == :A
|
177
286
|
|
178
287
|
m.map_string_int32["c"] = 3
|
179
288
|
assert m.map_string_int32["c"] == 3
|
@@ -197,18 +306,37 @@ module BasicTest
|
|
197
306
|
m.map_string_int32 = {}
|
198
307
|
end
|
199
308
|
|
200
|
-
assert_raise TypeError do
|
309
|
+
assert_raise Google::Protobuf::TypeError do
|
201
310
|
m = MapMessage.new(:map_string_int32 => { 1 => "I am not a number" })
|
202
311
|
end
|
203
312
|
end
|
204
313
|
|
314
|
+
def test_map_field_with_symbol
|
315
|
+
m = MapMessage.new
|
316
|
+
assert m.map_string_int32 == {}
|
317
|
+
assert m.map_string_msg == {}
|
318
|
+
|
319
|
+
m = MapMessage.new(
|
320
|
+
:map_string_int32 => {a: 1, "b" => 2},
|
321
|
+
:map_string_msg => {a: TestMessage2.new(:foo => 1),
|
322
|
+
b: TestMessage2.new(:foo => 10)})
|
323
|
+
assert_equal 1, m.map_string_int32[:a]
|
324
|
+
assert_equal 2, m.map_string_int32[:b]
|
325
|
+
assert_equal 10, m.map_string_msg[:b].foo
|
326
|
+
end
|
327
|
+
|
205
328
|
def test_map_inspect
|
206
329
|
m = MapMessage.new(
|
207
330
|
:map_string_int32 => {"a" => 1, "b" => 2},
|
208
331
|
:map_string_msg => {"a" => TestMessage2.new(:foo => 1),
|
209
|
-
"b" => TestMessage2.new(:foo => 2)}
|
210
|
-
|
211
|
-
|
332
|
+
"b" => TestMessage2.new(:foo => 2)},
|
333
|
+
:map_string_enum => {"a" => :A, "b" => :B})
|
334
|
+
|
335
|
+
# JRuby doesn't keep consistent ordering so check for either version
|
336
|
+
expected_a = "<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}>"
|
337
|
+
expected_b = "<BasicTest::MapMessage: map_string_int32: {\"a\"=>1, \"b\"=>2}, map_string_msg: {\"a\"=><BasicTest::TestMessage2: foo: 1>, \"b\"=><BasicTest::TestMessage2: foo: 2>}, map_string_enum: {\"a\"=>:A, \"b\"=>:B}>"
|
338
|
+
inspect_result = m.inspect
|
339
|
+
assert expected_a == inspect_result || expected_b == inspect_result, "Incorrect inspect result: #{inspect_result}"
|
212
340
|
end
|
213
341
|
|
214
342
|
def test_map_corruption
|
@@ -218,6 +346,128 @@ module BasicTest
|
|
218
346
|
m.map_string_int32['aaa'] = 3
|
219
347
|
end
|
220
348
|
|
349
|
+
def test_map_wrappers
|
350
|
+
run_asserts = ->(m) {
|
351
|
+
assert_equal 2.0, m.map_double[0].value
|
352
|
+
assert_equal 4.0, m.map_float[0].value
|
353
|
+
assert_equal 3, m.map_int32[0].value
|
354
|
+
assert_equal 4, m.map_int64[0].value
|
355
|
+
assert_equal 5, m.map_uint32[0].value
|
356
|
+
assert_equal 6, m.map_uint64[0].value
|
357
|
+
assert_equal true, m.map_bool[0].value
|
358
|
+
assert_equal 'str', m.map_string[0].value
|
359
|
+
assert_equal 'fun', m.map_bytes[0].value
|
360
|
+
}
|
361
|
+
|
362
|
+
m = proto_module::Wrapper.new(
|
363
|
+
map_double: {0 => Google::Protobuf::DoubleValue.new(value: 2.0)},
|
364
|
+
map_float: {0 => Google::Protobuf::FloatValue.new(value: 4.0)},
|
365
|
+
map_int32: {0 => Google::Protobuf::Int32Value.new(value: 3)},
|
366
|
+
map_int64: {0 => Google::Protobuf::Int64Value.new(value: 4)},
|
367
|
+
map_uint32: {0 => Google::Protobuf::UInt32Value.new(value: 5)},
|
368
|
+
map_uint64: {0 => Google::Protobuf::UInt64Value.new(value: 6)},
|
369
|
+
map_bool: {0 => Google::Protobuf::BoolValue.new(value: true)},
|
370
|
+
map_string: {0 => Google::Protobuf::StringValue.new(value: 'str')},
|
371
|
+
map_bytes: {0 => Google::Protobuf::BytesValue.new(value: 'fun')},
|
372
|
+
)
|
373
|
+
|
374
|
+
run_asserts.call(m)
|
375
|
+
serialized = proto_module::Wrapper::encode(m)
|
376
|
+
m2 = proto_module::Wrapper::decode(serialized)
|
377
|
+
run_asserts.call(m2)
|
378
|
+
|
379
|
+
# Test the case where we are serializing directly from the parsed form
|
380
|
+
# (before anything lazy is materialized).
|
381
|
+
m3 = proto_module::Wrapper::decode(serialized)
|
382
|
+
serialized2 = proto_module::Wrapper::encode(m3)
|
383
|
+
m4 = proto_module::Wrapper::decode(serialized2)
|
384
|
+
run_asserts.call(m4)
|
385
|
+
|
386
|
+
# Test that the lazy form compares equal to the expanded form.
|
387
|
+
m5 = proto_module::Wrapper::decode(serialized2)
|
388
|
+
assert_equal m5, m
|
389
|
+
end
|
390
|
+
|
391
|
+
def test_map_wrappers_with_default_values
|
392
|
+
run_asserts = ->(m) {
|
393
|
+
assert_equal 0.0, m.map_double[0].value
|
394
|
+
assert_equal 0.0, m.map_float[0].value
|
395
|
+
assert_equal 0, m.map_int32[0].value
|
396
|
+
assert_equal 0, m.map_int64[0].value
|
397
|
+
assert_equal 0, m.map_uint32[0].value
|
398
|
+
assert_equal 0, m.map_uint64[0].value
|
399
|
+
assert_equal false, m.map_bool[0].value
|
400
|
+
assert_equal '', m.map_string[0].value
|
401
|
+
assert_equal '', m.map_bytes[0].value
|
402
|
+
}
|
403
|
+
|
404
|
+
m = proto_module::Wrapper.new(
|
405
|
+
map_double: {0 => Google::Protobuf::DoubleValue.new(value: 0.0)},
|
406
|
+
map_float: {0 => Google::Protobuf::FloatValue.new(value: 0.0)},
|
407
|
+
map_int32: {0 => Google::Protobuf::Int32Value.new(value: 0)},
|
408
|
+
map_int64: {0 => Google::Protobuf::Int64Value.new(value: 0)},
|
409
|
+
map_uint32: {0 => Google::Protobuf::UInt32Value.new(value: 0)},
|
410
|
+
map_uint64: {0 => Google::Protobuf::UInt64Value.new(value: 0)},
|
411
|
+
map_bool: {0 => Google::Protobuf::BoolValue.new(value: false)},
|
412
|
+
map_string: {0 => Google::Protobuf::StringValue.new(value: '')},
|
413
|
+
map_bytes: {0 => Google::Protobuf::BytesValue.new(value: '')},
|
414
|
+
)
|
415
|
+
|
416
|
+
run_asserts.call(m)
|
417
|
+
serialized = proto_module::Wrapper::encode(m)
|
418
|
+
m2 = proto_module::Wrapper::decode(serialized)
|
419
|
+
run_asserts.call(m2)
|
420
|
+
|
421
|
+
# Test the case where we are serializing directly from the parsed form
|
422
|
+
# (before anything lazy is materialized).
|
423
|
+
m3 = proto_module::Wrapper::decode(serialized)
|
424
|
+
serialized2 = proto_module::Wrapper::encode(m3)
|
425
|
+
m4 = proto_module::Wrapper::decode(serialized2)
|
426
|
+
run_asserts.call(m4)
|
427
|
+
|
428
|
+
# Test that the lazy form compares equal to the expanded form.
|
429
|
+
m5 = proto_module::Wrapper::decode(serialized2)
|
430
|
+
assert_equal m5, m
|
431
|
+
end
|
432
|
+
|
433
|
+
def test_map_wrappers_with_no_value
|
434
|
+
run_asserts = ->(m) {
|
435
|
+
assert_equal 0.0, m.map_double[0].value
|
436
|
+
assert_equal 0.0, m.map_float[0].value
|
437
|
+
assert_equal 0, m.map_int32[0].value
|
438
|
+
assert_equal 0, m.map_int64[0].value
|
439
|
+
assert_equal 0, m.map_uint32[0].value
|
440
|
+
assert_equal 0, m.map_uint64[0].value
|
441
|
+
assert_equal false, m.map_bool[0].value
|
442
|
+
assert_equal '', m.map_string[0].value
|
443
|
+
assert_equal '', m.map_bytes[0].value
|
444
|
+
}
|
445
|
+
|
446
|
+
m = proto_module::Wrapper.new(
|
447
|
+
map_double: {0 => Google::Protobuf::DoubleValue.new()},
|
448
|
+
map_float: {0 => Google::Protobuf::FloatValue.new()},
|
449
|
+
map_int32: {0 => Google::Protobuf::Int32Value.new()},
|
450
|
+
map_int64: {0 => Google::Protobuf::Int64Value.new()},
|
451
|
+
map_uint32: {0 => Google::Protobuf::UInt32Value.new()},
|
452
|
+
map_uint64: {0 => Google::Protobuf::UInt64Value.new()},
|
453
|
+
map_bool: {0 => Google::Protobuf::BoolValue.new()},
|
454
|
+
map_string: {0 => Google::Protobuf::StringValue.new()},
|
455
|
+
map_bytes: {0 => Google::Protobuf::BytesValue.new()},
|
456
|
+
)
|
457
|
+
run_asserts.call(m)
|
458
|
+
|
459
|
+
serialized = proto_module::Wrapper::encode(m)
|
460
|
+
m2 = proto_module::Wrapper::decode(serialized)
|
461
|
+
run_asserts.call(m2)
|
462
|
+
|
463
|
+
# Test the case where we are serializing directly from the parsed form
|
464
|
+
# (before anything lazy is materialized).
|
465
|
+
m3 = proto_module::Wrapper::decode(serialized)
|
466
|
+
serialized2 = proto_module::Wrapper::encode(m3)
|
467
|
+
m4 = proto_module::Wrapper::decode(serialized2)
|
468
|
+
run_asserts.call(m4)
|
469
|
+
end
|
470
|
+
|
221
471
|
def test_concurrent_decoding
|
222
472
|
o = Outer.new
|
223
473
|
o.items[0] = Inner.new
|
@@ -237,7 +487,8 @@ module BasicTest
|
|
237
487
|
m = MapMessage.new(
|
238
488
|
:map_string_int32 => {"a" => 1, "b" => 2},
|
239
489
|
:map_string_msg => {"a" => TestMessage2.new(:foo => 1),
|
240
|
-
"b" => TestMessage2.new(:foo => 2)}
|
490
|
+
"b" => TestMessage2.new(:foo => 2)},
|
491
|
+
:map_string_enum => {"a" => :A, "b" => :B})
|
241
492
|
m2 = MapMessage.decode(MapMessage.encode(m))
|
242
493
|
assert m == m2
|
243
494
|
|
@@ -267,6 +518,14 @@ module BasicTest
|
|
267
518
|
assert_match(/No such field: not_in_message/, e.message)
|
268
519
|
end
|
269
520
|
|
521
|
+
#def test_json_quoted_string
|
522
|
+
# m = TestMessage.decode_json(%q(
|
523
|
+
# "optionalInt64": "1",,
|
524
|
+
# }))
|
525
|
+
# puts(m)
|
526
|
+
# assert_equal 1, m.optional_int32
|
527
|
+
#end
|
528
|
+
|
270
529
|
def test_to_h
|
271
530
|
m = TestMessage.new(:optional_bool => true, :optional_double => -10.100001, :optional_string => 'foo', :repeated_string => ['bar1', 'bar2'], :repeated_msg => [TestMessage2.new(:foo => 100)])
|
272
531
|
expected_result = {
|
@@ -278,6 +537,8 @@ module BasicTest
|
|
278
537
|
:optional_int32=>0,
|
279
538
|
:optional_int64=>0,
|
280
539
|
:optional_msg=>nil,
|
540
|
+
:optional_msg2=>nil,
|
541
|
+
:optional_proto2_submessage=>nil,
|
281
542
|
:optional_string=>"foo",
|
282
543
|
:optional_uint32=>0,
|
283
544
|
:optional_uint64=>0,
|
@@ -298,44 +559,62 @@ module BasicTest
|
|
298
559
|
m = MapMessage.new(
|
299
560
|
:map_string_int32 => {"a" => 1, "b" => 2},
|
300
561
|
:map_string_msg => {"a" => TestMessage2.new(:foo => 1),
|
301
|
-
"b" => TestMessage2.new(:foo => 2)}
|
562
|
+
"b" => TestMessage2.new(:foo => 2)},
|
563
|
+
:map_string_enum => {"a" => :A, "b" => :B})
|
302
564
|
expected_result = {
|
303
565
|
:map_string_int32 => {"a" => 1, "b" => 2},
|
304
|
-
:map_string_msg => {"a" => {:foo => 1}, "b" => {:foo => 2}}
|
566
|
+
:map_string_msg => {"a" => {:foo => 1}, "b" => {:foo => 2}},
|
567
|
+
:map_string_enum => {"a" => :A, "b" => :B}
|
305
568
|
}
|
306
569
|
assert_equal expected_result, m.to_h
|
307
570
|
end
|
308
571
|
|
309
572
|
|
310
573
|
def test_json_maps
|
311
|
-
# TODO: Fix JSON in JRuby version.
|
312
|
-
return if RUBY_PLATFORM == "java"
|
313
574
|
m = MapMessage.new(:map_string_int32 => {"a" => 1})
|
314
|
-
expected = {mapStringInt32: {a: 1}, mapStringMsg: {}}
|
315
|
-
expected_preserve = {map_string_int32: {a: 1}, map_string_msg: {}}
|
316
|
-
|
575
|
+
expected = {mapStringInt32: {a: 1}, mapStringMsg: {}, mapStringEnum: {}}
|
576
|
+
expected_preserve = {map_string_int32: {a: 1}, map_string_msg: {}, map_string_enum: {}}
|
577
|
+
assert_equal JSON.parse(MapMessage.encode_json(m, :emit_defaults=>true), :symbolize_names => true), expected
|
317
578
|
|
318
|
-
json = MapMessage.encode_json(m, :preserve_proto_fieldnames => true)
|
319
|
-
|
579
|
+
json = MapMessage.encode_json(m, :preserve_proto_fieldnames => true, :emit_defaults=>true)
|
580
|
+
assert_equal JSON.parse(json, :symbolize_names => true), expected_preserve
|
320
581
|
|
321
582
|
m2 = MapMessage.decode_json(MapMessage.encode_json(m))
|
322
|
-
|
583
|
+
assert_equal m, m2
|
323
584
|
end
|
324
585
|
|
325
586
|
def test_json_maps_emit_defaults_submsg
|
326
|
-
|
327
|
-
|
328
|
-
m = MapMessage.new(:map_string_msg => {"a" => TestMessage2.new})
|
329
|
-
expected = {mapStringInt32: {}, mapStringMsg: {a: {foo: 0}}}
|
587
|
+
m = MapMessage.new(:map_string_msg => {"a" => TestMessage2.new(foo: 0)})
|
588
|
+
expected = {mapStringInt32: {}, mapStringMsg: {a: {foo: 0}}, mapStringEnum: {}}
|
330
589
|
|
331
590
|
actual = MapMessage.encode_json(m, :emit_defaults => true)
|
332
591
|
|
333
|
-
|
592
|
+
assert_equal JSON.parse(actual, :symbolize_names => true), expected
|
593
|
+
end
|
594
|
+
|
595
|
+
def test_json_emit_defaults_submsg
|
596
|
+
m = TestSingularFields.new(singular_msg: proto_module::TestMessage2.new)
|
597
|
+
|
598
|
+
expected = {
|
599
|
+
singularInt32: 0,
|
600
|
+
singularInt64: "0",
|
601
|
+
singularUint32: 0,
|
602
|
+
singularUint64: "0",
|
603
|
+
singularBool: false,
|
604
|
+
singularFloat: 0,
|
605
|
+
singularDouble: 0,
|
606
|
+
singularString: "",
|
607
|
+
singularBytes: "",
|
608
|
+
singularMsg: {},
|
609
|
+
singularEnum: "Default",
|
610
|
+
}
|
611
|
+
|
612
|
+
actual = proto_module::TestMessage.encode_json(m, :emit_defaults => true)
|
613
|
+
|
614
|
+
assert_equal expected, JSON.parse(actual, :symbolize_names => true)
|
334
615
|
end
|
335
616
|
|
336
617
|
def test_respond_to
|
337
|
-
# This test fails with JRuby 1.7.23, likely because of an old JRuby bug.
|
338
|
-
return if RUBY_PLATFORM == "java"
|
339
618
|
msg = MapMessage.new
|
340
619
|
assert msg.respond_to?(:map_string_int32)
|
341
620
|
assert !msg.respond_to?(:bacon)
|
@@ -351,11 +630,110 @@ module BasicTest
|
|
351
630
|
assert nil != file_descriptor
|
352
631
|
assert_equal "tests/basic_test.proto", file_descriptor.name
|
353
632
|
assert_equal :proto3, file_descriptor.syntax
|
633
|
+
end
|
354
634
|
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
635
|
+
# Ruby 2.5 changed to raise FrozenError instead of RuntimeError
|
636
|
+
FrozenErrorType = Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.5') ? RuntimeError : FrozenError
|
637
|
+
|
638
|
+
def test_map_freeze
|
639
|
+
m = proto_module::MapMessage.new
|
640
|
+
m.map_string_int32['a'] = 5
|
641
|
+
m.map_string_msg['b'] = proto_module::TestMessage2.new
|
642
|
+
|
643
|
+
m.map_string_int32.freeze
|
644
|
+
m.map_string_msg.freeze
|
645
|
+
|
646
|
+
assert m.map_string_int32.frozen?
|
647
|
+
assert m.map_string_msg.frozen?
|
648
|
+
|
649
|
+
assert_raise(FrozenErrorType) { m.map_string_int32['foo'] = 1 }
|
650
|
+
assert_raise(FrozenErrorType) { m.map_string_msg['bar'] = proto_module::TestMessage2.new }
|
651
|
+
assert_raise(FrozenErrorType) { m.map_string_int32.delete('a') }
|
652
|
+
assert_raise(FrozenErrorType) { m.map_string_int32.clear }
|
653
|
+
end
|
654
|
+
|
655
|
+
def test_map_length
|
656
|
+
m = proto_module::MapMessage.new
|
657
|
+
assert_equal 0, m.map_string_int32.length
|
658
|
+
assert_equal 0, m.map_string_msg.length
|
659
|
+
assert_equal 0, m.map_string_int32.size
|
660
|
+
assert_equal 0, m.map_string_msg.size
|
661
|
+
|
662
|
+
m.map_string_int32['a'] = 1
|
663
|
+
m.map_string_int32['b'] = 2
|
664
|
+
m.map_string_msg['a'] = proto_module::TestMessage2.new
|
665
|
+
assert_equal 2, m.map_string_int32.length
|
666
|
+
assert_equal 1, m.map_string_msg.length
|
667
|
+
assert_equal 2, m.map_string_int32.size
|
668
|
+
assert_equal 1, m.map_string_msg.size
|
669
|
+
end
|
670
|
+
|
671
|
+
def test_string_with_singleton_class_enabled
|
672
|
+
str = 'foobar'
|
673
|
+
# NOTE: Accessing a singleton class of an object changes its low level class representation
|
674
|
+
# as far as the C API's CLASS_OF() method concerned, exposing the issue
|
675
|
+
str.singleton_class
|
676
|
+
m = proto_module::TestMessage.new(
|
677
|
+
optional_string: str,
|
678
|
+
optional_bytes: str
|
679
|
+
)
|
680
|
+
|
681
|
+
assert_equal str, m.optional_string
|
682
|
+
assert_equal str, m.optional_bytes
|
683
|
+
end
|
684
|
+
|
685
|
+
def test_utf8
|
686
|
+
m = proto_module::TestMessage.new(
|
687
|
+
optional_string: "µpb",
|
688
|
+
)
|
689
|
+
m2 = proto_module::TestMessage.decode(proto_module::TestMessage.encode(m))
|
690
|
+
assert_equal m2, m
|
691
|
+
end
|
692
|
+
|
693
|
+
def test_map_fields_respond_to? # regression test for issue 9202
|
694
|
+
msg = proto_module::MapMessage.new
|
695
|
+
assert msg.respond_to?(:map_string_int32=)
|
696
|
+
msg.map_string_int32 = Google::Protobuf::Map.new(:string, :int32)
|
697
|
+
assert msg.respond_to?(:map_string_int32)
|
698
|
+
assert_equal( Google::Protobuf::Map.new(:string, :int32), msg.map_string_int32 )
|
699
|
+
assert msg.respond_to?(:clear_map_string_int32)
|
700
|
+
msg.clear_map_string_int32
|
701
|
+
|
702
|
+
assert !msg.respond_to?(:has_map_string_int32?)
|
703
|
+
assert_raise NoMethodError do
|
704
|
+
msg.has_map_string_int32?
|
705
|
+
end
|
706
|
+
assert !msg.respond_to?(:map_string_int32_as_value)
|
707
|
+
assert_raise NoMethodError do
|
708
|
+
msg.map_string_int32_as_value
|
709
|
+
end
|
710
|
+
assert !msg.respond_to?(:map_string_int32_as_value=)
|
711
|
+
assert_raise NoMethodError do
|
712
|
+
msg.map_string_int32_as_value = :boom
|
713
|
+
end
|
714
|
+
end
|
715
|
+
end
|
716
|
+
|
717
|
+
def test_oneof_fields_respond_to? # regression test for issue 9202
|
718
|
+
msg = proto_module::OneofMessage.new
|
719
|
+
# `has_` prefix + "?" suffix actions should only work for oneofs fields.
|
720
|
+
assert msg.has_my_oneof?
|
721
|
+
assert msg.respond_to? :has_my_oneof?
|
722
|
+
assert !msg.respond_to?( :has_a? )
|
723
|
+
assert_raise NoMethodError do
|
724
|
+
msg.has_a?
|
725
|
+
end
|
726
|
+
assert !msg.respond_to?( :has_b? )
|
727
|
+
assert_raise NoMethodError do
|
728
|
+
msg.has_b?
|
729
|
+
end
|
730
|
+
assert !msg.respond_to?( :has_c? )
|
731
|
+
assert_raise NoMethodError do
|
732
|
+
msg.has_c?
|
733
|
+
end
|
734
|
+
assert !msg.respond_to?( :has_d? )
|
735
|
+
assert_raise NoMethodError do
|
736
|
+
msg.has_d?
|
359
737
|
end
|
360
738
|
end
|
361
739
|
end
|
File without changes
|