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