1#! /usr/bin/python 2# 3# Protocol Buffers - Google's data interchange format 4# Copyright 2008 Google Inc. All rights reserved. 5# http://code.google.com/p/protobuf/ 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 33"""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""" 43 44__author__ = 'gps@google.com (Gregory P. Smith)' 45 46import copy 47import math 48import operator 49import pickle 50 51import unittest 52from google.protobuf import unittest_import_pb2 53from google.protobuf import unittest_pb2 54from google.protobuf.internal import api_implementation 55from google.protobuf.internal import test_util 56from google.protobuf import message 57 58# Python pre-2.6 does not have isinf() or isnan() functions, so we have 59# to provide our own. 60def isnan(val): 61 # NaN is never equal to itself. 62 return val != val 63def isinf(val): 64 # Infinity times zero equals NaN. 65 return not isnan(val) and isnan(val * 0) 66def IsPosInf(val): 67 return isinf(val) and (val > 0) 68def IsNegInf(val): 69 return isinf(val) and (val < 0) 70 71class MessageTest(unittest.TestCase): 72 73 def testGoldenMessage(self): 74 golden_data = test_util.GoldenFile('golden_message').read() 75 golden_message = unittest_pb2.TestAllTypes() 76 golden_message.ParseFromString(golden_data) 77 test_util.ExpectAllFieldsSet(self, golden_message) 78 self.assertEqual(golden_data, golden_message.SerializeToString()) 79 golden_copy = copy.deepcopy(golden_message) 80 self.assertEqual(golden_data, golden_copy.SerializeToString()) 81 82 def testGoldenExtensions(self): 83 golden_data = test_util.GoldenFile('golden_message').read() 84 golden_message = unittest_pb2.TestAllExtensions() 85 golden_message.ParseFromString(golden_data) 86 all_set = unittest_pb2.TestAllExtensions() 87 test_util.SetAllExtensions(all_set) 88 self.assertEquals(all_set, golden_message) 89 self.assertEqual(golden_data, golden_message.SerializeToString()) 90 golden_copy = copy.deepcopy(golden_message) 91 self.assertEqual(golden_data, golden_copy.SerializeToString()) 92 93 def testGoldenPackedMessage(self): 94 golden_data = test_util.GoldenFile('golden_packed_fields_message').read() 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 104 def testGoldenPackedExtensions(self): 105 golden_data = test_util.GoldenFile('golden_packed_fields_message').read() 106 golden_message = unittest_pb2.TestPackedExtensions() 107 golden_message.ParseFromString(golden_data) 108 all_set = unittest_pb2.TestPackedExtensions() 109 test_util.SetAllPackedExtensions(all_set) 110 self.assertEquals(all_set, golden_message) 111 self.assertEqual(golden_data, all_set.SerializeToString()) 112 golden_copy = copy.deepcopy(golden_message) 113 self.assertEqual(golden_data, golden_copy.SerializeToString()) 114 115 def testPickleSupport(self): 116 golden_data = test_util.GoldenFile('golden_message').read() 117 golden_message = unittest_pb2.TestAllTypes() 118 golden_message.ParseFromString(golden_data) 119 pickled_message = pickle.dumps(golden_message) 120 121 unpickled_message = pickle.loads(pickled_message) 122 self.assertEquals(unpickled_message, golden_message) 123 124 def testPickleIncompleteProto(self): 125 golden_message = unittest_pb2.TestRequired(a=1) 126 pickled_message = pickle.dumps(golden_message) 127 128 unpickled_message = pickle.loads(pickled_message) 129 self.assertEquals(unpickled_message, golden_message) 130 self.assertEquals(unpickled_message.a, 1) 131 # This is still an incomplete proto - so serializing should fail 132 self.assertRaises(message.EncodeError, unpickled_message.SerializeToString) 133 134 def testPositiveInfinity(self): 135 golden_data = ('\x5D\x00\x00\x80\x7F' 136 '\x61\x00\x00\x00\x00\x00\x00\xF0\x7F' 137 '\xCD\x02\x00\x00\x80\x7F' 138 '\xD1\x02\x00\x00\x00\x00\x00\x00\xF0\x7F') 139 golden_message = unittest_pb2.TestAllTypes() 140 golden_message.ParseFromString(golden_data) 141 self.assertTrue(IsPosInf(golden_message.optional_float)) 142 self.assertTrue(IsPosInf(golden_message.optional_double)) 143 self.assertTrue(IsPosInf(golden_message.repeated_float[0])) 144 self.assertTrue(IsPosInf(golden_message.repeated_double[0])) 145 self.assertEqual(golden_data, golden_message.SerializeToString()) 146 147 def testNegativeInfinity(self): 148 golden_data = ('\x5D\x00\x00\x80\xFF' 149 '\x61\x00\x00\x00\x00\x00\x00\xF0\xFF' 150 '\xCD\x02\x00\x00\x80\xFF' 151 '\xD1\x02\x00\x00\x00\x00\x00\x00\xF0\xFF') 152 golden_message = unittest_pb2.TestAllTypes() 153 golden_message.ParseFromString(golden_data) 154 self.assertTrue(IsNegInf(golden_message.optional_float)) 155 self.assertTrue(IsNegInf(golden_message.optional_double)) 156 self.assertTrue(IsNegInf(golden_message.repeated_float[0])) 157 self.assertTrue(IsNegInf(golden_message.repeated_double[0])) 158 self.assertEqual(golden_data, golden_message.SerializeToString()) 159 160 def testNotANumber(self): 161 golden_data = ('\x5D\x00\x00\xC0\x7F' 162 '\x61\x00\x00\x00\x00\x00\x00\xF8\x7F' 163 '\xCD\x02\x00\x00\xC0\x7F' 164 '\xD1\x02\x00\x00\x00\x00\x00\x00\xF8\x7F') 165 golden_message = unittest_pb2.TestAllTypes() 166 golden_message.ParseFromString(golden_data) 167 self.assertTrue(isnan(golden_message.optional_float)) 168 self.assertTrue(isnan(golden_message.optional_double)) 169 self.assertTrue(isnan(golden_message.repeated_float[0])) 170 self.assertTrue(isnan(golden_message.repeated_double[0])) 171 172 # The protocol buffer may serialize to any one of multiple different 173 # representations of a NaN. Rather than verify a specific representation, 174 # verify the serialized string can be converted into a correctly 175 # behaving protocol buffer. 176 serialized = golden_message.SerializeToString() 177 message = unittest_pb2.TestAllTypes() 178 message.ParseFromString(serialized) 179 self.assertTrue(isnan(message.optional_float)) 180 self.assertTrue(isnan(message.optional_double)) 181 self.assertTrue(isnan(message.repeated_float[0])) 182 self.assertTrue(isnan(message.repeated_double[0])) 183 184 def testPositiveInfinityPacked(self): 185 golden_data = ('\xA2\x06\x04\x00\x00\x80\x7F' 186 '\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF0\x7F') 187 golden_message = unittest_pb2.TestPackedTypes() 188 golden_message.ParseFromString(golden_data) 189 self.assertTrue(IsPosInf(golden_message.packed_float[0])) 190 self.assertTrue(IsPosInf(golden_message.packed_double[0])) 191 self.assertEqual(golden_data, golden_message.SerializeToString()) 192 193 def testNegativeInfinityPacked(self): 194 golden_data = ('\xA2\x06\x04\x00\x00\x80\xFF' 195 '\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF0\xFF') 196 golden_message = unittest_pb2.TestPackedTypes() 197 golden_message.ParseFromString(golden_data) 198 self.assertTrue(IsNegInf(golden_message.packed_float[0])) 199 self.assertTrue(IsNegInf(golden_message.packed_double[0])) 200 self.assertEqual(golden_data, golden_message.SerializeToString()) 201 202 def testNotANumberPacked(self): 203 golden_data = ('\xA2\x06\x04\x00\x00\xC0\x7F' 204 '\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF8\x7F') 205 golden_message = unittest_pb2.TestPackedTypes() 206 golden_message.ParseFromString(golden_data) 207 self.assertTrue(isnan(golden_message.packed_float[0])) 208 self.assertTrue(isnan(golden_message.packed_double[0])) 209 210 serialized = golden_message.SerializeToString() 211 message = unittest_pb2.TestPackedTypes() 212 message.ParseFromString(serialized) 213 self.assertTrue(isnan(message.packed_float[0])) 214 self.assertTrue(isnan(message.packed_double[0])) 215 216 def testExtremeFloatValues(self): 217 message = unittest_pb2.TestAllTypes() 218 219 # Most positive exponent, no significand bits set. 220 kMostPosExponentNoSigBits = math.pow(2, 127) 221 message.optional_float = kMostPosExponentNoSigBits 222 message.ParseFromString(message.SerializeToString()) 223 self.assertTrue(message.optional_float == kMostPosExponentNoSigBits) 224 225 # Most positive exponent, one significand bit set. 226 kMostPosExponentOneSigBit = 1.5 * math.pow(2, 127) 227 message.optional_float = kMostPosExponentOneSigBit 228 message.ParseFromString(message.SerializeToString()) 229 self.assertTrue(message.optional_float == kMostPosExponentOneSigBit) 230 231 # Repeat last two cases with values of same magnitude, but negative. 232 message.optional_float = -kMostPosExponentNoSigBits 233 message.ParseFromString(message.SerializeToString()) 234 self.assertTrue(message.optional_float == -kMostPosExponentNoSigBits) 235 236 message.optional_float = -kMostPosExponentOneSigBit 237 message.ParseFromString(message.SerializeToString()) 238 self.assertTrue(message.optional_float == -kMostPosExponentOneSigBit) 239 240 # Most negative exponent, no significand bits set. 241 kMostNegExponentNoSigBits = math.pow(2, -127) 242 message.optional_float = kMostNegExponentNoSigBits 243 message.ParseFromString(message.SerializeToString()) 244 self.assertTrue(message.optional_float == kMostNegExponentNoSigBits) 245 246 # Most negative exponent, one significand bit set. 247 kMostNegExponentOneSigBit = 1.5 * math.pow(2, -127) 248 message.optional_float = kMostNegExponentOneSigBit 249 message.ParseFromString(message.SerializeToString()) 250 self.assertTrue(message.optional_float == kMostNegExponentOneSigBit) 251 252 # Repeat last two cases with values of the same magnitude, but negative. 253 message.optional_float = -kMostNegExponentNoSigBits 254 message.ParseFromString(message.SerializeToString()) 255 self.assertTrue(message.optional_float == -kMostNegExponentNoSigBits) 256 257 message.optional_float = -kMostNegExponentOneSigBit 258 message.ParseFromString(message.SerializeToString()) 259 self.assertTrue(message.optional_float == -kMostNegExponentOneSigBit) 260 261 def testExtremeDoubleValues(self): 262 message = unittest_pb2.TestAllTypes() 263 264 # Most positive exponent, no significand bits set. 265 kMostPosExponentNoSigBits = math.pow(2, 1023) 266 message.optional_double = kMostPosExponentNoSigBits 267 message.ParseFromString(message.SerializeToString()) 268 self.assertTrue(message.optional_double == kMostPosExponentNoSigBits) 269 270 # Most positive exponent, one significand bit set. 271 kMostPosExponentOneSigBit = 1.5 * math.pow(2, 1023) 272 message.optional_double = kMostPosExponentOneSigBit 273 message.ParseFromString(message.SerializeToString()) 274 self.assertTrue(message.optional_double == kMostPosExponentOneSigBit) 275 276 # Repeat last two cases with values of same magnitude, but negative. 277 message.optional_double = -kMostPosExponentNoSigBits 278 message.ParseFromString(message.SerializeToString()) 279 self.assertTrue(message.optional_double == -kMostPosExponentNoSigBits) 280 281 message.optional_double = -kMostPosExponentOneSigBit 282 message.ParseFromString(message.SerializeToString()) 283 self.assertTrue(message.optional_double == -kMostPosExponentOneSigBit) 284 285 # Most negative exponent, no significand bits set. 286 kMostNegExponentNoSigBits = math.pow(2, -1023) 287 message.optional_double = kMostNegExponentNoSigBits 288 message.ParseFromString(message.SerializeToString()) 289 self.assertTrue(message.optional_double == kMostNegExponentNoSigBits) 290 291 # Most negative exponent, one significand bit set. 292 kMostNegExponentOneSigBit = 1.5 * math.pow(2, -1023) 293 message.optional_double = kMostNegExponentOneSigBit 294 message.ParseFromString(message.SerializeToString()) 295 self.assertTrue(message.optional_double == kMostNegExponentOneSigBit) 296 297 # Repeat last two cases with values of the same magnitude, but negative. 298 message.optional_double = -kMostNegExponentNoSigBits 299 message.ParseFromString(message.SerializeToString()) 300 self.assertTrue(message.optional_double == -kMostNegExponentNoSigBits) 301 302 message.optional_double = -kMostNegExponentOneSigBit 303 message.ParseFromString(message.SerializeToString()) 304 self.assertTrue(message.optional_double == -kMostNegExponentOneSigBit) 305 306 def testSortingRepeatedScalarFieldsDefaultComparator(self): 307 """Check some different types with the default comparator.""" 308 message = unittest_pb2.TestAllTypes() 309 310 # TODO(mattp): would testing more scalar types strengthen test? 311 message.repeated_int32.append(1) 312 message.repeated_int32.append(3) 313 message.repeated_int32.append(2) 314 message.repeated_int32.sort() 315 self.assertEqual(message.repeated_int32[0], 1) 316 self.assertEqual(message.repeated_int32[1], 2) 317 self.assertEqual(message.repeated_int32[2], 3) 318 319 message.repeated_float.append(1.1) 320 message.repeated_float.append(1.3) 321 message.repeated_float.append(1.2) 322 message.repeated_float.sort() 323 self.assertAlmostEqual(message.repeated_float[0], 1.1) 324 self.assertAlmostEqual(message.repeated_float[1], 1.2) 325 self.assertAlmostEqual(message.repeated_float[2], 1.3) 326 327 message.repeated_string.append('a') 328 message.repeated_string.append('c') 329 message.repeated_string.append('b') 330 message.repeated_string.sort() 331 self.assertEqual(message.repeated_string[0], 'a') 332 self.assertEqual(message.repeated_string[1], 'b') 333 self.assertEqual(message.repeated_string[2], 'c') 334 335 message.repeated_bytes.append('a') 336 message.repeated_bytes.append('c') 337 message.repeated_bytes.append('b') 338 message.repeated_bytes.sort() 339 self.assertEqual(message.repeated_bytes[0], 'a') 340 self.assertEqual(message.repeated_bytes[1], 'b') 341 self.assertEqual(message.repeated_bytes[2], 'c') 342 343 def testSortingRepeatedScalarFieldsCustomComparator(self): 344 """Check some different types with custom comparator.""" 345 message = unittest_pb2.TestAllTypes() 346 347 message.repeated_int32.append(-3) 348 message.repeated_int32.append(-2) 349 message.repeated_int32.append(-1) 350 message.repeated_int32.sort(lambda x,y: cmp(abs(x), abs(y))) 351 self.assertEqual(message.repeated_int32[0], -1) 352 self.assertEqual(message.repeated_int32[1], -2) 353 self.assertEqual(message.repeated_int32[2], -3) 354 355 message.repeated_string.append('aaa') 356 message.repeated_string.append('bb') 357 message.repeated_string.append('c') 358 message.repeated_string.sort(lambda x,y: cmp(len(x), len(y))) 359 self.assertEqual(message.repeated_string[0], 'c') 360 self.assertEqual(message.repeated_string[1], 'bb') 361 self.assertEqual(message.repeated_string[2], 'aaa') 362 363 def testSortingRepeatedCompositeFieldsCustomComparator(self): 364 """Check passing a custom comparator to sort a repeated composite field.""" 365 message = unittest_pb2.TestAllTypes() 366 367 message.repeated_nested_message.add().bb = 1 368 message.repeated_nested_message.add().bb = 3 369 message.repeated_nested_message.add().bb = 2 370 message.repeated_nested_message.add().bb = 6 371 message.repeated_nested_message.add().bb = 5 372 message.repeated_nested_message.add().bb = 4 373 message.repeated_nested_message.sort(lambda x,y: cmp(x.bb, y.bb)) 374 self.assertEqual(message.repeated_nested_message[0].bb, 1) 375 self.assertEqual(message.repeated_nested_message[1].bb, 2) 376 self.assertEqual(message.repeated_nested_message[2].bb, 3) 377 self.assertEqual(message.repeated_nested_message[3].bb, 4) 378 self.assertEqual(message.repeated_nested_message[4].bb, 5) 379 self.assertEqual(message.repeated_nested_message[5].bb, 6) 380 381 def testRepeatedCompositeFieldSortArguments(self): 382 """Check sorting a repeated composite field using list.sort() arguments.""" 383 message = unittest_pb2.TestAllTypes() 384 385 get_bb = operator.attrgetter('bb') 386 cmp_bb = lambda a, b: cmp(a.bb, b.bb) 387 message.repeated_nested_message.add().bb = 1 388 message.repeated_nested_message.add().bb = 3 389 message.repeated_nested_message.add().bb = 2 390 message.repeated_nested_message.add().bb = 6 391 message.repeated_nested_message.add().bb = 5 392 message.repeated_nested_message.add().bb = 4 393 message.repeated_nested_message.sort(key=get_bb) 394 self.assertEqual([k.bb for k in message.repeated_nested_message], 395 [1, 2, 3, 4, 5, 6]) 396 message.repeated_nested_message.sort(key=get_bb, reverse=True) 397 self.assertEqual([k.bb for k in message.repeated_nested_message], 398 [6, 5, 4, 3, 2, 1]) 399 message.repeated_nested_message.sort(sort_function=cmp_bb) 400 self.assertEqual([k.bb for k in message.repeated_nested_message], 401 [1, 2, 3, 4, 5, 6]) 402 message.repeated_nested_message.sort(cmp=cmp_bb, reverse=True) 403 self.assertEqual([k.bb for k in message.repeated_nested_message], 404 [6, 5, 4, 3, 2, 1]) 405 406 def testRepeatedScalarFieldSortArguments(self): 407 """Check sorting a scalar field using list.sort() arguments.""" 408 message = unittest_pb2.TestAllTypes() 409 410 abs_cmp = lambda a, b: cmp(abs(a), abs(b)) 411 message.repeated_int32.append(-3) 412 message.repeated_int32.append(-2) 413 message.repeated_int32.append(-1) 414 message.repeated_int32.sort(key=abs) 415 self.assertEqual(list(message.repeated_int32), [-1, -2, -3]) 416 message.repeated_int32.sort(key=abs, reverse=True) 417 self.assertEqual(list(message.repeated_int32), [-3, -2, -1]) 418 message.repeated_int32.sort(sort_function=abs_cmp) 419 self.assertEqual(list(message.repeated_int32), [-1, -2, -3]) 420 message.repeated_int32.sort(cmp=abs_cmp, reverse=True) 421 self.assertEqual(list(message.repeated_int32), [-3, -2, -1]) 422 423 len_cmp = lambda a, b: cmp(len(a), len(b)) 424 message.repeated_string.append('aaa') 425 message.repeated_string.append('bb') 426 message.repeated_string.append('c') 427 message.repeated_string.sort(key=len) 428 self.assertEqual(list(message.repeated_string), ['c', 'bb', 'aaa']) 429 message.repeated_string.sort(key=len, reverse=True) 430 self.assertEqual(list(message.repeated_string), ['aaa', 'bb', 'c']) 431 message.repeated_string.sort(sort_function=len_cmp) 432 self.assertEqual(list(message.repeated_string), ['c', 'bb', 'aaa']) 433 message.repeated_string.sort(cmp=len_cmp, reverse=True) 434 self.assertEqual(list(message.repeated_string), ['aaa', 'bb', 'c']) 435 436 def testParsingMerge(self): 437 """Check the merge behavior when a required or optional field appears 438 multiple times in the input.""" 439 messages = [ 440 unittest_pb2.TestAllTypes(), 441 unittest_pb2.TestAllTypes(), 442 unittest_pb2.TestAllTypes() ] 443 messages[0].optional_int32 = 1 444 messages[1].optional_int64 = 2 445 messages[2].optional_int32 = 3 446 messages[2].optional_string = 'hello' 447 448 merged_message = unittest_pb2.TestAllTypes() 449 merged_message.optional_int32 = 3 450 merged_message.optional_int64 = 2 451 merged_message.optional_string = 'hello' 452 453 generator = unittest_pb2.TestParsingMerge.RepeatedFieldsGenerator() 454 generator.field1.extend(messages) 455 generator.field2.extend(messages) 456 generator.field3.extend(messages) 457 generator.ext1.extend(messages) 458 generator.ext2.extend(messages) 459 generator.group1.add().field1.MergeFrom(messages[0]) 460 generator.group1.add().field1.MergeFrom(messages[1]) 461 generator.group1.add().field1.MergeFrom(messages[2]) 462 generator.group2.add().field1.MergeFrom(messages[0]) 463 generator.group2.add().field1.MergeFrom(messages[1]) 464 generator.group2.add().field1.MergeFrom(messages[2]) 465 466 data = generator.SerializeToString() 467 parsing_merge = unittest_pb2.TestParsingMerge() 468 parsing_merge.ParseFromString(data) 469 470 # Required and optional fields should be merged. 471 self.assertEqual(parsing_merge.required_all_types, merged_message) 472 self.assertEqual(parsing_merge.optional_all_types, merged_message) 473 self.assertEqual(parsing_merge.optionalgroup.optional_group_all_types, 474 merged_message) 475 self.assertEqual(parsing_merge.Extensions[ 476 unittest_pb2.TestParsingMerge.optional_ext], 477 merged_message) 478 479 # Repeated fields should not be merged. 480 self.assertEqual(len(parsing_merge.repeated_all_types), 3) 481 self.assertEqual(len(parsing_merge.repeatedgroup), 3) 482 self.assertEqual(len(parsing_merge.Extensions[ 483 unittest_pb2.TestParsingMerge.repeated_ext]), 3) 484 485 486 def testSortEmptyRepeatedCompositeContainer(self): 487 """Exercise a scenario that has led to segfaults in the past. 488 """ 489 m = unittest_pb2.TestAllTypes() 490 m.repeated_nested_message.sort() 491 492 493if __name__ == '__main__': 494 unittest.main() 495