message_test.py 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721
  1. #! /usr/bin/python
  2. #
  3. # Protocol Buffers - Google's data interchange format
  4. # Copyright 2008 Google Inc. All rights reserved.
  5. # https://developers.google.com/protocol-buffers/
  6. #
  7. # Redistribution and use in source and binary forms, with or without
  8. # modification, are permitted provided that the following conditions are
  9. # met:
  10. #
  11. # * Redistributions of source code must retain the above copyright
  12. # notice, this list of conditions and the following disclaimer.
  13. # * Redistributions in binary form must reproduce the above
  14. # copyright notice, this list of conditions and the following disclaimer
  15. # in the documentation and/or other materials provided with the
  16. # distribution.
  17. # * Neither the name of Google Inc. nor the names of its
  18. # contributors may be used to endorse or promote products derived from
  19. # this software without specific prior written permission.
  20. #
  21. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  24. # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  25. # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  26. # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  27. # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  28. # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  29. # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  30. # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  31. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. """Tests python protocol buffers against the golden message.
  33. Note that the golden messages exercise every known field type, thus this
  34. test ends up exercising and verifying nearly all of the parsing and
  35. serialization code in the whole library.
  36. TODO(kenton): Merge with wire_format_test? It doesn't make a whole lot of
  37. sense to call this a test of the "message" module, which only declares an
  38. abstract interface.
  39. """
  40. __author__ = 'gps@google.com (Gregory P. Smith)'
  41. import copy
  42. import math
  43. import operator
  44. import pickle
  45. import sys
  46. from google.apputils import basetest
  47. from google.protobuf import unittest_pb2
  48. from google.protobuf.internal import api_implementation
  49. from google.protobuf.internal import test_util
  50. from google.protobuf import message
  51. # Python pre-2.6 does not have isinf() or isnan() functions, so we have
  52. # to provide our own.
  53. def isnan(val):
  54. # NaN is never equal to itself.
  55. return val != val
  56. def isinf(val):
  57. # Infinity times zero equals NaN.
  58. return not isnan(val) and isnan(val * 0)
  59. def IsPosInf(val):
  60. return isinf(val) and (val > 0)
  61. def IsNegInf(val):
  62. return isinf(val) and (val < 0)
  63. class MessageTest(basetest.TestCase):
  64. def testBadUtf8String(self):
  65. if api_implementation.Type() != 'python':
  66. self.skipTest("Skipping testBadUtf8String, currently only the python "
  67. "api implementation raises UnicodeDecodeError when a "
  68. "string field contains bad utf-8.")
  69. bad_utf8_data = test_util.GoldenFileData('bad_utf8_string')
  70. with self.assertRaises(UnicodeDecodeError) as context:
  71. unittest_pb2.TestAllTypes.FromString(bad_utf8_data)
  72. self.assertIn('field: protobuf_unittest.TestAllTypes.optional_string',
  73. str(context.exception))
  74. def testGoldenMessage(self):
  75. golden_data = test_util.GoldenFileData(
  76. 'golden_message_oneof_implemented')
  77. golden_message = unittest_pb2.TestAllTypes()
  78. golden_message.ParseFromString(golden_data)
  79. test_util.ExpectAllFieldsSet(self, golden_message)
  80. self.assertEqual(golden_data, golden_message.SerializeToString())
  81. golden_copy = copy.deepcopy(golden_message)
  82. self.assertEqual(golden_data, golden_copy.SerializeToString())
  83. def testGoldenExtensions(self):
  84. golden_data = test_util.GoldenFileData('golden_message')
  85. golden_message = unittest_pb2.TestAllExtensions()
  86. golden_message.ParseFromString(golden_data)
  87. all_set = unittest_pb2.TestAllExtensions()
  88. test_util.SetAllExtensions(all_set)
  89. self.assertEquals(all_set, golden_message)
  90. self.assertEqual(golden_data, golden_message.SerializeToString())
  91. golden_copy = copy.deepcopy(golden_message)
  92. self.assertEqual(golden_data, golden_copy.SerializeToString())
  93. def testGoldenPackedMessage(self):
  94. golden_data = test_util.GoldenFileData('golden_packed_fields_message')
  95. golden_message = unittest_pb2.TestPackedTypes()
  96. golden_message.ParseFromString(golden_data)
  97. all_set = unittest_pb2.TestPackedTypes()
  98. test_util.SetAllPackedFields(all_set)
  99. self.assertEquals(all_set, golden_message)
  100. self.assertEqual(golden_data, all_set.SerializeToString())
  101. golden_copy = copy.deepcopy(golden_message)
  102. self.assertEqual(golden_data, golden_copy.SerializeToString())
  103. def testGoldenPackedExtensions(self):
  104. golden_data = test_util.GoldenFileData('golden_packed_fields_message')
  105. golden_message = unittest_pb2.TestPackedExtensions()
  106. golden_message.ParseFromString(golden_data)
  107. all_set = unittest_pb2.TestPackedExtensions()
  108. test_util.SetAllPackedExtensions(all_set)
  109. self.assertEquals(all_set, golden_message)
  110. self.assertEqual(golden_data, all_set.SerializeToString())
  111. golden_copy = copy.deepcopy(golden_message)
  112. self.assertEqual(golden_data, golden_copy.SerializeToString())
  113. def testPickleSupport(self):
  114. golden_data = test_util.GoldenFileData('golden_message')
  115. golden_message = unittest_pb2.TestAllTypes()
  116. golden_message.ParseFromString(golden_data)
  117. pickled_message = pickle.dumps(golden_message)
  118. unpickled_message = pickle.loads(pickled_message)
  119. self.assertEquals(unpickled_message, golden_message)
  120. def testPickleIncompleteProto(self):
  121. golden_message = unittest_pb2.TestRequired(a=1)
  122. pickled_message = pickle.dumps(golden_message)
  123. unpickled_message = pickle.loads(pickled_message)
  124. self.assertEquals(unpickled_message, golden_message)
  125. self.assertEquals(unpickled_message.a, 1)
  126. # This is still an incomplete proto - so serializing should fail
  127. self.assertRaises(message.EncodeError, unpickled_message.SerializeToString)
  128. def testPositiveInfinity(self):
  129. golden_data = (b'\x5D\x00\x00\x80\x7F'
  130. b'\x61\x00\x00\x00\x00\x00\x00\xF0\x7F'
  131. b'\xCD\x02\x00\x00\x80\x7F'
  132. b'\xD1\x02\x00\x00\x00\x00\x00\x00\xF0\x7F')
  133. golden_message = unittest_pb2.TestAllTypes()
  134. golden_message.ParseFromString(golden_data)
  135. self.assertTrue(IsPosInf(golden_message.optional_float))
  136. self.assertTrue(IsPosInf(golden_message.optional_double))
  137. self.assertTrue(IsPosInf(golden_message.repeated_float[0]))
  138. self.assertTrue(IsPosInf(golden_message.repeated_double[0]))
  139. self.assertEqual(golden_data, golden_message.SerializeToString())
  140. def testNegativeInfinity(self):
  141. golden_data = (b'\x5D\x00\x00\x80\xFF'
  142. b'\x61\x00\x00\x00\x00\x00\x00\xF0\xFF'
  143. b'\xCD\x02\x00\x00\x80\xFF'
  144. b'\xD1\x02\x00\x00\x00\x00\x00\x00\xF0\xFF')
  145. golden_message = unittest_pb2.TestAllTypes()
  146. golden_message.ParseFromString(golden_data)
  147. self.assertTrue(IsNegInf(golden_message.optional_float))
  148. self.assertTrue(IsNegInf(golden_message.optional_double))
  149. self.assertTrue(IsNegInf(golden_message.repeated_float[0]))
  150. self.assertTrue(IsNegInf(golden_message.repeated_double[0]))
  151. self.assertEqual(golden_data, golden_message.SerializeToString())
  152. def testNotANumber(self):
  153. golden_data = (b'\x5D\x00\x00\xC0\x7F'
  154. b'\x61\x00\x00\x00\x00\x00\x00\xF8\x7F'
  155. b'\xCD\x02\x00\x00\xC0\x7F'
  156. b'\xD1\x02\x00\x00\x00\x00\x00\x00\xF8\x7F')
  157. golden_message = unittest_pb2.TestAllTypes()
  158. golden_message.ParseFromString(golden_data)
  159. self.assertTrue(isnan(golden_message.optional_float))
  160. self.assertTrue(isnan(golden_message.optional_double))
  161. self.assertTrue(isnan(golden_message.repeated_float[0]))
  162. self.assertTrue(isnan(golden_message.repeated_double[0]))
  163. # The protocol buffer may serialize to any one of multiple different
  164. # representations of a NaN. Rather than verify a specific representation,
  165. # verify the serialized string can be converted into a correctly
  166. # behaving protocol buffer.
  167. serialized = golden_message.SerializeToString()
  168. message = unittest_pb2.TestAllTypes()
  169. message.ParseFromString(serialized)
  170. self.assertTrue(isnan(message.optional_float))
  171. self.assertTrue(isnan(message.optional_double))
  172. self.assertTrue(isnan(message.repeated_float[0]))
  173. self.assertTrue(isnan(message.repeated_double[0]))
  174. def testPositiveInfinityPacked(self):
  175. golden_data = (b'\xA2\x06\x04\x00\x00\x80\x7F'
  176. b'\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF0\x7F')
  177. golden_message = unittest_pb2.TestPackedTypes()
  178. golden_message.ParseFromString(golden_data)
  179. self.assertTrue(IsPosInf(golden_message.packed_float[0]))
  180. self.assertTrue(IsPosInf(golden_message.packed_double[0]))
  181. self.assertEqual(golden_data, golden_message.SerializeToString())
  182. def testNegativeInfinityPacked(self):
  183. golden_data = (b'\xA2\x06\x04\x00\x00\x80\xFF'
  184. b'\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF0\xFF')
  185. golden_message = unittest_pb2.TestPackedTypes()
  186. golden_message.ParseFromString(golden_data)
  187. self.assertTrue(IsNegInf(golden_message.packed_float[0]))
  188. self.assertTrue(IsNegInf(golden_message.packed_double[0]))
  189. self.assertEqual(golden_data, golden_message.SerializeToString())
  190. def testNotANumberPacked(self):
  191. golden_data = (b'\xA2\x06\x04\x00\x00\xC0\x7F'
  192. b'\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF8\x7F')
  193. golden_message = unittest_pb2.TestPackedTypes()
  194. golden_message.ParseFromString(golden_data)
  195. self.assertTrue(isnan(golden_message.packed_float[0]))
  196. self.assertTrue(isnan(golden_message.packed_double[0]))
  197. serialized = golden_message.SerializeToString()
  198. message = unittest_pb2.TestPackedTypes()
  199. message.ParseFromString(serialized)
  200. self.assertTrue(isnan(message.packed_float[0]))
  201. self.assertTrue(isnan(message.packed_double[0]))
  202. def testExtremeFloatValues(self):
  203. message = unittest_pb2.TestAllTypes()
  204. # Most positive exponent, no significand bits set.
  205. kMostPosExponentNoSigBits = math.pow(2, 127)
  206. message.optional_float = kMostPosExponentNoSigBits
  207. message.ParseFromString(message.SerializeToString())
  208. self.assertTrue(message.optional_float == kMostPosExponentNoSigBits)
  209. # Most positive exponent, one significand bit set.
  210. kMostPosExponentOneSigBit = 1.5 * math.pow(2, 127)
  211. message.optional_float = kMostPosExponentOneSigBit
  212. message.ParseFromString(message.SerializeToString())
  213. self.assertTrue(message.optional_float == kMostPosExponentOneSigBit)
  214. # Repeat last two cases with values of same magnitude, but negative.
  215. message.optional_float = -kMostPosExponentNoSigBits
  216. message.ParseFromString(message.SerializeToString())
  217. self.assertTrue(message.optional_float == -kMostPosExponentNoSigBits)
  218. message.optional_float = -kMostPosExponentOneSigBit
  219. message.ParseFromString(message.SerializeToString())
  220. self.assertTrue(message.optional_float == -kMostPosExponentOneSigBit)
  221. # Most negative exponent, no significand bits set.
  222. kMostNegExponentNoSigBits = math.pow(2, -127)
  223. message.optional_float = kMostNegExponentNoSigBits
  224. message.ParseFromString(message.SerializeToString())
  225. self.assertTrue(message.optional_float == kMostNegExponentNoSigBits)
  226. # Most negative exponent, one significand bit set.
  227. kMostNegExponentOneSigBit = 1.5 * math.pow(2, -127)
  228. message.optional_float = kMostNegExponentOneSigBit
  229. message.ParseFromString(message.SerializeToString())
  230. self.assertTrue(message.optional_float == kMostNegExponentOneSigBit)
  231. # Repeat last two cases with values of the same magnitude, but negative.
  232. message.optional_float = -kMostNegExponentNoSigBits
  233. message.ParseFromString(message.SerializeToString())
  234. self.assertTrue(message.optional_float == -kMostNegExponentNoSigBits)
  235. message.optional_float = -kMostNegExponentOneSigBit
  236. message.ParseFromString(message.SerializeToString())
  237. self.assertTrue(message.optional_float == -kMostNegExponentOneSigBit)
  238. def testExtremeDoubleValues(self):
  239. message = unittest_pb2.TestAllTypes()
  240. # Most positive exponent, no significand bits set.
  241. kMostPosExponentNoSigBits = math.pow(2, 1023)
  242. message.optional_double = kMostPosExponentNoSigBits
  243. message.ParseFromString(message.SerializeToString())
  244. self.assertTrue(message.optional_double == kMostPosExponentNoSigBits)
  245. # Most positive exponent, one significand bit set.
  246. kMostPosExponentOneSigBit = 1.5 * math.pow(2, 1023)
  247. message.optional_double = kMostPosExponentOneSigBit
  248. message.ParseFromString(message.SerializeToString())
  249. self.assertTrue(message.optional_double == kMostPosExponentOneSigBit)
  250. # Repeat last two cases with values of same magnitude, but negative.
  251. message.optional_double = -kMostPosExponentNoSigBits
  252. message.ParseFromString(message.SerializeToString())
  253. self.assertTrue(message.optional_double == -kMostPosExponentNoSigBits)
  254. message.optional_double = -kMostPosExponentOneSigBit
  255. message.ParseFromString(message.SerializeToString())
  256. self.assertTrue(message.optional_double == -kMostPosExponentOneSigBit)
  257. # Most negative exponent, no significand bits set.
  258. kMostNegExponentNoSigBits = math.pow(2, -1023)
  259. message.optional_double = kMostNegExponentNoSigBits
  260. message.ParseFromString(message.SerializeToString())
  261. self.assertTrue(message.optional_double == kMostNegExponentNoSigBits)
  262. # Most negative exponent, one significand bit set.
  263. kMostNegExponentOneSigBit = 1.5 * math.pow(2, -1023)
  264. message.optional_double = kMostNegExponentOneSigBit
  265. message.ParseFromString(message.SerializeToString())
  266. self.assertTrue(message.optional_double == kMostNegExponentOneSigBit)
  267. # Repeat last two cases with values of the same magnitude, but negative.
  268. message.optional_double = -kMostNegExponentNoSigBits
  269. message.ParseFromString(message.SerializeToString())
  270. self.assertTrue(message.optional_double == -kMostNegExponentNoSigBits)
  271. message.optional_double = -kMostNegExponentOneSigBit
  272. message.ParseFromString(message.SerializeToString())
  273. self.assertTrue(message.optional_double == -kMostNegExponentOneSigBit)
  274. def testFloatPrinting(self):
  275. message = unittest_pb2.TestAllTypes()
  276. message.optional_float = 2.0
  277. self.assertEqual(str(message), 'optional_float: 2.0\n')
  278. def testHighPrecisionFloatPrinting(self):
  279. message = unittest_pb2.TestAllTypes()
  280. message.optional_double = 0.12345678912345678
  281. if sys.version_info.major >= 3:
  282. self.assertEqual(str(message), 'optional_double: 0.12345678912345678\n')
  283. else:
  284. self.assertEqual(str(message), 'optional_double: 0.123456789123\n')
  285. def testUnknownFieldPrinting(self):
  286. populated = unittest_pb2.TestAllTypes()
  287. test_util.SetAllNonLazyFields(populated)
  288. empty = unittest_pb2.TestEmptyMessage()
  289. empty.ParseFromString(populated.SerializeToString())
  290. self.assertEqual(str(empty), '')
  291. def testRepeatedNestedFieldIteration(self):
  292. msg = unittest_pb2.TestAllTypes()
  293. msg.repeated_nested_message.add(bb=1)
  294. msg.repeated_nested_message.add(bb=2)
  295. msg.repeated_nested_message.add(bb=3)
  296. msg.repeated_nested_message.add(bb=4)
  297. self.assertEquals([1, 2, 3, 4],
  298. [m.bb for m in msg.repeated_nested_message])
  299. self.assertEquals([4, 3, 2, 1],
  300. [m.bb for m in reversed(msg.repeated_nested_message)])
  301. self.assertEquals([4, 3, 2, 1],
  302. [m.bb for m in msg.repeated_nested_message[::-1]])
  303. def testSortingRepeatedScalarFieldsDefaultComparator(self):
  304. """Check some different types with the default comparator."""
  305. message = unittest_pb2.TestAllTypes()
  306. # TODO(mattp): would testing more scalar types strengthen test?
  307. message.repeated_int32.append(1)
  308. message.repeated_int32.append(3)
  309. message.repeated_int32.append(2)
  310. message.repeated_int32.sort()
  311. self.assertEqual(message.repeated_int32[0], 1)
  312. self.assertEqual(message.repeated_int32[1], 2)
  313. self.assertEqual(message.repeated_int32[2], 3)
  314. message.repeated_float.append(1.1)
  315. message.repeated_float.append(1.3)
  316. message.repeated_float.append(1.2)
  317. message.repeated_float.sort()
  318. self.assertAlmostEqual(message.repeated_float[0], 1.1)
  319. self.assertAlmostEqual(message.repeated_float[1], 1.2)
  320. self.assertAlmostEqual(message.repeated_float[2], 1.3)
  321. message.repeated_string.append('a')
  322. message.repeated_string.append('c')
  323. message.repeated_string.append('b')
  324. message.repeated_string.sort()
  325. self.assertEqual(message.repeated_string[0], 'a')
  326. self.assertEqual(message.repeated_string[1], 'b')
  327. self.assertEqual(message.repeated_string[2], 'c')
  328. message.repeated_bytes.append(b'a')
  329. message.repeated_bytes.append(b'c')
  330. message.repeated_bytes.append(b'b')
  331. message.repeated_bytes.sort()
  332. self.assertEqual(message.repeated_bytes[0], b'a')
  333. self.assertEqual(message.repeated_bytes[1], b'b')
  334. self.assertEqual(message.repeated_bytes[2], b'c')
  335. def testSortingRepeatedScalarFieldsCustomComparator(self):
  336. """Check some different types with custom comparator."""
  337. message = unittest_pb2.TestAllTypes()
  338. message.repeated_int32.append(-3)
  339. message.repeated_int32.append(-2)
  340. message.repeated_int32.append(-1)
  341. message.repeated_int32.sort(key=abs)
  342. self.assertEqual(message.repeated_int32[0], -1)
  343. self.assertEqual(message.repeated_int32[1], -2)
  344. self.assertEqual(message.repeated_int32[2], -3)
  345. message.repeated_string.append('aaa')
  346. message.repeated_string.append('bb')
  347. message.repeated_string.append('c')
  348. message.repeated_string.sort(key=len)
  349. self.assertEqual(message.repeated_string[0], 'c')
  350. self.assertEqual(message.repeated_string[1], 'bb')
  351. self.assertEqual(message.repeated_string[2], 'aaa')
  352. def testSortingRepeatedCompositeFieldsCustomComparator(self):
  353. """Check passing a custom comparator to sort a repeated composite field."""
  354. message = unittest_pb2.TestAllTypes()
  355. message.repeated_nested_message.add().bb = 1
  356. message.repeated_nested_message.add().bb = 3
  357. message.repeated_nested_message.add().bb = 2
  358. message.repeated_nested_message.add().bb = 6
  359. message.repeated_nested_message.add().bb = 5
  360. message.repeated_nested_message.add().bb = 4
  361. message.repeated_nested_message.sort(key=operator.attrgetter('bb'))
  362. self.assertEqual(message.repeated_nested_message[0].bb, 1)
  363. self.assertEqual(message.repeated_nested_message[1].bb, 2)
  364. self.assertEqual(message.repeated_nested_message[2].bb, 3)
  365. self.assertEqual(message.repeated_nested_message[3].bb, 4)
  366. self.assertEqual(message.repeated_nested_message[4].bb, 5)
  367. self.assertEqual(message.repeated_nested_message[5].bb, 6)
  368. def testRepeatedCompositeFieldSortArguments(self):
  369. """Check sorting a repeated composite field using list.sort() arguments."""
  370. message = unittest_pb2.TestAllTypes()
  371. get_bb = operator.attrgetter('bb')
  372. cmp_bb = lambda a, b: cmp(a.bb, b.bb)
  373. message.repeated_nested_message.add().bb = 1
  374. message.repeated_nested_message.add().bb = 3
  375. message.repeated_nested_message.add().bb = 2
  376. message.repeated_nested_message.add().bb = 6
  377. message.repeated_nested_message.add().bb = 5
  378. message.repeated_nested_message.add().bb = 4
  379. message.repeated_nested_message.sort(key=get_bb)
  380. self.assertEqual([k.bb for k in message.repeated_nested_message],
  381. [1, 2, 3, 4, 5, 6])
  382. message.repeated_nested_message.sort(key=get_bb, reverse=True)
  383. self.assertEqual([k.bb for k in message.repeated_nested_message],
  384. [6, 5, 4, 3, 2, 1])
  385. if sys.version_info.major >= 3: return # No cmp sorting in PY3.
  386. message.repeated_nested_message.sort(sort_function=cmp_bb)
  387. self.assertEqual([k.bb for k in message.repeated_nested_message],
  388. [1, 2, 3, 4, 5, 6])
  389. message.repeated_nested_message.sort(cmp=cmp_bb, reverse=True)
  390. self.assertEqual([k.bb for k in message.repeated_nested_message],
  391. [6, 5, 4, 3, 2, 1])
  392. def testRepeatedScalarFieldSortArguments(self):
  393. """Check sorting a scalar field using list.sort() arguments."""
  394. message = unittest_pb2.TestAllTypes()
  395. message.repeated_int32.append(-3)
  396. message.repeated_int32.append(-2)
  397. message.repeated_int32.append(-1)
  398. message.repeated_int32.sort(key=abs)
  399. self.assertEqual(list(message.repeated_int32), [-1, -2, -3])
  400. message.repeated_int32.sort(key=abs, reverse=True)
  401. self.assertEqual(list(message.repeated_int32), [-3, -2, -1])
  402. if sys.version_info.major < 3: # No cmp sorting in PY3.
  403. abs_cmp = lambda a, b: cmp(abs(a), abs(b))
  404. message.repeated_int32.sort(sort_function=abs_cmp)
  405. self.assertEqual(list(message.repeated_int32), [-1, -2, -3])
  406. message.repeated_int32.sort(cmp=abs_cmp, reverse=True)
  407. self.assertEqual(list(message.repeated_int32), [-3, -2, -1])
  408. message.repeated_string.append('aaa')
  409. message.repeated_string.append('bb')
  410. message.repeated_string.append('c')
  411. message.repeated_string.sort(key=len)
  412. self.assertEqual(list(message.repeated_string), ['c', 'bb', 'aaa'])
  413. message.repeated_string.sort(key=len, reverse=True)
  414. self.assertEqual(list(message.repeated_string), ['aaa', 'bb', 'c'])
  415. if sys.version_info.major < 3: # No cmp sorting in PY3.
  416. len_cmp = lambda a, b: cmp(len(a), len(b))
  417. message.repeated_string.sort(sort_function=len_cmp)
  418. self.assertEqual(list(message.repeated_string), ['c', 'bb', 'aaa'])
  419. message.repeated_string.sort(cmp=len_cmp, reverse=True)
  420. self.assertEqual(list(message.repeated_string), ['aaa', 'bb', 'c'])
  421. def testRepeatedFieldsComparable(self):
  422. m1 = unittest_pb2.TestAllTypes()
  423. m2 = unittest_pb2.TestAllTypes()
  424. m1.repeated_int32.append(0)
  425. m1.repeated_int32.append(1)
  426. m1.repeated_int32.append(2)
  427. m2.repeated_int32.append(0)
  428. m2.repeated_int32.append(1)
  429. m2.repeated_int32.append(2)
  430. m1.repeated_nested_message.add().bb = 1
  431. m1.repeated_nested_message.add().bb = 2
  432. m1.repeated_nested_message.add().bb = 3
  433. m2.repeated_nested_message.add().bb = 1
  434. m2.repeated_nested_message.add().bb = 2
  435. m2.repeated_nested_message.add().bb = 3
  436. if sys.version_info.major >= 3: return # No cmp() in PY3.
  437. # These comparisons should not raise errors.
  438. _ = m1 < m2
  439. _ = m1.repeated_nested_message < m2.repeated_nested_message
  440. # Make sure cmp always works. If it wasn't defined, these would be
  441. # id() comparisons and would all fail.
  442. self.assertEqual(cmp(m1, m2), 0)
  443. self.assertEqual(cmp(m1.repeated_int32, m2.repeated_int32), 0)
  444. self.assertEqual(cmp(m1.repeated_int32, [0, 1, 2]), 0)
  445. self.assertEqual(cmp(m1.repeated_nested_message,
  446. m2.repeated_nested_message), 0)
  447. with self.assertRaises(TypeError):
  448. # Can't compare repeated composite containers to lists.
  449. cmp(m1.repeated_nested_message, m2.repeated_nested_message[:])
  450. # TODO(anuraag): Implement extensiondict comparison in C++ and then add test
  451. def testParsingMerge(self):
  452. """Check the merge behavior when a required or optional field appears
  453. multiple times in the input."""
  454. messages = [
  455. unittest_pb2.TestAllTypes(),
  456. unittest_pb2.TestAllTypes(),
  457. unittest_pb2.TestAllTypes() ]
  458. messages[0].optional_int32 = 1
  459. messages[1].optional_int64 = 2
  460. messages[2].optional_int32 = 3
  461. messages[2].optional_string = 'hello'
  462. merged_message = unittest_pb2.TestAllTypes()
  463. merged_message.optional_int32 = 3
  464. merged_message.optional_int64 = 2
  465. merged_message.optional_string = 'hello'
  466. generator = unittest_pb2.TestParsingMerge.RepeatedFieldsGenerator()
  467. generator.field1.extend(messages)
  468. generator.field2.extend(messages)
  469. generator.field3.extend(messages)
  470. generator.ext1.extend(messages)
  471. generator.ext2.extend(messages)
  472. generator.group1.add().field1.MergeFrom(messages[0])
  473. generator.group1.add().field1.MergeFrom(messages[1])
  474. generator.group1.add().field1.MergeFrom(messages[2])
  475. generator.group2.add().field1.MergeFrom(messages[0])
  476. generator.group2.add().field1.MergeFrom(messages[1])
  477. generator.group2.add().field1.MergeFrom(messages[2])
  478. data = generator.SerializeToString()
  479. parsing_merge = unittest_pb2.TestParsingMerge()
  480. parsing_merge.ParseFromString(data)
  481. # Required and optional fields should be merged.
  482. self.assertEqual(parsing_merge.required_all_types, merged_message)
  483. self.assertEqual(parsing_merge.optional_all_types, merged_message)
  484. self.assertEqual(parsing_merge.optionalgroup.optional_group_all_types,
  485. merged_message)
  486. self.assertEqual(parsing_merge.Extensions[
  487. unittest_pb2.TestParsingMerge.optional_ext],
  488. merged_message)
  489. # Repeated fields should not be merged.
  490. self.assertEqual(len(parsing_merge.repeated_all_types), 3)
  491. self.assertEqual(len(parsing_merge.repeatedgroup), 3)
  492. self.assertEqual(len(parsing_merge.Extensions[
  493. unittest_pb2.TestParsingMerge.repeated_ext]), 3)
  494. def ensureNestedMessageExists(self, msg, attribute):
  495. """Make sure that a nested message object exists.
  496. As soon as a nested message attribute is accessed, it will be present in the
  497. _fields dict, without being marked as actually being set.
  498. """
  499. getattr(msg, attribute)
  500. self.assertFalse(msg.HasField(attribute))
  501. def testOneofGetCaseNonexistingField(self):
  502. m = unittest_pb2.TestAllTypes()
  503. self.assertRaises(ValueError, m.WhichOneof, 'no_such_oneof_field')
  504. def testOneofSemantics(self):
  505. m = unittest_pb2.TestAllTypes()
  506. self.assertIs(None, m.WhichOneof('oneof_field'))
  507. m.oneof_uint32 = 11
  508. self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field'))
  509. self.assertTrue(m.HasField('oneof_uint32'))
  510. m.oneof_string = u'foo'
  511. self.assertEqual('oneof_string', m.WhichOneof('oneof_field'))
  512. self.assertFalse(m.HasField('oneof_uint32'))
  513. self.assertTrue(m.HasField('oneof_string'))
  514. m.oneof_nested_message.bb = 11
  515. self.assertEqual('oneof_nested_message', m.WhichOneof('oneof_field'))
  516. self.assertFalse(m.HasField('oneof_string'))
  517. self.assertTrue(m.HasField('oneof_nested_message'))
  518. m.oneof_bytes = b'bb'
  519. self.assertEqual('oneof_bytes', m.WhichOneof('oneof_field'))
  520. self.assertFalse(m.HasField('oneof_nested_message'))
  521. self.assertTrue(m.HasField('oneof_bytes'))
  522. def testOneofCompositeFieldReadAccess(self):
  523. m = unittest_pb2.TestAllTypes()
  524. m.oneof_uint32 = 11
  525. self.ensureNestedMessageExists(m, 'oneof_nested_message')
  526. self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field'))
  527. self.assertEqual(11, m.oneof_uint32)
  528. def testOneofHasField(self):
  529. m = unittest_pb2.TestAllTypes()
  530. self.assertFalse(m.HasField('oneof_field'))
  531. m.oneof_uint32 = 11
  532. self.assertTrue(m.HasField('oneof_field'))
  533. m.oneof_bytes = b'bb'
  534. self.assertTrue(m.HasField('oneof_field'))
  535. m.ClearField('oneof_bytes')
  536. self.assertFalse(m.HasField('oneof_field'))
  537. def testOneofClearField(self):
  538. m = unittest_pb2.TestAllTypes()
  539. m.oneof_uint32 = 11
  540. m.ClearField('oneof_field')
  541. self.assertFalse(m.HasField('oneof_field'))
  542. self.assertFalse(m.HasField('oneof_uint32'))
  543. self.assertIs(None, m.WhichOneof('oneof_field'))
  544. def testOneofClearSetField(self):
  545. m = unittest_pb2.TestAllTypes()
  546. m.oneof_uint32 = 11
  547. m.ClearField('oneof_uint32')
  548. self.assertFalse(m.HasField('oneof_field'))
  549. self.assertFalse(m.HasField('oneof_uint32'))
  550. self.assertIs(None, m.WhichOneof('oneof_field'))
  551. def testOneofClearUnsetField(self):
  552. m = unittest_pb2.TestAllTypes()
  553. m.oneof_uint32 = 11
  554. self.ensureNestedMessageExists(m, 'oneof_nested_message')
  555. m.ClearField('oneof_nested_message')
  556. self.assertEqual(11, m.oneof_uint32)
  557. self.assertTrue(m.HasField('oneof_field'))
  558. self.assertTrue(m.HasField('oneof_uint32'))
  559. self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field'))
  560. def testOneofDeserialize(self):
  561. m = unittest_pb2.TestAllTypes()
  562. m.oneof_uint32 = 11
  563. m2 = unittest_pb2.TestAllTypes()
  564. m2.ParseFromString(m.SerializeToString())
  565. self.assertEqual('oneof_uint32', m2.WhichOneof('oneof_field'))
  566. def testOneofCopyFrom(self):
  567. m = unittest_pb2.TestAllTypes()
  568. m.oneof_uint32 = 11
  569. m2 = unittest_pb2.TestAllTypes()
  570. m2.CopyFrom(m)
  571. self.assertEqual('oneof_uint32', m2.WhichOneof('oneof_field'))
  572. def testOneofNestedMergeFrom(self):
  573. m = unittest_pb2.NestedTestAllTypes()
  574. m.payload.oneof_uint32 = 11
  575. m2 = unittest_pb2.NestedTestAllTypes()
  576. m2.payload.oneof_bytes = b'bb'
  577. m2.child.payload.oneof_bytes = b'bb'
  578. m2.MergeFrom(m)
  579. self.assertEqual('oneof_uint32', m2.payload.WhichOneof('oneof_field'))
  580. self.assertEqual('oneof_bytes', m2.child.payload.WhichOneof('oneof_field'))
  581. def testOneofClear(self):
  582. m = unittest_pb2.TestAllTypes()
  583. m.oneof_uint32 = 11
  584. m.Clear()
  585. self.assertIsNone(m.WhichOneof('oneof_field'))
  586. m.oneof_bytes = b'bb'
  587. self.assertTrue(m.HasField('oneof_field'))
  588. def testSortEmptyRepeatedCompositeContainer(self):
  589. """Exercise a scenario that has led to segfaults in the past.
  590. """
  591. m = unittest_pb2.TestAllTypes()
  592. m.repeated_nested_message.sort()
  593. def testHasFieldOnRepeatedField(self):
  594. """Using HasField on a repeated field should raise an exception.
  595. """
  596. m = unittest_pb2.TestAllTypes()
  597. with self.assertRaises(ValueError) as _:
  598. m.HasField('repeated_int32')
  599. class ValidTypeNamesTest(basetest.TestCase):
  600. def assertImportFromName(self, msg, base_name):
  601. # Parse <type 'module.class_name'> to extra 'some.name' as a string.
  602. tp_name = str(type(msg)).split("'")[1]
  603. valid_names = ('Repeated%sContainer' % base_name,
  604. 'Repeated%sFieldContainer' % base_name)
  605. self.assertTrue(any(tp_name.endswith(v) for v in valid_names),
  606. '%r does end with any of %r' % (tp_name, valid_names))
  607. parts = tp_name.split('.')
  608. class_name = parts[-1]
  609. module_name = '.'.join(parts[:-1])
  610. __import__(module_name, fromlist=[class_name])
  611. def testTypeNamesCanBeImported(self):
  612. # If import doesn't work, pickling won't work either.
  613. pb = unittest_pb2.TestAllTypes()
  614. self.assertImportFromName(pb.repeated_int32, 'Scalar')
  615. self.assertImportFromName(pb.repeated_nested_message, 'Composite')
  616. if __name__ == '__main__':
  617. basetest.main()