basic.rb 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. #!/usr/bin/ruby
  2. # basic_test_pb.rb is in the same directory as this test.
  3. $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__)))
  4. require 'basic_test_pb'
  5. require 'common_tests'
  6. require 'google/protobuf'
  7. require 'json'
  8. require 'test/unit'
  9. # ------------- generated code --------------
  10. module BasicTest
  11. pool = Google::Protobuf::DescriptorPool.new
  12. pool.build do
  13. add_message "BadFieldNames" do
  14. optional :dup, :int32, 1
  15. optional :class, :int32, 2
  16. end
  17. end
  18. BadFieldNames = pool.lookup("BadFieldNames").msgclass
  19. # ------------ test cases ---------------
  20. class MessageContainerTest < Test::Unit::TestCase
  21. # Required by CommonTests module to resolve proto3 proto classes used in tests.
  22. def proto_module
  23. ::BasicTest
  24. end
  25. include CommonTests
  26. def test_issue_8311_crash
  27. Google::Protobuf::DescriptorPool.generated_pool.build do
  28. add_file("inner.proto", :syntax => :proto3) do
  29. add_message "Inner" do
  30. # Removing either of these fixes the segfault.
  31. optional :foo, :string, 1
  32. optional :bar, :string, 2
  33. end
  34. end
  35. end
  36. Google::Protobuf::DescriptorPool.generated_pool.build do
  37. add_file("outer.proto", :syntax => :proto3) do
  38. add_message "Outer" do
  39. repeated :inners, :message, 1, "Inner"
  40. end
  41. end
  42. end
  43. outer = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("Outer").msgclass
  44. outer.new(
  45. inners: []
  46. )['inners'].to_s
  47. assert_raise Google::Protobuf::TypeError do
  48. outer.new(
  49. inners: [nil]
  50. ).to_s
  51. end
  52. end
  53. def test_has_field
  54. m = TestSingularFields.new
  55. assert !m.has_singular_msg?
  56. m.singular_msg = TestMessage2.new
  57. assert m.has_singular_msg?
  58. assert TestSingularFields.descriptor.lookup('singular_msg').has?(m)
  59. m = OneofMessage.new
  60. assert !m.has_my_oneof?
  61. m.a = "foo"
  62. assert m.has_my_oneof?
  63. assert_raise NoMethodError do
  64. m.has_a?
  65. end
  66. assert_true OneofMessage.descriptor.lookup('a').has?(m)
  67. m = TestSingularFields.new
  68. assert_raise NoMethodError do
  69. m.has_singular_int32?
  70. end
  71. assert_raise ArgumentError do
  72. TestSingularFields.descriptor.lookup('singular_int32').has?(m)
  73. end
  74. assert_raise NoMethodError do
  75. m.has_singular_string?
  76. end
  77. assert_raise ArgumentError do
  78. TestSingularFields.descriptor.lookup('singular_string').has?(m)
  79. end
  80. assert_raise NoMethodError do
  81. m.has_singular_bool?
  82. end
  83. assert_raise ArgumentError do
  84. TestSingularFields.descriptor.lookup('singular_bool').has?(m)
  85. end
  86. m = TestMessage.new
  87. assert_raise NoMethodError do
  88. m.has_repeated_msg?
  89. end
  90. assert_raise ArgumentError do
  91. TestMessage.descriptor.lookup('repeated_msg').has?(m)
  92. end
  93. end
  94. def test_no_presence
  95. m = TestSingularFields.new
  96. # Explicitly setting to zero does not cause anything to be serialized.
  97. m.singular_int32 = 0
  98. assert_equal "", TestSingularFields.encode(m)
  99. # Explicitly setting to a non-zero value *does* cause serialization.
  100. m.singular_int32 = 1
  101. assert_not_equal "", TestSingularFields.encode(m)
  102. m.singular_int32 = 0
  103. assert_equal "", TestSingularFields.encode(m)
  104. end
  105. def test_set_clear_defaults
  106. m = TestSingularFields.new
  107. m.singular_int32 = -42
  108. assert_equal -42, m.singular_int32
  109. m.clear_singular_int32
  110. assert_equal 0, m.singular_int32
  111. m.singular_int32 = 50
  112. assert_equal 50, m.singular_int32
  113. TestSingularFields.descriptor.lookup('singular_int32').clear(m)
  114. assert_equal 0, m.singular_int32
  115. m.singular_string = "foo bar"
  116. assert_equal "foo bar", m.singular_string
  117. m.clear_singular_string
  118. assert_equal "", m.singular_string
  119. m.singular_string = "foo"
  120. assert_equal "foo", m.singular_string
  121. TestSingularFields.descriptor.lookup('singular_string').clear(m)
  122. assert_equal "", m.singular_string
  123. m.singular_msg = TestMessage2.new(:foo => 42)
  124. assert_equal TestMessage2.new(:foo => 42), m.singular_msg
  125. assert m.has_singular_msg?
  126. m.clear_singular_msg
  127. assert_equal nil, m.singular_msg
  128. assert !m.has_singular_msg?
  129. m.singular_msg = TestMessage2.new(:foo => 42)
  130. assert_equal TestMessage2.new(:foo => 42), m.singular_msg
  131. TestSingularFields.descriptor.lookup('singular_msg').clear(m)
  132. assert_equal nil, m.singular_msg
  133. end
  134. def test_clear_repeated_fields
  135. m = TestMessage.new
  136. m.repeated_int32.push(1)
  137. assert_equal [1], m.repeated_int32
  138. m.clear_repeated_int32
  139. assert_equal [], m.repeated_int32
  140. m.repeated_int32.push(1)
  141. assert_equal [1], m.repeated_int32
  142. TestMessage.descriptor.lookup('repeated_int32').clear(m)
  143. assert_equal [], m.repeated_int32
  144. m = OneofMessage.new
  145. m.a = "foo"
  146. assert_equal "foo", m.a
  147. assert m.has_my_oneof?
  148. assert_equal :a, m.my_oneof
  149. m.clear_a
  150. assert !m.has_my_oneof?
  151. m.a = "foobar"
  152. assert m.has_my_oneof?
  153. m.clear_my_oneof
  154. assert !m.has_my_oneof?
  155. m.a = "bar"
  156. assert_equal "bar", m.a
  157. assert m.has_my_oneof?
  158. OneofMessage.descriptor.lookup('a').clear(m)
  159. assert !m.has_my_oneof?
  160. end
  161. def test_initialization_map_errors
  162. e = assert_raise ArgumentError do
  163. TestMessage.new(:hello => "world")
  164. end
  165. assert_match(/hello/, e.message)
  166. e = assert_raise ArgumentError do
  167. MapMessage.new(:map_string_int32 => "hello")
  168. end
  169. assert_equal e.message, "Expected Hash object as initializer value for map field 'map_string_int32' (given String)."
  170. e = assert_raise ArgumentError do
  171. TestMessage.new(:repeated_uint32 => "hello")
  172. end
  173. assert_equal e.message, "Expected array as initializer value for repeated field 'repeated_uint32' (given String)."
  174. end
  175. def test_map_field
  176. m = MapMessage.new
  177. assert m.map_string_int32 == {}
  178. assert m.map_string_msg == {}
  179. m = MapMessage.new(
  180. :map_string_int32 => {"a" => 1, "b" => 2},
  181. :map_string_msg => {"a" => TestMessage2.new(:foo => 1),
  182. "b" => TestMessage2.new(:foo => 2)},
  183. :map_string_enum => {"a" => :A, "b" => :B})
  184. assert m.map_string_int32.keys.sort == ["a", "b"]
  185. assert m.map_string_int32["a"] == 1
  186. assert m.map_string_msg["b"].foo == 2
  187. assert m.map_string_enum["a"] == :A
  188. m.map_string_int32["c"] = 3
  189. assert m.map_string_int32["c"] == 3
  190. m.map_string_msg["c"] = TestMessage2.new(:foo => 3)
  191. assert m.map_string_msg["c"] == TestMessage2.new(:foo => 3)
  192. m.map_string_msg.delete("b")
  193. m.map_string_msg.delete("c")
  194. assert m.map_string_msg == { "a" => TestMessage2.new(:foo => 1) }
  195. assert_raise Google::Protobuf::TypeError do
  196. m.map_string_msg["e"] = TestMessage.new # wrong value type
  197. end
  198. # ensure nothing was added by the above
  199. assert m.map_string_msg == { "a" => TestMessage2.new(:foo => 1) }
  200. m.map_string_int32 = Google::Protobuf::Map.new(:string, :int32)
  201. assert_raise Google::Protobuf::TypeError do
  202. m.map_string_int32 = Google::Protobuf::Map.new(:string, :int64)
  203. end
  204. assert_raise Google::Protobuf::TypeError do
  205. m.map_string_int32 = {}
  206. end
  207. assert_raise Google::Protobuf::TypeError do
  208. m = MapMessage.new(:map_string_int32 => { 1 => "I am not a number" })
  209. end
  210. end
  211. def test_map_field_with_symbol
  212. m = MapMessage.new
  213. assert m.map_string_int32 == {}
  214. assert m.map_string_msg == {}
  215. m = MapMessage.new(
  216. :map_string_int32 => {a: 1, "b" => 2},
  217. :map_string_msg => {a: TestMessage2.new(:foo => 1),
  218. b: TestMessage2.new(:foo => 10)})
  219. assert_equal 1, m.map_string_int32[:a]
  220. assert_equal 2, m.map_string_int32[:b]
  221. assert_equal 10, m.map_string_msg[:b].foo
  222. end
  223. def test_map_inspect
  224. m = MapMessage.new(
  225. :map_string_int32 => {"a" => 1, "b" => 2},
  226. :map_string_msg => {"a" => TestMessage2.new(:foo => 1),
  227. "b" => TestMessage2.new(:foo => 2)},
  228. :map_string_enum => {"a" => :A, "b" => :B})
  229. # JRuby doesn't keep consistent ordering so check for either version
  230. expected_a = "<BasicTest::MapMessage: map_string_int32: {\"b\"=>2, \"a\"=>1}, map_string_msg: {\"b\"=><BasicTest::TestMessage2: foo: 2>, \"a\"=><BasicTest::TestMessage2: foo: 1>}, map_string_enum: {\"b\"=>:B, \"a\"=>:A}>"
  231. expected_b = "<BasicTest::MapMessage: map_string_int32: {\"a\"=>1, \"b\"=>2}, map_string_msg: {\"a\"=><BasicTest::TestMessage2: foo: 1>, \"b\"=><BasicTest::TestMessage2: foo: 2>}, map_string_enum: {\"a\"=>:A, \"b\"=>:B}>"
  232. inspect_result = m.inspect
  233. assert expected_a == inspect_result || expected_b == inspect_result, "Incorrect inspect result: #{inspect_result}"
  234. end
  235. def test_map_corruption
  236. # This pattern led to a crash in a previous version of upb/protobuf.
  237. m = MapMessage.new(map_string_int32: { "aaa" => 1 })
  238. m.map_string_int32['podid'] = 2
  239. m.map_string_int32['aaa'] = 3
  240. end
  241. def test_map_wrappers
  242. run_asserts = ->(m) {
  243. assert_equal 2.0, m.map_double[0].value
  244. assert_equal 4.0, m.map_float[0].value
  245. assert_equal 3, m.map_int32[0].value
  246. assert_equal 4, m.map_int64[0].value
  247. assert_equal 5, m.map_uint32[0].value
  248. assert_equal 6, m.map_uint64[0].value
  249. assert_equal true, m.map_bool[0].value
  250. assert_equal 'str', m.map_string[0].value
  251. assert_equal 'fun', m.map_bytes[0].value
  252. }
  253. m = proto_module::Wrapper.new(
  254. map_double: {0 => Google::Protobuf::DoubleValue.new(value: 2.0)},
  255. map_float: {0 => Google::Protobuf::FloatValue.new(value: 4.0)},
  256. map_int32: {0 => Google::Protobuf::Int32Value.new(value: 3)},
  257. map_int64: {0 => Google::Protobuf::Int64Value.new(value: 4)},
  258. map_uint32: {0 => Google::Protobuf::UInt32Value.new(value: 5)},
  259. map_uint64: {0 => Google::Protobuf::UInt64Value.new(value: 6)},
  260. map_bool: {0 => Google::Protobuf::BoolValue.new(value: true)},
  261. map_string: {0 => Google::Protobuf::StringValue.new(value: 'str')},
  262. map_bytes: {0 => Google::Protobuf::BytesValue.new(value: 'fun')},
  263. )
  264. run_asserts.call(m)
  265. serialized = proto_module::Wrapper::encode(m)
  266. m2 = proto_module::Wrapper::decode(serialized)
  267. run_asserts.call(m2)
  268. # Test the case where we are serializing directly from the parsed form
  269. # (before anything lazy is materialized).
  270. m3 = proto_module::Wrapper::decode(serialized)
  271. serialized2 = proto_module::Wrapper::encode(m3)
  272. m4 = proto_module::Wrapper::decode(serialized2)
  273. run_asserts.call(m4)
  274. # Test that the lazy form compares equal to the expanded form.
  275. m5 = proto_module::Wrapper::decode(serialized2)
  276. assert_equal m5, m
  277. end
  278. def test_map_wrappers_with_default_values
  279. run_asserts = ->(m) {
  280. assert_equal 0.0, m.map_double[0].value
  281. assert_equal 0.0, m.map_float[0].value
  282. assert_equal 0, m.map_int32[0].value
  283. assert_equal 0, m.map_int64[0].value
  284. assert_equal 0, m.map_uint32[0].value
  285. assert_equal 0, m.map_uint64[0].value
  286. assert_equal false, m.map_bool[0].value
  287. assert_equal '', m.map_string[0].value
  288. assert_equal '', m.map_bytes[0].value
  289. }
  290. m = proto_module::Wrapper.new(
  291. map_double: {0 => Google::Protobuf::DoubleValue.new(value: 0.0)},
  292. map_float: {0 => Google::Protobuf::FloatValue.new(value: 0.0)},
  293. map_int32: {0 => Google::Protobuf::Int32Value.new(value: 0)},
  294. map_int64: {0 => Google::Protobuf::Int64Value.new(value: 0)},
  295. map_uint32: {0 => Google::Protobuf::UInt32Value.new(value: 0)},
  296. map_uint64: {0 => Google::Protobuf::UInt64Value.new(value: 0)},
  297. map_bool: {0 => Google::Protobuf::BoolValue.new(value: false)},
  298. map_string: {0 => Google::Protobuf::StringValue.new(value: '')},
  299. map_bytes: {0 => Google::Protobuf::BytesValue.new(value: '')},
  300. )
  301. run_asserts.call(m)
  302. serialized = proto_module::Wrapper::encode(m)
  303. m2 = proto_module::Wrapper::decode(serialized)
  304. run_asserts.call(m2)
  305. # Test the case where we are serializing directly from the parsed form
  306. # (before anything lazy is materialized).
  307. m3 = proto_module::Wrapper::decode(serialized)
  308. serialized2 = proto_module::Wrapper::encode(m3)
  309. m4 = proto_module::Wrapper::decode(serialized2)
  310. run_asserts.call(m4)
  311. # Test that the lazy form compares equal to the expanded form.
  312. m5 = proto_module::Wrapper::decode(serialized2)
  313. assert_equal m5, m
  314. end
  315. def test_map_wrappers_with_no_value
  316. run_asserts = ->(m) {
  317. assert_equal 0.0, m.map_double[0].value
  318. assert_equal 0.0, m.map_float[0].value
  319. assert_equal 0, m.map_int32[0].value
  320. assert_equal 0, m.map_int64[0].value
  321. assert_equal 0, m.map_uint32[0].value
  322. assert_equal 0, m.map_uint64[0].value
  323. assert_equal false, m.map_bool[0].value
  324. assert_equal '', m.map_string[0].value
  325. assert_equal '', m.map_bytes[0].value
  326. }
  327. m = proto_module::Wrapper.new(
  328. map_double: {0 => Google::Protobuf::DoubleValue.new()},
  329. map_float: {0 => Google::Protobuf::FloatValue.new()},
  330. map_int32: {0 => Google::Protobuf::Int32Value.new()},
  331. map_int64: {0 => Google::Protobuf::Int64Value.new()},
  332. map_uint32: {0 => Google::Protobuf::UInt32Value.new()},
  333. map_uint64: {0 => Google::Protobuf::UInt64Value.new()},
  334. map_bool: {0 => Google::Protobuf::BoolValue.new()},
  335. map_string: {0 => Google::Protobuf::StringValue.new()},
  336. map_bytes: {0 => Google::Protobuf::BytesValue.new()},
  337. )
  338. run_asserts.call(m)
  339. serialized = proto_module::Wrapper::encode(m)
  340. m2 = proto_module::Wrapper::decode(serialized)
  341. run_asserts.call(m2)
  342. # Test the case where we are serializing directly from the parsed form
  343. # (before anything lazy is materialized).
  344. m3 = proto_module::Wrapper::decode(serialized)
  345. serialized2 = proto_module::Wrapper::encode(m3)
  346. m4 = proto_module::Wrapper::decode(serialized2)
  347. run_asserts.call(m4)
  348. end
  349. def test_concurrent_decoding
  350. o = Outer.new
  351. o.items[0] = Inner.new
  352. raw = Outer.encode(o)
  353. thds = 2.times.map do
  354. Thread.new do
  355. 100000.times do
  356. assert_equal o, Outer.decode(raw)
  357. end
  358. end
  359. end
  360. thds.map(&:join)
  361. end
  362. def test_map_encode_decode
  363. m = MapMessage.new(
  364. :map_string_int32 => {"a" => 1, "b" => 2},
  365. :map_string_msg => {"a" => TestMessage2.new(:foo => 1),
  366. "b" => TestMessage2.new(:foo => 2)},
  367. :map_string_enum => {"a" => :A, "b" => :B})
  368. m2 = MapMessage.decode(MapMessage.encode(m))
  369. assert m == m2
  370. m3 = MapMessageWireEquiv.decode(MapMessage.encode(m))
  371. assert m3.map_string_int32.length == 2
  372. kv = {}
  373. m3.map_string_int32.map { |msg| kv[msg.key] = msg.value }
  374. assert kv == {"a" => 1, "b" => 2}
  375. kv = {}
  376. m3.map_string_msg.map { |msg| kv[msg.key] = msg.value }
  377. assert kv == {"a" => TestMessage2.new(:foo => 1),
  378. "b" => TestMessage2.new(:foo => 2)}
  379. end
  380. def test_protobuf_decode_json_ignore_unknown_fields
  381. m = TestMessage.decode_json({
  382. optional_string: "foo",
  383. not_in_message: "some_value"
  384. }.to_json, { ignore_unknown_fields: true })
  385. assert_equal m.optional_string, "foo"
  386. e = assert_raise Google::Protobuf::ParseError do
  387. TestMessage.decode_json({ not_in_message: "some_value" }.to_json)
  388. end
  389. assert_match(/No such field: not_in_message/, e.message)
  390. end
  391. #def test_json_quoted_string
  392. # m = TestMessage.decode_json(%q(
  393. # "optionalInt64": "1",,
  394. # }))
  395. # puts(m)
  396. # assert_equal 1, m.optional_int32
  397. #end
  398. def test_to_h
  399. m = TestMessage.new(:optional_bool => true, :optional_double => -10.100001, :optional_string => 'foo', :repeated_string => ['bar1', 'bar2'], :repeated_msg => [TestMessage2.new(:foo => 100)])
  400. expected_result = {
  401. :optional_bool=>true,
  402. :optional_bytes=>"",
  403. :optional_double=>-10.100001,
  404. :optional_enum=>:Default,
  405. :optional_float=>0.0,
  406. :optional_int32=>0,
  407. :optional_int64=>0,
  408. :optional_msg=>nil,
  409. :optional_msg2=>nil,
  410. :optional_string=>"foo",
  411. :optional_uint32=>0,
  412. :optional_uint64=>0,
  413. :repeated_bool=>[],
  414. :repeated_bytes=>[],
  415. :repeated_double=>[],
  416. :repeated_enum=>[],
  417. :repeated_float=>[],
  418. :repeated_int32=>[],
  419. :repeated_int64=>[],
  420. :repeated_msg=>[{:foo => 100}],
  421. :repeated_string=>["bar1", "bar2"],
  422. :repeated_uint32=>[],
  423. :repeated_uint64=>[]
  424. }
  425. assert_equal expected_result, m.to_h
  426. m = MapMessage.new(
  427. :map_string_int32 => {"a" => 1, "b" => 2},
  428. :map_string_msg => {"a" => TestMessage2.new(:foo => 1),
  429. "b" => TestMessage2.new(:foo => 2)},
  430. :map_string_enum => {"a" => :A, "b" => :B})
  431. expected_result = {
  432. :map_string_int32 => {"a" => 1, "b" => 2},
  433. :map_string_msg => {"a" => {:foo => 1}, "b" => {:foo => 2}},
  434. :map_string_enum => {"a" => :A, "b" => :B}
  435. }
  436. assert_equal expected_result, m.to_h
  437. end
  438. def test_json_maps
  439. # TODO: Fix JSON in JRuby version.
  440. return if RUBY_PLATFORM == "java"
  441. m = MapMessage.new(:map_string_int32 => {"a" => 1})
  442. expected = {mapStringInt32: {a: 1}, mapStringMsg: {}, mapStringEnum: {}}
  443. expected_preserve = {map_string_int32: {a: 1}, map_string_msg: {}, map_string_enum: {}}
  444. assert_equal JSON.parse(MapMessage.encode_json(m, :emit_defaults=>true), :symbolize_names => true), expected
  445. json = MapMessage.encode_json(m, :preserve_proto_fieldnames => true, :emit_defaults=>true)
  446. assert_equal JSON.parse(json, :symbolize_names => true), expected_preserve
  447. m2 = MapMessage.decode_json(MapMessage.encode_json(m))
  448. assert_equal m, m2
  449. end
  450. def test_json_maps_emit_defaults_submsg
  451. # TODO: Fix JSON in JRuby version.
  452. return if RUBY_PLATFORM == "java"
  453. m = MapMessage.new(:map_string_msg => {"a" => TestMessage2.new(foo: 0)})
  454. expected = {mapStringInt32: {}, mapStringMsg: {a: {foo: 0}}, mapStringEnum: {}}
  455. actual = MapMessage.encode_json(m, :emit_defaults => true)
  456. assert_equal JSON.parse(actual, :symbolize_names => true), expected
  457. end
  458. def test_json_emit_defaults_submsg
  459. # TODO: Fix JSON in JRuby version.
  460. return if RUBY_PLATFORM == "java"
  461. m = TestSingularFields.new(singular_msg: proto_module::TestMessage2.new)
  462. expected = {
  463. singularInt32: 0,
  464. singularInt64: "0",
  465. singularUint32: 0,
  466. singularUint64: "0",
  467. singularBool: false,
  468. singularFloat: 0,
  469. singularDouble: 0,
  470. singularString: "",
  471. singularBytes: "",
  472. singularMsg: {},
  473. singularEnum: "Default",
  474. }
  475. actual = proto_module::TestMessage.encode_json(m, :emit_defaults => true)
  476. assert_equal expected, JSON.parse(actual, :symbolize_names => true)
  477. end
  478. def test_respond_to
  479. # This test fails with JRuby 1.7.23, likely because of an old JRuby bug.
  480. return if RUBY_PLATFORM == "java"
  481. msg = MapMessage.new
  482. assert msg.respond_to?(:map_string_int32)
  483. assert !msg.respond_to?(:bacon)
  484. end
  485. def test_file_descriptor
  486. file_descriptor = TestMessage.descriptor.file_descriptor
  487. assert nil != file_descriptor
  488. assert_equal "tests/basic_test.proto", file_descriptor.name
  489. assert_equal :proto3, file_descriptor.syntax
  490. file_descriptor = TestEnum.descriptor.file_descriptor
  491. assert nil != file_descriptor
  492. assert_equal "tests/basic_test.proto", file_descriptor.name
  493. assert_equal :proto3, file_descriptor.syntax
  494. end
  495. # Ruby 2.5 changed to raise FrozenError instead of RuntimeError
  496. FrozenErrorType = Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.5') ? RuntimeError : FrozenError
  497. def test_map_freeze
  498. m = proto_module::MapMessage.new
  499. m.map_string_int32['a'] = 5
  500. m.map_string_msg['b'] = proto_module::TestMessage2.new
  501. m.map_string_int32.freeze
  502. m.map_string_msg.freeze
  503. assert m.map_string_int32.frozen?
  504. assert m.map_string_msg.frozen?
  505. assert_raise(FrozenErrorType) { m.map_string_int32['foo'] = 1 }
  506. assert_raise(FrozenErrorType) { m.map_string_msg['bar'] = proto_module::TestMessage2.new }
  507. assert_raise(FrozenErrorType) { m.map_string_int32.delete('a') }
  508. assert_raise(FrozenErrorType) { m.map_string_int32.clear }
  509. end
  510. end
  511. end