blob: a354778238f75cf641b961a23d38f5e9458e2fab [file] [log] [blame]
kenton@google.com26bd9ee2008-11-21 00:06:27 +00001#! /usr/bin/python
2#
temporal40ee5512008-07-10 02:12:20 +00003# Protocol Buffers - Google's data interchange format
kenton@google.com24bf56f2008-09-24 20:31:01 +00004# Copyright 2008 Google Inc. All rights reserved.
temporal40ee5512008-07-10 02:12:20 +00005# http://code.google.com/p/protobuf/
6#
kenton@google.com24bf56f2008-09-24 20:31:01 +00007# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions are
9# met:
temporal40ee5512008-07-10 02:12:20 +000010#
kenton@google.com24bf56f2008-09-24 20:31:01 +000011# * 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.
temporal40ee5512008-07-10 02:12:20 +000020#
kenton@google.com24bf56f2008-09-24 20:31:01 +000021# 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.
temporal40ee5512008-07-10 02:12:20 +000032
33"""Test for google.protobuf.text_format."""
34
35__author__ = 'kenton@google.com (Kenton Varda)'
36
37import difflib
liujisi@google.com33165fe2010-11-02 13:14:58 +000038import re
temporal40ee5512008-07-10 02:12:20 +000039
40import unittest
41from google.protobuf import text_format
42from google.protobuf.internal import test_util
43from google.protobuf import unittest_pb2
44from google.protobuf import unittest_mset_pb2
45
kenton@google.com80b1d622009-07-29 01:13:20 +000046
kenton@google.comfccb1462009-12-18 02:11:36 +000047class TextFormatTest(unittest.TestCase):
kenton@google.com80b1d622009-07-29 01:13:20 +000048 def ReadGolden(self, golden_filename):
temporal40ee5512008-07-10 02:12:20 +000049 f = test_util.GoldenFile(golden_filename)
50 golden_lines = f.readlines()
51 f.close()
kenton@google.com80b1d622009-07-29 01:13:20 +000052 return golden_lines
53
54 def CompareToGoldenFile(self, text, golden_filename):
55 golden_lines = self.ReadGolden(golden_filename)
temporal40ee5512008-07-10 02:12:20 +000056 self.CompareToGoldenLines(text, golden_lines)
57
58 def CompareToGoldenText(self, text, golden_text):
59 self.CompareToGoldenLines(text, golden_text.splitlines(1))
60
61 def CompareToGoldenLines(self, text, golden_lines):
62 actual_lines = text.splitlines(1)
63 self.assertEqual(golden_lines, actual_lines,
64 "Text doesn't match golden. Diff:\n" +
65 ''.join(difflib.ndiff(golden_lines, actual_lines)))
66
67 def testPrintAllFields(self):
68 message = unittest_pb2.TestAllTypes()
69 test_util.SetAllFields(message)
temporalf2063512008-07-23 01:19:07 +000070 self.CompareToGoldenFile(
71 self.RemoveRedundantZeros(text_format.MessageToString(message)),
72 'text_format_unittest_data.txt')
temporal40ee5512008-07-10 02:12:20 +000073
74 def testPrintAllExtensions(self):
75 message = unittest_pb2.TestAllExtensions()
76 test_util.SetAllExtensions(message)
temporalf2063512008-07-23 01:19:07 +000077 self.CompareToGoldenFile(
78 self.RemoveRedundantZeros(text_format.MessageToString(message)),
79 'text_format_unittest_extensions_data.txt')
temporal40ee5512008-07-10 02:12:20 +000080
81 def testPrintMessageSet(self):
82 message = unittest_mset_pb2.TestMessageSetContainer()
83 ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
84 ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
85 message.message_set.Extensions[ext1].i = 23
86 message.message_set.Extensions[ext2].str = 'foo'
87 self.CompareToGoldenText(text_format.MessageToString(message),
88 'message_set {\n'
89 ' [protobuf_unittest.TestMessageSetExtension1] {\n'
90 ' i: 23\n'
91 ' }\n'
92 ' [protobuf_unittest.TestMessageSetExtension2] {\n'
93 ' str: \"foo\"\n'
94 ' }\n'
95 '}\n')
96
97 def testPrintExotic(self):
98 message = unittest_pb2.TestAllTypes()
liujisi@google.com33165fe2010-11-02 13:14:58 +000099 message.repeated_int64.append(-9223372036854775808)
100 message.repeated_uint64.append(18446744073709551615)
101 message.repeated_double.append(123.456)
102 message.repeated_double.append(1.23e22)
103 message.repeated_double.append(1.23e-18)
104 message.repeated_string.append('\000\001\a\b\f\n\r\t\v\\\'"')
105 message.repeated_string.append(u'\u00fc\ua71f')
temporalf2063512008-07-23 01:19:07 +0000106 self.CompareToGoldenText(
107 self.RemoveRedundantZeros(text_format.MessageToString(message)),
temporal40ee5512008-07-10 02:12:20 +0000108 'repeated_int64: -9223372036854775808\n'
109 'repeated_uint64: 18446744073709551615\n'
110 'repeated_double: 123.456\n'
111 'repeated_double: 1.23e+22\n'
112 'repeated_double: 1.23e-18\n'
113 'repeated_string: '
liujisi@google.com33165fe2010-11-02 13:14:58 +0000114 '"\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\""\n'
115 'repeated_string: "\\303\\274\\352\\234\\237"\n')
116
117 def testPrintNestedMessageAsOneLine(self):
118 message = unittest_pb2.TestAllTypes()
119 msg = message.repeated_nested_message.add()
120 msg.bb = 42;
121 self.CompareToGoldenText(
122 text_format.MessageToString(message, as_one_line=True),
123 'repeated_nested_message { bb: 42 }')
124
125 def testPrintRepeatedFieldsAsOneLine(self):
126 message = unittest_pb2.TestAllTypes()
127 message.repeated_int32.append(1)
128 message.repeated_int32.append(1)
129 message.repeated_int32.append(3)
130 message.repeated_string.append("Google")
131 message.repeated_string.append("Zurich")
132 self.CompareToGoldenText(
133 text_format.MessageToString(message, as_one_line=True),
134 'repeated_int32: 1 repeated_int32: 1 repeated_int32: 3 '
135 'repeated_string: "Google" repeated_string: "Zurich"')
136
137 def testPrintNestedNewLineInStringAsOneLine(self):
138 message = unittest_pb2.TestAllTypes()
139 message.optional_string = "a\nnew\nline"
140 self.CompareToGoldenText(
141 text_format.MessageToString(message, as_one_line=True),
142 'optional_string: "a\\nnew\\nline"')
143
144 def testPrintMessageSetAsOneLine(self):
145 message = unittest_mset_pb2.TestMessageSetContainer()
146 ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
147 ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
148 message.message_set.Extensions[ext1].i = 23
149 message.message_set.Extensions[ext2].str = 'foo'
150 self.CompareToGoldenText(
151 text_format.MessageToString(message, as_one_line=True),
152 'message_set {'
153 ' [protobuf_unittest.TestMessageSetExtension1] {'
154 ' i: 23'
155 ' }'
156 ' [protobuf_unittest.TestMessageSetExtension2] {'
157 ' str: \"foo\"'
158 ' }'
159 ' }')
160
161 def testPrintExoticAsOneLine(self):
162 message = unittest_pb2.TestAllTypes()
163 message.repeated_int64.append(-9223372036854775808)
164 message.repeated_uint64.append(18446744073709551615)
165 message.repeated_double.append(123.456)
166 message.repeated_double.append(1.23e22)
167 message.repeated_double.append(1.23e-18)
168 message.repeated_string.append('\000\001\a\b\f\n\r\t\v\\\'"')
169 message.repeated_string.append(u'\u00fc\ua71f')
170 self.CompareToGoldenText(
171 self.RemoveRedundantZeros(
172 text_format.MessageToString(message, as_one_line=True)),
173 'repeated_int64: -9223372036854775808'
174 ' repeated_uint64: 18446744073709551615'
175 ' repeated_double: 123.456'
176 ' repeated_double: 1.23e+22'
177 ' repeated_double: 1.23e-18'
178 ' repeated_string: '
179 '"\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\""'
180 ' repeated_string: "\\303\\274\\352\\234\\237"')
181
182 def testRoundTripExoticAsOneLine(self):
183 message = unittest_pb2.TestAllTypes()
184 message.repeated_int64.append(-9223372036854775808)
185 message.repeated_uint64.append(18446744073709551615)
186 message.repeated_double.append(123.456)
187 message.repeated_double.append(1.23e22)
188 message.repeated_double.append(1.23e-18)
189 message.repeated_string.append('\000\001\a\b\f\n\r\t\v\\\'"')
190 message.repeated_string.append(u'\u00fc\ua71f')
191
192 wire_text = text_format.MessageToString(message, as_one_line=True)
193 parsed_message = unittest_pb2.TestAllTypes()
194 text_format.Merge(wire_text, parsed_message)
195 self.assertEquals(message, parsed_message)
196
197 def testPrintRawUtf8String(self):
198 message = unittest_pb2.TestAllTypes()
199 message.repeated_string.append(u'\u00fc\ua71f')
200 self.CompareToGoldenText(
201 text_format.MessageToString(message, as_utf8 = True),
202 'repeated_string: "\303\274\352\234\237"\n')
temporal40ee5512008-07-10 02:12:20 +0000203
204 def testMessageToString(self):
205 message = unittest_pb2.ForeignMessage()
206 message.c = 123
207 self.assertEqual('c: 123\n', str(message))
208
temporalf2063512008-07-23 01:19:07 +0000209 def RemoveRedundantZeros(self, text):
210 # Some platforms print 1e+5 as 1e+005. This is fine, but we need to remove
211 # these zeros in order to match the golden file.
liujisi@google.com33165fe2010-11-02 13:14:58 +0000212 text = text.replace('e+0','e+').replace('e+0','e+') \
temporalf2063512008-07-23 01:19:07 +0000213 .replace('e-0','e-').replace('e-0','e-')
liujisi@google.com33165fe2010-11-02 13:14:58 +0000214 # Floating point fields are printed with .0 suffix even if they are
215 # actualy integer numbers.
216 text = re.compile('\.0$', re.MULTILINE).sub('', text)
217 return text
temporalf2063512008-07-23 01:19:07 +0000218
kenton@google.com80b1d622009-07-29 01:13:20 +0000219 def testMergeGolden(self):
220 golden_text = '\n'.join(self.ReadGolden('text_format_unittest_data.txt'))
221 parsed_message = unittest_pb2.TestAllTypes()
222 text_format.Merge(golden_text, parsed_message)
223
224 message = unittest_pb2.TestAllTypes()
225 test_util.SetAllFields(message)
226 self.assertEquals(message, parsed_message)
227
228 def testMergeGoldenExtensions(self):
229 golden_text = '\n'.join(self.ReadGolden(
230 'text_format_unittest_extensions_data.txt'))
231 parsed_message = unittest_pb2.TestAllExtensions()
232 text_format.Merge(golden_text, parsed_message)
233
234 message = unittest_pb2.TestAllExtensions()
235 test_util.SetAllExtensions(message)
236 self.assertEquals(message, parsed_message)
237
238 def testMergeAllFields(self):
239 message = unittest_pb2.TestAllTypes()
240 test_util.SetAllFields(message)
241 ascii_text = text_format.MessageToString(message)
242
243 parsed_message = unittest_pb2.TestAllTypes()
244 text_format.Merge(ascii_text, parsed_message)
245 self.assertEqual(message, parsed_message)
kenton@google.comfccb1462009-12-18 02:11:36 +0000246 test_util.ExpectAllFieldsSet(self, message)
kenton@google.com80b1d622009-07-29 01:13:20 +0000247
248 def testMergeAllExtensions(self):
249 message = unittest_pb2.TestAllExtensions()
250 test_util.SetAllExtensions(message)
251 ascii_text = text_format.MessageToString(message)
252
253 parsed_message = unittest_pb2.TestAllExtensions()
254 text_format.Merge(ascii_text, parsed_message)
255 self.assertEqual(message, parsed_message)
256
257 def testMergeMessageSet(self):
258 message = unittest_pb2.TestAllTypes()
259 text = ('repeated_uint64: 1\n'
260 'repeated_uint64: 2\n')
261 text_format.Merge(text, message)
262 self.assertEqual(1, message.repeated_uint64[0])
263 self.assertEqual(2, message.repeated_uint64[1])
264
265 message = unittest_mset_pb2.TestMessageSetContainer()
266 text = ('message_set {\n'
267 ' [protobuf_unittest.TestMessageSetExtension1] {\n'
268 ' i: 23\n'
269 ' }\n'
270 ' [protobuf_unittest.TestMessageSetExtension2] {\n'
271 ' str: \"foo\"\n'
272 ' }\n'
273 '}\n')
274 text_format.Merge(text, message)
275 ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
276 ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
277 self.assertEquals(23, message.message_set.Extensions[ext1].i)
278 self.assertEquals('foo', message.message_set.Extensions[ext2].str)
279
280 def testMergeExotic(self):
281 message = unittest_pb2.TestAllTypes()
282 text = ('repeated_int64: -9223372036854775808\n'
283 'repeated_uint64: 18446744073709551615\n'
284 'repeated_double: 123.456\n'
285 'repeated_double: 1.23e+22\n'
286 'repeated_double: 1.23e-18\n'
287 'repeated_string: \n'
liujisi@google.com33165fe2010-11-02 13:14:58 +0000288 '"\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\""\n'
289 'repeated_string: "foo" \'corge\' "grault"\n'
290 'repeated_string: "\\303\\274\\352\\234\\237"\n'
291 'repeated_string: "\\xc3\\xbc"\n'
292 'repeated_string: "\xc3\xbc"\n')
kenton@google.com80b1d622009-07-29 01:13:20 +0000293 text_format.Merge(text, message)
294
295 self.assertEqual(-9223372036854775808, message.repeated_int64[0])
296 self.assertEqual(18446744073709551615, message.repeated_uint64[0])
297 self.assertEqual(123.456, message.repeated_double[0])
298 self.assertEqual(1.23e22, message.repeated_double[1])
299 self.assertEqual(1.23e-18, message.repeated_double[2])
300 self.assertEqual(
liujisi@google.com33165fe2010-11-02 13:14:58 +0000301 '\000\001\a\b\f\n\r\t\v\\\'"', message.repeated_string[0])
kenton@google.comeef5f832009-12-23 01:32:45 +0000302 self.assertEqual('foocorgegrault', message.repeated_string[1])
liujisi@google.com33165fe2010-11-02 13:14:58 +0000303 self.assertEqual(u'\u00fc\ua71f', message.repeated_string[2])
304 self.assertEqual(u'\u00fc', message.repeated_string[3])
305
306 def testMergeEmptyText(self):
307 message = unittest_pb2.TestAllTypes()
308 text = ''
309 text_format.Merge(text, message)
310 self.assertEquals(unittest_pb2.TestAllTypes(), message)
311
312 def testMergeInvalidUtf8(self):
313 message = unittest_pb2.TestAllTypes()
314 text = 'repeated_string: "\\xc3\\xc3"'
315 self.assertRaises(text_format.ParseError, text_format.Merge, text, message)
316
317 def testMergeSingleWord(self):
318 message = unittest_pb2.TestAllTypes()
319 text = 'foo'
320 self.assertRaisesWithMessage(
321 text_format.ParseError,
322 ('1:1 : Message type "protobuf_unittest.TestAllTypes" has no field named '
323 '"foo".'),
324 text_format.Merge, text, message)
kenton@google.com80b1d622009-07-29 01:13:20 +0000325
326 def testMergeUnknownField(self):
327 message = unittest_pb2.TestAllTypes()
328 text = 'unknown_field: 8\n'
329 self.assertRaisesWithMessage(
330 text_format.ParseError,
331 ('1:1 : Message type "protobuf_unittest.TestAllTypes" has no field named '
332 '"unknown_field".'),
333 text_format.Merge, text, message)
334
335 def testMergeBadExtension(self):
kenton@google.comfccb1462009-12-18 02:11:36 +0000336 message = unittest_pb2.TestAllExtensions()
kenton@google.com80b1d622009-07-29 01:13:20 +0000337 text = '[unknown_extension]: 8\n'
338 self.assertRaisesWithMessage(
339 text_format.ParseError,
340 '1:2 : Extension "unknown_extension" not registered.',
341 text_format.Merge, text, message)
kenton@google.comfccb1462009-12-18 02:11:36 +0000342 message = unittest_pb2.TestAllTypes()
343 self.assertRaisesWithMessage(
344 text_format.ParseError,
345 ('1:2 : Message type "protobuf_unittest.TestAllTypes" does not have '
346 'extensions.'),
347 text_format.Merge, text, message)
kenton@google.com80b1d622009-07-29 01:13:20 +0000348
349 def testMergeGroupNotClosed(self):
350 message = unittest_pb2.TestAllTypes()
351 text = 'RepeatedGroup: <'
352 self.assertRaisesWithMessage(
353 text_format.ParseError, '1:16 : Expected ">".',
354 text_format.Merge, text, message)
355
356 text = 'RepeatedGroup: {'
357 self.assertRaisesWithMessage(
358 text_format.ParseError, '1:16 : Expected "}".',
359 text_format.Merge, text, message)
360
kenton@google.comfccb1462009-12-18 02:11:36 +0000361 def testMergeEmptyGroup(self):
362 message = unittest_pb2.TestAllTypes()
363 text = 'OptionalGroup: {}'
364 text_format.Merge(text, message)
365 self.assertTrue(message.HasField('optionalgroup'))
366
367 message.Clear()
368
369 message = unittest_pb2.TestAllTypes()
370 text = 'OptionalGroup: <>'
371 text_format.Merge(text, message)
372 self.assertTrue(message.HasField('optionalgroup'))
373
kenton@google.com80b1d622009-07-29 01:13:20 +0000374 def testMergeBadEnumValue(self):
375 message = unittest_pb2.TestAllTypes()
376 text = 'optional_nested_enum: BARR'
377 self.assertRaisesWithMessage(
378 text_format.ParseError,
379 ('1:23 : Enum type "protobuf_unittest.TestAllTypes.NestedEnum" '
380 'has no value named BARR.'),
381 text_format.Merge, text, message)
382
383 message = unittest_pb2.TestAllTypes()
384 text = 'optional_nested_enum: 100'
385 self.assertRaisesWithMessage(
386 text_format.ParseError,
387 ('1:23 : Enum type "protobuf_unittest.TestAllTypes.NestedEnum" '
388 'has no value with number 100.'),
389 text_format.Merge, text, message)
390
391 def assertRaisesWithMessage(self, e_class, e, func, *args, **kwargs):
392 """Same as assertRaises, but also compares the exception message."""
393 if hasattr(e_class, '__name__'):
394 exc_name = e_class.__name__
395 else:
396 exc_name = str(e_class)
397
398 try:
399 func(*args, **kwargs)
400 except e_class, expr:
401 if str(expr) != e:
402 msg = '%s raised, but with wrong message: "%s" instead of "%s"'
403 raise self.failureException(msg % (exc_name,
404 str(expr).encode('string_escape'),
405 e.encode('string_escape')))
406 return
407 else:
408 raise self.failureException('%s not raised' % exc_name)
409
410
411class TokenizerTest(unittest.TestCase):
412
413 def testSimpleTokenCases(self):
414 text = ('identifier1:"string1"\n \n\n'
415 'identifier2 : \n \n123 \n identifier3 :\'string\'\n'
416 'identifiER_4 : 1.1e+2 ID5:-0.23 ID6:\'aaaa\\\'bbbb\'\n'
417 'ID7 : "aa\\"bb"\n\n\n\n ID8: {A:inf B:-inf C:true D:false}\n'
418 'ID9: 22 ID10: -111111111111111111 ID11: -22\n'
liujisi@google.com33165fe2010-11-02 13:14:58 +0000419 'ID12: 2222222222222222222 '
420 'false_bool: 0 true_BOOL:t \n true_bool1: 1 false_BOOL1:f ' )
kenton@google.com80b1d622009-07-29 01:13:20 +0000421 tokenizer = text_format._Tokenizer(text)
422 methods = [(tokenizer.ConsumeIdentifier, 'identifier1'),
423 ':',
424 (tokenizer.ConsumeString, 'string1'),
425 (tokenizer.ConsumeIdentifier, 'identifier2'),
426 ':',
427 (tokenizer.ConsumeInt32, 123),
428 (tokenizer.ConsumeIdentifier, 'identifier3'),
429 ':',
430 (tokenizer.ConsumeString, 'string'),
431 (tokenizer.ConsumeIdentifier, 'identifiER_4'),
432 ':',
433 (tokenizer.ConsumeFloat, 1.1e+2),
434 (tokenizer.ConsumeIdentifier, 'ID5'),
435 ':',
436 (tokenizer.ConsumeFloat, -0.23),
437 (tokenizer.ConsumeIdentifier, 'ID6'),
438 ':',
439 (tokenizer.ConsumeString, 'aaaa\'bbbb'),
440 (tokenizer.ConsumeIdentifier, 'ID7'),
441 ':',
442 (tokenizer.ConsumeString, 'aa\"bb'),
443 (tokenizer.ConsumeIdentifier, 'ID8'),
444 ':',
445 '{',
446 (tokenizer.ConsumeIdentifier, 'A'),
447 ':',
kenton@google.comd0047c42009-12-23 02:01:01 +0000448 (tokenizer.ConsumeFloat, text_format._INFINITY),
kenton@google.com80b1d622009-07-29 01:13:20 +0000449 (tokenizer.ConsumeIdentifier, 'B'),
450 ':',
kenton@google.comd0047c42009-12-23 02:01:01 +0000451 (tokenizer.ConsumeFloat, -text_format._INFINITY),
kenton@google.com80b1d622009-07-29 01:13:20 +0000452 (tokenizer.ConsumeIdentifier, 'C'),
453 ':',
454 (tokenizer.ConsumeBool, True),
455 (tokenizer.ConsumeIdentifier, 'D'),
456 ':',
457 (tokenizer.ConsumeBool, False),
458 '}',
459 (tokenizer.ConsumeIdentifier, 'ID9'),
460 ':',
461 (tokenizer.ConsumeUint32, 22),
462 (tokenizer.ConsumeIdentifier, 'ID10'),
463 ':',
464 (tokenizer.ConsumeInt64, -111111111111111111),
465 (tokenizer.ConsumeIdentifier, 'ID11'),
466 ':',
467 (tokenizer.ConsumeInt32, -22),
468 (tokenizer.ConsumeIdentifier, 'ID12'),
469 ':',
liujisi@google.com33165fe2010-11-02 13:14:58 +0000470 (tokenizer.ConsumeUint64, 2222222222222222222),
471 (tokenizer.ConsumeIdentifier, 'false_bool'),
472 ':',
473 (tokenizer.ConsumeBool, False),
474 (tokenizer.ConsumeIdentifier, 'true_BOOL'),
475 ':',
476 (tokenizer.ConsumeBool, True),
477 (tokenizer.ConsumeIdentifier, 'true_bool1'),
478 ':',
479 (tokenizer.ConsumeBool, True),
480 (tokenizer.ConsumeIdentifier, 'false_BOOL1'),
481 ':',
482 (tokenizer.ConsumeBool, False)]
kenton@google.com80b1d622009-07-29 01:13:20 +0000483
484 i = 0
485 while not tokenizer.AtEnd():
486 m = methods[i]
487 if type(m) == str:
488 token = tokenizer.token
489 self.assertEqual(token, m)
490 tokenizer.NextToken()
491 else:
492 self.assertEqual(m[1], m[0]())
493 i += 1
494
495 def testConsumeIntegers(self):
496 # This test only tests the failures in the integer parsing methods as well
497 # as the '0' special cases.
498 int64_max = (1 << 63) - 1
499 uint32_max = (1 << 32) - 1
500 text = '-1 %d %d' % (uint32_max + 1, int64_max + 1)
501 tokenizer = text_format._Tokenizer(text)
502 self.assertRaises(text_format.ParseError, tokenizer.ConsumeUint32)
503 self.assertRaises(text_format.ParseError, tokenizer.ConsumeUint64)
504 self.assertEqual(-1, tokenizer.ConsumeInt32())
505
506 self.assertRaises(text_format.ParseError, tokenizer.ConsumeUint32)
507 self.assertRaises(text_format.ParseError, tokenizer.ConsumeInt32)
508 self.assertEqual(uint32_max + 1, tokenizer.ConsumeInt64())
509
510 self.assertRaises(text_format.ParseError, tokenizer.ConsumeInt64)
511 self.assertEqual(int64_max + 1, tokenizer.ConsumeUint64())
512 self.assertTrue(tokenizer.AtEnd())
513
514 text = '-0 -0 0 0'
515 tokenizer = text_format._Tokenizer(text)
516 self.assertEqual(0, tokenizer.ConsumeUint32())
517 self.assertEqual(0, tokenizer.ConsumeUint64())
518 self.assertEqual(0, tokenizer.ConsumeUint32())
519 self.assertEqual(0, tokenizer.ConsumeUint64())
520 self.assertTrue(tokenizer.AtEnd())
521
522 def testConsumeByteString(self):
523 text = '"string1\''
524 tokenizer = text_format._Tokenizer(text)
525 self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString)
526
527 text = 'string1"'
528 tokenizer = text_format._Tokenizer(text)
529 self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString)
530
531 text = '\n"\\xt"'
532 tokenizer = text_format._Tokenizer(text)
533 self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString)
534
535 text = '\n"\\"'
536 tokenizer = text_format._Tokenizer(text)
537 self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString)
538
539 text = '\n"\\x"'
540 tokenizer = text_format._Tokenizer(text)
541 self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString)
542
543 def testConsumeBool(self):
544 text = 'not-a-bool'
545 tokenizer = text_format._Tokenizer(text)
546 self.assertRaises(text_format.ParseError, tokenizer.ConsumeBool)
547
kenton@google.comd0047c42009-12-23 02:01:01 +0000548 def testInfNan(self):
549 # Make sure our infinity and NaN definitions are sound.
550 self.assertEquals(float, type(text_format._INFINITY))
551 self.assertEquals(float, type(text_format._NAN))
552 self.assertTrue(text_format._NAN != text_format._NAN)
553
554 inf_times_zero = text_format._INFINITY * 0
555 self.assertTrue(inf_times_zero != inf_times_zero)
556 self.assertTrue(text_format._INFINITY > 0)
557
kenton@google.com80b1d622009-07-29 01:13:20 +0000558
temporal40ee5512008-07-10 02:12:20 +0000559if __name__ == '__main__':
560 unittest.main()