...

Text file src/github.com/google/flatbuffers/tests/py_flexbuffers_test.py

Documentation: github.com/google/flatbuffers/tests

     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('<%s' % {1: 'b', 2: 'h', 4: 'i', 8: 'q'}[byte_width], value)
    78
    79
    80def uint_bytes(value, byte_width):
    81  return struct.pack('<%s' % {1: 'B', 2: 'H', 4: 'I', 8: 'Q'}[byte_width], value)
    82
    83
    84def float_bytes(value, byte_width):
    85  return struct.pack('<%s' % {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()

View as plain text