kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 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 | |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 33 | """Tests python protocol buffers against the golden message. |
| 34 | |
| 35 | Note that the golden messages exercise every known field type, thus this |
| 36 | test ends up exercising and verifying nearly all of the parsing and |
| 37 | serialization code in the whole library. |
| 38 | |
| 39 | TODO(kenton): Merge with wire_format_test? It doesn't make a whole lot of |
| 40 | sense to call this a test of the "message" module, which only declares an |
| 41 | abstract interface. |
| 42 | """ |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 43 | |
| 44 | __author__ = 'gps@google.com (Gregory P. Smith)' |
| 45 | |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame^] | 46 | import copy |
| 47 | import math |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 48 | import unittest |
| 49 | from google.protobuf import unittest_import_pb2 |
| 50 | from google.protobuf import unittest_pb2 |
| 51 | from google.protobuf.internal import test_util |
| 52 | |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame^] | 53 | # Python pre-2.6 does not have isinf() or isnan() functions, so we have |
| 54 | # to provide our own. |
| 55 | def isnan(val): |
| 56 | # NaN is never equal to itself. |
| 57 | return val != val |
| 58 | def isinf(val): |
| 59 | # Infinity times zero equals NaN. |
| 60 | return not isnan(val) and isnan(val * 0) |
| 61 | def IsPosInf(val): |
| 62 | return isinf(val) and (val > 0) |
| 63 | def IsNegInf(val): |
| 64 | return isinf(val) and (val < 0) |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 65 | |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 66 | class MessageTest(unittest.TestCase): |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 67 | |
| 68 | def testGoldenMessage(self): |
| 69 | golden_data = test_util.GoldenFile('golden_message').read() |
| 70 | golden_message = unittest_pb2.TestAllTypes() |
| 71 | golden_message.ParseFromString(golden_data) |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 72 | test_util.ExpectAllFieldsSet(self, golden_message) |
| 73 | self.assertTrue(golden_message.SerializeToString() == golden_data) |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame^] | 74 | golden_copy = copy.deepcopy(golden_message) |
| 75 | self.assertTrue(golden_copy.SerializeToString() == golden_data) |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 76 | |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 77 | def testGoldenExtensions(self): |
| 78 | golden_data = test_util.GoldenFile('golden_message').read() |
| 79 | golden_message = unittest_pb2.TestAllExtensions() |
| 80 | golden_message.ParseFromString(golden_data) |
| 81 | all_set = unittest_pb2.TestAllExtensions() |
| 82 | test_util.SetAllExtensions(all_set) |
| 83 | self.assertEquals(all_set, golden_message) |
| 84 | self.assertTrue(golden_message.SerializeToString() == golden_data) |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame^] | 85 | golden_copy = copy.deepcopy(golden_message) |
| 86 | self.assertTrue(golden_copy.SerializeToString() == golden_data) |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 87 | |
| 88 | def testGoldenPackedMessage(self): |
| 89 | golden_data = test_util.GoldenFile('golden_packed_fields_message').read() |
| 90 | golden_message = unittest_pb2.TestPackedTypes() |
| 91 | golden_message.ParseFromString(golden_data) |
| 92 | all_set = unittest_pb2.TestPackedTypes() |
| 93 | test_util.SetAllPackedFields(all_set) |
| 94 | self.assertEquals(all_set, golden_message) |
| 95 | self.assertTrue(all_set.SerializeToString() == golden_data) |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame^] | 96 | golden_copy = copy.deepcopy(golden_message) |
| 97 | self.assertTrue(golden_copy.SerializeToString() == golden_data) |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 98 | |
| 99 | def testGoldenPackedExtensions(self): |
| 100 | golden_data = test_util.GoldenFile('golden_packed_fields_message').read() |
| 101 | golden_message = unittest_pb2.TestPackedExtensions() |
| 102 | golden_message.ParseFromString(golden_data) |
| 103 | all_set = unittest_pb2.TestPackedExtensions() |
| 104 | test_util.SetAllPackedExtensions(all_set) |
| 105 | self.assertEquals(all_set, golden_message) |
| 106 | self.assertTrue(all_set.SerializeToString() == golden_data) |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame^] | 107 | golden_copy = copy.deepcopy(golden_message) |
| 108 | self.assertTrue(golden_copy.SerializeToString() == golden_data) |
| 109 | |
| 110 | def testPositiveInfinity(self): |
| 111 | golden_data = ('\x5D\x00\x00\x80\x7F' |
| 112 | '\x61\x00\x00\x00\x00\x00\x00\xF0\x7F' |
| 113 | '\xCD\x02\x00\x00\x80\x7F' |
| 114 | '\xD1\x02\x00\x00\x00\x00\x00\x00\xF0\x7F') |
| 115 | golden_message = unittest_pb2.TestAllTypes() |
| 116 | golden_message.ParseFromString(golden_data) |
| 117 | self.assertTrue(IsPosInf(golden_message.optional_float)) |
| 118 | self.assertTrue(IsPosInf(golden_message.optional_double)) |
| 119 | self.assertTrue(IsPosInf(golden_message.repeated_float[0])) |
| 120 | self.assertTrue(IsPosInf(golden_message.repeated_double[0])) |
| 121 | self.assertTrue(golden_message.SerializeToString() == golden_data) |
| 122 | |
| 123 | def testNegativeInfinity(self): |
| 124 | golden_data = ('\x5D\x00\x00\x80\xFF' |
| 125 | '\x61\x00\x00\x00\x00\x00\x00\xF0\xFF' |
| 126 | '\xCD\x02\x00\x00\x80\xFF' |
| 127 | '\xD1\x02\x00\x00\x00\x00\x00\x00\xF0\xFF') |
| 128 | golden_message = unittest_pb2.TestAllTypes() |
| 129 | golden_message.ParseFromString(golden_data) |
| 130 | self.assertTrue(IsNegInf(golden_message.optional_float)) |
| 131 | self.assertTrue(IsNegInf(golden_message.optional_double)) |
| 132 | self.assertTrue(IsNegInf(golden_message.repeated_float[0])) |
| 133 | self.assertTrue(IsNegInf(golden_message.repeated_double[0])) |
| 134 | self.assertTrue(golden_message.SerializeToString() == golden_data) |
| 135 | |
| 136 | def testNotANumber(self): |
| 137 | golden_data = ('\x5D\x00\x00\xC0\x7F' |
| 138 | '\x61\x00\x00\x00\x00\x00\x00\xF8\x7F' |
| 139 | '\xCD\x02\x00\x00\xC0\x7F' |
| 140 | '\xD1\x02\x00\x00\x00\x00\x00\x00\xF8\x7F') |
| 141 | golden_message = unittest_pb2.TestAllTypes() |
| 142 | golden_message.ParseFromString(golden_data) |
| 143 | self.assertTrue(isnan(golden_message.optional_float)) |
| 144 | self.assertTrue(isnan(golden_message.optional_double)) |
| 145 | self.assertTrue(isnan(golden_message.repeated_float[0])) |
| 146 | self.assertTrue(isnan(golden_message.repeated_double[0])) |
| 147 | self.assertTrue(golden_message.SerializeToString() == golden_data) |
| 148 | |
| 149 | def testPositiveInfinityPacked(self): |
| 150 | golden_data = ('\xA2\x06\x04\x00\x00\x80\x7F' |
| 151 | '\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF0\x7F') |
| 152 | golden_message = unittest_pb2.TestPackedTypes() |
| 153 | golden_message.ParseFromString(golden_data) |
| 154 | self.assertTrue(IsPosInf(golden_message.packed_float[0])) |
| 155 | self.assertTrue(IsPosInf(golden_message.packed_double[0])) |
| 156 | self.assertTrue(golden_message.SerializeToString() == golden_data) |
| 157 | |
| 158 | def testNegativeInfinityPacked(self): |
| 159 | golden_data = ('\xA2\x06\x04\x00\x00\x80\xFF' |
| 160 | '\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF0\xFF') |
| 161 | golden_message = unittest_pb2.TestPackedTypes() |
| 162 | golden_message.ParseFromString(golden_data) |
| 163 | self.assertTrue(IsNegInf(golden_message.packed_float[0])) |
| 164 | self.assertTrue(IsNegInf(golden_message.packed_double[0])) |
| 165 | self.assertTrue(golden_message.SerializeToString() == golden_data) |
| 166 | |
| 167 | def testNotANumberPacked(self): |
| 168 | golden_data = ('\xA2\x06\x04\x00\x00\xC0\x7F' |
| 169 | '\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF8\x7F') |
| 170 | golden_message = unittest_pb2.TestPackedTypes() |
| 171 | golden_message.ParseFromString(golden_data) |
| 172 | self.assertTrue(isnan(golden_message.packed_float[0])) |
| 173 | self.assertTrue(isnan(golden_message.packed_double[0])) |
| 174 | self.assertTrue(golden_message.SerializeToString() == golden_data) |
| 175 | |
| 176 | def testExtremeFloatValues(self): |
| 177 | message = unittest_pb2.TestAllTypes() |
| 178 | |
| 179 | # Most positive exponent, no significand bits set. |
| 180 | kMostPosExponentNoSigBits = math.pow(2, 127) |
| 181 | message.optional_float = kMostPosExponentNoSigBits |
| 182 | message.ParseFromString(message.SerializeToString()) |
| 183 | self.assertTrue(message.optional_float == kMostPosExponentNoSigBits) |
| 184 | |
| 185 | # Most positive exponent, one significand bit set. |
| 186 | kMostPosExponentOneSigBit = 1.5 * math.pow(2, 127) |
| 187 | message.optional_float = kMostPosExponentOneSigBit |
| 188 | message.ParseFromString(message.SerializeToString()) |
| 189 | self.assertTrue(message.optional_float == kMostPosExponentOneSigBit) |
| 190 | |
| 191 | # Repeat last two cases with values of same magnitude, but negative. |
| 192 | message.optional_float = -kMostPosExponentNoSigBits |
| 193 | message.ParseFromString(message.SerializeToString()) |
| 194 | self.assertTrue(message.optional_float == -kMostPosExponentNoSigBits) |
| 195 | |
| 196 | message.optional_float = -kMostPosExponentOneSigBit |
| 197 | message.ParseFromString(message.SerializeToString()) |
| 198 | self.assertTrue(message.optional_float == -kMostPosExponentOneSigBit) |
| 199 | |
| 200 | # Most negative exponent, no significand bits set. |
| 201 | kMostNegExponentNoSigBits = math.pow(2, -127) |
| 202 | message.optional_float = kMostNegExponentNoSigBits |
| 203 | message.ParseFromString(message.SerializeToString()) |
| 204 | self.assertTrue(message.optional_float == kMostNegExponentNoSigBits) |
| 205 | |
| 206 | # Most negative exponent, one significand bit set. |
| 207 | kMostNegExponentOneSigBit = 1.5 * math.pow(2, -127) |
| 208 | message.optional_float = kMostNegExponentOneSigBit |
| 209 | message.ParseFromString(message.SerializeToString()) |
| 210 | self.assertTrue(message.optional_float == kMostNegExponentOneSigBit) |
| 211 | |
| 212 | # Repeat last two cases with values of the same magnitude, but negative. |
| 213 | message.optional_float = -kMostNegExponentNoSigBits |
| 214 | message.ParseFromString(message.SerializeToString()) |
| 215 | self.assertTrue(message.optional_float == -kMostNegExponentNoSigBits) |
| 216 | |
| 217 | message.optional_float = -kMostNegExponentOneSigBit |
| 218 | message.ParseFromString(message.SerializeToString()) |
| 219 | self.assertTrue(message.optional_float == -kMostNegExponentOneSigBit) |
| 220 | |
| 221 | def testExtremeFloatValues(self): |
| 222 | message = unittest_pb2.TestAllTypes() |
| 223 | |
| 224 | # Most positive exponent, no significand bits set. |
| 225 | kMostPosExponentNoSigBits = math.pow(2, 1023) |
| 226 | message.optional_double = kMostPosExponentNoSigBits |
| 227 | message.ParseFromString(message.SerializeToString()) |
| 228 | self.assertTrue(message.optional_double == kMostPosExponentNoSigBits) |
| 229 | |
| 230 | # Most positive exponent, one significand bit set. |
| 231 | kMostPosExponentOneSigBit = 1.5 * math.pow(2, 1023) |
| 232 | message.optional_double = kMostPosExponentOneSigBit |
| 233 | message.ParseFromString(message.SerializeToString()) |
| 234 | self.assertTrue(message.optional_double == kMostPosExponentOneSigBit) |
| 235 | |
| 236 | # Repeat last two cases with values of same magnitude, but negative. |
| 237 | message.optional_double = -kMostPosExponentNoSigBits |
| 238 | message.ParseFromString(message.SerializeToString()) |
| 239 | self.assertTrue(message.optional_double == -kMostPosExponentNoSigBits) |
| 240 | |
| 241 | message.optional_double = -kMostPosExponentOneSigBit |
| 242 | message.ParseFromString(message.SerializeToString()) |
| 243 | self.assertTrue(message.optional_double == -kMostPosExponentOneSigBit) |
| 244 | |
| 245 | # Most negative exponent, no significand bits set. |
| 246 | kMostNegExponentNoSigBits = math.pow(2, -1023) |
| 247 | message.optional_double = kMostNegExponentNoSigBits |
| 248 | message.ParseFromString(message.SerializeToString()) |
| 249 | self.assertTrue(message.optional_double == kMostNegExponentNoSigBits) |
| 250 | |
| 251 | # Most negative exponent, one significand bit set. |
| 252 | kMostNegExponentOneSigBit = 1.5 * math.pow(2, -1023) |
| 253 | message.optional_double = kMostNegExponentOneSigBit |
| 254 | message.ParseFromString(message.SerializeToString()) |
| 255 | self.assertTrue(message.optional_double == kMostNegExponentOneSigBit) |
| 256 | |
| 257 | # Repeat last two cases with values of the same magnitude, but negative. |
| 258 | message.optional_double = -kMostNegExponentNoSigBits |
| 259 | message.ParseFromString(message.SerializeToString()) |
| 260 | self.assertTrue(message.optional_double == -kMostNegExponentNoSigBits) |
| 261 | |
| 262 | message.optional_double = -kMostNegExponentOneSigBit |
| 263 | message.ParseFromString(message.SerializeToString()) |
| 264 | self.assertTrue(message.optional_double == -kMostNegExponentOneSigBit) |
| 265 | |
| 266 | def testSortingRepeatedScalarFieldsDefaultComparator(self): |
| 267 | """Check some different types with the default comparator.""" |
| 268 | message = unittest_pb2.TestAllTypes() |
| 269 | |
| 270 | # TODO(mattp): would testing more scalar types strengthen test? |
| 271 | message.repeated_int32.append(1) |
| 272 | message.repeated_int32.append(3) |
| 273 | message.repeated_int32.append(2) |
| 274 | message.repeated_int32.sort() |
| 275 | self.assertEqual(message.repeated_int32[0], 1) |
| 276 | self.assertEqual(message.repeated_int32[1], 2) |
| 277 | self.assertEqual(message.repeated_int32[2], 3) |
| 278 | |
| 279 | message.repeated_float.append(1.1) |
| 280 | message.repeated_float.append(1.3) |
| 281 | message.repeated_float.append(1.2) |
| 282 | message.repeated_float.sort() |
| 283 | self.assertAlmostEqual(message.repeated_float[0], 1.1) |
| 284 | self.assertAlmostEqual(message.repeated_float[1], 1.2) |
| 285 | self.assertAlmostEqual(message.repeated_float[2], 1.3) |
| 286 | |
| 287 | message.repeated_string.append('a') |
| 288 | message.repeated_string.append('c') |
| 289 | message.repeated_string.append('b') |
| 290 | message.repeated_string.sort() |
| 291 | self.assertEqual(message.repeated_string[0], 'a') |
| 292 | self.assertEqual(message.repeated_string[1], 'b') |
| 293 | self.assertEqual(message.repeated_string[2], 'c') |
| 294 | |
| 295 | message.repeated_bytes.append('a') |
| 296 | message.repeated_bytes.append('c') |
| 297 | message.repeated_bytes.append('b') |
| 298 | message.repeated_bytes.sort() |
| 299 | self.assertEqual(message.repeated_bytes[0], 'a') |
| 300 | self.assertEqual(message.repeated_bytes[1], 'b') |
| 301 | self.assertEqual(message.repeated_bytes[2], 'c') |
| 302 | |
| 303 | def testSortingRepeatedScalarFieldsCustomComparator(self): |
| 304 | """Check some different types with custom comparator.""" |
| 305 | message = unittest_pb2.TestAllTypes() |
| 306 | |
| 307 | message.repeated_int32.append(-3) |
| 308 | message.repeated_int32.append(-2) |
| 309 | message.repeated_int32.append(-1) |
| 310 | message.repeated_int32.sort(lambda x,y: cmp(abs(x), abs(y))) |
| 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 | |
| 315 | message.repeated_string.append('aaa') |
| 316 | message.repeated_string.append('bb') |
| 317 | message.repeated_string.append('c') |
| 318 | message.repeated_string.sort(lambda x,y: cmp(len(x), len(y))) |
| 319 | self.assertEqual(message.repeated_string[0], 'c') |
| 320 | self.assertEqual(message.repeated_string[1], 'bb') |
| 321 | self.assertEqual(message.repeated_string[2], 'aaa') |
| 322 | |
| 323 | def testSortingRepeatedCompositeFieldsCustomComparator(self): |
| 324 | """Check passing a custom comparator to sort a repeated composite field.""" |
| 325 | message = unittest_pb2.TestAllTypes() |
| 326 | |
| 327 | message.repeated_nested_message.add().bb = 1 |
| 328 | message.repeated_nested_message.add().bb = 3 |
| 329 | message.repeated_nested_message.add().bb = 2 |
| 330 | message.repeated_nested_message.add().bb = 6 |
| 331 | message.repeated_nested_message.add().bb = 5 |
| 332 | message.repeated_nested_message.add().bb = 4 |
| 333 | message.repeated_nested_message.sort(lambda x,y: cmp(x.bb, y.bb)) |
| 334 | self.assertEqual(message.repeated_nested_message[0].bb, 1) |
| 335 | self.assertEqual(message.repeated_nested_message[1].bb, 2) |
| 336 | self.assertEqual(message.repeated_nested_message[2].bb, 3) |
| 337 | self.assertEqual(message.repeated_nested_message[3].bb, 4) |
| 338 | self.assertEqual(message.repeated_nested_message[4].bb, 5) |
| 339 | self.assertEqual(message.repeated_nested_message[5].bb, 6) |
| 340 | |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 341 | |
| 342 | if __name__ == '__main__': |
| 343 | unittest.main() |