basic.rb 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. #!/usr/bin/ruby
  2. require 'protobuf'
  3. require 'test/unit'
  4. # ------------- generated code --------------
  5. module BasicTest
  6. pool = Google::Protobuf::DescriptorPool.new
  7. pool.build do
  8. add_message "TestMessage" do
  9. optional :optional_int32, :int32, 1
  10. optional :optional_int64, :int64, 2
  11. optional :optional_uint32, :uint32, 3
  12. optional :optional_uint64, :uint64, 4
  13. optional :optional_bool, :bool, 5
  14. optional :optional_float, :float, 6
  15. optional :optional_double, :double, 7
  16. optional :optional_string, :string, 8
  17. optional :optional_bytes, :bytes, 9
  18. optional :optional_msg, :message, 10, "TestMessage2"
  19. optional :optional_enum, :enum, 11, "TestEnum"
  20. repeated :repeated_int32, :int32, 12
  21. repeated :repeated_int64, :int64, 13
  22. repeated :repeated_uint32, :uint32, 14
  23. repeated :repeated_uint64, :uint64, 15
  24. repeated :repeated_bool, :bool, 16
  25. repeated :repeated_float, :float, 17
  26. repeated :repeated_double, :double, 18
  27. repeated :repeated_string, :string, 19
  28. repeated :repeated_bytes, :bytes, 20
  29. repeated :repeated_msg, :message, 21, "TestMessage2"
  30. repeated :repeated_enum, :enum, 22, "TestEnum"
  31. end
  32. add_message "TestMessage2" do
  33. optional :foo, :int32, 1
  34. end
  35. add_message "Recursive1" do
  36. optional :foo, :message, 1, "Recursive2"
  37. end
  38. add_message "Recursive2" do
  39. optional :foo, :message, 1, "Recursive1"
  40. end
  41. add_enum "TestEnum" do
  42. value :Default, 0
  43. value :A, 1
  44. value :B, 2
  45. value :C, 3
  46. end
  47. add_message "BadFieldNames" do
  48. optional :dup, :int32, 1
  49. optional :class, :int32, 2
  50. optional :"a.b", :int32, 3
  51. end
  52. end
  53. TestMessage = pool.lookup("TestMessage").msgclass
  54. TestMessage2 = pool.lookup("TestMessage2").msgclass
  55. Recursive1 = pool.lookup("Recursive1").msgclass
  56. Recursive2 = pool.lookup("Recursive2").msgclass
  57. TestEnum = pool.lookup("TestEnum").enummodule
  58. BadFieldNames = pool.lookup("BadFieldNames").msgclass
  59. # ------------ test cases ---------------
  60. class MessageContainerTest < Test::Unit::TestCase
  61. def test_defaults
  62. m = TestMessage.new
  63. assert m.optional_int32 == 0
  64. assert m.optional_int64 == 0
  65. assert m.optional_uint32 == 0
  66. assert m.optional_uint64 == 0
  67. assert m.optional_bool == false
  68. assert m.optional_float == 0.0
  69. assert m.optional_double == 0.0
  70. assert m.optional_string == ""
  71. assert m.optional_bytes == ""
  72. assert m.optional_msg == nil
  73. assert m.optional_enum == :Default
  74. end
  75. def test_setters
  76. m = TestMessage.new
  77. m.optional_int32 = -42
  78. assert m.optional_int32 == -42
  79. m.optional_int64 = -0x1_0000_0000
  80. assert m.optional_int64 == -0x1_0000_0000
  81. m.optional_uint32 = 0x9000_0000
  82. assert m.optional_uint32 == 0x9000_0000
  83. m.optional_uint64 = 0x9000_0000_0000_0000
  84. assert m.optional_uint64 == 0x9000_0000_0000_0000
  85. m.optional_bool = true
  86. assert m.optional_bool == true
  87. m.optional_float = 0.5
  88. assert m.optional_float == 0.5
  89. m.optional_double = 0.5
  90. m.optional_string = "hello"
  91. assert m.optional_string == "hello"
  92. m.optional_bytes = "world".encode!('ASCII-8BIT')
  93. assert m.optional_bytes == "world"
  94. m.optional_msg = TestMessage2.new(:foo => 42)
  95. assert m.optional_msg == TestMessage2.new(:foo => 42)
  96. end
  97. def test_ctor_args
  98. m = TestMessage.new(:optional_int32 => -42,
  99. :optional_msg => TestMessage2.new,
  100. :optional_enum => :C,
  101. :repeated_string => ["hello", "there", "world"])
  102. assert m.optional_int32 == -42
  103. assert m.optional_msg.class == TestMessage2
  104. assert m.repeated_string.length == 3
  105. assert m.optional_enum == :C
  106. assert m.repeated_string[0] == "hello"
  107. assert m.repeated_string[1] == "there"
  108. assert m.repeated_string[2] == "world"
  109. end
  110. def test_inspect
  111. m = TestMessage.new(:optional_int32 => -42,
  112. :optional_enum => :A,
  113. :optional_msg => TestMessage2.new,
  114. :repeated_string => ["hello", "there", "world"])
  115. 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: []>'
  116. assert m.inspect == expected
  117. end
  118. def test_hash
  119. m1 = TestMessage.new(:optional_int32 => 42)
  120. m2 = TestMessage.new(:optional_int32 => 102)
  121. assert m1.hash != 0
  122. assert m2.hash != 0
  123. # relying on the randomness here -- if hash function changes and we are
  124. # unlucky enough to get a collision, then change the values above.
  125. assert m1.hash != m2.hash
  126. end
  127. def test_type_errors
  128. m = TestMessage.new
  129. assert_raise TypeError do
  130. m.optional_int32 = "hello"
  131. end
  132. assert_raise TypeError do
  133. m.optional_string = 42
  134. end
  135. assert_raise TypeError do
  136. m.optional_string = nil
  137. end
  138. assert_raise TypeError do
  139. m.optional_bool = 42
  140. end
  141. assert_raise TypeError do
  142. m.optional_msg = TestMessage.new # expects TestMessage2
  143. end
  144. assert_raise TypeError do
  145. m.repeated_int32 = [] # needs RepeatedField
  146. end
  147. assert_raise TypeError do
  148. m.repeated_int32.push "hello"
  149. end
  150. assert_raise TypeError do
  151. m.repeated_msg.push TestMessage.new
  152. end
  153. end
  154. def test_string_encoding
  155. m = TestMessage.new
  156. # Assigning a normal (ASCII or UTF8) string to a bytes field, or
  157. # ASCII-8BIT to a string field, raises an error.
  158. assert_raise TypeError do
  159. m.optional_bytes = "Test string ASCII".encode!('ASCII')
  160. end
  161. assert_raise TypeError do
  162. m.optional_bytes = "Test string UTF-8 \u0100".encode!('UTF-8')
  163. end
  164. assert_raise TypeError do
  165. m.optional_string = ["FFFF"].pack('H*')
  166. end
  167. # "Ordinary" use case.
  168. m.optional_bytes = ["FFFF"].pack('H*')
  169. m.optional_string = "\u0100"
  170. # strings are mutable so we can do this, but serialize should catch it.
  171. m.optional_string = "asdf".encode!('UTF-8')
  172. m.optional_string.encode!('ASCII-8BIT')
  173. assert_raise TypeError do
  174. data = TestMessage.encode(m)
  175. end
  176. end
  177. def test_rptfield_int32
  178. l = Google::Protobuf::RepeatedField.new(:int32)
  179. assert l.count == 0
  180. l = Google::Protobuf::RepeatedField.new(:int32, [1, 2, 3])
  181. assert l.count == 3
  182. assert l == [1, 2, 3]
  183. l.push 4
  184. assert l == [1, 2, 3, 4]
  185. dst_list = []
  186. l.each { |val| dst_list.push val }
  187. assert dst_list == [1, 2, 3, 4]
  188. assert l.to_a == [1, 2, 3, 4]
  189. assert l[0] == 1
  190. assert l[3] == 4
  191. l[0] = 5
  192. assert l == [5, 2, 3, 4]
  193. l2 = l.dup
  194. assert l == l2
  195. assert l.object_id != l2.object_id
  196. l2.push 6
  197. assert l.count == 4
  198. assert l2.count == 5
  199. assert l.inspect == '[5, 2, 3, 4]'
  200. l.insert(7, 8, 9)
  201. assert l == [5, 2, 3, 4, 7, 8, 9]
  202. assert l.pop == 9
  203. assert l == [5, 2, 3, 4, 7, 8]
  204. assert_raise TypeError do
  205. m = TestMessage.new
  206. l.push m
  207. end
  208. m = TestMessage.new
  209. m.repeated_int32 = l
  210. assert m.repeated_int32 == [5, 2, 3, 4, 7, 8]
  211. assert m.repeated_int32.object_id == l.object_id
  212. l.push 42
  213. assert m.repeated_int32.pop == 42
  214. l3 = l + l.dup
  215. assert l3.count == l.count * 2
  216. l.count.times do |i|
  217. assert l3[i] == l[i]
  218. assert l3[l.count + i] == l[i]
  219. end
  220. l.clear
  221. assert l.count == 0
  222. l += [1, 2, 3, 4]
  223. l.replace([5, 6, 7, 8])
  224. assert l == [5, 6, 7, 8]
  225. l4 = Google::Protobuf::RepeatedField.new(:int32)
  226. l4[5] = 42
  227. assert l4 == [0, 0, 0, 0, 0, 42]
  228. l4 << 100
  229. assert l4 == [0, 0, 0, 0, 0, 42, 100]
  230. l4 << 101 << 102
  231. assert l4 == [0, 0, 0, 0, 0, 42, 100, 101, 102]
  232. end
  233. def test_rptfield_msg
  234. l = Google::Protobuf::RepeatedField.new(:message, TestMessage)
  235. l.push TestMessage.new
  236. assert l.count == 1
  237. assert_raise TypeError do
  238. l.push TestMessage2.new
  239. end
  240. assert_raise TypeError do
  241. l.push 42
  242. end
  243. l2 = l.dup
  244. assert l2[0] == l[0]
  245. assert l2[0].object_id == l[0].object_id
  246. l2 = Google::Protobuf.deep_copy(l)
  247. assert l2[0] == l[0]
  248. assert l2[0].object_id != l[0].object_id
  249. l3 = l + l2
  250. assert l3.count == 2
  251. assert l3[0] == l[0]
  252. assert l3[1] == l2[0]
  253. l3[0].optional_int32 = 1000
  254. assert l[0].optional_int32 == 1000
  255. new_msg = TestMessage.new(:optional_int32 => 200)
  256. l4 = l + [new_msg]
  257. assert l4.count == 2
  258. new_msg.optional_int32 = 1000
  259. assert l4[1].optional_int32 == 1000
  260. end
  261. def test_rptfield_enum
  262. l = Google::Protobuf::RepeatedField.new(:enum, TestEnum)
  263. l.push :A
  264. l.push :B
  265. l.push :C
  266. assert l.count == 3
  267. assert_raise NameError do
  268. l.push :D
  269. end
  270. assert l[0] == :A
  271. l.push 4
  272. assert l[3] == 4
  273. end
  274. def test_rptfield_initialize
  275. assert_raise ArgumentError do
  276. l = Google::Protobuf::RepeatedField.new
  277. end
  278. assert_raise ArgumentError do
  279. l = Google::Protobuf::RepeatedField.new(:message)
  280. end
  281. assert_raise ArgumentError do
  282. l = Google::Protobuf::RepeatedField.new([1, 2, 3])
  283. end
  284. assert_raise ArgumentError do
  285. l = Google::Protobuf::RepeatedField.new(:message, [TestMessage2.new])
  286. end
  287. end
  288. def test_enum_field
  289. m = TestMessage.new
  290. assert m.optional_enum == :Default
  291. m.optional_enum = :A
  292. assert m.optional_enum == :A
  293. assert_raise NameError do
  294. m.optional_enum = :ASDF
  295. end
  296. m.optional_enum = 1
  297. assert m.optional_enum == :A
  298. m.optional_enum = 100
  299. assert m.optional_enum == 100
  300. end
  301. def test_dup
  302. m = TestMessage.new
  303. m.optional_string = "hello"
  304. m.optional_int32 = 42
  305. m.repeated_msg.push TestMessage2.new(:foo => 100)
  306. m.repeated_msg.push TestMessage2.new(:foo => 200)
  307. m2 = m.dup
  308. assert m == m2
  309. m.optional_int32 += 1
  310. assert m != m2
  311. assert m.repeated_msg[0] == m2.repeated_msg[0]
  312. assert m.repeated_msg[0].object_id == m2.repeated_msg[0].object_id
  313. end
  314. def test_deep_copy
  315. m = TestMessage.new(:optional_int32 => 42,
  316. :repeated_msg => [TestMessage2.new(:foo => 100)])
  317. m2 = Google::Protobuf.deep_copy(m)
  318. assert m == m2
  319. assert m.repeated_msg == m2.repeated_msg
  320. assert m.repeated_msg.object_id != m2.repeated_msg.object_id
  321. assert m.repeated_msg[0].object_id != m2.repeated_msg[0].object_id
  322. end
  323. def test_enum_lookup
  324. assert TestEnum::A == 1
  325. assert TestEnum::B == 2
  326. assert TestEnum::C == 3
  327. assert TestEnum::lookup(1) == :A
  328. assert TestEnum::lookup(2) == :B
  329. assert TestEnum::lookup(3) == :C
  330. assert TestEnum::resolve(:A) == 1
  331. assert TestEnum::resolve(:B) == 2
  332. assert TestEnum::resolve(:C) == 3
  333. end
  334. def test_parse_serialize
  335. m = TestMessage.new(:optional_int32 => 42,
  336. :optional_string => "hello world",
  337. :optional_enum => :B,
  338. :repeated_string => ["a", "b", "c"],
  339. :repeated_int32 => [42, 43, 44],
  340. :repeated_enum => [:A, :B, :C, 100],
  341. :repeated_msg => [TestMessage2.new(:foo => 1), TestMessage2.new(:foo => 2)])
  342. data = TestMessage.encode m
  343. m2 = TestMessage.decode data
  344. assert m == m2
  345. data = Google::Protobuf.encode m
  346. m2 = Google::Protobuf.decode(TestMessage, data)
  347. assert m == m2
  348. end
  349. def test_def_errors
  350. s = Google::Protobuf::DescriptorPool.new
  351. assert_raise TypeError do
  352. s.build do
  353. # enum with no default (integer value 0)
  354. add_enum "MyEnum" do
  355. value :A, 1
  356. end
  357. end
  358. end
  359. assert_raise TypeError do
  360. s.build do
  361. # message with required field (unsupported in proto3)
  362. add_message "MyMessage" do
  363. required :foo, :int32, 1
  364. end
  365. end
  366. end
  367. end
  368. def test_corecursive
  369. # just be sure that we can instantiate types with corecursive field-type
  370. # references.
  371. m = Recursive1.new(:foo => Recursive2.new(:foo => Recursive1.new))
  372. assert Recursive1.descriptor.lookup("foo").subtype ==
  373. Recursive2.descriptor
  374. assert Recursive2.descriptor.lookup("foo").subtype ==
  375. Recursive1.descriptor
  376. serialized = Recursive1.encode(m)
  377. m2 = Recursive1.decode(serialized)
  378. assert m == m2
  379. end
  380. def test_serialize_cycle
  381. m = Recursive1.new(:foo => Recursive2.new)
  382. m.foo.foo = m
  383. assert_raise RuntimeError do
  384. serialized = Recursive1.encode(m)
  385. end
  386. end
  387. def test_bad_field_names
  388. m = BadFieldNames.new(:dup => 1, :class => 2)
  389. m2 = m.dup
  390. assert m == m2
  391. assert m['dup'] == 1
  392. assert m['class'] == 2
  393. m['dup'] = 3
  394. assert m['dup'] == 3
  395. m['a.b'] = 4
  396. assert m['a.b'] == 4
  397. end
  398. def test_int_ranges
  399. m = TestMessage.new
  400. m.optional_int32 = 0
  401. m.optional_int32 = -0x8000_0000
  402. m.optional_int32 = +0x7fff_ffff
  403. m.optional_int32 = 1.0
  404. m.optional_int32 = -1.0
  405. m.optional_int32 = 2e9
  406. assert_raise RangeError do
  407. m.optional_int32 = -0x8000_0001
  408. end
  409. assert_raise RangeError do
  410. m.optional_int32 = +0x8000_0000
  411. end
  412. assert_raise RangeError do
  413. m.optional_int32 = +0x1000_0000_0000_0000_0000_0000 # force Bignum
  414. end
  415. assert_raise RangeError do
  416. m.optional_int32 = 1e12
  417. end
  418. assert_raise RangeError do
  419. m.optional_int32 = 1.5
  420. end
  421. m.optional_uint32 = 0
  422. m.optional_uint32 = +0xffff_ffff
  423. m.optional_uint32 = 1.0
  424. m.optional_uint32 = 4e9
  425. assert_raise RangeError do
  426. m.optional_uint32 = -1
  427. end
  428. assert_raise RangeError do
  429. m.optional_uint32 = -1.5
  430. end
  431. assert_raise RangeError do
  432. m.optional_uint32 = -1.5e12
  433. end
  434. assert_raise RangeError do
  435. m.optional_uint32 = -0x1000_0000_0000_0000
  436. end
  437. assert_raise RangeError do
  438. m.optional_uint32 = +0x1_0000_0000
  439. end
  440. assert_raise RangeError do
  441. m.optional_uint32 = +0x1000_0000_0000_0000_0000_0000 # force Bignum
  442. end
  443. assert_raise RangeError do
  444. m.optional_uint32 = 1e12
  445. end
  446. assert_raise RangeError do
  447. m.optional_uint32 = 1.5
  448. end
  449. m.optional_int64 = 0
  450. m.optional_int64 = -0x8000_0000_0000_0000
  451. m.optional_int64 = +0x7fff_ffff_ffff_ffff
  452. m.optional_int64 = 1.0
  453. m.optional_int64 = -1.0
  454. m.optional_int64 = 8e18
  455. m.optional_int64 = -8e18
  456. assert_raise RangeError do
  457. m.optional_int64 = -0x8000_0000_0000_0001
  458. end
  459. assert_raise RangeError do
  460. m.optional_int64 = +0x8000_0000_0000_0000
  461. end
  462. assert_raise RangeError do
  463. m.optional_int64 = +0x1000_0000_0000_0000_0000_0000 # force Bignum
  464. end
  465. assert_raise RangeError do
  466. m.optional_int64 = 1e50
  467. end
  468. assert_raise RangeError do
  469. m.optional_int64 = 1.5
  470. end
  471. m.optional_uint64 = 0
  472. m.optional_uint64 = +0xffff_ffff_ffff_ffff
  473. m.optional_uint64 = 1.0
  474. m.optional_uint64 = 16e18
  475. assert_raise RangeError do
  476. m.optional_uint64 = -1
  477. end
  478. assert_raise RangeError do
  479. m.optional_uint64 = -1.5
  480. end
  481. assert_raise RangeError do
  482. m.optional_uint64 = -1.5e12
  483. end
  484. assert_raise RangeError do
  485. m.optional_uint64 = -0x1_0000_0000_0000_0000
  486. end
  487. assert_raise RangeError do
  488. m.optional_uint64 = +0x1_0000_0000_0000_0000
  489. end
  490. assert_raise RangeError do
  491. m.optional_uint64 = +0x1000_0000_0000_0000_0000_0000 # force Bignum
  492. end
  493. assert_raise RangeError do
  494. m.optional_uint64 = 1e50
  495. end
  496. assert_raise RangeError do
  497. m.optional_uint64 = 1.5
  498. end
  499. end
  500. def test_stress_test
  501. m = TestMessage.new
  502. m.optional_int32 = 42
  503. m.optional_int64 = 0x100000000
  504. m.optional_string = "hello world"
  505. 10.times do m.repeated_msg.push TestMessage2.new(:foo => 42) end
  506. 10.times do m.repeated_string.push "hello world" end
  507. data = TestMessage.encode(m)
  508. l = 0
  509. 10_000.times do
  510. m = TestMessage.decode(data)
  511. data_new = TestMessage.encode(m)
  512. assert data_new == data
  513. data = data_new
  514. end
  515. end
  516. def test_reflection
  517. m = TestMessage.new(:optional_int32 => 1234)
  518. msgdef = m.class.descriptor
  519. assert msgdef.class == Google::Protobuf::Descriptor
  520. assert msgdef.any? {|field| field.name == "optional_int32"}
  521. optional_int32 = msgdef.lookup "optional_int32"
  522. assert optional_int32.class == Google::Protobuf::FieldDescriptor
  523. assert optional_int32 != nil
  524. assert optional_int32.name == "optional_int32"
  525. assert optional_int32.type == :int32
  526. optional_int32.set(m, 5678)
  527. assert m.optional_int32 == 5678
  528. m.optional_int32 = 1000
  529. assert optional_int32.get(m) == 1000
  530. optional_msg = msgdef.lookup "optional_msg"
  531. assert optional_msg.subtype == TestMessage2.descriptor
  532. optional_msg.set(m, optional_msg.subtype.msgclass.new)
  533. assert msgdef.msgclass == TestMessage
  534. optional_enum = msgdef.lookup "optional_enum"
  535. assert optional_enum.subtype == TestEnum.descriptor
  536. assert optional_enum.subtype.class == Google::Protobuf::EnumDescriptor
  537. optional_enum.subtype.each do |k, v|
  538. # set with integer, check resolution to symbolic name
  539. optional_enum.set(m, v)
  540. assert optional_enum.get(m) == k
  541. end
  542. end
  543. def test_json
  544. m = TestMessage.new(:optional_int32 => 1234,
  545. :optional_int64 => -0x1_0000_0000,
  546. :optional_uint32 => 0x8000_0000,
  547. :optional_uint64 => 0xffff_ffff_ffff_ffff,
  548. :optional_bool => true,
  549. :optional_float => 1.0,
  550. :optional_double => -1e100,
  551. :optional_string => "Test string",
  552. :optional_bytes => ["FFFFFFFF"].pack('H*'),
  553. :optional_msg => TestMessage2.new(:foo => 42),
  554. :repeated_int32 => [1, 2, 3, 4],
  555. :repeated_string => ["a", "b", "c"],
  556. :repeated_bool => [true, false, true, false],
  557. :repeated_msg => [TestMessage2.new(:foo => 1),
  558. TestMessage2.new(:foo => 2)])
  559. json_text = TestMessage.encode_json(m)
  560. m2 = TestMessage.decode_json(json_text)
  561. assert m == m2
  562. end
  563. end
  564. end