• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# coding=utf-8
2# Copyright 2014 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
16import os.path
17import sys
18import imp
19PY_VERSION = sys.version_info[:2]
20
21import ctypes
22from collections import defaultdict
23import math
24import random
25import timeit
26import unittest
27
28from flatbuffers import compat
29from flatbuffers import util
30from flatbuffers.compat import range_func as compat_range
31from flatbuffers.compat import NumpyRequiredForThisFeature
32
33import flatbuffers
34from flatbuffers import number_types as N
35
36import MyGame  # refers to generated code
37import MyGame.Example  # refers to generated code
38import MyGame.Example.Any  # refers to generated code
39import MyGame.Example.Color  # refers to generated code
40import MyGame.Example.Monster  # refers to generated code
41import MyGame.Example.Test  # refers to generated code
42import MyGame.Example.Stat  # refers to generated code
43import MyGame.Example.Vec3  # refers to generated code
44import MyGame.MonsterExtra  # refers to generated code
45import MyGame.InParentNamespace # refers to generated code
46import MyGame.Example.ArrayTable  # refers to generated code
47import MyGame.Example.ArrayStruct  # refers to generated code
48import MyGame.Example.NestedStruct  # refers to generated code
49import MyGame.Example.TestEnum  # refers to generated code
50
51def assertRaises(test_case, fn, exception_class):
52    ''' Backwards-compatible assertion for exceptions raised. '''
53
54    exc = None
55    try:
56        fn()
57    except Exception as e:
58        exc = e
59    test_case.assertTrue(exc is not None)
60    test_case.assertTrue(isinstance(exc, exception_class))
61
62
63class TestWireFormat(unittest.TestCase):
64    def test_wire_format(self):
65        # Verify that using the generated Python code builds a buffer without
66        # returning errors, and is interpreted correctly, for size prefixed
67        # representation and regular:
68        for sizePrefix in [True, False]:
69            for file_identifier in [None, b"MONS"]:
70                gen_buf, gen_off = make_monster_from_generated_code(sizePrefix=sizePrefix, file_identifier=file_identifier)
71                CheckReadBuffer(gen_buf, gen_off, sizePrefix=sizePrefix, file_identifier=file_identifier)
72
73        # Verify that the canonical flatbuffer file is readable by the
74        # generated Python code. Note that context managers are not part of
75        # Python 2.5, so we use the simpler open/close methods here:
76        f = open('monsterdata_test.mon', 'rb')
77        canonicalWireData = f.read()
78        f.close()
79        CheckReadBuffer(bytearray(canonicalWireData), 0, file_identifier=b'MONS')
80
81        # Write the generated buffer out to a file:
82        f = open('monsterdata_python_wire.mon', 'wb')
83        f.write(gen_buf[gen_off:])
84        f.close()
85
86
87class TestObjectBasedAPI(unittest.TestCase):
88    ''' Tests the generated object based API.'''
89
90    def test_consistenty_with_repeated_pack_and_unpack(self):
91        ''' Checks the serialization and deserialization between a buffer and
92        its python object. It tests in the same way as the C++ object API test,
93        ObjectFlatBuffersTest in test.cpp. '''
94
95        buf, off = make_monster_from_generated_code()
96
97        # Turns a buffer into Python object (T class).
98        monster1 = MyGame.Example.Monster.Monster.GetRootAsMonster(buf, off)
99        monsterT1 = MyGame.Example.Monster.MonsterT.InitFromObj(monster1)
100
101        for sizePrefix in [True, False]:
102            # Re-serialize the data into a buffer.
103            b1 = flatbuffers.Builder(0)
104            if sizePrefix:
105                b1.FinishSizePrefixed(monsterT1.Pack(b1))
106            else:
107                b1.Finish(monsterT1.Pack(b1))
108            CheckReadBuffer(b1.Bytes, b1.Head(), sizePrefix)
109
110        # Deserializes the buffer into Python object again.
111        monster2 = MyGame.Example.Monster.Monster.GetRootAsMonster(b1.Bytes,
112                                                                   b1.Head())
113        # Re-serializes the data into a buffer for one more time.
114        monsterT2 = MyGame.Example.Monster.MonsterT.InitFromObj(monster2)
115        for sizePrefix in [True, False]:
116            # Re-serializes the data into a buffer
117            b2 = flatbuffers.Builder(0)
118            if sizePrefix:
119                b2.FinishSizePrefixed(monsterT2.Pack(b2))
120            else:
121                b2.Finish(monsterT2.Pack(b2))
122            CheckReadBuffer(b2.Bytes, b2.Head(), sizePrefix)
123
124    def test_default_values_with_pack_and_unpack(self):
125        ''' Serializes and deserializes between a buffer with default values (no
126        specific values are filled when the buffer is created) and its python
127        object. '''
128        # Creates a flatbuffer with default values.
129        b1 = flatbuffers.Builder(0)
130        MyGame.Example.Monster.MonsterStart(b1)
131        gen_mon = MyGame.Example.Monster.MonsterEnd(b1)
132        b1.Finish(gen_mon)
133
134        # Converts the flatbuffer into the object class.
135        monster1 = MyGame.Example.Monster.Monster.GetRootAsMonster(b1.Bytes,
136                                                                   b1.Head())
137        monsterT1 = MyGame.Example.Monster.MonsterT.InitFromObj(monster1)
138
139        # Packs the object class into another flatbuffer.
140        b2 = flatbuffers.Builder(0)
141        b2.Finish(monsterT1.Pack(b2))
142        monster2 = MyGame.Example.Monster.Monster.GetRootAsMonster(b2.Bytes,
143                                                                   b2.Head())
144        # Checks the default values.
145        self.assertTrue(monster2.Pos() is None)
146        self.assertEqual(monster2.Mana(),150)
147        self.assertEqual(monster2.Hp(), 100)
148        self.assertTrue(monster2.Name() is None)
149        self.assertEqual(monster2.Inventory(0), 0)
150        self.assertEqual(monster2.InventoryAsNumpy(), 0)
151        self.assertEqual(monster2.InventoryLength(), 0)
152        self.assertTrue(monster2.InventoryIsNone())
153        self.assertTrue(monster2.Color() is 8)
154        self.assertEqual(monster2.TestType(), 0)
155        self.assertTrue(monster2.Test() is None)
156        self.assertTrue(monster2.Test4(0) is None)
157        self.assertEqual(monster2.Test4Length(), 0)
158        self.assertTrue(monster2.Test4IsNone())
159        self.assertTrue(monster2.Testarrayofstring(0) is "")
160        self.assertEqual(monster2.TestarrayofstringLength(), 0)
161        self.assertTrue(monster2.TestarrayofstringIsNone())
162        self.assertTrue(monster2.Testarrayoftables(0) is None)
163        self.assertEqual(monster2.TestarrayoftablesLength(), 0)
164        self.assertTrue(monster2.TestarrayoftablesIsNone())
165        self.assertTrue(monster2.Enemy() is None)
166        self.assertEqual(monster2.Testnestedflatbuffer(0), 0)
167        self.assertEqual(monster2.TestnestedflatbufferAsNumpy(), 0)
168        self.assertEqual(monster2.TestnestedflatbufferLength(), 0)
169        self.assertTrue(monster2.TestnestedflatbufferIsNone())
170        self.assertTrue(monster2.Testempty() is None)
171        self.assertTrue(monster2.Testbool() is False)
172        self.assertEqual(monster2.Testhashs32Fnv1(), 0)
173        self.assertEqual(monster2.Testhashu32Fnv1(), 0)
174        self.assertEqual(monster2.Testhashs64Fnv1(), 0)
175        self.assertEqual(monster2.Testhashu64Fnv1(), 0)
176        self.assertEqual(monster2.Testhashs32Fnv1a(), 0)
177        self.assertEqual(monster2.Testhashu32Fnv1a(), 0)
178        self.assertEqual(monster2.Testhashs64Fnv1a(), 0)
179        self.assertEqual(monster2.Testhashu64Fnv1a(), 0)
180        self.assertEqual(monster2.Testarrayofbools(0), 0)
181        self.assertEqual(monster2.TestarrayofboolsAsNumpy(), 0)
182        self.assertEqual(monster2.TestarrayofboolsLength(), 0)
183        self.assertTrue(monster2.TestarrayofboolsIsNone())
184        self.assertEqual(monster2.Testf(), 3.14159)
185        self.assertEqual(monster2.Testf2(), 3.0)
186        self.assertEqual(monster2.Testf3(), 0.0)
187        self.assertTrue(monster2.Testarrayofstring2(0) is "")
188        self.assertEqual(monster2.Testarrayofstring2Length(), 0)
189        self.assertTrue(monster2.Testarrayofstring2IsNone())
190        self.assertTrue(monster2.Testarrayofsortedstruct(0) is None)
191        self.assertEqual(monster2.TestarrayofsortedstructLength(), 0)
192        self.assertTrue(monster2.TestarrayofsortedstructIsNone())
193        self.assertEqual(monster2.Flex(0), 0)
194        self.assertEqual(monster2.FlexAsNumpy(), 0)
195        self.assertEqual(monster2.FlexLength(), 0)
196        self.assertTrue(monster2.FlexIsNone())
197        self.assertTrue(monster2.Test5(0) is None)
198        self.assertEqual(monster2.Test5Length(), 0)
199        self.assertTrue(monster2.Test5IsNone())
200        self.assertEqual(monster2.VectorOfLongs(0), 0)
201        self.assertEqual(monster2.VectorOfLongsAsNumpy(), 0)
202        self.assertEqual(monster2.VectorOfLongsLength(), 0)
203        self.assertTrue(monster2.VectorOfLongsIsNone())
204        self.assertEqual(monster2.VectorOfDoubles(0), 0)
205        self.assertEqual(monster2.VectorOfDoublesAsNumpy(), 0)
206        self.assertEqual(monster2.VectorOfDoublesLength(), 0)
207        self.assertTrue(monster2.VectorOfDoublesIsNone())
208        self.assertTrue(monster2.ParentNamespaceTest() is None)
209        self.assertTrue(monster2.VectorOfReferrables(0) is None)
210        self.assertEqual(monster2.VectorOfReferrablesLength(), 0)
211        self.assertTrue(monster2.VectorOfReferrablesIsNone())
212        self.assertEqual(monster2.SingleWeakReference(), 0)
213        self.assertEqual(monster2.VectorOfWeakReferences(0), 0)
214        self.assertEqual(monster2.VectorOfWeakReferencesAsNumpy(), 0)
215        self.assertEqual(monster2.VectorOfWeakReferencesLength(), 0)
216        self.assertTrue(monster2.VectorOfWeakReferencesIsNone())
217        self.assertTrue(monster2.VectorOfStrongReferrables(0) is None)
218        self.assertEqual(monster2.VectorOfStrongReferrablesLength(), 0)
219        self.assertTrue(monster2.VectorOfStrongReferrablesIsNone())
220        self.assertEqual(monster2.CoOwningReference(), 0)
221        self.assertEqual(monster2.VectorOfCoOwningReferences(0), 0)
222        self.assertEqual(monster2.VectorOfCoOwningReferencesAsNumpy(), 0)
223        self.assertEqual(monster2.VectorOfCoOwningReferencesLength(), 0)
224        self.assertTrue(monster2.VectorOfCoOwningReferencesIsNone())
225        self.assertEqual(monster2.NonOwningReference(), 0)
226        self.assertEqual(monster2.VectorOfNonOwningReferences(0), 0)
227        self.assertEqual(monster2.VectorOfNonOwningReferencesAsNumpy(), 0)
228        self.assertEqual(monster2.VectorOfNonOwningReferencesLength(), 0)
229        self.assertTrue(monster2.VectorOfNonOwningReferencesIsNone())
230        self.assertEqual(monster2.AnyUniqueType(), 0)
231        self.assertTrue(monster2.AnyUnique() is None)
232        self.assertEqual(monster2.AnyAmbiguousType(), 0)
233        self.assertTrue(monster2.AnyAmbiguous() is None)
234        self.assertEqual(monster2.VectorOfEnums(0), 0)
235        self.assertEqual(monster2.VectorOfEnumsAsNumpy(), 0)
236        self.assertEqual(monster2.VectorOfEnumsLength(), 0)
237        self.assertTrue(monster2.VectorOfEnumsIsNone())
238
239
240class TestAllMutableCodePathsOfExampleSchema(unittest.TestCase):
241    ''' Tests the object API generated for monster_test.fbs for mutation
242        purposes. In each test, the default values will be changed through the
243        object API. We'll then pack the object class into the buf class and read
244        the updated values out from it to validate if the values are mutated as
245        expected.'''
246
247    def setUp(self, *args, **kwargs):
248        super(TestAllMutableCodePathsOfExampleSchema, self).setUp(*args,
249                                                                  **kwargs)
250        # Creates an empty monster flatbuffer, and loads it into the object
251        # class for future tests.
252        b = flatbuffers.Builder(0)
253        MyGame.Example.Monster.MonsterStart(b)
254        self.monsterT = self._create_and_load_object_class(b)
255
256    def _pack_and_load_buf_class(self, monsterT):
257        ''' Packs the object class into a flatbuffer and loads it into a buf
258        class.'''
259        b = flatbuffers.Builder(0)
260        b.Finish(monsterT.Pack(b))
261        monster = MyGame.Example.Monster.Monster.GetRootAsMonster(b.Bytes,
262                                                                  b.Head())
263        return monster
264
265    def _create_and_load_object_class(self, b):
266        ''' Finishs the creation of a monster flatbuffer and loads it into an
267        object class.'''
268        gen_mon = MyGame.Example.Monster.MonsterEnd(b)
269        b.Finish(gen_mon)
270        monster = MyGame.Example.Monster.Monster.GetRootAsMonster(b.Bytes,
271                                                                  b.Head())
272        monsterT = MyGame.Example.Monster.MonsterT()
273        monsterT.InitFromObj(monster)
274        return monsterT
275
276    def test_mutate_pos(self):
277        posT = MyGame.Example.Vec3.Vec3T()
278        posT.x = 4.0
279        posT.y = 5.0
280        posT.z = 6.0
281        posT.test1 = 6.0
282        posT.test2 = 7
283        test3T = MyGame.Example.Test.TestT()
284        test3T.a = 8
285        test3T.b = 9
286        posT.test3 = test3T
287        self.monsterT.pos = posT
288
289        # Packs the updated values.
290        monster = self._pack_and_load_buf_class(self.monsterT)
291
292        # Checks if values are loaded correctly into the object class.
293        pos = monster.Pos()
294
295        # Verifies the properties of the Vec3.
296        self.assertEqual(pos.X(), 4.0)
297        self.assertEqual(pos.Y(), 5.0)
298        self.assertEqual(pos.Z(), 6.0)
299        self.assertEqual(pos.Test1(), 6.0)
300        self.assertEqual(pos.Test2(), 7)
301        t3 = MyGame.Example.Test.Test()
302        t3 = pos.Test3(t3)
303        self.assertEqual(t3.A(), 8)
304        self.assertEqual(t3.B(), 9)
305
306    def test_mutate_mana(self):
307        self.monsterT.mana = 200
308        monster = self._pack_and_load_buf_class(self.monsterT)
309        self.assertEqual(monster.Mana(), 200)
310
311    def test_mutate_hp(self):
312        self.monsterT.hp = 200
313        monster = self._pack_and_load_buf_class(self.monsterT)
314        self.assertEqual(monster.Hp(), 200)
315
316    def test_mutate_name(self):
317        self.monsterT.name = "MyMonster"
318        monster = self._pack_and_load_buf_class(self.monsterT)
319        self.assertEqual(monster.Name(), b"MyMonster")
320
321    def test_mutate_inventory(self):
322        self.monsterT.inventory = [1, 7, 8]
323        monster = self._pack_and_load_buf_class(self.monsterT)
324        self.assertEqual(monster.Inventory(0), 1)
325        self.assertEqual(monster.Inventory(1), 7)
326        self.assertEqual(monster.Inventory(2), 8)
327
328    def test_empty_inventory(self):
329        self.monsterT.inventory = []
330        monster = self._pack_and_load_buf_class(self.monsterT)
331        self.assertFalse(monster.InventoryIsNone())
332
333    def test_mutate_color(self):
334        self.monsterT.color = MyGame.Example.Color.Color.Red
335        monster = self._pack_and_load_buf_class(self.monsterT)
336        self.assertEqual(monster.Color(), MyGame.Example.Color.Color.Red)
337
338    def test_mutate_testtype(self):
339        self.monsterT.testType = MyGame.Example.Any.Any.Monster
340        monster = self._pack_and_load_buf_class(self.monsterT)
341        self.assertEqual(monster.TestType(), MyGame.Example.Any.Any.Monster)
342
343    def test_mutate_test(self):
344        testT = MyGame.Example.Monster.MonsterT()
345        testT.hp = 200
346        self.monsterT.test = testT
347        monster = self._pack_and_load_buf_class(self.monsterT)
348        # Initializes a Table from a union field Test(...).
349        table = monster.Test()
350
351        # Initializes a Monster from the Table from the union.
352        test_monster = MyGame.Example.Monster.Monster()
353        test_monster.Init(table.Bytes, table.Pos)
354        self.assertEqual(test_monster.Hp(), 200)
355
356    def test_mutate_test4(self):
357        test0T = MyGame.Example.Test.TestT()
358        test0T.a = 10
359        test0T.b = 20
360        test1T = MyGame.Example.Test.TestT()
361        test1T.a = 30
362        test1T.b = 40
363        self.monsterT.test4 = [test0T, test1T]
364
365        monster = self._pack_and_load_buf_class(self.monsterT)
366        test0 = monster.Test4(0)
367        self.assertEqual(test0.A(), 10)
368        self.assertEqual(test0.B(), 20)
369        test1 = monster.Test4(1)
370        self.assertEqual(test1.A(), 30)
371        self.assertEqual(test1.B(), 40)
372
373    def test_empty_test4(self):
374        self.monsterT.test4 = []
375        monster = self._pack_and_load_buf_class(self.monsterT)
376        self.assertFalse(monster.Test4IsNone())
377
378    def test_mutate_testarrayofstring(self):
379        self.monsterT.testarrayofstring = []
380        self.monsterT.testarrayofstring.append("test1")
381        self.monsterT.testarrayofstring.append("test2")
382        monster = self._pack_and_load_buf_class(self.monsterT)
383        self.assertEqual(monster.Testarrayofstring(0), b"test1")
384        self.assertEqual(monster.Testarrayofstring(1), b"test2")
385
386    def test_empty_testarrayofstring(self):
387        self.monsterT.testarrayofstring = []
388        monster = self._pack_and_load_buf_class(self.monsterT)
389        self.assertFalse(monster.TestarrayofstringIsNone())
390
391    def test_mutate_testarrayoftables(self):
392        monsterT0 = MyGame.Example.Monster.MonsterT()
393        monsterT0.hp = 200
394        monsterT1 = MyGame.Example.Monster.MonsterT()
395        monsterT1.hp = 400
396        self.monsterT.testarrayoftables = []
397        self.monsterT.testarrayoftables.append(monsterT0)
398        self.monsterT.testarrayoftables.append(monsterT1)
399        monster = self._pack_and_load_buf_class(self.monsterT)
400        self.assertEqual(monster.Testarrayoftables(0).Hp(), 200)
401        self.assertEqual(monster.Testarrayoftables(1).Hp(), 400)
402
403    def test_empty_testarrayoftables(self):
404        self.monsterT.testarrayoftables = []
405        monster = self._pack_and_load_buf_class(self.monsterT)
406        self.assertFalse(monster.TestarrayoftablesIsNone())
407
408    def test_mutate_enemy(self):
409        monsterT = MyGame.Example.Monster.MonsterT()
410        monsterT.hp = 200
411        self.monsterT.enemy = monsterT
412        monster = self._pack_and_load_buf_class(self.monsterT)
413        self.assertEqual(monster.Enemy().Hp(), 200)
414
415    def test_mutate_testnestedflatbuffer(self):
416        self.monsterT.testnestedflatbuffer = [8, 2, 4]
417        monster = self._pack_and_load_buf_class(self.monsterT)
418        self.assertEqual(monster.Testnestedflatbuffer(0), 8)
419        self.assertEqual(monster.Testnestedflatbuffer(1), 2)
420        self.assertEqual(monster.Testnestedflatbuffer(2), 4)
421
422    def test_empty_testnestedflatbuffer(self):
423        self.monsterT.testnestedflatbuffer = []
424        monster = self._pack_and_load_buf_class(self.monsterT)
425        self.assertFalse(monster.TestnestedflatbufferIsNone())
426
427    def test_mutate_testbool(self):
428        self.monsterT.testbool = True
429        monster = self._pack_and_load_buf_class(self.monsterT)
430        self.assertTrue(monster.Testbool())
431
432    def test_mutate_testhashes(self):
433        self.monsterT.testhashs32Fnv1 = 1
434        self.monsterT.testhashu32Fnv1 = 2
435        self.monsterT.testhashs64Fnv1 = 3
436        self.monsterT.testhashu64Fnv1 = 4
437        self.monsterT.testhashs32Fnv1a = 5
438        self.monsterT.testhashu32Fnv1a = 6
439        self.monsterT.testhashs64Fnv1a = 7
440        self.monsterT.testhashu64Fnv1a = 8
441        monster = self._pack_and_load_buf_class(self.monsterT)
442        self.assertEqual(monster.Testhashs32Fnv1(), 1)
443        self.assertEqual(monster.Testhashu32Fnv1(), 2)
444        self.assertEqual(monster.Testhashs64Fnv1(), 3)
445        self.assertEqual(monster.Testhashu64Fnv1(), 4)
446        self.assertEqual(monster.Testhashs32Fnv1a(), 5)
447        self.assertEqual(monster.Testhashu32Fnv1a(), 6)
448        self.assertEqual(monster.Testhashs64Fnv1a(), 7)
449        self.assertEqual(monster.Testhashu64Fnv1a(), 8)
450
451    def test_mutate_testarrayofbools(self):
452        self.monsterT.testarrayofbools = []
453        self.monsterT.testarrayofbools.append(True)
454        self.monsterT.testarrayofbools.append(True)
455        self.monsterT.testarrayofbools.append(False)
456        monster = self._pack_and_load_buf_class(self.monsterT)
457        self.assertEqual(monster.Testarrayofbools(0), True)
458        self.assertEqual(monster.Testarrayofbools(1), True)
459        self.assertEqual(monster.Testarrayofbools(2), False)
460
461    def test_empty_testarrayofbools(self):
462        self.monsterT.testarrayofbools = []
463        monster = self._pack_and_load_buf_class(self.monsterT)
464        self.assertFalse(monster.TestarrayofboolsIsNone())
465
466    def test_mutate_testf(self):
467        self.monsterT.testf = 2.0
468        monster = self._pack_and_load_buf_class(self.monsterT)
469        self.assertEqual(monster.Testf(), 2.0)
470
471    def test_mutate_vectoroflongs(self):
472        self.monsterT.vectorOfLongs = []
473        self.monsterT.vectorOfLongs.append(1)
474        self.monsterT.vectorOfLongs.append(100)
475        self.monsterT.vectorOfLongs.append(10000)
476        self.monsterT.vectorOfLongs.append(1000000)
477        self.monsterT.vectorOfLongs.append(100000000)
478        monster = self._pack_and_load_buf_class(self.monsterT)
479        self.assertEqual(monster.VectorOfLongs(0), 1)
480        self.assertEqual(monster.VectorOfLongs(1), 100)
481        self.assertEqual(monster.VectorOfLongs(2), 10000)
482        self.assertEqual(monster.VectorOfLongs(3), 1000000)
483        self.assertEqual(monster.VectorOfLongs(4), 100000000)
484
485    def test_empty_vectoroflongs(self):
486        self.monsterT.vectorOfLongs = []
487        monster = self._pack_and_load_buf_class(self.monsterT)
488        self.assertFalse(monster.VectorOfLongsIsNone())
489
490    def test_mutate_vectorofdoubles(self):
491        self.monsterT.vectorOfDoubles = []
492        self.monsterT.vectorOfDoubles.append(-1.7976931348623157e+308)
493        self.monsterT.vectorOfDoubles.append(0)
494        self.monsterT.vectorOfDoubles.append(1.7976931348623157e+308)
495        monster = self._pack_and_load_buf_class(self.monsterT)
496        self.assertEqual(monster.VectorOfDoubles(0), -1.7976931348623157e+308)
497        self.assertEqual(monster.VectorOfDoubles(1), 0)
498        self.assertEqual(monster.VectorOfDoubles(2), 1.7976931348623157e+308)
499
500    def test_empty_vectorofdoubles(self):
501        self.monsterT.vectorOfDoubles = []
502        monster = self._pack_and_load_buf_class(self.monsterT)
503        self.assertFalse(monster.VectorOfDoublesIsNone())
504
505    def test_mutate_parentnamespacetest(self):
506        self.monsterT.parentNamespaceTest = MyGame.InParentNamespace.InParentNamespaceT()
507        monster = self._pack_and_load_buf_class(self.monsterT)
508        self.assertTrue(isinstance(monster.ParentNamespaceTest(),
509                                   MyGame.InParentNamespace.InParentNamespace))
510
511    def test_mutate_vectorofEnums(self):
512        self.monsterT.vectorOfEnums = []
513        self.monsterT.vectorOfEnums.append(MyGame.Example.Color.Color.Red)
514        self.monsterT.vectorOfEnums.append(MyGame.Example.Color.Color.Blue)
515        self.monsterT.vectorOfEnums.append(MyGame.Example.Color.Color.Red)
516        monster = self._pack_and_load_buf_class(self.monsterT)
517        self.assertEqual(monster.VectorOfEnums(0),
518                         MyGame.Example.Color.Color.Red)
519        self.assertEqual(monster.VectorOfEnums(1),
520                         MyGame.Example.Color.Color.Blue)
521        self.assertEqual(monster.VectorOfEnums(2),
522                         MyGame.Example.Color.Color.Red)
523
524    def test_empty_vectorofEnums(self):
525        self.monsterT.vectorOfEnums = []
526        monster = self._pack_and_load_buf_class(self.monsterT)
527        self.assertFalse(monster.VectorOfEnumsIsNone())
528
529
530def CheckReadBuffer(buf, offset, sizePrefix=False, file_identifier=None):
531    ''' CheckReadBuffer checks that the given buffer is evaluated correctly
532        as the example Monster. '''
533
534    def asserter(stmt):
535        ''' An assertion helper that is separated from TestCase classes. '''
536        if not stmt:
537            raise AssertionError('CheckReadBuffer case failed')
538    if file_identifier:
539        # test prior to removal of size_prefix
540        asserter(util.GetBufferIdentifier(buf, offset, size_prefixed=sizePrefix) == file_identifier)
541        asserter(util.BufferHasIdentifier(buf, offset, file_identifier=file_identifier, size_prefixed=sizePrefix))
542        asserter(MyGame.Example.Monster.Monster.MonsterBufferHasIdentifier(buf, offset, size_prefixed=sizePrefix))
543    if sizePrefix:
544        size = util.GetSizePrefix(buf, offset)
545        asserter(size == len(buf[offset:])-4)
546        buf, offset = util.RemoveSizePrefix(buf, offset)
547    if file_identifier:
548        asserter(MyGame.Example.Monster.Monster.MonsterBufferHasIdentifier(buf, offset))
549    else:
550        asserter(not MyGame.Example.Monster.Monster.MonsterBufferHasIdentifier(buf, offset))
551    monster = MyGame.Example.Monster.Monster.GetRootAsMonster(buf, offset)
552
553    asserter(monster.Hp() == 80)
554    asserter(monster.Mana() == 150)
555    asserter(monster.Name() == b'MyMonster')
556
557    # initialize a Vec3 from Pos()
558    vec = monster.Pos()
559    asserter(vec is not None)
560
561    # verify the properties of the Vec3
562    asserter(vec.X() == 1.0)
563    asserter(vec.Y() == 2.0)
564    asserter(vec.Z() == 3.0)
565    asserter(vec.Test1() == 3.0)
566    asserter(vec.Test2() == 2)
567
568    # initialize a Test from Test3(...)
569    t = MyGame.Example.Test.Test()
570    t = vec.Test3(t)
571    asserter(t is not None)
572
573    # verify the properties of the Test
574    asserter(t.A() == 5)
575    asserter(t.B() == 6)
576
577    # verify that the enum code matches the enum declaration:
578    union_type = MyGame.Example.Any.Any
579    asserter(monster.TestType() == union_type.Monster)
580
581    # initialize a Table from a union field Test(...)
582    table2 = monster.Test()
583    asserter(type(table2) is flatbuffers.table.Table)
584
585    # initialize a Monster from the Table from the union
586    monster2 = MyGame.Example.Monster.Monster()
587    monster2.Init(table2.Bytes, table2.Pos)
588
589    asserter(monster2.Name() == b"Fred")
590
591    # iterate through the first monster's inventory:
592    asserter(monster.InventoryLength() == 5)
593    asserter(not monster.InventoryIsNone())
594
595    invsum = 0
596    for i in compat_range(monster.InventoryLength()):
597        v = monster.Inventory(i)
598        invsum += int(v)
599    asserter(invsum == 10)
600
601    for i in range(5):
602        asserter(monster.VectorOfLongs(i) == 10 ** (i * 2))
603
604    asserter(not monster.VectorOfDoublesIsNone())
605    asserter(([-1.7976931348623157e+308, 0, 1.7976931348623157e+308]
606              == [monster.VectorOfDoubles(i)
607                  for i in range(monster.VectorOfDoublesLength())]))
608
609    try:
610        imp.find_module('numpy')
611        # if numpy exists, then we should be able to get the
612        # vector as a numpy array
613        import numpy as np
614
615        asserter(monster.InventoryAsNumpy().sum() == 10)
616        asserter(monster.InventoryAsNumpy().dtype == np.dtype('uint8'))
617
618        VectorOfLongs = monster.VectorOfLongsAsNumpy()
619        asserter(VectorOfLongs.dtype == np.dtype('int64'))
620        for i in range(5):
621            asserter(VectorOfLongs[i] == 10 ** (i * 2))
622
623        VectorOfDoubles = monster.VectorOfDoublesAsNumpy()
624        asserter(VectorOfDoubles.dtype == np.dtype('float64'))
625        asserter(VectorOfDoubles[0] == np.finfo('float64').min)
626        asserter(VectorOfDoubles[1] == 0.0)
627        asserter(VectorOfDoubles[2] == np.finfo('float64').max)
628
629    except ImportError:
630        # If numpy does not exist, trying to get vector as numpy
631        # array should raise NumpyRequiredForThisFeature. The way
632        # assertRaises has been implemented prevents us from
633        # asserting this error is raised outside of a test case.
634        pass
635
636    asserter(monster.Test4Length() == 2)
637    asserter(not monster.Test4IsNone())
638
639    # create a 'Test' object and populate it:
640    test0 = monster.Test4(0)
641    asserter(type(test0) is MyGame.Example.Test.Test)
642
643    test1 = monster.Test4(1)
644    asserter(type(test1) is MyGame.Example.Test.Test)
645
646    # the position of test0 and test1 are swapped in monsterdata_java_wire
647    # and monsterdata_test_wire, so ignore ordering
648    v0 = test0.A()
649    v1 = test0.B()
650    v2 = test1.A()
651    v3 = test1.B()
652    sumtest12 = int(v0) + int(v1) + int(v2) + int(v3)
653
654    asserter(sumtest12 == 100)
655
656    asserter(not monster.TestarrayofstringIsNone())
657    asserter(monster.TestarrayofstringLength() == 2)
658    asserter(monster.Testarrayofstring(0) == b"test1")
659    asserter(monster.Testarrayofstring(1) == b"test2")
660
661    asserter(monster.TestarrayoftablesIsNone())
662    asserter(monster.TestarrayoftablesLength() == 0)
663    asserter(monster.TestnestedflatbufferIsNone())
664    asserter(monster.TestnestedflatbufferLength() == 0)
665    asserter(monster.Testempty() is None)
666
667
668class TestFuzz(unittest.TestCase):
669    ''' Low level stress/fuzz test: serialize/deserialize a variety of
670        different kinds of data in different combinations '''
671
672    binary_type = compat.binary_types[0] # this will always exist
673    ofInt32Bytes = binary_type([0x83, 0x33, 0x33, 0x33])
674    ofInt64Bytes = binary_type([0x84, 0x44, 0x44, 0x44,
675                                0x44, 0x44, 0x44, 0x44])
676    overflowingInt32Val = flatbuffers.encode.Get(flatbuffers.packer.int32,
677                                                 ofInt32Bytes, 0)
678    overflowingInt64Val = flatbuffers.encode.Get(flatbuffers.packer.int64,
679                                                 ofInt64Bytes, 0)
680
681    # Values we're testing against: chosen to ensure no bits get chopped
682    # off anywhere, and also be different from eachother.
683    boolVal = True
684    int8Val = N.Int8Flags.py_type(-127) # 0x81
685    uint8Val = N.Uint8Flags.py_type(0xFF)
686    int16Val = N.Int16Flags.py_type(-32222) # 0x8222
687    uint16Val = N.Uint16Flags.py_type(0xFEEE)
688    int32Val = N.Int32Flags.py_type(overflowingInt32Val)
689    uint32Val = N.Uint32Flags.py_type(0xFDDDDDDD)
690    int64Val = N.Int64Flags.py_type(overflowingInt64Val)
691    uint64Val = N.Uint64Flags.py_type(0xFCCCCCCCCCCCCCCC)
692    # Python uses doubles, so force it here
693    float32Val = N.Float32Flags.py_type(ctypes.c_float(3.14159).value)
694    float64Val = N.Float64Flags.py_type(3.14159265359)
695
696    def test_fuzz(self):
697        return self.check_once(11, 100)
698
699    def check_once(self, fuzzFields, fuzzObjects):
700        testValuesMax = 11 # hardcoded to the number of scalar types
701
702        builder = flatbuffers.Builder(0)
703        l = LCG()
704
705        objects = [0 for _ in compat_range(fuzzObjects)]
706
707        # Generate fuzzObjects random objects each consisting of
708        # fuzzFields fields, each of a random type.
709        for i in compat_range(fuzzObjects):
710            builder.StartObject(fuzzFields)
711
712            for j in compat_range(fuzzFields):
713                choice = int(l.Next()) % testValuesMax
714                if choice == 0:
715                    builder.PrependBoolSlot(int(j), self.boolVal, False)
716                elif choice == 1:
717                    builder.PrependInt8Slot(int(j), self.int8Val, 0)
718                elif choice == 2:
719                    builder.PrependUint8Slot(int(j), self.uint8Val, 0)
720                elif choice == 3:
721                    builder.PrependInt16Slot(int(j), self.int16Val, 0)
722                elif choice == 4:
723                    builder.PrependUint16Slot(int(j), self.uint16Val, 0)
724                elif choice == 5:
725                    builder.PrependInt32Slot(int(j), self.int32Val, 0)
726                elif choice == 6:
727                    builder.PrependUint32Slot(int(j), self.uint32Val, 0)
728                elif choice == 7:
729                    builder.PrependInt64Slot(int(j), self.int64Val, 0)
730                elif choice == 8:
731                    builder.PrependUint64Slot(int(j), self.uint64Val, 0)
732                elif choice == 9:
733                    builder.PrependFloat32Slot(int(j), self.float32Val, 0)
734                elif choice == 10:
735                    builder.PrependFloat64Slot(int(j), self.float64Val, 0)
736                else:
737                    raise RuntimeError('unreachable')
738
739            off = builder.EndObject()
740
741            # store the offset from the end of the builder buffer,
742            # since it will keep growing:
743            objects[i] = off
744
745        # Do some bookkeeping to generate stats on fuzzes:
746        stats = defaultdict(int)
747        def check(table, desc, want, got):
748            stats[desc] += 1
749            self.assertEqual(want, got, "%s != %s, %s" % (want, got, desc))
750
751        l = LCG()  # Reset.
752
753        # Test that all objects we generated are readable and return the
754        # expected values. We generate random objects in the same order
755        # so this is deterministic.
756        for i in compat_range(fuzzObjects):
757
758            table = flatbuffers.table.Table(builder.Bytes,
759                                            len(builder.Bytes) - objects[i])
760
761            for j in compat_range(fuzzFields):
762                field_count = flatbuffers.builder.VtableMetadataFields + j
763                f = N.VOffsetTFlags.py_type(field_count *
764                                            N.VOffsetTFlags.bytewidth)
765                choice = int(l.Next()) % testValuesMax
766
767                if choice == 0:
768                    check(table, "bool", self.boolVal,
769                          table.GetSlot(f, False, N.BoolFlags))
770                elif choice == 1:
771                    check(table, "int8", self.int8Val,
772                          table.GetSlot(f, 0, N.Int8Flags))
773                elif choice == 2:
774                    check(table, "uint8", self.uint8Val,
775                          table.GetSlot(f, 0, N.Uint8Flags))
776                elif choice == 3:
777                    check(table, "int16", self.int16Val,
778                          table.GetSlot(f, 0, N.Int16Flags))
779                elif choice == 4:
780                    check(table, "uint16", self.uint16Val,
781                          table.GetSlot(f, 0, N.Uint16Flags))
782                elif choice == 5:
783                    check(table, "int32", self.int32Val,
784                          table.GetSlot(f, 0, N.Int32Flags))
785                elif choice == 6:
786                    check(table, "uint32", self.uint32Val,
787                          table.GetSlot(f, 0, N.Uint32Flags))
788                elif choice == 7:
789                    check(table, "int64", self.int64Val,
790                          table.GetSlot(f, 0, N.Int64Flags))
791                elif choice == 8:
792                    check(table, "uint64", self.uint64Val,
793                          table.GetSlot(f, 0, N.Uint64Flags))
794                elif choice == 9:
795                    check(table, "float32", self.float32Val,
796                          table.GetSlot(f, 0, N.Float32Flags))
797                elif choice == 10:
798                    check(table, "float64", self.float64Val,
799                          table.GetSlot(f, 0, N.Float64Flags))
800                else:
801                    raise RuntimeError('unreachable')
802
803        # If enough checks were made, verify that all scalar types were used:
804        self.assertEqual(testValuesMax, len(stats),
805                "fuzzing failed to test all scalar types: %s" % stats)
806
807
808class TestByteLayout(unittest.TestCase):
809    ''' TestByteLayout checks the bytes of a Builder in various scenarios. '''
810
811    def assertBuilderEquals(self, builder, want_chars_or_ints):
812        def integerize(x):
813            if isinstance(x, compat.string_types):
814                return ord(x)
815            return x
816
817        want_ints = list(map(integerize, want_chars_or_ints))
818        want = bytearray(want_ints)
819        got = builder.Bytes[builder.Head():] # use the buffer directly
820        self.assertEqual(want, got)
821
822    def test_numbers(self):
823        b = flatbuffers.Builder(0)
824        self.assertBuilderEquals(b, [])
825        b.PrependBool(True)
826        self.assertBuilderEquals(b, [1])
827        b.PrependInt8(-127)
828        self.assertBuilderEquals(b, [129, 1])
829        b.PrependUint8(255)
830        self.assertBuilderEquals(b, [255, 129, 1])
831        b.PrependInt16(-32222)
832        self.assertBuilderEquals(b, [0x22, 0x82, 0, 255, 129, 1]) # first pad
833        b.PrependUint16(0xFEEE)
834        # no pad this time:
835        self.assertBuilderEquals(b, [0xEE, 0xFE, 0x22, 0x82, 0, 255, 129, 1])
836        b.PrependInt32(-53687092)
837        self.assertBuilderEquals(b, [204, 204, 204, 252, 0xEE, 0xFE,
838                                     0x22, 0x82, 0, 255, 129, 1])
839        b.PrependUint32(0x98765432)
840        self.assertBuilderEquals(b, [0x32, 0x54, 0x76, 0x98,
841                                     204, 204, 204, 252,
842                                     0xEE, 0xFE, 0x22, 0x82,
843                                     0, 255, 129, 1])
844
845    def test_numbers64(self):
846        b = flatbuffers.Builder(0)
847        b.PrependUint64(0x1122334455667788)
848        self.assertBuilderEquals(b, [0x88, 0x77, 0x66, 0x55,
849                                     0x44, 0x33, 0x22, 0x11])
850
851        b = flatbuffers.Builder(0)
852        b.PrependInt64(0x1122334455667788)
853        self.assertBuilderEquals(b, [0x88, 0x77, 0x66, 0x55,
854                                     0x44, 0x33, 0x22, 0x11])
855
856    def test_1xbyte_vector(self):
857        b = flatbuffers.Builder(0)
858        self.assertBuilderEquals(b, [])
859        b.StartVector(flatbuffers.number_types.Uint8Flags.bytewidth, 1, 1)
860        self.assertBuilderEquals(b, [0, 0, 0]) # align to 4bytes
861        b.PrependByte(1)
862        self.assertBuilderEquals(b, [1, 0, 0, 0])
863        b.EndVector(1)
864        self.assertBuilderEquals(b, [1, 0, 0, 0, 1, 0, 0, 0]) # padding
865
866    def test_2xbyte_vector(self):
867        b = flatbuffers.Builder(0)
868        b.StartVector(flatbuffers.number_types.Uint8Flags.bytewidth, 2, 1)
869        self.assertBuilderEquals(b, [0, 0]) # align to 4bytes
870        b.PrependByte(1)
871        self.assertBuilderEquals(b, [1, 0, 0])
872        b.PrependByte(2)
873        self.assertBuilderEquals(b, [2, 1, 0, 0])
874        b.EndVector(2)
875        self.assertBuilderEquals(b, [2, 0, 0, 0, 2, 1, 0, 0]) # padding
876
877    def test_1xuint16_vector(self):
878        b = flatbuffers.Builder(0)
879        b.StartVector(flatbuffers.number_types.Uint16Flags.bytewidth, 1, 1)
880        self.assertBuilderEquals(b, [0, 0]) # align to 4bytes
881        b.PrependUint16(1)
882        self.assertBuilderEquals(b, [1, 0, 0, 0])
883        b.EndVector(1)
884        self.assertBuilderEquals(b, [1, 0, 0, 0, 1, 0, 0, 0]) # padding
885
886    def test_2xuint16_vector(self):
887        b = flatbuffers.Builder(0)
888        b.StartVector(flatbuffers.number_types.Uint16Flags.bytewidth, 2, 1)
889        self.assertBuilderEquals(b, []) # align to 4bytes
890        b.PrependUint16(0xABCD)
891        self.assertBuilderEquals(b, [0xCD, 0xAB])
892        b.PrependUint16(0xDCBA)
893        self.assertBuilderEquals(b, [0xBA, 0xDC, 0xCD, 0xAB])
894        b.EndVector(2)
895        self.assertBuilderEquals(b, [2, 0, 0, 0, 0xBA, 0xDC, 0xCD, 0xAB])
896
897    def test_create_ascii_string(self):
898        b = flatbuffers.Builder(0)
899        b.CreateString(u"foo", encoding='ascii')
900
901        # 0-terminated, no pad:
902        self.assertBuilderEquals(b, [3, 0, 0, 0, 'f', 'o', 'o', 0])
903        b.CreateString(u"moop", encoding='ascii')
904        # 0-terminated, 3-byte pad:
905        self.assertBuilderEquals(b, [4, 0, 0, 0, 'm', 'o', 'o', 'p',
906                                     0, 0, 0, 0,
907                                     3, 0, 0, 0, 'f', 'o', 'o', 0])
908
909    def test_create_utf8_string(self):
910        b = flatbuffers.Builder(0)
911        b.CreateString(u"Цлїςσδε")
912        self.assertBuilderEquals(b, "\x0e\x00\x00\x00\xd0\xa6\xd0\xbb\xd1\x97" \
913            "\xcf\x82\xcf\x83\xce\xb4\xce\xb5\x00\x00")
914
915        b.CreateString(u"フムアムカモケモ")
916        self.assertBuilderEquals(b, "\x18\x00\x00\x00\xef\xbe\x8c\xef\xbe\x91" \
917            "\xef\xbd\xb1\xef\xbe\x91\xef\xbd\xb6\xef\xbe\x93\xef\xbd\xb9\xef" \
918            "\xbe\x93\x00\x00\x00\x00\x0e\x00\x00\x00\xd0\xa6\xd0\xbb\xd1\x97" \
919            "\xcf\x82\xcf\x83\xce\xb4\xce\xb5\x00\x00")
920
921    def test_create_arbitrary_string(self):
922        b = flatbuffers.Builder(0)
923        s = "\x01\x02\x03"
924        b.CreateString(s) # Default encoding is utf-8.
925        # 0-terminated, no pad:
926        self.assertBuilderEquals(b, [3, 0, 0, 0, 1, 2, 3, 0])
927        s2 = "\x04\x05\x06\x07"
928        b.CreateString(s2) # Default encoding is utf-8.
929        # 0-terminated, 3-byte pad:
930        self.assertBuilderEquals(b, [4, 0, 0, 0, 4, 5, 6, 7, 0, 0, 0, 0,
931                                     3, 0, 0, 0, 1, 2, 3, 0])
932
933    def test_create_byte_vector(self):
934        b = flatbuffers.Builder(0)
935        b.CreateByteVector(b"")
936        # 0-byte pad:
937        self.assertBuilderEquals(b, [0, 0, 0, 0])
938
939        b = flatbuffers.Builder(0)
940        b.CreateByteVector(b"\x01\x02\x03")
941        # 1-byte pad:
942        self.assertBuilderEquals(b, [3, 0, 0, 0, 1, 2, 3, 0])
943
944    def test_create_numpy_vector_int8(self):
945        try:
946            imp.find_module('numpy')
947            # if numpy exists, then we should be able to get the
948            # vector as a numpy array
949            import numpy as np
950
951            # Systems endian:
952            b = flatbuffers.Builder(0)
953            x = np.array([1, 2, -3], dtype=np.int8)
954            b.CreateNumpyVector(x)
955            self.assertBuilderEquals(b, [
956                3, 0, 0, 0,  # vector length
957                1, 2, 256 - 3, 0   # vector value + padding
958            ])
959
960            # Reverse endian:
961            b = flatbuffers.Builder(0)
962            x_other_endian = x.byteswap().newbyteorder()
963            b.CreateNumpyVector(x_other_endian)
964            self.assertBuilderEquals(b, [
965                3, 0, 0, 0,  # vector length
966                1, 2, 256 - 3, 0   # vector value + padding
967            ])
968        except ImportError:
969            b = flatbuffers.Builder(0)
970            x = 0
971            assertRaises(
972                self,
973                lambda: b.CreateNumpyVector(x),
974                NumpyRequiredForThisFeature)
975
976    def test_create_numpy_vector_uint16(self):
977        try:
978            imp.find_module('numpy')
979            # if numpy exists, then we should be able to get the
980            # vector as a numpy array
981            import numpy as np
982
983            # Systems endian:
984            b = flatbuffers.Builder(0)
985            x = np.array([1, 2, 312], dtype=np.uint16)
986            b.CreateNumpyVector(x)
987            self.assertBuilderEquals(b, [
988                3, 0, 0, 0,     # vector length
989                1, 0,           # 1
990                2, 0,           # 2
991                312 - 256, 1,   # 312
992                0, 0            # padding
993            ])
994
995            # Reverse endian:
996            b = flatbuffers.Builder(0)
997            x_other_endian = x.byteswap().newbyteorder()
998            b.CreateNumpyVector(x_other_endian)
999            self.assertBuilderEquals(b, [
1000                3, 0, 0, 0,     # vector length
1001                1, 0,           # 1
1002                2, 0,           # 2
1003                312 - 256, 1,   # 312
1004                0, 0            # padding
1005            ])
1006        except ImportError:
1007            b = flatbuffers.Builder(0)
1008            x = 0
1009            assertRaises(
1010                self,
1011                lambda: b.CreateNumpyVector(x),
1012                NumpyRequiredForThisFeature)
1013
1014    def test_create_numpy_vector_int64(self):
1015        try:
1016            imp.find_module('numpy')
1017            # if numpy exists, then we should be able to get the
1018            # vector as a numpy array
1019            import numpy as np
1020
1021            # Systems endian:
1022            b = flatbuffers.Builder(0)
1023            x = np.array([1, 2, -12], dtype=np.int64)
1024            b.CreateNumpyVector(x)
1025            self.assertBuilderEquals(b, [
1026                3, 0, 0, 0,                     # vector length
1027                1, 0, 0, 0, 0, 0, 0, 0,         # 1
1028                2, 0, 0, 0, 0, 0, 0, 0,         # 2
1029                256 - 12, 255, 255, 255, 255, 255, 255, 255   # -12
1030            ])
1031
1032            # Reverse endian:
1033            b = flatbuffers.Builder(0)
1034            x_other_endian = x.byteswap().newbyteorder()
1035            b.CreateNumpyVector(x_other_endian)
1036            self.assertBuilderEquals(b, [
1037                3, 0, 0, 0,                     # vector length
1038                1, 0, 0, 0, 0, 0, 0, 0,         # 1
1039                2, 0, 0, 0, 0, 0, 0, 0,         # 2
1040                256 - 12, 255, 255, 255, 255, 255, 255, 255   # -12
1041            ])
1042
1043        except ImportError:
1044            b = flatbuffers.Builder(0)
1045            x = 0
1046            assertRaises(
1047                self,
1048                lambda: b.CreateNumpyVector(x),
1049                NumpyRequiredForThisFeature)
1050
1051    def test_create_numpy_vector_float32(self):
1052        try:
1053            imp.find_module('numpy')
1054            # if numpy exists, then we should be able to get the
1055            # vector as a numpy array
1056            import numpy as np
1057
1058            # Systems endian:
1059            b = flatbuffers.Builder(0)
1060            x = np.array([1, 2, -12], dtype=np.float32)
1061            b.CreateNumpyVector(x)
1062            self.assertBuilderEquals(b, [
1063                3, 0, 0, 0,                     # vector length
1064                0, 0, 128, 63,                  # 1
1065                0, 0, 0, 64,                    # 2
1066                0, 0, 64, 193                   # -12
1067            ])
1068
1069            # Reverse endian:
1070            b = flatbuffers.Builder(0)
1071            x_other_endian = x.byteswap().newbyteorder()
1072            b.CreateNumpyVector(x_other_endian)
1073            self.assertBuilderEquals(b, [
1074                3, 0, 0, 0,                     # vector length
1075                0, 0, 128, 63,                  # 1
1076                0, 0, 0, 64,                    # 2
1077                0, 0, 64, 193                   # -12
1078            ])
1079
1080        except ImportError:
1081            b = flatbuffers.Builder(0)
1082            x = 0
1083            assertRaises(
1084                self,
1085                lambda: b.CreateNumpyVector(x),
1086                NumpyRequiredForThisFeature)
1087
1088    def test_create_numpy_vector_float64(self):
1089        try:
1090            imp.find_module('numpy')
1091            # if numpy exists, then we should be able to get the
1092            # vector as a numpy array
1093            import numpy as np
1094
1095            # Systems endian:
1096            b = flatbuffers.Builder(0)
1097            x = np.array([1, 2, -12], dtype=np.float64)
1098            b.CreateNumpyVector(x)
1099            self.assertBuilderEquals(b, [
1100                3, 0, 0, 0,                     # vector length
1101                0, 0, 0, 0, 0, 0, 240, 63,                  # 1
1102                0, 0, 0, 0, 0, 0, 0, 64,                    # 2
1103                0, 0, 0, 0, 0, 0, 40, 192                   # -12
1104            ])
1105
1106            # Reverse endian:
1107            b = flatbuffers.Builder(0)
1108            x_other_endian = x.byteswap().newbyteorder()
1109            b.CreateNumpyVector(x_other_endian)
1110            self.assertBuilderEquals(b, [
1111                3, 0, 0, 0,                     # vector length
1112                0, 0, 0, 0, 0, 0, 240, 63,                  # 1
1113                0, 0, 0, 0, 0, 0, 0, 64,                    # 2
1114                0, 0, 0, 0, 0, 0, 40, 192                   # -12
1115            ])
1116
1117        except ImportError:
1118            b = flatbuffers.Builder(0)
1119            x = 0
1120            assertRaises(
1121                self,
1122                lambda: b.CreateNumpyVector(x),
1123                NumpyRequiredForThisFeature)
1124
1125    def test_create_numpy_vector_bool(self):
1126        try:
1127            imp.find_module('numpy')
1128            # if numpy exists, then we should be able to get the
1129            # vector as a numpy array
1130            import numpy as np
1131
1132            # Systems endian:
1133            b = flatbuffers.Builder(0)
1134            x = np.array([True, False, True], dtype=np.bool)
1135            b.CreateNumpyVector(x)
1136            self.assertBuilderEquals(b, [
1137                3, 0, 0, 0, # vector length
1138                1, 0, 1, 0  # vector values + padding
1139            ])
1140
1141            # Reverse endian:
1142            b = flatbuffers.Builder(0)
1143            x_other_endian = x.byteswap().newbyteorder()
1144            b.CreateNumpyVector(x_other_endian)
1145            self.assertBuilderEquals(b, [
1146                3, 0, 0, 0, # vector length
1147                1, 0, 1, 0  # vector values + padding
1148            ])
1149
1150        except ImportError:
1151            b = flatbuffers.Builder(0)
1152            x = 0
1153            assertRaises(
1154                self,
1155                lambda: b.CreateNumpyVector(x),
1156                NumpyRequiredForThisFeature)
1157
1158    def test_create_numpy_vector_reject_strings(self):
1159        try:
1160            imp.find_module('numpy')
1161            # if numpy exists, then we should be able to get the
1162            # vector as a numpy array
1163            import numpy as np
1164
1165            # Create String array
1166            b = flatbuffers.Builder(0)
1167            x = np.array(["hello", "fb", "testing"])
1168            assertRaises(
1169                self,
1170                lambda: b.CreateNumpyVector(x),
1171                TypeError)
1172
1173        except ImportError:
1174            b = flatbuffers.Builder(0)
1175            x = 0
1176            assertRaises(
1177                self,
1178                lambda: b.CreateNumpyVector(x),
1179                NumpyRequiredForThisFeature)
1180
1181    def test_create_numpy_vector_reject_object(self):
1182        try:
1183            imp.find_module('numpy')
1184            # if numpy exists, then we should be able to get the
1185            # vector as a numpy array
1186            import numpy as np
1187
1188            # Create String array
1189            b = flatbuffers.Builder(0)
1190            x = np.array([{"m": 0}, {"as": -2.1, 'c': 'c'}])
1191            assertRaises(
1192                self,
1193                lambda: b.CreateNumpyVector(x),
1194                TypeError)
1195
1196        except ImportError:
1197            b = flatbuffers.Builder(0)
1198            x = 0
1199            assertRaises(
1200                self,
1201                lambda: b.CreateNumpyVector(x),
1202                NumpyRequiredForThisFeature)
1203
1204    def test_empty_vtable(self):
1205        b = flatbuffers.Builder(0)
1206        b.StartObject(0)
1207        self.assertBuilderEquals(b, [])
1208        b.EndObject()
1209        self.assertBuilderEquals(b, [4, 0, 4, 0, 4, 0, 0, 0])
1210
1211    def test_vtable_with_one_true_bool(self):
1212        b = flatbuffers.Builder(0)
1213        self.assertBuilderEquals(b, [])
1214        b.StartObject(1)
1215        self.assertBuilderEquals(b, [])
1216        b.PrependBoolSlot(0, True, False)
1217        b.EndObject()
1218        self.assertBuilderEquals(b, [
1219            6, 0,  # vtable bytes
1220            8, 0,  # length of object including vtable offset
1221            7, 0,  # start of bool value
1222            6, 0, 0, 0,  # offset for start of vtable (int32)
1223            0, 0, 0,  # padded to 4 bytes
1224            1,  # bool value
1225        ])
1226
1227    def test_vtable_with_one_default_bool(self):
1228        b = flatbuffers.Builder(0)
1229        self.assertBuilderEquals(b, [])
1230        b.StartObject(1)
1231        self.assertBuilderEquals(b, [])
1232        b.PrependBoolSlot(0, False, False)
1233        b.EndObject()
1234        self.assertBuilderEquals(b, [
1235            4, 0,  # vtable bytes
1236            4, 0,  # end of object from here
1237            # entry 1 is zero and not stored
1238            4, 0, 0, 0,  # offset for start of vtable (int32)
1239        ])
1240
1241    def test_vtable_with_one_int16(self):
1242        b = flatbuffers.Builder(0)
1243        b.StartObject(1)
1244        b.PrependInt16Slot(0, 0x789A, 0)
1245        b.EndObject()
1246        self.assertBuilderEquals(b, [
1247            6, 0,  # vtable bytes
1248            8, 0,  # end of object from here
1249            6, 0,  # offset to value
1250            6, 0, 0, 0,  # offset for start of vtable (int32)
1251            0, 0,  # padding to 4 bytes
1252            0x9A, 0x78,
1253        ])
1254
1255    def test_vtable_with_two_int16(self):
1256        b = flatbuffers.Builder(0)
1257        b.StartObject(2)
1258        b.PrependInt16Slot(0, 0x3456, 0)
1259        b.PrependInt16Slot(1, 0x789A, 0)
1260        b.EndObject()
1261        self.assertBuilderEquals(b, [
1262            8, 0,  # vtable bytes
1263            8, 0,  # end of object from here
1264            6, 0,  # offset to value 0
1265            4, 0,  # offset to value 1
1266            8, 0, 0, 0,  # offset for start of vtable (int32)
1267            0x9A, 0x78,  # value 1
1268            0x56, 0x34,  # value 0
1269        ])
1270
1271    def test_vtable_with_int16_and_bool(self):
1272        b = flatbuffers.Builder(0)
1273        b.StartObject(2)
1274        b.PrependInt16Slot(0, 0x3456, 0)
1275        b.PrependBoolSlot(1, True, False)
1276        b.EndObject()
1277        self.assertBuilderEquals(b, [
1278            8, 0,  # vtable bytes
1279            8, 0,  # end of object from here
1280            6, 0,  # offset to value 0
1281            5, 0,  # offset to value 1
1282            8, 0, 0, 0,  # offset for start of vtable (int32)
1283            0,          # padding
1284            1,          # value 1
1285            0x56, 0x34,  # value 0
1286        ])
1287
1288    def test_vtable_with_empty_vector(self):
1289        b = flatbuffers.Builder(0)
1290        b.StartVector(flatbuffers.number_types.Uint8Flags.bytewidth, 0, 1)
1291        vecend = b.EndVector(0)
1292        b.StartObject(1)
1293        b.PrependUOffsetTRelativeSlot(0, vecend, 0)
1294        b.EndObject()
1295        self.assertBuilderEquals(b, [
1296            6, 0,  # vtable bytes
1297            8, 0,
1298            4, 0,  # offset to vector offset
1299            6, 0, 0, 0,  # offset for start of vtable (int32)
1300            4, 0, 0, 0,
1301            0, 0, 0, 0,  # length of vector (not in struct)
1302        ])
1303
1304    def test_vtable_with_empty_vector_of_byte_and_some_scalars(self):
1305        b = flatbuffers.Builder(0)
1306        b.StartVector(flatbuffers.number_types.Uint8Flags.bytewidth, 0, 1)
1307        vecend = b.EndVector(0)
1308        b.StartObject(2)
1309        b.PrependInt16Slot(0, 55, 0)
1310        b.PrependUOffsetTRelativeSlot(1, vecend, 0)
1311        b.EndObject()
1312        self.assertBuilderEquals(b, [
1313            8, 0,  # vtable bytes
1314            12, 0,
1315            10, 0,  # offset to value 0
1316            4, 0,  # offset to vector offset
1317            8, 0, 0, 0,  # vtable loc
1318            8, 0, 0, 0,  # value 1
1319            0, 0, 55, 0,  # value 0
1320
1321            0, 0, 0, 0,  # length of vector (not in struct)
1322        ])
1323
1324    def test_vtable_with_1_int16_and_2vector_of_int16(self):
1325        b = flatbuffers.Builder(0)
1326        b.StartVector(flatbuffers.number_types.Int16Flags.bytewidth, 2, 1)
1327        b.PrependInt16(0x1234)
1328        b.PrependInt16(0x5678)
1329        vecend = b.EndVector(2)
1330        b.StartObject(2)
1331        b.PrependUOffsetTRelativeSlot(1, vecend, 0)
1332        b.PrependInt16Slot(0, 55, 0)
1333        b.EndObject()
1334        self.assertBuilderEquals(b, [
1335            8, 0,  # vtable bytes
1336            12, 0,  # length of object
1337            6, 0,  # start of value 0 from end of vtable
1338            8, 0,  # start of value 1 from end of buffer
1339            8, 0, 0, 0,  # offset for start of vtable (int32)
1340            0, 0,  # padding
1341            55, 0,  # value 0
1342            4, 0, 0, 0,  # vector position from here
1343            2, 0, 0, 0,  # length of vector (uint32)
1344            0x78, 0x56,  # vector value 1
1345            0x34, 0x12,  # vector value 0
1346        ])
1347
1348    def test_vtable_with_1_struct_of_1_int8__1_int16__1_int32(self):
1349        b = flatbuffers.Builder(0)
1350        b.StartObject(1)
1351        b.Prep(4+4+4, 0)
1352        b.PrependInt8(55)
1353        b.Pad(3)
1354        b.PrependInt16(0x1234)
1355        b.Pad(2)
1356        b.PrependInt32(0x12345678)
1357        structStart = b.Offset()
1358        b.PrependStructSlot(0, structStart, 0)
1359        b.EndObject()
1360        self.assertBuilderEquals(b, [
1361            6, 0,  # vtable bytes
1362            16, 0,  # end of object from here
1363            4, 0,  # start of struct from here
1364            6, 0, 0, 0,  # offset for start of vtable (int32)
1365            0x78, 0x56, 0x34, 0x12,  # value 2
1366            0, 0,  # padding
1367            0x34, 0x12,  # value 1
1368            0, 0, 0,  # padding
1369            55,  # value 0
1370        ])
1371
1372    def test_vtable_with_1_vector_of_2_struct_of_2_int8(self):
1373        b = flatbuffers.Builder(0)
1374        b.StartVector(flatbuffers.number_types.Int8Flags.bytewidth*2, 2, 1)
1375        b.PrependInt8(33)
1376        b.PrependInt8(44)
1377        b.PrependInt8(55)
1378        b.PrependInt8(66)
1379        vecend = b.EndVector(2)
1380        b.StartObject(1)
1381        b.PrependUOffsetTRelativeSlot(0, vecend, 0)
1382        b.EndObject()
1383        self.assertBuilderEquals(b, [
1384            6, 0,  # vtable bytes
1385            8, 0,
1386            4, 0,  # offset of vector offset
1387            6, 0, 0, 0,  # offset for start of vtable (int32)
1388            4, 0, 0, 0,  # vector start offset
1389
1390            2, 0, 0, 0,  # vector length
1391            66,  # vector value 1,1
1392            55,  # vector value 1,0
1393            44,  # vector value 0,1
1394            33,  # vector value 0,0
1395        ])
1396
1397    def test_table_with_some_elements(self):
1398        b = flatbuffers.Builder(0)
1399        b.StartObject(2)
1400        b.PrependInt8Slot(0, 33, 0)
1401        b.PrependInt16Slot(1, 66, 0)
1402        off = b.EndObject()
1403        b.Finish(off)
1404
1405        self.assertBuilderEquals(b, [
1406            12, 0, 0, 0,  # root of table: points to vtable offset
1407
1408            8, 0,  # vtable bytes
1409            8, 0,  # end of object from here
1410            7, 0,  # start of value 0
1411            4, 0,  # start of value 1
1412
1413            8, 0, 0, 0,  # offset for start of vtable (int32)
1414
1415            66, 0,  # value 1
1416            0,  # padding
1417            33,  # value 0
1418        ])
1419
1420    def test__one_unfinished_table_and_one_finished_table(self):
1421        b = flatbuffers.Builder(0)
1422        b.StartObject(2)
1423        b.PrependInt8Slot(0, 33, 0)
1424        b.PrependInt8Slot(1, 44, 0)
1425        off = b.EndObject()
1426        b.Finish(off)
1427
1428        b.StartObject(3)
1429        b.PrependInt8Slot(0, 55, 0)
1430        b.PrependInt8Slot(1, 66, 0)
1431        b.PrependInt8Slot(2, 77, 0)
1432        off = b.EndObject()
1433        b.Finish(off)
1434
1435        self.assertBuilderEquals(b, [
1436            16, 0, 0, 0,  # root of table: points to object
1437            0, 0,  # padding
1438
1439            10, 0,  # vtable bytes
1440            8, 0,  # size of object
1441            7, 0,  # start of value 0
1442            6, 0,  # start of value 1
1443            5, 0,  # start of value 2
1444            10, 0, 0, 0,  # offset for start of vtable (int32)
1445            0,  # padding
1446            77,  # value 2
1447            66,  # value 1
1448            55,  # value 0
1449
1450            12, 0, 0, 0,  # root of table: points to object
1451
1452            8, 0,  # vtable bytes
1453            8, 0,  # size of object
1454            7, 0,  # start of value 0
1455            6, 0,  # start of value 1
1456            8, 0, 0, 0,  # offset for start of vtable (int32)
1457            0, 0,  # padding
1458            44,  # value 1
1459            33,  # value 0
1460        ])
1461
1462    def test_a_bunch_of_bools(self):
1463        b = flatbuffers.Builder(0)
1464        b.StartObject(8)
1465        b.PrependBoolSlot(0, True, False)
1466        b.PrependBoolSlot(1, True, False)
1467        b.PrependBoolSlot(2, True, False)
1468        b.PrependBoolSlot(3, True, False)
1469        b.PrependBoolSlot(4, True, False)
1470        b.PrependBoolSlot(5, True, False)
1471        b.PrependBoolSlot(6, True, False)
1472        b.PrependBoolSlot(7, True, False)
1473        off = b.EndObject()
1474        b.Finish(off)
1475
1476        self.assertBuilderEquals(b, [
1477            24, 0, 0, 0,  # root of table: points to vtable offset
1478
1479            20, 0,  # vtable bytes
1480            12, 0,  # size of object
1481            11, 0,  # start of value 0
1482            10, 0,  # start of value 1
1483            9, 0,  # start of value 2
1484            8, 0,  # start of value 3
1485            7, 0,  # start of value 4
1486            6, 0,  # start of value 5
1487            5, 0,  # start of value 6
1488            4, 0,  # start of value 7
1489            20, 0, 0, 0,  # vtable offset
1490
1491            1,  # value 7
1492            1,  # value 6
1493            1,  # value 5
1494            1,  # value 4
1495            1,  # value 3
1496            1,  # value 2
1497            1,  # value 1
1498            1,  # value 0
1499        ])
1500
1501    def test_three_bools(self):
1502        b = flatbuffers.Builder(0)
1503        b.StartObject(3)
1504        b.PrependBoolSlot(0, True, False)
1505        b.PrependBoolSlot(1, True, False)
1506        b.PrependBoolSlot(2, True, False)
1507        off = b.EndObject()
1508        b.Finish(off)
1509
1510        self.assertBuilderEquals(b, [
1511            16, 0, 0, 0,  # root of table: points to vtable offset
1512
1513            0, 0,  # padding
1514
1515            10, 0,  # vtable bytes
1516            8, 0,  # size of object
1517            7, 0,  # start of value 0
1518            6, 0,  # start of value 1
1519            5, 0,  # start of value 2
1520            10, 0, 0, 0,  # vtable offset from here
1521
1522            0,  # padding
1523            1,  # value 2
1524            1,  # value 1
1525            1,  # value 0
1526        ])
1527
1528    def test_some_floats(self):
1529        b = flatbuffers.Builder(0)
1530        b.StartObject(1)
1531        b.PrependFloat32Slot(0, 1.0, 0.0)
1532        off = b.EndObject()
1533
1534        self.assertBuilderEquals(b, [
1535            6, 0,  # vtable bytes
1536            8, 0,  # size of object
1537            4, 0,  # start of value 0
1538            6, 0, 0, 0,  # vtable offset
1539
1540            0, 0, 128, 63,  # value 0
1541        ])
1542
1543
1544def make_monster_from_generated_code(sizePrefix = False, file_identifier=None):
1545    ''' Use generated code to build the example Monster. '''
1546
1547    b = flatbuffers.Builder(0)
1548    string = b.CreateString("MyMonster")
1549    test1 = b.CreateString("test1")
1550    test2 = b.CreateString("test2")
1551    fred = b.CreateString("Fred")
1552
1553    MyGame.Example.Monster.MonsterStartInventoryVector(b, 5)
1554    b.PrependByte(4)
1555    b.PrependByte(3)
1556    b.PrependByte(2)
1557    b.PrependByte(1)
1558    b.PrependByte(0)
1559    inv = b.EndVector(5)
1560
1561    MyGame.Example.Monster.MonsterStart(b)
1562    MyGame.Example.Monster.MonsterAddName(b, fred)
1563    mon2 = MyGame.Example.Monster.MonsterEnd(b)
1564
1565    MyGame.Example.Monster.MonsterStartTest4Vector(b, 2)
1566    MyGame.Example.Test.CreateTest(b, 10, 20)
1567    MyGame.Example.Test.CreateTest(b, 30, 40)
1568    test4 = b.EndVector(2)
1569
1570    MyGame.Example.Monster.MonsterStartTestarrayofstringVector(b, 2)
1571    b.PrependUOffsetTRelative(test2)
1572    b.PrependUOffsetTRelative(test1)
1573    testArrayOfString = b.EndVector(2)
1574
1575    MyGame.Example.Monster.MonsterStartVectorOfLongsVector(b, 5)
1576    b.PrependInt64(100000000)
1577    b.PrependInt64(1000000)
1578    b.PrependInt64(10000)
1579    b.PrependInt64(100)
1580    b.PrependInt64(1)
1581    VectorOfLongs = b.EndVector(5)
1582
1583    MyGame.Example.Monster.MonsterStartVectorOfDoublesVector(b, 3)
1584    b.PrependFloat64(1.7976931348623157e+308)
1585    b.PrependFloat64(0)
1586    b.PrependFloat64(-1.7976931348623157e+308)
1587    VectorOfDoubles = b.EndVector(3)
1588
1589    MyGame.Example.Monster.MonsterStart(b)
1590
1591    pos = MyGame.Example.Vec3.CreateVec3(b, 1.0, 2.0, 3.0, 3.0, 2, 5, 6)
1592    MyGame.Example.Monster.MonsterAddPos(b, pos)
1593
1594    MyGame.Example.Monster.MonsterAddHp(b, 80)
1595    MyGame.Example.Monster.MonsterAddName(b, string)
1596    MyGame.Example.Monster.MonsterAddInventory(b, inv)
1597    MyGame.Example.Monster.MonsterAddTestType(b, 1)
1598    MyGame.Example.Monster.MonsterAddTest(b, mon2)
1599    MyGame.Example.Monster.MonsterAddTest4(b, test4)
1600    MyGame.Example.Monster.MonsterAddTestarrayofstring(b, testArrayOfString)
1601    MyGame.Example.Monster.MonsterAddVectorOfLongs(b, VectorOfLongs)
1602    MyGame.Example.Monster.MonsterAddVectorOfDoubles(b, VectorOfDoubles)
1603    mon = MyGame.Example.Monster.MonsterEnd(b)
1604
1605    if sizePrefix:
1606        b.FinishSizePrefixed(mon, file_identifier)
1607    else:
1608        b.Finish(mon, file_identifier)
1609
1610    return b.Bytes, b.Head()
1611
1612
1613class TestBuilderForceDefaults(unittest.TestCase):
1614    """Verify that the builder adds default values when forced."""
1615
1616    test_flags = [N.BoolFlags(), N.Uint8Flags(), N.Uint16Flags(), \
1617                  N.Uint32Flags(), N.Uint64Flags(), N.Int8Flags(), \
1618                  N.Int16Flags(), N.Int32Flags(), N.Int64Flags(), \
1619                  N.Float32Flags(), N.Float64Flags(), N.UOffsetTFlags()]
1620    def test_default_force_defaults(self):
1621        for flag in self.test_flags:
1622            b = flatbuffers.Builder(0)
1623            b.StartObject(1)
1624            stored_offset = b.Offset()
1625            if flag != N.UOffsetTFlags():
1626                b.PrependSlot(flag, 0, 0, 0)
1627            else:
1628                b.PrependUOffsetTRelativeSlot(0, 0, 0)
1629            end_offset = b.Offset()
1630            b.EndObject()
1631            self.assertEqual(0, end_offset - stored_offset)
1632
1633    def test_force_defaults_true(self):
1634        for flag in self.test_flags:
1635            b = flatbuffers.Builder(0)
1636            b.ForceDefaults(True)
1637            b.StartObject(1)
1638            stored_offset = b.Offset()
1639            if flag != N.UOffsetTFlags():
1640                b.PrependSlot(flag, 0, 0, 0)
1641            else:
1642                b.PrependUOffsetTRelativeSlot(0, 0, 0)
1643            end_offset = b.Offset()
1644            b.EndObject()
1645            self.assertEqual(flag.bytewidth, end_offset - stored_offset)
1646
1647
1648class TestAllCodePathsOfExampleSchema(unittest.TestCase):
1649    def setUp(self, *args, **kwargs):
1650        super(TestAllCodePathsOfExampleSchema, self).setUp(*args, **kwargs)
1651
1652        b = flatbuffers.Builder(0)
1653        MyGame.Example.Monster.MonsterStart(b)
1654        gen_mon = MyGame.Example.Monster.MonsterEnd(b)
1655        b.Finish(gen_mon)
1656
1657        self.mon = MyGame.Example.Monster.Monster.GetRootAsMonster(b.Bytes,
1658                                                                   b.Head())
1659
1660    def test_default_monster_pos(self):
1661        self.assertTrue(self.mon.Pos() is None)
1662
1663    def test_nondefault_monster_mana(self):
1664        b = flatbuffers.Builder(0)
1665        MyGame.Example.Monster.MonsterStart(b)
1666        MyGame.Example.Monster.MonsterAddMana(b, 50)
1667        mon = MyGame.Example.Monster.MonsterEnd(b)
1668        b.Finish(mon)
1669
1670        got_mon = MyGame.Example.Monster.Monster.GetRootAsMonster(b.Bytes,
1671                                                                  b.Head())
1672        self.assertEqual(50, got_mon.Mana())
1673
1674    def test_default_monster_hp(self):
1675        self.assertEqual(100, self.mon.Hp())
1676
1677    def test_default_monster_name(self):
1678        self.assertEqual(None, self.mon.Name())
1679
1680    def test_default_monster_inventory_item(self):
1681        self.assertEqual(0, self.mon.Inventory(0))
1682
1683    def test_default_monster_inventory_length(self):
1684        self.assertEqual(0, self.mon.InventoryLength())
1685        self.assertTrue(self.mon.InventoryIsNone())
1686
1687    def test_empty_monster_inventory_vector(self):
1688        b = flatbuffers.Builder(0)
1689        MyGame.Example.Monster.MonsterStartInventoryVector(b, 0)
1690        inv = b.EndVector(0)
1691        MyGame.Example.Monster.MonsterStart(b)
1692        MyGame.Example.Monster.MonsterAddInventory(b, inv)
1693        mon = MyGame.Example.Monster.MonsterEnd(b)
1694        b.Finish(mon)
1695        mon2 = MyGame.Example.Monster.Monster.GetRootAsMonster(b.Bytes,
1696                                                               b.Head())
1697        self.assertFalse(mon2.InventoryIsNone())
1698
1699    def test_default_monster_color(self):
1700        self.assertEqual(MyGame.Example.Color.Color.Blue, self.mon.Color())
1701
1702    def test_nondefault_monster_color(self):
1703        b = flatbuffers.Builder(0)
1704        color = MyGame.Example.Color.Color.Red
1705        MyGame.Example.Monster.MonsterStart(b)
1706        MyGame.Example.Monster.MonsterAddColor(b, color)
1707        mon = MyGame.Example.Monster.MonsterEnd(b)
1708        b.Finish(mon)
1709
1710        mon2 = MyGame.Example.Monster.Monster.GetRootAsMonster(b.Bytes,
1711                                                               b.Head())
1712        self.assertEqual(MyGame.Example.Color.Color.Red, mon2.Color())
1713
1714    def test_default_monster_testtype(self):
1715        self.assertEqual(0, self.mon.TestType())
1716
1717    def test_default_monster_test_field(self):
1718        self.assertEqual(None, self.mon.Test())
1719
1720    def test_default_monster_test4_item(self):
1721        self.assertEqual(None, self.mon.Test4(0))
1722
1723    def test_default_monster_test4_length(self):
1724        self.assertEqual(0, self.mon.Test4Length())
1725        self.assertTrue(self.mon.Test4IsNone())
1726
1727    def test_empty_monster_test4_vector(self):
1728        b = flatbuffers.Builder(0)
1729        MyGame.Example.Monster.MonsterStartTest4Vector(b, 0)
1730        test4 = b.EndVector(0)
1731        MyGame.Example.Monster.MonsterStart(b)
1732        MyGame.Example.Monster.MonsterAddTest4(b, test4)
1733        mon = MyGame.Example.Monster.MonsterEnd(b)
1734        b.Finish(mon)
1735        mon2 = MyGame.Example.Monster.Monster.GetRootAsMonster(b.Bytes,
1736                                                               b.Head())
1737        self.assertFalse(mon2.Test4IsNone())
1738
1739    def test_default_monster_testarrayofstring(self):
1740        self.assertEqual("", self.mon.Testarrayofstring(0))
1741
1742    def test_default_monster_testarrayofstring_length(self):
1743        self.assertEqual(0, self.mon.TestarrayofstringLength())
1744        self.assertTrue(self.mon.TestarrayofstringIsNone())
1745
1746    def test_empty_monster_testarrayofstring_vector(self):
1747        b = flatbuffers.Builder(0)
1748        MyGame.Example.Monster.MonsterStartTestarrayofstringVector(b, 0)
1749        testarrayofstring = b.EndVector(0)
1750        MyGame.Example.Monster.MonsterStart(b)
1751        MyGame.Example.Monster.MonsterAddTestarrayofstring(b, testarrayofstring)
1752        mon = MyGame.Example.Monster.MonsterEnd(b)
1753        b.Finish(mon)
1754        mon2 = MyGame.Example.Monster.Monster.GetRootAsMonster(b.Bytes,
1755                                                               b.Head())
1756        self.assertFalse(mon2.TestarrayofstringIsNone())
1757
1758    def test_default_monster_testarrayoftables(self):
1759        self.assertEqual(None, self.mon.Testarrayoftables(0))
1760
1761    def test_nondefault_monster_testarrayoftables(self):
1762        b = flatbuffers.Builder(0)
1763
1764        # make a child Monster within a vector of Monsters:
1765        MyGame.Example.Monster.MonsterStart(b)
1766        MyGame.Example.Monster.MonsterAddHp(b, 99)
1767        sub_monster = MyGame.Example.Monster.MonsterEnd(b)
1768
1769        # build the vector:
1770        MyGame.Example.Monster.MonsterStartTestarrayoftablesVector(b, 1)
1771        b.PrependUOffsetTRelative(sub_monster)
1772        vec = b.EndVector(1)
1773
1774        # make the parent monster and include the vector of Monster:
1775        MyGame.Example.Monster.MonsterStart(b)
1776        MyGame.Example.Monster.MonsterAddTestarrayoftables(b, vec)
1777        mon = MyGame.Example.Monster.MonsterEnd(b)
1778        b.Finish(mon)
1779
1780        # inspect the resulting data:
1781        mon2 = MyGame.Example.Monster.Monster.GetRootAsMonster(b.Output(), 0)
1782        self.assertEqual(99, mon2.Testarrayoftables(0).Hp())
1783        self.assertEqual(1, mon2.TestarrayoftablesLength())
1784        self.assertFalse(mon2.TestarrayoftablesIsNone())
1785
1786    def test_default_monster_testarrayoftables_length(self):
1787        self.assertEqual(0, self.mon.TestarrayoftablesLength())
1788        self.assertTrue(self.mon.TestarrayoftablesIsNone())
1789
1790    def test_empty_monster_testarrayoftables_vector(self):
1791        b = flatbuffers.Builder(0)
1792        MyGame.Example.Monster.MonsterStartTestarrayoftablesVector(b, 0)
1793        testarrayoftables = b.EndVector(0)
1794        MyGame.Example.Monster.MonsterStart(b)
1795        MyGame.Example.Monster.MonsterAddTestarrayoftables(b, testarrayoftables)
1796        mon = MyGame.Example.Monster.MonsterEnd(b)
1797        b.Finish(mon)
1798        mon2 = MyGame.Example.Monster.Monster.GetRootAsMonster(b.Bytes,
1799                                                               b.Head())
1800        self.assertFalse(mon2.TestarrayoftablesIsNone())
1801
1802    def test_default_monster_testarrayoftables_length(self):
1803        self.assertEqual(0, self.mon.TestarrayoftablesLength())
1804
1805    def test_nondefault_monster_enemy(self):
1806        b = flatbuffers.Builder(0)
1807
1808        # make an Enemy object:
1809        MyGame.Example.Monster.MonsterStart(b)
1810        MyGame.Example.Monster.MonsterAddHp(b, 88)
1811        enemy = MyGame.Example.Monster.MonsterEnd(b)
1812        b.Finish(enemy)
1813
1814        # make the parent monster and include the vector of Monster:
1815        MyGame.Example.Monster.MonsterStart(b)
1816        MyGame.Example.Monster.MonsterAddEnemy(b, enemy)
1817        mon = MyGame.Example.Monster.MonsterEnd(b)
1818        b.Finish(mon)
1819
1820        # inspect the resulting data:
1821        mon2 = MyGame.Example.Monster.Monster.GetRootAsMonster(b.Bytes,
1822                                                               b.Head())
1823        self.assertEqual(88, mon2.Enemy().Hp())
1824
1825    def test_default_monster_testnestedflatbuffer(self):
1826        self.assertEqual(0, self.mon.Testnestedflatbuffer(0))
1827
1828    def test_default_monster_testnestedflatbuffer_length(self):
1829        self.assertEqual(0, self.mon.TestnestedflatbufferLength())
1830        self.assertTrue(self.mon.TestnestedflatbufferIsNone())
1831
1832    def test_empty_monster_testnestedflatbuffer_vector(self):
1833        b = flatbuffers.Builder(0)
1834        MyGame.Example.Monster.MonsterStartTestnestedflatbufferVector(b, 0)
1835        testnestedflatbuffer = b.EndVector(0)
1836        MyGame.Example.Monster.MonsterStart(b)
1837        MyGame.Example.Monster.MonsterAddTestnestedflatbuffer(b, testnestedflatbuffer)
1838        mon = MyGame.Example.Monster.MonsterEnd(b)
1839        b.Finish(mon)
1840        mon2 = MyGame.Example.Monster.Monster.GetRootAsMonster(b.Bytes,
1841                                                               b.Head())
1842        self.assertFalse(mon2.TestnestedflatbufferIsNone())
1843
1844    def test_nondefault_monster_testnestedflatbuffer(self):
1845        b = flatbuffers.Builder(0)
1846
1847        MyGame.Example.Monster.MonsterStartTestnestedflatbufferVector(b, 3)
1848        b.PrependByte(4)
1849        b.PrependByte(2)
1850        b.PrependByte(0)
1851        sub_buf = b.EndVector(3)
1852
1853        # make the parent monster and include the vector of Monster:
1854        MyGame.Example.Monster.MonsterStart(b)
1855        MyGame.Example.Monster.MonsterAddTestnestedflatbuffer(b, sub_buf)
1856        mon = MyGame.Example.Monster.MonsterEnd(b)
1857        b.Finish(mon)
1858
1859        # inspect the resulting data:
1860        mon2 = MyGame.Example.Monster.Monster.GetRootAsMonster(b.Bytes,
1861                                                               b.Head())
1862        self.assertEqual(3, mon2.TestnestedflatbufferLength())
1863        self.assertFalse(mon2.TestnestedflatbufferIsNone())
1864        self.assertEqual(0, mon2.Testnestedflatbuffer(0))
1865        self.assertEqual(2, mon2.Testnestedflatbuffer(1))
1866        self.assertEqual(4, mon2.Testnestedflatbuffer(2))
1867        try:
1868            imp.find_module('numpy')
1869            # if numpy exists, then we should be able to get the
1870            # vector as a numpy array
1871            self.assertEqual([0, 2, 4], mon2.TestnestedflatbufferAsNumpy().tolist())
1872        except ImportError:
1873            assertRaises(self,
1874                         lambda: mon2.TestnestedflatbufferAsNumpy(),
1875                         NumpyRequiredForThisFeature)
1876
1877    def test_nondefault_monster_testempty(self):
1878        b = flatbuffers.Builder(0)
1879
1880        # make a Stat object:
1881        MyGame.Example.Stat.StatStart(b)
1882        MyGame.Example.Stat.StatAddVal(b, 123)
1883        my_stat = MyGame.Example.Stat.StatEnd(b)
1884        b.Finish(my_stat)
1885
1886        # include the stat object in a monster:
1887        MyGame.Example.Monster.MonsterStart(b)
1888        MyGame.Example.Monster.MonsterAddTestempty(b, my_stat)
1889        mon = MyGame.Example.Monster.MonsterEnd(b)
1890        b.Finish(mon)
1891
1892        # inspect the resulting data:
1893        mon2 = MyGame.Example.Monster.Monster.GetRootAsMonster(b.Bytes,
1894                                                               b.Head())
1895        self.assertEqual(123, mon2.Testempty().Val())
1896
1897    def test_default_monster_testbool(self):
1898        self.assertFalse(self.mon.Testbool())
1899
1900    def test_nondefault_monster_testbool(self):
1901        b = flatbuffers.Builder(0)
1902        MyGame.Example.Monster.MonsterStart(b)
1903        MyGame.Example.Monster.MonsterAddTestbool(b, True)
1904        mon = MyGame.Example.Monster.MonsterEnd(b)
1905        b.Finish(mon)
1906
1907        # inspect the resulting data:
1908        mon2 = MyGame.Example.Monster.Monster.GetRootAsMonster(b.Bytes,
1909                                                               b.Head())
1910        self.assertTrue(mon2.Testbool())
1911
1912    def test_default_monster_testhashes(self):
1913        self.assertEqual(0, self.mon.Testhashs32Fnv1())
1914        self.assertEqual(0, self.mon.Testhashu32Fnv1())
1915        self.assertEqual(0, self.mon.Testhashs64Fnv1())
1916        self.assertEqual(0, self.mon.Testhashu64Fnv1())
1917        self.assertEqual(0, self.mon.Testhashs32Fnv1a())
1918        self.assertEqual(0, self.mon.Testhashu32Fnv1a())
1919        self.assertEqual(0, self.mon.Testhashs64Fnv1a())
1920        self.assertEqual(0, self.mon.Testhashu64Fnv1a())
1921
1922    def test_nondefault_monster_testhashes(self):
1923        b = flatbuffers.Builder(0)
1924        MyGame.Example.Monster.MonsterStart(b)
1925        MyGame.Example.Monster.MonsterAddTesthashs32Fnv1(b, 1)
1926        MyGame.Example.Monster.MonsterAddTesthashu32Fnv1(b, 2)
1927        MyGame.Example.Monster.MonsterAddTesthashs64Fnv1(b, 3)
1928        MyGame.Example.Monster.MonsterAddTesthashu64Fnv1(b, 4)
1929        MyGame.Example.Monster.MonsterAddTesthashs32Fnv1a(b, 5)
1930        MyGame.Example.Monster.MonsterAddTesthashu32Fnv1a(b, 6)
1931        MyGame.Example.Monster.MonsterAddTesthashs64Fnv1a(b, 7)
1932        MyGame.Example.Monster.MonsterAddTesthashu64Fnv1a(b, 8)
1933        mon = MyGame.Example.Monster.MonsterEnd(b)
1934        b.Finish(mon)
1935
1936        # inspect the resulting data:
1937        mon2 = MyGame.Example.Monster.Monster.GetRootAsMonster(b.Bytes,
1938                                                               b.Head())
1939        self.assertEqual(1, mon2.Testhashs32Fnv1())
1940        self.assertEqual(2, mon2.Testhashu32Fnv1())
1941        self.assertEqual(3, mon2.Testhashs64Fnv1())
1942        self.assertEqual(4, mon2.Testhashu64Fnv1())
1943        self.assertEqual(5, mon2.Testhashs32Fnv1a())
1944        self.assertEqual(6, mon2.Testhashu32Fnv1a())
1945        self.assertEqual(7, mon2.Testhashs64Fnv1a())
1946        self.assertEqual(8, mon2.Testhashu64Fnv1a())
1947
1948    def test_default_monster_parent_namespace_test(self):
1949        self.assertEqual(None, self.mon.ParentNamespaceTest())
1950
1951    def test_nondefault_monster_parent_namespace_test(self):
1952        b = flatbuffers.Builder(0)
1953        MyGame.InParentNamespace.InParentNamespaceStart(b)
1954        parent = MyGame.InParentNamespace.InParentNamespaceEnd(b)
1955        MyGame.Example.Monster.MonsterStart(b)
1956        MyGame.Example.Monster.MonsterAddParentNamespaceTest(b, parent)
1957        mon = MyGame.Example.Monster.MonsterEnd(b)
1958        b.Finish(mon)
1959
1960        # Inspect the resulting data.
1961        monster = MyGame.Example.Monster.Monster.GetRootAsMonster(b.Bytes,
1962                                                                  b.Head())
1963        self.assertTrue(isinstance(monster.ParentNamespaceTest(),
1964                                   MyGame.InParentNamespace.InParentNamespace))
1965
1966    def test_getrootas_for_nonroot_table(self):
1967        b = flatbuffers.Builder(0)
1968        string = b.CreateString("MyStat")
1969
1970        MyGame.Example.Stat.StatStart(b)
1971        MyGame.Example.Stat.StatAddId(b, string)
1972        MyGame.Example.Stat.StatAddVal(b, 12345678)
1973        MyGame.Example.Stat.StatAddCount(b, 12345)
1974        stat = MyGame.Example.Stat.StatEnd(b)
1975        b.Finish(stat)
1976
1977        stat2 = MyGame.Example.Stat.Stat.GetRootAsStat(b.Bytes, b.Head())
1978
1979        self.assertEqual(b"MyStat", stat2.Id())
1980        self.assertEqual(12345678, stat2.Val())
1981        self.assertEqual(12345, stat2.Count())
1982
1983
1984class TestAllCodePathsOfMonsterExtraSchema(unittest.TestCase):
1985    def setUp(self, *args, **kwargs):
1986        super(TestAllCodePathsOfMonsterExtraSchema, self).setUp(*args, **kwargs)
1987
1988        b = flatbuffers.Builder(0)
1989        MyGame.MonsterExtra.MonsterExtraStart(b)
1990        gen_mon = MyGame.MonsterExtra.MonsterExtraEnd(b)
1991        b.Finish(gen_mon)
1992
1993        self.mon = MyGame.MonsterExtra.MonsterExtra.GetRootAsMonsterExtra(b.Bytes, b.Head())
1994
1995    def test_default_nan_inf(self):
1996        self.assertTrue(math.isnan(self.mon.F1()))
1997        self.assertEqual(self.mon.F2(), float("inf"))
1998        self.assertEqual(self.mon.F3(), float("-inf"))
1999
2000        self.assertTrue(math.isnan(self.mon.D1()))
2001        self.assertEqual(self.mon.D2(), float("inf"))
2002        self.assertEqual(self.mon.D3(), float("-inf"))
2003
2004
2005class TestVtableDeduplication(unittest.TestCase):
2006    ''' TestVtableDeduplication verifies that vtables are deduplicated. '''
2007
2008    def test_vtable_deduplication(self):
2009        b = flatbuffers.Builder(0)
2010
2011        b.StartObject(4)
2012        b.PrependByteSlot(0, 0, 0)
2013        b.PrependByteSlot(1, 11, 0)
2014        b.PrependByteSlot(2, 22, 0)
2015        b.PrependInt16Slot(3, 33, 0)
2016        obj0 = b.EndObject()
2017
2018        b.StartObject(4)
2019        b.PrependByteSlot(0, 0, 0)
2020        b.PrependByteSlot(1, 44, 0)
2021        b.PrependByteSlot(2, 55, 0)
2022        b.PrependInt16Slot(3, 66, 0)
2023        obj1 = b.EndObject()
2024
2025        b.StartObject(4)
2026        b.PrependByteSlot(0, 0, 0)
2027        b.PrependByteSlot(1, 77, 0)
2028        b.PrependByteSlot(2, 88, 0)
2029        b.PrependInt16Slot(3, 99, 0)
2030        obj2 = b.EndObject()
2031
2032        got = b.Bytes[b.Head():]
2033
2034        want = bytearray([
2035            240, 255, 255, 255,  # == -12. offset to dedupped vtable.
2036            99, 0,
2037            88,
2038            77,
2039            248, 255, 255, 255,  # == -8. offset to dedupped vtable.
2040            66, 0,
2041            55,
2042            44,
2043            12, 0,
2044            8, 0,
2045            0, 0,
2046            7, 0,
2047            6, 0,
2048            4, 0,
2049            12, 0, 0, 0,
2050            33, 0,
2051            22,
2052            11,
2053        ])
2054
2055        self.assertEqual((len(want), want), (len(got), got))
2056
2057        table0 = flatbuffers.table.Table(b.Bytes, len(b.Bytes) - obj0)
2058        table1 = flatbuffers.table.Table(b.Bytes, len(b.Bytes) - obj1)
2059        table2 = flatbuffers.table.Table(b.Bytes, len(b.Bytes) - obj2)
2060
2061        def _checkTable(tab, voffsett_value, b, c, d):
2062            # vtable size
2063            got = tab.GetVOffsetTSlot(0, 0)
2064            self.assertEqual(12, got, 'case 0, 0')
2065
2066            # object size
2067            got = tab.GetVOffsetTSlot(2, 0)
2068            self.assertEqual(8, got, 'case 2, 0')
2069
2070            # default value
2071            got = tab.GetVOffsetTSlot(4, 0)
2072            self.assertEqual(voffsett_value, got, 'case 4, 0')
2073
2074            got = tab.GetSlot(6, 0, N.Uint8Flags)
2075            self.assertEqual(b, got, 'case 6, 0')
2076
2077            val = tab.GetSlot(8, 0, N.Uint8Flags)
2078            self.assertEqual(c, val, 'failed 8, 0')
2079
2080            got = tab.GetSlot(10, 0, N.Uint8Flags)
2081            self.assertEqual(d, got, 'failed 10, 0')
2082
2083        _checkTable(table0, 0, 11, 22, 33)
2084        _checkTable(table1, 0, 44, 55, 66)
2085        _checkTable(table2, 0, 77, 88, 99)
2086
2087
2088class TestExceptions(unittest.TestCase):
2089    def test_object_is_nested_error(self):
2090        b = flatbuffers.Builder(0)
2091        b.StartObject(0)
2092        assertRaises(self, lambda: b.StartObject(0),
2093                     flatbuffers.builder.IsNestedError)
2094
2095    def test_object_is_not_nested_error(self):
2096        b = flatbuffers.Builder(0)
2097        assertRaises(self, lambda: b.EndObject(),
2098                     flatbuffers.builder.IsNotNestedError)
2099
2100    def test_struct_is_not_inline_error(self):
2101        b = flatbuffers.Builder(0)
2102        b.StartObject(0)
2103        assertRaises(self, lambda: b.PrependStructSlot(0, 1, 0),
2104                     flatbuffers.builder.StructIsNotInlineError)
2105
2106    def test_unreachable_error(self):
2107        b = flatbuffers.Builder(0)
2108        assertRaises(self, lambda: b.PrependUOffsetTRelative(1),
2109                     flatbuffers.builder.OffsetArithmeticError)
2110
2111    def test_create_string_is_nested_error(self):
2112        b = flatbuffers.Builder(0)
2113        b.StartObject(0)
2114        s = 'test1'
2115        assertRaises(self, lambda: b.CreateString(s),
2116                     flatbuffers.builder.IsNestedError)
2117
2118    def test_create_byte_vector_is_nested_error(self):
2119        b = flatbuffers.Builder(0)
2120        b.StartObject(0)
2121        s = b'test1'
2122        assertRaises(self, lambda: b.CreateByteVector(s),
2123                     flatbuffers.builder.IsNestedError)
2124
2125    def test_finished_bytes_error(self):
2126        b = flatbuffers.Builder(0)
2127        assertRaises(self, lambda: b.Output(),
2128                     flatbuffers.builder.BuilderNotFinishedError)
2129
2130
2131class TestFixedLengthArrays(unittest.TestCase):
2132    def test_fixed_length_array(self):
2133        builder = flatbuffers.Builder(0)
2134
2135        a = 0.5
2136        b = range(0, 15)
2137        c = 1
2138        d_a = [[1, 2], [3, 4]]
2139        d_b = [MyGame.Example.TestEnum.TestEnum.B, \
2140                MyGame.Example.TestEnum.TestEnum.C]
2141        d_c = [[MyGame.Example.TestEnum.TestEnum.A, \
2142                MyGame.Example.TestEnum.TestEnum.B], \
2143                [MyGame.Example.TestEnum.TestEnum.C, \
2144                 MyGame.Example.TestEnum.TestEnum.B]]
2145        d_d = [[-1, 1], [-2, 2]]
2146        e = 2
2147        f = [-1, 1]
2148
2149        arrayOffset = MyGame.Example.ArrayStruct.CreateArrayStruct(builder, \
2150            a, b, c, d_a, d_b, d_c, d_d, e, f)
2151
2152        # Create a table with the ArrayStruct.
2153        MyGame.Example.ArrayTable.ArrayTableStart(builder)
2154        MyGame.Example.ArrayTable.ArrayTableAddA(builder, arrayOffset)
2155        tableOffset = MyGame.Example.ArrayTable.ArrayTableEnd(builder)
2156
2157        builder.Finish(tableOffset)
2158
2159        buf = builder.Output()
2160
2161        table = MyGame.Example.ArrayTable.ArrayTable.GetRootAsArrayTable(buf, 0)
2162
2163        # Verify structure.
2164        nested = MyGame.Example.NestedStruct.NestedStruct()
2165        self.assertEqual(table.A().A(), 0.5)
2166        self.assertEqual(table.A().B(), \
2167            [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])
2168        self.assertEqual(table.A().C(), 1)
2169        self.assertEqual(table.A().D(nested, 0).A(), [1, 2])
2170        self.assertEqual(table.A().D(nested, 1).A(), [3, 4])
2171        self.assertEqual(table.A().D(nested, 0).B(), \
2172            MyGame.Example.TestEnum.TestEnum.B)
2173        self.assertEqual(table.A().D(nested, 1).B(), \
2174            MyGame.Example.TestEnum.TestEnum.C)
2175        self.assertEqual(table.A().D(nested, 0).C(), \
2176            [MyGame.Example.TestEnum.TestEnum.A, \
2177             MyGame.Example.TestEnum.TestEnum.B])
2178        self.assertEqual(table.A().D(nested, 1).C(), \
2179            [MyGame.Example.TestEnum.TestEnum.C, \
2180             MyGame.Example.TestEnum.TestEnum.B])
2181        self.assertEqual(table.A().D(nested, 0).D(), [-1, 1])
2182        self.assertEqual(table.A().D(nested, 1).D(), [-2, 2])
2183        self.assertEqual(table.A().E(), 2)
2184        self.assertEqual(table.A().F(), [-1, 1])
2185
2186
2187def CheckAgainstGoldDataGo():
2188    try:
2189        gen_buf, gen_off = make_monster_from_generated_code()
2190        fn = 'monsterdata_go_wire.mon'
2191        if not os.path.exists(fn):
2192            print('Go-generated data does not exist, failed.')
2193            return False
2194
2195        # would like to use a context manager here, but it's less
2196        # backwards-compatible:
2197        f = open(fn, 'rb')
2198        go_wire_data = f.read()
2199        f.close()
2200
2201        CheckReadBuffer(bytearray(go_wire_data), 0)
2202        if not bytearray(gen_buf[gen_off:]) == bytearray(go_wire_data):
2203            raise AssertionError('CheckAgainstGoldDataGo failed')
2204    except:
2205        print('Failed to test against Go-generated test data.')
2206        return False
2207
2208    print('Can read Go-generated test data, and Python generates bytewise identical data.')
2209    return True
2210
2211
2212def CheckAgainstGoldDataJava():
2213    try:
2214        gen_buf, gen_off = make_monster_from_generated_code()
2215        fn = 'monsterdata_java_wire.mon'
2216        if not os.path.exists(fn):
2217            print('Java-generated data does not exist, failed.')
2218            return False
2219        f = open(fn, 'rb')
2220        java_wire_data = f.read()
2221        f.close()
2222
2223        CheckReadBuffer(bytearray(java_wire_data), 0)
2224    except:
2225        print('Failed to read Java-generated test data.')
2226        return False
2227
2228    print('Can read Java-generated test data.')
2229    return True
2230
2231
2232class LCG(object):
2233    ''' Include simple random number generator to ensure results will be the
2234        same cross platform.
2235        http://en.wikipedia.org/wiki/Park%E2%80%93Miller_random_number_generator '''
2236
2237    __slots__ = ['n']
2238
2239    InitialLCGSeed = 48271
2240
2241    def __init__(self):
2242        self.n = self.InitialLCGSeed
2243
2244    def Reset(self):
2245        self.n = self.InitialLCGSeed
2246
2247    def Next(self):
2248        self.n = ((self.n * 279470273) % 4294967291) & 0xFFFFFFFF
2249        return self.n
2250
2251
2252def BenchmarkVtableDeduplication(count):
2253    '''
2254    BenchmarkVtableDeduplication measures the speed of vtable deduplication
2255    by creating `prePop` vtables, then populating `count` objects with a
2256    different single vtable.
2257
2258    When count is large (as in long benchmarks), memory usage may be high.
2259    '''
2260
2261    for prePop in (1, 10, 100, 1000):
2262        builder = flatbuffers.Builder(0)
2263        n = 1 + int(math.log(prePop, 1.5))
2264
2265        # generate some layouts:
2266        layouts = set()
2267        r = list(compat_range(n))
2268        while len(layouts) < prePop:
2269            layouts.add(tuple(sorted(random.sample(r, int(max(1, n / 2))))))
2270
2271        layouts = list(layouts)
2272
2273        # pre-populate vtables:
2274        for layout in layouts:
2275            builder.StartObject(n)
2276            for j in layout:
2277                builder.PrependInt16Slot(j, j, 0)
2278            builder.EndObject()
2279
2280        # benchmark deduplication of a new vtable:
2281        def f():
2282            layout = random.choice(layouts)
2283            builder.StartObject(n)
2284            for j in layout:
2285                builder.PrependInt16Slot(j, j, 0)
2286            builder.EndObject()
2287
2288        duration = timeit.timeit(stmt=f, number=count)
2289        rate = float(count) / duration
2290        print(('vtable deduplication rate (n=%d, vtables=%d): %.2f sec' % (
2291            prePop,
2292            len(builder.vtables),
2293            rate))
2294        )
2295
2296
2297def BenchmarkCheckReadBuffer(count, buf, off):
2298    '''
2299    BenchmarkCheckReadBuffer measures the speed of flatbuffer reading
2300    by re-using the CheckReadBuffer function with the gold data.
2301    '''
2302
2303    def f():
2304        CheckReadBuffer(buf, off)
2305
2306    duration = timeit.timeit(stmt=f, number=count)
2307    rate = float(count) / duration
2308    data = float(len(buf) * count) / float(1024 * 1024)
2309    data_rate = data / float(duration)
2310
2311    print(('traversed %d %d-byte flatbuffers in %.2fsec: %.2f/sec, %.2fMB/sec')
2312          % (count, len(buf), duration, rate, data_rate))
2313
2314
2315def BenchmarkMakeMonsterFromGeneratedCode(count, length):
2316    '''
2317    BenchmarkMakeMonsterFromGeneratedCode measures the speed of flatbuffer
2318    creation by re-using the make_monster_from_generated_code function for
2319    generating gold data examples.
2320    '''
2321
2322    duration = timeit.timeit(stmt=make_monster_from_generated_code,
2323                             number=count)
2324    rate = float(count) / duration
2325    data = float(length * count) / float(1024 * 1024)
2326    data_rate = data / float(duration)
2327
2328    print(('built %d %d-byte flatbuffers in %.2fsec: %.2f/sec, %.2fMB/sec' % \
2329           (count, length, duration, rate, data_rate)))
2330
2331
2332def backward_compatible_run_tests(**kwargs):
2333    if PY_VERSION < (2, 6):
2334        sys.stderr.write("Python version less than 2.6 are not supported")
2335        sys.stderr.flush()
2336        return False
2337
2338    # python2.6 has a reduced-functionality unittest.main function:
2339    if PY_VERSION == (2, 6):
2340        try:
2341            unittest.main(**kwargs)
2342        except SystemExit as e:
2343            if not e.code == 0:
2344                return False
2345        return True
2346
2347    # python2.7 and above let us not exit once unittest.main is run:
2348    kwargs['exit'] = False
2349    kwargs['verbosity'] = 0
2350    ret = unittest.main(**kwargs)
2351    if ret.result.errors or ret.result.failures:
2352        return False
2353
2354    return True
2355
2356def main():
2357    import os
2358    import sys
2359    if not len(sys.argv) == 4:
2360       sys.stderr.write('Usage: %s <benchmark vtable count>'
2361                        '<benchmark read count> <benchmark build count>\n'
2362                        % sys.argv[0])
2363       sys.stderr.write('       Provide COMPARE_GENERATED_TO_GO=1   to check'
2364                        'for bytewise comparison to Go data.\n')
2365       sys.stderr.write('       Provide COMPARE_GENERATED_TO_JAVA=1 to check'
2366                        'for bytewise comparison to Java data.\n')
2367       sys.stderr.flush()
2368       sys.exit(1)
2369
2370    kwargs = dict(argv=sys.argv[:-3])
2371
2372    # show whether numpy is present, as it changes the test logic:
2373    try:
2374        import numpy
2375        print('numpy available')
2376    except ImportError:
2377        print('numpy not available')
2378
2379    # run tests, and run some language comparison checks if needed:
2380    success = backward_compatible_run_tests(**kwargs)
2381    if success and os.environ.get('COMPARE_GENERATED_TO_GO', 0) == "1":
2382        success = success and CheckAgainstGoldDataGo()
2383    if success and os.environ.get('COMPARE_GENERATED_TO_JAVA', 0) == "1":
2384        success = success and CheckAgainstGoldDataJava()
2385
2386    if not success:
2387        sys.stderr.write('Tests failed, skipping benchmarks.\n')
2388        sys.stderr.flush()
2389        sys.exit(1)
2390
2391    # run benchmarks (if 0, they will be a noop):
2392    bench_vtable = int(sys.argv[1])
2393    bench_traverse = int(sys.argv[2])
2394    bench_build = int(sys.argv[3])
2395    if bench_vtable:
2396        BenchmarkVtableDeduplication(bench_vtable)
2397    if bench_traverse:
2398        buf, off = make_monster_from_generated_code()
2399        BenchmarkCheckReadBuffer(bench_traverse, buf, off)
2400    if bench_build:
2401        buf, off = make_monster_from_generated_code()
2402        BenchmarkMakeMonsterFromGeneratedCode(bench_build, len(buf))
2403
2404if __name__ == '__main__':
2405    main()
2406