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