google-protobuf 3.19.0.rc.1-x86_64-darwin

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of google-protobuf might be problematic. Click here for more details.

Files changed (43) hide show
  1. checksums.yaml +7 -0
  2. data/ext/google/protobuf_c/convert.c +348 -0
  3. data/ext/google/protobuf_c/convert.h +72 -0
  4. data/ext/google/protobuf_c/defs.c +1284 -0
  5. data/ext/google/protobuf_c/defs.h +107 -0
  6. data/ext/google/protobuf_c/extconf.rb +20 -0
  7. data/ext/google/protobuf_c/map.c +694 -0
  8. data/ext/google/protobuf_c/map.h +67 -0
  9. data/ext/google/protobuf_c/message.c +1328 -0
  10. data/ext/google/protobuf_c/message.h +101 -0
  11. data/ext/google/protobuf_c/protobuf.c +470 -0
  12. data/ext/google/protobuf_c/protobuf.h +117 -0
  13. data/ext/google/protobuf_c/repeated_field.c +659 -0
  14. data/ext/google/protobuf_c/repeated_field.h +63 -0
  15. data/ext/google/protobuf_c/ruby-upb.c +9171 -0
  16. data/ext/google/protobuf_c/ruby-upb.h +4704 -0
  17. data/ext/google/protobuf_c/wrap_memcpy.c +51 -0
  18. data/lib/google/2.3/protobuf_c.bundle +0 -0
  19. data/lib/google/2.4/protobuf_c.bundle +0 -0
  20. data/lib/google/2.5/protobuf_c.bundle +0 -0
  21. data/lib/google/2.6/protobuf_c.bundle +0 -0
  22. data/lib/google/2.7/protobuf_c.bundle +0 -0
  23. data/lib/google/3.0/protobuf_c.bundle +0 -0
  24. data/lib/google/protobuf/any_pb.rb +19 -0
  25. data/lib/google/protobuf/api_pb.rb +41 -0
  26. data/lib/google/protobuf/descriptor_dsl.rb +458 -0
  27. data/lib/google/protobuf/descriptor_pb.rb +266 -0
  28. data/lib/google/protobuf/duration_pb.rb +19 -0
  29. data/lib/google/protobuf/empty_pb.rb +17 -0
  30. data/lib/google/protobuf/field_mask_pb.rb +18 -0
  31. data/lib/google/protobuf/message_exts.rb +53 -0
  32. data/lib/google/protobuf/repeated_field.rb +188 -0
  33. data/lib/google/protobuf/source_context_pb.rb +18 -0
  34. data/lib/google/protobuf/struct_pb.rb +37 -0
  35. data/lib/google/protobuf/timestamp_pb.rb +19 -0
  36. data/lib/google/protobuf/type_pb.rb +91 -0
  37. data/lib/google/protobuf/well_known_types.rb +235 -0
  38. data/lib/google/protobuf/wrappers_pb.rb +50 -0
  39. data/lib/google/protobuf.rb +79 -0
  40. data/tests/basic.rb +640 -0
  41. data/tests/generated_code_test.rb +23 -0
  42. data/tests/stress.rb +38 -0
  43. metadata +144 -0
data/tests/basic.rb ADDED
@@ -0,0 +1,640 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # basic_test_pb.rb is in the same directory as this test.
4
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__)))
5
+
6
+ require 'basic_test_pb'
7
+ require 'common_tests'
8
+ require 'google/protobuf'
9
+ require 'json'
10
+ require 'test/unit'
11
+
12
+ # ------------- generated code --------------
13
+
14
+ module BasicTest
15
+ pool = Google::Protobuf::DescriptorPool.new
16
+ pool.build do
17
+ add_message "BadFieldNames" do
18
+ optional :dup, :int32, 1
19
+ optional :class, :int32, 2
20
+ end
21
+ end
22
+
23
+ BadFieldNames = pool.lookup("BadFieldNames").msgclass
24
+
25
+ # ------------ test cases ---------------
26
+
27
+ class MessageContainerTest < Test::Unit::TestCase
28
+ # Required by CommonTests module to resolve proto3 proto classes used in tests.
29
+ def proto_module
30
+ ::BasicTest
31
+ end
32
+ include CommonTests
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
+ # TODO: Remove the platform check once https://github.com/jruby/jruby/issues/6818 is released in JRuby 9.3.0.0
70
+ GC.start(full_mark: true, immediate_sweep: true) unless RUBY_PLATFORM == "java"
71
+ TestMessage.encode(msg)
72
+ end
73
+
74
+ def test_has_field
75
+ m = TestSingularFields.new
76
+ assert !m.has_singular_msg?
77
+ m.singular_msg = TestMessage2.new
78
+ assert m.has_singular_msg?
79
+ assert TestSingularFields.descriptor.lookup('singular_msg').has?(m)
80
+
81
+ m = OneofMessage.new
82
+ assert !m.has_my_oneof?
83
+ m.a = "foo"
84
+ assert m.has_my_oneof?
85
+ assert_raise NoMethodError do
86
+ m.has_a?
87
+ end
88
+ assert_true OneofMessage.descriptor.lookup('a').has?(m)
89
+
90
+ m = TestSingularFields.new
91
+ assert_raise NoMethodError do
92
+ m.has_singular_int32?
93
+ end
94
+ assert_raise ArgumentError do
95
+ TestSingularFields.descriptor.lookup('singular_int32').has?(m)
96
+ end
97
+
98
+ assert_raise NoMethodError do
99
+ m.has_singular_string?
100
+ end
101
+ assert_raise ArgumentError do
102
+ TestSingularFields.descriptor.lookup('singular_string').has?(m)
103
+ end
104
+
105
+ assert_raise NoMethodError do
106
+ m.has_singular_bool?
107
+ end
108
+ assert_raise ArgumentError do
109
+ TestSingularFields.descriptor.lookup('singular_bool').has?(m)
110
+ end
111
+
112
+ m = TestMessage.new
113
+ assert_raise NoMethodError do
114
+ m.has_repeated_msg?
115
+ end
116
+ assert_raise ArgumentError do
117
+ TestMessage.descriptor.lookup('repeated_msg').has?(m)
118
+ end
119
+ end
120
+
121
+ def test_no_presence
122
+ m = TestSingularFields.new
123
+
124
+ # Explicitly setting to zero does not cause anything to be serialized.
125
+ m.singular_int32 = 0
126
+ assert_equal "", TestSingularFields.encode(m)
127
+
128
+ # Explicitly setting to a non-zero value *does* cause serialization.
129
+ m.singular_int32 = 1
130
+ assert_not_equal "", TestSingularFields.encode(m)
131
+
132
+ m.singular_int32 = 0
133
+ assert_equal "", TestSingularFields.encode(m)
134
+ end
135
+
136
+ def test_set_clear_defaults
137
+ m = TestSingularFields.new
138
+
139
+ m.singular_int32 = -42
140
+ assert_equal -42, m.singular_int32
141
+ m.clear_singular_int32
142
+ assert_equal 0, m.singular_int32
143
+
144
+ m.singular_int32 = 50
145
+ assert_equal 50, m.singular_int32
146
+ TestSingularFields.descriptor.lookup('singular_int32').clear(m)
147
+ assert_equal 0, m.singular_int32
148
+
149
+ m.singular_string = "foo bar"
150
+ assert_equal "foo bar", m.singular_string
151
+ m.clear_singular_string
152
+ assert_equal "", m.singular_string
153
+
154
+ m.singular_string = "foo"
155
+ assert_equal "foo", m.singular_string
156
+ TestSingularFields.descriptor.lookup('singular_string').clear(m)
157
+ assert_equal "", m.singular_string
158
+
159
+ m.singular_msg = TestMessage2.new(:foo => 42)
160
+ assert_equal TestMessage2.new(:foo => 42), m.singular_msg
161
+ assert m.has_singular_msg?
162
+ m.clear_singular_msg
163
+ assert_equal nil, m.singular_msg
164
+ assert !m.has_singular_msg?
165
+
166
+ m.singular_msg = TestMessage2.new(:foo => 42)
167
+ assert_equal TestMessage2.new(:foo => 42), m.singular_msg
168
+ TestSingularFields.descriptor.lookup('singular_msg').clear(m)
169
+ assert_equal nil, m.singular_msg
170
+ end
171
+
172
+ def test_import_proto2
173
+ m = TestMessage.new
174
+ assert !m.has_optional_proto2_submessage?
175
+ m.optional_proto2_submessage = ::FooBar::Proto2::TestImportedMessage.new
176
+ assert m.has_optional_proto2_submessage?
177
+ assert TestMessage.descriptor.lookup('optional_proto2_submessage').has?(m)
178
+
179
+ m.clear_optional_proto2_submessage
180
+ assert !m.has_optional_proto2_submessage?
181
+ end
182
+
183
+ def test_clear_repeated_fields
184
+ m = TestMessage.new
185
+
186
+ m.repeated_int32.push(1)
187
+ assert_equal [1], m.repeated_int32
188
+ m.clear_repeated_int32
189
+ assert_equal [], m.repeated_int32
190
+
191
+ m.repeated_int32.push(1)
192
+ assert_equal [1], m.repeated_int32
193
+ TestMessage.descriptor.lookup('repeated_int32').clear(m)
194
+ assert_equal [], m.repeated_int32
195
+
196
+ m = OneofMessage.new
197
+ m.a = "foo"
198
+ assert_equal "foo", m.a
199
+ assert m.has_my_oneof?
200
+ assert_equal :a, m.my_oneof
201
+ m.clear_a
202
+ assert !m.has_my_oneof?
203
+
204
+ m.a = "foobar"
205
+ assert m.has_my_oneof?
206
+ m.clear_my_oneof
207
+ assert !m.has_my_oneof?
208
+
209
+ m.a = "bar"
210
+ assert_equal "bar", m.a
211
+ assert m.has_my_oneof?
212
+ OneofMessage.descriptor.lookup('a').clear(m)
213
+ assert !m.has_my_oneof?
214
+ end
215
+
216
+ def test_initialization_map_errors
217
+ e = assert_raise ArgumentError do
218
+ TestMessage.new(:hello => "world")
219
+ end
220
+ assert_match(/hello/, e.message)
221
+
222
+ e = assert_raise ArgumentError do
223
+ MapMessage.new(:map_string_int32 => "hello")
224
+ end
225
+ assert_equal e.message, "Expected Hash object as initializer value for map field 'map_string_int32' (given String)."
226
+
227
+ e = assert_raise ArgumentError do
228
+ TestMessage.new(:repeated_uint32 => "hello")
229
+ end
230
+ assert_equal e.message, "Expected array as initializer value for repeated field 'repeated_uint32' (given String)."
231
+ end
232
+
233
+ def test_map_field
234
+ m = MapMessage.new
235
+ assert m.map_string_int32 == {}
236
+ assert m.map_string_msg == {}
237
+
238
+ m = MapMessage.new(
239
+ :map_string_int32 => {"a" => 1, "b" => 2},
240
+ :map_string_msg => {"a" => TestMessage2.new(:foo => 1),
241
+ "b" => TestMessage2.new(:foo => 2)},
242
+ :map_string_enum => {"a" => :A, "b" => :B})
243
+ assert m.map_string_int32.keys.sort == ["a", "b"]
244
+ assert m.map_string_int32["a"] == 1
245
+ assert m.map_string_msg["b"].foo == 2
246
+ assert m.map_string_enum["a"] == :A
247
+
248
+ m.map_string_int32["c"] = 3
249
+ assert m.map_string_int32["c"] == 3
250
+ m.map_string_msg["c"] = TestMessage2.new(:foo => 3)
251
+ assert m.map_string_msg["c"] == TestMessage2.new(:foo => 3)
252
+ m.map_string_msg.delete("b")
253
+ m.map_string_msg.delete("c")
254
+ assert m.map_string_msg == { "a" => TestMessage2.new(:foo => 1) }
255
+
256
+ assert_raise Google::Protobuf::TypeError do
257
+ m.map_string_msg["e"] = TestMessage.new # wrong value type
258
+ end
259
+ # ensure nothing was added by the above
260
+ assert m.map_string_msg == { "a" => TestMessage2.new(:foo => 1) }
261
+
262
+ m.map_string_int32 = Google::Protobuf::Map.new(:string, :int32)
263
+ assert_raise Google::Protobuf::TypeError do
264
+ m.map_string_int32 = Google::Protobuf::Map.new(:string, :int64)
265
+ end
266
+ assert_raise Google::Protobuf::TypeError do
267
+ m.map_string_int32 = {}
268
+ end
269
+
270
+ assert_raise Google::Protobuf::TypeError do
271
+ m = MapMessage.new(:map_string_int32 => { 1 => "I am not a number" })
272
+ end
273
+ end
274
+
275
+ def test_map_field_with_symbol
276
+ m = MapMessage.new
277
+ assert m.map_string_int32 == {}
278
+ assert m.map_string_msg == {}
279
+
280
+ m = MapMessage.new(
281
+ :map_string_int32 => {a: 1, "b" => 2},
282
+ :map_string_msg => {a: TestMessage2.new(:foo => 1),
283
+ b: TestMessage2.new(:foo => 10)})
284
+ assert_equal 1, m.map_string_int32[:a]
285
+ assert_equal 2, m.map_string_int32[:b]
286
+ assert_equal 10, m.map_string_msg[:b].foo
287
+ end
288
+
289
+ def test_map_inspect
290
+ m = MapMessage.new(
291
+ :map_string_int32 => {"a" => 1, "b" => 2},
292
+ :map_string_msg => {"a" => TestMessage2.new(:foo => 1),
293
+ "b" => TestMessage2.new(:foo => 2)},
294
+ :map_string_enum => {"a" => :A, "b" => :B})
295
+
296
+ # JRuby doesn't keep consistent ordering so check for either version
297
+ 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}>"
298
+ 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}>"
299
+ inspect_result = m.inspect
300
+ assert expected_a == inspect_result || expected_b == inspect_result, "Incorrect inspect result: #{inspect_result}"
301
+ end
302
+
303
+ def test_map_corruption
304
+ # This pattern led to a crash in a previous version of upb/protobuf.
305
+ m = MapMessage.new(map_string_int32: { "aaa" => 1 })
306
+ m.map_string_int32['podid'] = 2
307
+ m.map_string_int32['aaa'] = 3
308
+ end
309
+
310
+ def test_map_wrappers
311
+ run_asserts = ->(m) {
312
+ assert_equal 2.0, m.map_double[0].value
313
+ assert_equal 4.0, m.map_float[0].value
314
+ assert_equal 3, m.map_int32[0].value
315
+ assert_equal 4, m.map_int64[0].value
316
+ assert_equal 5, m.map_uint32[0].value
317
+ assert_equal 6, m.map_uint64[0].value
318
+ assert_equal true, m.map_bool[0].value
319
+ assert_equal 'str', m.map_string[0].value
320
+ assert_equal 'fun', m.map_bytes[0].value
321
+ }
322
+
323
+ m = proto_module::Wrapper.new(
324
+ map_double: {0 => Google::Protobuf::DoubleValue.new(value: 2.0)},
325
+ map_float: {0 => Google::Protobuf::FloatValue.new(value: 4.0)},
326
+ map_int32: {0 => Google::Protobuf::Int32Value.new(value: 3)},
327
+ map_int64: {0 => Google::Protobuf::Int64Value.new(value: 4)},
328
+ map_uint32: {0 => Google::Protobuf::UInt32Value.new(value: 5)},
329
+ map_uint64: {0 => Google::Protobuf::UInt64Value.new(value: 6)},
330
+ map_bool: {0 => Google::Protobuf::BoolValue.new(value: true)},
331
+ map_string: {0 => Google::Protobuf::StringValue.new(value: 'str')},
332
+ map_bytes: {0 => Google::Protobuf::BytesValue.new(value: 'fun')},
333
+ )
334
+
335
+ run_asserts.call(m)
336
+ serialized = proto_module::Wrapper::encode(m)
337
+ m2 = proto_module::Wrapper::decode(serialized)
338
+ run_asserts.call(m2)
339
+
340
+ # Test the case where we are serializing directly from the parsed form
341
+ # (before anything lazy is materialized).
342
+ m3 = proto_module::Wrapper::decode(serialized)
343
+ serialized2 = proto_module::Wrapper::encode(m3)
344
+ m4 = proto_module::Wrapper::decode(serialized2)
345
+ run_asserts.call(m4)
346
+
347
+ # Test that the lazy form compares equal to the expanded form.
348
+ m5 = proto_module::Wrapper::decode(serialized2)
349
+ assert_equal m5, m
350
+ end
351
+
352
+ def test_map_wrappers_with_default_values
353
+ run_asserts = ->(m) {
354
+ assert_equal 0.0, m.map_double[0].value
355
+ assert_equal 0.0, m.map_float[0].value
356
+ assert_equal 0, m.map_int32[0].value
357
+ assert_equal 0, m.map_int64[0].value
358
+ assert_equal 0, m.map_uint32[0].value
359
+ assert_equal 0, m.map_uint64[0].value
360
+ assert_equal false, m.map_bool[0].value
361
+ assert_equal '', m.map_string[0].value
362
+ assert_equal '', m.map_bytes[0].value
363
+ }
364
+
365
+ m = proto_module::Wrapper.new(
366
+ map_double: {0 => Google::Protobuf::DoubleValue.new(value: 0.0)},
367
+ map_float: {0 => Google::Protobuf::FloatValue.new(value: 0.0)},
368
+ map_int32: {0 => Google::Protobuf::Int32Value.new(value: 0)},
369
+ map_int64: {0 => Google::Protobuf::Int64Value.new(value: 0)},
370
+ map_uint32: {0 => Google::Protobuf::UInt32Value.new(value: 0)},
371
+ map_uint64: {0 => Google::Protobuf::UInt64Value.new(value: 0)},
372
+ map_bool: {0 => Google::Protobuf::BoolValue.new(value: false)},
373
+ map_string: {0 => Google::Protobuf::StringValue.new(value: '')},
374
+ map_bytes: {0 => Google::Protobuf::BytesValue.new(value: '')},
375
+ )
376
+
377
+ run_asserts.call(m)
378
+ serialized = proto_module::Wrapper::encode(m)
379
+ m2 = proto_module::Wrapper::decode(serialized)
380
+ run_asserts.call(m2)
381
+
382
+ # Test the case where we are serializing directly from the parsed form
383
+ # (before anything lazy is materialized).
384
+ m3 = proto_module::Wrapper::decode(serialized)
385
+ serialized2 = proto_module::Wrapper::encode(m3)
386
+ m4 = proto_module::Wrapper::decode(serialized2)
387
+ run_asserts.call(m4)
388
+
389
+ # Test that the lazy form compares equal to the expanded form.
390
+ m5 = proto_module::Wrapper::decode(serialized2)
391
+ assert_equal m5, m
392
+ end
393
+
394
+ def test_map_wrappers_with_no_value
395
+ run_asserts = ->(m) {
396
+ assert_equal 0.0, m.map_double[0].value
397
+ assert_equal 0.0, m.map_float[0].value
398
+ assert_equal 0, m.map_int32[0].value
399
+ assert_equal 0, m.map_int64[0].value
400
+ assert_equal 0, m.map_uint32[0].value
401
+ assert_equal 0, m.map_uint64[0].value
402
+ assert_equal false, m.map_bool[0].value
403
+ assert_equal '', m.map_string[0].value
404
+ assert_equal '', m.map_bytes[0].value
405
+ }
406
+
407
+ m = proto_module::Wrapper.new(
408
+ map_double: {0 => Google::Protobuf::DoubleValue.new()},
409
+ map_float: {0 => Google::Protobuf::FloatValue.new()},
410
+ map_int32: {0 => Google::Protobuf::Int32Value.new()},
411
+ map_int64: {0 => Google::Protobuf::Int64Value.new()},
412
+ map_uint32: {0 => Google::Protobuf::UInt32Value.new()},
413
+ map_uint64: {0 => Google::Protobuf::UInt64Value.new()},
414
+ map_bool: {0 => Google::Protobuf::BoolValue.new()},
415
+ map_string: {0 => Google::Protobuf::StringValue.new()},
416
+ map_bytes: {0 => Google::Protobuf::BytesValue.new()},
417
+ )
418
+ run_asserts.call(m)
419
+
420
+ serialized = proto_module::Wrapper::encode(m)
421
+ m2 = proto_module::Wrapper::decode(serialized)
422
+ run_asserts.call(m2)
423
+
424
+ # Test the case where we are serializing directly from the parsed form
425
+ # (before anything lazy is materialized).
426
+ m3 = proto_module::Wrapper::decode(serialized)
427
+ serialized2 = proto_module::Wrapper::encode(m3)
428
+ m4 = proto_module::Wrapper::decode(serialized2)
429
+ run_asserts.call(m4)
430
+ end
431
+
432
+ def test_concurrent_decoding
433
+ o = Outer.new
434
+ o.items[0] = Inner.new
435
+ raw = Outer.encode(o)
436
+
437
+ thds = 2.times.map do
438
+ Thread.new do
439
+ 100000.times do
440
+ assert_equal o, Outer.decode(raw)
441
+ end
442
+ end
443
+ end
444
+ thds.map(&:join)
445
+ end
446
+
447
+ def test_map_encode_decode
448
+ m = MapMessage.new(
449
+ :map_string_int32 => {"a" => 1, "b" => 2},
450
+ :map_string_msg => {"a" => TestMessage2.new(:foo => 1),
451
+ "b" => TestMessage2.new(:foo => 2)},
452
+ :map_string_enum => {"a" => :A, "b" => :B})
453
+ m2 = MapMessage.decode(MapMessage.encode(m))
454
+ assert m == m2
455
+
456
+ m3 = MapMessageWireEquiv.decode(MapMessage.encode(m))
457
+ assert m3.map_string_int32.length == 2
458
+
459
+ kv = {}
460
+ m3.map_string_int32.map { |msg| kv[msg.key] = msg.value }
461
+ assert kv == {"a" => 1, "b" => 2}
462
+
463
+ kv = {}
464
+ m3.map_string_msg.map { |msg| kv[msg.key] = msg.value }
465
+ assert kv == {"a" => TestMessage2.new(:foo => 1),
466
+ "b" => TestMessage2.new(:foo => 2)}
467
+ end
468
+
469
+ def test_protobuf_decode_json_ignore_unknown_fields
470
+ m = TestMessage.decode_json({
471
+ optional_string: "foo",
472
+ not_in_message: "some_value"
473
+ }.to_json, { ignore_unknown_fields: true })
474
+
475
+ assert_equal m.optional_string, "foo"
476
+ e = assert_raise Google::Protobuf::ParseError do
477
+ TestMessage.decode_json({ not_in_message: "some_value" }.to_json)
478
+ end
479
+ assert_match(/No such field: not_in_message/, e.message)
480
+ end
481
+
482
+ #def test_json_quoted_string
483
+ # m = TestMessage.decode_json(%q(
484
+ # "optionalInt64": "1",,
485
+ # }))
486
+ # puts(m)
487
+ # assert_equal 1, m.optional_int32
488
+ #end
489
+
490
+ def test_to_h
491
+ m = TestMessage.new(:optional_bool => true, :optional_double => -10.100001, :optional_string => 'foo', :repeated_string => ['bar1', 'bar2'], :repeated_msg => [TestMessage2.new(:foo => 100)])
492
+ expected_result = {
493
+ :optional_bool=>true,
494
+ :optional_bytes=>"",
495
+ :optional_double=>-10.100001,
496
+ :optional_enum=>:Default,
497
+ :optional_float=>0.0,
498
+ :optional_int32=>0,
499
+ :optional_int64=>0,
500
+ :optional_msg=>nil,
501
+ :optional_msg2=>nil,
502
+ :optional_proto2_submessage=>nil,
503
+ :optional_string=>"foo",
504
+ :optional_uint32=>0,
505
+ :optional_uint64=>0,
506
+ :repeated_bool=>[],
507
+ :repeated_bytes=>[],
508
+ :repeated_double=>[],
509
+ :repeated_enum=>[],
510
+ :repeated_float=>[],
511
+ :repeated_int32=>[],
512
+ :repeated_int64=>[],
513
+ :repeated_msg=>[{:foo => 100}],
514
+ :repeated_string=>["bar1", "bar2"],
515
+ :repeated_uint32=>[],
516
+ :repeated_uint64=>[]
517
+ }
518
+ assert_equal expected_result, m.to_h
519
+
520
+ m = MapMessage.new(
521
+ :map_string_int32 => {"a" => 1, "b" => 2},
522
+ :map_string_msg => {"a" => TestMessage2.new(:foo => 1),
523
+ "b" => TestMessage2.new(:foo => 2)},
524
+ :map_string_enum => {"a" => :A, "b" => :B})
525
+ expected_result = {
526
+ :map_string_int32 => {"a" => 1, "b" => 2},
527
+ :map_string_msg => {"a" => {:foo => 1}, "b" => {:foo => 2}},
528
+ :map_string_enum => {"a" => :A, "b" => :B}
529
+ }
530
+ assert_equal expected_result, m.to_h
531
+ end
532
+
533
+
534
+ def test_json_maps
535
+ # TODO: Fix JSON in JRuby version.
536
+ return if RUBY_PLATFORM == "java"
537
+ m = MapMessage.new(:map_string_int32 => {"a" => 1})
538
+ expected = {mapStringInt32: {a: 1}, mapStringMsg: {}, mapStringEnum: {}}
539
+ expected_preserve = {map_string_int32: {a: 1}, map_string_msg: {}, map_string_enum: {}}
540
+ assert_equal JSON.parse(MapMessage.encode_json(m, :emit_defaults=>true), :symbolize_names => true), expected
541
+
542
+ json = MapMessage.encode_json(m, :preserve_proto_fieldnames => true, :emit_defaults=>true)
543
+ assert_equal JSON.parse(json, :symbolize_names => true), expected_preserve
544
+
545
+ m2 = MapMessage.decode_json(MapMessage.encode_json(m))
546
+ assert_equal m, m2
547
+ end
548
+
549
+ def test_json_maps_emit_defaults_submsg
550
+ # TODO: Fix JSON in JRuby version.
551
+ return if RUBY_PLATFORM == "java"
552
+ m = MapMessage.new(:map_string_msg => {"a" => TestMessage2.new(foo: 0)})
553
+ expected = {mapStringInt32: {}, mapStringMsg: {a: {foo: 0}}, mapStringEnum: {}}
554
+
555
+ actual = MapMessage.encode_json(m, :emit_defaults => true)
556
+
557
+ assert_equal JSON.parse(actual, :symbolize_names => true), expected
558
+ end
559
+
560
+ def test_json_emit_defaults_submsg
561
+ # TODO: Fix JSON in JRuby version.
562
+ return if RUBY_PLATFORM == "java"
563
+ m = TestSingularFields.new(singular_msg: proto_module::TestMessage2.new)
564
+
565
+ expected = {
566
+ singularInt32: 0,
567
+ singularInt64: "0",
568
+ singularUint32: 0,
569
+ singularUint64: "0",
570
+ singularBool: false,
571
+ singularFloat: 0,
572
+ singularDouble: 0,
573
+ singularString: "",
574
+ singularBytes: "",
575
+ singularMsg: {},
576
+ singularEnum: "Default",
577
+ }
578
+
579
+ actual = proto_module::TestMessage.encode_json(m, :emit_defaults => true)
580
+
581
+ assert_equal expected, JSON.parse(actual, :symbolize_names => true)
582
+ end
583
+
584
+ def test_respond_to
585
+ # This test fails with JRuby 1.7.23, likely because of an old JRuby bug.
586
+ return if RUBY_PLATFORM == "java"
587
+ msg = MapMessage.new
588
+ assert msg.respond_to?(:map_string_int32)
589
+ assert !msg.respond_to?(:bacon)
590
+ end
591
+
592
+ def test_file_descriptor
593
+ file_descriptor = TestMessage.descriptor.file_descriptor
594
+ assert nil != file_descriptor
595
+ assert_equal "tests/basic_test.proto", file_descriptor.name
596
+ assert_equal :proto3, file_descriptor.syntax
597
+
598
+ file_descriptor = TestEnum.descriptor.file_descriptor
599
+ assert nil != file_descriptor
600
+ assert_equal "tests/basic_test.proto", file_descriptor.name
601
+ assert_equal :proto3, file_descriptor.syntax
602
+ end
603
+
604
+ # Ruby 2.5 changed to raise FrozenError instead of RuntimeError
605
+ FrozenErrorType = Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.5') ? RuntimeError : FrozenError
606
+
607
+ def test_map_freeze
608
+ m = proto_module::MapMessage.new
609
+ m.map_string_int32['a'] = 5
610
+ m.map_string_msg['b'] = proto_module::TestMessage2.new
611
+
612
+ m.map_string_int32.freeze
613
+ m.map_string_msg.freeze
614
+
615
+ assert m.map_string_int32.frozen?
616
+ assert m.map_string_msg.frozen?
617
+
618
+ assert_raise(FrozenErrorType) { m.map_string_int32['foo'] = 1 }
619
+ assert_raise(FrozenErrorType) { m.map_string_msg['bar'] = proto_module::TestMessage2.new }
620
+ assert_raise(FrozenErrorType) { m.map_string_int32.delete('a') }
621
+ assert_raise(FrozenErrorType) { m.map_string_int32.clear }
622
+ end
623
+
624
+ def test_map_length
625
+ m = proto_module::MapMessage.new
626
+ assert_equal 0, m.map_string_int32.length
627
+ assert_equal 0, m.map_string_msg.length
628
+ assert_equal 0, m.map_string_int32.size
629
+ assert_equal 0, m.map_string_msg.size
630
+
631
+ m.map_string_int32['a'] = 1
632
+ m.map_string_int32['b'] = 2
633
+ m.map_string_msg['a'] = proto_module::TestMessage2.new
634
+ assert_equal 2, m.map_string_int32.length
635
+ assert_equal 1, m.map_string_msg.length
636
+ assert_equal 2, m.map_string_int32.size
637
+ assert_equal 1, m.map_string_msg.size
638
+ end
639
+ end
640
+ end
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # generated_code.rb is in the same directory as this test.
4
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__)))
5
+
6
+ require 'generated_code_pb'
7
+ require 'test_import_pb'
8
+ require 'test_ruby_package_pb'
9
+ require 'test/unit'
10
+
11
+ class GeneratedCodeTest < Test::Unit::TestCase
12
+ def test_generated_msg
13
+ # just test that we can instantiate the message. The purpose of this test
14
+ # is to ensure that the output of the code generator is valid Ruby and
15
+ # successfully creates message definitions and classes, not to test every
16
+ # aspect of the extension (basic.rb is for that).
17
+ A::B::C::TestMessage.new
18
+ A::B::C::TestMessage::NestedMessage.new
19
+ A::B::C::TestLowercaseNested::Lowercase.new
20
+ FooBar::TestImportedMessage.new
21
+ A::B::TestRubyPackageMessage.new
22
+ end
23
+ end
data/tests/stress.rb ADDED
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'google/protobuf'
4
+ require 'test/unit'
5
+
6
+ module StressTest
7
+ pool = Google::Protobuf::DescriptorPool.new
8
+ pool.build do
9
+ add_message "TestMessage" do
10
+ optional :a, :int32, 1
11
+ repeated :b, :message, 2, "M"
12
+ end
13
+ add_message "M" do
14
+ optional :foo, :string, 1
15
+ end
16
+ end
17
+
18
+ TestMessage = pool.lookup("TestMessage").msgclass
19
+ M = pool.lookup("M").msgclass
20
+
21
+ class StressTest < Test::Unit::TestCase
22
+ def get_msg
23
+ TestMessage.new(:a => 1000,
24
+ :b => [M.new(:foo => "hello"),
25
+ M.new(:foo => "world")])
26
+ end
27
+ def test_stress
28
+ m = get_msg
29
+ data = TestMessage.encode(m)
30
+ 100_000.times do
31
+ mnew = TestMessage.decode(data)
32
+ mnew = mnew.dup
33
+ assert_equal m.inspect, mnew.inspect
34
+ assert TestMessage.encode(mnew) == data
35
+ end
36
+ end
37
+ end
38
+ end