Pull new version of protobuf sources.
[chromium-blink-merge.git] / third_party / protobuf / ruby / tests / basic.rb
blob40c200786beb7526bee5f1b79cef9b3e957b915d
1 #!/usr/bin/ruby
3 require 'google/protobuf'
4 require 'test/unit'
6 # ------------- generated code --------------
8 module BasicTest
9   pool = Google::Protobuf::DescriptorPool.new
10   pool.build do
11     add_message "Foo" do
12       optional :bar, :message, 1, "Bar"
13       repeated :baz, :message, 2, "Baz"
14     end
16     add_message "Bar" do
17       optional :msg, :string, 1
18     end
20     add_message "Baz" do
21       optional :msg, :string, 1
22     end
24     add_message "TestMessage" do
25       optional :optional_int32,  :int32,        1
26       optional :optional_int64,  :int64,        2
27       optional :optional_uint32, :uint32,       3
28       optional :optional_uint64, :uint64,       4
29       optional :optional_bool,   :bool,         5
30       optional :optional_float,  :float,        6
31       optional :optional_double, :double,       7
32       optional :optional_string, :string,       8
33       optional :optional_bytes,  :bytes,        9
34       optional :optional_msg,    :message,      10, "TestMessage2"
35       optional :optional_enum,   :enum,         11, "TestEnum"
37       repeated :repeated_int32,  :int32,        12
38       repeated :repeated_int64,  :int64,        13
39       repeated :repeated_uint32, :uint32,       14
40       repeated :repeated_uint64, :uint64,       15
41       repeated :repeated_bool,   :bool,         16
42       repeated :repeated_float,  :float,        17
43       repeated :repeated_double, :double,       18
44       repeated :repeated_string, :string,       19
45       repeated :repeated_bytes,  :bytes,        20
46       repeated :repeated_msg,    :message,      21, "TestMessage2"
47       repeated :repeated_enum,   :enum,         22, "TestEnum"
48     end
49     add_message "TestMessage2" do
50       optional :foo, :int32, 1
51     end
53     add_message "Recursive1" do
54       optional :foo, :message, 1, "Recursive2"
55     end
56     add_message "Recursive2" do
57       optional :foo, :message, 1, "Recursive1"
58     end
60     add_enum "TestEnum" do
61       value :Default, 0
62       value :A, 1
63       value :B, 2
64       value :C, 3
65     end
67     add_message "BadFieldNames" do
68       optional :dup, :int32, 1
69       optional :class, :int32, 2
70       optional :"a.b", :int32, 3
71     end
73     add_message "MapMessage" do
74       map :map_string_int32, :string, :int32, 1
75       map :map_string_msg, :string, :message, 2, "TestMessage2"
76     end
77     add_message "MapMessageWireEquiv" do
78       repeated :map_string_int32, :message, 1, "MapMessageWireEquiv_entry1"
79       repeated :map_string_msg, :message, 2, "MapMessageWireEquiv_entry2"
80     end
81     add_message "MapMessageWireEquiv_entry1" do
82       optional :key, :string, 1
83       optional :value, :int32, 2
84     end
85     add_message "MapMessageWireEquiv_entry2" do
86       optional :key, :string, 1
87       optional :value, :message, 2, "TestMessage2"
88     end
90     add_message "OneofMessage" do
91       oneof :my_oneof do
92         optional :a, :string, 1
93         optional :b, :int32, 2
94         optional :c, :message, 3, "TestMessage2"
95         optional :d, :enum, 4, "TestEnum"
96       end
97     end
98   end
100   Foo = pool.lookup("Foo").msgclass
101   Bar = pool.lookup("Bar").msgclass
102   Baz = pool.lookup("Baz").msgclass
103   TestMessage = pool.lookup("TestMessage").msgclass
104   TestMessage2 = pool.lookup("TestMessage2").msgclass
105   Recursive1 = pool.lookup("Recursive1").msgclass
106   Recursive2 = pool.lookup("Recursive2").msgclass
107   TestEnum = pool.lookup("TestEnum").enummodule
108   BadFieldNames = pool.lookup("BadFieldNames").msgclass
109   MapMessage = pool.lookup("MapMessage").msgclass
110   MapMessageWireEquiv = pool.lookup("MapMessageWireEquiv").msgclass
111   MapMessageWireEquiv_entry1 =
112     pool.lookup("MapMessageWireEquiv_entry1").msgclass
113   MapMessageWireEquiv_entry2 =
114     pool.lookup("MapMessageWireEquiv_entry2").msgclass
115   OneofMessage = pool.lookup("OneofMessage").msgclass
117 # ------------ test cases ---------------
119   class MessageContainerTest < Test::Unit::TestCase
121     def test_defaults
122       m = TestMessage.new
123       assert m.optional_int32 == 0
124       assert m.optional_int64 == 0
125       assert m.optional_uint32 == 0
126       assert m.optional_uint64 == 0
127       assert m.optional_bool == false
128       assert m.optional_float == 0.0
129       assert m.optional_double == 0.0
130       assert m.optional_string == ""
131       assert m.optional_bytes == ""
132       assert m.optional_msg == nil
133       assert m.optional_enum == :Default
134     end
136     def test_setters
137       m = TestMessage.new
138       m.optional_int32 = -42
139       assert m.optional_int32 == -42
140       m.optional_int64 = -0x1_0000_0000
141       assert m.optional_int64 == -0x1_0000_0000
142       m.optional_uint32 = 0x9000_0000
143       assert m.optional_uint32 == 0x9000_0000
144       m.optional_uint64 = 0x9000_0000_0000_0000
145       assert m.optional_uint64 == 0x9000_0000_0000_0000
146       m.optional_bool = true
147       assert m.optional_bool == true
148       m.optional_float = 0.5
149       assert m.optional_float == 0.5
150       m.optional_double = 0.5
151       m.optional_string = "hello"
152       assert m.optional_string == "hello"
153       m.optional_bytes = "world".encode!('ASCII-8BIT')
154       assert m.optional_bytes == "world"
155       m.optional_msg = TestMessage2.new(:foo => 42)
156       assert m.optional_msg == TestMessage2.new(:foo => 42)
157       m.optional_msg = nil
158       assert m.optional_msg == nil
159     end
161     def test_ctor_args
162       m = TestMessage.new(:optional_int32 => -42,
163                           :optional_msg => TestMessage2.new,
164                           :optional_enum => :C,
165                           :repeated_string => ["hello", "there", "world"])
166       assert m.optional_int32 == -42
167       assert m.optional_msg.class == TestMessage2
168       assert m.repeated_string.length == 3
169       assert m.optional_enum == :C
170       assert m.repeated_string[0] == "hello"
171       assert m.repeated_string[1] == "there"
172       assert m.repeated_string[2] == "world"
173     end
175     def test_inspect
176       m = TestMessage.new(:optional_int32 => -42,
177                           :optional_enum => :A,
178                           :optional_msg => TestMessage2.new,
179                           :repeated_string => ["hello", "there", "world"])
180       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: []>'
181       assert_equal expected, m.inspect
182     end
184     def test_hash
185       m1 = TestMessage.new(:optional_int32 => 42)
186       m2 = TestMessage.new(:optional_int32 => 102)
187       assert m1.hash != 0
188       assert m2.hash != 0
189       # relying on the randomness here -- if hash function changes and we are
190       # unlucky enough to get a collision, then change the values above.
191       assert m1.hash != m2.hash
192     end
194     def test_type_errors
195       m = TestMessage.new
196       assert_raise TypeError do
197         m.optional_int32 = "hello"
198       end
199       assert_raise TypeError do
200         m.optional_string = 42
201       end
202       assert_raise TypeError do
203         m.optional_string = nil
204       end
205       assert_raise TypeError do
206         m.optional_bool = 42
207       end
208       assert_raise TypeError do
209         m.optional_msg = TestMessage.new  # expects TestMessage2
210       end
212       assert_raise TypeError do
213         m.repeated_int32 = []  # needs RepeatedField
214       end
216       assert_raise TypeError do
217         m.repeated_int32.push "hello"
218       end
220       assert_raise TypeError do
221         m.repeated_msg.push TestMessage.new
222       end
223     end
225     def test_string_encoding
226       m = TestMessage.new
228       # Assigning a normal (ASCII or UTF8) string to a bytes field, or
229       # ASCII-8BIT to a string field, raises an error.
230       assert_raise TypeError do
231         m.optional_bytes = "Test string ASCII".encode!('ASCII')
232       end
233       assert_raise TypeError do
234         m.optional_bytes = "Test string UTF-8 \u0100".encode!('UTF-8')
235       end
236       assert_raise TypeError do
237         m.optional_string = ["FFFF"].pack('H*')
238       end
240       # "Ordinary" use case.
241       m.optional_bytes = ["FFFF"].pack('H*')
242       m.optional_string = "\u0100"
244       # strings are mutable so we can do this, but serialize should catch it.
245       m.optional_string = "asdf".encode!('UTF-8')
246       m.optional_string.encode!('ASCII-8BIT')
247       assert_raise TypeError do
248         data = TestMessage.encode(m)
249       end
250     end
252     def test_rptfield_int32
253       l = Google::Protobuf::RepeatedField.new(:int32)
254       assert l.count == 0
255       l = Google::Protobuf::RepeatedField.new(:int32, [1, 2, 3])
256       assert l.count == 3
257       assert_equal [1, 2, 3], l
258       assert_equal l, [1, 2, 3]
259       l.push 4
260       assert l == [1, 2, 3, 4]
261       dst_list = []
262       l.each { |val| dst_list.push val }
263       assert dst_list == [1, 2, 3, 4]
264       assert l.to_a == [1, 2, 3, 4]
265       assert l[0] == 1
266       assert l[3] == 4
267       l[0] = 5
268       assert l == [5, 2, 3, 4]
270       l2 = l.dup
271       assert l == l2
272       assert l.object_id != l2.object_id
273       l2.push 6
274       assert l.count == 4
275       assert l2.count == 5
277       assert l.inspect == '[5, 2, 3, 4]'
279       l.concat([7, 8, 9])
280       assert l == [5, 2, 3, 4, 7, 8, 9]
281       assert l.pop == 9
282       assert l == [5, 2, 3, 4, 7, 8]
284       assert_raise TypeError do
285         m = TestMessage.new
286         l.push m
287       end
289       m = TestMessage.new
290       m.repeated_int32 = l
291       assert m.repeated_int32 == [5, 2, 3, 4, 7, 8]
292       assert m.repeated_int32.object_id == l.object_id
293       l.push 42
294       assert m.repeated_int32.pop == 42
296       l3 = l + l.dup
297       assert l3.count == l.count * 2
298       l.count.times do |i|
299         assert l3[i] == l[i]
300         assert l3[l.count + i] == l[i]
301       end
303       l.clear
304       assert l.count == 0
305       l += [1, 2, 3, 4]
306       l.replace([5, 6, 7, 8])
307       assert l == [5, 6, 7, 8]
309       l4 = Google::Protobuf::RepeatedField.new(:int32)
310       l4[5] = 42
311       assert l4 == [0, 0, 0, 0, 0, 42]
313       l4 << 100
314       assert l4 == [0, 0, 0, 0, 0, 42, 100]
315       l4 << 101 << 102
316       assert l4 == [0, 0, 0, 0, 0, 42, 100, 101, 102]
317     end
319     def test_parent_rptfield
320       #make sure we set the RepeatedField and can add to it
321       m = TestMessage.new
322       assert m.repeated_string == []
323       m.repeated_string << 'ok'
324       m.repeated_string.push('ok2')
325       assert m.repeated_string == ['ok', 'ok2']
326       m.repeated_string += ['ok3']
327       assert m.repeated_string == ['ok', 'ok2', 'ok3']
328     end
330     def test_rptfield_msg
331       l = Google::Protobuf::RepeatedField.new(:message, TestMessage)
332       l.push TestMessage.new
333       assert l.count == 1
334       assert_raise TypeError do
335         l.push TestMessage2.new
336       end
337       assert_raise TypeError do
338         l.push 42
339       end
341       l2 = l.dup
342       assert l2[0] == l[0]
343       assert l2[0].object_id == l[0].object_id
345       l2 = Google::Protobuf.deep_copy(l)
346       assert l2[0] == l[0]
347       assert l2[0].object_id != l[0].object_id
349       l3 = l + l2
350       assert l3.count == 2
351       assert l3[0] == l[0]
352       assert l3[1] == l2[0]
353       l3[0].optional_int32 = 1000
354       assert l[0].optional_int32 == 1000
356       new_msg = TestMessage.new(:optional_int32 => 200)
357       l4 = l + [new_msg]
358       assert l4.count == 2
359       new_msg.optional_int32 = 1000
360       assert l4[1].optional_int32 == 1000
361     end
363     def test_rptfield_enum
364       l = Google::Protobuf::RepeatedField.new(:enum, TestEnum)
365       l.push :A
366       l.push :B
367       l.push :C
368       assert l.count == 3
369       assert_raise RangeError do
370         l.push :D
371       end
372       assert l[0] == :A
374       l.push 4
375       assert l[3] == 4
376     end
378     def test_rptfield_initialize
379       assert_raise ArgumentError do
380         l = Google::Protobuf::RepeatedField.new
381       end
382       assert_raise ArgumentError do
383         l = Google::Protobuf::RepeatedField.new(:message)
384       end
385       assert_raise ArgumentError do
386         l = Google::Protobuf::RepeatedField.new([1, 2, 3])
387       end
388       assert_raise ArgumentError do
389         l = Google::Protobuf::RepeatedField.new(:message, [TestMessage2.new])
390       end
391     end
393     def test_rptfield_array_ducktyping
394       l = Google::Protobuf::RepeatedField.new(:int32)
395       length_methods = %w(count length size)
396       length_methods.each do |lm|
397         assert l.send(lm)  == 0
398       end
399       # out of bounds returns a nil
400       assert l[0] == nil
401       assert l[1] == nil
402       assert l[-1] == nil
403       l.push 4
404       length_methods.each do |lm|
405         assert l.send(lm) == 1
406       end
407       assert l[0] == 4
408       assert l[1] == nil
409       assert l[-1] == 4
410       assert l[-2] == nil
412       l.push 2
413       length_methods.each do |lm|
414         assert l.send(lm) == 2
415       end
416       assert l[0] == 4
417       assert l[1] == 2
418       assert l[2] == nil
419       assert l[-1] == 2
420       assert l[-2] == 4
421       assert l[-3] == nil
423       #adding out of scope will backfill with empty objects
424     end
426     def test_map_basic
427       # allowed key types:
428       # :int32, :int64, :uint32, :uint64, :bool, :string, :bytes.
430       m = Google::Protobuf::Map.new(:string, :int32)
431       m["asdf"] = 1
432       assert m["asdf"] == 1
433       m["jkl;"] = 42
434       assert m == { "jkl;" => 42, "asdf" => 1 }
435       assert m.has_key?("asdf")
436       assert !m.has_key?("qwerty")
437       assert m.length == 2
439       m2 = m.dup
440       assert m == m2
441       assert m.hash != 0
442       assert m.hash == m2.hash
444       collected = {}
445       m.each { |k,v| collected[v] = k }
446       assert collected == { 42 => "jkl;", 1 => "asdf" }
448       assert m.delete("asdf") == 1
449       assert !m.has_key?("asdf")
450       assert m["asdf"] == nil
451       assert !m.has_key?("asdf")
453       # We only assert on inspect value when there is one map entry because the
454       # order in which elements appear is unspecified (depends on the internal
455       # hash function). We don't want a brittle test.
456       assert m.inspect == "{\"jkl;\"=>42}"
458       assert m.keys == ["jkl;"]
459       assert m.values == [42]
461       m.clear
462       assert m.length == 0
463       assert m == {}
465       assert_raise TypeError do
466         m[1] = 1
467       end
468       assert_raise RangeError do
469         m["asdf"] = 0x1_0000_0000
470       end
471     end
473     def test_map_ctor
474       m = Google::Protobuf::Map.new(:string, :int32,
475                                     {"a" => 1, "b" => 2, "c" => 3})
476       assert m == {"a" => 1, "c" => 3, "b" => 2}
477     end
479     def test_map_keytypes
480       m = Google::Protobuf::Map.new(:int32, :int32)
481       m[1] = 42
482       m[-1] = 42
483       assert_raise RangeError do
484         m[0x8000_0000] = 1
485       end
486       assert_raise TypeError do
487         m["asdf"] = 1
488       end
490       m = Google::Protobuf::Map.new(:int64, :int32)
491       m[0x1000_0000_0000_0000] = 1
492       assert_raise RangeError do
493         m[0x1_0000_0000_0000_0000] = 1
494       end
495       assert_raise TypeError do
496         m["asdf"] = 1
497       end
499       m = Google::Protobuf::Map.new(:uint32, :int32)
500       m[0x8000_0000] = 1
501       assert_raise RangeError do
502         m[0x1_0000_0000] = 1
503       end
504       assert_raise RangeError do
505         m[-1] = 1
506       end
508       m = Google::Protobuf::Map.new(:uint64, :int32)
509       m[0x8000_0000_0000_0000] = 1
510       assert_raise RangeError do
511         m[0x1_0000_0000_0000_0000] = 1
512       end
513       assert_raise RangeError do
514         m[-1] = 1
515       end
517       m = Google::Protobuf::Map.new(:bool, :int32)
518       m[true] = 1
519       m[false] = 2
520       assert_raise TypeError do
521         m[1] = 1
522       end
523       assert_raise TypeError do
524         m["asdf"] = 1
525       end
527       m = Google::Protobuf::Map.new(:string, :int32)
528       m["asdf"] = 1
529       assert_raise TypeError do
530         m[1] = 1
531       end
532       assert_raise TypeError do
533         bytestring = ["FFFF"].pack("H*")
534         m[bytestring] = 1
535       end
537       m = Google::Protobuf::Map.new(:bytes, :int32)
538       bytestring = ["FFFF"].pack("H*")
539       m[bytestring] = 1
540       assert_raise TypeError do
541         m["asdf"] = 1
542       end
543       assert_raise TypeError do
544         m[1] = 1
545       end
546     end
548     def test_map_msg_enum_valuetypes
549       m = Google::Protobuf::Map.new(:string, :message, TestMessage)
550       m["asdf"] = TestMessage.new
551       assert_raise TypeError do
552         m["jkl;"] = TestMessage2.new
553       end
555       m = Google::Protobuf::Map.new(
556         :string, :message, TestMessage,
557         { "a" => TestMessage.new(:optional_int32 => 42),
558           "b" => TestMessage.new(:optional_int32 => 84) })
559       assert m.length == 2
560       assert m.values.map{|msg| msg.optional_int32}.sort == [42, 84]
562       m = Google::Protobuf::Map.new(:string, :enum, TestEnum,
563                                     { "x" => :A, "y" => :B, "z" => :C })
564       assert m.length == 3
565       assert m["z"] == :C
566       m["z"] = 2
567       assert m["z"] == :B
568       m["z"] = 4
569       assert m["z"] == 4
570       assert_raise RangeError do
571         m["z"] = :Z
572       end
573       assert_raise TypeError do
574         m["z"] = "z"
575       end
576     end
578     def test_map_dup_deep_copy
579       m = Google::Protobuf::Map.new(
580         :string, :message, TestMessage,
581         { "a" => TestMessage.new(:optional_int32 => 42),
582           "b" => TestMessage.new(:optional_int32 => 84) })
584       m2 = m.dup
585       assert m == m2
586       assert m.object_id != m2.object_id
587       assert m["a"].object_id == m2["a"].object_id
588       assert m["b"].object_id == m2["b"].object_id
590       m2 = Google::Protobuf.deep_copy(m)
591       assert m == m2
592       assert m.object_id != m2.object_id
593       assert m["a"].object_id != m2["a"].object_id
594       assert m["b"].object_id != m2["b"].object_id
595     end
597     def test_map_field
598       m = MapMessage.new
599       assert m.map_string_int32 == {}
600       assert m.map_string_msg == {}
602       m = MapMessage.new(
603         :map_string_int32 => {"a" => 1, "b" => 2},
604         :map_string_msg => {"a" => TestMessage2.new(:foo => 1),
605                             "b" => TestMessage2.new(:foo => 2)})
606       assert m.map_string_int32.keys.sort == ["a", "b"]
607       assert m.map_string_int32["a"] == 1
608       assert m.map_string_msg["b"].foo == 2
610       m.map_string_int32["c"] = 3
611       assert m.map_string_int32["c"] == 3
612       m.map_string_msg["c"] = TestMessage2.new(:foo => 3)
613       assert m.map_string_msg["c"] == TestMessage2.new(:foo => 3)
614       m.map_string_msg.delete("b")
615       m.map_string_msg.delete("c")
616       assert m.map_string_msg == { "a" => TestMessage2.new(:foo => 1) }
618       assert_raise TypeError do
619         m.map_string_msg["e"] = TestMessage.new # wrong value type
620       end
621       # ensure nothing was added by the above
622       assert m.map_string_msg == { "a" => TestMessage2.new(:foo => 1) }
624       m.map_string_int32 = Google::Protobuf::Map.new(:string, :int32)
625       assert_raise TypeError do
626         m.map_string_int32 = Google::Protobuf::Map.new(:string, :int64)
627       end
628       assert_raise TypeError do
629         m.map_string_int32 = {}
630       end
632       assert_raise TypeError do
633         m = MapMessage.new(:map_string_int32 => { 1 => "I am not a number" })
634       end
635     end
637     def test_map_encode_decode
638       m = MapMessage.new(
639         :map_string_int32 => {"a" => 1, "b" => 2},
640         :map_string_msg => {"a" => TestMessage2.new(:foo => 1),
641                             "b" => TestMessage2.new(:foo => 2)})
642       m2 = MapMessage.decode(MapMessage.encode(m))
643       assert m == m2
645       m3 = MapMessageWireEquiv.decode(MapMessage.encode(m))
646       assert m3.map_string_int32.length == 2
648       kv = {}
649       m3.map_string_int32.map { |msg| kv[msg.key] = msg.value }
650       assert kv == {"a" => 1, "b" => 2}
652       kv = {}
653       m3.map_string_msg.map { |msg| kv[msg.key] = msg.value }
654       assert kv == {"a" => TestMessage2.new(:foo => 1),
655                     "b" => TestMessage2.new(:foo => 2)}
656     end
658     def test_oneof_descriptors
659       d = OneofMessage.descriptor
660       o = d.lookup_oneof("my_oneof")
661       assert o != nil
662       assert o.class == Google::Protobuf::OneofDescriptor
663       assert o.name == "my_oneof"
664       oneof_count = 0
665       d.each_oneof{ |oneof|
666         oneof_count += 1
667         assert oneof == o
668       }
669       assert oneof_count == 1
670       assert o.count == 4
671       field_names = o.map{|f| f.name}.sort
672       assert field_names == ["a", "b", "c", "d"]
673     end
675     def test_oneof
676       d = OneofMessage.new
677       assert d.a == nil
678       assert d.b == nil
679       assert d.c == nil
680       assert d.d == nil
681       assert d.my_oneof == nil
683       d.a = "hi"
684       assert d.a == "hi"
685       assert d.b == nil
686       assert d.c == nil
687       assert d.d == nil
688       assert d.my_oneof == :a
690       d.b = 42
691       assert d.a == nil
692       assert d.b == 42
693       assert d.c == nil
694       assert d.d == nil
695       assert d.my_oneof == :b
697       d.c = TestMessage2.new(:foo => 100)
698       assert d.a == nil
699       assert d.b == nil
700       assert d.c.foo == 100
701       assert d.d == nil
702       assert d.my_oneof == :c
704       d.d = :C
705       assert d.a == nil
706       assert d.b == nil
707       assert d.c == nil
708       assert d.d == :C
709       assert d.my_oneof == :d
711       d2 = OneofMessage.decode(OneofMessage.encode(d))
712       assert d2 == d
714       encoded_field_a = OneofMessage.encode(OneofMessage.new(:a => "string"))
715       encoded_field_b = OneofMessage.encode(OneofMessage.new(:b => 1000))
716       encoded_field_c = OneofMessage.encode(
717         OneofMessage.new(:c => TestMessage2.new(:foo => 1)))
718       encoded_field_d = OneofMessage.encode(OneofMessage.new(:d => :B))
720       d3 = OneofMessage.decode(
721         encoded_field_c + encoded_field_a + encoded_field_d)
722       assert d3.a == nil
723       assert d3.b == nil
724       assert d3.c == nil
725       assert d3.d == :B
727       d4 = OneofMessage.decode(
728         encoded_field_c + encoded_field_a + encoded_field_d +
729         encoded_field_c)
730       assert d4.a == nil
731       assert d4.b == nil
732       assert d4.c.foo == 1
733       assert d4.d == nil
735       d5 = OneofMessage.new(:a => "hello")
736       assert d5.a != nil
737       d5.a = nil
738       assert d5.a == nil
739       assert OneofMessage.encode(d5) == ''
740       assert d5.my_oneof == nil
741     end
743     def test_enum_field
744       m = TestMessage.new
745       assert m.optional_enum == :Default
746       m.optional_enum = :A
747       assert m.optional_enum == :A
748       assert_raise RangeError do
749         m.optional_enum = :ASDF
750       end
751       m.optional_enum = 1
752       assert m.optional_enum == :A
753       m.optional_enum = 100
754       assert m.optional_enum == 100
755     end
757     def test_dup
758       m = TestMessage.new
759       m.optional_string = "hello"
760       m.optional_int32 = 42
761       tm1 = TestMessage2.new(:foo => 100)
762       tm2 = TestMessage2.new(:foo => 200)
763       m.repeated_msg.push tm1
764       assert m.repeated_msg[-1] == tm1
765       m.repeated_msg.push tm2
766       assert m.repeated_msg[-1] == tm2
767       m2 = m.dup
768       assert m == m2
769       m.optional_int32 += 1
770       assert m != m2
771       assert m.repeated_msg[0] == m2.repeated_msg[0]
772       assert m.repeated_msg[0].object_id == m2.repeated_msg[0].object_id
773     end
775     def test_deep_copy
776       m = TestMessage.new(:optional_int32 => 42,
777                           :repeated_msg => [TestMessage2.new(:foo => 100)])
778       m2 = Google::Protobuf.deep_copy(m)
779       assert m == m2
780       assert m.repeated_msg == m2.repeated_msg
781       assert m.repeated_msg.object_id != m2.repeated_msg.object_id
782       assert m.repeated_msg[0].object_id != m2.repeated_msg[0].object_id
783     end
785     def test_eq
786       m = TestMessage.new(:optional_int32 => 42,
787                           :repeated_int32 => [1, 2, 3])
788       m2 = TestMessage.new(:optional_int32 => 43,
789                            :repeated_int32 => [1, 2, 3])
790       assert m != m2
791     end
793     def test_enum_lookup
794       assert TestEnum::A == 1
795       assert TestEnum::B == 2
796       assert TestEnum::C == 3
798       assert TestEnum::lookup(1) == :A
799       assert TestEnum::lookup(2) == :B
800       assert TestEnum::lookup(3) == :C
802       assert TestEnum::resolve(:A) == 1
803       assert TestEnum::resolve(:B) == 2
804       assert TestEnum::resolve(:C) == 3
805     end
807     def test_parse_serialize
808       m = TestMessage.new(:optional_int32 => 42,
809                           :optional_string => "hello world",
810                           :optional_enum => :B,
811                           :repeated_string => ["a", "b", "c"],
812                           :repeated_int32 => [42, 43, 44],
813                           :repeated_enum => [:A, :B, :C, 100],
814                           :repeated_msg => [TestMessage2.new(:foo => 1),
815                                             TestMessage2.new(:foo => 2)])
816       data = TestMessage.encode m
817       m2 = TestMessage.decode data
818       assert m == m2
820       data = Google::Protobuf.encode m
821       m2 = Google::Protobuf.decode(TestMessage, data)
822       assert m == m2
823     end
825     def test_encode_decode_helpers
826       m = TestMessage.new(:optional_string => 'foo', :repeated_string => ['bar1', 'bar2'])
827       json = m.to_json
828       m2 = TestMessage.decode_json(json)
829       assert m2.optional_string == 'foo'
830       assert m2.repeated_string == ['bar1', 'bar2']
832       proto = m.to_proto
833       m2 = TestMessage.decode(proto)
834       assert m2.optional_string == 'foo'
835       assert m2.repeated_string == ['bar1', 'bar2']
836     end
838     def test_protobuf_encode_decode_helpers
839       m = TestMessage.new(:optional_string => 'foo', :repeated_string => ['bar1', 'bar2'])
840       encoded_msg = Google::Protobuf.encode(m)
841       assert_equal m.to_proto, encoded_msg
843       decoded_msg = Google::Protobuf.decode(TestMessage, encoded_msg)
844       assert_equal TestMessage.decode(m.to_proto), decoded_msg
845     end
847     def test_protobuf_encode_decode_json_helpers
848       m = TestMessage.new(:optional_string => 'foo', :repeated_string => ['bar1', 'bar2'])
849       encoded_msg = Google::Protobuf.encode_json(m)
850       assert_equal m.to_json, encoded_msg
852       decoded_msg = Google::Protobuf.decode_json(TestMessage, encoded_msg)
853       assert_equal TestMessage.decode_json(m.to_json), decoded_msg
854     end
856     def test_to_h
857       m = TestMessage.new(:optional_bool => true, :optional_double => -10.100001, :optional_string => 'foo', :repeated_string => ['bar1', 'bar2'])
858       expected_result = {
859         :optional_bool=>true,
860         :optional_bytes=>"",
861         :optional_double=>-10.100001,
862         :optional_enum=>:Default,
863         :optional_float=>0.0,
864         :optional_int32=>0,
865         :optional_int64=>0,
866         :optional_msg=>nil,
867         :optional_string=>"foo",
868         :optional_uint32=>0,
869         :optional_uint64=>0,
870         :repeated_bool=>[],
871         :repeated_bytes=>[],
872         :repeated_double=>[],
873         :repeated_enum=>[],
874         :repeated_float=>[],
875         :repeated_int32=>[],
876         :repeated_int64=>[],
877         :repeated_msg=>[],
878         :repeated_string=>["bar1", "bar2"],
879         :repeated_uint32=>[],
880         :repeated_uint64=>[]
881       }
882       assert_equal expected_result, m.to_h
883     end
886     def test_def_errors
887       s = Google::Protobuf::DescriptorPool.new
888       assert_raise TypeError do
889         s.build do
890           # enum with no default (integer value 0)
891           add_enum "MyEnum" do
892             value :A, 1
893           end
894         end
895       end
896       assert_raise TypeError do
897         s.build do
898           # message with required field (unsupported in proto3)
899           add_message "MyMessage" do
900             required :foo, :int32, 1
901           end
902         end
903       end
904     end
906     def test_corecursive
907       # just be sure that we can instantiate types with corecursive field-type
908       # references.
909       m = Recursive1.new(:foo => Recursive2.new(:foo => Recursive1.new))
910       assert Recursive1.descriptor.lookup("foo").subtype ==
911         Recursive2.descriptor
912       assert Recursive2.descriptor.lookup("foo").subtype ==
913         Recursive1.descriptor
915       serialized = Recursive1.encode(m)
916       m2 = Recursive1.decode(serialized)
917       assert m == m2
918     end
920     def test_serialize_cycle
921       m = Recursive1.new(:foo => Recursive2.new)
922       m.foo.foo = m
923       assert_raise RuntimeError do
924         serialized = Recursive1.encode(m)
925       end
926     end
928     def test_bad_field_names
929       m = BadFieldNames.new(:dup => 1, :class => 2)
930       m2 = m.dup
931       assert m == m2
932       assert m['dup'] == 1
933       assert m['class'] == 2
934       m['dup'] = 3
935       assert m['dup'] == 3
936       m['a.b'] = 4
937       assert m['a.b'] == 4
938     end
940     def test_int_ranges
941       m = TestMessage.new
943       m.optional_int32 = 0
944       m.optional_int32 = -0x8000_0000
945       m.optional_int32 = +0x7fff_ffff
946       m.optional_int32 = 1.0
947       m.optional_int32 = -1.0
948       m.optional_int32 = 2e9
949       assert_raise RangeError do
950         m.optional_int32 = -0x8000_0001
951       end
952       assert_raise RangeError do
953         m.optional_int32 = +0x8000_0000
954       end
955       assert_raise RangeError do
956         m.optional_int32 = +0x1000_0000_0000_0000_0000_0000 # force Bignum
957       end
958       assert_raise RangeError do
959         m.optional_int32 = 1e12
960       end
961       assert_raise RangeError do
962         m.optional_int32 = 1.5
963       end
965       m.optional_uint32 = 0
966       m.optional_uint32 = +0xffff_ffff
967       m.optional_uint32 = 1.0
968       m.optional_uint32 = 4e9
969       assert_raise RangeError do
970         m.optional_uint32 = -1
971       end
972       assert_raise RangeError do
973         m.optional_uint32 = -1.5
974       end
975       assert_raise RangeError do
976         m.optional_uint32 = -1.5e12
977       end
978       assert_raise RangeError do
979         m.optional_uint32 = -0x1000_0000_0000_0000
980       end
981       assert_raise RangeError do
982         m.optional_uint32 = +0x1_0000_0000
983       end
984       assert_raise RangeError do
985         m.optional_uint32 = +0x1000_0000_0000_0000_0000_0000 # force Bignum
986       end
987       assert_raise RangeError do
988         m.optional_uint32 = 1e12
989       end
990       assert_raise RangeError do
991         m.optional_uint32 = 1.5
992       end
994       m.optional_int64 = 0
995       m.optional_int64 = -0x8000_0000_0000_0000
996       m.optional_int64 = +0x7fff_ffff_ffff_ffff
997       m.optional_int64 = 1.0
998       m.optional_int64 = -1.0
999       m.optional_int64 = 8e18
1000       m.optional_int64 = -8e18
1001       assert_raise RangeError do
1002         m.optional_int64 = -0x8000_0000_0000_0001
1003       end
1004       assert_raise RangeError do
1005         m.optional_int64 = +0x8000_0000_0000_0000
1006       end
1007       assert_raise RangeError do
1008         m.optional_int64 = +0x1000_0000_0000_0000_0000_0000 # force Bignum
1009       end
1010       assert_raise RangeError do
1011         m.optional_int64 = 1e50
1012       end
1013       assert_raise RangeError do
1014         m.optional_int64 = 1.5
1015       end
1017       m.optional_uint64 = 0
1018       m.optional_uint64 = +0xffff_ffff_ffff_ffff
1019       m.optional_uint64 = 1.0
1020       m.optional_uint64 = 16e18
1021       assert_raise RangeError do
1022         m.optional_uint64 = -1
1023       end
1024       assert_raise RangeError do
1025         m.optional_uint64 = -1.5
1026       end
1027       assert_raise RangeError do
1028         m.optional_uint64 = -1.5e12
1029       end
1030       assert_raise RangeError do
1031         m.optional_uint64 = -0x1_0000_0000_0000_0000
1032       end
1033       assert_raise RangeError do
1034         m.optional_uint64 = +0x1_0000_0000_0000_0000
1035       end
1036       assert_raise RangeError do
1037         m.optional_uint64 = +0x1000_0000_0000_0000_0000_0000 # force Bignum
1038       end
1039       assert_raise RangeError do
1040         m.optional_uint64 = 1e50
1041       end
1042       assert_raise RangeError do
1043         m.optional_uint64 = 1.5
1044       end
1045     end
1047     def test_stress_test
1048       m = TestMessage.new
1049       m.optional_int32 = 42
1050       m.optional_int64 = 0x100000000
1051       m.optional_string = "hello world"
1052       10.times do m.repeated_msg.push TestMessage2.new(:foo => 42) end
1053       10.times do m.repeated_string.push "hello world" end
1055       data = TestMessage.encode(m)
1057       l = 0
1058       10_000.times do
1059         m = TestMessage.decode(data)
1060         data_new = TestMessage.encode(m)
1061         assert data_new == data
1062         data = data_new
1063       end
1064     end
1066     def test_reflection
1067       m = TestMessage.new(:optional_int32 => 1234)
1068       msgdef = m.class.descriptor
1069       assert msgdef.class == Google::Protobuf::Descriptor
1070       assert msgdef.any? {|field| field.name == "optional_int32"}
1071       optional_int32 = msgdef.lookup "optional_int32"
1072       assert optional_int32.class == Google::Protobuf::FieldDescriptor
1073       assert optional_int32 != nil
1074       assert optional_int32.name == "optional_int32"
1075       assert optional_int32.type == :int32
1076       optional_int32.set(m, 5678)
1077       assert m.optional_int32 == 5678
1078       m.optional_int32 = 1000
1079       assert optional_int32.get(m) == 1000
1081       optional_msg = msgdef.lookup "optional_msg"
1082       assert optional_msg.subtype == TestMessage2.descriptor
1084       optional_msg.set(m, optional_msg.subtype.msgclass.new)
1086       assert msgdef.msgclass == TestMessage
1088       optional_enum = msgdef.lookup "optional_enum"
1089       assert optional_enum.subtype == TestEnum.descriptor
1090       assert optional_enum.subtype.class == Google::Protobuf::EnumDescriptor
1091       optional_enum.subtype.each do |k, v|
1092         # set with integer, check resolution to symbolic name
1093         optional_enum.set(m, v)
1094         assert optional_enum.get(m) == k
1095       end
1096     end
1098     def test_json
1099       # TODO: Fix JSON in JRuby version.
1100       return if RUBY_PLATFORM == "java"
1101       m = TestMessage.new(:optional_int32 => 1234,
1102                           :optional_int64 => -0x1_0000_0000,
1103                           :optional_uint32 => 0x8000_0000,
1104                           :optional_uint64 => 0xffff_ffff_ffff_ffff,
1105                           :optional_bool => true,
1106                           :optional_float => 1.0,
1107                           :optional_double => -1e100,
1108                           :optional_string => "Test string",
1109                           :optional_bytes => ["FFFFFFFF"].pack('H*'),
1110                           :optional_msg => TestMessage2.new(:foo => 42),
1111                           :repeated_int32 => [1, 2, 3, 4],
1112                           :repeated_string => ["a", "b", "c"],
1113                           :repeated_bool => [true, false, true, false],
1114                           :repeated_msg => [TestMessage2.new(:foo => 1),
1115                                             TestMessage2.new(:foo => 2)])
1117       json_text = TestMessage.encode_json(m)
1118       m2 = TestMessage.decode_json(json_text)
1119       assert m == m2
1121       # Crash case from GitHub issue 283.
1122       bar = Bar.new(msg: "bar")
1123       baz1 = Baz.new(msg: "baz")
1124       baz2 = Baz.new(msg: "quux")
1125       Foo.encode_json(Foo.new)
1126       Foo.encode_json(Foo.new(bar: bar))
1127       Foo.encode_json(Foo.new(bar: bar, baz: [baz1, baz2]))
1128     end
1130     def test_json_maps
1131       # TODO: Fix JSON in JRuby version.
1132       return if RUBY_PLATFORM == "java"
1133       m = MapMessage.new(:map_string_int32 => {"a" => 1})
1134       expected = '{"map_string_int32":{"a":1},"map_string_msg":{}}'
1135       assert MapMessage.encode_json(m) == expected
1136       m2 = MapMessage.decode_json(MapMessage.encode_json(m))
1137       assert m == m2
1138     end
1139   end