1#!/usr/bin/ruby 2 3# basic_test_pb.rb is in the same directory as this test. 4$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) 5 6require 'basic_test_proto2_pb' 7require 'common_tests' 8require 'google/protobuf' 9require 'google/protobuf/descriptor_pb' 10require 'json' 11require 'test/unit' 12 13module BasicTestProto2 14 class MessageContainerTest < Test::Unit::TestCase 15 # Required by CommonTests module to resolve proto2 proto classes used in tests. 16 def proto_module 17 ::BasicTestProto2 18 end 19 include CommonTests 20 21 def test_has_field 22 m = TestMessage.new 23 refute m.has_optional_int32? 24 refute TestMessage.descriptor.lookup('optional_int32').has?(m) 25 refute m.has_optional_int64? 26 refute TestMessage.descriptor.lookup('optional_int64').has?(m) 27 refute m.has_optional_uint32? 28 refute TestMessage.descriptor.lookup('optional_uint32').has?(m) 29 refute m.has_optional_uint64? 30 refute TestMessage.descriptor.lookup('optional_uint64').has?(m) 31 refute m.has_optional_bool? 32 refute TestMessage.descriptor.lookup('optional_bool').has?(m) 33 refute m.has_optional_float? 34 refute TestMessage.descriptor.lookup('optional_float').has?(m) 35 refute m.has_optional_double? 36 refute TestMessage.descriptor.lookup('optional_double').has?(m) 37 refute m.has_optional_string? 38 refute TestMessage.descriptor.lookup('optional_string').has?(m) 39 refute m.has_optional_bytes? 40 refute TestMessage.descriptor.lookup('optional_bytes').has?(m) 41 refute m.has_optional_enum? 42 refute TestMessage.descriptor.lookup('optional_enum').has?(m) 43 44 m = TestMessage.new(:optional_int32 => nil) 45 refute m.has_optional_int32? 46 47 assert_raises NoMethodError do 48 m.has_repeated_msg? 49 end 50 assert_raises ArgumentError do 51 TestMessage.descriptor.lookup('repeated_msg').has?(m) 52 end 53 54 m.optional_msg = TestMessage2.new 55 assert m.has_optional_msg? 56 assert TestMessage.descriptor.lookup('optional_msg').has?(m) 57 58 m = OneofMessage.new 59 refute m.has_my_oneof? 60 m.a = "foo" 61 assert m.has_my_oneof? 62 assert_equal :a, m.my_oneof 63 assert m.has_a? 64 assert OneofMessage.descriptor.lookup('a').has?(m) 65 assert_equal "foo", m.a 66 refute m.has_b? 67 refute OneofMessage.descriptor.lookup('b').has?(m) 68 refute m.has_c? 69 refute OneofMessage.descriptor.lookup('c').has?(m) 70 refute m.has_d? 71 refute OneofMessage.descriptor.lookup('d').has?(m) 72 73 m = OneofMessage.new 74 m.b = 100 75 assert m.has_b? 76 assert_equal 100, m.b 77 assert m.has_my_oneof? 78 refute m.has_a? 79 refute m.has_c? 80 refute m.has_d? 81 82 m = OneofMessage.new 83 m.c = TestMessage2.new 84 assert m.has_c? 85 assert_equal TestMessage2.new, m.c 86 assert m.has_my_oneof? 87 refute m.has_a? 88 refute m.has_b? 89 refute m.has_d? 90 91 m = OneofMessage.new 92 m.d = :A 93 assert m.has_d? 94 assert_equal :A, m.d 95 assert m.has_my_oneof? 96 refute m.has_a? 97 refute m.has_b? 98 refute m.has_c? 99 end 100 101 def test_defined_defaults 102 m = TestMessageDefaults.new 103 assert_equal 1, m.optional_int32 104 assert_equal 2, m.optional_int64 105 assert_equal 3, m.optional_uint32 106 assert_equal 4, m.optional_uint64 107 assert m.optional_bool 108 assert_equal 6.0, m.optional_float 109 assert_equal 7.0, m.optional_double 110 assert_equal "Default Str", m.optional_string 111 assert_equal "\xCF\xA5s\xBD\xBA\xE6fubar".force_encoding("ASCII-8BIT"), m.optional_bytes 112 assert_equal :B2, m.optional_enum 113 114 refute m.has_optional_int32? 115 refute m.has_optional_int64? 116 refute m.has_optional_uint32? 117 refute m.has_optional_uint64? 118 refute m.has_optional_bool? 119 refute m.has_optional_float? 120 refute m.has_optional_double? 121 refute m.has_optional_string? 122 refute m.has_optional_bytes? 123 refute m.has_optional_enum? 124 end 125 126 def test_set_clear_defaults 127 m = TestMessageDefaults.new 128 129 m.optional_int32 = -42 130 assert_equal( -42, m.optional_int32 ) 131 assert m.has_optional_int32? 132 m.clear_optional_int32 133 assert_equal 1, m.optional_int32 134 refute m.has_optional_int32? 135 136 m.optional_string = "foo bar" 137 assert_equal "foo bar", m.optional_string 138 assert m.has_optional_string? 139 m.clear_optional_string 140 assert_equal "Default Str", m.optional_string 141 refute m.has_optional_string? 142 143 m.optional_msg = TestMessage2.new(:foo => 42) 144 assert_equal TestMessage2.new(:foo => 42), m.optional_msg 145 assert m.has_optional_msg? 146 147 m.clear_optional_msg 148 assert_nil m.optional_msg 149 refute m.has_optional_msg? 150 151 m.optional_msg = TestMessage2.new(:foo => 42) 152 assert_equal TestMessage2.new(:foo => 42), m.optional_msg 153 assert TestMessageDefaults.descriptor.lookup('optional_msg').has?(m) 154 155 TestMessageDefaults.descriptor.lookup('optional_msg').clear(m) 156 assert_nil m.optional_msg 157 refute TestMessageDefaults.descriptor.lookup('optional_msg').has?(m) 158 159 m = TestMessage.new 160 m.repeated_int32.push(1) 161 assert_equal [1], m.repeated_int32 162 m.clear_repeated_int32 163 assert_empty m.repeated_int32 164 m = OneofMessage.new 165 m.a = "foo" 166 assert_equal "foo", m.a 167 assert m.has_a? 168 m.clear_a 169 refute m.has_a? 170 171 m = OneofMessage.new 172 m.a = "foobar" 173 assert m.has_my_oneof? 174 m.clear_my_oneof 175 refute m.has_my_oneof? 176 177 m = OneofMessage.new 178 m.a = "bar" 179 assert_equal "bar", m.a 180 assert m.has_my_oneof? 181 OneofMessage.descriptor.lookup('a').clear(m) 182 refute m.has_my_oneof? 183 end 184 185 def test_assign_nil 186 m = TestMessageDefaults.new 187 m.optional_msg = TestMessage2.new(:foo => 42) 188 189 assert_equal TestMessage2.new(:foo => 42), m.optional_msg 190 assert m.has_optional_msg? 191 m.optional_msg = nil 192 assert_nil m.optional_msg 193 refute m.has_optional_msg? 194 end 195 196 def test_initialization_map_errors 197 e = assert_raises ArgumentError do 198 TestMessage.new(:hello => "world") 199 end 200 assert_match(/hello/, e.message) 201 202 e = assert_raises ArgumentError do 203 TestMessage.new(:repeated_uint32 => "hello") 204 end 205 assert_equal "Expected array as initializer value for repeated field 'repeated_uint32' (given String).", e.message 206 end 207 208 209 def test_to_h 210 m = TestMessage.new(:optional_bool => true, :optional_double => -10.100001, :optional_string => 'foo', :repeated_string => ['bar1', 'bar2']) 211 expected_result = { 212 :optional_bool=>true, 213 :optional_double=>-10.100001, 214 :optional_string=>"foo", 215 :repeated_string=>["bar1", "bar2"], 216 } 217 assert_equal expected_result, m.to_h 218 219 m = OneofMessage.new(:a => "foo") 220 expected_result = {:a => "foo"} 221 assert_equal expected_result, m.to_h 222 end 223 224 def test_respond_to 225 # This test fails with JRuby 1.7.23, likely because of an old JRuby bug. 226 return if RUBY_PLATFORM == "java" 227 msg = TestMessage.new 228 refute_respond_to msg, :bacon 229 end 230 231 def test_file_descriptor 232 file_descriptor = TestMessage.descriptor.file_descriptor 233 refute_nil file_descriptor 234 assert_equal "basic_test_proto2.proto", file_descriptor.name 235 236 file_descriptor = TestEnum.descriptor.file_descriptor 237 refute_nil file_descriptor 238 assert_equal "basic_test_proto2.proto", file_descriptor.name 239 end 240 241 def test_oneof_fields_respond_to? # regression test for issue 9202 242 msg = proto_module::OneofMessage.new(a: "foo") 243 # `has_` prefix + "?" suffix actions should only work for oneofs fields. 244 assert msg.respond_to? :has_my_oneof? 245 assert msg.has_my_oneof? 246 assert msg.respond_to? :has_a? 247 assert msg.has_a? 248 assert msg.respond_to? :has_b? 249 refute msg.has_b? 250 assert msg.respond_to? :has_c? 251 refute msg.has_c? 252 assert msg.respond_to? :has_d? 253 refute msg.has_d? 254 end 255 256 def test_is_packed 257 assert_false TestMessage.descriptor.lookup("optional_int32").is_packed? 258 assert_false TestMessage.descriptor.lookup("repeated_int32").is_packed? 259 end 260 261 def test_extension 262 message = TestExtensions.new 263 extension = Google::Protobuf::DescriptorPool.generated_pool.lookup 'basic_test_proto2.optional_int32_extension' 264 assert_instance_of Google::Protobuf::FieldDescriptor, extension 265 assert_equal 0, extension.get(message) 266 extension.set message, 42 267 assert_equal 42, extension.get(message) 268 end 269 270 def test_extension_json 271 omit "Java Protobuf JsonFormat does not handle Proto2 extensions" if defined? JRUBY_VERSION and :NATIVE == Google::Protobuf::IMPLEMENTATION 272 message = TestExtensions.decode_json '{"[basic_test_proto2.optional_int32_extension]": 123}' 273 extension = Google::Protobuf::DescriptorPool.generated_pool.lookup 'basic_test_proto2.optional_int32_extension' 274 assert_instance_of Google::Protobuf::FieldDescriptor, extension 275 assert_equal 123, extension.get(message) 276 end 277 278 def test_extension_json_separate_pool 279 omit "Java Protobuf JsonFormat does not handle Proto2 extensions" if defined? JRUBY_VERSION and :NATIVE == Google::Protobuf::IMPLEMENTATION 280 pool = Google::Protobuf::DescriptorPool.new 281 282 # This serialized descriptor is a subset of basic_test_proto2.proto: 283 # 284 # syntax = "proto2"; 285 # package basic_test_proto2; 286 # 287 # message TestExtensions { 288 # extensions 1 to max; 289 # } 290 # 291 # extend TestExtensions { 292 # # Same extension as basic_test_proto2.proto, but with a different 293 # # name. 294 # optional int32 different_optional_int32_extension = 1; 295 # } 296 # 297 descriptor_data = "\n\x17\x62\x61sic_test_proto2.proto\x12\x11\x62\x61sic_test_proto2\"\x1a\n\x0eTestExtensions*\x08\x08\x01\x10\x80\x80\x80\x80\x02:M\n\"different_optional_int32_extension\x12!.basic_test_proto2.TestExtensions\x18\x01 \x01(\x05" 298 pool.add_serialized_file(descriptor_data) 299 message_class = pool.lookup("basic_test_proto2.TestExtensions").msgclass 300 extension = pool.lookup 'basic_test_proto2.different_optional_int32_extension' 301 302 message = message_class.decode_json '{"[basic_test_proto2.different_optional_int32_extension]": 123}' 303 assert_equal 123, extension.get(message) 304 305 message2 = message_class.decode_json(message_class.encode_json(message)) 306 assert_equal 123, extension.get(message2) 307 end 308 309 def test_nested_extension 310 message = TestExtensions.new 311 extension = Google::Protobuf::DescriptorPool.generated_pool.lookup 'basic_test_proto2.TestNestedExtension.test' 312 assert_instance_of Google::Protobuf::FieldDescriptor, extension 313 assert_equal 'test', extension.get(message) 314 extension.set message, 'another test' 315 assert_equal 'another test', extension.get(message) 316 end 317 318 def test_message_set_extension_json_roundtrip 319 omit "Java Protobuf JsonFormat does not handle Proto2 extensions" if defined? JRUBY_VERSION and :NATIVE == Google::Protobuf::IMPLEMENTATION 320 message = TestMessageSet.new 321 ext1 = Google::Protobuf::DescriptorPool.generated_pool.lookup 'basic_test_proto2.TestMessageSetExtension1.message_set_extension' 322 assert_instance_of Google::Protobuf::FieldDescriptor, ext1 323 ext2 = Google::Protobuf::DescriptorPool.generated_pool.lookup 'basic_test_proto2.TestMessageSetExtension2.message_set_extension' 324 assert_instance_of Google::Protobuf::FieldDescriptor, ext2 325 ext3 = Google::Protobuf::DescriptorPool.generated_pool.lookup 'basic_test_proto2.message_set_extension3' 326 assert_instance_of Google::Protobuf::FieldDescriptor, ext3 327 ext1.set(message, ext1.subtype.msgclass.new(i: 42)) 328 ext2.set(message, ext2.subtype.msgclass.new(str: 'foo')) 329 ext3.set(message, ext3.subtype.msgclass.new(text: 'bar')) 330 message_text = message.to_json 331 parsed_message = TestMessageSet.decode_json message_text 332 assert_equal message, parsed_message 333 end 334 335 336 def test_message_set_extension_roundtrip 337 message = TestMessageSet.new 338 ext1 = Google::Protobuf::DescriptorPool.generated_pool.lookup 'basic_test_proto2.TestMessageSetExtension1.message_set_extension' 339 assert_instance_of Google::Protobuf::FieldDescriptor, ext1 340 ext2 = Google::Protobuf::DescriptorPool.generated_pool.lookup 'basic_test_proto2.TestMessageSetExtension2.message_set_extension' 341 assert_instance_of Google::Protobuf::FieldDescriptor, ext2 342 ext3 = Google::Protobuf::DescriptorPool.generated_pool.lookup 'basic_test_proto2.message_set_extension3' 343 assert_instance_of Google::Protobuf::FieldDescriptor, ext3 344 ext1.set(message, ext1.subtype.msgclass.new(i: 42)) 345 ext2.set(message, ext2.subtype.msgclass.new(str: 'foo')) 346 ext3.set(message, ext3.subtype.msgclass.new(text: 'bar')) 347 encoded_message = TestMessageSet.encode message 348 decoded_message = TestMessageSet.decode encoded_message 349 assert_equal message, decoded_message 350 end 351 352 def test_field_explicit_presence 353 descriptor = TestMessage.descriptor.lookup("optional_int32") 354 assert_true descriptor.has_presence? 355 assert_false descriptor.options.has_features? 356 end 357 358 def test_field_expanded_encoding 359 descriptor = TestMessage.descriptor.lookup("repeated_int32") 360 assert_false descriptor.is_packed? 361 assert_false descriptor.options.has_features? 362 end 363 364 def test_field_packed_encoding 365 descriptor = TestPackedMessage.descriptor.lookup("repeated_int32") 366 assert_true descriptor.is_packed? 367 assert_false descriptor.options.has_features? 368 end 369 370 def test_field_group_type 371 descriptor = TestGroupMessage.descriptor.lookup("groupfield") 372 assert_equal :group, descriptor.type 373 assert_false descriptor.options.has_features? 374 end 375 376 def test_field_required 377 descriptor = TestRequiredMessage.descriptor.lookup("required_int32") 378 assert_equal :required, descriptor.label 379 assert_false descriptor.options.has_features? 380 end 381 end 382end 383