google-protobuf 3.4.0.2 → 3.19.4

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.

Files changed (41) hide show
  1. checksums.yaml +5 -5
  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 +709 -1188
  5. data/ext/google/protobuf_c/defs.h +107 -0
  6. data/ext/google/protobuf_c/extconf.rb +7 -4
  7. data/ext/google/protobuf_c/map.c +316 -463
  8. data/ext/google/protobuf_c/map.h +67 -0
  9. data/ext/google/protobuf_c/message.c +993 -296
  10. data/ext/google/protobuf_c/message.h +101 -0
  11. data/ext/google/protobuf_c/protobuf.c +403 -50
  12. data/ext/google/protobuf_c/protobuf.h +47 -473
  13. data/ext/google/protobuf_c/repeated_field.c +314 -309
  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 +1 -1
  18. data/lib/google/protobuf/any_pb.rb +6 -4
  19. data/lib/google/protobuf/api_pb.rb +27 -24
  20. data/lib/google/protobuf/descriptor_dsl.rb +458 -0
  21. data/lib/google/protobuf/descriptor_pb.rb +268 -0
  22. data/lib/google/protobuf/duration_pb.rb +6 -4
  23. data/lib/google/protobuf/empty_pb.rb +4 -2
  24. data/lib/google/protobuf/field_mask_pb.rb +5 -3
  25. data/lib/google/protobuf/message_exts.rb +2 -2
  26. data/lib/google/protobuf/repeated_field.rb +3 -3
  27. data/lib/google/protobuf/source_context_pb.rb +5 -3
  28. data/lib/google/protobuf/struct_pb.rb +23 -21
  29. data/lib/google/protobuf/timestamp_pb.rb +6 -4
  30. data/lib/google/protobuf/type_pb.rb +77 -74
  31. data/lib/google/protobuf/well_known_types.rb +25 -2
  32. data/lib/google/protobuf/wrappers_pb.rb +37 -35
  33. data/lib/google/protobuf.rb +7 -4
  34. data/tests/basic.rb +432 -1115
  35. data/tests/generated_code_test.rb +6 -2
  36. data/tests/stress.rb +1 -1
  37. metadata +22 -30
  38. data/ext/google/protobuf_c/encode_decode.c +0 -1311
  39. data/ext/google/protobuf_c/storage.c +0 -893
  40. data/ext/google/protobuf_c/upb.c +0 -13911
  41. data/ext/google/protobuf_c/upb.h +0 -8872
data/tests/basic.rb CHANGED
@@ -1,5 +1,10 @@
1
1
  #!/usr/bin/ruby
2
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'
3
8
  require 'google/protobuf'
4
9
  require 'json'
5
10
  require 'test/unit'
@@ -9,623 +14,228 @@ require 'test/unit'
9
14
  module BasicTest
10
15
  pool = Google::Protobuf::DescriptorPool.new
11
16
  pool.build do
12
- add_message "Foo" do
13
- optional :bar, :message, 1, "Bar"
14
- repeated :baz, :message, 2, "Baz"
15
- end
16
-
17
- add_message "Bar" do
18
- optional :msg, :string, 1
19
- end
20
-
21
- add_message "Baz" do
22
- optional :msg, :string, 1
23
- end
24
-
25
- add_message "TestMessage" do
26
- optional :optional_int32, :int32, 1
27
- optional :optional_int64, :int64, 2
28
- optional :optional_uint32, :uint32, 3
29
- optional :optional_uint64, :uint64, 4
30
- optional :optional_bool, :bool, 5
31
- optional :optional_float, :float, 6
32
- optional :optional_double, :double, 7
33
- optional :optional_string, :string, 8
34
- optional :optional_bytes, :bytes, 9
35
- optional :optional_msg, :message, 10, "TestMessage2"
36
- optional :optional_enum, :enum, 11, "TestEnum"
37
-
38
- repeated :repeated_int32, :int32, 12
39
- repeated :repeated_int64, :int64, 13
40
- repeated :repeated_uint32, :uint32, 14
41
- repeated :repeated_uint64, :uint64, 15
42
- repeated :repeated_bool, :bool, 16
43
- repeated :repeated_float, :float, 17
44
- repeated :repeated_double, :double, 18
45
- repeated :repeated_string, :string, 19
46
- repeated :repeated_bytes, :bytes, 20
47
- repeated :repeated_msg, :message, 21, "TestMessage2"
48
- repeated :repeated_enum, :enum, 22, "TestEnum"
49
- end
50
- add_message "TestMessage2" do
51
- optional :foo, :int32, 1
52
- end
53
-
54
- add_message "Recursive1" do
55
- optional :foo, :message, 1, "Recursive2"
56
- end
57
- add_message "Recursive2" do
58
- optional :foo, :message, 1, "Recursive1"
59
- end
60
-
61
- add_enum "TestEnum" do
62
- value :Default, 0
63
- value :A, 1
64
- value :B, 2
65
- value :C, 3
66
- end
67
-
68
17
  add_message "BadFieldNames" do
69
18
  optional :dup, :int32, 1
70
19
  optional :class, :int32, 2
71
- optional :"a.b", :int32, 3
72
- end
73
-
74
- add_message "MapMessage" do
75
- map :map_string_int32, :string, :int32, 1
76
- map :map_string_msg, :string, :message, 2, "TestMessage2"
77
- end
78
- add_message "MapMessageWireEquiv" do
79
- repeated :map_string_int32, :message, 1, "MapMessageWireEquiv_entry1"
80
- repeated :map_string_msg, :message, 2, "MapMessageWireEquiv_entry2"
81
- end
82
- add_message "MapMessageWireEquiv_entry1" do
83
- optional :key, :string, 1
84
- optional :value, :int32, 2
85
- end
86
- add_message "MapMessageWireEquiv_entry2" do
87
- optional :key, :string, 1
88
- optional :value, :message, 2, "TestMessage2"
89
- end
90
-
91
- add_message "OneofMessage" do
92
- oneof :my_oneof do
93
- optional :a, :string, 1
94
- optional :b, :int32, 2
95
- optional :c, :message, 3, "TestMessage2"
96
- optional :d, :enum, 4, "TestEnum"
97
- end
98
20
  end
99
21
  end
100
22
 
101
- Foo = pool.lookup("Foo").msgclass
102
- Bar = pool.lookup("Bar").msgclass
103
- Baz = pool.lookup("Baz").msgclass
104
- TestMessage = pool.lookup("TestMessage").msgclass
105
- TestMessage2 = pool.lookup("TestMessage2").msgclass
106
- Recursive1 = pool.lookup("Recursive1").msgclass
107
- Recursive2 = pool.lookup("Recursive2").msgclass
108
- TestEnum = pool.lookup("TestEnum").enummodule
109
23
  BadFieldNames = pool.lookup("BadFieldNames").msgclass
110
- MapMessage = pool.lookup("MapMessage").msgclass
111
- MapMessageWireEquiv = pool.lookup("MapMessageWireEquiv").msgclass
112
- MapMessageWireEquiv_entry1 =
113
- pool.lookup("MapMessageWireEquiv_entry1").msgclass
114
- MapMessageWireEquiv_entry2 =
115
- pool.lookup("MapMessageWireEquiv_entry2").msgclass
116
- OneofMessage = pool.lookup("OneofMessage").msgclass
117
24
 
118
25
  # ------------ test cases ---------------
119
26
 
120
27
  class MessageContainerTest < Test::Unit::TestCase
121
-
122
- def test_defaults
123
- m = TestMessage.new
124
- assert m.optional_int32 == 0
125
- assert m.optional_int64 == 0
126
- assert m.optional_uint32 == 0
127
- assert m.optional_uint64 == 0
128
- assert m.optional_bool == false
129
- assert m.optional_float == 0.0
130
- assert m.optional_double == 0.0
131
- assert m.optional_string == ""
132
- assert m.optional_bytes == ""
133
- assert m.optional_msg == nil
134
- assert m.optional_enum == :Default
135
- end
136
-
137
- def test_setters
138
- m = TestMessage.new
139
- m.optional_int32 = -42
140
- assert m.optional_int32 == -42
141
- m.optional_int64 = -0x1_0000_0000
142
- assert m.optional_int64 == -0x1_0000_0000
143
- m.optional_uint32 = 0x9000_0000
144
- assert m.optional_uint32 == 0x9000_0000
145
- m.optional_uint64 = 0x9000_0000_0000_0000
146
- assert m.optional_uint64 == 0x9000_0000_0000_0000
147
- m.optional_bool = true
148
- assert m.optional_bool == true
149
- m.optional_float = 0.5
150
- assert m.optional_float == 0.5
151
- m.optional_double = 0.5
152
- m.optional_string = "hello"
153
- assert m.optional_string == "hello"
154
- m.optional_bytes = "world".encode!('ASCII-8BIT')
155
- assert m.optional_bytes == "world"
156
- m.optional_msg = TestMessage2.new(:foo => 42)
157
- assert m.optional_msg == TestMessage2.new(:foo => 42)
158
- m.optional_msg = nil
159
- assert m.optional_msg == nil
160
- end
161
-
162
- def test_ctor_args
163
- m = TestMessage.new(:optional_int32 => -42,
164
- :optional_msg => TestMessage2.new,
165
- :optional_enum => :C,
166
- :repeated_string => ["hello", "there", "world"])
167
- assert m.optional_int32 == -42
168
- assert m.optional_msg.class == TestMessage2
169
- assert m.repeated_string.length == 3
170
- assert m.optional_enum == :C
171
- assert m.repeated_string[0] == "hello"
172
- assert m.repeated_string[1] == "there"
173
- assert m.repeated_string[2] == "world"
174
- end
175
-
176
- def test_inspect
177
- m = TestMessage.new(:optional_int32 => -42,
178
- :optional_enum => :A,
179
- :optional_msg => TestMessage2.new,
180
- :repeated_string => ["hello", "there", "world"])
181
- expected = '<BasicTest::TestMessage: optional_int32: -42, optional_int64: 0, optional_uint32: 0, optional_uint64: 0, optional_bool: false, optional_float: 0.0, optional_double: 0.0, optional_string: "", optional_bytes: "", optional_msg: <BasicTest::TestMessage2: foo: 0>, optional_enum: :A, repeated_int32: [], repeated_int64: [], repeated_uint32: [], repeated_uint64: [], repeated_bool: [], repeated_float: [], repeated_double: [], repeated_string: ["hello", "there", "world"], repeated_bytes: [], repeated_msg: [], repeated_enum: []>'
182
- assert_equal expected, m.inspect
183
- end
184
-
185
- def test_hash
186
- m1 = TestMessage.new(:optional_int32 => 42)
187
- m2 = TestMessage.new(:optional_int32 => 102, repeated_string: ['please', 'work', 'ok?'])
188
- m3 = TestMessage.new(:optional_int32 => 102, repeated_string: ['please', 'work', 'ok?'])
189
- assert m1.hash != 0
190
- assert m2.hash != 0
191
- assert m3.hash != 0
192
- # relying on the randomness here -- if hash function changes and we are
193
- # unlucky enough to get a collision, then change the values above.
194
- assert m1.hash != m2.hash
195
- assert_equal m2.hash, m3.hash
196
- end
197
-
198
- def test_unknown_field_errors
199
- e = assert_raise NoMethodError do
200
- TestMessage.new.hello
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
201
43
  end
202
- assert_match(/hello/, e.message)
203
44
 
204
- e = assert_raise NoMethodError do
205
- TestMessage.new.hello = "world"
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
206
51
  end
207
- assert_match(/hello/, e.message)
208
- end
209
52
 
210
- def test_initialization_map_errors
211
- e = assert_raise ArgumentError do
212
- TestMessage.new(:hello => "world")
213
- end
214
- assert_match(/hello/, e.message)
53
+ outer = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("Outer").msgclass
215
54
 
216
- e = assert_raise ArgumentError do
217
- MapMessage.new(:map_string_int32 => "hello")
218
- end
219
- assert_equal e.message, "Expected Hash object as initializer value for map field 'map_string_int32'."
55
+ outer.new(
56
+ inners: []
57
+ )['inners'].to_s
220
58
 
221
- e = assert_raise ArgumentError do
222
- TestMessage.new(:repeated_uint32 => "hello")
59
+ assert_raise Google::Protobuf::TypeError do
60
+ outer.new(
61
+ inners: [nil]
62
+ ).to_s
223
63
  end
224
- assert_equal e.message, "Expected array as initializer value for repeated field 'repeated_uint32'."
225
64
  end
226
65
 
227
- def test_type_errors
228
- m = TestMessage.new
229
- assert_raise TypeError do
230
- m.optional_int32 = "hello"
231
- end
232
- assert_raise TypeError do
233
- m.optional_string = 42
234
- end
235
- assert_raise TypeError do
236
- m.optional_string = nil
237
- end
238
- assert_raise TypeError do
239
- m.optional_bool = 42
240
- end
241
- assert_raise TypeError do
242
- m.optional_msg = TestMessage.new # expects TestMessage2
243
- end
244
-
245
- assert_raise TypeError do
246
- m.repeated_int32 = [] # needs RepeatedField
247
- end
248
-
249
- assert_raise TypeError do
250
- m.repeated_int32.push "hello"
251
- end
252
-
253
- assert_raise TypeError do
254
- m.repeated_msg.push TestMessage.new
255
- end
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)
256
72
  end
257
73
 
258
- def test_string_encoding
259
- m = TestMessage.new
260
-
261
- # Assigning a normal (ASCII or UTF8) string to a bytes field, or
262
- # ASCII-8BIT to a string field will convert to the proper encoding.
263
- m.optional_bytes = "Test string ASCII".encode!('ASCII')
264
- assert m.optional_bytes.frozen?
265
- assert_equal Encoding::ASCII_8BIT, m.optional_bytes.encoding
266
- assert_equal "Test string ASCII", m.optional_bytes
267
-
268
- assert_raise Encoding::UndefinedConversionError do
269
- m.optional_bytes = "Test string UTF-8 \u0100".encode!('UTF-8')
270
- end
271
-
272
- assert_raise Encoding::UndefinedConversionError do
273
- m.optional_string = ["FFFF"].pack('H*')
274
- end
275
-
276
- # "Ordinary" use case.
277
- m.optional_bytes = ["FFFF"].pack('H*')
278
- m.optional_string = "\u0100"
279
-
280
- # strings are immutable so we can't do this, but serialize should catch it.
281
- m.optional_string = "asdf".encode!('UTF-8')
282
- assert_raise RuntimeError do
283
- m.optional_string.encode!('ASCII-8BIT')
284
- end
74
+ def test_issue_9440
75
+ msg = HelloRequest.new
76
+ msg.id = 8
77
+ assert_equal 8, msg.id
78
+ msg.version = '1'
79
+ assert_equal 8, msg.id
285
80
  end
286
81
 
287
- def test_rptfield_int32
288
- l = Google::Protobuf::RepeatedField.new(:int32)
289
- assert l.count == 0
290
- l = Google::Protobuf::RepeatedField.new(:int32, [1, 2, 3])
291
- assert l.count == 3
292
- assert_equal [1, 2, 3], l
293
- assert_equal l, [1, 2, 3]
294
- l.push 4
295
- assert l == [1, 2, 3, 4]
296
- dst_list = []
297
- l.each { |val| dst_list.push val }
298
- assert dst_list == [1, 2, 3, 4]
299
- assert l.to_a == [1, 2, 3, 4]
300
- assert l[0] == 1
301
- assert l[3] == 4
302
- l[0] = 5
303
- assert l == [5, 2, 3, 4]
304
-
305
- l2 = l.dup
306
- assert l == l2
307
- assert l.object_id != l2.object_id
308
- l2.push 6
309
- assert l.count == 4
310
- assert l2.count == 5
311
-
312
- assert l.inspect == '[5, 2, 3, 4]'
313
-
314
- l.concat([7, 8, 9])
315
- assert l == [5, 2, 3, 4, 7, 8, 9]
316
- assert l.pop == 9
317
- assert l == [5, 2, 3, 4, 7, 8]
318
-
319
- assert_raise TypeError do
320
- m = TestMessage.new
321
- l.push m
322
- end
82
+ def test_has_field
83
+ m = TestSingularFields.new
84
+ assert !m.has_singular_msg?
85
+ m.singular_msg = TestMessage2.new
86
+ assert m.has_singular_msg?
87
+ assert TestSingularFields.descriptor.lookup('singular_msg').has?(m)
323
88
 
324
- m = TestMessage.new
325
- m.repeated_int32 = l
326
- assert m.repeated_int32 == [5, 2, 3, 4, 7, 8]
327
- assert m.repeated_int32.object_id == l.object_id
328
- l.push 42
329
- assert m.repeated_int32.pop == 42
330
-
331
- l3 = l + l.dup
332
- assert l3.count == l.count * 2
333
- l.count.times do |i|
334
- assert l3[i] == l[i]
335
- assert l3[l.count + i] == l[i]
89
+ m = OneofMessage.new
90
+ assert !m.has_my_oneof?
91
+ m.a = "foo"
92
+ assert m.has_my_oneof?
93
+ assert_raise NoMethodError do
94
+ m.has_a?
336
95
  end
96
+ assert_true OneofMessage.descriptor.lookup('a').has?(m)
337
97
 
338
- l.clear
339
- assert l.count == 0
340
- l += [1, 2, 3, 4]
341
- l.replace([5, 6, 7, 8])
342
- assert l == [5, 6, 7, 8]
343
-
344
- l4 = Google::Protobuf::RepeatedField.new(:int32)
345
- l4[5] = 42
346
- assert l4 == [0, 0, 0, 0, 0, 42]
347
-
348
- l4 << 100
349
- assert l4 == [0, 0, 0, 0, 0, 42, 100]
350
- l4 << 101 << 102
351
- assert l4 == [0, 0, 0, 0, 0, 42, 100, 101, 102]
352
- end
353
-
354
- def test_parent_rptfield
355
- #make sure we set the RepeatedField and can add to it
356
- m = TestMessage.new
357
- assert m.repeated_string == []
358
- m.repeated_string << 'ok'
359
- m.repeated_string.push('ok2')
360
- assert m.repeated_string == ['ok', 'ok2']
361
- m.repeated_string += ['ok3']
362
- assert m.repeated_string == ['ok', 'ok2', 'ok3']
363
- end
364
-
365
- def test_rptfield_msg
366
- l = Google::Protobuf::RepeatedField.new(:message, TestMessage)
367
- l.push TestMessage.new
368
- assert l.count == 1
369
- assert_raise TypeError do
370
- l.push TestMessage2.new
371
- end
372
- assert_raise TypeError do
373
- l.push 42
98
+ m = TestSingularFields.new
99
+ assert_raise NoMethodError do
100
+ m.has_singular_int32?
374
101
  end
375
-
376
- l2 = l.dup
377
- assert l2[0] == l[0]
378
- assert l2[0].object_id == l[0].object_id
379
-
380
- l2 = Google::Protobuf.deep_copy(l)
381
- assert l2[0] == l[0]
382
- assert l2[0].object_id != l[0].object_id
383
-
384
- l3 = l + l2
385
- assert l3.count == 2
386
- assert l3[0] == l[0]
387
- assert l3[1] == l2[0]
388
- l3[0].optional_int32 = 1000
389
- assert l[0].optional_int32 == 1000
390
-
391
- new_msg = TestMessage.new(:optional_int32 => 200)
392
- l4 = l + [new_msg]
393
- assert l4.count == 2
394
- new_msg.optional_int32 = 1000
395
- assert l4[1].optional_int32 == 1000
396
- end
397
-
398
- def test_rptfield_enum
399
- l = Google::Protobuf::RepeatedField.new(:enum, TestEnum)
400
- l.push :A
401
- l.push :B
402
- l.push :C
403
- assert l.count == 3
404
- assert_raise RangeError do
405
- l.push :D
102
+ assert_raise ArgumentError do
103
+ TestSingularFields.descriptor.lookup('singular_int32').has?(m)
406
104
  end
407
- assert l[0] == :A
408
-
409
- l.push 4
410
- assert l[3] == 4
411
- end
412
105
 
413
- def test_rptfield_initialize
414
- assert_raise ArgumentError do
415
- l = Google::Protobuf::RepeatedField.new
106
+ assert_raise NoMethodError do
107
+ m.has_singular_string?
416
108
  end
417
109
  assert_raise ArgumentError do
418
- l = Google::Protobuf::RepeatedField.new(:message)
110
+ TestSingularFields.descriptor.lookup('singular_string').has?(m)
419
111
  end
420
- assert_raise ArgumentError do
421
- l = Google::Protobuf::RepeatedField.new([1, 2, 3])
112
+
113
+ assert_raise NoMethodError do
114
+ m.has_singular_bool?
422
115
  end
423
116
  assert_raise ArgumentError do
424
- l = Google::Protobuf::RepeatedField.new(:message, [TestMessage2.new])
117
+ TestSingularFields.descriptor.lookup('singular_bool').has?(m)
425
118
  end
426
- end
427
119
 
428
- def test_rptfield_array_ducktyping
429
- l = Google::Protobuf::RepeatedField.new(:int32)
430
- length_methods = %w(count length size)
431
- length_methods.each do |lm|
432
- assert l.send(lm) == 0
433
- end
434
- # out of bounds returns a nil
435
- assert l[0] == nil
436
- assert l[1] == nil
437
- assert l[-1] == nil
438
- l.push 4
439
- length_methods.each do |lm|
440
- assert l.send(lm) == 1
120
+ m = TestMessage.new
121
+ assert_raise NoMethodError do
122
+ m.has_repeated_msg?
441
123
  end
442
- assert l[0] == 4
443
- assert l[1] == nil
444
- assert l[-1] == 4
445
- assert l[-2] == nil
446
-
447
- l.push 2
448
- length_methods.each do |lm|
449
- assert l.send(lm) == 2
124
+ assert_raise ArgumentError do
125
+ TestMessage.descriptor.lookup('repeated_msg').has?(m)
450
126
  end
451
- assert l[0] == 4
452
- assert l[1] == 2
453
- assert l[2] == nil
454
- assert l[-1] == 2
455
- assert l[-2] == 4
456
- assert l[-3] == nil
457
-
458
- #adding out of scope will backfill with empty objects
459
127
  end
460
128
 
461
- def test_map_basic
462
- # allowed key types:
463
- # :int32, :int64, :uint32, :uint64, :bool, :string, :bytes.
129
+ def test_no_presence
130
+ m = TestSingularFields.new
464
131
 
465
- m = Google::Protobuf::Map.new(:string, :int32)
466
- m["asdf"] = 1
467
- assert m["asdf"] == 1
468
- m["jkl;"] = 42
469
- assert m == { "jkl;" => 42, "asdf" => 1 }
470
- assert m.has_key?("asdf")
471
- assert !m.has_key?("qwerty")
472
- assert m.length == 2
132
+ # Explicitly setting to zero does not cause anything to be serialized.
133
+ m.singular_int32 = 0
134
+ assert_equal "", TestSingularFields.encode(m)
473
135
 
474
- m2 = m.dup
475
- assert_equal m, m2
476
- assert m.hash != 0
477
- assert_equal m.hash, m2.hash
136
+ # Explicitly setting to a non-zero value *does* cause serialization.
137
+ m.singular_int32 = 1
138
+ assert_not_equal "", TestSingularFields.encode(m)
478
139
 
479
- collected = {}
480
- m.each { |k,v| collected[v] = k }
481
- assert collected == { 42 => "jkl;", 1 => "asdf" }
140
+ m.singular_int32 = 0
141
+ assert_equal "", TestSingularFields.encode(m)
142
+ end
482
143
 
483
- assert m.delete("asdf") == 1
484
- assert !m.has_key?("asdf")
485
- assert m["asdf"] == nil
486
- assert !m.has_key?("asdf")
144
+ def test_set_clear_defaults
145
+ m = TestSingularFields.new
487
146
 
488
- # We only assert on inspect value when there is one map entry because the
489
- # order in which elements appear is unspecified (depends on the internal
490
- # hash function). We don't want a brittle test.
491
- assert m.inspect == "{\"jkl;\"=>42}"
147
+ m.singular_int32 = -42
148
+ assert_equal -42, m.singular_int32
149
+ m.clear_singular_int32
150
+ assert_equal 0, m.singular_int32
492
151
 
493
- assert m.keys == ["jkl;"]
494
- assert m.values == [42]
152
+ m.singular_int32 = 50
153
+ assert_equal 50, m.singular_int32
154
+ TestSingularFields.descriptor.lookup('singular_int32').clear(m)
155
+ assert_equal 0, m.singular_int32
495
156
 
496
- m.clear
497
- assert m.length == 0
498
- assert m == {}
157
+ m.singular_string = "foo bar"
158
+ assert_equal "foo bar", m.singular_string
159
+ m.clear_singular_string
160
+ assert_equal "", m.singular_string
499
161
 
500
- assert_raise TypeError do
501
- m[1] = 1
502
- end
503
- assert_raise RangeError do
504
- m["asdf"] = 0x1_0000_0000
505
- end
506
- end
162
+ m.singular_string = "foo"
163
+ assert_equal "foo", m.singular_string
164
+ TestSingularFields.descriptor.lookup('singular_string').clear(m)
165
+ assert_equal "", m.singular_string
166
+
167
+ m.singular_msg = TestMessage2.new(:foo => 42)
168
+ assert_equal TestMessage2.new(:foo => 42), m.singular_msg
169
+ assert m.has_singular_msg?
170
+ m.clear_singular_msg
171
+ assert_equal nil, m.singular_msg
172
+ assert !m.has_singular_msg?
507
173
 
508
- def test_map_ctor
509
- m = Google::Protobuf::Map.new(:string, :int32,
510
- {"a" => 1, "b" => 2, "c" => 3})
511
- assert m == {"a" => 1, "c" => 3, "b" => 2}
174
+ m.singular_msg = TestMessage2.new(:foo => 42)
175
+ assert_equal TestMessage2.new(:foo => 42), m.singular_msg
176
+ TestSingularFields.descriptor.lookup('singular_msg').clear(m)
177
+ assert_equal nil, m.singular_msg
512
178
  end
513
179
 
514
- def test_map_keytypes
515
- m = Google::Protobuf::Map.new(:int32, :int32)
516
- m[1] = 42
517
- m[-1] = 42
518
- assert_raise RangeError do
519
- m[0x8000_0000] = 1
520
- end
521
- assert_raise TypeError do
522
- m["asdf"] = 1
523
- end
180
+ def test_import_proto2
181
+ m = TestMessage.new
182
+ assert !m.has_optional_proto2_submessage?
183
+ m.optional_proto2_submessage = ::FooBar::Proto2::TestImportedMessage.new
184
+ assert m.has_optional_proto2_submessage?
185
+ assert TestMessage.descriptor.lookup('optional_proto2_submessage').has?(m)
524
186
 
525
- m = Google::Protobuf::Map.new(:int64, :int32)
526
- m[0x1000_0000_0000_0000] = 1
527
- assert_raise RangeError do
528
- m[0x1_0000_0000_0000_0000] = 1
529
- end
530
- assert_raise TypeError do
531
- m["asdf"] = 1
532
- end
187
+ m.clear_optional_proto2_submessage
188
+ assert !m.has_optional_proto2_submessage?
189
+ end
533
190
 
534
- m = Google::Protobuf::Map.new(:uint32, :int32)
535
- m[0x8000_0000] = 1
536
- assert_raise RangeError do
537
- m[0x1_0000_0000] = 1
538
- end
539
- assert_raise RangeError do
540
- m[-1] = 1
541
- end
191
+ def test_clear_repeated_fields
192
+ m = TestMessage.new
542
193
 
543
- m = Google::Protobuf::Map.new(:uint64, :int32)
544
- m[0x8000_0000_0000_0000] = 1
545
- assert_raise RangeError do
546
- m[0x1_0000_0000_0000_0000] = 1
547
- end
548
- assert_raise RangeError do
549
- m[-1] = 1
550
- end
194
+ m.repeated_int32.push(1)
195
+ assert_equal [1], m.repeated_int32
196
+ m.clear_repeated_int32
197
+ assert_equal [], m.repeated_int32
551
198
 
552
- m = Google::Protobuf::Map.new(:bool, :int32)
553
- m[true] = 1
554
- m[false] = 2
555
- assert_raise TypeError do
556
- m[1] = 1
557
- end
558
- assert_raise TypeError do
559
- m["asdf"] = 1
560
- end
199
+ m.repeated_int32.push(1)
200
+ assert_equal [1], m.repeated_int32
201
+ TestMessage.descriptor.lookup('repeated_int32').clear(m)
202
+ assert_equal [], m.repeated_int32
561
203
 
562
- m = Google::Protobuf::Map.new(:string, :int32)
563
- m["asdf"] = 1
564
- assert_raise TypeError do
565
- m[1] = 1
566
- end
567
- assert_raise Encoding::UndefinedConversionError do
568
- bytestring = ["FFFF"].pack("H*")
569
- m[bytestring] = 1
570
- end
204
+ m = OneofMessage.new
205
+ m.a = "foo"
206
+ assert_equal "foo", m.a
207
+ assert m.has_my_oneof?
208
+ assert_equal :a, m.my_oneof
209
+ m.clear_a
210
+ assert !m.has_my_oneof?
571
211
 
572
- m = Google::Protobuf::Map.new(:bytes, :int32)
573
- bytestring = ["FFFF"].pack("H*")
574
- m[bytestring] = 1
575
- # Allowed -- we will automatically convert to ASCII-8BIT.
576
- m["asdf"] = 1
577
- assert_raise TypeError do
578
- m[1] = 1
579
- end
212
+ m.a = "foobar"
213
+ assert m.has_my_oneof?
214
+ m.clear_my_oneof
215
+ assert !m.has_my_oneof?
216
+
217
+ m.a = "bar"
218
+ assert_equal "bar", m.a
219
+ assert m.has_my_oneof?
220
+ OneofMessage.descriptor.lookup('a').clear(m)
221
+ assert !m.has_my_oneof?
580
222
  end
581
223
 
582
- def test_map_msg_enum_valuetypes
583
- m = Google::Protobuf::Map.new(:string, :message, TestMessage)
584
- m["asdf"] = TestMessage.new
585
- assert_raise TypeError do
586
- m["jkl;"] = TestMessage2.new
224
+ def test_initialization_map_errors
225
+ e = assert_raise ArgumentError do
226
+ TestMessage.new(:hello => "world")
587
227
  end
228
+ assert_match(/hello/, e.message)
588
229
 
589
- m = Google::Protobuf::Map.new(
590
- :string, :message, TestMessage,
591
- { "a" => TestMessage.new(:optional_int32 => 42),
592
- "b" => TestMessage.new(:optional_int32 => 84) })
593
- assert m.length == 2
594
- assert m.values.map{|msg| msg.optional_int32}.sort == [42, 84]
595
-
596
- m = Google::Protobuf::Map.new(:string, :enum, TestEnum,
597
- { "x" => :A, "y" => :B, "z" => :C })
598
- assert m.length == 3
599
- assert m["z"] == :C
600
- m["z"] = 2
601
- assert m["z"] == :B
602
- m["z"] = 4
603
- assert m["z"] == 4
604
- assert_raise RangeError do
605
- m["z"] = :Z
606
- end
607
- assert_raise TypeError do
608
- m["z"] = "z"
230
+ e = assert_raise ArgumentError do
231
+ MapMessage.new(:map_string_int32 => "hello")
609
232
  end
610
- end
611
-
612
- def test_map_dup_deep_copy
613
- m = Google::Protobuf::Map.new(
614
- :string, :message, TestMessage,
615
- { "a" => TestMessage.new(:optional_int32 => 42),
616
- "b" => TestMessage.new(:optional_int32 => 84) })
233
+ assert_equal e.message, "Expected Hash object as initializer value for map field 'map_string_int32' (given String)."
617
234
 
618
- m2 = m.dup
619
- assert m == m2
620
- assert m.object_id != m2.object_id
621
- assert m["a"].object_id == m2["a"].object_id
622
- assert m["b"].object_id == m2["b"].object_id
623
-
624
- m2 = Google::Protobuf.deep_copy(m)
625
- assert m == m2
626
- assert m.object_id != m2.object_id
627
- assert m["a"].object_id != m2["a"].object_id
628
- assert m["b"].object_id != m2["b"].object_id
235
+ e = assert_raise ArgumentError do
236
+ TestMessage.new(:repeated_uint32 => "hello")
237
+ end
238
+ assert_equal e.message, "Expected array as initializer value for repeated field 'repeated_uint32' (given String)."
629
239
  end
630
240
 
631
241
  def test_map_field
@@ -636,10 +246,12 @@ module BasicTest
636
246
  m = MapMessage.new(
637
247
  :map_string_int32 => {"a" => 1, "b" => 2},
638
248
  :map_string_msg => {"a" => TestMessage2.new(:foo => 1),
639
- "b" => TestMessage2.new(:foo => 2)})
249
+ "b" => TestMessage2.new(:foo => 2)},
250
+ :map_string_enum => {"a" => :A, "b" => :B})
640
251
  assert m.map_string_int32.keys.sort == ["a", "b"]
641
252
  assert m.map_string_int32["a"] == 1
642
253
  assert m.map_string_msg["b"].foo == 2
254
+ assert m.map_string_enum["a"] == :A
643
255
 
644
256
  m.map_string_int32["c"] = 3
645
257
  assert m.map_string_int32["c"] == 3
@@ -649,25 +261,53 @@ module BasicTest
649
261
  m.map_string_msg.delete("c")
650
262
  assert m.map_string_msg == { "a" => TestMessage2.new(:foo => 1) }
651
263
 
652
- assert_raise TypeError do
264
+ assert_raise Google::Protobuf::TypeError do
653
265
  m.map_string_msg["e"] = TestMessage.new # wrong value type
654
266
  end
655
267
  # ensure nothing was added by the above
656
268
  assert m.map_string_msg == { "a" => TestMessage2.new(:foo => 1) }
657
269
 
658
270
  m.map_string_int32 = Google::Protobuf::Map.new(:string, :int32)
659
- assert_raise TypeError do
271
+ assert_raise Google::Protobuf::TypeError do
660
272
  m.map_string_int32 = Google::Protobuf::Map.new(:string, :int64)
661
273
  end
662
- assert_raise TypeError do
274
+ assert_raise Google::Protobuf::TypeError do
663
275
  m.map_string_int32 = {}
664
276
  end
665
277
 
666
- assert_raise TypeError do
278
+ assert_raise Google::Protobuf::TypeError do
667
279
  m = MapMessage.new(:map_string_int32 => { 1 => "I am not a number" })
668
280
  end
669
281
  end
670
282
 
283
+ def test_map_field_with_symbol
284
+ m = MapMessage.new
285
+ assert m.map_string_int32 == {}
286
+ assert m.map_string_msg == {}
287
+
288
+ m = MapMessage.new(
289
+ :map_string_int32 => {a: 1, "b" => 2},
290
+ :map_string_msg => {a: TestMessage2.new(:foo => 1),
291
+ b: TestMessage2.new(:foo => 10)})
292
+ assert_equal 1, m.map_string_int32[:a]
293
+ assert_equal 2, m.map_string_int32[:b]
294
+ assert_equal 10, m.map_string_msg[:b].foo
295
+ end
296
+
297
+ def test_map_inspect
298
+ m = MapMessage.new(
299
+ :map_string_int32 => {"a" => 1, "b" => 2},
300
+ :map_string_msg => {"a" => TestMessage2.new(:foo => 1),
301
+ "b" => TestMessage2.new(:foo => 2)},
302
+ :map_string_enum => {"a" => :A, "b" => :B})
303
+
304
+ # JRuby doesn't keep consistent ordering so check for either version
305
+ 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}>"
306
+ 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}>"
307
+ inspect_result = m.inspect
308
+ assert expected_a == inspect_result || expected_b == inspect_result, "Incorrect inspect result: #{inspect_result}"
309
+ end
310
+
671
311
  def test_map_corruption
672
312
  # This pattern led to a crash in a previous version of upb/protobuf.
673
313
  m = MapMessage.new(map_string_int32: { "aaa" => 1 })
@@ -675,11 +315,149 @@ module BasicTest
675
315
  m.map_string_int32['aaa'] = 3
676
316
  end
677
317
 
318
+ def test_map_wrappers
319
+ run_asserts = ->(m) {
320
+ assert_equal 2.0, m.map_double[0].value
321
+ assert_equal 4.0, m.map_float[0].value
322
+ assert_equal 3, m.map_int32[0].value
323
+ assert_equal 4, m.map_int64[0].value
324
+ assert_equal 5, m.map_uint32[0].value
325
+ assert_equal 6, m.map_uint64[0].value
326
+ assert_equal true, m.map_bool[0].value
327
+ assert_equal 'str', m.map_string[0].value
328
+ assert_equal 'fun', m.map_bytes[0].value
329
+ }
330
+
331
+ m = proto_module::Wrapper.new(
332
+ map_double: {0 => Google::Protobuf::DoubleValue.new(value: 2.0)},
333
+ map_float: {0 => Google::Protobuf::FloatValue.new(value: 4.0)},
334
+ map_int32: {0 => Google::Protobuf::Int32Value.new(value: 3)},
335
+ map_int64: {0 => Google::Protobuf::Int64Value.new(value: 4)},
336
+ map_uint32: {0 => Google::Protobuf::UInt32Value.new(value: 5)},
337
+ map_uint64: {0 => Google::Protobuf::UInt64Value.new(value: 6)},
338
+ map_bool: {0 => Google::Protobuf::BoolValue.new(value: true)},
339
+ map_string: {0 => Google::Protobuf::StringValue.new(value: 'str')},
340
+ map_bytes: {0 => Google::Protobuf::BytesValue.new(value: 'fun')},
341
+ )
342
+
343
+ run_asserts.call(m)
344
+ serialized = proto_module::Wrapper::encode(m)
345
+ m2 = proto_module::Wrapper::decode(serialized)
346
+ run_asserts.call(m2)
347
+
348
+ # Test the case where we are serializing directly from the parsed form
349
+ # (before anything lazy is materialized).
350
+ m3 = proto_module::Wrapper::decode(serialized)
351
+ serialized2 = proto_module::Wrapper::encode(m3)
352
+ m4 = proto_module::Wrapper::decode(serialized2)
353
+ run_asserts.call(m4)
354
+
355
+ # Test that the lazy form compares equal to the expanded form.
356
+ m5 = proto_module::Wrapper::decode(serialized2)
357
+ assert_equal m5, m
358
+ end
359
+
360
+ def test_map_wrappers_with_default_values
361
+ run_asserts = ->(m) {
362
+ assert_equal 0.0, m.map_double[0].value
363
+ assert_equal 0.0, m.map_float[0].value
364
+ assert_equal 0, m.map_int32[0].value
365
+ assert_equal 0, m.map_int64[0].value
366
+ assert_equal 0, m.map_uint32[0].value
367
+ assert_equal 0, m.map_uint64[0].value
368
+ assert_equal false, m.map_bool[0].value
369
+ assert_equal '', m.map_string[0].value
370
+ assert_equal '', m.map_bytes[0].value
371
+ }
372
+
373
+ m = proto_module::Wrapper.new(
374
+ map_double: {0 => Google::Protobuf::DoubleValue.new(value: 0.0)},
375
+ map_float: {0 => Google::Protobuf::FloatValue.new(value: 0.0)},
376
+ map_int32: {0 => Google::Protobuf::Int32Value.new(value: 0)},
377
+ map_int64: {0 => Google::Protobuf::Int64Value.new(value: 0)},
378
+ map_uint32: {0 => Google::Protobuf::UInt32Value.new(value: 0)},
379
+ map_uint64: {0 => Google::Protobuf::UInt64Value.new(value: 0)},
380
+ map_bool: {0 => Google::Protobuf::BoolValue.new(value: false)},
381
+ map_string: {0 => Google::Protobuf::StringValue.new(value: '')},
382
+ map_bytes: {0 => Google::Protobuf::BytesValue.new(value: '')},
383
+ )
384
+
385
+ run_asserts.call(m)
386
+ serialized = proto_module::Wrapper::encode(m)
387
+ m2 = proto_module::Wrapper::decode(serialized)
388
+ run_asserts.call(m2)
389
+
390
+ # Test the case where we are serializing directly from the parsed form
391
+ # (before anything lazy is materialized).
392
+ m3 = proto_module::Wrapper::decode(serialized)
393
+ serialized2 = proto_module::Wrapper::encode(m3)
394
+ m4 = proto_module::Wrapper::decode(serialized2)
395
+ run_asserts.call(m4)
396
+
397
+ # Test that the lazy form compares equal to the expanded form.
398
+ m5 = proto_module::Wrapper::decode(serialized2)
399
+ assert_equal m5, m
400
+ end
401
+
402
+ def test_map_wrappers_with_no_value
403
+ run_asserts = ->(m) {
404
+ assert_equal 0.0, m.map_double[0].value
405
+ assert_equal 0.0, m.map_float[0].value
406
+ assert_equal 0, m.map_int32[0].value
407
+ assert_equal 0, m.map_int64[0].value
408
+ assert_equal 0, m.map_uint32[0].value
409
+ assert_equal 0, m.map_uint64[0].value
410
+ assert_equal false, m.map_bool[0].value
411
+ assert_equal '', m.map_string[0].value
412
+ assert_equal '', m.map_bytes[0].value
413
+ }
414
+
415
+ m = proto_module::Wrapper.new(
416
+ map_double: {0 => Google::Protobuf::DoubleValue.new()},
417
+ map_float: {0 => Google::Protobuf::FloatValue.new()},
418
+ map_int32: {0 => Google::Protobuf::Int32Value.new()},
419
+ map_int64: {0 => Google::Protobuf::Int64Value.new()},
420
+ map_uint32: {0 => Google::Protobuf::UInt32Value.new()},
421
+ map_uint64: {0 => Google::Protobuf::UInt64Value.new()},
422
+ map_bool: {0 => Google::Protobuf::BoolValue.new()},
423
+ map_string: {0 => Google::Protobuf::StringValue.new()},
424
+ map_bytes: {0 => Google::Protobuf::BytesValue.new()},
425
+ )
426
+ run_asserts.call(m)
427
+
428
+ serialized = proto_module::Wrapper::encode(m)
429
+ m2 = proto_module::Wrapper::decode(serialized)
430
+ run_asserts.call(m2)
431
+
432
+ # Test the case where we are serializing directly from the parsed form
433
+ # (before anything lazy is materialized).
434
+ m3 = proto_module::Wrapper::decode(serialized)
435
+ serialized2 = proto_module::Wrapper::encode(m3)
436
+ m4 = proto_module::Wrapper::decode(serialized2)
437
+ run_asserts.call(m4)
438
+ end
439
+
440
+ def test_concurrent_decoding
441
+ o = Outer.new
442
+ o.items[0] = Inner.new
443
+ raw = Outer.encode(o)
444
+
445
+ thds = 2.times.map do
446
+ Thread.new do
447
+ 100000.times do
448
+ assert_equal o, Outer.decode(raw)
449
+ end
450
+ end
451
+ end
452
+ thds.map(&:join)
453
+ end
454
+
678
455
  def test_map_encode_decode
679
456
  m = MapMessage.new(
680
457
  :map_string_int32 => {"a" => 1, "b" => 2},
681
458
  :map_string_msg => {"a" => TestMessage2.new(:foo => 1),
682
- "b" => TestMessage2.new(:foo => 2)})
459
+ "b" => TestMessage2.new(:foo => 2)},
460
+ :map_string_enum => {"a" => :A, "b" => :B})
683
461
  m2 = MapMessage.decode(MapMessage.encode(m))
684
462
  assert m == m2
685
463
 
@@ -696,213 +474,29 @@ module BasicTest
696
474
  "b" => TestMessage2.new(:foo => 2)}
697
475
  end
698
476
 
699
- def test_oneof_descriptors
700
- d = OneofMessage.descriptor
701
- o = d.lookup_oneof("my_oneof")
702
- assert o != nil
703
- assert o.class == Google::Protobuf::OneofDescriptor
704
- assert o.name == "my_oneof"
705
- oneof_count = 0
706
- d.each_oneof{ |oneof|
707
- oneof_count += 1
708
- assert oneof == o
709
- }
710
- assert oneof_count == 1
711
- assert o.count == 4
712
- field_names = o.map{|f| f.name}.sort
713
- assert field_names == ["a", "b", "c", "d"]
714
- end
715
-
716
- def test_oneof
717
- d = OneofMessage.new
718
- assert d.a == ""
719
- assert d.b == 0
720
- assert d.c == nil
721
- assert d.d == :Default
722
- assert d.my_oneof == nil
723
-
724
- d.a = "hi"
725
- assert d.a == "hi"
726
- assert d.b == 0
727
- assert d.c == nil
728
- assert d.d == :Default
729
- assert d.my_oneof == :a
730
-
731
- d.b = 42
732
- assert d.a == ""
733
- assert d.b == 42
734
- assert d.c == nil
735
- assert d.d == :Default
736
- assert d.my_oneof == :b
737
-
738
- d.c = TestMessage2.new(:foo => 100)
739
- assert d.a == ""
740
- assert d.b == 0
741
- assert d.c.foo == 100
742
- assert d.d == :Default
743
- assert d.my_oneof == :c
744
-
745
- d.d = :C
746
- assert d.a == ""
747
- assert d.b == 0
748
- assert d.c == nil
749
- assert d.d == :C
750
- assert d.my_oneof == :d
751
-
752
- d2 = OneofMessage.decode(OneofMessage.encode(d))
753
- assert d2 == d
754
-
755
- encoded_field_a = OneofMessage.encode(OneofMessage.new(:a => "string"))
756
- encoded_field_b = OneofMessage.encode(OneofMessage.new(:b => 1000))
757
- encoded_field_c = OneofMessage.encode(
758
- OneofMessage.new(:c => TestMessage2.new(:foo => 1)))
759
- encoded_field_d = OneofMessage.encode(OneofMessage.new(:d => :B))
760
-
761
- d3 = OneofMessage.decode(
762
- encoded_field_c + encoded_field_a + encoded_field_d)
763
- assert d3.a == ""
764
- assert d3.b == 0
765
- assert d3.c == nil
766
- assert d3.d == :B
767
-
768
- d4 = OneofMessage.decode(
769
- encoded_field_c + encoded_field_a + encoded_field_d +
770
- encoded_field_c)
771
- assert d4.a == ""
772
- assert d4.b == 0
773
- assert d4.c.foo == 1
774
- assert d4.d == :Default
775
-
776
- d5 = OneofMessage.new(:a => "hello")
777
- assert d5.a == "hello"
778
- d5.a = nil
779
- assert d5.a == ""
780
- assert OneofMessage.encode(d5) == ''
781
- assert d5.my_oneof == nil
782
- end
783
-
784
- def test_enum_field
785
- m = TestMessage.new
786
- assert m.optional_enum == :Default
787
- m.optional_enum = :A
788
- assert m.optional_enum == :A
789
- assert_raise RangeError do
790
- m.optional_enum = :ASDF
791
- end
792
- m.optional_enum = 1
793
- assert m.optional_enum == :A
794
- m.optional_enum = 100
795
- assert m.optional_enum == 100
796
- end
797
-
798
- def test_dup
799
- m = TestMessage.new
800
- m.optional_string = "hello"
801
- m.optional_int32 = 42
802
- tm1 = TestMessage2.new(:foo => 100)
803
- tm2 = TestMessage2.new(:foo => 200)
804
- m.repeated_msg.push tm1
805
- assert m.repeated_msg[-1] == tm1
806
- m.repeated_msg.push tm2
807
- assert m.repeated_msg[-1] == tm2
808
- m2 = m.dup
809
- assert m == m2
810
- m.optional_int32 += 1
811
- assert m != m2
812
- assert m.repeated_msg[0] == m2.repeated_msg[0]
813
- assert m.repeated_msg[0].object_id == m2.repeated_msg[0].object_id
814
- end
815
-
816
- def test_deep_copy
817
- m = TestMessage.new(:optional_int32 => 42,
818
- :repeated_msg => [TestMessage2.new(:foo => 100)])
819
- m2 = Google::Protobuf.deep_copy(m)
820
- assert m == m2
821
- assert m.repeated_msg == m2.repeated_msg
822
- assert m.repeated_msg.object_id != m2.repeated_msg.object_id
823
- assert m.repeated_msg[0].object_id != m2.repeated_msg[0].object_id
824
- end
825
-
826
- def test_eq
827
- m = TestMessage.new(:optional_int32 => 42,
828
- :repeated_int32 => [1, 2, 3])
829
- m2 = TestMessage.new(:optional_int32 => 43,
830
- :repeated_int32 => [1, 2, 3])
831
- assert m != m2
832
- end
833
-
834
- def test_enum_lookup
835
- assert TestEnum::A == 1
836
- assert TestEnum::B == 2
837
- assert TestEnum::C == 3
838
-
839
- assert TestEnum::lookup(1) == :A
840
- assert TestEnum::lookup(2) == :B
841
- assert TestEnum::lookup(3) == :C
842
-
843
- assert TestEnum::resolve(:A) == 1
844
- assert TestEnum::resolve(:B) == 2
845
- assert TestEnum::resolve(:C) == 3
846
- end
847
-
848
- def test_parse_serialize
849
- m = TestMessage.new(:optional_int32 => 42,
850
- :optional_string => "hello world",
851
- :optional_enum => :B,
852
- :repeated_string => ["a", "b", "c"],
853
- :repeated_int32 => [42, 43, 44],
854
- :repeated_enum => [:A, :B, :C, 100],
855
- :repeated_msg => [TestMessage2.new(:foo => 1),
856
- TestMessage2.new(:foo => 2)])
857
- data = TestMessage.encode m
858
- m2 = TestMessage.decode data
859
- assert m == m2
477
+ def test_protobuf_decode_json_ignore_unknown_fields
478
+ m = TestMessage.decode_json({
479
+ optional_string: "foo",
480
+ not_in_message: "some_value"
481
+ }.to_json, { ignore_unknown_fields: true })
860
482
 
861
- data = Google::Protobuf.encode m
862
- m2 = Google::Protobuf.decode(TestMessage, data)
863
- assert m == m2
864
- end
865
-
866
- def test_encode_decode_helpers
867
- m = TestMessage.new(:optional_string => 'foo', :repeated_string => ['bar1', 'bar2'])
868
- assert_equal 'foo', m.optional_string
869
- assert_equal ['bar1', 'bar2'], m.repeated_string
870
-
871
- json = m.to_json
872
- m2 = TestMessage.decode_json(json)
873
- assert_equal 'foo', m2.optional_string
874
- assert_equal ['bar1', 'bar2'], m2.repeated_string
875
- if RUBY_PLATFORM != "java"
876
- assert m2.optional_string.frozen?
877
- assert m2.repeated_string[0].frozen?
483
+ assert_equal m.optional_string, "foo"
484
+ e = assert_raise Google::Protobuf::ParseError do
485
+ TestMessage.decode_json({ not_in_message: "some_value" }.to_json)
878
486
  end
879
-
880
- proto = m.to_proto
881
- m2 = TestMessage.decode(proto)
882
- assert_equal 'foo', m2.optional_string
883
- assert_equal ['bar1', 'bar2'], m2.repeated_string
487
+ assert_match(/No such field: not_in_message/, e.message)
884
488
  end
885
489
 
886
- def test_protobuf_encode_decode_helpers
887
- m = TestMessage.new(:optional_string => 'foo', :repeated_string => ['bar1', 'bar2'])
888
- encoded_msg = Google::Protobuf.encode(m)
889
- assert_equal m.to_proto, encoded_msg
890
-
891
- decoded_msg = Google::Protobuf.decode(TestMessage, encoded_msg)
892
- assert_equal TestMessage.decode(m.to_proto), decoded_msg
893
- end
894
-
895
- def test_protobuf_encode_decode_json_helpers
896
- m = TestMessage.new(:optional_string => 'foo', :repeated_string => ['bar1', 'bar2'])
897
- encoded_msg = Google::Protobuf.encode_json(m)
898
- assert_equal m.to_json, encoded_msg
899
-
900
- decoded_msg = Google::Protobuf.decode_json(TestMessage, encoded_msg)
901
- assert_equal TestMessage.decode_json(m.to_json), decoded_msg
902
- end
490
+ #def test_json_quoted_string
491
+ # m = TestMessage.decode_json(%q(
492
+ # "optionalInt64": "1",,
493
+ # }))
494
+ # puts(m)
495
+ # assert_equal 1, m.optional_int32
496
+ #end
903
497
 
904
498
  def test_to_h
905
- m = TestMessage.new(:optional_bool => true, :optional_double => -10.100001, :optional_string => 'foo', :repeated_string => ['bar1', 'bar2'])
499
+ m = TestMessage.new(:optional_bool => true, :optional_double => -10.100001, :optional_string => 'foo', :repeated_string => ['bar1', 'bar2'], :repeated_msg => [TestMessage2.new(:foo => 100)])
906
500
  expected_result = {
907
501
  :optional_bool=>true,
908
502
  :optional_bytes=>"",
@@ -912,6 +506,8 @@ module BasicTest
912
506
  :optional_int32=>0,
913
507
  :optional_int64=>0,
914
508
  :optional_msg=>nil,
509
+ :optional_msg2=>nil,
510
+ :optional_proto2_submessage=>nil,
915
511
  :optional_string=>"foo",
916
512
  :optional_uint32=>0,
917
513
  :optional_uint64=>0,
@@ -922,7 +518,7 @@ module BasicTest
922
518
  :repeated_float=>[],
923
519
  :repeated_int32=>[],
924
520
  :repeated_int64=>[],
925
- :repeated_msg=>[],
521
+ :repeated_msg=>[{:foo => 100}],
926
522
  :repeated_string=>["bar1", "bar2"],
927
523
  :repeated_uint32=>[],
928
524
  :repeated_uint64=>[]
@@ -932,400 +528,121 @@ module BasicTest
932
528
  m = MapMessage.new(
933
529
  :map_string_int32 => {"a" => 1, "b" => 2},
934
530
  :map_string_msg => {"a" => TestMessage2.new(:foo => 1),
935
- "b" => TestMessage2.new(:foo => 2)})
531
+ "b" => TestMessage2.new(:foo => 2)},
532
+ :map_string_enum => {"a" => :A, "b" => :B})
936
533
  expected_result = {
937
534
  :map_string_int32 => {"a" => 1, "b" => 2},
938
- :map_string_msg => {"a" => {:foo => 1}, "b" => {:foo => 2}}
535
+ :map_string_msg => {"a" => {:foo => 1}, "b" => {:foo => 2}},
536
+ :map_string_enum => {"a" => :A, "b" => :B}
939
537
  }
940
538
  assert_equal expected_result, m.to_h
941
539
  end
942
540
 
943
541
 
944
- def test_def_errors
945
- s = Google::Protobuf::DescriptorPool.new
946
- assert_raise TypeError do
947
- s.build do
948
- # enum with no default (integer value 0)
949
- add_enum "MyEnum" do
950
- value :A, 1
951
- end
952
- end
953
- end
954
- assert_raise TypeError do
955
- s.build do
956
- # message with required field (unsupported in proto3)
957
- add_message "MyMessage" do
958
- required :foo, :int32, 1
959
- end
960
- end
961
- end
962
- end
963
-
964
- def test_corecursive
965
- # just be sure that we can instantiate types with corecursive field-type
966
- # references.
967
- m = Recursive1.new(:foo => Recursive2.new(:foo => Recursive1.new))
968
- assert Recursive1.descriptor.lookup("foo").subtype ==
969
- Recursive2.descriptor
970
- assert Recursive2.descriptor.lookup("foo").subtype ==
971
- Recursive1.descriptor
972
-
973
- serialized = Recursive1.encode(m)
974
- m2 = Recursive1.decode(serialized)
975
- assert m == m2
976
- end
977
-
978
- def test_serialize_cycle
979
- m = Recursive1.new(:foo => Recursive2.new)
980
- m.foo.foo = m
981
- assert_raise RuntimeError do
982
- serialized = Recursive1.encode(m)
983
- end
984
- end
985
-
986
- def test_bad_field_names
987
- m = BadFieldNames.new(:dup => 1, :class => 2)
988
- m2 = m.dup
989
- assert m == m2
990
- assert m['dup'] == 1
991
- assert m['class'] == 2
992
- m['dup'] = 3
993
- assert m['dup'] == 3
994
- m['a.b'] = 4
995
- assert m['a.b'] == 4
996
- end
997
-
998
- def test_int_ranges
999
- m = TestMessage.new
1000
-
1001
- m.optional_int32 = 0
1002
- m.optional_int32 = -0x8000_0000
1003
- m.optional_int32 = +0x7fff_ffff
1004
- m.optional_int32 = 1.0
1005
- m.optional_int32 = -1.0
1006
- m.optional_int32 = 2e9
1007
- assert_raise RangeError do
1008
- m.optional_int32 = -0x8000_0001
1009
- end
1010
- assert_raise RangeError do
1011
- m.optional_int32 = +0x8000_0000
1012
- end
1013
- assert_raise RangeError do
1014
- m.optional_int32 = +0x1000_0000_0000_0000_0000_0000 # force Bignum
1015
- end
1016
- assert_raise RangeError do
1017
- m.optional_int32 = 1e12
1018
- end
1019
- assert_raise RangeError do
1020
- m.optional_int32 = 1.5
1021
- end
1022
-
1023
- m.optional_uint32 = 0
1024
- m.optional_uint32 = +0xffff_ffff
1025
- m.optional_uint32 = 1.0
1026
- m.optional_uint32 = 4e9
1027
- assert_raise RangeError do
1028
- m.optional_uint32 = -1
1029
- end
1030
- assert_raise RangeError do
1031
- m.optional_uint32 = -1.5
1032
- end
1033
- assert_raise RangeError do
1034
- m.optional_uint32 = -1.5e12
1035
- end
1036
- assert_raise RangeError do
1037
- m.optional_uint32 = -0x1000_0000_0000_0000
1038
- end
1039
- assert_raise RangeError do
1040
- m.optional_uint32 = +0x1_0000_0000
1041
- end
1042
- assert_raise RangeError do
1043
- m.optional_uint32 = +0x1000_0000_0000_0000_0000_0000 # force Bignum
1044
- end
1045
- assert_raise RangeError do
1046
- m.optional_uint32 = 1e12
1047
- end
1048
- assert_raise RangeError do
1049
- m.optional_uint32 = 1.5
1050
- end
1051
-
1052
- m.optional_int64 = 0
1053
- m.optional_int64 = -0x8000_0000_0000_0000
1054
- m.optional_int64 = +0x7fff_ffff_ffff_ffff
1055
- m.optional_int64 = 1.0
1056
- m.optional_int64 = -1.0
1057
- m.optional_int64 = 8e18
1058
- m.optional_int64 = -8e18
1059
- assert_raise RangeError do
1060
- m.optional_int64 = -0x8000_0000_0000_0001
1061
- end
1062
- assert_raise RangeError do
1063
- m.optional_int64 = +0x8000_0000_0000_0000
1064
- end
1065
- assert_raise RangeError do
1066
- m.optional_int64 = +0x1000_0000_0000_0000_0000_0000 # force Bignum
1067
- end
1068
- assert_raise RangeError do
1069
- m.optional_int64 = 1e50
1070
- end
1071
- assert_raise RangeError do
1072
- m.optional_int64 = 1.5
1073
- end
1074
-
1075
- m.optional_uint64 = 0
1076
- m.optional_uint64 = +0xffff_ffff_ffff_ffff
1077
- m.optional_uint64 = 1.0
1078
- m.optional_uint64 = 16e18
1079
- assert_raise RangeError do
1080
- m.optional_uint64 = -1
1081
- end
1082
- assert_raise RangeError do
1083
- m.optional_uint64 = -1.5
1084
- end
1085
- assert_raise RangeError do
1086
- m.optional_uint64 = -1.5e12
1087
- end
1088
- assert_raise RangeError do
1089
- m.optional_uint64 = -0x1_0000_0000_0000_0000
1090
- end
1091
- assert_raise RangeError do
1092
- m.optional_uint64 = +0x1_0000_0000_0000_0000
1093
- end
1094
- assert_raise RangeError do
1095
- m.optional_uint64 = +0x1000_0000_0000_0000_0000_0000 # force Bignum
1096
- end
1097
- assert_raise RangeError do
1098
- m.optional_uint64 = 1e50
1099
- end
1100
- assert_raise RangeError do
1101
- m.optional_uint64 = 1.5
1102
- end
1103
- end
1104
-
1105
- def test_stress_test
1106
- m = TestMessage.new
1107
- m.optional_int32 = 42
1108
- m.optional_int64 = 0x100000000
1109
- m.optional_string = "hello world"
1110
- 10.times do m.repeated_msg.push TestMessage2.new(:foo => 42) end
1111
- 10.times do m.repeated_string.push "hello world" end
1112
-
1113
- data = TestMessage.encode(m)
1114
-
1115
- l = 0
1116
- 10_000.times do
1117
- m = TestMessage.decode(data)
1118
- data_new = TestMessage.encode(m)
1119
- assert data_new == data
1120
- data = data_new
1121
- end
1122
- end
1123
-
1124
- def test_reflection
1125
- m = TestMessage.new(:optional_int32 => 1234)
1126
- msgdef = m.class.descriptor
1127
- assert msgdef.class == Google::Protobuf::Descriptor
1128
- assert msgdef.any? {|field| field.name == "optional_int32"}
1129
- optional_int32 = msgdef.lookup "optional_int32"
1130
- assert optional_int32.class == Google::Protobuf::FieldDescriptor
1131
- assert optional_int32 != nil
1132
- assert optional_int32.name == "optional_int32"
1133
- assert optional_int32.type == :int32
1134
- optional_int32.set(m, 5678)
1135
- assert m.optional_int32 == 5678
1136
- m.optional_int32 = 1000
1137
- assert optional_int32.get(m) == 1000
1138
-
1139
- optional_msg = msgdef.lookup "optional_msg"
1140
- assert optional_msg.subtype == TestMessage2.descriptor
1141
-
1142
- optional_msg.set(m, optional_msg.subtype.msgclass.new)
1143
-
1144
- assert msgdef.msgclass == TestMessage
1145
-
1146
- optional_enum = msgdef.lookup "optional_enum"
1147
- assert optional_enum.subtype == TestEnum.descriptor
1148
- assert optional_enum.subtype.class == Google::Protobuf::EnumDescriptor
1149
- optional_enum.subtype.each do |k, v|
1150
- # set with integer, check resolution to symbolic name
1151
- optional_enum.set(m, v)
1152
- assert optional_enum.get(m) == k
1153
- end
1154
- end
1155
-
1156
- def test_json
542
+ def test_json_maps
1157
543
  # TODO: Fix JSON in JRuby version.
1158
544
  return if RUBY_PLATFORM == "java"
1159
- m = TestMessage.new(:optional_int32 => 1234,
1160
- :optional_int64 => -0x1_0000_0000,
1161
- :optional_uint32 => 0x8000_0000,
1162
- :optional_uint64 => 0xffff_ffff_ffff_ffff,
1163
- :optional_bool => true,
1164
- :optional_float => 1.0,
1165
- :optional_double => -1e100,
1166
- :optional_string => "Test string",
1167
- :optional_bytes => ["FFFFFFFF"].pack('H*'),
1168
- :optional_msg => TestMessage2.new(:foo => 42),
1169
- :repeated_int32 => [1, 2, 3, 4],
1170
- :repeated_string => ["a", "b", "c"],
1171
- :repeated_bool => [true, false, true, false],
1172
- :repeated_msg => [TestMessage2.new(:foo => 1),
1173
- TestMessage2.new(:foo => 2)])
1174
-
1175
- json_text = TestMessage.encode_json(m)
1176
- m2 = TestMessage.decode_json(json_text)
1177
- puts m.inspect
1178
- puts m2.inspect
1179
- assert m == m2
545
+ m = MapMessage.new(:map_string_int32 => {"a" => 1})
546
+ expected = {mapStringInt32: {a: 1}, mapStringMsg: {}, mapStringEnum: {}}
547
+ expected_preserve = {map_string_int32: {a: 1}, map_string_msg: {}, map_string_enum: {}}
548
+ assert_equal JSON.parse(MapMessage.encode_json(m, :emit_defaults=>true), :symbolize_names => true), expected
1180
549
 
1181
- # Crash case from GitHub issue 283.
1182
- bar = Bar.new(msg: "bar")
1183
- baz1 = Baz.new(msg: "baz")
1184
- baz2 = Baz.new(msg: "quux")
1185
- Foo.encode_json(Foo.new)
1186
- Foo.encode_json(Foo.new(bar: bar))
1187
- Foo.encode_json(Foo.new(bar: bar, baz: [baz1, baz2]))
550
+ json = MapMessage.encode_json(m, :preserve_proto_fieldnames => true, :emit_defaults=>true)
551
+ assert_equal JSON.parse(json, :symbolize_names => true), expected_preserve
552
+
553
+ m2 = MapMessage.decode_json(MapMessage.encode_json(m))
554
+ assert_equal m, m2
1188
555
  end
1189
556
 
1190
- def test_json_emit_defaults
557
+ def test_json_maps_emit_defaults_submsg
1191
558
  # TODO: Fix JSON in JRuby version.
1192
559
  return if RUBY_PLATFORM == "java"
1193
- m = TestMessage.new
560
+ m = MapMessage.new(:map_string_msg => {"a" => TestMessage2.new(foo: 0)})
561
+ expected = {mapStringInt32: {}, mapStringMsg: {a: {foo: 0}}, mapStringEnum: {}}
1194
562
 
1195
- expected = {
1196
- optionalInt32: 0,
1197
- optionalInt64: 0,
1198
- optionalUint32: 0,
1199
- optionalUint64: 0,
1200
- optionalBool: false,
1201
- optionalFloat: 0,
1202
- optionalDouble: 0,
1203
- optionalString: "",
1204
- optionalBytes: "",
1205
- optionalEnum: "Default",
1206
- repeatedInt32: [],
1207
- repeatedInt64: [],
1208
- repeatedUint32: [],
1209
- repeatedUint64: [],
1210
- repeatedBool: [],
1211
- repeatedFloat: [],
1212
- repeatedDouble: [],
1213
- repeatedString: [],
1214
- repeatedBytes: [],
1215
- repeatedMsg: [],
1216
- repeatedEnum: []
1217
- }
1218
-
1219
- actual = TestMessage.encode_json(m, :emit_defaults => true)
563
+ actual = MapMessage.encode_json(m, :emit_defaults => true)
1220
564
 
1221
- assert JSON.parse(actual, :symbolize_names => true) == expected
565
+ assert_equal JSON.parse(actual, :symbolize_names => true), expected
1222
566
  end
1223
567
 
1224
568
  def test_json_emit_defaults_submsg
1225
569
  # TODO: Fix JSON in JRuby version.
1226
570
  return if RUBY_PLATFORM == "java"
1227
- m = TestMessage.new(optional_msg: TestMessage2.new)
571
+ m = TestSingularFields.new(singular_msg: proto_module::TestMessage2.new)
1228
572
 
1229
573
  expected = {
1230
- optionalInt32: 0,
1231
- optionalInt64: 0,
1232
- optionalUint32: 0,
1233
- optionalUint64: 0,
1234
- optionalBool: false,
1235
- optionalFloat: 0,
1236
- optionalDouble: 0,
1237
- optionalString: "",
1238
- optionalBytes: "",
1239
- optionalMsg: {foo: 0},
1240
- optionalEnum: "Default",
1241
- repeatedInt32: [],
1242
- repeatedInt64: [],
1243
- repeatedUint32: [],
1244
- repeatedUint64: [],
1245
- repeatedBool: [],
1246
- repeatedFloat: [],
1247
- repeatedDouble: [],
1248
- repeatedString: [],
1249
- repeatedBytes: [],
1250
- repeatedMsg: [],
1251
- repeatedEnum: []
574
+ singularInt32: 0,
575
+ singularInt64: "0",
576
+ singularUint32: 0,
577
+ singularUint64: "0",
578
+ singularBool: false,
579
+ singularFloat: 0,
580
+ singularDouble: 0,
581
+ singularString: "",
582
+ singularBytes: "",
583
+ singularMsg: {},
584
+ singularEnum: "Default",
1252
585
  }
1253
586
 
1254
- actual = TestMessage.encode_json(m, :emit_defaults => true)
587
+ actual = proto_module::TestMessage.encode_json(m, :emit_defaults => true)
1255
588
 
1256
- assert JSON.parse(actual, :symbolize_names => true) == expected
589
+ assert_equal expected, JSON.parse(actual, :symbolize_names => true)
1257
590
  end
1258
591
 
1259
- def test_json_emit_defaults_repeated_submsg
1260
- # TODO: Fix JSON in JRuby version.
592
+ def test_respond_to
593
+ # This test fails with JRuby 1.7.23, likely because of an old JRuby bug.
1261
594
  return if RUBY_PLATFORM == "java"
1262
- m = TestMessage.new(repeated_msg: [TestMessage2.new])
1263
-
1264
- expected = {
1265
- optionalInt32: 0,
1266
- optionalInt64: 0,
1267
- optionalUint32: 0,
1268
- optionalUint64: 0,
1269
- optionalBool: false,
1270
- optionalFloat: 0,
1271
- optionalDouble: 0,
1272
- optionalString: "",
1273
- optionalBytes: "",
1274
- optionalEnum: "Default",
1275
- repeatedInt32: [],
1276
- repeatedInt64: [],
1277
- repeatedUint32: [],
1278
- repeatedUint64: [],
1279
- repeatedBool: [],
1280
- repeatedFloat: [],
1281
- repeatedDouble: [],
1282
- repeatedString: [],
1283
- repeatedBytes: [],
1284
- repeatedMsg: [{foo: 0}],
1285
- repeatedEnum: []
1286
- }
595
+ msg = MapMessage.new
596
+ assert msg.respond_to?(:map_string_int32)
597
+ assert !msg.respond_to?(:bacon)
598
+ end
1287
599
 
1288
- actual = TestMessage.encode_json(m, :emit_defaults => true)
600
+ def test_file_descriptor
601
+ file_descriptor = TestMessage.descriptor.file_descriptor
602
+ assert nil != file_descriptor
603
+ assert_equal "tests/basic_test.proto", file_descriptor.name
604
+ assert_equal :proto3, file_descriptor.syntax
1289
605
 
1290
- assert JSON.parse(actual, :symbolize_names => true) == expected
606
+ file_descriptor = TestEnum.descriptor.file_descriptor
607
+ assert nil != file_descriptor
608
+ assert_equal "tests/basic_test.proto", file_descriptor.name
609
+ assert_equal :proto3, file_descriptor.syntax
1291
610
  end
1292
611
 
1293
- def test_json_maps
1294
- # TODO: Fix JSON in JRuby version.
1295
- return if RUBY_PLATFORM == "java"
1296
- m = MapMessage.new(:map_string_int32 => {"a" => 1})
1297
- expected = {mapStringInt32: {a: 1}, mapStringMsg: {}}
1298
- expected_preserve = {map_string_int32: {a: 1}, map_string_msg: {}}
1299
- assert JSON.parse(MapMessage.encode_json(m), :symbolize_names => true) == expected
1300
-
1301
- json = MapMessage.encode_json(m, :preserve_proto_fieldnames => true)
1302
- assert JSON.parse(json, :symbolize_names => true) == expected_preserve
612
+ # Ruby 2.5 changed to raise FrozenError instead of RuntimeError
613
+ FrozenErrorType = Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.5') ? RuntimeError : FrozenError
1303
614
 
1304
- m2 = MapMessage.decode_json(MapMessage.encode_json(m))
1305
- assert m == m2
1306
- end
615
+ def test_map_freeze
616
+ m = proto_module::MapMessage.new
617
+ m.map_string_int32['a'] = 5
618
+ m.map_string_msg['b'] = proto_module::TestMessage2.new
1307
619
 
1308
- def test_json_maps_emit_defaults_submsg
1309
- # TODO: Fix JSON in JRuby version.
1310
- return if RUBY_PLATFORM == "java"
1311
- m = MapMessage.new(:map_string_msg => {"a" => TestMessage2.new})
1312
- expected = {mapStringInt32: {}, mapStringMsg: {a: {foo: 0}}}
620
+ m.map_string_int32.freeze
621
+ m.map_string_msg.freeze
1313
622
 
1314
- actual = MapMessage.encode_json(m, :emit_defaults => true)
623
+ assert m.map_string_int32.frozen?
624
+ assert m.map_string_msg.frozen?
1315
625
 
1316
- assert JSON.parse(actual, :symbolize_names => true) == expected
626
+ assert_raise(FrozenErrorType) { m.map_string_int32['foo'] = 1 }
627
+ assert_raise(FrozenErrorType) { m.map_string_msg['bar'] = proto_module::TestMessage2.new }
628
+ assert_raise(FrozenErrorType) { m.map_string_int32.delete('a') }
629
+ assert_raise(FrozenErrorType) { m.map_string_int32.clear }
1317
630
  end
1318
631
 
1319
- def test_comparison_with_arbitrary_object
1320
- assert MapMessage.new != nil
1321
- end
632
+ def test_map_length
633
+ m = proto_module::MapMessage.new
634
+ assert_equal 0, m.map_string_int32.length
635
+ assert_equal 0, m.map_string_msg.length
636
+ assert_equal 0, m.map_string_int32.size
637
+ assert_equal 0, m.map_string_msg.size
1322
638
 
1323
- def test_respond_to
1324
- # This test fails with JRuby 1.7.23, likely because of an old JRuby bug.
1325
- return if RUBY_PLATFORM == "java"
1326
- msg = MapMessage.new
1327
- assert msg.respond_to?(:map_string_int32)
1328
- assert !msg.respond_to?(:bacon)
639
+ m.map_string_int32['a'] = 1
640
+ m.map_string_int32['b'] = 2
641
+ m.map_string_msg['a'] = proto_module::TestMessage2.new
642
+ assert_equal 2, m.map_string_int32.length
643
+ assert_equal 1, m.map_string_msg.length
644
+ assert_equal 2, m.map_string_int32.size
645
+ assert_equal 1, m.map_string_msg.size
1329
646
  end
1330
647
  end
1331
648
  end