blob: ed1298af7defb489a08ea1c112180b25883873e7 [file] [log] [blame]
kenton@google.com80b1d622009-07-29 01:13:20 +00001#! /usr/bin/python
2#
3# Protocol Buffers - Google's data interchange format
4# Copyright 2008 Google Inc. All rights reserved.
Feng Xiaoe4288622014-10-01 16:26:23 -07005# https://developers.google.com/protocol-buffers/
kenton@google.com80b1d622009-07-29 01:13:20 +00006#
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
kenton@google.comfccb1462009-12-18 02:11:36 +000033"""Tests python protocol buffers against the golden message.
34
35Note that the golden messages exercise every known field type, thus this
36test ends up exercising and verifying nearly all of the parsing and
37serialization code in the whole library.
38
39TODO(kenton): Merge with wire_format_test? It doesn't make a whole lot of
40sense to call this a test of the "message" module, which only declares an
41abstract interface.
42"""
kenton@google.com80b1d622009-07-29 01:13:20 +000043
44__author__ = 'gps@google.com (Gregory P. Smith)'
45
liujisi@google.com33165fe2010-11-02 13:14:58 +000046import copy
47import math
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000048import operator
49import pickle
jieluo@google.combde4a322014-08-12 21:10:30 +000050import sys
Jisi Liuada65562015-02-25 16:39:11 -080051import unittest
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000052
jieluo@google.combde4a322014-08-12 21:10:30 +000053from google.apputils import basetest
Jisi Liu885b6122015-02-28 14:51:22 -080054from google.protobuf.internal import _parameterized
kenton@google.com80b1d622009-07-29 01:13:20 +000055from google.protobuf import unittest_pb2
Jisi Liuada65562015-02-25 16:39:11 -080056from google.protobuf import unittest_proto3_arena_pb2
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000057from google.protobuf.internal import api_implementation
kenton@google.com80b1d622009-07-29 01:13:20 +000058from google.protobuf.internal import test_util
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000059from google.protobuf import message
kenton@google.com80b1d622009-07-29 01:13:20 +000060
liujisi@google.com33165fe2010-11-02 13:14:58 +000061# Python pre-2.6 does not have isinf() or isnan() functions, so we have
62# to provide our own.
63def isnan(val):
64 # NaN is never equal to itself.
65 return val != val
66def isinf(val):
67 # Infinity times zero equals NaN.
68 return not isnan(val) and isnan(val * 0)
69def IsPosInf(val):
70 return isinf(val) and (val > 0)
71def IsNegInf(val):
72 return isinf(val) and (val < 0)
kenton@google.com80b1d622009-07-29 01:13:20 +000073
jieluo@google.combde4a322014-08-12 21:10:30 +000074
Josh Haberman0b70a432015-02-25 20:17:32 -080075@_parameterized.Parameters(
Jisi Liuada65562015-02-25 16:39:11 -080076 (unittest_pb2),
77 (unittest_proto3_arena_pb2))
jieluo@google.combde4a322014-08-12 21:10:30 +000078class MessageTest(basetest.TestCase):
79
Jisi Liuada65562015-02-25 16:39:11 -080080 def testBadUtf8String(self, message_module):
jieluo@google.combde4a322014-08-12 21:10:30 +000081 if api_implementation.Type() != 'python':
82 self.skipTest("Skipping testBadUtf8String, currently only the python "
83 "api implementation raises UnicodeDecodeError when a "
84 "string field contains bad utf-8.")
85 bad_utf8_data = test_util.GoldenFileData('bad_utf8_string')
86 with self.assertRaises(UnicodeDecodeError) as context:
Jisi Liuada65562015-02-25 16:39:11 -080087 message_module.TestAllTypes.FromString(bad_utf8_data)
88 self.assertIn('TestAllTypes.optional_string', str(context.exception))
kenton@google.com80b1d622009-07-29 01:13:20 +000089
Jisi Liuada65562015-02-25 16:39:11 -080090 def testGoldenMessage(self, message_module):
91 # Proto3 doesn't have the "default_foo" members or foreign enums,
92 # and doesn't preserve unknown fields, so for proto3 we use a golden
93 # message that doesn't have these fields set.
94 if message_module is unittest_pb2:
95 golden_data = test_util.GoldenFileData(
96 'golden_message_oneof_implemented')
97 else:
98 golden_data = test_util.GoldenFileData('golden_message_proto3')
99
100 golden_message = message_module.TestAllTypes()
kenton@google.com80b1d622009-07-29 01:13:20 +0000101 golden_message.ParseFromString(golden_data)
Jisi Liuada65562015-02-25 16:39:11 -0800102 if message_module is unittest_pb2:
103 test_util.ExpectAllFieldsSet(self, golden_message)
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000104 self.assertEqual(golden_data, golden_message.SerializeToString())
liujisi@google.com33165fe2010-11-02 13:14:58 +0000105 golden_copy = copy.deepcopy(golden_message)
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000106 self.assertEqual(golden_data, golden_copy.SerializeToString())
kenton@google.com80b1d622009-07-29 01:13:20 +0000107
Jisi Liuada65562015-02-25 16:39:11 -0800108 def testGoldenPackedMessage(self, message_module):
jieluo@google.combde4a322014-08-12 21:10:30 +0000109 golden_data = test_util.GoldenFileData('golden_packed_fields_message')
Jisi Liuada65562015-02-25 16:39:11 -0800110 golden_message = message_module.TestPackedTypes()
kenton@google.comfccb1462009-12-18 02:11:36 +0000111 golden_message.ParseFromString(golden_data)
Jisi Liuada65562015-02-25 16:39:11 -0800112 all_set = message_module.TestPackedTypes()
kenton@google.comfccb1462009-12-18 02:11:36 +0000113 test_util.SetAllPackedFields(all_set)
Jisi Liuada65562015-02-25 16:39:11 -0800114 self.assertEqual(all_set, golden_message)
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000115 self.assertEqual(golden_data, all_set.SerializeToString())
liujisi@google.com33165fe2010-11-02 13:14:58 +0000116 golden_copy = copy.deepcopy(golden_message)
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000117 self.assertEqual(golden_data, golden_copy.SerializeToString())
kenton@google.comfccb1462009-12-18 02:11:36 +0000118
Jisi Liuada65562015-02-25 16:39:11 -0800119 def testPickleSupport(self, message_module):
jieluo@google.combde4a322014-08-12 21:10:30 +0000120 golden_data = test_util.GoldenFileData('golden_message')
Jisi Liuada65562015-02-25 16:39:11 -0800121 golden_message = message_module.TestAllTypes()
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000122 golden_message.ParseFromString(golden_data)
123 pickled_message = pickle.dumps(golden_message)
124
125 unpickled_message = pickle.loads(pickled_message)
Jisi Liuada65562015-02-25 16:39:11 -0800126 self.assertEqual(unpickled_message, golden_message)
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000127
Jisi Liuada65562015-02-25 16:39:11 -0800128 def testPositiveInfinity(self, message_module):
jieluo@google.combde4a322014-08-12 21:10:30 +0000129 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')
Jisi Liuada65562015-02-25 16:39:11 -0800133 golden_message = message_module.TestAllTypes()
liujisi@google.com33165fe2010-11-02 13:14:58 +0000134 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]))
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000139 self.assertEqual(golden_data, golden_message.SerializeToString())
liujisi@google.com33165fe2010-11-02 13:14:58 +0000140
Jisi Liuada65562015-02-25 16:39:11 -0800141 def testNegativeInfinity(self, message_module):
jieluo@google.combde4a322014-08-12 21:10:30 +0000142 golden_data = (b'\x5D\x00\x00\x80\xFF'
143 b'\x61\x00\x00\x00\x00\x00\x00\xF0\xFF'
144 b'\xCD\x02\x00\x00\x80\xFF'
145 b'\xD1\x02\x00\x00\x00\x00\x00\x00\xF0\xFF')
Jisi Liuada65562015-02-25 16:39:11 -0800146 golden_message = message_module.TestAllTypes()
liujisi@google.com33165fe2010-11-02 13:14:58 +0000147 golden_message.ParseFromString(golden_data)
148 self.assertTrue(IsNegInf(golden_message.optional_float))
149 self.assertTrue(IsNegInf(golden_message.optional_double))
150 self.assertTrue(IsNegInf(golden_message.repeated_float[0]))
151 self.assertTrue(IsNegInf(golden_message.repeated_double[0]))
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000152 self.assertEqual(golden_data, golden_message.SerializeToString())
liujisi@google.com33165fe2010-11-02 13:14:58 +0000153
Jisi Liuada65562015-02-25 16:39:11 -0800154 def testNotANumber(self, message_module):
jieluo@google.combde4a322014-08-12 21:10:30 +0000155 golden_data = (b'\x5D\x00\x00\xC0\x7F'
156 b'\x61\x00\x00\x00\x00\x00\x00\xF8\x7F'
157 b'\xCD\x02\x00\x00\xC0\x7F'
158 b'\xD1\x02\x00\x00\x00\x00\x00\x00\xF8\x7F')
Jisi Liuada65562015-02-25 16:39:11 -0800159 golden_message = message_module.TestAllTypes()
liujisi@google.com33165fe2010-11-02 13:14:58 +0000160 golden_message.ParseFromString(golden_data)
161 self.assertTrue(isnan(golden_message.optional_float))
162 self.assertTrue(isnan(golden_message.optional_double))
163 self.assertTrue(isnan(golden_message.repeated_float[0]))
164 self.assertTrue(isnan(golden_message.repeated_double[0]))
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000165
166 # The protocol buffer may serialize to any one of multiple different
167 # representations of a NaN. Rather than verify a specific representation,
168 # verify the serialized string can be converted into a correctly
169 # behaving protocol buffer.
170 serialized = golden_message.SerializeToString()
Jisi Liuada65562015-02-25 16:39:11 -0800171 message = message_module.TestAllTypes()
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000172 message.ParseFromString(serialized)
173 self.assertTrue(isnan(message.optional_float))
174 self.assertTrue(isnan(message.optional_double))
175 self.assertTrue(isnan(message.repeated_float[0]))
176 self.assertTrue(isnan(message.repeated_double[0]))
liujisi@google.com33165fe2010-11-02 13:14:58 +0000177
Jisi Liuada65562015-02-25 16:39:11 -0800178 def testPositiveInfinityPacked(self, message_module):
jieluo@google.combde4a322014-08-12 21:10:30 +0000179 golden_data = (b'\xA2\x06\x04\x00\x00\x80\x7F'
180 b'\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF0\x7F')
Jisi Liuada65562015-02-25 16:39:11 -0800181 golden_message = message_module.TestPackedTypes()
liujisi@google.com33165fe2010-11-02 13:14:58 +0000182 golden_message.ParseFromString(golden_data)
183 self.assertTrue(IsPosInf(golden_message.packed_float[0]))
184 self.assertTrue(IsPosInf(golden_message.packed_double[0]))
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000185 self.assertEqual(golden_data, golden_message.SerializeToString())
liujisi@google.com33165fe2010-11-02 13:14:58 +0000186
Jisi Liuada65562015-02-25 16:39:11 -0800187 def testNegativeInfinityPacked(self, message_module):
jieluo@google.combde4a322014-08-12 21:10:30 +0000188 golden_data = (b'\xA2\x06\x04\x00\x00\x80\xFF'
189 b'\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF0\xFF')
Jisi Liuada65562015-02-25 16:39:11 -0800190 golden_message = message_module.TestPackedTypes()
liujisi@google.com33165fe2010-11-02 13:14:58 +0000191 golden_message.ParseFromString(golden_data)
192 self.assertTrue(IsNegInf(golden_message.packed_float[0]))
193 self.assertTrue(IsNegInf(golden_message.packed_double[0]))
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000194 self.assertEqual(golden_data, golden_message.SerializeToString())
liujisi@google.com33165fe2010-11-02 13:14:58 +0000195
Jisi Liuada65562015-02-25 16:39:11 -0800196 def testNotANumberPacked(self, message_module):
jieluo@google.combde4a322014-08-12 21:10:30 +0000197 golden_data = (b'\xA2\x06\x04\x00\x00\xC0\x7F'
198 b'\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF8\x7F')
Jisi Liuada65562015-02-25 16:39:11 -0800199 golden_message = message_module.TestPackedTypes()
liujisi@google.com33165fe2010-11-02 13:14:58 +0000200 golden_message.ParseFromString(golden_data)
201 self.assertTrue(isnan(golden_message.packed_float[0]))
202 self.assertTrue(isnan(golden_message.packed_double[0]))
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000203
204 serialized = golden_message.SerializeToString()
Jisi Liuada65562015-02-25 16:39:11 -0800205 message = message_module.TestPackedTypes()
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000206 message.ParseFromString(serialized)
207 self.assertTrue(isnan(message.packed_float[0]))
208 self.assertTrue(isnan(message.packed_double[0]))
liujisi@google.com33165fe2010-11-02 13:14:58 +0000209
Jisi Liuada65562015-02-25 16:39:11 -0800210 def testExtremeFloatValues(self, message_module):
211 message = message_module.TestAllTypes()
liujisi@google.com33165fe2010-11-02 13:14:58 +0000212
213 # Most positive exponent, no significand bits set.
214 kMostPosExponentNoSigBits = math.pow(2, 127)
215 message.optional_float = kMostPosExponentNoSigBits
216 message.ParseFromString(message.SerializeToString())
217 self.assertTrue(message.optional_float == kMostPosExponentNoSigBits)
218
219 # Most positive exponent, one significand bit set.
220 kMostPosExponentOneSigBit = 1.5 * math.pow(2, 127)
221 message.optional_float = kMostPosExponentOneSigBit
222 message.ParseFromString(message.SerializeToString())
223 self.assertTrue(message.optional_float == kMostPosExponentOneSigBit)
224
225 # Repeat last two cases with values of same magnitude, but negative.
226 message.optional_float = -kMostPosExponentNoSigBits
227 message.ParseFromString(message.SerializeToString())
228 self.assertTrue(message.optional_float == -kMostPosExponentNoSigBits)
229
230 message.optional_float = -kMostPosExponentOneSigBit
231 message.ParseFromString(message.SerializeToString())
232 self.assertTrue(message.optional_float == -kMostPosExponentOneSigBit)
233
234 # Most negative exponent, no significand bits set.
235 kMostNegExponentNoSigBits = math.pow(2, -127)
236 message.optional_float = kMostNegExponentNoSigBits
237 message.ParseFromString(message.SerializeToString())
238 self.assertTrue(message.optional_float == kMostNegExponentNoSigBits)
239
240 # Most negative exponent, one significand bit set.
241 kMostNegExponentOneSigBit = 1.5 * math.pow(2, -127)
242 message.optional_float = kMostNegExponentOneSigBit
243 message.ParseFromString(message.SerializeToString())
244 self.assertTrue(message.optional_float == kMostNegExponentOneSigBit)
245
246 # Repeat last two cases with values of the same magnitude, but negative.
247 message.optional_float = -kMostNegExponentNoSigBits
248 message.ParseFromString(message.SerializeToString())
249 self.assertTrue(message.optional_float == -kMostNegExponentNoSigBits)
250
251 message.optional_float = -kMostNegExponentOneSigBit
252 message.ParseFromString(message.SerializeToString())
253 self.assertTrue(message.optional_float == -kMostNegExponentOneSigBit)
254
Jisi Liuada65562015-02-25 16:39:11 -0800255 def testExtremeDoubleValues(self, message_module):
256 message = message_module.TestAllTypes()
liujisi@google.com33165fe2010-11-02 13:14:58 +0000257
258 # Most positive exponent, no significand bits set.
259 kMostPosExponentNoSigBits = math.pow(2, 1023)
260 message.optional_double = kMostPosExponentNoSigBits
261 message.ParseFromString(message.SerializeToString())
262 self.assertTrue(message.optional_double == kMostPosExponentNoSigBits)
263
264 # Most positive exponent, one significand bit set.
265 kMostPosExponentOneSigBit = 1.5 * math.pow(2, 1023)
266 message.optional_double = kMostPosExponentOneSigBit
267 message.ParseFromString(message.SerializeToString())
268 self.assertTrue(message.optional_double == kMostPosExponentOneSigBit)
269
270 # Repeat last two cases with values of same magnitude, but negative.
271 message.optional_double = -kMostPosExponentNoSigBits
272 message.ParseFromString(message.SerializeToString())
273 self.assertTrue(message.optional_double == -kMostPosExponentNoSigBits)
274
275 message.optional_double = -kMostPosExponentOneSigBit
276 message.ParseFromString(message.SerializeToString())
277 self.assertTrue(message.optional_double == -kMostPosExponentOneSigBit)
278
279 # Most negative exponent, no significand bits set.
280 kMostNegExponentNoSigBits = math.pow(2, -1023)
281 message.optional_double = kMostNegExponentNoSigBits
282 message.ParseFromString(message.SerializeToString())
283 self.assertTrue(message.optional_double == kMostNegExponentNoSigBits)
284
285 # Most negative exponent, one significand bit set.
286 kMostNegExponentOneSigBit = 1.5 * math.pow(2, -1023)
287 message.optional_double = kMostNegExponentOneSigBit
288 message.ParseFromString(message.SerializeToString())
289 self.assertTrue(message.optional_double == kMostNegExponentOneSigBit)
290
291 # Repeat last two cases with values of the same magnitude, but negative.
292 message.optional_double = -kMostNegExponentNoSigBits
293 message.ParseFromString(message.SerializeToString())
294 self.assertTrue(message.optional_double == -kMostNegExponentNoSigBits)
295
296 message.optional_double = -kMostNegExponentOneSigBit
297 message.ParseFromString(message.SerializeToString())
298 self.assertTrue(message.optional_double == -kMostNegExponentOneSigBit)
299
Jisi Liuada65562015-02-25 16:39:11 -0800300 def testFloatPrinting(self, message_module):
301 message = message_module.TestAllTypes()
jieluo@google.combde4a322014-08-12 21:10:30 +0000302 message.optional_float = 2.0
303 self.assertEqual(str(message), 'optional_float: 2.0\n')
304
Jisi Liuada65562015-02-25 16:39:11 -0800305 def testHighPrecisionFloatPrinting(self, message_module):
306 message = message_module.TestAllTypes()
jieluo@google.combde4a322014-08-12 21:10:30 +0000307 message.optional_double = 0.12345678912345678
308 if sys.version_info.major >= 3:
309 self.assertEqual(str(message), 'optional_double: 0.12345678912345678\n')
310 else:
311 self.assertEqual(str(message), 'optional_double: 0.123456789123\n')
312
Jisi Liuada65562015-02-25 16:39:11 -0800313 def testUnknownFieldPrinting(self, message_module):
314 populated = message_module.TestAllTypes()
jieluo@google.combde4a322014-08-12 21:10:30 +0000315 test_util.SetAllNonLazyFields(populated)
Jisi Liuada65562015-02-25 16:39:11 -0800316 empty = message_module.TestEmptyMessage()
jieluo@google.combde4a322014-08-12 21:10:30 +0000317 empty.ParseFromString(populated.SerializeToString())
318 self.assertEqual(str(empty), '')
319
Jisi Liuada65562015-02-25 16:39:11 -0800320 def testRepeatedNestedFieldIteration(self, message_module):
321 msg = message_module.TestAllTypes()
Feng Xiao6ef984a2014-11-10 17:34:54 -0800322 msg.repeated_nested_message.add(bb=1)
323 msg.repeated_nested_message.add(bb=2)
324 msg.repeated_nested_message.add(bb=3)
325 msg.repeated_nested_message.add(bb=4)
326
Jisi Liuada65562015-02-25 16:39:11 -0800327 self.assertEqual([1, 2, 3, 4],
328 [m.bb for m in msg.repeated_nested_message])
329 self.assertEqual([4, 3, 2, 1],
330 [m.bb for m in reversed(msg.repeated_nested_message)])
331 self.assertEqual([4, 3, 2, 1],
332 [m.bb for m in msg.repeated_nested_message[::-1]])
Feng Xiao6ef984a2014-11-10 17:34:54 -0800333
Jisi Liuada65562015-02-25 16:39:11 -0800334 def testSortingRepeatedScalarFieldsDefaultComparator(self, message_module):
liujisi@google.com33165fe2010-11-02 13:14:58 +0000335 """Check some different types with the default comparator."""
Jisi Liuada65562015-02-25 16:39:11 -0800336 message = message_module.TestAllTypes()
liujisi@google.com33165fe2010-11-02 13:14:58 +0000337
338 # TODO(mattp): would testing more scalar types strengthen test?
339 message.repeated_int32.append(1)
340 message.repeated_int32.append(3)
341 message.repeated_int32.append(2)
342 message.repeated_int32.sort()
343 self.assertEqual(message.repeated_int32[0], 1)
344 self.assertEqual(message.repeated_int32[1], 2)
345 self.assertEqual(message.repeated_int32[2], 3)
346
347 message.repeated_float.append(1.1)
348 message.repeated_float.append(1.3)
349 message.repeated_float.append(1.2)
350 message.repeated_float.sort()
351 self.assertAlmostEqual(message.repeated_float[0], 1.1)
352 self.assertAlmostEqual(message.repeated_float[1], 1.2)
353 self.assertAlmostEqual(message.repeated_float[2], 1.3)
354
355 message.repeated_string.append('a')
356 message.repeated_string.append('c')
357 message.repeated_string.append('b')
358 message.repeated_string.sort()
359 self.assertEqual(message.repeated_string[0], 'a')
360 self.assertEqual(message.repeated_string[1], 'b')
361 self.assertEqual(message.repeated_string[2], 'c')
362
jieluo@google.combde4a322014-08-12 21:10:30 +0000363 message.repeated_bytes.append(b'a')
364 message.repeated_bytes.append(b'c')
365 message.repeated_bytes.append(b'b')
liujisi@google.com33165fe2010-11-02 13:14:58 +0000366 message.repeated_bytes.sort()
jieluo@google.combde4a322014-08-12 21:10:30 +0000367 self.assertEqual(message.repeated_bytes[0], b'a')
368 self.assertEqual(message.repeated_bytes[1], b'b')
369 self.assertEqual(message.repeated_bytes[2], b'c')
liujisi@google.com33165fe2010-11-02 13:14:58 +0000370
Jisi Liuada65562015-02-25 16:39:11 -0800371 def testSortingRepeatedScalarFieldsCustomComparator(self, message_module):
liujisi@google.com33165fe2010-11-02 13:14:58 +0000372 """Check some different types with custom comparator."""
Jisi Liuada65562015-02-25 16:39:11 -0800373 message = message_module.TestAllTypes()
liujisi@google.com33165fe2010-11-02 13:14:58 +0000374
375 message.repeated_int32.append(-3)
376 message.repeated_int32.append(-2)
377 message.repeated_int32.append(-1)
jieluo@google.combde4a322014-08-12 21:10:30 +0000378 message.repeated_int32.sort(key=abs)
liujisi@google.com33165fe2010-11-02 13:14:58 +0000379 self.assertEqual(message.repeated_int32[0], -1)
380 self.assertEqual(message.repeated_int32[1], -2)
381 self.assertEqual(message.repeated_int32[2], -3)
382
383 message.repeated_string.append('aaa')
384 message.repeated_string.append('bb')
385 message.repeated_string.append('c')
jieluo@google.combde4a322014-08-12 21:10:30 +0000386 message.repeated_string.sort(key=len)
liujisi@google.com33165fe2010-11-02 13:14:58 +0000387 self.assertEqual(message.repeated_string[0], 'c')
388 self.assertEqual(message.repeated_string[1], 'bb')
389 self.assertEqual(message.repeated_string[2], 'aaa')
390
Jisi Liuada65562015-02-25 16:39:11 -0800391 def testSortingRepeatedCompositeFieldsCustomComparator(self, message_module):
liujisi@google.com33165fe2010-11-02 13:14:58 +0000392 """Check passing a custom comparator to sort a repeated composite field."""
Jisi Liuada65562015-02-25 16:39:11 -0800393 message = message_module.TestAllTypes()
liujisi@google.com33165fe2010-11-02 13:14:58 +0000394
395 message.repeated_nested_message.add().bb = 1
396 message.repeated_nested_message.add().bb = 3
397 message.repeated_nested_message.add().bb = 2
398 message.repeated_nested_message.add().bb = 6
399 message.repeated_nested_message.add().bb = 5
400 message.repeated_nested_message.add().bb = 4
jieluo@google.combde4a322014-08-12 21:10:30 +0000401 message.repeated_nested_message.sort(key=operator.attrgetter('bb'))
liujisi@google.com33165fe2010-11-02 13:14:58 +0000402 self.assertEqual(message.repeated_nested_message[0].bb, 1)
403 self.assertEqual(message.repeated_nested_message[1].bb, 2)
404 self.assertEqual(message.repeated_nested_message[2].bb, 3)
405 self.assertEqual(message.repeated_nested_message[3].bb, 4)
406 self.assertEqual(message.repeated_nested_message[4].bb, 5)
407 self.assertEqual(message.repeated_nested_message[5].bb, 6)
408
Jisi Liuada65562015-02-25 16:39:11 -0800409 def testRepeatedCompositeFieldSortArguments(self, message_module):
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000410 """Check sorting a repeated composite field using list.sort() arguments."""
Jisi Liuada65562015-02-25 16:39:11 -0800411 message = message_module.TestAllTypes()
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000412
413 get_bb = operator.attrgetter('bb')
414 cmp_bb = lambda a, b: cmp(a.bb, b.bb)
415 message.repeated_nested_message.add().bb = 1
416 message.repeated_nested_message.add().bb = 3
417 message.repeated_nested_message.add().bb = 2
418 message.repeated_nested_message.add().bb = 6
419 message.repeated_nested_message.add().bb = 5
420 message.repeated_nested_message.add().bb = 4
421 message.repeated_nested_message.sort(key=get_bb)
422 self.assertEqual([k.bb for k in message.repeated_nested_message],
423 [1, 2, 3, 4, 5, 6])
424 message.repeated_nested_message.sort(key=get_bb, reverse=True)
425 self.assertEqual([k.bb for k in message.repeated_nested_message],
426 [6, 5, 4, 3, 2, 1])
jieluo@google.combde4a322014-08-12 21:10:30 +0000427 if sys.version_info.major >= 3: return # No cmp sorting in PY3.
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000428 message.repeated_nested_message.sort(sort_function=cmp_bb)
429 self.assertEqual([k.bb for k in message.repeated_nested_message],
430 [1, 2, 3, 4, 5, 6])
431 message.repeated_nested_message.sort(cmp=cmp_bb, reverse=True)
432 self.assertEqual([k.bb for k in message.repeated_nested_message],
433 [6, 5, 4, 3, 2, 1])
434
Jisi Liuada65562015-02-25 16:39:11 -0800435 def testRepeatedScalarFieldSortArguments(self, message_module):
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000436 """Check sorting a scalar field using list.sort() arguments."""
Jisi Liuada65562015-02-25 16:39:11 -0800437 message = message_module.TestAllTypes()
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000438
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000439 message.repeated_int32.append(-3)
440 message.repeated_int32.append(-2)
441 message.repeated_int32.append(-1)
442 message.repeated_int32.sort(key=abs)
443 self.assertEqual(list(message.repeated_int32), [-1, -2, -3])
444 message.repeated_int32.sort(key=abs, reverse=True)
445 self.assertEqual(list(message.repeated_int32), [-3, -2, -1])
jieluo@google.combde4a322014-08-12 21:10:30 +0000446 if sys.version_info.major < 3: # No cmp sorting in PY3.
447 abs_cmp = lambda a, b: cmp(abs(a), abs(b))
448 message.repeated_int32.sort(sort_function=abs_cmp)
449 self.assertEqual(list(message.repeated_int32), [-1, -2, -3])
450 message.repeated_int32.sort(cmp=abs_cmp, reverse=True)
451 self.assertEqual(list(message.repeated_int32), [-3, -2, -1])
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000452
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000453 message.repeated_string.append('aaa')
454 message.repeated_string.append('bb')
455 message.repeated_string.append('c')
456 message.repeated_string.sort(key=len)
457 self.assertEqual(list(message.repeated_string), ['c', 'bb', 'aaa'])
458 message.repeated_string.sort(key=len, reverse=True)
459 self.assertEqual(list(message.repeated_string), ['aaa', 'bb', 'c'])
jieluo@google.combde4a322014-08-12 21:10:30 +0000460 if sys.version_info.major < 3: # No cmp sorting in PY3.
461 len_cmp = lambda a, b: cmp(len(a), len(b))
462 message.repeated_string.sort(sort_function=len_cmp)
463 self.assertEqual(list(message.repeated_string), ['c', 'bb', 'aaa'])
464 message.repeated_string.sort(cmp=len_cmp, reverse=True)
465 self.assertEqual(list(message.repeated_string), ['aaa', 'bb', 'c'])
466
Jisi Liuada65562015-02-25 16:39:11 -0800467 def testRepeatedFieldsComparable(self, message_module):
468 m1 = message_module.TestAllTypes()
469 m2 = message_module.TestAllTypes()
jieluo@google.combde4a322014-08-12 21:10:30 +0000470 m1.repeated_int32.append(0)
471 m1.repeated_int32.append(1)
472 m1.repeated_int32.append(2)
473 m2.repeated_int32.append(0)
474 m2.repeated_int32.append(1)
475 m2.repeated_int32.append(2)
476 m1.repeated_nested_message.add().bb = 1
477 m1.repeated_nested_message.add().bb = 2
478 m1.repeated_nested_message.add().bb = 3
479 m2.repeated_nested_message.add().bb = 1
480 m2.repeated_nested_message.add().bb = 2
481 m2.repeated_nested_message.add().bb = 3
482
483 if sys.version_info.major >= 3: return # No cmp() in PY3.
484
485 # These comparisons should not raise errors.
486 _ = m1 < m2
487 _ = m1.repeated_nested_message < m2.repeated_nested_message
488
489 # Make sure cmp always works. If it wasn't defined, these would be
490 # id() comparisons and would all fail.
491 self.assertEqual(cmp(m1, m2), 0)
492 self.assertEqual(cmp(m1.repeated_int32, m2.repeated_int32), 0)
493 self.assertEqual(cmp(m1.repeated_int32, [0, 1, 2]), 0)
494 self.assertEqual(cmp(m1.repeated_nested_message,
495 m2.repeated_nested_message), 0)
496 with self.assertRaises(TypeError):
497 # Can't compare repeated composite containers to lists.
498 cmp(m1.repeated_nested_message, m2.repeated_nested_message[:])
499
500 # TODO(anuraag): Implement extensiondict comparison in C++ and then add test
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000501
Jisi Liuada65562015-02-25 16:39:11 -0800502 def ensureNestedMessageExists(self, msg, attribute):
503 """Make sure that a nested message object exists.
504
505 As soon as a nested message attribute is accessed, it will be present in the
506 _fields dict, without being marked as actually being set.
507 """
508 getattr(msg, attribute)
509 self.assertFalse(msg.HasField(attribute))
510
511 def testOneofGetCaseNonexistingField(self, message_module):
512 m = message_module.TestAllTypes()
513 self.assertRaises(ValueError, m.WhichOneof, 'no_such_oneof_field')
514
515 def testOneofDefaultValues(self, message_module):
516 m = message_module.TestAllTypes()
517 self.assertIs(None, m.WhichOneof('oneof_field'))
518 self.assertFalse(m.HasField('oneof_uint32'))
519
520 # Oneof is set even when setting it to a default value.
521 m.oneof_uint32 = 0
522 self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field'))
523 self.assertTrue(m.HasField('oneof_uint32'))
524 self.assertFalse(m.HasField('oneof_string'))
525
526 m.oneof_string = ""
527 self.assertEqual('oneof_string', m.WhichOneof('oneof_field'))
528 self.assertTrue(m.HasField('oneof_string'))
529 self.assertFalse(m.HasField('oneof_uint32'))
530
531 def testOneofSemantics(self, message_module):
532 m = message_module.TestAllTypes()
533 self.assertIs(None, m.WhichOneof('oneof_field'))
534
535 m.oneof_uint32 = 11
536 self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field'))
537 self.assertTrue(m.HasField('oneof_uint32'))
538
539 m.oneof_string = u'foo'
540 self.assertEqual('oneof_string', m.WhichOneof('oneof_field'))
541 self.assertFalse(m.HasField('oneof_uint32'))
542 self.assertTrue(m.HasField('oneof_string'))
543
544 m.oneof_nested_message.bb = 11
545 self.assertEqual('oneof_nested_message', m.WhichOneof('oneof_field'))
546 self.assertFalse(m.HasField('oneof_string'))
547 self.assertTrue(m.HasField('oneof_nested_message'))
548
549 m.oneof_bytes = b'bb'
550 self.assertEqual('oneof_bytes', m.WhichOneof('oneof_field'))
551 self.assertFalse(m.HasField('oneof_nested_message'))
552 self.assertTrue(m.HasField('oneof_bytes'))
553
554 def testOneofCompositeFieldReadAccess(self, message_module):
555 m = message_module.TestAllTypes()
556 m.oneof_uint32 = 11
557
558 self.ensureNestedMessageExists(m, 'oneof_nested_message')
559 self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field'))
560 self.assertEqual(11, m.oneof_uint32)
561
562 def testOneofWhichOneof(self, message_module):
563 m = message_module.TestAllTypes()
564 self.assertIs(None, m.WhichOneof('oneof_field'))
565 if message_module is unittest_pb2:
566 self.assertFalse(m.HasField('oneof_field'))
567
568 m.oneof_uint32 = 11
569 self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field'))
570 if message_module is unittest_pb2:
571 self.assertTrue(m.HasField('oneof_field'))
572
573 m.oneof_bytes = b'bb'
574 self.assertEqual('oneof_bytes', m.WhichOneof('oneof_field'))
575
576 m.ClearField('oneof_bytes')
577 self.assertIs(None, m.WhichOneof('oneof_field'))
578 if message_module is unittest_pb2:
579 self.assertFalse(m.HasField('oneof_field'))
580
581 def testOneofClearField(self, message_module):
582 m = message_module.TestAllTypes()
583 m.oneof_uint32 = 11
584 m.ClearField('oneof_field')
585 if message_module is unittest_pb2:
586 self.assertFalse(m.HasField('oneof_field'))
587 self.assertFalse(m.HasField('oneof_uint32'))
588 self.assertIs(None, m.WhichOneof('oneof_field'))
589
590 def testOneofClearSetField(self, message_module):
591 m = message_module.TestAllTypes()
592 m.oneof_uint32 = 11
593 m.ClearField('oneof_uint32')
594 if message_module is unittest_pb2:
595 self.assertFalse(m.HasField('oneof_field'))
596 self.assertFalse(m.HasField('oneof_uint32'))
597 self.assertIs(None, m.WhichOneof('oneof_field'))
598
599 def testOneofClearUnsetField(self, message_module):
600 m = message_module.TestAllTypes()
601 m.oneof_uint32 = 11
602 self.ensureNestedMessageExists(m, 'oneof_nested_message')
603 m.ClearField('oneof_nested_message')
604 self.assertEqual(11, m.oneof_uint32)
605 if message_module is unittest_pb2:
606 self.assertTrue(m.HasField('oneof_field'))
607 self.assertTrue(m.HasField('oneof_uint32'))
608 self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field'))
609
610 def testOneofDeserialize(self, message_module):
611 m = message_module.TestAllTypes()
612 m.oneof_uint32 = 11
613 m2 = message_module.TestAllTypes()
614 m2.ParseFromString(m.SerializeToString())
615 self.assertEqual('oneof_uint32', m2.WhichOneof('oneof_field'))
616
617 def testOneofCopyFrom(self, message_module):
618 m = message_module.TestAllTypes()
619 m.oneof_uint32 = 11
620 m2 = message_module.TestAllTypes()
621 m2.CopyFrom(m)
622 self.assertEqual('oneof_uint32', m2.WhichOneof('oneof_field'))
623
624 def testOneofNestedMergeFrom(self, message_module):
625 m = message_module.NestedTestAllTypes()
626 m.payload.oneof_uint32 = 11
627 m2 = message_module.NestedTestAllTypes()
628 m2.payload.oneof_bytes = b'bb'
629 m2.child.payload.oneof_bytes = b'bb'
630 m2.MergeFrom(m)
631 self.assertEqual('oneof_uint32', m2.payload.WhichOneof('oneof_field'))
632 self.assertEqual('oneof_bytes', m2.child.payload.WhichOneof('oneof_field'))
633
634 def testOneofMessageMergeFrom(self, message_module):
635 m = message_module.NestedTestAllTypes()
636 m.payload.oneof_nested_message.bb = 11
637 m.child.payload.oneof_nested_message.bb = 12
638 m2 = message_module.NestedTestAllTypes()
639 m2.payload.oneof_uint32 = 13
640 m2.MergeFrom(m)
641 self.assertEqual('oneof_nested_message',
642 m2.payload.WhichOneof('oneof_field'))
643 self.assertEqual('oneof_nested_message',
644 m2.child.payload.WhichOneof('oneof_field'))
645
646 def testOneofNestedMessageInit(self, message_module):
647 m = message_module.TestAllTypes(
648 oneof_nested_message=message_module.TestAllTypes.NestedMessage())
649 self.assertEqual('oneof_nested_message', m.WhichOneof('oneof_field'))
650
651 def testOneofClear(self, message_module):
652 m = message_module.TestAllTypes()
653 m.oneof_uint32 = 11
654 m.Clear()
655 self.assertIsNone(m.WhichOneof('oneof_field'))
656 m.oneof_bytes = b'bb'
657 self.assertEqual('oneof_bytes', m.WhichOneof('oneof_field'))
658
659 def testAssignByteStringToUnicodeField(self, message_module):
660 """Assigning a byte string to a string field should result
661 in the value being converted to a Unicode string."""
662 m = message_module.TestAllTypes()
663 m.optional_string = str('')
664 self.assertTrue(isinstance(m.optional_string, unicode))
665
666# TODO(haberman): why are these tests Google-internal only?
667
668 def testLongValuedSlice(self, message_module):
669 """It should be possible to use long-valued indicies in slices
670
671 This didn't used to work in the v2 C++ implementation.
672 """
673 m = message_module.TestAllTypes()
674
675 # Repeated scalar
676 m.repeated_int32.append(1)
677 sl = m.repeated_int32[long(0):long(len(m.repeated_int32))]
678 self.assertEqual(len(m.repeated_int32), len(sl))
679
680 # Repeated composite
681 m.repeated_nested_message.add().bb = 3
682 sl = m.repeated_nested_message[long(0):long(len(m.repeated_nested_message))]
683 self.assertEqual(len(m.repeated_nested_message), len(sl))
684
685 def testExtendShouldNotSwallowExceptions(self, message_module):
686 """This didn't use to work in the v2 C++ implementation."""
687 m = message_module.TestAllTypes()
688 with self.assertRaises(NameError) as _:
689 m.repeated_int32.extend(a for i in range(10)) # pylint: disable=undefined-variable
690 with self.assertRaises(NameError) as _:
691 m.repeated_nested_enum.extend(
692 a for i in range(10)) # pylint: disable=undefined-variable
693
694 FALSY_VALUES = [None, False, 0, 0.0, b'', u'', bytearray(), [], {}, set()]
695
696 def testExtendInt32WithNothing(self, message_module):
697 """Test no-ops extending repeated int32 fields."""
698 m = message_module.TestAllTypes()
699 self.assertSequenceEqual([], m.repeated_int32)
700
701 # TODO(ptucker): Deprecate this behavior. b/18413862
702 for falsy_value in MessageTest.FALSY_VALUES:
703 m.repeated_int32.extend(falsy_value)
704 self.assertSequenceEqual([], m.repeated_int32)
705
706 m.repeated_int32.extend([])
707 self.assertSequenceEqual([], m.repeated_int32)
708
709 def testExtendFloatWithNothing(self, message_module):
710 """Test no-ops extending repeated float fields."""
711 m = message_module.TestAllTypes()
712 self.assertSequenceEqual([], m.repeated_float)
713
714 # TODO(ptucker): Deprecate this behavior. b/18413862
715 for falsy_value in MessageTest.FALSY_VALUES:
716 m.repeated_float.extend(falsy_value)
717 self.assertSequenceEqual([], m.repeated_float)
718
719 m.repeated_float.extend([])
720 self.assertSequenceEqual([], m.repeated_float)
721
722 def testExtendStringWithNothing(self, message_module):
723 """Test no-ops extending repeated string fields."""
724 m = message_module.TestAllTypes()
725 self.assertSequenceEqual([], m.repeated_string)
726
727 # TODO(ptucker): Deprecate this behavior. b/18413862
728 for falsy_value in MessageTest.FALSY_VALUES:
729 m.repeated_string.extend(falsy_value)
730 self.assertSequenceEqual([], m.repeated_string)
731
732 m.repeated_string.extend([])
733 self.assertSequenceEqual([], m.repeated_string)
734
735 def testExtendInt32WithPythonList(self, message_module):
736 """Test extending repeated int32 fields with python lists."""
737 m = message_module.TestAllTypes()
738 self.assertSequenceEqual([], m.repeated_int32)
739 m.repeated_int32.extend([0])
740 self.assertSequenceEqual([0], m.repeated_int32)
741 m.repeated_int32.extend([1, 2])
742 self.assertSequenceEqual([0, 1, 2], m.repeated_int32)
743 m.repeated_int32.extend([3, 4])
744 self.assertSequenceEqual([0, 1, 2, 3, 4], m.repeated_int32)
745
746 def testExtendFloatWithPythonList(self, message_module):
747 """Test extending repeated float fields with python lists."""
748 m = message_module.TestAllTypes()
749 self.assertSequenceEqual([], m.repeated_float)
750 m.repeated_float.extend([0.0])
751 self.assertSequenceEqual([0.0], m.repeated_float)
752 m.repeated_float.extend([1.0, 2.0])
753 self.assertSequenceEqual([0.0, 1.0, 2.0], m.repeated_float)
754 m.repeated_float.extend([3.0, 4.0])
755 self.assertSequenceEqual([0.0, 1.0, 2.0, 3.0, 4.0], m.repeated_float)
756
757 def testExtendStringWithPythonList(self, message_module):
758 """Test extending repeated string fields with python lists."""
759 m = message_module.TestAllTypes()
760 self.assertSequenceEqual([], m.repeated_string)
761 m.repeated_string.extend([''])
762 self.assertSequenceEqual([''], m.repeated_string)
763 m.repeated_string.extend(['11', '22'])
764 self.assertSequenceEqual(['', '11', '22'], m.repeated_string)
765 m.repeated_string.extend(['33', '44'])
766 self.assertSequenceEqual(['', '11', '22', '33', '44'], m.repeated_string)
767
768 def testExtendStringWithString(self, message_module):
769 """Test extending repeated string fields with characters from a string."""
770 m = message_module.TestAllTypes()
771 self.assertSequenceEqual([], m.repeated_string)
772 m.repeated_string.extend('abc')
773 self.assertSequenceEqual(['a', 'b', 'c'], m.repeated_string)
774
775 class TestIterable(object):
776 """This iterable object mimics the behavior of numpy.array.
777
778 __nonzero__ fails for length > 1, and returns bool(item[0]) for length == 1.
779
780 """
781
782 def __init__(self, values=None):
783 self._list = values or []
784
785 def __nonzero__(self):
786 size = len(self._list)
787 if size == 0:
788 return False
789 if size == 1:
790 return bool(self._list[0])
791 raise ValueError('Truth value is ambiguous.')
792
793 def __len__(self):
794 return len(self._list)
795
796 def __iter__(self):
797 return self._list.__iter__()
798
799 def testExtendInt32WithIterable(self, message_module):
800 """Test extending repeated int32 fields with iterable."""
801 m = message_module.TestAllTypes()
802 self.assertSequenceEqual([], m.repeated_int32)
803 m.repeated_int32.extend(MessageTest.TestIterable([]))
804 self.assertSequenceEqual([], m.repeated_int32)
805 m.repeated_int32.extend(MessageTest.TestIterable([0]))
806 self.assertSequenceEqual([0], m.repeated_int32)
807 m.repeated_int32.extend(MessageTest.TestIterable([1, 2]))
808 self.assertSequenceEqual([0, 1, 2], m.repeated_int32)
809 m.repeated_int32.extend(MessageTest.TestIterable([3, 4]))
810 self.assertSequenceEqual([0, 1, 2, 3, 4], m.repeated_int32)
811
812 def testExtendFloatWithIterable(self, message_module):
813 """Test extending repeated float fields with iterable."""
814 m = message_module.TestAllTypes()
815 self.assertSequenceEqual([], m.repeated_float)
816 m.repeated_float.extend(MessageTest.TestIterable([]))
817 self.assertSequenceEqual([], m.repeated_float)
818 m.repeated_float.extend(MessageTest.TestIterable([0.0]))
819 self.assertSequenceEqual([0.0], m.repeated_float)
820 m.repeated_float.extend(MessageTest.TestIterable([1.0, 2.0]))
821 self.assertSequenceEqual([0.0, 1.0, 2.0], m.repeated_float)
822 m.repeated_float.extend(MessageTest.TestIterable([3.0, 4.0]))
823 self.assertSequenceEqual([0.0, 1.0, 2.0, 3.0, 4.0], m.repeated_float)
824
825 def testExtendStringWithIterable(self, message_module):
826 """Test extending repeated string fields with iterable."""
827 m = message_module.TestAllTypes()
828 self.assertSequenceEqual([], m.repeated_string)
829 m.repeated_string.extend(MessageTest.TestIterable([]))
830 self.assertSequenceEqual([], m.repeated_string)
831 m.repeated_string.extend(MessageTest.TestIterable(['']))
832 self.assertSequenceEqual([''], m.repeated_string)
833 m.repeated_string.extend(MessageTest.TestIterable(['1', '2']))
834 self.assertSequenceEqual(['', '1', '2'], m.repeated_string)
835 m.repeated_string.extend(MessageTest.TestIterable(['3', '4']))
836 self.assertSequenceEqual(['', '1', '2', '3', '4'], m.repeated_string)
837
838 def testPickleRepeatedScalarContainer(self, message_module):
839 # TODO(tibell): The pure-Python implementation support pickling of
840 # scalar containers in *some* cases. For now the cpp2 version
841 # throws an exception to avoid a segfault. Investigate if we
842 # want to support pickling of these fields.
843 #
844 # For more information see: https://b2.corp.google.com/u/0/issues/18677897
845 if (api_implementation.Type() != 'cpp' or
846 api_implementation.Version() == 2):
847 return
848 m = message_module.TestAllTypes()
849 with self.assertRaises(pickle.PickleError) as _:
850 pickle.dumps(m.repeated_int32, pickle.HIGHEST_PROTOCOL)
851
852
853 def testSortEmptyRepeatedCompositeContainer(self, message_module):
854 """Exercise a scenario that has led to segfaults in the past.
855 """
856 m = message_module.TestAllTypes()
857 m.repeated_nested_message.sort()
858
859 def testHasFieldOnRepeatedField(self, message_module):
860 """Using HasField on a repeated field should raise an exception.
861 """
862 m = message_module.TestAllTypes()
863 with self.assertRaises(ValueError) as _:
864 m.HasField('repeated_int32')
865
866 def testRepeatedScalarFieldPop(self, message_module):
867 m = message_module.TestAllTypes()
868 with self.assertRaises(IndexError) as _:
869 m.repeated_int32.pop()
870 m.repeated_int32.extend(range(5))
871 self.assertEqual(4, m.repeated_int32.pop())
872 self.assertEqual(0, m.repeated_int32.pop(0))
873 self.assertEqual(2, m.repeated_int32.pop(1))
874 self.assertEqual([1, 3], m.repeated_int32)
875
876 def testRepeatedCompositeFieldPop(self, message_module):
877 m = message_module.TestAllTypes()
878 with self.assertRaises(IndexError) as _:
879 m.repeated_nested_message.pop()
880 for i in range(5):
881 n = m.repeated_nested_message.add()
882 n.bb = i
883 self.assertEqual(4, m.repeated_nested_message.pop().bb)
884 self.assertEqual(0, m.repeated_nested_message.pop(0).bb)
885 self.assertEqual(2, m.repeated_nested_message.pop(1).bb)
886 self.assertEqual([1, 3], [n.bb for n in m.repeated_nested_message])
887
888
889# Class to test proto2-only features (required, extensions, etc.)
890class Proto2Test(basetest.TestCase):
891
892 def testFieldPresence(self):
893 message = unittest_pb2.TestAllTypes()
894
895 self.assertFalse(message.HasField("optional_int32"))
896 self.assertFalse(message.HasField("optional_bool"))
897 self.assertFalse(message.HasField("optional_nested_message"))
898
899 with self.assertRaises(ValueError):
900 message.HasField("field_doesnt_exist")
901
902 with self.assertRaises(ValueError):
903 message.HasField("repeated_int32")
904 with self.assertRaises(ValueError):
905 message.HasField("repeated_nested_message")
906
907 self.assertEqual(0, message.optional_int32)
908 self.assertEqual(False, message.optional_bool)
909 self.assertEqual(0, message.optional_nested_message.bb)
910
911 # Fields are set even when setting the values to default values.
912 message.optional_int32 = 0
913 message.optional_bool = False
914 message.optional_nested_message.bb = 0
915 self.assertTrue(message.HasField("optional_int32"))
916 self.assertTrue(message.HasField("optional_bool"))
917 self.assertTrue(message.HasField("optional_nested_message"))
918
919 # Set the fields to non-default values.
920 message.optional_int32 = 5
921 message.optional_bool = True
922 message.optional_nested_message.bb = 15
923
924 self.assertTrue(message.HasField("optional_int32"))
925 self.assertTrue(message.HasField("optional_bool"))
926 self.assertTrue(message.HasField("optional_nested_message"))
927
928 # Clearing the fields unsets them and resets their value to default.
929 message.ClearField("optional_int32")
930 message.ClearField("optional_bool")
931 message.ClearField("optional_nested_message")
932
933 self.assertFalse(message.HasField("optional_int32"))
934 self.assertFalse(message.HasField("optional_bool"))
935 self.assertFalse(message.HasField("optional_nested_message"))
936 self.assertEqual(0, message.optional_int32)
937 self.assertEqual(False, message.optional_bool)
938 self.assertEqual(0, message.optional_nested_message.bb)
939
940 # TODO(tibell): The C++ implementations actually allows assignment
941 # of unknown enum values to *scalar* fields (but not repeated
942 # fields). Once checked enum fields becomes the default in the
943 # Python implementation, the C++ implementation should follow suit.
944 def testAssignInvalidEnum(self):
945 """It should not be possible to assign an invalid enum number to an
946 enum field."""
947 m = unittest_pb2.TestAllTypes()
948
949 with self.assertRaises(ValueError) as _:
950 m.optional_nested_enum = 1234567
951 self.assertRaises(ValueError, m.repeated_nested_enum.append, 1234567)
952
953 def testGoldenExtensions(self):
954 golden_data = test_util.GoldenFileData('golden_message')
955 golden_message = unittest_pb2.TestAllExtensions()
956 golden_message.ParseFromString(golden_data)
957 all_set = unittest_pb2.TestAllExtensions()
958 test_util.SetAllExtensions(all_set)
959 self.assertEqual(all_set, golden_message)
960 self.assertEqual(golden_data, golden_message.SerializeToString())
961 golden_copy = copy.deepcopy(golden_message)
962 self.assertEqual(golden_data, golden_copy.SerializeToString())
963
964 def testGoldenPackedExtensions(self):
965 golden_data = test_util.GoldenFileData('golden_packed_fields_message')
966 golden_message = unittest_pb2.TestPackedExtensions()
967 golden_message.ParseFromString(golden_data)
968 all_set = unittest_pb2.TestPackedExtensions()
969 test_util.SetAllPackedExtensions(all_set)
970 self.assertEqual(all_set, golden_message)
971 self.assertEqual(golden_data, all_set.SerializeToString())
972 golden_copy = copy.deepcopy(golden_message)
973 self.assertEqual(golden_data, golden_copy.SerializeToString())
974
975 def testPickleIncompleteProto(self):
976 golden_message = unittest_pb2.TestRequired(a=1)
977 pickled_message = pickle.dumps(golden_message)
978
979 unpickled_message = pickle.loads(pickled_message)
980 self.assertEqual(unpickled_message, golden_message)
981 self.assertEqual(unpickled_message.a, 1)
982 # This is still an incomplete proto - so serializing should fail
983 self.assertRaises(message.EncodeError, unpickled_message.SerializeToString)
984
Jisi Liu885b6122015-02-28 14:51:22 -0800985
Jisi Liuada65562015-02-25 16:39:11 -0800986 # TODO(haberman): this isn't really a proto2-specific test except that this
987 # message has a required field in it. Should probably be factored out so
988 # that we can test the other parts with proto3.
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000989 def testParsingMerge(self):
990 """Check the merge behavior when a required or optional field appears
991 multiple times in the input."""
992 messages = [
993 unittest_pb2.TestAllTypes(),
994 unittest_pb2.TestAllTypes(),
995 unittest_pb2.TestAllTypes() ]
996 messages[0].optional_int32 = 1
997 messages[1].optional_int64 = 2
998 messages[2].optional_int32 = 3
999 messages[2].optional_string = 'hello'
1000
1001 merged_message = unittest_pb2.TestAllTypes()
1002 merged_message.optional_int32 = 3
1003 merged_message.optional_int64 = 2
1004 merged_message.optional_string = 'hello'
1005
1006 generator = unittest_pb2.TestParsingMerge.RepeatedFieldsGenerator()
1007 generator.field1.extend(messages)
1008 generator.field2.extend(messages)
1009 generator.field3.extend(messages)
1010 generator.ext1.extend(messages)
1011 generator.ext2.extend(messages)
1012 generator.group1.add().field1.MergeFrom(messages[0])
1013 generator.group1.add().field1.MergeFrom(messages[1])
1014 generator.group1.add().field1.MergeFrom(messages[2])
1015 generator.group2.add().field1.MergeFrom(messages[0])
1016 generator.group2.add().field1.MergeFrom(messages[1])
1017 generator.group2.add().field1.MergeFrom(messages[2])
1018
1019 data = generator.SerializeToString()
1020 parsing_merge = unittest_pb2.TestParsingMerge()
1021 parsing_merge.ParseFromString(data)
1022
1023 # Required and optional fields should be merged.
1024 self.assertEqual(parsing_merge.required_all_types, merged_message)
1025 self.assertEqual(parsing_merge.optional_all_types, merged_message)
1026 self.assertEqual(parsing_merge.optionalgroup.optional_group_all_types,
1027 merged_message)
1028 self.assertEqual(parsing_merge.Extensions[
1029 unittest_pb2.TestParsingMerge.optional_ext],
1030 merged_message)
1031
1032 # Repeated fields should not be merged.
1033 self.assertEqual(len(parsing_merge.repeated_all_types), 3)
1034 self.assertEqual(len(parsing_merge.repeatedgroup), 3)
1035 self.assertEqual(len(parsing_merge.Extensions[
1036 unittest_pb2.TestParsingMerge.repeated_ext]), 3)
1037
jieluo@google.combde4a322014-08-12 21:10:30 +00001038
Jisi Liuada65562015-02-25 16:39:11 -08001039# Class to test proto3-only features/behavior (updated field presence & enums)
1040class Proto3Test(basetest.TestCase):
jieluo@google.combde4a322014-08-12 21:10:30 +00001041
Jisi Liuada65562015-02-25 16:39:11 -08001042 def testFieldPresence(self):
1043 message = unittest_proto3_arena_pb2.TestAllTypes()
jieluo@google.combde4a322014-08-12 21:10:30 +00001044
Jisi Liuada65562015-02-25 16:39:11 -08001045 # We can't test presence of non-repeated, non-submessage fields.
1046 with self.assertRaises(ValueError):
1047 message.HasField("optional_int32")
1048 with self.assertRaises(ValueError):
1049 message.HasField("optional_float")
1050 with self.assertRaises(ValueError):
1051 message.HasField("optional_string")
1052 with self.assertRaises(ValueError):
1053 message.HasField("optional_bool")
jieluo@google.combde4a322014-08-12 21:10:30 +00001054
Jisi Liuada65562015-02-25 16:39:11 -08001055 # But we can still test presence of submessage fields.
1056 self.assertFalse(message.HasField("optional_nested_message"))
jieluo@google.combde4a322014-08-12 21:10:30 +00001057
Jisi Liuada65562015-02-25 16:39:11 -08001058 # As with proto2, we can't test presence of fields that don't exist, or
1059 # repeated fields.
1060 with self.assertRaises(ValueError):
1061 message.HasField("field_doesnt_exist")
jieluo@google.combde4a322014-08-12 21:10:30 +00001062
Jisi Liuada65562015-02-25 16:39:11 -08001063 with self.assertRaises(ValueError):
1064 message.HasField("repeated_int32")
1065 with self.assertRaises(ValueError):
1066 message.HasField("repeated_nested_message")
jieluo@google.combde4a322014-08-12 21:10:30 +00001067
Jisi Liuada65562015-02-25 16:39:11 -08001068 # Fields should default to their type-specific default.
1069 self.assertEqual(0, message.optional_int32)
1070 self.assertEqual(0, message.optional_float)
1071 self.assertEqual("", message.optional_string)
1072 self.assertEqual(False, message.optional_bool)
1073 self.assertEqual(0, message.optional_nested_message.bb)
jieluo@google.combde4a322014-08-12 21:10:30 +00001074
Jisi Liuada65562015-02-25 16:39:11 -08001075 # Setting a submessage should still return proper presence information.
1076 message.optional_nested_message.bb = 0
1077 self.assertTrue(message.HasField("optional_nested_message"))
jieluo@google.combde4a322014-08-12 21:10:30 +00001078
Jisi Liuada65562015-02-25 16:39:11 -08001079 # Set the fields to non-default values.
1080 message.optional_int32 = 5
1081 message.optional_float = 1.1
1082 message.optional_string = "abc"
1083 message.optional_bool = True
1084 message.optional_nested_message.bb = 15
jieluo@google.combde4a322014-08-12 21:10:30 +00001085
Jisi Liuada65562015-02-25 16:39:11 -08001086 # Clearing the fields unsets them and resets their value to default.
1087 message.ClearField("optional_int32")
1088 message.ClearField("optional_float")
1089 message.ClearField("optional_string")
1090 message.ClearField("optional_bool")
1091 message.ClearField("optional_nested_message")
jieluo@google.combde4a322014-08-12 21:10:30 +00001092
Jisi Liuada65562015-02-25 16:39:11 -08001093 self.assertEqual(0, message.optional_int32)
1094 self.assertEqual(0, message.optional_float)
1095 self.assertEqual("", message.optional_string)
1096 self.assertEqual(False, message.optional_bool)
1097 self.assertEqual(0, message.optional_nested_message.bb)
jieluo@google.combde4a322014-08-12 21:10:30 +00001098
Jisi Liuada65562015-02-25 16:39:11 -08001099 def testAssignUnknownEnum(self):
1100 """Assigning an unknown enum value is allowed and preserves the value."""
1101 m = unittest_proto3_arena_pb2.TestAllTypes()
jieluo@google.combde4a322014-08-12 21:10:30 +00001102
Jisi Liuada65562015-02-25 16:39:11 -08001103 m.optional_nested_enum = 1234567
1104 self.assertEqual(1234567, m.optional_nested_enum)
1105 m.repeated_nested_enum.append(22334455)
1106 self.assertEqual(22334455, m.repeated_nested_enum[0])
1107 # Assignment is a different code path than append for the C++ impl.
1108 m.repeated_nested_enum[0] = 7654321
1109 self.assertEqual(7654321, m.repeated_nested_enum[0])
1110 serialized = m.SerializeToString()
jieluo@google.combde4a322014-08-12 21:10:30 +00001111
Jisi Liuada65562015-02-25 16:39:11 -08001112 m2 = unittest_proto3_arena_pb2.TestAllTypes()
1113 m2.ParseFromString(serialized)
1114 self.assertEqual(1234567, m2.optional_nested_enum)
1115 self.assertEqual(7654321, m2.repeated_nested_enum[0])
jieluo@google.combde4a322014-08-12 21:10:30 +00001116
1117
1118class ValidTypeNamesTest(basetest.TestCase):
1119
1120 def assertImportFromName(self, msg, base_name):
1121 # Parse <type 'module.class_name'> to extra 'some.name' as a string.
1122 tp_name = str(type(msg)).split("'")[1]
1123 valid_names = ('Repeated%sContainer' % base_name,
1124 'Repeated%sFieldContainer' % base_name)
1125 self.assertTrue(any(tp_name.endswith(v) for v in valid_names),
1126 '%r does end with any of %r' % (tp_name, valid_names))
1127
1128 parts = tp_name.split('.')
1129 class_name = parts[-1]
1130 module_name = '.'.join(parts[:-1])
1131 __import__(module_name, fromlist=[class_name])
1132
1133 def testTypeNamesCanBeImported(self):
1134 # If import doesn't work, pickling won't work either.
1135 pb = unittest_pb2.TestAllTypes()
1136 self.assertImportFromName(pb.repeated_int32, 'Scalar')
1137 self.assertImportFromName(pb.repeated_nested_message, 'Composite')
1138
kenton@google.com80b1d622009-07-29 01:13:20 +00001139
1140if __name__ == '__main__':
jieluo@google.combde4a322014-08-12 21:10:30 +00001141 basetest.main()