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