• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Lint as: python3
2# Copyright 2020 Google Inc. All rights reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#     http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15"""Unit tests for flexbuffers.py."""
16
17import array
18import os.path
19import struct
20import unittest
21
22from flatbuffers import flexbuffers
23
24Type = flexbuffers.Type
25
26LOG2 = {1: 0, 2: 1, 4: 2, 8: 3}
27
28GOLD_FLEXBUFFER_OBJ = {
29    'bar': [1, 2, 3],
30    'bar3': [1, 2, 3],
31    'bool': True,
32    'bools': [True, False, True, False],
33    'foo': 100.0,
34    'mymap': {'foo': 'Fred'},
35    'vec': [-100, 'Fred', 4.0, b'M', False, 4.0]
36}
37
38GOLD_FLEXBUFFER_FILE = 'gold_flexbuffer_example.bin'
39
40
41def read_test_file(name):
42  with open(os.path.join(os.path.dirname(__file__), name), 'rb') as f:
43    return f.read()
44
45
46def packed_type(type_, i):
47  return (type_ << 2) | LOG2[i]
48
49
50def uint_size(value):
51  """Returns number of bytes (power of two) to represent unsigned value."""
52  assert value >= 0
53
54  n = 8
55  while not value < (1 << n):
56    n *= 2
57  return n // 8
58
59
60def int_size(value):
61  """Returns number of bytes (power of two) to represent signed value."""
62  n = 8
63  while not -(1 << (n - 1)) <= value < (1 << (n - 1)):
64    n *= 2
65  return n // 8
66
67
68def uint_sizes(value):
69  return tuple(1 << i for i in range(LOG2[uint_size(value)], 4))
70
71
72def int_sizes(value):
73  return tuple(1 << i for i in range(LOG2[int_size(value)], 4))
74
75
76def int_bytes(value, byte_width):
77  return struct.pack({1: 'b', 2: 'h', 4: 'i', 8: 'q'}[byte_width], value)
78
79
80def uint_bytes(value, byte_width):
81  return struct.pack({1: 'B', 2: 'H', 4: 'I', 8: 'Q'}[byte_width], value)
82
83
84def float_bytes(value, byte_width):
85  return struct.pack({4: 'f', 8: 'd'}[byte_width], value)
86
87
88def min_value(type_, byte_width):
89  assert byte_width > 0
90
91  if type_ in (Type.INT, Type.INDIRECT_INT):
92    return -(1 << (8 * byte_width - 1))
93  elif type_ in (Type.UINT, Type.INDIRECT_UINT):
94    return 0
95  else:
96    raise ValueError('Unsupported type %s' % type_)
97
98
99def max_value(type_, byte_width):
100  assert byte_width > 0
101
102  if type_ in (Type.INT, Type.INDIRECT_INT):
103    return (1 << (8 * byte_width - 1)) - 1
104  elif type_ in (Type.UINT, Type.INDIRECT_UINT):
105    return (1 << 8 * byte_width) - 1
106  else:
107    raise ValueError('Unsupported type %s' % type_)
108
109
110def str_bytes(value, byte_width):
111  value_bytes = value.encode('utf-8')
112  return [*uint_bytes(len(value_bytes), byte_width), *value_bytes, 0]
113
114
115def key_bytes(value):
116  return [*value.encode('ascii'), 0]
117
118
119def encode_type(type_, value, byte_width=None):
120  fbb = flexbuffers.Builder()
121  add = fbb.Adder(type_)
122  if byte_width:
123    add(value, byte_width)
124  else:
125    add(value)
126  return fbb.Finish()
127
128
129INT_MIN_MAX_VALUES = (min_value(Type.INT, 1), max_value(Type.INT, 1),
130                      min_value(Type.INT, 2), max_value(Type.INT, 2),
131                      min_value(Type.INT, 4), max_value(Type.INT, 4),
132                      min_value(Type.INT, 8), max_value(Type.INT, 8))
133
134UINT_MIN_MAX_VALUES = (0, max_value(Type.UINT, 1), max_value(Type.UINT, 2),
135                       max_value(Type.UINT, 4), max_value(Type.UINT, 8))
136
137
138class UtilTest(unittest.TestCase):
139  """Tests to check FlexBuffer utility functions."""
140
141  def _test_type_predicate(self, pred, types):
142    for type_ in types:
143      with self.subTest(type=type_, pred=pred):
144        self.assertTrue(pred(type_))
145
146    for type_ in set(Type).difference(types):
147      with self.subTest(type=type_, pred=pred):
148        self.assertFalse(pred(type_))
149
150  def test_inline_types(self):
151    self._test_type_predicate(
152        Type.IsInline, (Type.NULL, Type.INT, Type.UINT, Type.FLOAT, Type.BOOL))
153
154  def test_typed_vector(self):
155    self._test_type_predicate(
156        Type.IsTypedVector,
157        (Type.VECTOR_INT, Type.VECTOR_UINT, Type.VECTOR_FLOAT, Type.VECTOR_KEY,
158         Type.VECTOR_STRING_DEPRECATED, Type.VECTOR_BOOL))
159
160    self._test_type_predicate(
161        Type.IsTypedVectorElementType,
162        (Type.INT, Type.UINT, Type.FLOAT, Type.KEY, Type.STRING, Type.BOOL))
163
164    with self.assertRaises(ValueError):
165      Type.ToTypedVectorElementType(Type.VECTOR)
166    self.assertIs(Type.ToTypedVectorElementType(Type.VECTOR_INT), Type.INT)
167    self.assertIs(Type.ToTypedVectorElementType(Type.VECTOR_UINT), Type.UINT)
168    self.assertIs(Type.ToTypedVectorElementType(Type.VECTOR_FLOAT), Type.FLOAT)
169    self.assertIs(Type.ToTypedVectorElementType(Type.VECTOR_KEY), Type.KEY)
170    self.assertIs(
171        Type.ToTypedVectorElementType(Type.VECTOR_STRING_DEPRECATED),
172        Type.STRING)
173    self.assertIs(Type.ToTypedVectorElementType(Type.VECTOR_BOOL), Type.BOOL)
174
175    with self.assertRaises(ValueError):
176      Type.ToTypedVector(Type.VECTOR)
177    self.assertIs(Type.ToTypedVector(Type.INT), Type.VECTOR_INT)
178    self.assertIs(Type.ToTypedVector(Type.UINT), Type.VECTOR_UINT)
179    self.assertIs(Type.ToTypedVector(Type.FLOAT), Type.VECTOR_FLOAT)
180    self.assertIs(Type.ToTypedVector(Type.KEY), Type.VECTOR_KEY)
181    self.assertIs(
182        Type.ToTypedVector(Type.STRING), Type.VECTOR_STRING_DEPRECATED)
183    self.assertIs(Type.ToTypedVector(Type.BOOL), Type.VECTOR_BOOL)
184
185  def test_fixed_typed_vector(self):
186    self._test_type_predicate(
187        Type.IsFixedTypedVector,
188        (Type.VECTOR_INT2, Type.VECTOR_UINT2, Type.VECTOR_FLOAT2,
189         Type.VECTOR_INT3, Type.VECTOR_UINT3, Type.VECTOR_FLOAT3,
190         Type.VECTOR_INT4, Type.VECTOR_UINT4, Type.VECTOR_FLOAT4))
191
192    self._test_type_predicate(Type.IsFixedTypedVectorElementType,
193                              (Type.INT, Type.UINT, Type.FLOAT))
194
195    self.assertEqual(
196        Type.ToFixedTypedVectorElementType(Type.VECTOR_INT2), (Type.INT, 2))
197    self.assertEqual(
198        Type.ToFixedTypedVectorElementType(Type.VECTOR_UINT2), (Type.UINT, 2))
199    self.assertEqual(
200        Type.ToFixedTypedVectorElementType(Type.VECTOR_FLOAT2), (Type.FLOAT, 2))
201    self.assertEqual(
202        Type.ToFixedTypedVectorElementType(Type.VECTOR_INT3), (Type.INT, 3))
203    self.assertEqual(
204        Type.ToFixedTypedVectorElementType(Type.VECTOR_UINT3), (Type.UINT, 3))
205    self.assertEqual(
206        Type.ToFixedTypedVectorElementType(Type.VECTOR_FLOAT3), (Type.FLOAT, 3))
207    self.assertEqual(
208        Type.ToFixedTypedVectorElementType(Type.VECTOR_INT4), (Type.INT, 4))
209    self.assertEqual(
210        Type.ToFixedTypedVectorElementType(Type.VECTOR_UINT4), (Type.UINT, 4))
211    self.assertEqual(
212        Type.ToFixedTypedVectorElementType(Type.VECTOR_FLOAT4), (Type.FLOAT, 4))
213
214    # Invalid size
215    for type_ in Type.INT, Type.UINT, Type.FLOAT:
216      with self.assertRaises(ValueError):
217        Type.ToTypedVector(type_, 1)
218      with self.assertRaises(ValueError):
219        Type.ToTypedVector(type_, 5)
220
221    # Invalid element type
222    for length in 1, 2, 3, 4, 5:
223      with self.assertRaises(ValueError):
224        Type.ToTypedVector(Type.STRING, length)
225
226    self.assertIs(Type.ToTypedVector(Type.INT, 2), Type.VECTOR_INT2)
227    self.assertIs(Type.ToTypedVector(Type.INT, 3), Type.VECTOR_INT3)
228    self.assertIs(Type.ToTypedVector(Type.INT, 4), Type.VECTOR_INT4)
229
230    self.assertIs(Type.ToTypedVector(Type.UINT, 2), Type.VECTOR_UINT2)
231    self.assertIs(Type.ToTypedVector(Type.UINT, 3), Type.VECTOR_UINT3)
232    self.assertIs(Type.ToTypedVector(Type.UINT, 4), Type.VECTOR_UINT4)
233
234    self.assertIs(Type.ToTypedVector(Type.FLOAT, 2), Type.VECTOR_FLOAT2)
235    self.assertIs(Type.ToTypedVector(Type.FLOAT, 3), Type.VECTOR_FLOAT3)
236    self.assertIs(Type.ToTypedVector(Type.FLOAT, 4), Type.VECTOR_FLOAT4)
237
238  def test_width(self):
239    for x in range(1 << 10):
240      self.assertEqual(flexbuffers.BitWidth.U(x), LOG2[uint_size(x)])
241
242    for x in range(-(1 << 10), 1 << 10):
243      self.assertEqual(flexbuffers.BitWidth.I(x), LOG2[int_size(x)])
244
245  def test_padding(self):
246    self.assertEqual(flexbuffers._PaddingBytes(0, 4), 0)
247    self.assertEqual(flexbuffers._PaddingBytes(0, 8), 0)
248    self.assertEqual(flexbuffers._PaddingBytes(0, 16), 0)
249
250    self.assertEqual(flexbuffers._PaddingBytes(1, 8), 7)
251    self.assertEqual(flexbuffers._PaddingBytes(17, 8), 7)
252
253    self.assertEqual(flexbuffers._PaddingBytes(42, 2), 0)
254
255
256class DecoderTest(unittest.TestCase):
257  """Tests to check FlexBuffer decoding functions.
258
259  Common variable names used in the tests for compactness:
260    bw: byte_width
261    ebw: element_byte_width
262    kbw: key_byte_width
263    vbw: value_byte_width
264    tbw: type_byte_width
265
266  Having '_ignored' suffix means that variable doesn't affect the constructed
267  byte buffer size.
268  """
269
270  def test_null(self):
271    for bw in 1, 2, 4, 8:
272      for ebw_ignored in 1, 2, 4, 8:
273        with self.subTest(bw=bw, ebw_ignored=ebw_ignored):
274          data = bytes([
275              *uint_bytes(0, bw),
276              packed_type(Type.NULL, ebw_ignored),
277              bw,
278          ])
279
280          root = flexbuffers.GetRoot(data)
281          self.assertTrue(root.IsNull)
282          self.assertEqual(root.AsBool, False)
283          self.assertEqual(root.AsInt, 0)
284          self.assertEqual(root.AsFloat, 0.0)
285
286          for prop in (type(root).AsKey, type(root).AsString, type(root).AsBlob,
287                       type(root).AsVector, type(root).AsTypedVector,
288                       type(root).AsFixedTypedVector, type(root).AsMap):
289            with self.assertRaises(TypeError):
290              prop.fget(root)
291
292          self.assertEqual(root.Value, None)
293
294          self.assertIsNone(flexbuffers.Loads(data))
295
296  def test_bool(self):
297    for value in False, True:
298      for bw in 1, 2, 4, 8:
299        for ebw_ignored in 1, 2, 4, 8:
300          with self.subTest(bw=bw, ebw_ignored=ebw_ignored):
301            data = bytes([
302                *uint_bytes(int(value), bw),
303                packed_type(Type.BOOL, ebw_ignored),
304                bw,
305            ])
306
307            root = flexbuffers.GetRoot(data)
308            self.assertTrue(root.IsBool)
309            self.assertEqual(root.AsBool, value)
310            self.assertEqual(root.AsInt, int(value))
311            self.assertEqual(root.AsFloat, float(value))
312
313            for prop in (type(root).AsKey, type(root).AsString,
314                         type(root).AsBlob,
315                         type(root).AsVector, type(root).AsTypedVector,
316                         type(root).AsFixedTypedVector, type(root).AsMap):
317              with self.assertRaises(TypeError):
318                prop.fget(root)
319
320            self.assertEqual(root.Value, value)
321
322            self.assertEqual(flexbuffers.Loads(data), value)
323
324  def test_mutate_bool(self):
325    root = flexbuffers.GetRoot(flexbuffers.Dumps(True))
326    self.assertTrue(root.IsBool)
327    self.assertTrue(root.AsBool)
328
329    self.assertTrue(root.MutateBool(False))
330    self.assertTrue(root.IsBool)
331    self.assertFalse(root.AsBool)
332
333    self.assertTrue(root.MutateBool(True))
334    self.assertTrue(root.IsBool)
335    self.assertTrue(root.AsBool)
336
337  def _check_int(self, data, value):
338    root = flexbuffers.GetRoot(data)
339    self.assertTrue(root.IsInt)
340    self.assertEqual(root.AsInt, value)
341    self.assertEqual(root.AsBool, bool(value))
342    self.assertEqual(root.AsFloat, float(value))
343
344    for prop in (type(root).AsKey, type(root).AsString, type(root).AsBlob,
345                 type(root).AsVector, type(root).AsTypedVector,
346                 type(root).AsFixedTypedVector, type(root).AsMap):
347      with self.assertRaises(TypeError):
348        prop.fget(root)
349
350    self.assertEqual(root.Value, value)
351
352    self.assertEqual(flexbuffers.Loads(data), value)
353
354  def test_int(self):
355    for value in (0, 1, -1, 15, -17, *INT_MIN_MAX_VALUES):
356      for bw in int_sizes(value):
357        for ebw_ignored in 1, 2, 4, 8:
358          with self.subTest(value=value, bw=bw, ebw_ignored=ebw_ignored):
359            data = bytes([
360                *int_bytes(value, bw),
361                packed_type(Type.INT, ebw_ignored),
362                bw,
363            ])
364
365            self._check_int(data, value)
366
367  def test_indirect_int(self):
368    for value in (0, 1, -1, 15, -17, *INT_MIN_MAX_VALUES):
369      for bw in 1, 2, 4, 8:
370        for ebw in int_sizes(value):
371          with self.subTest(value=value, bw=bw, ebw=ebw):
372            data = bytes([
373                # Int
374                *int_bytes(value, ebw),
375                # Root
376                *uint_bytes(ebw, bw),
377                packed_type(Type.INDIRECT_INT, ebw),
378                bw,
379            ])
380            self._check_int(data, value)
381
382  def test_uint(self):
383    for value in (1, *UINT_MIN_MAX_VALUES):
384      for bw in uint_sizes(value):
385        for ebw_ignored in 1, 2, 4, 8:
386          with self.subTest(value=value, bw=bw, ebw_ignored=ebw_ignored):
387            data = bytes([
388                *uint_bytes(value, bw),
389                packed_type(Type.UINT, ebw_ignored),
390                bw,
391            ])
392
393            self._check_int(data, value)
394
395  def test_inidirect_uint(self):
396    for value in (1, *UINT_MIN_MAX_VALUES):
397      for bw in 1, 2, 4, 8:
398        for ebw in uint_sizes(value):
399          with self.subTest(value=value, bw=bw, ebw=ebw):
400            data = bytes([
401                # UInt
402                *uint_bytes(value, ebw),
403                # Root
404                *uint_bytes(ebw, bw),
405                packed_type(Type.INDIRECT_UINT, ebw),
406                bw,
407            ])
408
409            self._check_int(data, value)
410
411  def test_mutate_ints(self):
412    # Signed
413    for type_ in Type.INT, Type.INDIRECT_INT:
414      with self.subTest(type=type_):
415        root = flexbuffers.GetRoot(encode_type(type_, 56))
416        self.assertEqual(root.AsInt, 56)
417
418        for new_value in 0, 1, -1, -128, 127:
419          self.assertTrue(root.MutateInt(new_value))
420          self.assertEqual(root.AsInt, new_value)
421
422        for new_value in -129, 128:
423          self.assertFalse(root.MutateInt(new_value))
424
425    # Unsigned
426    for type_ in Type.UINT, Type.INDIRECT_UINT:
427      with self.subTest(type=type_):
428        root = flexbuffers.GetRoot(encode_type(type_, 1))
429        self.assertEqual(root.AsInt, 1)
430
431        for new_value in 0, 1, 255:
432          self.assertTrue(root.MutateInt(new_value))
433          self.assertEqual(root.AsInt, new_value)
434
435        self.assertFalse(root.MutateInt(256))
436
437    # Inside vector
438    fbb = flexbuffers.Builder()
439    fbb.VectorFromElements([13, 0, -15])
440    data = fbb.Finish()
441
442    self.assertEqual(flexbuffers.Loads(data), [13, 0, -15])
443    self.assertTrue(flexbuffers.GetRoot(data).AsVector[0].MutateInt(0))
444    self.assertTrue(flexbuffers.GetRoot(data).AsVector[1].MutateInt(-7))
445    self.assertTrue(flexbuffers.GetRoot(data).AsVector[2].MutateInt(45))
446    self.assertEqual(flexbuffers.Loads(data), [0, -7, 45])
447
448    # Inside map
449    fbb = flexbuffers.Builder()
450    fbb.MapFromElements({'x': -7, 'y': 46})
451    data = fbb.Finish()
452
453    self.assertEqual(flexbuffers.Loads(data), {'x': -7, 'y': 46})
454    self.assertTrue(flexbuffers.GetRoot(data).AsMap['x'].MutateInt(14))
455    self.assertTrue(flexbuffers.GetRoot(data).AsMap['y'].MutateInt(-1))
456    self.assertEqual(flexbuffers.Loads(data), {'x': 14, 'y': -1})
457
458  def _check_float(self, data, value):
459    root = flexbuffers.GetRoot(data)
460    self.assertTrue(root.IsFloat)
461    self.assertAlmostEqual(root.AsFloat, value)
462
463    for prop in (type(root).AsKey, type(root).AsString, type(root).AsBlob,
464                 type(root).AsVector, type(root).AsTypedVector,
465                 type(root).AsFixedTypedVector, type(root).AsMap):
466      with self.assertRaises(TypeError):
467        prop.fget(root)
468
469    self.assertAlmostEqual(root.Value, value)
470
471    self.assertAlmostEqual(flexbuffers.Loads(data), value)
472
473  def test_float(self):
474    for value in -1.0, 0.0, 1.0, 3.141592, 1.5e6:
475      for bw in 4, 8:
476        for ebw_ignored in 1, 2, 4, 8:
477          with self.subTest(value=value, bw=bw, ebw_ignored=ebw_ignored):
478            data = bytes([
479                *float_bytes(value, bw),
480                packed_type(Type.FLOAT, ebw_ignored),
481                bw,
482            ])
483
484            self._check_float(data, value)
485
486  def test_indirect_float(self):
487    for value in -1.0, 0.0, 1.0, 3.141592, 1.5e6:
488      for bw in 1, 2, 4, 8:
489        for ebw in 4, 8:
490          with self.subTest(value=value, bw=bw, ebw=ebw):
491            data = bytes([
492                # Float
493                *float_bytes(value, ebw),
494                # Root
495                *uint_bytes(ebw, bw),
496                packed_type(Type.INDIRECT_FLOAT, ebw),
497                bw,
498            ])
499
500            self._check_float(data, value)
501
502  def test_mutate_float(self):
503    for type_ in Type.FLOAT, Type.INDIRECT_FLOAT:
504      for bw in 4, 8:
505        value = 3.141592
506        root = flexbuffers.GetRoot(encode_type(type_, value, bw))
507        self.assertAlmostEqual(root.AsFloat, value)
508
509        value = 2.71828
510        self.assertTrue(root.MutateFloat(value))
511        self.assertAlmostEqual(root.AsFloat, value, places=5)
512
513    # Inside vector
514    data = flexbuffers.Dumps([2.4, 1.5, -7.2])
515
516    self.assertTrue(flexbuffers.GetRoot(data).AsVector[0].MutateFloat(0.0))
517    self.assertTrue(flexbuffers.GetRoot(data).AsVector[1].MutateFloat(15.2))
518    self.assertTrue(flexbuffers.GetRoot(data).AsVector[2].MutateFloat(-5.1))
519
520    for a, b in zip(flexbuffers.Loads(data), [0.0, 15.2, -5.1]):
521      self.assertAlmostEqual(a, b)
522
523  def test_string(self):
524    for value in 'red', 'green', 'blue', 'flatbuffers + flexbuffers':
525      value_bytes = value.encode('utf-8')
526      for bw in 1, 2, 4, 8:
527        for lbw in 1, 2, 4, 8:
528          with self.subTest(bw=bw, lbw=lbw):
529            data = bytes([
530                # String
531                *uint_bytes(len(value_bytes), lbw),
532                *value_bytes,
533                0,
534                # Root
535                *uint_bytes(len(value_bytes) + 1, bw),  # offset
536                packed_type(Type.STRING, lbw),
537                bw,
538            ])
539
540            root = flexbuffers.GetRoot(data)
541            self.assertTrue(root.IsString)
542            self.assertEqual(root.AsString, value)
543            self.assertEqual(root.Value, value)
544            self.assertEqual(root.AsInt, len(value))
545
546            self.assertEqual(flexbuffers.Loads(data), value)
547
548  def test_mutate_string(self):
549    data = encode_type(Type.STRING, '12345')
550
551    root = flexbuffers.GetRoot(data)
552    self.assertTrue(root.IsString)
553    self.assertEqual(root.AsString, '12345')
554
555    self.assertFalse(root.MutateString('543210'))
556
557    self.assertTrue(root.MutateString('54321'))
558    self.assertTrue(root.IsString)
559    self.assertEqual(root.AsString, '54321')
560
561    self.assertTrue(root.MutateString('543'))
562    self.assertTrue(root.IsString)
563    self.assertEqual(root.AsString, '543')
564
565    self.assertFalse(root.MutateString('54321'))
566
567  def test_empty_blob(self):
568    for bw in 1, 2, 4, 8:
569      for lbw in 1, 2, 4, 8:
570        with self.subTest(bw=bw, lbw=lbw):
571          data = bytes([
572              # Blob
573              *uint_bytes(0, lbw),
574              # Root
575              *uint_bytes(0, bw),
576              packed_type(Type.BLOB, lbw),
577              bw,
578          ])
579
580          root = flexbuffers.GetRoot(data)
581          self.assertTrue(root.IsBlob)
582          self.assertEqual(root.AsBlob, bytes())
583          self.assertEqual(root.Value, bytes())
584          self.assertEqual(flexbuffers.Loads(data), bytes())
585
586  def test_blob(self):
587    for blob in [], [215], [23, 75, 124, 0, 45, 15], 255 * [0]:
588      for bw in 1, 2, 4, 8:
589        for lbw in 1, 2, 4, 8:
590          with self.subTest(blob=blob, bw=bw, lbw=lbw):
591            data = bytes([
592                # Blob
593                *uint_bytes(len(blob), lbw),
594                *blob,
595                # Root
596                *uint_bytes(len(blob), bw),
597                packed_type(Type.BLOB, lbw),
598                bw,
599            ])
600
601            root = flexbuffers.GetRoot(data)
602            self.assertTrue(root.IsBlob)
603            self.assertEqual(root.AsBlob, bytes(blob))
604            self.assertEqual(root.Value, bytes(blob))
605            self.assertEqual(flexbuffers.Loads(data), bytes(blob))
606
607  def test_key(self):
608    for value in '', 'x', 'color':
609      for bw in 1, 2, 4, 8:
610        with self.subTest(value=value, bw=bw):
611          value_bytes = value.encode('ascii')
612          data = bytes([
613              # Key
614              *value_bytes,
615              0,
616              # Root
617              *uint_bytes(len(value_bytes) + 1, bw),
618              packed_type(Type.KEY, 1),
619              bw,
620          ])
621
622          root = flexbuffers.GetRoot(data)
623          self.assertTrue(root.IsKey)
624          self.assertEqual(root.AsKey, value)
625          self.assertEqual(root.Value, value)
626          self.assertEqual(flexbuffers.Loads(data), value)
627
628  def _check_fixed_typed_vector(self, data, vector, type_):
629    self.assertEqual(flexbuffers.Loads(data), vector)
630
631    root = flexbuffers.GetRoot(data)
632    self.assertTrue(root.IsFixedTypedVector)
633
634    v = root.AsFixedTypedVector
635    self.assertEqual(len(v), len(vector))
636    self.assertIs(v.ElementType, type_)
637    self.assertEqual([e.Value for e in v], vector)
638    self.assertSequenceEqual(v.Value, vector)
639
640    self.assertEqual(root.AsInt, len(vector))
641
642  def test_fixed_typed_vector_float(self):
643    for type_, vector in ((Type.VECTOR_FLOAT2, [-75.0, 34.89]),
644                          (Type.VECTOR_FLOAT3, [-75.0, 34.89, 12.0]),
645                          (Type.VECTOR_FLOAT4, [-75.0, 34.89, -1.0, 1.0])):
646      for bw in 1, 2, 4, 8:
647        for ebw in 4, 8:
648          with self.subTest(type=type_, vector=vector, bw=bw, ebw=ebw):
649            data = bytes([
650                # FixedTypedVector
651                *b''.join(float_bytes(e, ebw) for e in vector),
652                # Root
653                *uint_bytes(len(vector) * ebw, bw),
654                packed_type(type_, ebw),
655                bw,
656            ])
657
658            for a, b in zip(flexbuffers.Loads(data), vector):
659              self.assertAlmostEqual(a, b, places=2)
660
661  def test_fixed_typed_vector_int(self):
662    for type_, vector in ((Type.VECTOR_INT2, [0, -13]), (Type.VECTOR_INT3,
663                                                         [127, 0, -13]),
664                          (Type.VECTOR_INT4, [127, 0, -13, 0])):
665      for bw in 1, 2, 4, 8:
666        for ebw in 1, 2, 4, 8:
667          with self.subTest(type=type_, vector=vector, bw=bw, ebw=ebw):
668            data = bytes([
669                # FixedTypeVector
670                *b''.join(int_bytes(e, ebw) for e in vector),
671                # Root
672                *uint_bytes(ebw * len(vector), bw),
673                packed_type(type_, ebw),
674                bw,
675            ])
676
677            self._check_fixed_typed_vector(data, vector, Type.INT)
678
679  def test_fixed_typed_vector_uint(self):
680    for type_, vector in ((Type.VECTOR_UINT2, [0, 13]),
681                          (Type.VECTOR_UINT3, [127, 0, 13]), (Type.VECTOR_UINT4,
682                                                              [127, 0, 13, 0])):
683      for bw in 1, 2, 4, 8:
684        for ebw in 1, 2, 4, 8:
685          with self.subTest(type=type_, vector=vector, bw=bw, ebw=ebw):
686            data = bytes([
687                # FixedTypeVector
688                *b''.join(uint_bytes(e, ebw) for e in vector),
689                # Root
690                *uint_bytes(ebw * len(vector), bw),
691                packed_type(type_, ebw),
692                bw,
693            ])
694
695            self._check_fixed_typed_vector(data, vector, Type.UINT)
696
697  def _check_typed_vector(self, data, vector, type_):
698    self.assertEqual(flexbuffers.Loads(data), vector)
699
700    root = flexbuffers.GetRoot(data)
701    self.assertTrue(root.IsTypedVector)
702
703    v = root.AsTypedVector
704    self.assertIs(v.ElementType, type_)
705    self.assertEqual(len(v), len(vector))
706    self.assertEqual([e.Value for e in v], vector)
707    self.assertSequenceEqual(v.Value, vector)
708
709    self.assertEqual(root.AsInt, len(vector))
710
711  def test_empty_typed_vector(self):
712    for type_ in (Type.VECTOR_BOOL, Type.VECTOR_INT, Type.VECTOR_UINT,
713                  Type.VECTOR_FLOAT, Type.VECTOR_KEY,
714                  Type.VECTOR_STRING_DEPRECATED):
715      for bw in 1, 2, 4, 8:
716        for ebw in 1, 2, 4, 8:
717          with self.subTest(type=type_, bw=bw, ebw=ebw):
718            data = bytes([
719                # TypedVector[type_]
720                *uint_bytes(0, ebw),
721                # Root
722                *uint_bytes(0, bw),
723                packed_type(type_, ebw),
724                bw
725            ])
726
727            element_type = Type.ToTypedVectorElementType(type_)
728            if element_type == Type.STRING:
729              element_type = Type.KEY
730            self._check_typed_vector(data, [], element_type)
731
732  def test_typed_vector_bool(self):
733    vector = [True, False, False, False, True]
734
735    for bw in 1, 2, 4, 8:
736      for ebw in 1, 2, 4, 8:
737        with self.subTest(bw=bw, ebw=ebw):
738          data = bytes([
739              # TypedVector[Type.BOOL]
740              *uint_bytes(len(vector), ebw),
741              *b''.join(uint_bytes(int(e), ebw) for e in vector),
742              # Root
743              *uint_bytes(len(vector) * ebw, bw),
744              packed_type(Type.VECTOR_BOOL, ebw),
745              bw,
746          ])
747          self._check_typed_vector(data, vector, Type.BOOL)
748
749  def test_typed_vector_int(self):
750    vector = [-100, 200, -300]
751
752    for bw in 1, 2, 4, 8:
753      for ebw in 2, 4, 8:
754        with self.subTest(bw=bw, ebw=ebw):
755          data = bytes([
756              # TypedVector[Type.INT]
757              *uint_bytes(len(vector), ebw),
758              *b''.join(int_bytes(e, ebw) for e in vector),
759              # Root
760              *uint_bytes(len(vector) * ebw, bw),
761              packed_type(Type.VECTOR_INT, ebw),
762              bw,
763          ])
764          self._check_typed_vector(data, vector, Type.INT)
765
766  def test_typed_vector_uint(self):
767    vector = [100, 200, 300, 400, 0]
768
769    for bw in 1, 2, 4, 8:
770      for ebw in 2, 4, 8:
771        with self.subTest(bw=bw, ebw=ebw):
772          data = bytes([
773              # TypedVector[Type.UINT]
774              *uint_bytes(len(vector), ebw),
775              *b''.join(int_bytes(e, ebw) for e in vector),
776              # Root
777              *uint_bytes(len(vector) * ebw, bw),
778              packed_type(Type.VECTOR_UINT, ebw),
779              bw,
780          ])
781          self._check_typed_vector(data, vector, Type.UINT)
782
783  def test_typed_vector_float(self):
784    vector = [3.64, -6.36, 3.14, 634.0, -42.0]
785
786    for bw in 1, 2, 4, 8:
787      for ebw in 4, 8:
788        with self.subTest(bw=bw, ebw=ebw):
789          data = bytes([
790              # TypedVector[Type.FLOAT]
791              *uint_bytes(len(vector), ebw),
792              *b''.join(float_bytes(e, ebw) for e in vector),
793              # Root
794              *uint_bytes(ebw * len(vector), bw),
795              packed_type(Type.VECTOR_FLOAT, ebw),
796              bw,
797          ])
798
799          for a, b in zip(flexbuffers.Loads(data), vector):
800            self.assertAlmostEqual(a, b, places=2)
801
802  def test_typed_vector_key(self):
803    vector = ['red', 'green', 'blue']
804
805    for bw in 1, 2, 4, 8:
806      for ebw in 1, 2, 4, 8:
807        with self.subTest(bw=bw, ebw=ebw):
808          data = bytes([
809              # Keys
810              *key_bytes(vector[0]),
811              *key_bytes(vector[1]),
812              *key_bytes(vector[2]),
813              # TypedVector[Type.KEY]
814              *uint_bytes(len(vector), ebw),
815              *uint_bytes(15 + 1 * ebw, ebw),  # offset to vector[0]
816              *uint_bytes(11 + 2 * ebw, ebw),  # offset to vector[1]
817              *uint_bytes(5 + 3 * ebw, ebw),  # offset to vector[2]
818              # Root
819              *uint_bytes(len(vector) * ebw, bw),  # offset to vector
820              packed_type(Type.VECTOR_KEY, ebw),
821              bw,
822          ])
823          self._check_typed_vector(data, vector, Type.KEY)
824
825  def test_typed_vector_string(self):
826    vector = ['red', 'green', 'blue']
827
828    for bw in 1, 2, 4, 8:
829      for ebw in 1, 2, 4, 8:
830        with self.subTest(bw=bw, ebw=ebw):
831          data = bytes([
832              # Strings
833              *str_bytes(vector[0], 1),  # 5 bytes
834              *str_bytes(vector[1], 1),  # 7 bytes
835              *str_bytes(vector[2], 1),  # 6 bytes
836              # TypedVector[Type.STRING]
837              *uint_bytes(len(vector), ebw),
838              *uint_bytes(17 + 1 * ebw, ebw),  # offset to vector[0]
839              *uint_bytes(12 + 2 * ebw, ebw),  # offset to vector[1]
840              *uint_bytes(5 + 3 * ebw, ebw),  # offset to vector[2]
841              # Root
842              *uint_bytes(len(vector) * ebw, bw),  # offset to vector
843              packed_type(Type.VECTOR_STRING_DEPRECATED, ebw),
844              bw,
845          ])
846
847          # We have to pass Type.KEY because of Type.VECTOR_STRING_DEPRECATED.
848          self._check_typed_vector(data, vector, Type.KEY)
849
850  def test_typed_vector_string_deprecated(self):
851    # Check FlexBuffersDeprecatedTest() inside test.cpp for details.
852    vector = [300 * 'A', 'test']
853
854    fbb = flexbuffers.Builder()
855    with fbb.TypedVector():
856      for e in vector:
857        fbb.String(e)
858    data = fbb.Finish()
859
860    # We have to pass Type.KEY because of Type.VECTOR_STRING_DEPRECATED.
861    self._check_typed_vector(data, vector, Type.KEY)
862
863  def test_typed_vector_invalid(self):
864    fbb = flexbuffers.Builder()
865
866    with self.assertRaises(RuntimeError):
867      fbb.TypedVectorFromElements(['string', 423])
868
869  def test_empty_vector(self):
870    for bw in 1, 2, 4, 8:
871      for ebw in 1, 2, 4, 8:
872        data = bytes([
873            *uint_bytes(0, ebw),
874            # Root
875            *uint_bytes(0, bw),
876            packed_type(Type.VECTOR, ebw),
877            bw,
878        ])
879
880        root = flexbuffers.GetRoot(data)
881        self.assertTrue(root.IsVector)
882        self.assertEqual(len(root.AsVector), 0)
883
884        self.assertEqual(flexbuffers.Loads(data), [])
885
886  def test_vector1(self):
887    vector = [300, 400, 500]
888
889    for bw in 1, 2, 4, 8:
890      for ebw in 2, 4, 8:
891        for tbw_ignored in 1, 2, 4, 8:
892          with self.subTest(bw=bw, ebw=ebw, ignore=tbw_ignored):
893            data = bytes([
894                # Vector length
895                *uint_bytes(len(vector), ebw),
896                # Vector elements
897                *int_bytes(vector[0], ebw),
898                *int_bytes(vector[1], ebw),
899                *int_bytes(vector[2], ebw),
900                # Vector types
901                packed_type(Type.INT, tbw_ignored),
902                packed_type(Type.INT, tbw_ignored),
903                packed_type(Type.INT, tbw_ignored),
904                # Root
905                *uint_bytes(ebw * len(vector) + len(vector), bw),
906                packed_type(Type.VECTOR, ebw),
907                bw,
908            ])
909
910            root = flexbuffers.GetRoot(data)
911            self.assertTrue(root.IsVector)
912            self.assertFalse(root.IsMap)
913
914            v = root.AsVector
915            self.assertEqual(len(v), len(vector))
916
917            for i in range(len(v)):
918              self.assertTrue(v[i].IsInt)
919              self.assertEqual(v[i].AsInt, vector[i])
920
921            for i, e in enumerate(v):
922              self.assertTrue(e.IsInt)
923              self.assertEqual(e.AsInt, vector[i])
924
925            with self.assertRaises(IndexError):
926              v[-1].AsInt  # pylint: disable=pointless-statement
927
928            with self.assertRaises(IndexError):
929              v[3].AsInt  # pylint: disable=pointless-statement
930
931            with self.assertRaises(TypeError):
932              root.AsMap  # pylint: disable=pointless-statement
933
934            self.assertEqual(root.AsInt, len(vector))
935            self.assertEqual(root.AsFloat, float(len(vector)))
936
937            self.assertEqual(flexbuffers.Loads(data), vector)
938
939  def test_vector2(self):
940    vector = [1984, 'August', True]
941
942    for bw in 1, 2, 4, 8:
943      with self.subTest(bw=bw):
944        data = bytes([
945            *str_bytes(vector[1], 1),
946            # Vector
947            *uint_bytes(len(vector), 2),
948            *int_bytes(vector[0], 2),
949            *uint_bytes(11, 2),  # offset to 'August'
950            *uint_bytes(int(vector[2]), 2),
951            packed_type(Type.INT, 2),
952            packed_type(Type.STRING, 1),
953            packed_type(Type.BOOL, 2),
954            # Root
955            *uint_bytes(2 * len(vector) + len(vector), bw),  # offset to vector
956            packed_type(Type.VECTOR, 2),
957            bw,
958        ])
959        self.assertEqual(flexbuffers.Loads(data), vector)
960
961        root = flexbuffers.GetRoot(data)
962        self.assertTrue(root.IsVector)
963
964        v = root.AsVector
965        self.assertTrue(v[0].IsInt)
966        self.assertEqual(v[0].AsInt, 1984)
967
968        self.assertTrue(v[1].IsString)
969        self.assertEqual(v[1].AsString, 'August')
970
971        self.assertTrue(v[2].IsBool)
972        self.assertTrue(v[2].AsBool)
973
974        self.assertEqual(v.Value, vector)
975
976        self.assertEqual(root.AsInt, len(vector))
977
978  def test_empty_map(self):
979    for bw in 1, 2, 4, 8:
980      for kbw in 1, 2, 4, 8:
981        for vbw in 1, 2, 4, 8:
982          data = bytes([
983              *uint_bytes(0, kbw),  # Keys length
984              *uint_bytes(0, vbw),
985              *uint_bytes(kbw, vbw),
986              *uint_bytes(0, vbw),  # Values length
987              # Root
988              *uint_bytes(0, bw),
989              packed_type(Type.MAP, vbw),
990              bw,
991          ])
992
993          root = flexbuffers.GetRoot(data)
994          self.assertTrue(root.IsMap)
995          self.assertEqual(len(root.AsMap), 0)
996
997          self.assertEqual(flexbuffers.Loads(data), {})
998
999  def test_map(self):
1000    value = {'foo': 13, 'bar': 14}
1001
1002    for bw in 1, 2, 4, 8:
1003      for kbw in 1, 2, 4, 8:
1004        for vbw in 1, 2, 4, 8:
1005          with self.subTest(kbw=kbw, vbw=vbw, bw=bw):
1006            data = bytes([
1007                *key_bytes('foo'),  # 4 bytes
1008                *key_bytes('bar'),  # 4 bytes
1009                # Map
1010                *uint_bytes(len(value), kbw),
1011                *uint_bytes(4 + 1 * kbw, kbw),  # offset to 'bar'
1012                *uint_bytes(8 + 2 * kbw, kbw),  # offset to 'foo'
1013                *uint_bytes(len(value) * kbw, vbw),  # offset to keys
1014                *uint_bytes(kbw, vbw),
1015                *uint_bytes(len(value), vbw),
1016                *int_bytes(value['bar'], vbw),
1017                *int_bytes(value['foo'], vbw),
1018                packed_type(Type.INT, vbw),
1019                packed_type(Type.INT, vbw),
1020                # Root
1021                *uint_bytes(vbw * len(value) + len(value),
1022                            bw),  # offset to values
1023                packed_type(Type.MAP, vbw),
1024                bw,
1025            ])
1026
1027            root = flexbuffers.GetRoot(data)
1028            self.assertTrue(root.IsMap)
1029
1030            m = root.AsMap
1031            self.assertEqual(len(m), 2)
1032            self.assertEqual(m[0].AsInt, 14)
1033            self.assertEqual(m[1].AsInt, 13)
1034
1035            self.assertEqual(m['bar'].AsInt, 14)
1036            self.assertEqual(m['foo'].AsInt, 13)
1037
1038            for invalid_key in 'a', 'b', 'no':
1039              with self.assertRaises(KeyError):
1040                m[invalid_key]  # pylint: disable=pointless-statement
1041
1042            values = m.Values
1043            self.assertEqual(len(values), 2)
1044            self.assertEqual(values[0].AsInt, 14)
1045            self.assertEqual(values[1].AsInt, 13)
1046
1047            keys = m.Keys
1048            self.assertEqual(len(keys), 2)
1049            self.assertEqual(len(keys[0].AsKey), 3)
1050            self.assertEqual(keys[0].AsKey, 'bar')
1051            self.assertEqual(len(keys[1].AsKey), 3)
1052            self.assertEqual(keys[1].AsKey, 'foo')
1053
1054            keys = [key.AsKey for key in keys]
1055            self.assertEqual(sorted(keys), keys)
1056
1057            self.assertEqual(root.AsInt, len(value))
1058
1059            self.assertEqual(flexbuffers.Loads(data), value)
1060
1061  def test_alignment(self):
1062    value = ['test', 7]
1063
1064    data = bytes([
1065        *key_bytes('test'),  # 5 bytes: 'test' and \0
1066        0,
1067        0,
1068        0,  # 3 bytes: alignment
1069        # Vector
1070        *uint_bytes(len(value), byte_width=8),
1071        *uint_bytes(16, byte_width=8),
1072        *uint_bytes(7, byte_width=8),
1073        packed_type(Type.KEY, 1),
1074        packed_type(Type.INT, 8),
1075        # Root
1076        *uint_bytes(8 * len(value) + len(value), 1),
1077        packed_type(Type.VECTOR, 8),
1078        1,
1079    ])
1080
1081    self.assertEqual(flexbuffers.Loads(data), value)
1082
1083
1084class EncoderTest(unittest.TestCase):
1085  """Tests to check FlexBuffer encoding functions."""
1086
1087  def test_null(self):
1088    def encode_null():
1089      fbb = flexbuffers.Builder()
1090      fbb.Null()
1091      return fbb.Finish()
1092
1093    self.assertIsNone(flexbuffers.Loads(encode_null()))
1094
1095  def test_bool(self):
1096    for value in False, True:
1097      data = encode_type(Type.BOOL, value)
1098      self.assertEqual(flexbuffers.Loads(data), value)
1099
1100  def test_int(self):
1101    for byte_width in 1, 2, 4, 8:
1102      for type_ in Type.INT, Type.INDIRECT_INT, Type.UINT, Type.INDIRECT_UINT:
1103        with self.subTest(byte_width=byte_width, type=type_):
1104          value = min_value(type_, byte_width)
1105          data = encode_type(type_, value)
1106          self.assertEqual(flexbuffers.Loads(data), value)
1107
1108          value = max_value(type_, byte_width)
1109          data = encode_type(type_, value)
1110          self.assertEqual(flexbuffers.Loads(data), value)
1111
1112  def test_float(self):
1113    for value in 3.141592, 7.62, 999.99:
1114      for type_ in Type.FLOAT, Type.INDIRECT_FLOAT:
1115        with self.subTest(value=value, type=type_):
1116          data = encode_type(type_, value)
1117          self.assertEqual(flexbuffers.Loads(data), value)
1118
1119          data = encode_type(type_, value, 4)
1120          self.assertAlmostEqual(flexbuffers.Loads(data), value, places=4)
1121
1122          data = encode_type(type_, value, 8)
1123          self.assertEqual(flexbuffers.Loads(data), value)
1124
1125  def test_string(self):
1126    for value in '', 'x', 'color', 'hello world':
1127      with self.subTest(value=value):
1128        data = encode_type(Type.STRING, value)
1129        self.assertEqual(flexbuffers.Loads(data), value)
1130
1131  def test_blob(self):
1132    for value in bytes(), bytes([240, 12, 143, 7]), bytes(1000 * [17]):
1133      with self.subTest(value=value):
1134        data = encode_type(Type.BLOB, value)
1135        self.assertEqual(flexbuffers.Loads(data), value)
1136
1137  def test_key(self):
1138    for value in '', 'color', 'hello world':
1139      with self.subTest(value=value):
1140        data = encode_type(Type.KEY, value)
1141        self.assertEqual(flexbuffers.Loads(data), value)
1142
1143    with self.assertRaises(ValueError):
1144      encode_type(Type.KEY, (b'\x00' * 10).decode('ascii'))
1145
1146  def test_vector(self):
1147
1148    def encode_vector(elements, element_type):
1149      fbb = flexbuffers.Builder()
1150      with fbb.Vector():
1151        add = fbb.Adder(element_type)
1152        for e in elements:
1153          add(e)
1154      return fbb.Finish()
1155
1156    def encode_vector_from_elements(elements):
1157      fbb = flexbuffers.Builder()
1158      fbb.VectorFromElements(elements)
1159      return fbb.Finish()
1160
1161    for elements in [], [1435], [56, 23, 0, 6783]:
1162      data = encode_vector(elements, Type.INT)
1163      self.assertEqual(flexbuffers.Loads(data), elements)
1164
1165      data = encode_vector_from_elements(elements)
1166      self.assertEqual(flexbuffers.Loads(data), elements)
1167
1168    # Elements of different type: one by one
1169    elements = [56.0, 'flexbuffers', 0, False, 75123]
1170
1171    fbb = flexbuffers.Builder()
1172    with fbb.Vector():
1173      fbb.Float(elements[0])
1174      fbb.String(elements[1])
1175      fbb.UInt(elements[2], 8)
1176      fbb.Bool(elements[3])
1177      fbb.Int(elements[4])
1178    data = fbb.Finish()
1179    self.assertEqual(flexbuffers.Loads(data), elements)
1180
1181    # Elements of different type: all at once
1182    fbb = flexbuffers.Builder()
1183    fbb.VectorFromElements(elements)
1184    data = fbb.Finish()
1185    self.assertEqual(flexbuffers.Loads(data), elements)
1186
1187  def test_nested_vectors(self):
1188    fbb = flexbuffers.Builder()
1189    with fbb.Vector():
1190      fbb.String('begin')
1191      fbb.IndirectInt(42)
1192      with fbb.Vector():
1193        for i in range(5):
1194          fbb.Int(i)
1195      fbb.String('end')
1196    data = fbb.Finish()
1197
1198    self.assertEqual(
1199        flexbuffers.Loads(data), ['begin', 42, [0, 1, 2, 3, 4], 'end'])
1200
1201  def test_big_vector(self):
1202    n = 10 * 1000
1203    fbb = flexbuffers.Builder()
1204    with fbb.Vector():
1205      for i in range(n):
1206        fbb.Int(i)
1207    self.assertEqual(flexbuffers.Loads(fbb.Finish()), list(range(n)))
1208
1209  def test_typed_vector(self):
1210
1211    def encode_typed_vector_from_elements(elements, element_type=None):
1212      fbb = flexbuffers.Builder()
1213      fbb.TypedVectorFromElements(elements, element_type)
1214      return fbb.Finish()
1215
1216    for elements in [], [False], [True], [False, True, True, False, False]:
1217      data = encode_typed_vector_from_elements(elements, Type.BOOL)
1218      self.assertEqual(flexbuffers.Loads(data), elements)
1219
1220      data = encode_typed_vector_from_elements(elements)
1221      self.assertEqual(flexbuffers.Loads(data), elements)
1222
1223    for elements in [], [23455], [351, -2, 0, 6783, 0, -10]:
1224      data = encode_typed_vector_from_elements(elements, Type.INT)
1225      self.assertEqual(flexbuffers.Loads(data), elements)
1226
1227      data = encode_typed_vector_from_elements(elements)
1228      self.assertEqual(flexbuffers.Loads(data), elements)
1229
1230    for elements in [], [23455], [351, 2, 0, 6783, 0, 10]:
1231      data = encode_typed_vector_from_elements(elements)
1232      self.assertEqual(flexbuffers.Loads(data), elements)
1233
1234      data = encode_typed_vector_from_elements(elements, Type.INT)
1235      self.assertEqual(flexbuffers.Loads(data), elements)
1236
1237      data = encode_typed_vector_from_elements(elements, Type.UINT)
1238      self.assertEqual(flexbuffers.Loads(data), elements)
1239
1240    for elements in [], [7.0], [52.0, 51.2, 70.0, -4.0]:
1241      data = encode_typed_vector_from_elements(elements, Type.FLOAT)
1242      self.assertEqual(flexbuffers.Loads(data), elements)
1243
1244      data = encode_typed_vector_from_elements(elements)
1245      self.assertEqual(flexbuffers.Loads(data), elements)
1246
1247    for elements in [], ['color'], ['x', 'y']:
1248      data = encode_typed_vector_from_elements(elements, Type.KEY)
1249      self.assertEqual(flexbuffers.Loads(data), elements)
1250
1251      data = encode_typed_vector_from_elements(elements)
1252      self.assertEqual(flexbuffers.Loads(data), elements)
1253
1254  def test_typed_vector_from_array(self):
1255
1256    def encode_array(typecode, values):
1257      fbb = flexbuffers.Builder()
1258      fbb.VectorFromElements(array.array(typecode, values))
1259      return fbb.Finish()
1260
1261    values = [1.0, 3.14, -2.54, 0.0]
1262    data = encode_array('f', values)
1263    for a, b in zip(flexbuffers.Loads(data), values):
1264      self.assertAlmostEqual(a, b, places=2)
1265
1266    values = [1.0, 3.14, -2.54, 0.0]
1267    data = encode_array('d', values)
1268    self.assertEqual(flexbuffers.Loads(data), values)
1269
1270    values = [1, -7, 9, 26, 12]
1271    data = encode_array('i', values)
1272    self.assertEqual(flexbuffers.Loads(data), values)
1273
1274    values = [0, 1, 2, 3, 4, 5, 6]
1275    data = encode_array('I', values)
1276    self.assertEqual(flexbuffers.Loads(data), values)
1277
1278  def test_fixed_typed_vector(self):
1279
1280    def encode_fixed_typed_vector(elements, element_type=None):
1281      fbb = flexbuffers.Builder()
1282      fbb.FixedTypedVectorFromElements(elements, element_type)
1283      return fbb.Finish()
1284
1285    for elements in ((-2, 2), (1, 2, 3), (100, -100, 200, -200), (4.0, 7.0),
1286                     (0.0, 1.0, 8.0), (9.0, 7.0, 1.0, 5.5)):
1287      with self.subTest(elements=elements):
1288        data = encode_fixed_typed_vector(elements)
1289        self.assertSequenceEqual(flexbuffers.Loads(data), elements)
1290
1291    elements = [-170, 432, 0, -7]
1292    data = encode_fixed_typed_vector(elements, Type.INT)
1293    self.assertSequenceEqual(flexbuffers.Loads(data), elements)
1294
1295    with self.assertRaises(ValueError):
1296      encode_fixed_typed_vector([])  # Invalid input length
1297
1298    with self.assertRaises(ValueError):
1299      encode_fixed_typed_vector([1])  # Invalid input length
1300
1301    with self.assertRaises(ValueError):
1302      encode_fixed_typed_vector([1, 2, 3, 4, 5])  # Invalid input length
1303
1304    with self.assertRaises(TypeError):
1305      encode_fixed_typed_vector([1, 1.0])  # Invalid input types
1306
1307    with self.assertRaises(TypeError):
1308      encode_fixed_typed_vector(['', ''])  # Invalid input types
1309
1310  def test_map_builder(self):
1311
1312    def get_keys(data):
1313      return [key.AsKey for key in flexbuffers.GetRoot(data).AsMap.Keys]
1314
1315    # Empty map
1316    fbb = flexbuffers.Builder()
1317    with fbb.Map():
1318      pass
1319    data = fbb.Finish()
1320
1321    self.assertEqual(flexbuffers.Loads(data), {})
1322
1323    # Two-element map of Int
1324    fbb = flexbuffers.Builder()
1325    with fbb.Map():
1326      fbb.Int('y', -2)
1327      fbb.Int('x', 10)
1328    data = fbb.Finish()
1329
1330    self.assertEqual(flexbuffers.Loads(data), {'x': 10, 'y': -2})
1331
1332    # Multiple-element map of vectors
1333    fbb = flexbuffers.Builder()
1334    with fbb.Map():
1335      with fbb.Vector('v'):
1336        fbb.Int(45)
1337      with fbb.TypedVector('tv'):
1338        fbb.Int(-7)
1339      fbb.FixedTypedVectorFromElements('ftv', [-2.0, 1.0])
1340    data = fbb.Finish()
1341
1342    self.assertEqual(
1343        flexbuffers.Loads(data), {
1344            'v': [45],
1345            'tv': [-7],
1346            'ftv': [-2.0, 1.0]
1347        })
1348
1349    keys = get_keys(data)
1350    self.assertEqual(sorted(keys), keys)
1351
1352    # Multiple-element map of different types
1353    fbb = flexbuffers.Builder()
1354    with fbb.Map():
1355      fbb.Null('n')
1356      fbb.Bool('b', False)
1357      fbb.Int('i', -27)
1358      fbb.UInt('u', 27)
1359      fbb.Float('f', -0.85)
1360      fbb.String('s', 'String')
1361      fbb.Blob('bb', b'data')
1362      fbb.IndirectInt('ii', -9500)
1363      fbb.IndirectUInt('iu', 540)
1364      fbb.IndirectFloat('if', 0.0)
1365      fbb.VectorFromElements('v', [2, 1, 0.0])
1366      fbb.TypedVectorFromElements('tv', [2, 1, 0])
1367      fbb.FixedTypedVectorFromElements('ftv', [2.0, -6.0])
1368    data = fbb.Finish()
1369
1370    self.assertEqual(
1371        flexbuffers.Loads(data), {
1372            'n': None,
1373            'b': False,
1374            'i': -27,
1375            'u': 27,
1376            'f': -0.85,
1377            's': 'String',
1378            'bb': b'data',
1379            'ii': -9500,
1380            'iu': 540,
1381            'if': 0.0,
1382            'v': [2, 1, 0.0],
1383            'tv': [2, 1, 0],
1384            'ftv': [2.0, -6.0]
1385        })
1386
1387    keys = get_keys(data)
1388    self.assertEqual(sorted(keys), keys)
1389
1390  def test_map_python(self):
1391    maps = [
1392        {},
1393        {
1394            'key': 'value'
1395        },
1396        {
1397            'x': None,
1398            'y': 3400,
1399            'z': -7040
1400        },
1401        {
1402            'zzz': 100,
1403            'aaa': 5.0,
1404            'ccc': ['Test', 32, False, None, True]
1405        },
1406        {
1407            'name': ['John', 'Smith'],
1408            'valid': True,
1409            'note': None,
1410            'address': {
1411                'lines': [175, 'Alhambra'],
1412                'city': 'San Francisco',
1413                'zip': 94123,
1414            },
1415        },
1416    ]
1417
1418    for m in maps:
1419      self.assertEqual(flexbuffers.Loads(flexbuffers.Dumps(m)), m)
1420
1421  def test_gold_from_file(self):
1422    data = read_test_file(GOLD_FLEXBUFFER_FILE)
1423    self.assertEqual(flexbuffers.Loads(data), GOLD_FLEXBUFFER_OBJ)
1424
1425  def test_gold_from_builder(self):
1426    fbb = flexbuffers.Builder()
1427    with fbb.Map():
1428      with fbb.Vector('vec'):
1429        fbb.Int(-100)
1430        fbb.String('Fred')
1431        fbb.IndirectFloat(4.0)
1432        i_f = fbb.LastValue
1433        fbb.Blob(bytes([77]))
1434        fbb.Bool(False)
1435        fbb.ReuseValue(i_f)
1436
1437      vec = [1, 2, 3]
1438      fbb.VectorFromElements('bar', vec)
1439      fbb.FixedTypedVectorFromElements('bar3', [1, 2, 3])
1440      fbb.VectorFromElements('bools', [True, False, True, False])
1441      fbb.Bool('bool', True)
1442      fbb.Float('foo', 100)
1443      with fbb.Map('mymap'):
1444        fbb.String('foo', 'Fred')
1445    data = fbb.Finish()
1446
1447    self.assertEqual(flexbuffers.Loads(data), GOLD_FLEXBUFFER_OBJ)
1448
1449  def test_min_bit_width(self):
1450    fbb = flexbuffers.Builder(force_min_bit_width=flexbuffers.BitWidth.W8)
1451    fbb.TypedVectorFromElements([0, 1, 0, 1, 0])
1452    data = fbb.Finish()
1453
1454    root = flexbuffers.GetRoot(data)
1455    self.assertTrue(root.IsTypedVector)
1456    self.assertEqual(root.AsTypedVector.ByteWidth, 1)
1457
1458    fbb = flexbuffers.Builder(force_min_bit_width=flexbuffers.BitWidth.W32)
1459    fbb.TypedVectorFromElements([0, 1, 0, 1, 0])
1460    data = fbb.Finish()
1461
1462    root = flexbuffers.GetRoot(data)
1463    self.assertTrue(root.IsTypedVector)
1464    self.assertEqual(root.AsTypedVector.ByteWidth, 4)
1465
1466  def test_share_keys(self):
1467
1468    def encode_key_vector(value, count, share_keys):
1469      fbb = flexbuffers.Builder(share_keys=share_keys)
1470      with fbb.Vector():
1471        for _ in range(count):
1472          fbb.Key(value)
1473      return fbb.Finish(), fbb.KeyPool.Elements
1474
1475    data, pool = encode_key_vector('test', 10, share_keys=False)
1476    self.assertEqual(len(pool), 0)
1477    self.assertEqual(len(data), 74)
1478    self.assertEqual(flexbuffers.Loads(data), 10 * ['test'])
1479
1480    data, pool = encode_key_vector('test', 10, share_keys=True)
1481    self.assertEqual(len(pool), 1)
1482    self.assertEqual(pool[0], 'test'.encode('ascii'))
1483    self.assertEqual(len(data), 29)
1484    self.assertEqual(flexbuffers.Loads(data), 10 * ['test'])
1485
1486  def test_share_strings(self):
1487
1488    def encode_string_vector(value, count, share_strings):
1489      fbb = flexbuffers.Builder(share_strings=share_strings)
1490      with fbb.Vector():
1491        for _ in range(count):
1492          fbb.String(value)
1493      return fbb.Finish(), fbb.StringPool.Elements
1494
1495    data, pool = encode_string_vector('test', 10, share_strings=False)
1496    self.assertEqual(len(pool), 0)
1497    self.assertEqual(len(data), 84)
1498    self.assertEqual(flexbuffers.Loads(data), 10 * ['test'])
1499
1500    data, pool = encode_string_vector('test', 10, share_strings=True)
1501    self.assertEqual(len(pool), 1)
1502    self.assertEqual(pool[0], 'test'.encode('utf-8'))
1503    self.assertEqual(len(data), 30)
1504    self.assertEqual(flexbuffers.Loads(data), 10 * ['test'])
1505
1506  def test_invalid_stack_size(self):
1507    fbb = flexbuffers.Builder()
1508
1509    with self.assertRaises(RuntimeError):
1510      fbb.Finish()
1511
1512    fbb.Int(100)
1513    fbb.Int(200)
1514    with self.assertRaises(RuntimeError):
1515      fbb.Finish()
1516
1517    fbb.Clear()
1518    fbb.Int(420)
1519    fbb.Finish()
1520
1521
1522if __name__ == '__main__':
1523  unittest.main()
1524