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 timeit 25import unittest 26 27from flatbuffers import compat 28from flatbuffers import util 29from flatbuffers.compat import range_func as compat_range 30from flatbuffers.compat import NumpyRequiredForThisFeature 31 32import flatbuffers 33from flatbuffers import number_types as N 34 35import MyGame # refers to generated code 36import MyGame.Example # refers to generated code 37import MyGame.Example.Any # refers to generated code 38import MyGame.Example.Color # refers to generated code 39import MyGame.Example.Monster # refers to generated code 40import MyGame.Example.Test # refers to generated code 41import MyGame.Example.Stat # refers to generated code 42import MyGame.Example.Vec3 # refers to generated code 43import MyGame.MonsterExtra # refers to generated code 44 45 46def assertRaises(test_case, fn, exception_class): 47 ''' Backwards-compatible assertion for exceptions raised. ''' 48 49 exc = None 50 try: 51 fn() 52 except Exception as e: 53 exc = e 54 test_case.assertTrue(exc is not None) 55 test_case.assertTrue(isinstance(exc, exception_class)) 56 57 58class TestWireFormat(unittest.TestCase): 59 def test_wire_format(self): 60 # Verify that using the generated Python code builds a buffer without 61 # returning errors, and is interpreted correctly, for size prefixed 62 # representation and regular: 63 for sizePrefix in [True, False]: 64 gen_buf, gen_off = make_monster_from_generated_code(sizePrefix = sizePrefix) 65 CheckReadBuffer(gen_buf, gen_off, sizePrefix = sizePrefix) 66 67 # Verify that the canonical flatbuffer file is readable by the 68 # generated Python code. Note that context managers are not part of 69 # Python 2.5, so we use the simpler open/close methods here: 70 f = open('monsterdata_test.mon', 'rb') 71 canonicalWireData = f.read() 72 f.close() 73 CheckReadBuffer(bytearray(canonicalWireData), 0) 74 75 # Write the generated buffer out to a file: 76 f = open('monsterdata_python_wire.mon', 'wb') 77 f.write(gen_buf[gen_off:]) 78 f.close() 79 80 81def CheckReadBuffer(buf, offset, sizePrefix = False): 82 ''' CheckReadBuffer checks that the given buffer is evaluated correctly 83 as the example Monster. ''' 84 85 def asserter(stmt): 86 ''' An assertion helper that is separated from TestCase classes. ''' 87 if not stmt: 88 raise AssertionError('CheckReadBuffer case failed') 89 90 if sizePrefix: 91 size = util.GetSizePrefix(buf, offset) 92 # taken from the size of monsterdata_python_wire.mon, minus 4 93 asserter(size == 340) 94 buf, offset = util.RemoveSizePrefix(buf, offset) 95 monster = MyGame.Example.Monster.Monster.GetRootAsMonster(buf, offset) 96 97 asserter(monster.Hp() == 80) 98 asserter(monster.Mana() == 150) 99 asserter(monster.Name() == b'MyMonster') 100 101 # initialize a Vec3 from Pos() 102 vec = monster.Pos() 103 asserter(vec is not None) 104 105 # verify the properties of the Vec3 106 asserter(vec.X() == 1.0) 107 asserter(vec.Y() == 2.0) 108 asserter(vec.Z() == 3.0) 109 asserter(vec.Test1() == 3.0) 110 asserter(vec.Test2() == 2) 111 112 # initialize a Test from Test3(...) 113 t = MyGame.Example.Test.Test() 114 t = vec.Test3(t) 115 asserter(t is not None) 116 117 # verify the properties of the Test 118 asserter(t.A() == 5) 119 asserter(t.B() == 6) 120 121 # verify that the enum code matches the enum declaration: 122 union_type = MyGame.Example.Any.Any 123 asserter(monster.TestType() == union_type.Monster) 124 125 # initialize a Table from a union field Test(...) 126 table2 = monster.Test() 127 asserter(type(table2) is flatbuffers.table.Table) 128 129 # initialize a Monster from the Table from the union 130 monster2 = MyGame.Example.Monster.Monster() 131 monster2.Init(table2.Bytes, table2.Pos) 132 133 asserter(monster2.Name() == b"Fred") 134 135 # iterate through the first monster's inventory: 136 asserter(monster.InventoryLength() == 5) 137 138 invsum = 0 139 for i in compat_range(monster.InventoryLength()): 140 v = monster.Inventory(i) 141 invsum += int(v) 142 asserter(invsum == 10) 143 144 for i in range(5): 145 asserter(monster.VectorOfLongs(i) == 10 ** (i * 2)) 146 147 asserter(([-1.7976931348623157e+308, 0, 1.7976931348623157e+308] 148 == [monster.VectorOfDoubles(i) 149 for i in range(monster.VectorOfDoublesLength())])) 150 151 try: 152 imp.find_module('numpy') 153 # if numpy exists, then we should be able to get the 154 # vector as a numpy array 155 import numpy as np 156 157 asserter(monster.InventoryAsNumpy().sum() == 10) 158 asserter(monster.InventoryAsNumpy().dtype == np.dtype('uint8')) 159 160 VectorOfLongs = monster.VectorOfLongsAsNumpy() 161 asserter(VectorOfLongs.dtype == np.dtype('int64')) 162 for i in range(5): 163 asserter(VectorOfLongs[i] == 10 ** (i * 2)) 164 165 VectorOfDoubles = monster.VectorOfDoublesAsNumpy() 166 asserter(VectorOfDoubles.dtype == np.dtype('float64')) 167 asserter(VectorOfDoubles[0] == np.finfo('float64').min) 168 asserter(VectorOfDoubles[1] == 0.0) 169 asserter(VectorOfDoubles[2] == np.finfo('float64').max) 170 171 except ImportError: 172 # If numpy does not exist, trying to get vector as numpy 173 # array should raise NumpyRequiredForThisFeature. The way 174 # assertRaises has been implemented prevents us from 175 # asserting this error is raised outside of a test case. 176 pass 177 178 asserter(monster.Test4Length() == 2) 179 180 # create a 'Test' object and populate it: 181 test0 = monster.Test4(0) 182 asserter(type(test0) is MyGame.Example.Test.Test) 183 184 test1 = monster.Test4(1) 185 asserter(type(test1) is MyGame.Example.Test.Test) 186 187 # the position of test0 and test1 are swapped in monsterdata_java_wire 188 # and monsterdata_test_wire, so ignore ordering 189 v0 = test0.A() 190 v1 = test0.B() 191 v2 = test1.A() 192 v3 = test1.B() 193 sumtest12 = int(v0) + int(v1) + int(v2) + int(v3) 194 195 asserter(sumtest12 == 100) 196 197 asserter(monster.TestarrayofstringLength() == 2) 198 asserter(monster.Testarrayofstring(0) == b"test1") 199 asserter(monster.Testarrayofstring(1) == b"test2") 200 201 asserter(monster.TestarrayoftablesLength() == 0) 202 asserter(monster.TestnestedflatbufferLength() == 0) 203 asserter(monster.Testempty() is None) 204 205 206class TestFuzz(unittest.TestCase): 207 ''' Low level stress/fuzz test: serialize/deserialize a variety of 208 different kinds of data in different combinations ''' 209 210 binary_type = compat.binary_types[0] # this will always exist 211 ofInt32Bytes = binary_type([0x83, 0x33, 0x33, 0x33]) 212 ofInt64Bytes = binary_type([0x84, 0x44, 0x44, 0x44, 213 0x44, 0x44, 0x44, 0x44]) 214 overflowingInt32Val = flatbuffers.encode.Get(flatbuffers.packer.int32, 215 ofInt32Bytes, 0) 216 overflowingInt64Val = flatbuffers.encode.Get(flatbuffers.packer.int64, 217 ofInt64Bytes, 0) 218 219 # Values we're testing against: chosen to ensure no bits get chopped 220 # off anywhere, and also be different from eachother. 221 boolVal = True 222 int8Val = N.Int8Flags.py_type(-127) # 0x81 223 uint8Val = N.Uint8Flags.py_type(0xFF) 224 int16Val = N.Int16Flags.py_type(-32222) # 0x8222 225 uint16Val = N.Uint16Flags.py_type(0xFEEE) 226 int32Val = N.Int32Flags.py_type(overflowingInt32Val) 227 uint32Val = N.Uint32Flags.py_type(0xFDDDDDDD) 228 int64Val = N.Int64Flags.py_type(overflowingInt64Val) 229 uint64Val = N.Uint64Flags.py_type(0xFCCCCCCCCCCCCCCC) 230 # Python uses doubles, so force it here 231 float32Val = N.Float32Flags.py_type(ctypes.c_float(3.14159).value) 232 float64Val = N.Float64Flags.py_type(3.14159265359) 233 234 def test_fuzz(self): 235 return self.check_once(11, 100) 236 237 def check_once(self, fuzzFields, fuzzObjects): 238 testValuesMax = 11 # hardcoded to the number of scalar types 239 240 builder = flatbuffers.Builder(0) 241 l = LCG() 242 243 objects = [0 for _ in compat_range(fuzzObjects)] 244 245 # Generate fuzzObjects random objects each consisting of 246 # fuzzFields fields, each of a random type. 247 for i in compat_range(fuzzObjects): 248 builder.StartObject(fuzzFields) 249 250 for j in compat_range(fuzzFields): 251 choice = int(l.Next()) % testValuesMax 252 if choice == 0: 253 builder.PrependBoolSlot(int(j), self.boolVal, False) 254 elif choice == 1: 255 builder.PrependInt8Slot(int(j), self.int8Val, 0) 256 elif choice == 2: 257 builder.PrependUint8Slot(int(j), self.uint8Val, 0) 258 elif choice == 3: 259 builder.PrependInt16Slot(int(j), self.int16Val, 0) 260 elif choice == 4: 261 builder.PrependUint16Slot(int(j), self.uint16Val, 0) 262 elif choice == 5: 263 builder.PrependInt32Slot(int(j), self.int32Val, 0) 264 elif choice == 6: 265 builder.PrependUint32Slot(int(j), self.uint32Val, 0) 266 elif choice == 7: 267 builder.PrependInt64Slot(int(j), self.int64Val, 0) 268 elif choice == 8: 269 builder.PrependUint64Slot(int(j), self.uint64Val, 0) 270 elif choice == 9: 271 builder.PrependFloat32Slot(int(j), self.float32Val, 0) 272 elif choice == 10: 273 builder.PrependFloat64Slot(int(j), self.float64Val, 0) 274 else: 275 raise RuntimeError('unreachable') 276 277 off = builder.EndObject() 278 279 # store the offset from the end of the builder buffer, 280 # since it will keep growing: 281 objects[i] = off 282 283 # Do some bookkeeping to generate stats on fuzzes: 284 stats = defaultdict(int) 285 def check(table, desc, want, got): 286 stats[desc] += 1 287 self.assertEqual(want, got, "%s != %s, %s" % (want, got, desc)) 288 289 l = LCG() # Reset. 290 291 # Test that all objects we generated are readable and return the 292 # expected values. We generate random objects in the same order 293 # so this is deterministic. 294 for i in compat_range(fuzzObjects): 295 296 table = flatbuffers.table.Table(builder.Bytes, 297 len(builder.Bytes) - objects[i]) 298 299 for j in compat_range(fuzzFields): 300 field_count = flatbuffers.builder.VtableMetadataFields + j 301 f = N.VOffsetTFlags.py_type(field_count * 302 N.VOffsetTFlags.bytewidth) 303 choice = int(l.Next()) % testValuesMax 304 305 if choice == 0: 306 check(table, "bool", self.boolVal, 307 table.GetSlot(f, False, N.BoolFlags)) 308 elif choice == 1: 309 check(table, "int8", self.int8Val, 310 table.GetSlot(f, 0, N.Int8Flags)) 311 elif choice == 2: 312 check(table, "uint8", self.uint8Val, 313 table.GetSlot(f, 0, N.Uint8Flags)) 314 elif choice == 3: 315 check(table, "int16", self.int16Val, 316 table.GetSlot(f, 0, N.Int16Flags)) 317 elif choice == 4: 318 check(table, "uint16", self.uint16Val, 319 table.GetSlot(f, 0, N.Uint16Flags)) 320 elif choice == 5: 321 check(table, "int32", self.int32Val, 322 table.GetSlot(f, 0, N.Int32Flags)) 323 elif choice == 6: 324 check(table, "uint32", self.uint32Val, 325 table.GetSlot(f, 0, N.Uint32Flags)) 326 elif choice == 7: 327 check(table, "int64", self.int64Val, 328 table.GetSlot(f, 0, N.Int64Flags)) 329 elif choice == 8: 330 check(table, "uint64", self.uint64Val, 331 table.GetSlot(f, 0, N.Uint64Flags)) 332 elif choice == 9: 333 check(table, "float32", self.float32Val, 334 table.GetSlot(f, 0, N.Float32Flags)) 335 elif choice == 10: 336 check(table, "float64", self.float64Val, 337 table.GetSlot(f, 0, N.Float64Flags)) 338 else: 339 raise RuntimeError('unreachable') 340 341 # If enough checks were made, verify that all scalar types were used: 342 self.assertEqual(testValuesMax, len(stats), 343 "fuzzing failed to test all scalar types: %s" % stats) 344 345 346class TestByteLayout(unittest.TestCase): 347 ''' TestByteLayout checks the bytes of a Builder in various scenarios. ''' 348 349 def assertBuilderEquals(self, builder, want_chars_or_ints): 350 def integerize(x): 351 if isinstance(x, compat.string_types): 352 return ord(x) 353 return x 354 355 want_ints = list(map(integerize, want_chars_or_ints)) 356 want = bytearray(want_ints) 357 got = builder.Bytes[builder.Head():] # use the buffer directly 358 self.assertEqual(want, got) 359 360 def test_numbers(self): 361 b = flatbuffers.Builder(0) 362 self.assertBuilderEquals(b, []) 363 b.PrependBool(True) 364 self.assertBuilderEquals(b, [1]) 365 b.PrependInt8(-127) 366 self.assertBuilderEquals(b, [129, 1]) 367 b.PrependUint8(255) 368 self.assertBuilderEquals(b, [255, 129, 1]) 369 b.PrependInt16(-32222) 370 self.assertBuilderEquals(b, [0x22, 0x82, 0, 255, 129, 1]) # first pad 371 b.PrependUint16(0xFEEE) 372 # no pad this time: 373 self.assertBuilderEquals(b, [0xEE, 0xFE, 0x22, 0x82, 0, 255, 129, 1]) 374 b.PrependInt32(-53687092) 375 self.assertBuilderEquals(b, [204, 204, 204, 252, 0xEE, 0xFE, 376 0x22, 0x82, 0, 255, 129, 1]) 377 b.PrependUint32(0x98765432) 378 self.assertBuilderEquals(b, [0x32, 0x54, 0x76, 0x98, 379 204, 204, 204, 252, 380 0xEE, 0xFE, 0x22, 0x82, 381 0, 255, 129, 1]) 382 383 def test_numbers64(self): 384 b = flatbuffers.Builder(0) 385 b.PrependUint64(0x1122334455667788) 386 self.assertBuilderEquals(b, [0x88, 0x77, 0x66, 0x55, 387 0x44, 0x33, 0x22, 0x11]) 388 389 b = flatbuffers.Builder(0) 390 b.PrependInt64(0x1122334455667788) 391 self.assertBuilderEquals(b, [0x88, 0x77, 0x66, 0x55, 392 0x44, 0x33, 0x22, 0x11]) 393 394 def test_1xbyte_vector(self): 395 b = flatbuffers.Builder(0) 396 self.assertBuilderEquals(b, []) 397 b.StartVector(flatbuffers.number_types.Uint8Flags.bytewidth, 1, 1) 398 self.assertBuilderEquals(b, [0, 0, 0]) # align to 4bytes 399 b.PrependByte(1) 400 self.assertBuilderEquals(b, [1, 0, 0, 0]) 401 b.EndVector(1) 402 self.assertBuilderEquals(b, [1, 0, 0, 0, 1, 0, 0, 0]) # padding 403 404 def test_2xbyte_vector(self): 405 b = flatbuffers.Builder(0) 406 b.StartVector(flatbuffers.number_types.Uint8Flags.bytewidth, 2, 1) 407 self.assertBuilderEquals(b, [0, 0]) # align to 4bytes 408 b.PrependByte(1) 409 self.assertBuilderEquals(b, [1, 0, 0]) 410 b.PrependByte(2) 411 self.assertBuilderEquals(b, [2, 1, 0, 0]) 412 b.EndVector(2) 413 self.assertBuilderEquals(b, [2, 0, 0, 0, 2, 1, 0, 0]) # padding 414 415 def test_1xuint16_vector(self): 416 b = flatbuffers.Builder(0) 417 b.StartVector(flatbuffers.number_types.Uint16Flags.bytewidth, 1, 1) 418 self.assertBuilderEquals(b, [0, 0]) # align to 4bytes 419 b.PrependUint16(1) 420 self.assertBuilderEquals(b, [1, 0, 0, 0]) 421 b.EndVector(1) 422 self.assertBuilderEquals(b, [1, 0, 0, 0, 1, 0, 0, 0]) # padding 423 424 def test_2xuint16_vector(self): 425 b = flatbuffers.Builder(0) 426 b.StartVector(flatbuffers.number_types.Uint16Flags.bytewidth, 2, 1) 427 self.assertBuilderEquals(b, []) # align to 4bytes 428 b.PrependUint16(0xABCD) 429 self.assertBuilderEquals(b, [0xCD, 0xAB]) 430 b.PrependUint16(0xDCBA) 431 self.assertBuilderEquals(b, [0xBA, 0xDC, 0xCD, 0xAB]) 432 b.EndVector(2) 433 self.assertBuilderEquals(b, [2, 0, 0, 0, 0xBA, 0xDC, 0xCD, 0xAB]) 434 435 def test_create_ascii_string(self): 436 b = flatbuffers.Builder(0) 437 b.CreateString(u"foo", encoding='ascii') 438 439 # 0-terminated, no pad: 440 self.assertBuilderEquals(b, [3, 0, 0, 0, 'f', 'o', 'o', 0]) 441 b.CreateString(u"moop", encoding='ascii') 442 # 0-terminated, 3-byte pad: 443 self.assertBuilderEquals(b, [4, 0, 0, 0, 'm', 'o', 'o', 'p', 444 0, 0, 0, 0, 445 3, 0, 0, 0, 'f', 'o', 'o', 0]) 446 447 def test_create_utf8_string(self): 448 b = flatbuffers.Builder(0) 449 b.CreateString(u"Цлїςσδε") 450 self.assertBuilderEquals(b, "\x0e\x00\x00\x00\xd0\xa6\xd0\xbb\xd1\x97" \ 451 "\xcf\x82\xcf\x83\xce\xb4\xce\xb5\x00\x00") 452 453 b.CreateString(u"フムアムカモケモ") 454 self.assertBuilderEquals(b, "\x18\x00\x00\x00\xef\xbe\x8c\xef\xbe\x91" \ 455 "\xef\xbd\xb1\xef\xbe\x91\xef\xbd\xb6\xef\xbe\x93\xef\xbd\xb9\xef" \ 456 "\xbe\x93\x00\x00\x00\x00\x0e\x00\x00\x00\xd0\xa6\xd0\xbb\xd1\x97" \ 457 "\xcf\x82\xcf\x83\xce\xb4\xce\xb5\x00\x00") 458 459 def test_create_arbitrary_string(self): 460 b = flatbuffers.Builder(0) 461 s = "\x01\x02\x03" 462 b.CreateString(s) # Default encoding is utf-8. 463 # 0-terminated, no pad: 464 self.assertBuilderEquals(b, [3, 0, 0, 0, 1, 2, 3, 0]) 465 s2 = "\x04\x05\x06\x07" 466 b.CreateString(s2) # Default encoding is utf-8. 467 # 0-terminated, 3-byte pad: 468 self.assertBuilderEquals(b, [4, 0, 0, 0, 4, 5, 6, 7, 0, 0, 0, 0, 469 3, 0, 0, 0, 1, 2, 3, 0]) 470 471 def test_create_byte_vector(self): 472 b = flatbuffers.Builder(0) 473 b.CreateByteVector(b"") 474 # 0-byte pad: 475 self.assertBuilderEquals(b, [0, 0, 0, 0]) 476 477 b = flatbuffers.Builder(0) 478 b.CreateByteVector(b"\x01\x02\x03") 479 # 1-byte pad: 480 self.assertBuilderEquals(b, [3, 0, 0, 0, 1, 2, 3, 0]) 481 482 def test_create_numpy_vector_int8(self): 483 try: 484 imp.find_module('numpy') 485 # if numpy exists, then we should be able to get the 486 # vector as a numpy array 487 import numpy as np 488 489 # Systems endian: 490 b = flatbuffers.Builder(0) 491 x = np.array([1, 2, -3], dtype=np.int8) 492 b.CreateNumpyVector(x) 493 self.assertBuilderEquals(b, [ 494 3, 0, 0, 0, # vector length 495 1, 2, 256 - 3, 0 # vector value + padding 496 ]) 497 498 # Reverse endian: 499 b = flatbuffers.Builder(0) 500 x_other_endian = x.byteswap().newbyteorder() 501 b.CreateNumpyVector(x_other_endian) 502 self.assertBuilderEquals(b, [ 503 3, 0, 0, 0, # vector length 504 1, 2, 256 - 3, 0 # vector value + padding 505 ]) 506 except ImportError: 507 b = flatbuffers.Builder(0) 508 x = 0 509 assertRaises( 510 self, 511 lambda: b.CreateNumpyVector(x), 512 NumpyRequiredForThisFeature) 513 514 def test_create_numpy_vector_uint16(self): 515 try: 516 imp.find_module('numpy') 517 # if numpy exists, then we should be able to get the 518 # vector as a numpy array 519 import numpy as np 520 521 # Systems endian: 522 b = flatbuffers.Builder(0) 523 x = np.array([1, 2, 312], dtype=np.uint16) 524 b.CreateNumpyVector(x) 525 self.assertBuilderEquals(b, [ 526 3, 0, 0, 0, # vector length 527 1, 0, # 1 528 2, 0, # 2 529 312 - 256, 1, # 312 530 0, 0 # padding 531 ]) 532 533 # Reverse endian: 534 b = flatbuffers.Builder(0) 535 x_other_endian = x.byteswap().newbyteorder() 536 b.CreateNumpyVector(x_other_endian) 537 self.assertBuilderEquals(b, [ 538 3, 0, 0, 0, # vector length 539 1, 0, # 1 540 2, 0, # 2 541 312 - 256, 1, # 312 542 0, 0 # padding 543 ]) 544 except ImportError: 545 b = flatbuffers.Builder(0) 546 x = 0 547 assertRaises( 548 self, 549 lambda: b.CreateNumpyVector(x), 550 NumpyRequiredForThisFeature) 551 552 def test_create_numpy_vector_int64(self): 553 try: 554 imp.find_module('numpy') 555 # if numpy exists, then we should be able to get the 556 # vector as a numpy array 557 import numpy as np 558 559 # Systems endian: 560 b = flatbuffers.Builder(0) 561 x = np.array([1, 2, -12], dtype=np.int64) 562 b.CreateNumpyVector(x) 563 self.assertBuilderEquals(b, [ 564 3, 0, 0, 0, # vector length 565 1, 0, 0, 0, 0, 0, 0, 0, # 1 566 2, 0, 0, 0, 0, 0, 0, 0, # 2 567 256 - 12, 255, 255, 255, 255, 255, 255, 255 # -12 568 ]) 569 570 # Reverse endian: 571 b = flatbuffers.Builder(0) 572 x_other_endian = x.byteswap().newbyteorder() 573 b.CreateNumpyVector(x_other_endian) 574 self.assertBuilderEquals(b, [ 575 3, 0, 0, 0, # vector length 576 1, 0, 0, 0, 0, 0, 0, 0, # 1 577 2, 0, 0, 0, 0, 0, 0, 0, # 2 578 256 - 12, 255, 255, 255, 255, 255, 255, 255 # -12 579 ]) 580 581 except ImportError: 582 b = flatbuffers.Builder(0) 583 x = 0 584 assertRaises( 585 self, 586 lambda: b.CreateNumpyVector(x), 587 NumpyRequiredForThisFeature) 588 589 def test_create_numpy_vector_float32(self): 590 try: 591 imp.find_module('numpy') 592 # if numpy exists, then we should be able to get the 593 # vector as a numpy array 594 import numpy as np 595 596 # Systems endian: 597 b = flatbuffers.Builder(0) 598 x = np.array([1, 2, -12], dtype=np.float32) 599 b.CreateNumpyVector(x) 600 self.assertBuilderEquals(b, [ 601 3, 0, 0, 0, # vector length 602 0, 0, 128, 63, # 1 603 0, 0, 0, 64, # 2 604 0, 0, 64, 193 # -12 605 ]) 606 607 # Reverse endian: 608 b = flatbuffers.Builder(0) 609 x_other_endian = x.byteswap().newbyteorder() 610 b.CreateNumpyVector(x_other_endian) 611 self.assertBuilderEquals(b, [ 612 3, 0, 0, 0, # vector length 613 0, 0, 128, 63, # 1 614 0, 0, 0, 64, # 2 615 0, 0, 64, 193 # -12 616 ]) 617 618 except ImportError: 619 b = flatbuffers.Builder(0) 620 x = 0 621 assertRaises( 622 self, 623 lambda: b.CreateNumpyVector(x), 624 NumpyRequiredForThisFeature) 625 626 def test_create_numpy_vector_float64(self): 627 try: 628 imp.find_module('numpy') 629 # if numpy exists, then we should be able to get the 630 # vector as a numpy array 631 import numpy as np 632 633 # Systems endian: 634 b = flatbuffers.Builder(0) 635 x = np.array([1, 2, -12], dtype=np.float64) 636 b.CreateNumpyVector(x) 637 self.assertBuilderEquals(b, [ 638 3, 0, 0, 0, # vector length 639 0, 0, 0, 0, 0, 0, 240, 63, # 1 640 0, 0, 0, 0, 0, 0, 0, 64, # 2 641 0, 0, 0, 0, 0, 0, 40, 192 # -12 642 ]) 643 644 # Reverse endian: 645 b = flatbuffers.Builder(0) 646 x_other_endian = x.byteswap().newbyteorder() 647 b.CreateNumpyVector(x_other_endian) 648 self.assertBuilderEquals(b, [ 649 3, 0, 0, 0, # vector length 650 0, 0, 0, 0, 0, 0, 240, 63, # 1 651 0, 0, 0, 0, 0, 0, 0, 64, # 2 652 0, 0, 0, 0, 0, 0, 40, 192 # -12 653 ]) 654 655 except ImportError: 656 b = flatbuffers.Builder(0) 657 x = 0 658 assertRaises( 659 self, 660 lambda: b.CreateNumpyVector(x), 661 NumpyRequiredForThisFeature) 662 663 def test_create_numpy_vector_bool(self): 664 try: 665 imp.find_module('numpy') 666 # if numpy exists, then we should be able to get the 667 # vector as a numpy array 668 import numpy as np 669 670 # Systems endian: 671 b = flatbuffers.Builder(0) 672 x = np.array([True, False, True], dtype=np.bool) 673 b.CreateNumpyVector(x) 674 self.assertBuilderEquals(b, [ 675 3, 0, 0, 0, # vector length 676 1, 0, 1, 0 # vector values + padding 677 ]) 678 679 # Reverse endian: 680 b = flatbuffers.Builder(0) 681 x_other_endian = x.byteswap().newbyteorder() 682 b.CreateNumpyVector(x_other_endian) 683 self.assertBuilderEquals(b, [ 684 3, 0, 0, 0, # vector length 685 1, 0, 1, 0 # vector values + padding 686 ]) 687 688 except ImportError: 689 b = flatbuffers.Builder(0) 690 x = 0 691 assertRaises( 692 self, 693 lambda: b.CreateNumpyVector(x), 694 NumpyRequiredForThisFeature) 695 696 def test_create_numpy_vector_reject_strings(self): 697 try: 698 imp.find_module('numpy') 699 # if numpy exists, then we should be able to get the 700 # vector as a numpy array 701 import numpy as np 702 703 # Create String array 704 b = flatbuffers.Builder(0) 705 x = np.array(["hello", "fb", "testing"]) 706 assertRaises( 707 self, 708 lambda: b.CreateNumpyVector(x), 709 TypeError) 710 711 except ImportError: 712 b = flatbuffers.Builder(0) 713 x = 0 714 assertRaises( 715 self, 716 lambda: b.CreateNumpyVector(x), 717 NumpyRequiredForThisFeature) 718 719 def test_create_numpy_vector_reject_object(self): 720 try: 721 imp.find_module('numpy') 722 # if numpy exists, then we should be able to get the 723 # vector as a numpy array 724 import numpy as np 725 726 # Create String array 727 b = flatbuffers.Builder(0) 728 x = np.array([{"m": 0}, {"as": -2.1, 'c': 'c'}]) 729 assertRaises( 730 self, 731 lambda: b.CreateNumpyVector(x), 732 TypeError) 733 734 except ImportError: 735 b = flatbuffers.Builder(0) 736 x = 0 737 assertRaises( 738 self, 739 lambda: b.CreateNumpyVector(x), 740 NumpyRequiredForThisFeature) 741 742 def test_empty_vtable(self): 743 b = flatbuffers.Builder(0) 744 b.StartObject(0) 745 self.assertBuilderEquals(b, []) 746 b.EndObject() 747 self.assertBuilderEquals(b, [4, 0, 4, 0, 4, 0, 0, 0]) 748 749 def test_vtable_with_one_true_bool(self): 750 b = flatbuffers.Builder(0) 751 self.assertBuilderEquals(b, []) 752 b.StartObject(1) 753 self.assertBuilderEquals(b, []) 754 b.PrependBoolSlot(0, True, False) 755 b.EndObject() 756 self.assertBuilderEquals(b, [ 757 6, 0, # vtable bytes 758 8, 0, # length of object including vtable offset 759 7, 0, # start of bool value 760 6, 0, 0, 0, # offset for start of vtable (int32) 761 0, 0, 0, # padded to 4 bytes 762 1, # bool value 763 ]) 764 765 def test_vtable_with_one_default_bool(self): 766 b = flatbuffers.Builder(0) 767 self.assertBuilderEquals(b, []) 768 b.StartObject(1) 769 self.assertBuilderEquals(b, []) 770 b.PrependBoolSlot(0, False, False) 771 b.EndObject() 772 self.assertBuilderEquals(b, [ 773 4, 0, # vtable bytes 774 4, 0, # end of object from here 775 # entry 1 is zero and not stored 776 4, 0, 0, 0, # offset for start of vtable (int32) 777 ]) 778 779 def test_vtable_with_one_int16(self): 780 b = flatbuffers.Builder(0) 781 b.StartObject(1) 782 b.PrependInt16Slot(0, 0x789A, 0) 783 b.EndObject() 784 self.assertBuilderEquals(b, [ 785 6, 0, # vtable bytes 786 8, 0, # end of object from here 787 6, 0, # offset to value 788 6, 0, 0, 0, # offset for start of vtable (int32) 789 0, 0, # padding to 4 bytes 790 0x9A, 0x78, 791 ]) 792 793 def test_vtable_with_two_int16(self): 794 b = flatbuffers.Builder(0) 795 b.StartObject(2) 796 b.PrependInt16Slot(0, 0x3456, 0) 797 b.PrependInt16Slot(1, 0x789A, 0) 798 b.EndObject() 799 self.assertBuilderEquals(b, [ 800 8, 0, # vtable bytes 801 8, 0, # end of object from here 802 6, 0, # offset to value 0 803 4, 0, # offset to value 1 804 8, 0, 0, 0, # offset for start of vtable (int32) 805 0x9A, 0x78, # value 1 806 0x56, 0x34, # value 0 807 ]) 808 809 def test_vtable_with_int16_and_bool(self): 810 b = flatbuffers.Builder(0) 811 b.StartObject(2) 812 b.PrependInt16Slot(0, 0x3456, 0) 813 b.PrependBoolSlot(1, True, False) 814 b.EndObject() 815 self.assertBuilderEquals(b, [ 816 8, 0, # vtable bytes 817 8, 0, # end of object from here 818 6, 0, # offset to value 0 819 5, 0, # offset to value 1 820 8, 0, 0, 0, # offset for start of vtable (int32) 821 0, # padding 822 1, # value 1 823 0x56, 0x34, # value 0 824 ]) 825 826 def test_vtable_with_empty_vector(self): 827 b = flatbuffers.Builder(0) 828 b.StartVector(flatbuffers.number_types.Uint8Flags.bytewidth, 0, 1) 829 vecend = b.EndVector(0) 830 b.StartObject(1) 831 b.PrependUOffsetTRelativeSlot(0, vecend, 0) 832 b.EndObject() 833 self.assertBuilderEquals(b, [ 834 6, 0, # vtable bytes 835 8, 0, 836 4, 0, # offset to vector offset 837 6, 0, 0, 0, # offset for start of vtable (int32) 838 4, 0, 0, 0, 839 0, 0, 0, 0, # length of vector (not in struct) 840 ]) 841 842 def test_vtable_with_empty_vector_of_byte_and_some_scalars(self): 843 b = flatbuffers.Builder(0) 844 b.StartVector(flatbuffers.number_types.Uint8Flags.bytewidth, 0, 1) 845 vecend = b.EndVector(0) 846 b.StartObject(2) 847 b.PrependInt16Slot(0, 55, 0) 848 b.PrependUOffsetTRelativeSlot(1, vecend, 0) 849 b.EndObject() 850 self.assertBuilderEquals(b, [ 851 8, 0, # vtable bytes 852 12, 0, 853 10, 0, # offset to value 0 854 4, 0, # offset to vector offset 855 8, 0, 0, 0, # vtable loc 856 8, 0, 0, 0, # value 1 857 0, 0, 55, 0, # value 0 858 859 0, 0, 0, 0, # length of vector (not in struct) 860 ]) 861 862 def test_vtable_with_1_int16_and_2vector_of_int16(self): 863 b = flatbuffers.Builder(0) 864 b.StartVector(flatbuffers.number_types.Int16Flags.bytewidth, 2, 1) 865 b.PrependInt16(0x1234) 866 b.PrependInt16(0x5678) 867 vecend = b.EndVector(2) 868 b.StartObject(2) 869 b.PrependUOffsetTRelativeSlot(1, vecend, 0) 870 b.PrependInt16Slot(0, 55, 0) 871 b.EndObject() 872 self.assertBuilderEquals(b, [ 873 8, 0, # vtable bytes 874 12, 0, # length of object 875 6, 0, # start of value 0 from end of vtable 876 8, 0, # start of value 1 from end of buffer 877 8, 0, 0, 0, # offset for start of vtable (int32) 878 0, 0, # padding 879 55, 0, # value 0 880 4, 0, 0, 0, # vector position from here 881 2, 0, 0, 0, # length of vector (uint32) 882 0x78, 0x56, # vector value 1 883 0x34, 0x12, # vector value 0 884 ]) 885 886 def test_vtable_with_1_struct_of_1_int8__1_int16__1_int32(self): 887 b = flatbuffers.Builder(0) 888 b.StartObject(1) 889 b.Prep(4+4+4, 0) 890 b.PrependInt8(55) 891 b.Pad(3) 892 b.PrependInt16(0x1234) 893 b.Pad(2) 894 b.PrependInt32(0x12345678) 895 structStart = b.Offset() 896 b.PrependStructSlot(0, structStart, 0) 897 b.EndObject() 898 self.assertBuilderEquals(b, [ 899 6, 0, # vtable bytes 900 16, 0, # end of object from here 901 4, 0, # start of struct from here 902 6, 0, 0, 0, # offset for start of vtable (int32) 903 0x78, 0x56, 0x34, 0x12, # value 2 904 0, 0, # padding 905 0x34, 0x12, # value 1 906 0, 0, 0, # padding 907 55, # value 0 908 ]) 909 910 def test_vtable_with_1_vector_of_2_struct_of_2_int8(self): 911 b = flatbuffers.Builder(0) 912 b.StartVector(flatbuffers.number_types.Int8Flags.bytewidth*2, 2, 1) 913 b.PrependInt8(33) 914 b.PrependInt8(44) 915 b.PrependInt8(55) 916 b.PrependInt8(66) 917 vecend = b.EndVector(2) 918 b.StartObject(1) 919 b.PrependUOffsetTRelativeSlot(0, vecend, 0) 920 b.EndObject() 921 self.assertBuilderEquals(b, [ 922 6, 0, # vtable bytes 923 8, 0, 924 4, 0, # offset of vector offset 925 6, 0, 0, 0, # offset for start of vtable (int32) 926 4, 0, 0, 0, # vector start offset 927 928 2, 0, 0, 0, # vector length 929 66, # vector value 1,1 930 55, # vector value 1,0 931 44, # vector value 0,1 932 33, # vector value 0,0 933 ]) 934 935 def test_table_with_some_elements(self): 936 b = flatbuffers.Builder(0) 937 b.StartObject(2) 938 b.PrependInt8Slot(0, 33, 0) 939 b.PrependInt16Slot(1, 66, 0) 940 off = b.EndObject() 941 b.Finish(off) 942 943 self.assertBuilderEquals(b, [ 944 12, 0, 0, 0, # root of table: points to vtable offset 945 946 8, 0, # vtable bytes 947 8, 0, # end of object from here 948 7, 0, # start of value 0 949 4, 0, # start of value 1 950 951 8, 0, 0, 0, # offset for start of vtable (int32) 952 953 66, 0, # value 1 954 0, # padding 955 33, # value 0 956 ]) 957 958 def test__one_unfinished_table_and_one_finished_table(self): 959 b = flatbuffers.Builder(0) 960 b.StartObject(2) 961 b.PrependInt8Slot(0, 33, 0) 962 b.PrependInt8Slot(1, 44, 0) 963 off = b.EndObject() 964 b.Finish(off) 965 966 b.StartObject(3) 967 b.PrependInt8Slot(0, 55, 0) 968 b.PrependInt8Slot(1, 66, 0) 969 b.PrependInt8Slot(2, 77, 0) 970 off = b.EndObject() 971 b.Finish(off) 972 973 self.assertBuilderEquals(b, [ 974 16, 0, 0, 0, # root of table: points to object 975 0, 0, # padding 976 977 10, 0, # vtable bytes 978 8, 0, # size of object 979 7, 0, # start of value 0 980 6, 0, # start of value 1 981 5, 0, # start of value 2 982 10, 0, 0, 0, # offset for start of vtable (int32) 983 0, # padding 984 77, # value 2 985 66, # value 1 986 55, # value 0 987 988 12, 0, 0, 0, # root of table: points to object 989 990 8, 0, # vtable bytes 991 8, 0, # size of object 992 7, 0, # start of value 0 993 6, 0, # start of value 1 994 8, 0, 0, 0, # offset for start of vtable (int32) 995 0, 0, # padding 996 44, # value 1 997 33, # value 0 998 ]) 999 1000 def test_a_bunch_of_bools(self): 1001 b = flatbuffers.Builder(0) 1002 b.StartObject(8) 1003 b.PrependBoolSlot(0, True, False) 1004 b.PrependBoolSlot(1, True, False) 1005 b.PrependBoolSlot(2, True, False) 1006 b.PrependBoolSlot(3, True, False) 1007 b.PrependBoolSlot(4, True, False) 1008 b.PrependBoolSlot(5, True, False) 1009 b.PrependBoolSlot(6, True, False) 1010 b.PrependBoolSlot(7, True, False) 1011 off = b.EndObject() 1012 b.Finish(off) 1013 1014 self.assertBuilderEquals(b, [ 1015 24, 0, 0, 0, # root of table: points to vtable offset 1016 1017 20, 0, # vtable bytes 1018 12, 0, # size of object 1019 11, 0, # start of value 0 1020 10, 0, # start of value 1 1021 9, 0, # start of value 2 1022 8, 0, # start of value 3 1023 7, 0, # start of value 4 1024 6, 0, # start of value 5 1025 5, 0, # start of value 6 1026 4, 0, # start of value 7 1027 20, 0, 0, 0, # vtable offset 1028 1029 1, # value 7 1030 1, # value 6 1031 1, # value 5 1032 1, # value 4 1033 1, # value 3 1034 1, # value 2 1035 1, # value 1 1036 1, # value 0 1037 ]) 1038 1039 def test_three_bools(self): 1040 b = flatbuffers.Builder(0) 1041 b.StartObject(3) 1042 b.PrependBoolSlot(0, True, False) 1043 b.PrependBoolSlot(1, True, False) 1044 b.PrependBoolSlot(2, True, False) 1045 off = b.EndObject() 1046 b.Finish(off) 1047 1048 self.assertBuilderEquals(b, [ 1049 16, 0, 0, 0, # root of table: points to vtable offset 1050 1051 0, 0, # padding 1052 1053 10, 0, # vtable bytes 1054 8, 0, # size of object 1055 7, 0, # start of value 0 1056 6, 0, # start of value 1 1057 5, 0, # start of value 2 1058 10, 0, 0, 0, # vtable offset from here 1059 1060 0, # padding 1061 1, # value 2 1062 1, # value 1 1063 1, # value 0 1064 ]) 1065 1066 def test_some_floats(self): 1067 b = flatbuffers.Builder(0) 1068 b.StartObject(1) 1069 b.PrependFloat32Slot(0, 1.0, 0.0) 1070 off = b.EndObject() 1071 1072 self.assertBuilderEquals(b, [ 1073 6, 0, # vtable bytes 1074 8, 0, # size of object 1075 4, 0, # start of value 0 1076 6, 0, 0, 0, # vtable offset 1077 1078 0, 0, 128, 63, # value 0 1079 ]) 1080 1081 1082def make_monster_from_generated_code(sizePrefix = False): 1083 ''' Use generated code to build the example Monster. ''' 1084 1085 b = flatbuffers.Builder(0) 1086 string = b.CreateString("MyMonster") 1087 test1 = b.CreateString("test1") 1088 test2 = b.CreateString("test2") 1089 fred = b.CreateString("Fred") 1090 1091 MyGame.Example.Monster.MonsterStartInventoryVector(b, 5) 1092 b.PrependByte(4) 1093 b.PrependByte(3) 1094 b.PrependByte(2) 1095 b.PrependByte(1) 1096 b.PrependByte(0) 1097 inv = b.EndVector(5) 1098 1099 MyGame.Example.Monster.MonsterStart(b) 1100 MyGame.Example.Monster.MonsterAddName(b, fred) 1101 mon2 = MyGame.Example.Monster.MonsterEnd(b) 1102 1103 MyGame.Example.Monster.MonsterStartTest4Vector(b, 2) 1104 MyGame.Example.Test.CreateTest(b, 10, 20) 1105 MyGame.Example.Test.CreateTest(b, 30, 40) 1106 test4 = b.EndVector(2) 1107 1108 MyGame.Example.Monster.MonsterStartTestarrayofstringVector(b, 2) 1109 b.PrependUOffsetTRelative(test2) 1110 b.PrependUOffsetTRelative(test1) 1111 testArrayOfString = b.EndVector(2) 1112 1113 MyGame.Example.Monster.MonsterStartVectorOfLongsVector(b, 5) 1114 b.PrependInt64(100000000) 1115 b.PrependInt64(1000000) 1116 b.PrependInt64(10000) 1117 b.PrependInt64(100) 1118 b.PrependInt64(1) 1119 VectorOfLongs = b.EndVector(5) 1120 1121 MyGame.Example.Monster.MonsterStartVectorOfDoublesVector(b, 3) 1122 b.PrependFloat64(1.7976931348623157e+308) 1123 b.PrependFloat64(0) 1124 b.PrependFloat64(-1.7976931348623157e+308) 1125 VectorOfDoubles = b.EndVector(3) 1126 1127 MyGame.Example.Monster.MonsterStart(b) 1128 1129 pos = MyGame.Example.Vec3.CreateVec3(b, 1.0, 2.0, 3.0, 3.0, 2, 5, 6) 1130 MyGame.Example.Monster.MonsterAddPos(b, pos) 1131 1132 MyGame.Example.Monster.MonsterAddHp(b, 80) 1133 MyGame.Example.Monster.MonsterAddName(b, string) 1134 MyGame.Example.Monster.MonsterAddInventory(b, inv) 1135 MyGame.Example.Monster.MonsterAddTestType(b, 1) 1136 MyGame.Example.Monster.MonsterAddTest(b, mon2) 1137 MyGame.Example.Monster.MonsterAddTest4(b, test4) 1138 MyGame.Example.Monster.MonsterAddTestarrayofstring(b, testArrayOfString) 1139 MyGame.Example.Monster.MonsterAddVectorOfLongs(b, VectorOfLongs) 1140 MyGame.Example.Monster.MonsterAddVectorOfDoubles(b, VectorOfDoubles) 1141 mon = MyGame.Example.Monster.MonsterEnd(b) 1142 1143 if sizePrefix: 1144 b.FinishSizePrefixed(mon) 1145 else: 1146 b.Finish(mon) 1147 1148 return b.Bytes, b.Head() 1149 1150 1151class TestAllCodePathsOfExampleSchema(unittest.TestCase): 1152 def setUp(self, *args, **kwargs): 1153 super(TestAllCodePathsOfExampleSchema, self).setUp(*args, **kwargs) 1154 1155 b = flatbuffers.Builder(0) 1156 MyGame.Example.Monster.MonsterStart(b) 1157 gen_mon = MyGame.Example.Monster.MonsterEnd(b) 1158 b.Finish(gen_mon) 1159 1160 self.mon = MyGame.Example.Monster.Monster.GetRootAsMonster(b.Bytes, 1161 b.Head()) 1162 1163 def test_default_monster_pos(self): 1164 self.assertTrue(self.mon.Pos() is None) 1165 1166 def test_nondefault_monster_mana(self): 1167 b = flatbuffers.Builder(0) 1168 MyGame.Example.Monster.MonsterStart(b) 1169 MyGame.Example.Monster.MonsterAddMana(b, 50) 1170 mon = MyGame.Example.Monster.MonsterEnd(b) 1171 b.Finish(mon) 1172 1173 got_mon = MyGame.Example.Monster.Monster.GetRootAsMonster(b.Bytes, 1174 b.Head()) 1175 self.assertEqual(50, got_mon.Mana()) 1176 1177 def test_default_monster_hp(self): 1178 self.assertEqual(100, self.mon.Hp()) 1179 1180 def test_default_monster_name(self): 1181 self.assertEqual(None, self.mon.Name()) 1182 1183 def test_default_monster_inventory_item(self): 1184 self.assertEqual(0, self.mon.Inventory(0)) 1185 1186 def test_default_monster_inventory_length(self): 1187 self.assertEqual(0, self.mon.InventoryLength()) 1188 1189 def test_default_monster_color(self): 1190 self.assertEqual(MyGame.Example.Color.Color.Blue, self.mon.Color()) 1191 1192 def test_nondefault_monster_color(self): 1193 b = flatbuffers.Builder(0) 1194 color = MyGame.Example.Color.Color.Red 1195 MyGame.Example.Monster.MonsterStart(b) 1196 MyGame.Example.Monster.MonsterAddColor(b, color) 1197 mon = MyGame.Example.Monster.MonsterEnd(b) 1198 b.Finish(mon) 1199 1200 mon2 = MyGame.Example.Monster.Monster.GetRootAsMonster(b.Bytes, 1201 b.Head()) 1202 self.assertEqual(MyGame.Example.Color.Color.Red, mon2.Color()) 1203 1204 def test_default_monster_testtype(self): 1205 self.assertEqual(0, self.mon.TestType()) 1206 1207 def test_default_monster_test_field(self): 1208 self.assertEqual(None, self.mon.Test()) 1209 1210 def test_default_monster_test4_item(self): 1211 self.assertEqual(None, self.mon.Test4(0)) 1212 1213 def test_default_monster_test4_length(self): 1214 self.assertEqual(0, self.mon.Test4Length()) 1215 1216 def test_default_monster_testarrayofstring(self): 1217 self.assertEqual("", self.mon.Testarrayofstring(0)) 1218 1219 def test_default_monster_testarrayofstring_length(self): 1220 self.assertEqual(0, self.mon.TestarrayofstringLength()) 1221 1222 def test_default_monster_testarrayoftables(self): 1223 self.assertEqual(None, self.mon.Testarrayoftables(0)) 1224 1225 def test_nondefault_monster_testarrayoftables(self): 1226 b = flatbuffers.Builder(0) 1227 1228 # make a child Monster within a vector of Monsters: 1229 MyGame.Example.Monster.MonsterStart(b) 1230 MyGame.Example.Monster.MonsterAddHp(b, 99) 1231 sub_monster = MyGame.Example.Monster.MonsterEnd(b) 1232 1233 # build the vector: 1234 MyGame.Example.Monster.MonsterStartTestarrayoftablesVector(b, 1) 1235 b.PrependUOffsetTRelative(sub_monster) 1236 vec = b.EndVector(1) 1237 1238 # make the parent monster and include the vector of Monster: 1239 MyGame.Example.Monster.MonsterStart(b) 1240 MyGame.Example.Monster.MonsterAddTestarrayoftables(b, vec) 1241 mon = MyGame.Example.Monster.MonsterEnd(b) 1242 b.Finish(mon) 1243 1244 # inspect the resulting data: 1245 mon2 = MyGame.Example.Monster.Monster.GetRootAsMonster(b.Output(), 0) 1246 self.assertEqual(99, mon2.Testarrayoftables(0).Hp()) 1247 self.assertEqual(1, mon2.TestarrayoftablesLength()) 1248 1249 def test_default_monster_testarrayoftables_length(self): 1250 self.assertEqual(0, self.mon.TestarrayoftablesLength()) 1251 1252 def test_nondefault_monster_enemy(self): 1253 b = flatbuffers.Builder(0) 1254 1255 # make an Enemy object: 1256 MyGame.Example.Monster.MonsterStart(b) 1257 MyGame.Example.Monster.MonsterAddHp(b, 88) 1258 enemy = MyGame.Example.Monster.MonsterEnd(b) 1259 b.Finish(enemy) 1260 1261 # make the parent monster and include the vector of Monster: 1262 MyGame.Example.Monster.MonsterStart(b) 1263 MyGame.Example.Monster.MonsterAddEnemy(b, enemy) 1264 mon = MyGame.Example.Monster.MonsterEnd(b) 1265 b.Finish(mon) 1266 1267 # inspect the resulting data: 1268 mon2 = MyGame.Example.Monster.Monster.GetRootAsMonster(b.Bytes, 1269 b.Head()) 1270 self.assertEqual(88, mon2.Enemy().Hp()) 1271 1272 def test_default_monster_testnestedflatbuffer(self): 1273 self.assertEqual(0, self.mon.Testnestedflatbuffer(0)) 1274 1275 def test_default_monster_testnestedflatbuffer_length(self): 1276 self.assertEqual(0, self.mon.TestnestedflatbufferLength()) 1277 1278 def test_nondefault_monster_testnestedflatbuffer(self): 1279 b = flatbuffers.Builder(0) 1280 1281 MyGame.Example.Monster.MonsterStartTestnestedflatbufferVector(b, 3) 1282 b.PrependByte(4) 1283 b.PrependByte(2) 1284 b.PrependByte(0) 1285 sub_buf = b.EndVector(3) 1286 1287 # make the parent monster and include the vector of Monster: 1288 MyGame.Example.Monster.MonsterStart(b) 1289 MyGame.Example.Monster.MonsterAddTestnestedflatbuffer(b, sub_buf) 1290 mon = MyGame.Example.Monster.MonsterEnd(b) 1291 b.Finish(mon) 1292 1293 # inspect the resulting data: 1294 mon2 = MyGame.Example.Monster.Monster.GetRootAsMonster(b.Bytes, 1295 b.Head()) 1296 self.assertEqual(3, mon2.TestnestedflatbufferLength()) 1297 self.assertEqual(0, mon2.Testnestedflatbuffer(0)) 1298 self.assertEqual(2, mon2.Testnestedflatbuffer(1)) 1299 self.assertEqual(4, mon2.Testnestedflatbuffer(2)) 1300 try: 1301 imp.find_module('numpy') 1302 # if numpy exists, then we should be able to get the 1303 # vector as a numpy array 1304 self.assertEqual([0, 2, 4], mon2.TestnestedflatbufferAsNumpy().tolist()) 1305 except ImportError: 1306 assertRaises(self, 1307 lambda: mon2.TestnestedflatbufferAsNumpy(), 1308 NumpyRequiredForThisFeature) 1309 1310 def test_nondefault_monster_testempty(self): 1311 b = flatbuffers.Builder(0) 1312 1313 # make a Stat object: 1314 MyGame.Example.Stat.StatStart(b) 1315 MyGame.Example.Stat.StatAddVal(b, 123) 1316 my_stat = MyGame.Example.Stat.StatEnd(b) 1317 b.Finish(my_stat) 1318 1319 # include the stat object in a monster: 1320 MyGame.Example.Monster.MonsterStart(b) 1321 MyGame.Example.Monster.MonsterAddTestempty(b, my_stat) 1322 mon = MyGame.Example.Monster.MonsterEnd(b) 1323 b.Finish(mon) 1324 1325 # inspect the resulting data: 1326 mon2 = MyGame.Example.Monster.Monster.GetRootAsMonster(b.Bytes, 1327 b.Head()) 1328 self.assertEqual(123, mon2.Testempty().Val()) 1329 1330 def test_default_monster_testbool(self): 1331 self.assertFalse(self.mon.Testbool()) 1332 1333 def test_nondefault_monster_testbool(self): 1334 b = flatbuffers.Builder(0) 1335 MyGame.Example.Monster.MonsterStart(b) 1336 MyGame.Example.Monster.MonsterAddTestbool(b, True) 1337 mon = MyGame.Example.Monster.MonsterEnd(b) 1338 b.Finish(mon) 1339 1340 # inspect the resulting data: 1341 mon2 = MyGame.Example.Monster.Monster.GetRootAsMonster(b.Bytes, 1342 b.Head()) 1343 self.assertTrue(mon2.Testbool()) 1344 1345 def test_default_monster_testhashes(self): 1346 self.assertEqual(0, self.mon.Testhashs32Fnv1()) 1347 self.assertEqual(0, self.mon.Testhashu32Fnv1()) 1348 self.assertEqual(0, self.mon.Testhashs64Fnv1()) 1349 self.assertEqual(0, self.mon.Testhashu64Fnv1()) 1350 self.assertEqual(0, self.mon.Testhashs32Fnv1a()) 1351 self.assertEqual(0, self.mon.Testhashu32Fnv1a()) 1352 self.assertEqual(0, self.mon.Testhashs64Fnv1a()) 1353 self.assertEqual(0, self.mon.Testhashu64Fnv1a()) 1354 1355 def test_nondefault_monster_testhashes(self): 1356 b = flatbuffers.Builder(0) 1357 MyGame.Example.Monster.MonsterStart(b) 1358 MyGame.Example.Monster.MonsterAddTesthashs32Fnv1(b, 1) 1359 MyGame.Example.Monster.MonsterAddTesthashu32Fnv1(b, 2) 1360 MyGame.Example.Monster.MonsterAddTesthashs64Fnv1(b, 3) 1361 MyGame.Example.Monster.MonsterAddTesthashu64Fnv1(b, 4) 1362 MyGame.Example.Monster.MonsterAddTesthashs32Fnv1a(b, 5) 1363 MyGame.Example.Monster.MonsterAddTesthashu32Fnv1a(b, 6) 1364 MyGame.Example.Monster.MonsterAddTesthashs64Fnv1a(b, 7) 1365 MyGame.Example.Monster.MonsterAddTesthashu64Fnv1a(b, 8) 1366 mon = MyGame.Example.Monster.MonsterEnd(b) 1367 b.Finish(mon) 1368 1369 # inspect the resulting data: 1370 mon2 = MyGame.Example.Monster.Monster.GetRootAsMonster(b.Bytes, 1371 b.Head()) 1372 self.assertEqual(1, mon2.Testhashs32Fnv1()) 1373 self.assertEqual(2, mon2.Testhashu32Fnv1()) 1374 self.assertEqual(3, mon2.Testhashs64Fnv1()) 1375 self.assertEqual(4, mon2.Testhashu64Fnv1()) 1376 self.assertEqual(5, mon2.Testhashs32Fnv1a()) 1377 self.assertEqual(6, mon2.Testhashu32Fnv1a()) 1378 self.assertEqual(7, mon2.Testhashs64Fnv1a()) 1379 self.assertEqual(8, mon2.Testhashu64Fnv1a()) 1380 1381 def test_getrootas_for_nonroot_table(self): 1382 b = flatbuffers.Builder(0) 1383 string = b.CreateString("MyStat") 1384 1385 MyGame.Example.Stat.StatStart(b) 1386 MyGame.Example.Stat.StatAddId(b, string) 1387 MyGame.Example.Stat.StatAddVal(b, 12345678) 1388 MyGame.Example.Stat.StatAddCount(b, 12345) 1389 stat = MyGame.Example.Stat.StatEnd(b) 1390 b.Finish(stat) 1391 1392 stat2 = MyGame.Example.Stat.Stat.GetRootAsStat(b.Bytes, b.Head()) 1393 1394 self.assertEqual(b"MyStat", stat2.Id()) 1395 self.assertEqual(12345678, stat2.Val()) 1396 self.assertEqual(12345, stat2.Count()) 1397 1398 1399class TestAllCodePathsOfMonsterExtraSchema(unittest.TestCase): 1400 def setUp(self, *args, **kwargs): 1401 super(TestAllCodePathsOfMonsterExtraSchema, self).setUp(*args, **kwargs) 1402 1403 b = flatbuffers.Builder(0) 1404 MyGame.MonsterExtra.MonsterExtraStart(b) 1405 gen_mon = MyGame.MonsterExtra.MonsterExtraEnd(b) 1406 b.Finish(gen_mon) 1407 1408 self.mon = MyGame.MonsterExtra.MonsterExtra.GetRootAsMonsterExtra(b.Bytes, b.Head()) 1409 1410 def test_default_nan_inf(self): 1411 self.assertTrue(math.isnan(self.mon.TestfNan())) 1412 self.assertEqual(self.mon.TestfPinf(), float("inf")) 1413 self.assertEqual(self.mon.TestfNinf(), float("-inf")) 1414 1415 self.assertTrue(math.isnan(self.mon.TestdNan())) 1416 self.assertEqual(self.mon.TestdPinf(), float("inf")) 1417 self.assertEqual(self.mon.TestdNinf(), float("-inf")) 1418 1419 1420class TestVtableDeduplication(unittest.TestCase): 1421 ''' TestVtableDeduplication verifies that vtables are deduplicated. ''' 1422 1423 def test_vtable_deduplication(self): 1424 b = flatbuffers.Builder(0) 1425 1426 b.StartObject(4) 1427 b.PrependByteSlot(0, 0, 0) 1428 b.PrependByteSlot(1, 11, 0) 1429 b.PrependByteSlot(2, 22, 0) 1430 b.PrependInt16Slot(3, 33, 0) 1431 obj0 = b.EndObject() 1432 1433 b.StartObject(4) 1434 b.PrependByteSlot(0, 0, 0) 1435 b.PrependByteSlot(1, 44, 0) 1436 b.PrependByteSlot(2, 55, 0) 1437 b.PrependInt16Slot(3, 66, 0) 1438 obj1 = b.EndObject() 1439 1440 b.StartObject(4) 1441 b.PrependByteSlot(0, 0, 0) 1442 b.PrependByteSlot(1, 77, 0) 1443 b.PrependByteSlot(2, 88, 0) 1444 b.PrependInt16Slot(3, 99, 0) 1445 obj2 = b.EndObject() 1446 1447 got = b.Bytes[b.Head():] 1448 1449 want = bytearray([ 1450 240, 255, 255, 255, # == -12. offset to dedupped vtable. 1451 99, 0, 1452 88, 1453 77, 1454 248, 255, 255, 255, # == -8. offset to dedupped vtable. 1455 66, 0, 1456 55, 1457 44, 1458 12, 0, 1459 8, 0, 1460 0, 0, 1461 7, 0, 1462 6, 0, 1463 4, 0, 1464 12, 0, 0, 0, 1465 33, 0, 1466 22, 1467 11, 1468 ]) 1469 1470 self.assertEqual((len(want), want), (len(got), got)) 1471 1472 table0 = flatbuffers.table.Table(b.Bytes, len(b.Bytes) - obj0) 1473 table1 = flatbuffers.table.Table(b.Bytes, len(b.Bytes) - obj1) 1474 table2 = flatbuffers.table.Table(b.Bytes, len(b.Bytes) - obj2) 1475 1476 def _checkTable(tab, voffsett_value, b, c, d): 1477 # vtable size 1478 got = tab.GetVOffsetTSlot(0, 0) 1479 self.assertEqual(12, got, 'case 0, 0') 1480 1481 # object size 1482 got = tab.GetVOffsetTSlot(2, 0) 1483 self.assertEqual(8, got, 'case 2, 0') 1484 1485 # default value 1486 got = tab.GetVOffsetTSlot(4, 0) 1487 self.assertEqual(voffsett_value, got, 'case 4, 0') 1488 1489 got = tab.GetSlot(6, 0, N.Uint8Flags) 1490 self.assertEqual(b, got, 'case 6, 0') 1491 1492 val = tab.GetSlot(8, 0, N.Uint8Flags) 1493 self.assertEqual(c, val, 'failed 8, 0') 1494 1495 got = tab.GetSlot(10, 0, N.Uint8Flags) 1496 self.assertEqual(d, got, 'failed 10, 0') 1497 1498 _checkTable(table0, 0, 11, 22, 33) 1499 _checkTable(table1, 0, 44, 55, 66) 1500 _checkTable(table2, 0, 77, 88, 99) 1501 1502 1503class TestExceptions(unittest.TestCase): 1504 def test_object_is_nested_error(self): 1505 b = flatbuffers.Builder(0) 1506 b.StartObject(0) 1507 assertRaises(self, lambda: b.StartObject(0), 1508 flatbuffers.builder.IsNestedError) 1509 1510 def test_object_is_not_nested_error(self): 1511 b = flatbuffers.Builder(0) 1512 assertRaises(self, lambda: b.EndObject(), 1513 flatbuffers.builder.IsNotNestedError) 1514 1515 def test_struct_is_not_inline_error(self): 1516 b = flatbuffers.Builder(0) 1517 b.StartObject(0) 1518 assertRaises(self, lambda: b.PrependStructSlot(0, 1, 0), 1519 flatbuffers.builder.StructIsNotInlineError) 1520 1521 def test_unreachable_error(self): 1522 b = flatbuffers.Builder(0) 1523 assertRaises(self, lambda: b.PrependUOffsetTRelative(1), 1524 flatbuffers.builder.OffsetArithmeticError) 1525 1526 def test_create_string_is_nested_error(self): 1527 b = flatbuffers.Builder(0) 1528 b.StartObject(0) 1529 s = 'test1' 1530 assertRaises(self, lambda: b.CreateString(s), 1531 flatbuffers.builder.IsNestedError) 1532 1533 def test_create_byte_vector_is_nested_error(self): 1534 b = flatbuffers.Builder(0) 1535 b.StartObject(0) 1536 s = b'test1' 1537 assertRaises(self, lambda: b.CreateByteVector(s), 1538 flatbuffers.builder.IsNestedError) 1539 1540 def test_finished_bytes_error(self): 1541 b = flatbuffers.Builder(0) 1542 assertRaises(self, lambda: b.Output(), 1543 flatbuffers.builder.BuilderNotFinishedError) 1544 1545 1546def CheckAgainstGoldDataGo(): 1547 try: 1548 gen_buf, gen_off = make_monster_from_generated_code() 1549 fn = 'monsterdata_go_wire.mon' 1550 if not os.path.exists(fn): 1551 print('Go-generated data does not exist, failed.') 1552 return False 1553 1554 # would like to use a context manager here, but it's less 1555 # backwards-compatible: 1556 f = open(fn, 'rb') 1557 go_wire_data = f.read() 1558 f.close() 1559 1560 CheckReadBuffer(bytearray(go_wire_data), 0) 1561 if not bytearray(gen_buf[gen_off:]) == bytearray(go_wire_data): 1562 raise AssertionError('CheckAgainstGoldDataGo failed') 1563 except: 1564 print('Failed to test against Go-generated test data.') 1565 return False 1566 1567 print('Can read Go-generated test data, and Python generates bytewise identical data.') 1568 return True 1569 1570 1571def CheckAgainstGoldDataJava(): 1572 try: 1573 gen_buf, gen_off = make_monster_from_generated_code() 1574 fn = 'monsterdata_java_wire.mon' 1575 if not os.path.exists(fn): 1576 print('Java-generated data does not exist, failed.') 1577 return False 1578 f = open(fn, 'rb') 1579 java_wire_data = f.read() 1580 f.close() 1581 1582 CheckReadBuffer(bytearray(java_wire_data), 0) 1583 except: 1584 print('Failed to read Java-generated test data.') 1585 return False 1586 1587 print('Can read Java-generated test data.') 1588 return True 1589 1590 1591class LCG(object): 1592 ''' Include simple random number generator to ensure results will be the 1593 same cross platform. 1594 http://en.wikipedia.org/wiki/Park%E2%80%93Miller_random_number_generator ''' 1595 1596 __slots__ = ['n'] 1597 1598 InitialLCGSeed = 48271 1599 1600 def __init__(self): 1601 self.n = self.InitialLCGSeed 1602 1603 def Reset(self): 1604 self.n = self.InitialLCGSeed 1605 1606 def Next(self): 1607 self.n = ((self.n * 279470273) % 4294967291) & 0xFFFFFFFF 1608 return self.n 1609 1610 1611def BenchmarkVtableDeduplication(count): 1612 ''' 1613 BenchmarkVtableDeduplication measures the speed of vtable deduplication 1614 by creating `prePop` vtables, then populating `count` objects with a 1615 different single vtable. 1616 1617 When count is large (as in long benchmarks), memory usage may be high. 1618 ''' 1619 1620 prePop = 10 1621 builder = flatbuffers.Builder(0) 1622 1623 # pre-populate some vtables: 1624 for i in compat_range(prePop): 1625 builder.StartObject(i) 1626 for j in compat_range(i): 1627 builder.PrependInt16Slot(j, j, 0) 1628 builder.EndObject() 1629 1630 # benchmark deduplication of a new vtable: 1631 def f(): 1632 builder.StartObject(prePop) 1633 for j in compat_range(prePop): 1634 builder.PrependInt16Slot(j, j, 0) 1635 builder.EndObject() 1636 1637 duration = timeit.timeit(stmt=f, number=count) 1638 rate = float(count) / duration 1639 print(('vtable deduplication rate: %.2f/sec' % rate)) 1640 1641 1642def BenchmarkCheckReadBuffer(count, buf, off): 1643 ''' 1644 BenchmarkCheckReadBuffer measures the speed of flatbuffer reading 1645 by re-using the CheckReadBuffer function with the gold data. 1646 ''' 1647 1648 def f(): 1649 CheckReadBuffer(buf, off) 1650 1651 duration = timeit.timeit(stmt=f, number=count) 1652 rate = float(count) / duration 1653 data = float(len(buf) * count) / float(1024 * 1024) 1654 data_rate = data / float(duration) 1655 1656 print(('traversed %d %d-byte flatbuffers in %.2fsec: %.2f/sec, %.2fMB/sec') 1657 % (count, len(buf), duration, rate, data_rate)) 1658 1659 1660def BenchmarkMakeMonsterFromGeneratedCode(count, length): 1661 ''' 1662 BenchmarkMakeMonsterFromGeneratedCode measures the speed of flatbuffer 1663 creation by re-using the make_monster_from_generated_code function for 1664 generating gold data examples. 1665 ''' 1666 1667 duration = timeit.timeit(stmt=make_monster_from_generated_code, 1668 number=count) 1669 rate = float(count) / duration 1670 data = float(length * count) / float(1024 * 1024) 1671 data_rate = data / float(duration) 1672 1673 print(('built %d %d-byte flatbuffers in %.2fsec: %.2f/sec, %.2fMB/sec' % \ 1674 (count, length, duration, rate, data_rate))) 1675 1676 1677def backward_compatible_run_tests(**kwargs): 1678 if PY_VERSION < (2, 6): 1679 sys.stderr.write("Python version less than 2.6 are not supported") 1680 sys.stderr.flush() 1681 return False 1682 1683 # python2.6 has a reduced-functionality unittest.main function: 1684 if PY_VERSION == (2, 6): 1685 try: 1686 unittest.main(**kwargs) 1687 except SystemExit as e: 1688 if not e.code == 0: 1689 return False 1690 return True 1691 1692 # python2.7 and above let us not exit once unittest.main is run: 1693 kwargs['exit'] = False 1694 kwargs['verbosity'] = 0 1695 ret = unittest.main(**kwargs) 1696 if ret.result.errors or ret.result.failures: 1697 return False 1698 1699 return True 1700 1701def main(): 1702 import os 1703 import sys 1704 if not len(sys.argv) == 4: 1705 sys.stderr.write('Usage: %s <benchmark vtable count>' 1706 '<benchmark read count> <benchmark build count>\n' 1707 % sys.argv[0]) 1708 sys.stderr.write(' Provide COMPARE_GENERATED_TO_GO=1 to check' 1709 'for bytewise comparison to Go data.\n') 1710 sys.stderr.write(' Provide COMPARE_GENERATED_TO_JAVA=1 to check' 1711 'for bytewise comparison to Java data.\n') 1712 sys.stderr.flush() 1713 sys.exit(1) 1714 1715 kwargs = dict(argv=sys.argv[:-3]) 1716 1717 # run tests, and run some language comparison checks if needed: 1718 success = backward_compatible_run_tests(**kwargs) 1719 if success and os.environ.get('COMPARE_GENERATED_TO_GO', 0) == "1": 1720 success = success and CheckAgainstGoldDataGo() 1721 if success and os.environ.get('COMPARE_GENERATED_TO_JAVA', 0) == "1": 1722 success = success and CheckAgainstGoldDataJava() 1723 1724 if not success: 1725 sys.stderr.write('Tests failed, skipping benchmarks.\n') 1726 sys.stderr.flush() 1727 sys.exit(1) 1728 1729 # run benchmarks (if 0, they will be a noop): 1730 bench_vtable = int(sys.argv[1]) 1731 bench_traverse = int(sys.argv[2]) 1732 bench_build = int(sys.argv[3]) 1733 if bench_vtable: 1734 BenchmarkVtableDeduplication(bench_vtable) 1735 if bench_traverse: 1736 buf, off = make_monster_from_generated_code() 1737 BenchmarkCheckReadBuffer(bench_traverse, buf, off) 1738 if bench_build: 1739 buf, off = make_monster_from_generated_code() 1740 BenchmarkMakeMonsterFromGeneratedCode(bench_build, len(buf)) 1741 1742if __name__ == '__main__': 1743 main() 1744