blob: 65174373d5f7215edbfc7d0c457f3c688acc8b41 [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.
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.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
kenton@google.com80b1d622009-07-29 01:13:20 +000048import unittest
49from google.protobuf import unittest_import_pb2
50from google.protobuf import unittest_pb2
51from google.protobuf.internal import test_util
52
liujisi@google.com33165fe2010-11-02 13:14:58 +000053# Python pre-2.6 does not have isinf() or isnan() functions, so we have
54# to provide our own.
55def isnan(val):
56 # NaN is never equal to itself.
57 return val != val
58def isinf(val):
59 # Infinity times zero equals NaN.
60 return not isnan(val) and isnan(val * 0)
61def IsPosInf(val):
62 return isinf(val) and (val > 0)
63def IsNegInf(val):
64 return isinf(val) and (val < 0)
kenton@google.com80b1d622009-07-29 01:13:20 +000065
kenton@google.comfccb1462009-12-18 02:11:36 +000066class MessageTest(unittest.TestCase):
kenton@google.com80b1d622009-07-29 01:13:20 +000067
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.comfccb1462009-12-18 02:11:36 +000072 test_util.ExpectAllFieldsSet(self, golden_message)
73 self.assertTrue(golden_message.SerializeToString() == golden_data)
liujisi@google.com33165fe2010-11-02 13:14:58 +000074 golden_copy = copy.deepcopy(golden_message)
75 self.assertTrue(golden_copy.SerializeToString() == golden_data)
kenton@google.com80b1d622009-07-29 01:13:20 +000076
kenton@google.comfccb1462009-12-18 02:11:36 +000077 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.com33165fe2010-11-02 13:14:58 +000085 golden_copy = copy.deepcopy(golden_message)
86 self.assertTrue(golden_copy.SerializeToString() == golden_data)
kenton@google.comfccb1462009-12-18 02:11:36 +000087
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.com33165fe2010-11-02 13:14:58 +000096 golden_copy = copy.deepcopy(golden_message)
97 self.assertTrue(golden_copy.SerializeToString() == golden_data)
kenton@google.comfccb1462009-12-18 02:11:36 +000098
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.com33165fe2010-11-02 13:14:58 +0000107 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.com80b1d622009-07-29 01:13:20 +0000341
342if __name__ == '__main__':
343 unittest.main()