• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/ruby
2
3require 'google/protobuf'
4require 'test/unit'
5
6# ------------- generated code --------------
7
8module 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
15
16    add_message "Bar" do
17      optional :msg, :string, 1
18    end
19
20    add_message "Baz" do
21      optional :msg, :string, 1
22    end
23
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"
36
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
52
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
59
60    add_enum "TestEnum" do
61      value :Default, 0
62      value :A, 1
63      value :B, 2
64      value :C, 3
65    end
66
67    add_message "BadFieldNames" do
68      optional :dup, :int32, 1
69      optional :class, :int32, 2
70      optional :"a.b", :int32, 3
71    end
72
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
89
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
99
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
116
117# ------------ test cases ---------------
118
119  class MessageContainerTest < Test::Unit::TestCase
120
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
135
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
160
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
174
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
183
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
193
194    def test_unknown_field_errors
195      e = assert_raise NoMethodError do
196        TestMessage.new.hello
197      end
198      assert_match(/hello/, e.message)
199
200      e = assert_raise NoMethodError do
201        TestMessage.new.hello = "world"
202      end
203      assert_match(/hello/, e.message)
204    end
205
206    def test_initialization_map_errors
207      e = assert_raise ArgumentError do
208        TestMessage.new(:hello => "world")
209      end
210      assert_match(/hello/, e.message)
211
212      e = assert_raise ArgumentError do
213        MapMessage.new(:map_string_int32 => "hello")
214      end
215      assert_equal e.message, "Expected Hash object as initializer value for map field 'map_string_int32'."
216
217      e = assert_raise ArgumentError do
218        TestMessage.new(:repeated_uint32 => "hello")
219      end
220      assert_equal e.message, "Expected array as initializer value for repeated field 'repeated_uint32'."
221    end
222
223    def test_type_errors
224      m = TestMessage.new
225      assert_raise TypeError do
226        m.optional_int32 = "hello"
227      end
228      assert_raise TypeError do
229        m.optional_string = 42
230      end
231      assert_raise TypeError do
232        m.optional_string = nil
233      end
234      assert_raise TypeError do
235        m.optional_bool = 42
236      end
237      assert_raise TypeError do
238        m.optional_msg = TestMessage.new  # expects TestMessage2
239      end
240
241      assert_raise TypeError do
242        m.repeated_int32 = []  # needs RepeatedField
243      end
244
245      assert_raise TypeError do
246        m.repeated_int32.push "hello"
247      end
248
249      assert_raise TypeError do
250        m.repeated_msg.push TestMessage.new
251      end
252    end
253
254    def test_string_encoding
255      m = TestMessage.new
256
257      # Assigning a normal (ASCII or UTF8) string to a bytes field, or
258      # ASCII-8BIT to a string field, raises an error.
259      assert_raise TypeError do
260        m.optional_bytes = "Test string ASCII".encode!('ASCII')
261      end
262      assert_raise TypeError do
263        m.optional_bytes = "Test string UTF-8 \u0100".encode!('UTF-8')
264      end
265      assert_raise TypeError do
266        m.optional_string = ["FFFF"].pack('H*')
267      end
268
269      # "Ordinary" use case.
270      m.optional_bytes = ["FFFF"].pack('H*')
271      m.optional_string = "\u0100"
272
273      # strings are mutable so we can do this, but serialize should catch it.
274      m.optional_string = "asdf".encode!('UTF-8')
275      m.optional_string.encode!('ASCII-8BIT')
276      assert_raise TypeError do
277        data = TestMessage.encode(m)
278      end
279    end
280
281    def test_rptfield_int32
282      l = Google::Protobuf::RepeatedField.new(:int32)
283      assert l.count == 0
284      l = Google::Protobuf::RepeatedField.new(:int32, [1, 2, 3])
285      assert l.count == 3
286      assert_equal [1, 2, 3], l
287      assert_equal l, [1, 2, 3]
288      l.push 4
289      assert l == [1, 2, 3, 4]
290      dst_list = []
291      l.each { |val| dst_list.push val }
292      assert dst_list == [1, 2, 3, 4]
293      assert l.to_a == [1, 2, 3, 4]
294      assert l[0] == 1
295      assert l[3] == 4
296      l[0] = 5
297      assert l == [5, 2, 3, 4]
298
299      l2 = l.dup
300      assert l == l2
301      assert l.object_id != l2.object_id
302      l2.push 6
303      assert l.count == 4
304      assert l2.count == 5
305
306      assert l.inspect == '[5, 2, 3, 4]'
307
308      l.concat([7, 8, 9])
309      assert l == [5, 2, 3, 4, 7, 8, 9]
310      assert l.pop == 9
311      assert l == [5, 2, 3, 4, 7, 8]
312
313      assert_raise TypeError do
314        m = TestMessage.new
315        l.push m
316      end
317
318      m = TestMessage.new
319      m.repeated_int32 = l
320      assert m.repeated_int32 == [5, 2, 3, 4, 7, 8]
321      assert m.repeated_int32.object_id == l.object_id
322      l.push 42
323      assert m.repeated_int32.pop == 42
324
325      l3 = l + l.dup
326      assert l3.count == l.count * 2
327      l.count.times do |i|
328        assert l3[i] == l[i]
329        assert l3[l.count + i] == l[i]
330      end
331
332      l.clear
333      assert l.count == 0
334      l += [1, 2, 3, 4]
335      l.replace([5, 6, 7, 8])
336      assert l == [5, 6, 7, 8]
337
338      l4 = Google::Protobuf::RepeatedField.new(:int32)
339      l4[5] = 42
340      assert l4 == [0, 0, 0, 0, 0, 42]
341
342      l4 << 100
343      assert l4 == [0, 0, 0, 0, 0, 42, 100]
344      l4 << 101 << 102
345      assert l4 == [0, 0, 0, 0, 0, 42, 100, 101, 102]
346    end
347
348    def test_parent_rptfield
349      #make sure we set the RepeatedField and can add to it
350      m = TestMessage.new
351      assert m.repeated_string == []
352      m.repeated_string << 'ok'
353      m.repeated_string.push('ok2')
354      assert m.repeated_string == ['ok', 'ok2']
355      m.repeated_string += ['ok3']
356      assert m.repeated_string == ['ok', 'ok2', 'ok3']
357    end
358
359    def test_rptfield_msg
360      l = Google::Protobuf::RepeatedField.new(:message, TestMessage)
361      l.push TestMessage.new
362      assert l.count == 1
363      assert_raise TypeError do
364        l.push TestMessage2.new
365      end
366      assert_raise TypeError do
367        l.push 42
368      end
369
370      l2 = l.dup
371      assert l2[0] == l[0]
372      assert l2[0].object_id == l[0].object_id
373
374      l2 = Google::Protobuf.deep_copy(l)
375      assert l2[0] == l[0]
376      assert l2[0].object_id != l[0].object_id
377
378      l3 = l + l2
379      assert l3.count == 2
380      assert l3[0] == l[0]
381      assert l3[1] == l2[0]
382      l3[0].optional_int32 = 1000
383      assert l[0].optional_int32 == 1000
384
385      new_msg = TestMessage.new(:optional_int32 => 200)
386      l4 = l + [new_msg]
387      assert l4.count == 2
388      new_msg.optional_int32 = 1000
389      assert l4[1].optional_int32 == 1000
390    end
391
392    def test_rptfield_enum
393      l = Google::Protobuf::RepeatedField.new(:enum, TestEnum)
394      l.push :A
395      l.push :B
396      l.push :C
397      assert l.count == 3
398      assert_raise RangeError do
399        l.push :D
400      end
401      assert l[0] == :A
402
403      l.push 4
404      assert l[3] == 4
405    end
406
407    def test_rptfield_initialize
408      assert_raise ArgumentError do
409        l = Google::Protobuf::RepeatedField.new
410      end
411      assert_raise ArgumentError do
412        l = Google::Protobuf::RepeatedField.new(:message)
413      end
414      assert_raise ArgumentError do
415        l = Google::Protobuf::RepeatedField.new([1, 2, 3])
416      end
417      assert_raise ArgumentError do
418        l = Google::Protobuf::RepeatedField.new(:message, [TestMessage2.new])
419      end
420    end
421
422    def test_rptfield_array_ducktyping
423      l = Google::Protobuf::RepeatedField.new(:int32)
424      length_methods = %w(count length size)
425      length_methods.each do |lm|
426        assert l.send(lm)  == 0
427      end
428      # out of bounds returns a nil
429      assert l[0] == nil
430      assert l[1] == nil
431      assert l[-1] == nil
432      l.push 4
433      length_methods.each do |lm|
434        assert l.send(lm) == 1
435      end
436      assert l[0] == 4
437      assert l[1] == nil
438      assert l[-1] == 4
439      assert l[-2] == nil
440
441      l.push 2
442      length_methods.each do |lm|
443        assert l.send(lm) == 2
444      end
445      assert l[0] == 4
446      assert l[1] == 2
447      assert l[2] == nil
448      assert l[-1] == 2
449      assert l[-2] == 4
450      assert l[-3] == nil
451
452      #adding out of scope will backfill with empty objects
453    end
454
455    def test_map_basic
456      # allowed key types:
457      # :int32, :int64, :uint32, :uint64, :bool, :string, :bytes.
458
459      m = Google::Protobuf::Map.new(:string, :int32)
460      m["asdf"] = 1
461      assert m["asdf"] == 1
462      m["jkl;"] = 42
463      assert m == { "jkl;" => 42, "asdf" => 1 }
464      assert m.has_key?("asdf")
465      assert !m.has_key?("qwerty")
466      assert m.length == 2
467
468      m2 = m.dup
469      assert m == m2
470      assert m.hash != 0
471      assert m.hash == m2.hash
472
473      collected = {}
474      m.each { |k,v| collected[v] = k }
475      assert collected == { 42 => "jkl;", 1 => "asdf" }
476
477      assert m.delete("asdf") == 1
478      assert !m.has_key?("asdf")
479      assert m["asdf"] == nil
480      assert !m.has_key?("asdf")
481
482      # We only assert on inspect value when there is one map entry because the
483      # order in which elements appear is unspecified (depends on the internal
484      # hash function). We don't want a brittle test.
485      assert m.inspect == "{\"jkl;\"=>42}"
486
487      assert m.keys == ["jkl;"]
488      assert m.values == [42]
489
490      m.clear
491      assert m.length == 0
492      assert m == {}
493
494      assert_raise TypeError do
495        m[1] = 1
496      end
497      assert_raise RangeError do
498        m["asdf"] = 0x1_0000_0000
499      end
500    end
501
502    def test_map_ctor
503      m = Google::Protobuf::Map.new(:string, :int32,
504                                    {"a" => 1, "b" => 2, "c" => 3})
505      assert m == {"a" => 1, "c" => 3, "b" => 2}
506    end
507
508    def test_map_keytypes
509      m = Google::Protobuf::Map.new(:int32, :int32)
510      m[1] = 42
511      m[-1] = 42
512      assert_raise RangeError do
513        m[0x8000_0000] = 1
514      end
515      assert_raise TypeError do
516        m["asdf"] = 1
517      end
518
519      m = Google::Protobuf::Map.new(:int64, :int32)
520      m[0x1000_0000_0000_0000] = 1
521      assert_raise RangeError do
522        m[0x1_0000_0000_0000_0000] = 1
523      end
524      assert_raise TypeError do
525        m["asdf"] = 1
526      end
527
528      m = Google::Protobuf::Map.new(:uint32, :int32)
529      m[0x8000_0000] = 1
530      assert_raise RangeError do
531        m[0x1_0000_0000] = 1
532      end
533      assert_raise RangeError do
534        m[-1] = 1
535      end
536
537      m = Google::Protobuf::Map.new(:uint64, :int32)
538      m[0x8000_0000_0000_0000] = 1
539      assert_raise RangeError do
540        m[0x1_0000_0000_0000_0000] = 1
541      end
542      assert_raise RangeError do
543        m[-1] = 1
544      end
545
546      m = Google::Protobuf::Map.new(:bool, :int32)
547      m[true] = 1
548      m[false] = 2
549      assert_raise TypeError do
550        m[1] = 1
551      end
552      assert_raise TypeError do
553        m["asdf"] = 1
554      end
555
556      m = Google::Protobuf::Map.new(:string, :int32)
557      m["asdf"] = 1
558      assert_raise TypeError do
559        m[1] = 1
560      end
561      assert_raise TypeError do
562        bytestring = ["FFFF"].pack("H*")
563        m[bytestring] = 1
564      end
565
566      m = Google::Protobuf::Map.new(:bytes, :int32)
567      bytestring = ["FFFF"].pack("H*")
568      m[bytestring] = 1
569      assert_raise TypeError do
570        m["asdf"] = 1
571      end
572      assert_raise TypeError do
573        m[1] = 1
574      end
575    end
576
577    def test_map_msg_enum_valuetypes
578      m = Google::Protobuf::Map.new(:string, :message, TestMessage)
579      m["asdf"] = TestMessage.new
580      assert_raise TypeError do
581        m["jkl;"] = TestMessage2.new
582      end
583
584      m = Google::Protobuf::Map.new(
585        :string, :message, TestMessage,
586        { "a" => TestMessage.new(:optional_int32 => 42),
587          "b" => TestMessage.new(:optional_int32 => 84) })
588      assert m.length == 2
589      assert m.values.map{|msg| msg.optional_int32}.sort == [42, 84]
590
591      m = Google::Protobuf::Map.new(:string, :enum, TestEnum,
592                                    { "x" => :A, "y" => :B, "z" => :C })
593      assert m.length == 3
594      assert m["z"] == :C
595      m["z"] = 2
596      assert m["z"] == :B
597      m["z"] = 4
598      assert m["z"] == 4
599      assert_raise RangeError do
600        m["z"] = :Z
601      end
602      assert_raise TypeError do
603        m["z"] = "z"
604      end
605    end
606
607    def test_map_dup_deep_copy
608      m = Google::Protobuf::Map.new(
609        :string, :message, TestMessage,
610        { "a" => TestMessage.new(:optional_int32 => 42),
611          "b" => TestMessage.new(:optional_int32 => 84) })
612
613      m2 = m.dup
614      assert m == m2
615      assert m.object_id != m2.object_id
616      assert m["a"].object_id == m2["a"].object_id
617      assert m["b"].object_id == m2["b"].object_id
618
619      m2 = Google::Protobuf.deep_copy(m)
620      assert m == m2
621      assert m.object_id != m2.object_id
622      assert m["a"].object_id != m2["a"].object_id
623      assert m["b"].object_id != m2["b"].object_id
624    end
625
626    def test_map_field
627      m = MapMessage.new
628      assert m.map_string_int32 == {}
629      assert m.map_string_msg == {}
630
631      m = MapMessage.new(
632        :map_string_int32 => {"a" => 1, "b" => 2},
633        :map_string_msg => {"a" => TestMessage2.new(:foo => 1),
634                            "b" => TestMessage2.new(:foo => 2)})
635      assert m.map_string_int32.keys.sort == ["a", "b"]
636      assert m.map_string_int32["a"] == 1
637      assert m.map_string_msg["b"].foo == 2
638
639      m.map_string_int32["c"] = 3
640      assert m.map_string_int32["c"] == 3
641      m.map_string_msg["c"] = TestMessage2.new(:foo => 3)
642      assert m.map_string_msg["c"] == TestMessage2.new(:foo => 3)
643      m.map_string_msg.delete("b")
644      m.map_string_msg.delete("c")
645      assert m.map_string_msg == { "a" => TestMessage2.new(:foo => 1) }
646
647      assert_raise TypeError do
648        m.map_string_msg["e"] = TestMessage.new # wrong value type
649      end
650      # ensure nothing was added by the above
651      assert m.map_string_msg == { "a" => TestMessage2.new(:foo => 1) }
652
653      m.map_string_int32 = Google::Protobuf::Map.new(:string, :int32)
654      assert_raise TypeError do
655        m.map_string_int32 = Google::Protobuf::Map.new(:string, :int64)
656      end
657      assert_raise TypeError do
658        m.map_string_int32 = {}
659      end
660
661      assert_raise TypeError do
662        m = MapMessage.new(:map_string_int32 => { 1 => "I am not a number" })
663      end
664    end
665
666    def test_map_encode_decode
667      m = MapMessage.new(
668        :map_string_int32 => {"a" => 1, "b" => 2},
669        :map_string_msg => {"a" => TestMessage2.new(:foo => 1),
670                            "b" => TestMessage2.new(:foo => 2)})
671      m2 = MapMessage.decode(MapMessage.encode(m))
672      assert m == m2
673
674      m3 = MapMessageWireEquiv.decode(MapMessage.encode(m))
675      assert m3.map_string_int32.length == 2
676
677      kv = {}
678      m3.map_string_int32.map { |msg| kv[msg.key] = msg.value }
679      assert kv == {"a" => 1, "b" => 2}
680
681      kv = {}
682      m3.map_string_msg.map { |msg| kv[msg.key] = msg.value }
683      assert kv == {"a" => TestMessage2.new(:foo => 1),
684                    "b" => TestMessage2.new(:foo => 2)}
685    end
686
687    def test_oneof_descriptors
688      d = OneofMessage.descriptor
689      o = d.lookup_oneof("my_oneof")
690      assert o != nil
691      assert o.class == Google::Protobuf::OneofDescriptor
692      assert o.name == "my_oneof"
693      oneof_count = 0
694      d.each_oneof{ |oneof|
695        oneof_count += 1
696        assert oneof == o
697      }
698      assert oneof_count == 1
699      assert o.count == 4
700      field_names = o.map{|f| f.name}.sort
701      assert field_names == ["a", "b", "c", "d"]
702    end
703
704    def test_oneof
705      d = OneofMessage.new
706      assert d.a == nil
707      assert d.b == nil
708      assert d.c == nil
709      assert d.d == nil
710      assert d.my_oneof == nil
711
712      d.a = "hi"
713      assert d.a == "hi"
714      assert d.b == nil
715      assert d.c == nil
716      assert d.d == nil
717      assert d.my_oneof == :a
718
719      d.b = 42
720      assert d.a == nil
721      assert d.b == 42
722      assert d.c == nil
723      assert d.d == nil
724      assert d.my_oneof == :b
725
726      d.c = TestMessage2.new(:foo => 100)
727      assert d.a == nil
728      assert d.b == nil
729      assert d.c.foo == 100
730      assert d.d == nil
731      assert d.my_oneof == :c
732
733      d.d = :C
734      assert d.a == nil
735      assert d.b == nil
736      assert d.c == nil
737      assert d.d == :C
738      assert d.my_oneof == :d
739
740      d2 = OneofMessage.decode(OneofMessage.encode(d))
741      assert d2 == d
742
743      encoded_field_a = OneofMessage.encode(OneofMessage.new(:a => "string"))
744      encoded_field_b = OneofMessage.encode(OneofMessage.new(:b => 1000))
745      encoded_field_c = OneofMessage.encode(
746        OneofMessage.new(:c => TestMessage2.new(:foo => 1)))
747      encoded_field_d = OneofMessage.encode(OneofMessage.new(:d => :B))
748
749      d3 = OneofMessage.decode(
750        encoded_field_c + encoded_field_a + encoded_field_d)
751      assert d3.a == nil
752      assert d3.b == nil
753      assert d3.c == nil
754      assert d3.d == :B
755
756      d4 = OneofMessage.decode(
757        encoded_field_c + encoded_field_a + encoded_field_d +
758        encoded_field_c)
759      assert d4.a == nil
760      assert d4.b == nil
761      assert d4.c.foo == 1
762      assert d4.d == nil
763
764      d5 = OneofMessage.new(:a => "hello")
765      assert d5.a != nil
766      d5.a = nil
767      assert d5.a == nil
768      assert OneofMessage.encode(d5) == ''
769      assert d5.my_oneof == nil
770    end
771
772    def test_enum_field
773      m = TestMessage.new
774      assert m.optional_enum == :Default
775      m.optional_enum = :A
776      assert m.optional_enum == :A
777      assert_raise RangeError do
778        m.optional_enum = :ASDF
779      end
780      m.optional_enum = 1
781      assert m.optional_enum == :A
782      m.optional_enum = 100
783      assert m.optional_enum == 100
784    end
785
786    def test_dup
787      m = TestMessage.new
788      m.optional_string = "hello"
789      m.optional_int32 = 42
790      tm1 = TestMessage2.new(:foo => 100)
791      tm2 = TestMessage2.new(:foo => 200)
792      m.repeated_msg.push tm1
793      assert m.repeated_msg[-1] == tm1
794      m.repeated_msg.push tm2
795      assert m.repeated_msg[-1] == tm2
796      m2 = m.dup
797      assert m == m2
798      m.optional_int32 += 1
799      assert m != m2
800      assert m.repeated_msg[0] == m2.repeated_msg[0]
801      assert m.repeated_msg[0].object_id == m2.repeated_msg[0].object_id
802    end
803
804    def test_deep_copy
805      m = TestMessage.new(:optional_int32 => 42,
806                          :repeated_msg => [TestMessage2.new(:foo => 100)])
807      m2 = Google::Protobuf.deep_copy(m)
808      assert m == m2
809      assert m.repeated_msg == m2.repeated_msg
810      assert m.repeated_msg.object_id != m2.repeated_msg.object_id
811      assert m.repeated_msg[0].object_id != m2.repeated_msg[0].object_id
812    end
813
814    def test_eq
815      m = TestMessage.new(:optional_int32 => 42,
816                          :repeated_int32 => [1, 2, 3])
817      m2 = TestMessage.new(:optional_int32 => 43,
818                           :repeated_int32 => [1, 2, 3])
819      assert m != m2
820    end
821
822    def test_enum_lookup
823      assert TestEnum::A == 1
824      assert TestEnum::B == 2
825      assert TestEnum::C == 3
826
827      assert TestEnum::lookup(1) == :A
828      assert TestEnum::lookup(2) == :B
829      assert TestEnum::lookup(3) == :C
830
831      assert TestEnum::resolve(:A) == 1
832      assert TestEnum::resolve(:B) == 2
833      assert TestEnum::resolve(:C) == 3
834    end
835
836    def test_parse_serialize
837      m = TestMessage.new(:optional_int32 => 42,
838                          :optional_string => "hello world",
839                          :optional_enum => :B,
840                          :repeated_string => ["a", "b", "c"],
841                          :repeated_int32 => [42, 43, 44],
842                          :repeated_enum => [:A, :B, :C, 100],
843                          :repeated_msg => [TestMessage2.new(:foo => 1),
844                                            TestMessage2.new(:foo => 2)])
845      data = TestMessage.encode m
846      m2 = TestMessage.decode data
847      assert m == m2
848
849      data = Google::Protobuf.encode m
850      m2 = Google::Protobuf.decode(TestMessage, data)
851      assert m == m2
852    end
853
854    def test_encode_decode_helpers
855      m = TestMessage.new(:optional_string => 'foo', :repeated_string => ['bar1', 'bar2'])
856      json = m.to_json
857      m2 = TestMessage.decode_json(json)
858      assert m2.optional_string == 'foo'
859      assert m2.repeated_string == ['bar1', 'bar2']
860
861      proto = m.to_proto
862      m2 = TestMessage.decode(proto)
863      assert m2.optional_string == 'foo'
864      assert m2.repeated_string == ['bar1', 'bar2']
865    end
866
867    def test_protobuf_encode_decode_helpers
868      m = TestMessage.new(:optional_string => 'foo', :repeated_string => ['bar1', 'bar2'])
869      encoded_msg = Google::Protobuf.encode(m)
870      assert_equal m.to_proto, encoded_msg
871
872      decoded_msg = Google::Protobuf.decode(TestMessage, encoded_msg)
873      assert_equal TestMessage.decode(m.to_proto), decoded_msg
874    end
875
876    def test_protobuf_encode_decode_json_helpers
877      m = TestMessage.new(:optional_string => 'foo', :repeated_string => ['bar1', 'bar2'])
878      encoded_msg = Google::Protobuf.encode_json(m)
879      assert_equal m.to_json, encoded_msg
880
881      decoded_msg = Google::Protobuf.decode_json(TestMessage, encoded_msg)
882      assert_equal TestMessage.decode_json(m.to_json), decoded_msg
883    end
884
885    def test_to_h
886      m = TestMessage.new(:optional_bool => true, :optional_double => -10.100001, :optional_string => 'foo', :repeated_string => ['bar1', 'bar2'])
887      expected_result = {
888        :optional_bool=>true,
889        :optional_bytes=>"",
890        :optional_double=>-10.100001,
891        :optional_enum=>:Default,
892        :optional_float=>0.0,
893        :optional_int32=>0,
894        :optional_int64=>0,
895        :optional_msg=>nil,
896        :optional_string=>"foo",
897        :optional_uint32=>0,
898        :optional_uint64=>0,
899        :repeated_bool=>[],
900        :repeated_bytes=>[],
901        :repeated_double=>[],
902        :repeated_enum=>[],
903        :repeated_float=>[],
904        :repeated_int32=>[],
905        :repeated_int64=>[],
906        :repeated_msg=>[],
907        :repeated_string=>["bar1", "bar2"],
908        :repeated_uint32=>[],
909        :repeated_uint64=>[]
910      }
911      assert_equal expected_result, m.to_h
912    end
913
914
915    def test_def_errors
916      s = Google::Protobuf::DescriptorPool.new
917      assert_raise TypeError do
918        s.build do
919          # enum with no default (integer value 0)
920          add_enum "MyEnum" do
921            value :A, 1
922          end
923        end
924      end
925      assert_raise TypeError do
926        s.build do
927          # message with required field (unsupported in proto3)
928          add_message "MyMessage" do
929            required :foo, :int32, 1
930          end
931        end
932      end
933    end
934
935    def test_corecursive
936      # just be sure that we can instantiate types with corecursive field-type
937      # references.
938      m = Recursive1.new(:foo => Recursive2.new(:foo => Recursive1.new))
939      assert Recursive1.descriptor.lookup("foo").subtype ==
940        Recursive2.descriptor
941      assert Recursive2.descriptor.lookup("foo").subtype ==
942        Recursive1.descriptor
943
944      serialized = Recursive1.encode(m)
945      m2 = Recursive1.decode(serialized)
946      assert m == m2
947    end
948
949    def test_serialize_cycle
950      m = Recursive1.new(:foo => Recursive2.new)
951      m.foo.foo = m
952      assert_raise RuntimeError do
953        serialized = Recursive1.encode(m)
954      end
955    end
956
957    def test_bad_field_names
958      m = BadFieldNames.new(:dup => 1, :class => 2)
959      m2 = m.dup
960      assert m == m2
961      assert m['dup'] == 1
962      assert m['class'] == 2
963      m['dup'] = 3
964      assert m['dup'] == 3
965      m['a.b'] = 4
966      assert m['a.b'] == 4
967    end
968
969    def test_int_ranges
970      m = TestMessage.new
971
972      m.optional_int32 = 0
973      m.optional_int32 = -0x8000_0000
974      m.optional_int32 = +0x7fff_ffff
975      m.optional_int32 = 1.0
976      m.optional_int32 = -1.0
977      m.optional_int32 = 2e9
978      assert_raise RangeError do
979        m.optional_int32 = -0x8000_0001
980      end
981      assert_raise RangeError do
982        m.optional_int32 = +0x8000_0000
983      end
984      assert_raise RangeError do
985        m.optional_int32 = +0x1000_0000_0000_0000_0000_0000 # force Bignum
986      end
987      assert_raise RangeError do
988        m.optional_int32 = 1e12
989      end
990      assert_raise RangeError do
991        m.optional_int32 = 1.5
992      end
993
994      m.optional_uint32 = 0
995      m.optional_uint32 = +0xffff_ffff
996      m.optional_uint32 = 1.0
997      m.optional_uint32 = 4e9
998      assert_raise RangeError do
999        m.optional_uint32 = -1
1000      end
1001      assert_raise RangeError do
1002        m.optional_uint32 = -1.5
1003      end
1004      assert_raise RangeError do
1005        m.optional_uint32 = -1.5e12
1006      end
1007      assert_raise RangeError do
1008        m.optional_uint32 = -0x1000_0000_0000_0000
1009      end
1010      assert_raise RangeError do
1011        m.optional_uint32 = +0x1_0000_0000
1012      end
1013      assert_raise RangeError do
1014        m.optional_uint32 = +0x1000_0000_0000_0000_0000_0000 # force Bignum
1015      end
1016      assert_raise RangeError do
1017        m.optional_uint32 = 1e12
1018      end
1019      assert_raise RangeError do
1020        m.optional_uint32 = 1.5
1021      end
1022
1023      m.optional_int64 = 0
1024      m.optional_int64 = -0x8000_0000_0000_0000
1025      m.optional_int64 = +0x7fff_ffff_ffff_ffff
1026      m.optional_int64 = 1.0
1027      m.optional_int64 = -1.0
1028      m.optional_int64 = 8e18
1029      m.optional_int64 = -8e18
1030      assert_raise RangeError do
1031        m.optional_int64 = -0x8000_0000_0000_0001
1032      end
1033      assert_raise RangeError do
1034        m.optional_int64 = +0x8000_0000_0000_0000
1035      end
1036      assert_raise RangeError do
1037        m.optional_int64 = +0x1000_0000_0000_0000_0000_0000 # force Bignum
1038      end
1039      assert_raise RangeError do
1040        m.optional_int64 = 1e50
1041      end
1042      assert_raise RangeError do
1043        m.optional_int64 = 1.5
1044      end
1045
1046      m.optional_uint64 = 0
1047      m.optional_uint64 = +0xffff_ffff_ffff_ffff
1048      m.optional_uint64 = 1.0
1049      m.optional_uint64 = 16e18
1050      assert_raise RangeError do
1051        m.optional_uint64 = -1
1052      end
1053      assert_raise RangeError do
1054        m.optional_uint64 = -1.5
1055      end
1056      assert_raise RangeError do
1057        m.optional_uint64 = -1.5e12
1058      end
1059      assert_raise RangeError do
1060        m.optional_uint64 = -0x1_0000_0000_0000_0000
1061      end
1062      assert_raise RangeError do
1063        m.optional_uint64 = +0x1_0000_0000_0000_0000
1064      end
1065      assert_raise RangeError do
1066        m.optional_uint64 = +0x1000_0000_0000_0000_0000_0000 # force Bignum
1067      end
1068      assert_raise RangeError do
1069        m.optional_uint64 = 1e50
1070      end
1071      assert_raise RangeError do
1072        m.optional_uint64 = 1.5
1073      end
1074    end
1075
1076    def test_stress_test
1077      m = TestMessage.new
1078      m.optional_int32 = 42
1079      m.optional_int64 = 0x100000000
1080      m.optional_string = "hello world"
1081      10.times do m.repeated_msg.push TestMessage2.new(:foo => 42) end
1082      10.times do m.repeated_string.push "hello world" end
1083
1084      data = TestMessage.encode(m)
1085
1086      l = 0
1087      10_000.times do
1088        m = TestMessage.decode(data)
1089        data_new = TestMessage.encode(m)
1090        assert data_new == data
1091        data = data_new
1092      end
1093    end
1094
1095    def test_reflection
1096      m = TestMessage.new(:optional_int32 => 1234)
1097      msgdef = m.class.descriptor
1098      assert msgdef.class == Google::Protobuf::Descriptor
1099      assert msgdef.any? {|field| field.name == "optional_int32"}
1100      optional_int32 = msgdef.lookup "optional_int32"
1101      assert optional_int32.class == Google::Protobuf::FieldDescriptor
1102      assert optional_int32 != nil
1103      assert optional_int32.name == "optional_int32"
1104      assert optional_int32.type == :int32
1105      optional_int32.set(m, 5678)
1106      assert m.optional_int32 == 5678
1107      m.optional_int32 = 1000
1108      assert optional_int32.get(m) == 1000
1109
1110      optional_msg = msgdef.lookup "optional_msg"
1111      assert optional_msg.subtype == TestMessage2.descriptor
1112
1113      optional_msg.set(m, optional_msg.subtype.msgclass.new)
1114
1115      assert msgdef.msgclass == TestMessage
1116
1117      optional_enum = msgdef.lookup "optional_enum"
1118      assert optional_enum.subtype == TestEnum.descriptor
1119      assert optional_enum.subtype.class == Google::Protobuf::EnumDescriptor
1120      optional_enum.subtype.each do |k, v|
1121        # set with integer, check resolution to symbolic name
1122        optional_enum.set(m, v)
1123        assert optional_enum.get(m) == k
1124      end
1125    end
1126
1127    def test_json
1128      # TODO: Fix JSON in JRuby version.
1129      return if RUBY_PLATFORM == "java"
1130      m = TestMessage.new(:optional_int32 => 1234,
1131                          :optional_int64 => -0x1_0000_0000,
1132                          :optional_uint32 => 0x8000_0000,
1133                          :optional_uint64 => 0xffff_ffff_ffff_ffff,
1134                          :optional_bool => true,
1135                          :optional_float => 1.0,
1136                          :optional_double => -1e100,
1137                          :optional_string => "Test string",
1138                          :optional_bytes => ["FFFFFFFF"].pack('H*'),
1139                          :optional_msg => TestMessage2.new(:foo => 42),
1140                          :repeated_int32 => [1, 2, 3, 4],
1141                          :repeated_string => ["a", "b", "c"],
1142                          :repeated_bool => [true, false, true, false],
1143                          :repeated_msg => [TestMessage2.new(:foo => 1),
1144                                            TestMessage2.new(:foo => 2)])
1145
1146      json_text = TestMessage.encode_json(m)
1147      m2 = TestMessage.decode_json(json_text)
1148      assert m == m2
1149
1150      # Crash case from GitHub issue 283.
1151      bar = Bar.new(msg: "bar")
1152      baz1 = Baz.new(msg: "baz")
1153      baz2 = Baz.new(msg: "quux")
1154      Foo.encode_json(Foo.new)
1155      Foo.encode_json(Foo.new(bar: bar))
1156      Foo.encode_json(Foo.new(bar: bar, baz: [baz1, baz2]))
1157    end
1158
1159    def test_json_maps
1160      # TODO: Fix JSON in JRuby version.
1161      return if RUBY_PLATFORM == "java"
1162      m = MapMessage.new(:map_string_int32 => {"a" => 1})
1163      expected = '{"mapStringInt32":{"a":1},"mapStringMsg":{}}'
1164      expected_preserve = '{"map_string_int32":{"a":1},"map_string_msg":{}}'
1165      assert MapMessage.encode_json(m) == expected
1166
1167      json = MapMessage.encode_json(m, :preserve_proto_fieldnames => true)
1168      assert json == expected_preserve
1169
1170      m2 = MapMessage.decode_json(MapMessage.encode_json(m))
1171      assert m == m2
1172    end
1173  end
1174end
1175