Imported Upstream version 3.8.0
[platform/upstream/protobuf.git] / python / google / protobuf / internal / well_known_types_test.py
1 #! /usr/bin/env python
2 #
3 # Protocol Buffers - Google's data interchange format
4 # Copyright 2008 Google Inc.  All rights reserved.
5 # https://developers.google.com/protocol-buffers/
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 """Test for google.protobuf.internal.well_known_types."""
34
35 __author__ = 'jieluo@google.com (Jie Luo)'
36
37 import datetime
38
39 try:
40   # Since python 3
41   import collections.abc as collections_abc
42 except ImportError:
43   # Won't work after python 3.8
44   import collections as collections_abc
45
46 try:
47   import unittest2 as unittest  #PY26
48 except ImportError:
49   import unittest
50
51 from google.protobuf import any_pb2
52 from google.protobuf import duration_pb2
53 from google.protobuf import field_mask_pb2
54 from google.protobuf import struct_pb2
55 from google.protobuf import timestamp_pb2
56 from google.protobuf import map_unittest_pb2
57 from google.protobuf import unittest_pb2
58 from google.protobuf.internal import any_test_pb2
59 from google.protobuf.internal import test_util
60 from google.protobuf.internal import well_known_types
61 from google.protobuf import descriptor
62 from google.protobuf import text_format
63
64
65 class TimeUtilTestBase(unittest.TestCase):
66
67   def CheckTimestampConversion(self, message, text):
68     self.assertEqual(text, message.ToJsonString())
69     parsed_message = timestamp_pb2.Timestamp()
70     parsed_message.FromJsonString(text)
71     self.assertEqual(message, parsed_message)
72
73   def CheckDurationConversion(self, message, text):
74     self.assertEqual(text, message.ToJsonString())
75     parsed_message = duration_pb2.Duration()
76     parsed_message.FromJsonString(text)
77     self.assertEqual(message, parsed_message)
78
79
80 class TimeUtilTest(TimeUtilTestBase):
81
82   def testTimestampSerializeAndParse(self):
83     message = timestamp_pb2.Timestamp()
84     # Generated output should contain 3, 6, or 9 fractional digits.
85     message.seconds = 0
86     message.nanos = 0
87     self.CheckTimestampConversion(message, '1970-01-01T00:00:00Z')
88     message.nanos = 10000000
89     self.CheckTimestampConversion(message, '1970-01-01T00:00:00.010Z')
90     message.nanos = 10000
91     self.CheckTimestampConversion(message, '1970-01-01T00:00:00.000010Z')
92     message.nanos = 10
93     self.CheckTimestampConversion(message, '1970-01-01T00:00:00.000000010Z')
94     # Test min timestamps.
95     message.seconds = -62135596800
96     message.nanos = 0
97     self.CheckTimestampConversion(message, '0001-01-01T00:00:00Z')
98     # Test max timestamps.
99     message.seconds = 253402300799
100     message.nanos = 999999999
101     self.CheckTimestampConversion(message, '9999-12-31T23:59:59.999999999Z')
102     # Test negative timestamps.
103     message.seconds = -1
104     self.CheckTimestampConversion(message, '1969-12-31T23:59:59.999999999Z')
105
106     # Parsing accepts an fractional digits as long as they fit into nano
107     # precision.
108     message.FromJsonString('1970-01-01T00:00:00.1Z')
109     self.assertEqual(0, message.seconds)
110     self.assertEqual(100000000, message.nanos)
111     # Parsing accepts offsets.
112     message.FromJsonString('1970-01-01T00:00:00-08:00')
113     self.assertEqual(8 * 3600, message.seconds)
114     self.assertEqual(0, message.nanos)
115
116     # It is not easy to check with current time. For test coverage only.
117     message.GetCurrentTime()
118     self.assertNotEqual(8 * 3600, message.seconds)
119
120   def testDurationSerializeAndParse(self):
121     message = duration_pb2.Duration()
122     # Generated output should contain 3, 6, or 9 fractional digits.
123     message.seconds = 0
124     message.nanos = 0
125     self.CheckDurationConversion(message, '0s')
126     message.nanos = 10000000
127     self.CheckDurationConversion(message, '0.010s')
128     message.nanos = 10000
129     self.CheckDurationConversion(message, '0.000010s')
130     message.nanos = 10
131     self.CheckDurationConversion(message, '0.000000010s')
132
133     # Test min and max
134     message.seconds = 315576000000
135     message.nanos = 999999999
136     self.CheckDurationConversion(message, '315576000000.999999999s')
137     message.seconds = -315576000000
138     message.nanos = -999999999
139     self.CheckDurationConversion(message, '-315576000000.999999999s')
140
141     # Parsing accepts an fractional digits as long as they fit into nano
142     # precision.
143     message.FromJsonString('0.1s')
144     self.assertEqual(100000000, message.nanos)
145     message.FromJsonString('0.0000001s')
146     self.assertEqual(100, message.nanos)
147
148   def testTimestampIntegerConversion(self):
149     message = timestamp_pb2.Timestamp()
150     message.FromNanoseconds(1)
151     self.assertEqual('1970-01-01T00:00:00.000000001Z',
152                      message.ToJsonString())
153     self.assertEqual(1, message.ToNanoseconds())
154
155     message.FromNanoseconds(-1)
156     self.assertEqual('1969-12-31T23:59:59.999999999Z',
157                      message.ToJsonString())
158     self.assertEqual(-1, message.ToNanoseconds())
159
160     message.FromMicroseconds(1)
161     self.assertEqual('1970-01-01T00:00:00.000001Z',
162                      message.ToJsonString())
163     self.assertEqual(1, message.ToMicroseconds())
164
165     message.FromMicroseconds(-1)
166     self.assertEqual('1969-12-31T23:59:59.999999Z',
167                      message.ToJsonString())
168     self.assertEqual(-1, message.ToMicroseconds())
169
170     message.FromMilliseconds(1)
171     self.assertEqual('1970-01-01T00:00:00.001Z',
172                      message.ToJsonString())
173     self.assertEqual(1, message.ToMilliseconds())
174
175     message.FromMilliseconds(-1)
176     self.assertEqual('1969-12-31T23:59:59.999Z',
177                      message.ToJsonString())
178     self.assertEqual(-1, message.ToMilliseconds())
179
180     message.FromSeconds(1)
181     self.assertEqual('1970-01-01T00:00:01Z',
182                      message.ToJsonString())
183     self.assertEqual(1, message.ToSeconds())
184
185     message.FromSeconds(-1)
186     self.assertEqual('1969-12-31T23:59:59Z',
187                      message.ToJsonString())
188     self.assertEqual(-1, message.ToSeconds())
189
190     message.FromNanoseconds(1999)
191     self.assertEqual(1, message.ToMicroseconds())
192     # For negative values, Timestamp will be rounded down.
193     # For example, "1969-12-31T23:59:59.5Z" (i.e., -0.5s) rounded to seconds
194     # will be "1969-12-31T23:59:59Z" (i.e., -1s) rather than
195     # "1970-01-01T00:00:00Z" (i.e., 0s).
196     message.FromNanoseconds(-1999)
197     self.assertEqual(-2, message.ToMicroseconds())
198
199   def testDurationIntegerConversion(self):
200     message = duration_pb2.Duration()
201     message.FromNanoseconds(1)
202     self.assertEqual('0.000000001s',
203                      message.ToJsonString())
204     self.assertEqual(1, message.ToNanoseconds())
205
206     message.FromNanoseconds(-1)
207     self.assertEqual('-0.000000001s',
208                      message.ToJsonString())
209     self.assertEqual(-1, message.ToNanoseconds())
210
211     message.FromMicroseconds(1)
212     self.assertEqual('0.000001s',
213                      message.ToJsonString())
214     self.assertEqual(1, message.ToMicroseconds())
215
216     message.FromMicroseconds(-1)
217     self.assertEqual('-0.000001s',
218                      message.ToJsonString())
219     self.assertEqual(-1, message.ToMicroseconds())
220
221     message.FromMilliseconds(1)
222     self.assertEqual('0.001s',
223                      message.ToJsonString())
224     self.assertEqual(1, message.ToMilliseconds())
225
226     message.FromMilliseconds(-1)
227     self.assertEqual('-0.001s',
228                      message.ToJsonString())
229     self.assertEqual(-1, message.ToMilliseconds())
230
231     message.FromSeconds(1)
232     self.assertEqual('1s', message.ToJsonString())
233     self.assertEqual(1, message.ToSeconds())
234
235     message.FromSeconds(-1)
236     self.assertEqual('-1s',
237                      message.ToJsonString())
238     self.assertEqual(-1, message.ToSeconds())
239
240     # Test truncation behavior.
241     message.FromNanoseconds(1999)
242     self.assertEqual(1, message.ToMicroseconds())
243
244     # For negative values, Duration will be rounded towards 0.
245     message.FromNanoseconds(-1999)
246     self.assertEqual(-1, message.ToMicroseconds())
247
248   def testDatetimeConverison(self):
249     message = timestamp_pb2.Timestamp()
250     dt = datetime.datetime(1970, 1, 1)
251     message.FromDatetime(dt)
252     self.assertEqual(dt, message.ToDatetime())
253
254     message.FromMilliseconds(1999)
255     self.assertEqual(datetime.datetime(1970, 1, 1, 0, 0, 1, 999000),
256                      message.ToDatetime())
257
258     dt = datetime.datetime(2555, 2, 22, 1, 2, 3, 456789)
259     message.FromDatetime(dt)
260     self.assertEqual(dt, message.ToDatetime())
261
262     dt = datetime.datetime.max
263     message.FromDatetime(dt)
264     self.assertEqual(dt, message.ToDatetime())
265
266   def testDatetimeConversionWithTimezone(self):
267     class TZ(datetime.tzinfo):
268
269       def utcoffset(self, _):
270         return datetime.timedelta(hours=1)
271
272       def dst(self, _):
273         return datetime.timedelta(0)
274
275       def tzname(self, _):
276         return 'UTC+1'
277
278     message1 = timestamp_pb2.Timestamp()
279     dt = datetime.datetime(1970, 1, 1, 1, tzinfo=TZ())
280     message1.FromDatetime(dt)
281     message2 = timestamp_pb2.Timestamp()
282     dt = datetime.datetime(1970, 1, 1, 0)
283     message2.FromDatetime(dt)
284     self.assertEqual(message1, message2)
285
286   def testTimedeltaConversion(self):
287     message = duration_pb2.Duration()
288     message.FromNanoseconds(1999999999)
289     td = message.ToTimedelta()
290     self.assertEqual(1, td.seconds)
291     self.assertEqual(999999, td.microseconds)
292
293     message.FromNanoseconds(-1999999999)
294     td = message.ToTimedelta()
295     self.assertEqual(-1, td.days)
296     self.assertEqual(86398, td.seconds)
297     self.assertEqual(1, td.microseconds)
298
299     message.FromMicroseconds(-1)
300     td = message.ToTimedelta()
301     self.assertEqual(-1, td.days)
302     self.assertEqual(86399, td.seconds)
303     self.assertEqual(999999, td.microseconds)
304     converted_message = duration_pb2.Duration()
305     converted_message.FromTimedelta(td)
306     self.assertEqual(message, converted_message)
307
308   def testInvalidTimestamp(self):
309     message = timestamp_pb2.Timestamp()
310     self.assertRaisesRegexp(
311         ValueError,
312         'Failed to parse timestamp: missing valid timezone offset.',
313         message.FromJsonString,
314         '')
315     self.assertRaisesRegexp(
316         ValueError,
317         'Failed to parse timestamp: invalid trailing data '
318         '1970-01-01T00:00:01Ztrail.',
319         message.FromJsonString,
320         '1970-01-01T00:00:01Ztrail')
321     self.assertRaisesRegexp(
322         ValueError,
323         'time data \'10000-01-01T00:00:00\' does not match'
324         ' format \'%Y-%m-%dT%H:%M:%S\'',
325         message.FromJsonString, '10000-01-01T00:00:00.00Z')
326     self.assertRaisesRegexp(
327         ValueError,
328         'nanos 0123456789012 more than 9 fractional digits.',
329         message.FromJsonString,
330         '1970-01-01T00:00:00.0123456789012Z')
331     self.assertRaisesRegexp(
332         ValueError,
333         (r'Invalid timezone offset value: \+08.'),
334         message.FromJsonString,
335         '1972-01-01T01:00:00.01+08',)
336     self.assertRaisesRegexp(
337         ValueError,
338         'year (0 )?is out of range',
339         message.FromJsonString,
340         '0000-01-01T00:00:00Z')
341     message.seconds = 253402300800
342     self.assertRaisesRegexp(
343         OverflowError,
344         'date value out of range',
345         message.ToJsonString)
346
347   def testInvalidDuration(self):
348     message = duration_pb2.Duration()
349     self.assertRaisesRegexp(
350         ValueError,
351         'Duration must end with letter "s": 1.',
352         message.FromJsonString, '1')
353     self.assertRaisesRegexp(
354         ValueError,
355         'Couldn\'t parse duration: 1...2s.',
356         message.FromJsonString, '1...2s')
357     text = '-315576000001.000000000s'
358     self.assertRaisesRegexp(
359         ValueError,
360         r'Duration is not valid\: Seconds -315576000001 must be in range'
361         r' \[-315576000000\, 315576000000\].',
362         message.FromJsonString, text)
363     text = '315576000001.000000000s'
364     self.assertRaisesRegexp(
365         ValueError,
366         r'Duration is not valid\: Seconds 315576000001 must be in range'
367         r' \[-315576000000\, 315576000000\].',
368         message.FromJsonString, text)
369     message.seconds = -315576000001
370     message.nanos = 0
371     self.assertRaisesRegexp(
372         ValueError,
373         r'Duration is not valid\: Seconds -315576000001 must be in range'
374         r' \[-315576000000\, 315576000000\].',
375         message.ToJsonString)
376     message.seconds = 0
377     message.nanos = 999999999 + 1
378     self.assertRaisesRegexp(
379         ValueError,
380         r'Duration is not valid\: Nanos 1000000000 must be in range'
381         r' \[-999999999\, 999999999\].',
382         message.ToJsonString)
383     message.seconds = -1
384     message.nanos = 1
385     self.assertRaisesRegexp(
386         ValueError,
387         r'Duration is not valid\: Sign mismatch.',
388         message.ToJsonString)
389
390
391 class FieldMaskTest(unittest.TestCase):
392
393   def testStringFormat(self):
394     mask = field_mask_pb2.FieldMask()
395     self.assertEqual('', mask.ToJsonString())
396     mask.paths.append('foo')
397     self.assertEqual('foo', mask.ToJsonString())
398     mask.paths.append('bar')
399     self.assertEqual('foo,bar', mask.ToJsonString())
400
401     mask.FromJsonString('')
402     self.assertEqual('', mask.ToJsonString())
403     mask.FromJsonString('foo')
404     self.assertEqual(['foo'], mask.paths)
405     mask.FromJsonString('foo,bar')
406     self.assertEqual(['foo', 'bar'], mask.paths)
407
408     # Test camel case
409     mask.Clear()
410     mask.paths.append('foo_bar')
411     self.assertEqual('fooBar', mask.ToJsonString())
412     mask.paths.append('bar_quz')
413     self.assertEqual('fooBar,barQuz', mask.ToJsonString())
414
415     mask.FromJsonString('')
416     self.assertEqual('', mask.ToJsonString())
417     self.assertEqual([], mask.paths)
418     mask.FromJsonString('fooBar')
419     self.assertEqual(['foo_bar'], mask.paths)
420     mask.FromJsonString('fooBar,barQuz')
421     self.assertEqual(['foo_bar', 'bar_quz'], mask.paths)
422
423   def testDescriptorToFieldMask(self):
424     mask = field_mask_pb2.FieldMask()
425     msg_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR
426     mask.AllFieldsFromDescriptor(msg_descriptor)
427     self.assertEqual(75, len(mask.paths))
428     self.assertTrue(mask.IsValidForDescriptor(msg_descriptor))
429     for field in msg_descriptor.fields:
430       self.assertTrue(field.name in mask.paths)
431
432   def testIsValidForDescriptor(self):
433     msg_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR
434     # Empty mask
435     mask = field_mask_pb2.FieldMask()
436     self.assertTrue(mask.IsValidForDescriptor(msg_descriptor))
437     # All fields from descriptor
438     mask.AllFieldsFromDescriptor(msg_descriptor)
439     self.assertTrue(mask.IsValidForDescriptor(msg_descriptor))
440     # Child under optional message
441     mask.paths.append('optional_nested_message.bb')
442     self.assertTrue(mask.IsValidForDescriptor(msg_descriptor))
443     # Repeated field is only allowed in the last position of path
444     mask.paths.append('repeated_nested_message.bb')
445     self.assertFalse(mask.IsValidForDescriptor(msg_descriptor))
446     # Invalid top level field
447     mask = field_mask_pb2.FieldMask()
448     mask.paths.append('xxx')
449     self.assertFalse(mask.IsValidForDescriptor(msg_descriptor))
450     # Invalid field in root
451     mask = field_mask_pb2.FieldMask()
452     mask.paths.append('xxx.zzz')
453     self.assertFalse(mask.IsValidForDescriptor(msg_descriptor))
454     # Invalid field in internal node
455     mask = field_mask_pb2.FieldMask()
456     mask.paths.append('optional_nested_message.xxx.zzz')
457     self.assertFalse(mask.IsValidForDescriptor(msg_descriptor))
458     # Invalid field in leaf
459     mask = field_mask_pb2.FieldMask()
460     mask.paths.append('optional_nested_message.xxx')
461     self.assertFalse(mask.IsValidForDescriptor(msg_descriptor))
462
463   def testCanonicalFrom(self):
464     mask = field_mask_pb2.FieldMask()
465     out_mask = field_mask_pb2.FieldMask()
466     # Paths will be sorted.
467     mask.FromJsonString('baz.quz,bar,foo')
468     out_mask.CanonicalFormFromMask(mask)
469     self.assertEqual('bar,baz.quz,foo', out_mask.ToJsonString())
470     # Duplicated paths will be removed.
471     mask.FromJsonString('foo,bar,foo')
472     out_mask.CanonicalFormFromMask(mask)
473     self.assertEqual('bar,foo', out_mask.ToJsonString())
474     # Sub-paths of other paths will be removed.
475     mask.FromJsonString('foo.b1,bar.b1,foo.b2,bar')
476     out_mask.CanonicalFormFromMask(mask)
477     self.assertEqual('bar,foo.b1,foo.b2', out_mask.ToJsonString())
478
479     # Test more deeply nested cases.
480     mask.FromJsonString(
481         'foo.bar.baz1,foo.bar.baz2.quz,foo.bar.baz2')
482     out_mask.CanonicalFormFromMask(mask)
483     self.assertEqual('foo.bar.baz1,foo.bar.baz2',
484                      out_mask.ToJsonString())
485     mask.FromJsonString(
486         'foo.bar.baz1,foo.bar.baz2,foo.bar.baz2.quz')
487     out_mask.CanonicalFormFromMask(mask)
488     self.assertEqual('foo.bar.baz1,foo.bar.baz2',
489                      out_mask.ToJsonString())
490     mask.FromJsonString(
491         'foo.bar.baz1,foo.bar.baz2,foo.bar.baz2.quz,foo.bar')
492     out_mask.CanonicalFormFromMask(mask)
493     self.assertEqual('foo.bar', out_mask.ToJsonString())
494     mask.FromJsonString(
495         'foo.bar.baz1,foo.bar.baz2,foo.bar.baz2.quz,foo')
496     out_mask.CanonicalFormFromMask(mask)
497     self.assertEqual('foo', out_mask.ToJsonString())
498
499   def testUnion(self):
500     mask1 = field_mask_pb2.FieldMask()
501     mask2 = field_mask_pb2.FieldMask()
502     out_mask = field_mask_pb2.FieldMask()
503     mask1.FromJsonString('foo,baz')
504     mask2.FromJsonString('bar,quz')
505     out_mask.Union(mask1, mask2)
506     self.assertEqual('bar,baz,foo,quz', out_mask.ToJsonString())
507     # Overlap with duplicated paths.
508     mask1.FromJsonString('foo,baz.bb')
509     mask2.FromJsonString('baz.bb,quz')
510     out_mask.Union(mask1, mask2)
511     self.assertEqual('baz.bb,foo,quz', out_mask.ToJsonString())
512     # Overlap with paths covering some other paths.
513     mask1.FromJsonString('foo.bar.baz,quz')
514     mask2.FromJsonString('foo.bar,bar')
515     out_mask.Union(mask1, mask2)
516     self.assertEqual('bar,foo.bar,quz', out_mask.ToJsonString())
517     src = unittest_pb2.TestAllTypes()
518     with self.assertRaises(ValueError):
519       out_mask.Union(src, mask2)
520
521   def testIntersect(self):
522     mask1 = field_mask_pb2.FieldMask()
523     mask2 = field_mask_pb2.FieldMask()
524     out_mask = field_mask_pb2.FieldMask()
525     # Test cases without overlapping.
526     mask1.FromJsonString('foo,baz')
527     mask2.FromJsonString('bar,quz')
528     out_mask.Intersect(mask1, mask2)
529     self.assertEqual('', out_mask.ToJsonString())
530     self.assertEqual(len(out_mask.paths), 0)
531     self.assertEqual(out_mask.paths, [])
532     # Overlap with duplicated paths.
533     mask1.FromJsonString('foo,baz.bb')
534     mask2.FromJsonString('baz.bb,quz')
535     out_mask.Intersect(mask1, mask2)
536     self.assertEqual('baz.bb', out_mask.ToJsonString())
537     # Overlap with paths covering some other paths.
538     mask1.FromJsonString('foo.bar.baz,quz')
539     mask2.FromJsonString('foo.bar,bar')
540     out_mask.Intersect(mask1, mask2)
541     self.assertEqual('foo.bar.baz', out_mask.ToJsonString())
542     mask1.FromJsonString('foo.bar,bar')
543     mask2.FromJsonString('foo.bar.baz,quz')
544     out_mask.Intersect(mask1, mask2)
545     self.assertEqual('foo.bar.baz', out_mask.ToJsonString())
546     # Intersect '' with ''
547     mask1.Clear()
548     mask2.Clear()
549     mask1.paths.append('')
550     mask2.paths.append('')
551     self.assertEqual(mask1.paths, [''])
552     self.assertEqual('', mask1.ToJsonString())
553     out_mask.Intersect(mask1, mask2)
554     self.assertEqual(out_mask.paths, [])
555
556   def testMergeMessageWithoutMapFields(self):
557     # Test merge one field.
558     src = unittest_pb2.TestAllTypes()
559     test_util.SetAllFields(src)
560     for field in src.DESCRIPTOR.fields:
561       if field.containing_oneof:
562         continue
563       field_name = field.name
564       dst = unittest_pb2.TestAllTypes()
565       # Only set one path to mask.
566       mask = field_mask_pb2.FieldMask()
567       mask.paths.append(field_name)
568       mask.MergeMessage(src, dst)
569       # The expected result message.
570       msg = unittest_pb2.TestAllTypes()
571       if field.label == descriptor.FieldDescriptor.LABEL_REPEATED:
572         repeated_src = getattr(src, field_name)
573         repeated_msg = getattr(msg, field_name)
574         if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
575           for item in repeated_src:
576             repeated_msg.add().CopyFrom(item)
577         else:
578           repeated_msg.extend(repeated_src)
579       elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
580         getattr(msg, field_name).CopyFrom(getattr(src, field_name))
581       else:
582         setattr(msg, field_name, getattr(src, field_name))
583       # Only field specified in mask is merged.
584       self.assertEqual(msg, dst)
585
586     # Test merge nested fields.
587     nested_src = unittest_pb2.NestedTestAllTypes()
588     nested_dst = unittest_pb2.NestedTestAllTypes()
589     nested_src.child.payload.optional_int32 = 1234
590     nested_src.child.child.payload.optional_int32 = 5678
591     mask = field_mask_pb2.FieldMask()
592     mask.FromJsonString('child.payload')
593     mask.MergeMessage(nested_src, nested_dst)
594     self.assertEqual(1234, nested_dst.child.payload.optional_int32)
595     self.assertEqual(0, nested_dst.child.child.payload.optional_int32)
596
597     mask.FromJsonString('child.child.payload')
598     mask.MergeMessage(nested_src, nested_dst)
599     self.assertEqual(1234, nested_dst.child.payload.optional_int32)
600     self.assertEqual(5678, nested_dst.child.child.payload.optional_int32)
601
602     nested_dst.Clear()
603     mask.FromJsonString('child.child.payload')
604     mask.MergeMessage(nested_src, nested_dst)
605     self.assertEqual(0, nested_dst.child.payload.optional_int32)
606     self.assertEqual(5678, nested_dst.child.child.payload.optional_int32)
607
608     nested_dst.Clear()
609     mask.FromJsonString('child')
610     mask.MergeMessage(nested_src, nested_dst)
611     self.assertEqual(1234, nested_dst.child.payload.optional_int32)
612     self.assertEqual(5678, nested_dst.child.child.payload.optional_int32)
613
614     # Test MergeOptions.
615     nested_dst.Clear()
616     nested_dst.child.payload.optional_int64 = 4321
617     # Message fields will be merged by default.
618     mask.FromJsonString('child.payload')
619     mask.MergeMessage(nested_src, nested_dst)
620     self.assertEqual(1234, nested_dst.child.payload.optional_int32)
621     self.assertEqual(4321, nested_dst.child.payload.optional_int64)
622     # Change the behavior to replace message fields.
623     mask.FromJsonString('child.payload')
624     mask.MergeMessage(nested_src, nested_dst, True, False)
625     self.assertEqual(1234, nested_dst.child.payload.optional_int32)
626     self.assertEqual(0, nested_dst.child.payload.optional_int64)
627
628     # By default, fields missing in source are not cleared in destination.
629     nested_dst.payload.optional_int32 = 1234
630     self.assertTrue(nested_dst.HasField('payload'))
631     mask.FromJsonString('payload')
632     mask.MergeMessage(nested_src, nested_dst)
633     self.assertTrue(nested_dst.HasField('payload'))
634     # But they are cleared when replacing message fields.
635     nested_dst.Clear()
636     nested_dst.payload.optional_int32 = 1234
637     mask.FromJsonString('payload')
638     mask.MergeMessage(nested_src, nested_dst, True, False)
639     self.assertFalse(nested_dst.HasField('payload'))
640
641     nested_src.payload.repeated_int32.append(1234)
642     nested_dst.payload.repeated_int32.append(5678)
643     # Repeated fields will be appended by default.
644     mask.FromJsonString('payload.repeatedInt32')
645     mask.MergeMessage(nested_src, nested_dst)
646     self.assertEqual(2, len(nested_dst.payload.repeated_int32))
647     self.assertEqual(5678, nested_dst.payload.repeated_int32[0])
648     self.assertEqual(1234, nested_dst.payload.repeated_int32[1])
649     # Change the behavior to replace repeated fields.
650     mask.FromJsonString('payload.repeatedInt32')
651     mask.MergeMessage(nested_src, nested_dst, False, True)
652     self.assertEqual(1, len(nested_dst.payload.repeated_int32))
653     self.assertEqual(1234, nested_dst.payload.repeated_int32[0])
654
655     # Test Merge oneof field.
656     new_msg = unittest_pb2.TestOneof2()
657     dst = unittest_pb2.TestOneof2()
658     dst.foo_message.qux_int = 1
659     mask = field_mask_pb2.FieldMask()
660     mask.FromJsonString('fooMessage,fooLazyMessage.quxInt')
661     mask.MergeMessage(new_msg, dst)
662     self.assertTrue(dst.HasField('foo_message'))
663     self.assertFalse(dst.HasField('foo_lazy_message'))
664
665   def testMergeMessageWithMapField(self):
666     empty_map = map_unittest_pb2.TestRecursiveMapMessage()
667     src_level_2 = map_unittest_pb2.TestRecursiveMapMessage()
668     src_level_2.a['src level 2'].CopyFrom(empty_map)
669     src = map_unittest_pb2.TestRecursiveMapMessage()
670     src.a['common key'].CopyFrom(src_level_2)
671     src.a['src level 1'].CopyFrom(src_level_2)
672
673     dst_level_2 = map_unittest_pb2.TestRecursiveMapMessage()
674     dst_level_2.a['dst level 2'].CopyFrom(empty_map)
675     dst = map_unittest_pb2.TestRecursiveMapMessage()
676     dst.a['common key'].CopyFrom(dst_level_2)
677     dst.a['dst level 1'].CopyFrom(empty_map)
678
679     mask = field_mask_pb2.FieldMask()
680     mask.FromJsonString('a')
681     mask.MergeMessage(src, dst)
682
683     # map from dst is replaced with map from src.
684     self.assertEqual(dst.a['common key'], src_level_2)
685     self.assertEqual(dst.a['src level 1'], src_level_2)
686     self.assertEqual(dst.a['dst level 1'], empty_map)
687
688   def testMergeErrors(self):
689     src = unittest_pb2.TestAllTypes()
690     dst = unittest_pb2.TestAllTypes()
691     mask = field_mask_pb2.FieldMask()
692     test_util.SetAllFields(src)
693     mask.FromJsonString('optionalInt32.field')
694     with self.assertRaises(ValueError) as e:
695       mask.MergeMessage(src, dst)
696     self.assertEqual('Error: Field optional_int32 in message '
697                      'protobuf_unittest.TestAllTypes is not a singular '
698                      'message field and cannot have sub-fields.',
699                      str(e.exception))
700
701   def testSnakeCaseToCamelCase(self):
702     self.assertEqual('fooBar',
703                      well_known_types._SnakeCaseToCamelCase('foo_bar'))
704     self.assertEqual('FooBar',
705                      well_known_types._SnakeCaseToCamelCase('_foo_bar'))
706     self.assertEqual('foo3Bar',
707                      well_known_types._SnakeCaseToCamelCase('foo3_bar'))
708
709     # No uppercase letter is allowed.
710     self.assertRaisesRegexp(
711         ValueError,
712         'Fail to print FieldMask to Json string: Path name Foo must '
713         'not contain uppercase letters.',
714         well_known_types._SnakeCaseToCamelCase,
715         'Foo')
716     # Any character after a "_" must be a lowercase letter.
717     #   1. "_" cannot be followed by another "_".
718     #   2. "_" cannot be followed by a digit.
719     #   3. "_" cannot appear as the last character.
720     self.assertRaisesRegexp(
721         ValueError,
722         'Fail to print FieldMask to Json string: The character after a '
723         '"_" must be a lowercase letter in path name foo__bar.',
724         well_known_types._SnakeCaseToCamelCase,
725         'foo__bar')
726     self.assertRaisesRegexp(
727         ValueError,
728         'Fail to print FieldMask to Json string: The character after a '
729         '"_" must be a lowercase letter in path name foo_3bar.',
730         well_known_types._SnakeCaseToCamelCase,
731         'foo_3bar')
732     self.assertRaisesRegexp(
733         ValueError,
734         'Fail to print FieldMask to Json string: Trailing "_" in path '
735         'name foo_bar_.',
736         well_known_types._SnakeCaseToCamelCase,
737         'foo_bar_')
738
739   def testCamelCaseToSnakeCase(self):
740     self.assertEqual('foo_bar',
741                      well_known_types._CamelCaseToSnakeCase('fooBar'))
742     self.assertEqual('_foo_bar',
743                      well_known_types._CamelCaseToSnakeCase('FooBar'))
744     self.assertEqual('foo3_bar',
745                      well_known_types._CamelCaseToSnakeCase('foo3Bar'))
746     self.assertRaisesRegexp(
747         ValueError,
748         'Fail to parse FieldMask: Path name foo_bar must not contain "_"s.',
749         well_known_types._CamelCaseToSnakeCase,
750         'foo_bar')
751
752
753 class StructTest(unittest.TestCase):
754
755   def testStruct(self):
756     struct = struct_pb2.Struct()
757     self.assertIsInstance(struct, collections_abc.Mapping)
758     self.assertEqual(0, len(struct))
759     struct_class = struct.__class__
760
761     struct['key1'] = 5
762     struct['key2'] = 'abc'
763     struct['key3'] = True
764     struct.get_or_create_struct('key4')['subkey'] = 11.0
765     struct_list = struct.get_or_create_list('key5')
766     self.assertIsInstance(struct_list, collections_abc.Sequence)
767     struct_list.extend([6, 'seven', True, False, None])
768     struct_list.add_struct()['subkey2'] = 9
769     struct['key6'] = {'subkey': {}}
770     struct['key7'] = [2, False]
771
772     self.assertEqual(7, len(struct))
773     self.assertTrue(isinstance(struct, well_known_types.Struct))
774     self.assertEqual(5, struct['key1'])
775     self.assertEqual('abc', struct['key2'])
776     self.assertIs(True, struct['key3'])
777     self.assertEqual(11, struct['key4']['subkey'])
778     inner_struct = struct_class()
779     inner_struct['subkey2'] = 9
780     self.assertEqual([6, 'seven', True, False, None, inner_struct],
781                      list(struct['key5'].items()))
782     self.assertEqual({}, dict(struct['key6']['subkey'].fields))
783     self.assertEqual([2, False], list(struct['key7'].items()))
784
785     serialized = struct.SerializeToString()
786     struct2 = struct_pb2.Struct()
787     struct2.ParseFromString(serialized)
788
789     self.assertEqual(struct, struct2)
790     for key, value in struct.items():
791       self.assertIn(key, struct)
792       self.assertIn(key, struct2)
793       self.assertEqual(value, struct2[key])
794
795     self.assertEqual(7, len(struct.keys()))
796     self.assertEqual(7, len(struct.values()))
797     for key in struct.keys():
798       self.assertIn(key, struct)
799       self.assertIn(key, struct2)
800       self.assertEqual(struct[key], struct2[key])
801
802     item = (next(iter(struct.keys())), next(iter(struct.values())))
803     self.assertEqual(item, next(iter(struct.items())))
804
805     self.assertTrue(isinstance(struct2, well_known_types.Struct))
806     self.assertEqual(5, struct2['key1'])
807     self.assertEqual('abc', struct2['key2'])
808     self.assertIs(True, struct2['key3'])
809     self.assertEqual(11, struct2['key4']['subkey'])
810     self.assertEqual([6, 'seven', True, False, None, inner_struct],
811                      list(struct2['key5'].items()))
812
813     struct_list = struct2['key5']
814     self.assertEqual(6, struct_list[0])
815     self.assertEqual('seven', struct_list[1])
816     self.assertEqual(True, struct_list[2])
817     self.assertEqual(False, struct_list[3])
818     self.assertEqual(None, struct_list[4])
819     self.assertEqual(inner_struct, struct_list[5])
820
821     struct_list[1] = 7
822     self.assertEqual(7, struct_list[1])
823
824     struct_list.add_list().extend([1, 'two', True, False, None])
825     self.assertEqual([1, 'two', True, False, None],
826                      list(struct_list[6].items()))
827     struct_list.extend([{'nested_struct': 30}, ['nested_list', 99], {}, []])
828     self.assertEqual(11, len(struct_list.values))
829     self.assertEqual(30, struct_list[7]['nested_struct'])
830     self.assertEqual('nested_list', struct_list[8][0])
831     self.assertEqual(99, struct_list[8][1])
832     self.assertEqual({}, dict(struct_list[9].fields))
833     self.assertEqual([], list(struct_list[10].items()))
834     struct_list[0] = {'replace': 'set'}
835     struct_list[1] = ['replace', 'set']
836     self.assertEqual('set', struct_list[0]['replace'])
837     self.assertEqual(['replace', 'set'], list(struct_list[1].items()))
838
839     text_serialized = str(struct)
840     struct3 = struct_pb2.Struct()
841     text_format.Merge(text_serialized, struct3)
842     self.assertEqual(struct, struct3)
843
844     struct.get_or_create_struct('key3')['replace'] = 12
845     self.assertEqual(12, struct['key3']['replace'])
846
847     # Tests empty list.
848     struct.get_or_create_list('empty_list')
849     empty_list = struct['empty_list']
850     self.assertEqual([], list(empty_list.items()))
851     list2 = struct_pb2.ListValue()
852     list2.add_list()
853     empty_list = list2[0]
854     self.assertEqual([], list(empty_list.items()))
855
856     # Tests empty struct.
857     struct.get_or_create_struct('empty_struct')
858     empty_struct = struct['empty_struct']
859     self.assertEqual({}, dict(empty_struct.fields))
860     list2.add_struct()
861     empty_struct = list2[1]
862     self.assertEqual({}, dict(empty_struct.fields))
863
864     self.assertEqual(9, len(struct))
865     del struct['key3']
866     del struct['key4']
867     self.assertEqual(7, len(struct))
868     self.assertEqual(6, len(struct['key5']))
869     del struct['key5'][1]
870     self.assertEqual(5, len(struct['key5']))
871     self.assertEqual([6, True, False, None, inner_struct],
872                      list(struct['key5'].items()))
873
874   def testMergeFrom(self):
875     struct = struct_pb2.Struct()
876     struct_class = struct.__class__
877
878     dictionary = {
879         'key1': 5,
880         'key2': 'abc',
881         'key3': True,
882         'key4': {'subkey': 11.0},
883         'key5': [6, 'seven', True, False, None, {'subkey2': 9}],
884         'key6': [['nested_list', True]],
885         'empty_struct': {},
886         'empty_list': []
887     }
888     struct.update(dictionary)
889     self.assertEqual(5, struct['key1'])
890     self.assertEqual('abc', struct['key2'])
891     self.assertIs(True, struct['key3'])
892     self.assertEqual(11, struct['key4']['subkey'])
893     inner_struct = struct_class()
894     inner_struct['subkey2'] = 9
895     self.assertEqual([6, 'seven', True, False, None, inner_struct],
896                      list(struct['key5'].items()))
897     self.assertEqual(2, len(struct['key6'][0].values))
898     self.assertEqual('nested_list', struct['key6'][0][0])
899     self.assertEqual(True, struct['key6'][0][1])
900     empty_list = struct['empty_list']
901     self.assertEqual([], list(empty_list.items()))
902     empty_struct = struct['empty_struct']
903     self.assertEqual({}, dict(empty_struct.fields))
904
905     # According to documentation: "When parsing from the wire or when merging,
906     # if there are duplicate map keys the last key seen is used".
907     duplicate = {
908         'key4': {'replace': 20},
909         'key5': [[False, 5]]
910     }
911     struct.update(duplicate)
912     self.assertEqual(1, len(struct['key4'].fields))
913     self.assertEqual(20, struct['key4']['replace'])
914     self.assertEqual(1, len(struct['key5'].values))
915     self.assertEqual(False, struct['key5'][0][0])
916     self.assertEqual(5, struct['key5'][0][1])
917
918
919 class AnyTest(unittest.TestCase):
920
921   def testAnyMessage(self):
922     # Creates and sets message.
923     msg = any_test_pb2.TestAny()
924     msg_descriptor = msg.DESCRIPTOR
925     all_types = unittest_pb2.TestAllTypes()
926     all_descriptor = all_types.DESCRIPTOR
927     all_types.repeated_string.append(u'\u00fc\ua71f')
928     # Packs to Any.
929     msg.value.Pack(all_types)
930     self.assertEqual(msg.value.type_url,
931                      'type.googleapis.com/%s' % all_descriptor.full_name)
932     self.assertEqual(msg.value.value,
933                      all_types.SerializeToString())
934     # Tests Is() method.
935     self.assertTrue(msg.value.Is(all_descriptor))
936     self.assertFalse(msg.value.Is(msg_descriptor))
937     # Unpacks Any.
938     unpacked_message = unittest_pb2.TestAllTypes()
939     self.assertTrue(msg.value.Unpack(unpacked_message))
940     self.assertEqual(all_types, unpacked_message)
941     # Unpacks to different type.
942     self.assertFalse(msg.value.Unpack(msg))
943     # Only Any messages have Pack method.
944     try:
945       msg.Pack(all_types)
946     except AttributeError:
947       pass
948     else:
949       raise AttributeError('%s should not have Pack method.' %
950                            msg_descriptor.full_name)
951
952   def testUnpackWithNoSlashInTypeUrl(self):
953     msg = any_test_pb2.TestAny()
954     all_types = unittest_pb2.TestAllTypes()
955     all_descriptor = all_types.DESCRIPTOR
956     msg.value.Pack(all_types)
957     # Reset type_url to part of type_url after '/'
958     msg.value.type_url = msg.value.TypeName()
959     self.assertFalse(msg.value.Is(all_descriptor))
960     unpacked_message = unittest_pb2.TestAllTypes()
961     self.assertFalse(msg.value.Unpack(unpacked_message))
962
963   def testMessageName(self):
964     # Creates and sets message.
965     submessage = any_test_pb2.TestAny()
966     submessage.int_value = 12345
967     msg = any_pb2.Any()
968     msg.Pack(submessage)
969     self.assertEqual(msg.TypeName(), 'google.protobuf.internal.TestAny')
970
971   def testPackWithCustomTypeUrl(self):
972     submessage = any_test_pb2.TestAny()
973     submessage.int_value = 12345
974     msg = any_pb2.Any()
975     # Pack with a custom type URL prefix.
976     msg.Pack(submessage, 'type.myservice.com')
977     self.assertEqual(msg.type_url,
978                      'type.myservice.com/%s' % submessage.DESCRIPTOR.full_name)
979     # Pack with a custom type URL prefix ending with '/'.
980     msg.Pack(submessage, 'type.myservice.com/')
981     self.assertEqual(msg.type_url,
982                      'type.myservice.com/%s' % submessage.DESCRIPTOR.full_name)
983     # Pack with an empty type URL prefix.
984     msg.Pack(submessage, '')
985     self.assertEqual(msg.type_url,
986                      '/%s' % submessage.DESCRIPTOR.full_name)
987     # Test unpacking the type.
988     unpacked_message = any_test_pb2.TestAny()
989     self.assertTrue(msg.Unpack(unpacked_message))
990     self.assertEqual(submessage, unpacked_message)
991
992   def testPackDeterministic(self):
993     submessage = any_test_pb2.TestAny()
994     for i in range(10):
995       submessage.map_value[str(i)] = i * 2
996     msg = any_pb2.Any()
997     msg.Pack(submessage, deterministic=True)
998     serialized = msg.SerializeToString(deterministic=True)
999     golden = (b'\n4type.googleapis.com/google.protobuf.internal.TestAny\x12F'
1000               b'\x1a\x05\n\x010\x10\x00\x1a\x05\n\x011\x10\x02\x1a\x05\n\x01'
1001               b'2\x10\x04\x1a\x05\n\x013\x10\x06\x1a\x05\n\x014\x10\x08\x1a'
1002               b'\x05\n\x015\x10\n\x1a\x05\n\x016\x10\x0c\x1a\x05\n\x017\x10'
1003               b'\x0e\x1a\x05\n\x018\x10\x10\x1a\x05\n\x019\x10\x12')
1004     self.assertEqual(golden, serialized)
1005
1006
1007 if __name__ == '__main__':
1008   unittest.main()