1/* 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 */ 16 17package main 18 19import ( 20 mygame "MyGame" // refers to generated code 21 example "MyGame/Example" // refers to generated code 22 23 "bytes" 24 "flag" 25 "fmt" 26 "io/ioutil" 27 "os" 28 "reflect" 29 "sort" 30 "testing" 31 32 flatbuffers "github.com/google/flatbuffers/go" 33) 34 35var ( 36 cppData, javaData, outData string 37 fuzz bool 38 fuzzFields, fuzzObjects int 39) 40 41func init() { 42 flag.StringVar(&cppData, "cpp_data", "", 43 "location of monsterdata_test.mon to verify against (required)") 44 flag.StringVar(&javaData, "java_data", "", 45 "location of monsterdata_java_wire.mon to verify against (optional)") 46 flag.StringVar(&outData, "out_data", "", 47 "location to write generated Go data") 48 flag.BoolVar(&fuzz, "fuzz", false, "perform fuzzing") 49 flag.IntVar(&fuzzFields, "fuzz_fields", 4, "fields per fuzzer object") 50 flag.IntVar(&fuzzObjects, "fuzz_objects", 10000, 51 "number of fuzzer objects (higher is slower and more thorough") 52 flag.Parse() 53 54 if cppData == "" { 55 fmt.Fprintf(os.Stderr, "cpp_data argument is required\n") 56 os.Exit(1) 57 } 58} 59 60// Store specific byte patterns in these variables for the fuzzer. These 61// values are taken verbatim from the C++ function FuzzTest1. 62var ( 63 overflowingInt32Val = flatbuffers.GetInt32([]byte{0x83, 0x33, 0x33, 0x33}) 64 overflowingInt64Val = flatbuffers.GetInt64([]byte{0x84, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44}) 65) 66 67// TestAll runs all checks, failing if any errors occur. 68func TestAll(t *testing.T) { 69 // Verify that the Go FlatBuffers runtime library generates the 70 // expected bytes (does not use any schema): 71 CheckByteLayout(t.Fatalf) 72 CheckMutateMethods(t.Fatalf) 73 74 // Verify that panics are raised during exceptional conditions: 75 CheckNotInObjectError(t.Fatalf) 76 CheckStringIsNestedError(t.Fatalf) 77 CheckByteStringIsNestedError(t.Fatalf) 78 CheckStructIsNotInlineError(t.Fatalf) 79 CheckFinishedBytesError(t.Fatalf) 80 81 // Verify that GetRootAs works for non-root tables 82 CheckGetRootAsForNonRootTable(t.Fatalf) 83 CheckTableAccessors(t.Fatalf) 84 85 // Verify that using the generated Go code builds a buffer without 86 // returning errors: 87 generated, off := CheckGeneratedBuild(t.Fatalf) 88 89 // Verify that the buffer generated by Go code is readable by the 90 // generated Go code: 91 CheckReadBuffer(generated, off, t.Fatalf) 92 CheckMutateBuffer(generated, off, t.Fatalf) 93 94 // Verify that the buffer generated by C++ code is readable by the 95 // generated Go code: 96 monsterDataCpp, err := ioutil.ReadFile(cppData) 97 if err != nil { 98 t.Fatal(err) 99 } 100 CheckReadBuffer(monsterDataCpp, 0, t.Fatalf) 101 CheckMutateBuffer(monsterDataCpp, 0, t.Fatalf) 102 103 // Verify that vtables are deduplicated when written: 104 CheckVtableDeduplication(t.Fatalf) 105 106 // Verify the enum names 107 CheckEnumNames(t.Fatalf) 108 109 // Verify enum String methods 110 CheckEnumString(t.Fatalf) 111 112 // Verify the enum values maps 113 CheckEnumValues(t.Fatalf) 114 115 // Verify that the Go code used in FlatBuffers documentation passes 116 // some sanity checks: 117 CheckDocExample(generated, off, t.Fatalf) 118 119 // Check Builder.CreateByteVector 120 CheckCreateByteVector(t.Fatalf) 121 122 // Check a parent namespace import 123 CheckParentNamespace(t.Fatalf) 124 125 // If the filename of the FlatBuffers file generated by the Java test 126 // is given, check that Go code can read it, and that Go code 127 // generates an identical buffer when used to create the example data: 128 if javaData != "" { 129 monsterDataJava, err := ioutil.ReadFile(javaData) 130 if err != nil { 131 t.Fatal(err) 132 } 133 CheckReadBuffer(monsterDataJava, 0, t.Fatalf) 134 CheckByteEquality(generated[off:], monsterDataJava, t.Fatalf) 135 } 136 137 // Verify that various fuzzing scenarios produce a valid FlatBuffer. 138 if fuzz { 139 checkFuzz(fuzzFields, fuzzObjects, t.Fatalf) 140 } 141 142 // Write the generated buffer out to a file: 143 err = ioutil.WriteFile(outData, generated[off:], os.FileMode(0644)) 144 if err != nil { 145 t.Fatal(err) 146 } 147} 148 149// CheckReadBuffer checks that the given buffer is evaluated correctly 150// as the example Monster. 151func CheckReadBuffer(buf []byte, offset flatbuffers.UOffsetT, fail func(string, ...interface{})) { 152 // try the two ways of generating a monster 153 monster1 := example.GetRootAsMonster(buf, offset) 154 monster2 := &example.Monster{} 155 flatbuffers.GetRootAs(buf, offset, monster2) 156 for _, monster := range []*example.Monster{monster1, monster2} { 157 if got := monster.Hp(); 80 != got { 158 fail(FailString("hp", 80, got)) 159 } 160 161 // default 162 if got := monster.Mana(); 150 != got { 163 fail(FailString("mana", 150, got)) 164 } 165 166 if got := monster.Name(); !bytes.Equal([]byte("MyMonster"), got) { 167 fail(FailString("name", "MyMonster", got)) 168 } 169 170 if got := monster.Color(); example.ColorBlue != got { 171 fail(FailString("color", example.ColorBlue, got)) 172 } 173 174 if got := monster.Testbool(); true != got { 175 fail(FailString("testbool", true, got)) 176 } 177 178 // initialize a Vec3 from Pos() 179 vec := new(example.Vec3) 180 vec = monster.Pos(vec) 181 if vec == nil { 182 fail("vec3 initialization failed") 183 } 184 185 // check that new allocs equal given ones: 186 vec2 := monster.Pos(nil) 187 if !reflect.DeepEqual(vec, vec2) { 188 fail("fresh allocation failed") 189 } 190 191 // verify the properties of the Vec3 192 if got := vec.X(); float32(1.0) != got { 193 fail(FailString("Pos.X", float32(1.0), got)) 194 } 195 196 if got := vec.Y(); float32(2.0) != got { 197 fail(FailString("Pos.Y", float32(2.0), got)) 198 } 199 200 if got := vec.Z(); float32(3.0) != got { 201 fail(FailString("Pos.Z", float32(3.0), got)) 202 } 203 204 if got := vec.Test1(); float64(3.0) != got { 205 fail(FailString("Pos.Test1", float64(3.0), got)) 206 } 207 208 if got := vec.Test2(); example.ColorGreen != got { 209 fail(FailString("Pos.Test2", example.ColorGreen, got)) 210 } 211 212 // initialize a Test from Test3(...) 213 t := new(example.Test) 214 t = vec.Test3(t) 215 if t == nil { 216 fail("vec.Test3(&t) failed") 217 } 218 219 // check that new allocs equal given ones: 220 t2 := vec.Test3(nil) 221 if !reflect.DeepEqual(t, t2) { 222 fail("fresh allocation failed") 223 } 224 225 // verify the properties of the Test 226 if got := t.A(); int16(5) != got { 227 fail(FailString("t.A()", int16(5), got)) 228 } 229 230 if got := t.B(); int8(6) != got { 231 fail(FailString("t.B()", int8(6), got)) 232 } 233 234 if got := monster.TestType(); example.AnyMonster != got { 235 fail(FailString("monster.TestType()", example.AnyMonster, got)) 236 } 237 238 // initialize a Table from a union field Test(...) 239 var table2 flatbuffers.Table 240 if ok := monster.Test(&table2); !ok { 241 fail("monster.Test(&monster2) failed") 242 } 243 244 // initialize a Monster from the Table from the union 245 var monster2 example.Monster 246 monster2.Init(table2.Bytes, table2.Pos) 247 248 if got := monster2.Name(); !bytes.Equal([]byte("Fred"), got) { 249 fail(FailString("monster2.Name()", "Fred", got)) 250 } 251 252 inventorySlice := monster.InventoryBytes() 253 if len(inventorySlice) != monster.InventoryLength() { 254 fail(FailString("len(monster.InventoryBytes) != monster.InventoryLength", len(inventorySlice), monster.InventoryLength())) 255 } 256 257 if got := monster.InventoryLength(); 5 != got { 258 fail(FailString("monster.InventoryLength", 5, got)) 259 } 260 261 invsum := 0 262 l := monster.InventoryLength() 263 for i := 0; i < l; i++ { 264 v := monster.Inventory(i) 265 if v != inventorySlice[i] { 266 fail(FailString("monster inventory slice[i] != Inventory(i)", v, inventorySlice[i])) 267 } 268 invsum += int(v) 269 } 270 if invsum != 10 { 271 fail(FailString("monster inventory sum", 10, invsum)) 272 } 273 274 if got := monster.Test4Length(); 2 != got { 275 fail(FailString("monster.Test4Length()", 2, got)) 276 } 277 278 var test0 example.Test 279 ok := monster.Test4(&test0, 0) 280 if !ok { 281 fail(FailString("monster.Test4(&test0, 0)", true, ok)) 282 } 283 284 var test1 example.Test 285 ok = monster.Test4(&test1, 1) 286 if !ok { 287 fail(FailString("monster.Test4(&test1, 1)", true, ok)) 288 } 289 290 // the position of test0 and test1 are swapped in monsterdata_java_wire 291 // and monsterdata_test_wire, so ignore ordering 292 v0 := test0.A() 293 v1 := test0.B() 294 v2 := test1.A() 295 v3 := test1.B() 296 sum := int(v0) + int(v1) + int(v2) + int(v3) 297 298 if 100 != sum { 299 fail(FailString("test0 and test1 sum", 100, sum)) 300 } 301 302 if got := monster.TestarrayofstringLength(); 2 != got { 303 fail(FailString("Testarrayofstring length", 2, got)) 304 } 305 306 if got := monster.Testarrayofstring(0); !bytes.Equal([]byte("test1"), got) { 307 fail(FailString("Testarrayofstring(0)", "test1", got)) 308 } 309 310 if got := monster.Testarrayofstring(1); !bytes.Equal([]byte("test2"), got) { 311 fail(FailString("Testarrayofstring(1)", "test2", got)) 312 } 313 } 314} 315 316// CheckMutateBuffer checks that the given buffer can be mutated correctly 317// as the example Monster. Only available scalar values are mutated. 318func CheckMutateBuffer(org []byte, offset flatbuffers.UOffsetT, fail func(string, ...interface{})) { 319 // make a copy to mutate 320 buf := make([]byte, len(org)) 321 copy(buf, org) 322 323 // load monster data from the buffer 324 monster := example.GetRootAsMonster(buf, offset) 325 326 // test case struct 327 type testcase struct { 328 field string 329 testfn func() bool 330 } 331 332 testForOriginalValues := []testcase{ 333 testcase{"Hp", func() bool { return monster.Hp() == 80 }}, 334 testcase{"Mana", func() bool { return monster.Mana() == 150 }}, 335 testcase{"Testbool", func() bool { return monster.Testbool() == true }}, 336 testcase{"Pos.X'", func() bool { return monster.Pos(nil).X() == float32(1.0) }}, 337 testcase{"Pos.Y'", func() bool { return monster.Pos(nil).Y() == float32(2.0) }}, 338 testcase{"Pos.Z'", func() bool { return monster.Pos(nil).Z() == float32(3.0) }}, 339 testcase{"Pos.Test1'", func() bool { return monster.Pos(nil).Test1() == float64(3.0) }}, 340 testcase{"Pos.Test2'", func() bool { return monster.Pos(nil).Test2() == example.ColorGreen }}, 341 testcase{"Pos.Test3.A", func() bool { return monster.Pos(nil).Test3(nil).A() == int16(5) }}, 342 testcase{"Pos.Test3.B", func() bool { return monster.Pos(nil).Test3(nil).B() == int8(6) }}, 343 testcase{"Inventory[2]", func() bool { return monster.Inventory(2) == byte(2) }}, 344 } 345 346 testMutability := []testcase{ 347 testcase{"Hp", func() bool { return monster.MutateHp(70) }}, 348 testcase{"Mana", func() bool { return !monster.MutateMana(140) }}, 349 testcase{"Testbool", func() bool { return monster.MutateTestbool(false) }}, 350 testcase{"Pos.X", func() bool { return monster.Pos(nil).MutateX(10.0) }}, 351 testcase{"Pos.Y", func() bool { return monster.Pos(nil).MutateY(20.0) }}, 352 testcase{"Pos.Z", func() bool { return monster.Pos(nil).MutateZ(30.0) }}, 353 testcase{"Pos.Test1", func() bool { return monster.Pos(nil).MutateTest1(30.0) }}, 354 testcase{"Pos.Test2", func() bool { return monster.Pos(nil).MutateTest2(example.ColorBlue) }}, 355 testcase{"Pos.Test3.A", func() bool { return monster.Pos(nil).Test3(nil).MutateA(50) }}, 356 testcase{"Pos.Test3.B", func() bool { return monster.Pos(nil).Test3(nil).MutateB(60) }}, 357 testcase{"Inventory[2]", func() bool { return monster.MutateInventory(2, 200) }}, 358 } 359 360 testForMutatedValues := []testcase{ 361 testcase{"Hp", func() bool { return monster.Hp() == 70 }}, 362 testcase{"Mana", func() bool { return monster.Mana() == 150 }}, 363 testcase{"Testbool", func() bool { return monster.Testbool() == false }}, 364 testcase{"Pos.X'", func() bool { return monster.Pos(nil).X() == float32(10.0) }}, 365 testcase{"Pos.Y'", func() bool { return monster.Pos(nil).Y() == float32(20.0) }}, 366 testcase{"Pos.Z'", func() bool { return monster.Pos(nil).Z() == float32(30.0) }}, 367 testcase{"Pos.Test1'", func() bool { return monster.Pos(nil).Test1() == float64(30.0) }}, 368 testcase{"Pos.Test2'", func() bool { return monster.Pos(nil).Test2() == example.ColorBlue }}, 369 testcase{"Pos.Test3.A", func() bool { return monster.Pos(nil).Test3(nil).A() == int16(50) }}, 370 testcase{"Pos.Test3.B", func() bool { return monster.Pos(nil).Test3(nil).B() == int8(60) }}, 371 testcase{"Inventory[2]", func() bool { return monster.Inventory(2) == byte(200) }}, 372 } 373 374 testInvalidEnumValues := []testcase{ 375 testcase{"Pos.Test2", func() bool { return monster.Pos(nil).MutateTest2(example.Color(20)) }}, 376 testcase{"Pos.Test2", func() bool { return monster.Pos(nil).Test2() == example.Color(20) }}, 377 } 378 379 // make sure original values are okay 380 for _, t := range testForOriginalValues { 381 if !t.testfn() { 382 fail("field '" + t.field + "' doesn't have the expected original value") 383 } 384 } 385 386 // try to mutate fields and check mutability 387 for _, t := range testMutability { 388 if !t.testfn() { 389 fail(FailString("field '"+t.field+"' failed mutability test", true, false)) 390 } 391 } 392 393 // test whether values have changed 394 for _, t := range testForMutatedValues { 395 if !t.testfn() { 396 fail("field '" + t.field + "' doesn't have the expected mutated value") 397 } 398 } 399 400 // make sure the buffer has changed 401 if reflect.DeepEqual(buf, org) { 402 fail("mutate buffer failed") 403 } 404 405 // To make sure the buffer has changed accordingly 406 // Read data from the buffer and verify all fields 407 monster = example.GetRootAsMonster(buf, offset) 408 for _, t := range testForMutatedValues { 409 if !t.testfn() { 410 fail("field '" + t.field + "' doesn't have the expected mutated value") 411 } 412 } 413 414 // a couple extra tests for "invalid" enum values, which don't correspond to 415 // anything in the schema, but are allowed 416 for _, t := range testInvalidEnumValues { 417 if !t.testfn() { 418 fail("field '" + t.field + "' doesn't work with an invalid enum value") 419 } 420 } 421 422 // reverting all fields to original values should 423 // re-create the original buffer. Mutate all fields 424 // back to their original values and compare buffers. 425 // This test is done to make sure mutations do not do 426 // any unnecessary changes to the buffer. 427 monster = example.GetRootAsMonster(buf, offset) 428 monster.MutateHp(80) 429 monster.MutateTestbool(true) 430 monster.Pos(nil).MutateX(1.0) 431 monster.Pos(nil).MutateY(2.0) 432 monster.Pos(nil).MutateZ(3.0) 433 monster.Pos(nil).MutateTest1(3.0) 434 monster.Pos(nil).MutateTest2(example.ColorGreen) 435 monster.Pos(nil).Test3(nil).MutateA(5) 436 monster.Pos(nil).Test3(nil).MutateB(6) 437 monster.MutateInventory(2, 2) 438 439 for _, t := range testForOriginalValues { 440 if !t.testfn() { 441 fail("field '" + t.field + "' doesn't have the expected original value") 442 } 443 } 444 445 // buffer should have original values 446 if !reflect.DeepEqual(buf, org) { 447 fail("revert changes failed") 448 } 449} 450 451// Low level stress/fuzz test: serialize/deserialize a variety of 452// different kinds of data in different combinations 453func checkFuzz(fuzzFields, fuzzObjects int, fail func(string, ...interface{})) { 454 455 // Values we're testing against: chosen to ensure no bits get chopped 456 // off anywhere, and also be different from eachother. 457 boolVal := true 458 int8Val := int8(-127) // 0x81 459 uint8Val := uint8(0xFF) 460 int16Val := int16(-32222) // 0x8222 461 uint16Val := uint16(0xFEEE) 462 int32Val := int32(overflowingInt32Val) 463 uint32Val := uint32(0xFDDDDDDD) 464 int64Val := int64(overflowingInt64Val) 465 uint64Val := uint64(0xFCCCCCCCCCCCCCCC) 466 float32Val := float32(3.14159) 467 float64Val := float64(3.14159265359) 468 469 testValuesMax := 11 // hardcoded to the number of scalar types 470 471 builder := flatbuffers.NewBuilder(0) 472 l := NewLCG() 473 474 objects := make([]flatbuffers.UOffsetT, fuzzObjects) 475 476 // Generate fuzzObjects random objects each consisting of 477 // fuzzFields fields, each of a random type. 478 for i := 0; i < fuzzObjects; i++ { 479 builder.StartObject(fuzzFields) 480 481 for f := 0; f < fuzzFields; f++ { 482 choice := l.Next() % uint32(testValuesMax) 483 switch choice { 484 case 0: 485 builder.PrependBoolSlot(int(f), boolVal, false) 486 case 1: 487 builder.PrependInt8Slot(int(f), int8Val, 0) 488 case 2: 489 builder.PrependUint8Slot(int(f), uint8Val, 0) 490 case 3: 491 builder.PrependInt16Slot(int(f), int16Val, 0) 492 case 4: 493 builder.PrependUint16Slot(int(f), uint16Val, 0) 494 case 5: 495 builder.PrependInt32Slot(int(f), int32Val, 0) 496 case 6: 497 builder.PrependUint32Slot(int(f), uint32Val, 0) 498 case 7: 499 builder.PrependInt64Slot(int(f), int64Val, 0) 500 case 8: 501 builder.PrependUint64Slot(int(f), uint64Val, 0) 502 case 9: 503 builder.PrependFloat32Slot(int(f), float32Val, 0) 504 case 10: 505 builder.PrependFloat64Slot(int(f), float64Val, 0) 506 } 507 } 508 509 off := builder.EndObject() 510 511 // store the offset from the end of the builder buffer, 512 // since it will keep growing: 513 objects[i] = off 514 } 515 516 // Do some bookkeeping to generate stats on fuzzes: 517 stats := map[string]int{} 518 check := func(desc string, want, got interface{}) { 519 stats[desc]++ 520 if want != got { 521 fail("%s want %v got %v", desc, want, got) 522 } 523 } 524 525 l = NewLCG() // Reset. 526 527 // Test that all objects we generated are readable and return the 528 // expected values. We generate random objects in the same order 529 // so this is deterministic. 530 for i := 0; i < fuzzObjects; i++ { 531 532 table := &flatbuffers.Table{ 533 Bytes: builder.Bytes, 534 Pos: flatbuffers.UOffsetT(len(builder.Bytes)) - objects[i], 535 } 536 537 for j := 0; j < fuzzFields; j++ { 538 f := flatbuffers.VOffsetT((flatbuffers.VtableMetadataFields + j) * flatbuffers.SizeVOffsetT) 539 choice := l.Next() % uint32(testValuesMax) 540 541 switch choice { 542 case 0: 543 check("bool", boolVal, table.GetBoolSlot(f, false)) 544 case 1: 545 check("int8", int8Val, table.GetInt8Slot(f, 0)) 546 case 2: 547 check("uint8", uint8Val, table.GetUint8Slot(f, 0)) 548 case 3: 549 check("int16", int16Val, table.GetInt16Slot(f, 0)) 550 case 4: 551 check("uint16", uint16Val, table.GetUint16Slot(f, 0)) 552 case 5: 553 check("int32", int32Val, table.GetInt32Slot(f, 0)) 554 case 6: 555 check("uint32", uint32Val, table.GetUint32Slot(f, 0)) 556 case 7: 557 check("int64", int64Val, table.GetInt64Slot(f, 0)) 558 case 8: 559 check("uint64", uint64Val, table.GetUint64Slot(f, 0)) 560 case 9: 561 check("float32", float32Val, table.GetFloat32Slot(f, 0)) 562 case 10: 563 check("float64", float64Val, table.GetFloat64Slot(f, 0)) 564 } 565 } 566 } 567 568 // If enough checks were made, verify that all scalar types were used: 569 if fuzzFields*fuzzObjects >= testValuesMax { 570 if len(stats) != testValuesMax { 571 fail("fuzzing failed to test all scalar types") 572 } 573 } 574 575 // Print some counts, if needed: 576 if testing.Verbose() { 577 if fuzzFields == 0 || fuzzObjects == 0 { 578 fmt.Printf("fuzz\tfields: %d\tobjects: %d\t[none]\t%d\n", 579 fuzzFields, fuzzObjects, 0) 580 } else { 581 keys := make([]string, 0, len(stats)) 582 for k := range stats { 583 keys = append(keys, k) 584 } 585 sort.Strings(keys) 586 for _, k := range keys { 587 fmt.Printf("fuzz\tfields: %d\tobjects: %d\t%s\t%d\n", 588 fuzzFields, fuzzObjects, k, stats[k]) 589 } 590 } 591 } 592 593 return 594} 595 596// FailString makes a message for when expectations differ from reality. 597func FailString(name string, want, got interface{}) string { 598 return fmt.Sprintf("bad %s: want %#v got %#v", name, want, got) 599} 600 601// CheckByteLayout verifies the bytes of a Builder in various scenarios. 602func CheckByteLayout(fail func(string, ...interface{})) { 603 var b *flatbuffers.Builder 604 605 var i int 606 check := func(want []byte) { 607 i++ 608 got := b.Bytes[b.Head():] 609 if !bytes.Equal(want, got) { 610 fail("case %d: want\n%v\nbut got\n%v\n", i, want, got) 611 } 612 } 613 614 // test 1: numbers 615 616 b = flatbuffers.NewBuilder(0) 617 check([]byte{}) 618 b.PrependBool(true) 619 check([]byte{1}) 620 b.PrependInt8(-127) 621 check([]byte{129, 1}) 622 b.PrependUint8(255) 623 check([]byte{255, 129, 1}) 624 b.PrependInt16(-32222) 625 check([]byte{0x22, 0x82, 0, 255, 129, 1}) // first pad 626 b.PrependUint16(0xFEEE) 627 check([]byte{0xEE, 0xFE, 0x22, 0x82, 0, 255, 129, 1}) // no pad this time 628 b.PrependInt32(-53687092) 629 check([]byte{204, 204, 204, 252, 0xEE, 0xFE, 0x22, 0x82, 0, 255, 129, 1}) 630 b.PrependUint32(0x98765432) 631 check([]byte{0x32, 0x54, 0x76, 0x98, 204, 204, 204, 252, 0xEE, 0xFE, 0x22, 0x82, 0, 255, 129, 1}) 632 633 // test 1b: numbers 2 634 635 b = flatbuffers.NewBuilder(0) 636 b.PrependUint64(0x1122334455667788) 637 check([]byte{0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11}) 638 639 // test 2: 1xbyte vector 640 641 b = flatbuffers.NewBuilder(0) 642 check([]byte{}) 643 b.StartVector(flatbuffers.SizeByte, 1, 1) 644 check([]byte{0, 0, 0}) // align to 4bytes 645 b.PrependByte(1) 646 check([]byte{1, 0, 0, 0}) 647 b.EndVector(1) 648 check([]byte{1, 0, 0, 0, 1, 0, 0, 0}) // padding 649 650 // test 3: 2xbyte vector 651 652 b = flatbuffers.NewBuilder(0) 653 b.StartVector(flatbuffers.SizeByte, 2, 1) 654 check([]byte{0, 0}) // align to 4bytes 655 b.PrependByte(1) 656 check([]byte{1, 0, 0}) 657 b.PrependByte(2) 658 check([]byte{2, 1, 0, 0}) 659 b.EndVector(2) 660 check([]byte{2, 0, 0, 0, 2, 1, 0, 0}) // padding 661 662 // test 3b: 11xbyte vector matches builder size 663 664 b = flatbuffers.NewBuilder(12) 665 b.StartVector(flatbuffers.SizeByte, 8, 1) 666 start := []byte{} 667 check(start) 668 for i := 1; i < 12; i++ { 669 b.PrependByte(byte(i)) 670 start = append([]byte{byte(i)}, start...) 671 check(start) 672 } 673 b.EndVector(8) 674 check(append([]byte{8, 0, 0, 0}, start...)) 675 676 // test 4: 1xuint16 vector 677 678 b = flatbuffers.NewBuilder(0) 679 b.StartVector(flatbuffers.SizeUint16, 1, 1) 680 check([]byte{0, 0}) // align to 4bytes 681 b.PrependUint16(1) 682 check([]byte{1, 0, 0, 0}) 683 b.EndVector(1) 684 check([]byte{1, 0, 0, 0, 1, 0, 0, 0}) // padding 685 686 // test 5: 2xuint16 vector 687 688 b = flatbuffers.NewBuilder(0) 689 b.StartVector(flatbuffers.SizeUint16, 2, 1) 690 check([]byte{}) // align to 4bytes 691 b.PrependUint16(0xABCD) 692 check([]byte{0xCD, 0xAB}) 693 b.PrependUint16(0xDCBA) 694 check([]byte{0xBA, 0xDC, 0xCD, 0xAB}) 695 b.EndVector(2) 696 check([]byte{2, 0, 0, 0, 0xBA, 0xDC, 0xCD, 0xAB}) 697 698 // test 6: CreateString 699 700 b = flatbuffers.NewBuilder(0) 701 b.CreateString("foo") 702 check([]byte{3, 0, 0, 0, 'f', 'o', 'o', 0}) // 0-terminated, no pad 703 b.CreateString("moop") 704 check([]byte{4, 0, 0, 0, 'm', 'o', 'o', 'p', 0, 0, 0, 0, // 0-terminated, 3-byte pad 705 3, 0, 0, 0, 'f', 'o', 'o', 0}) 706 707 // test 6b: CreateString unicode 708 709 b = flatbuffers.NewBuilder(0) 710 // These characters are chinese from blog.golang.org/strings 711 // We use escape codes here so that editors without unicode support 712 // aren't bothered: 713 uni_str := "\u65e5\u672c\u8a9e" 714 b.CreateString(uni_str) 715 check([]byte{9, 0, 0, 0, 230, 151, 165, 230, 156, 172, 232, 170, 158, 0, // null-terminated, 2-byte pad 716 0, 0}) 717 718 // test 6c: CreateByteString 719 720 b = flatbuffers.NewBuilder(0) 721 b.CreateByteString([]byte("foo")) 722 check([]byte{3, 0, 0, 0, 'f', 'o', 'o', 0}) // 0-terminated, no pad 723 b.CreateByteString([]byte("moop")) 724 check([]byte{4, 0, 0, 0, 'm', 'o', 'o', 'p', 0, 0, 0, 0, // 0-terminated, 3-byte pad 725 3, 0, 0, 0, 'f', 'o', 'o', 0}) 726 727 // test 7: empty vtable 728 b = flatbuffers.NewBuilder(0) 729 b.StartObject(0) 730 check([]byte{}) 731 b.EndObject() 732 check([]byte{4, 0, 4, 0, 4, 0, 0, 0}) 733 734 // test 8: vtable with one true bool 735 b = flatbuffers.NewBuilder(0) 736 check([]byte{}) 737 b.StartObject(1) 738 check([]byte{}) 739 b.PrependBoolSlot(0, true, false) 740 b.EndObject() 741 check([]byte{ 742 6, 0, // vtable bytes 743 8, 0, // length of object including vtable offset 744 7, 0, // start of bool value 745 6, 0, 0, 0, // offset for start of vtable (int32) 746 0, 0, 0, // padded to 4 bytes 747 1, // bool value 748 }) 749 750 // test 9: vtable with one default bool 751 b = flatbuffers.NewBuilder(0) 752 check([]byte{}) 753 b.StartObject(1) 754 check([]byte{}) 755 b.PrependBoolSlot(0, false, false) 756 b.EndObject() 757 check([]byte{ 758 4, 0, // vtable bytes 759 4, 0, // end of object from here 760 // entry 1 is zero and not stored. 761 4, 0, 0, 0, // offset for start of vtable (int32) 762 }) 763 764 // test 10: vtable with one int16 765 b = flatbuffers.NewBuilder(0) 766 b.StartObject(1) 767 b.PrependInt16Slot(0, 0x789A, 0) 768 b.EndObject() 769 check([]byte{ 770 6, 0, // vtable bytes 771 8, 0, // end of object from here 772 6, 0, // offset to value 773 6, 0, 0, 0, // offset for start of vtable (int32) 774 0, 0, // padding to 4 bytes 775 0x9A, 0x78, 776 }) 777 778 // test 11: vtable with two int16 779 b = flatbuffers.NewBuilder(0) 780 b.StartObject(2) 781 b.PrependInt16Slot(0, 0x3456, 0) 782 b.PrependInt16Slot(1, 0x789A, 0) 783 b.EndObject() 784 check([]byte{ 785 8, 0, // vtable bytes 786 8, 0, // end of object from here 787 6, 0, // offset to value 0 788 4, 0, // offset to value 1 789 8, 0, 0, 0, // offset for start of vtable (int32) 790 0x9A, 0x78, // value 1 791 0x56, 0x34, // value 0 792 }) 793 794 // test 12: vtable with int16 and bool 795 b = flatbuffers.NewBuilder(0) 796 b.StartObject(2) 797 b.PrependInt16Slot(0, 0x3456, 0) 798 b.PrependBoolSlot(1, true, false) 799 b.EndObject() 800 check([]byte{ 801 8, 0, // vtable bytes 802 8, 0, // end of object from here 803 6, 0, // offset to value 0 804 5, 0, // offset to value 1 805 8, 0, 0, 0, // offset for start of vtable (int32) 806 0, // padding 807 1, // value 1 808 0x56, 0x34, // value 0 809 }) 810 811 // test 12: vtable with empty vector 812 b = flatbuffers.NewBuilder(0) 813 b.StartVector(flatbuffers.SizeByte, 0, 1) 814 vecend := b.EndVector(0) 815 b.StartObject(1) 816 b.PrependUOffsetTSlot(0, vecend, 0) 817 b.EndObject() 818 check([]byte{ 819 6, 0, // vtable bytes 820 8, 0, 821 4, 0, // offset to vector offset 822 6, 0, 0, 0, // offset for start of vtable (int32) 823 4, 0, 0, 0, 824 0, 0, 0, 0, // length of vector (not in struct) 825 }) 826 827 // test 12b: vtable with empty vector of byte and some scalars 828 b = flatbuffers.NewBuilder(0) 829 b.StartVector(flatbuffers.SizeByte, 0, 1) 830 vecend = b.EndVector(0) 831 b.StartObject(2) 832 b.PrependInt16Slot(0, 55, 0) 833 b.PrependUOffsetTSlot(1, vecend, 0) 834 b.EndObject() 835 check([]byte{ 836 8, 0, // vtable bytes 837 12, 0, 838 10, 0, // offset to value 0 839 4, 0, // offset to vector offset 840 8, 0, 0, 0, // vtable loc 841 8, 0, 0, 0, // value 1 842 0, 0, 55, 0, // value 0 843 844 0, 0, 0, 0, // length of vector (not in struct) 845 }) 846 847 // test 13: vtable with 1 int16 and 2-vector of int16 848 b = flatbuffers.NewBuilder(0) 849 b.StartVector(flatbuffers.SizeInt16, 2, 1) 850 b.PrependInt16(0x1234) 851 b.PrependInt16(0x5678) 852 vecend = b.EndVector(2) 853 b.StartObject(2) 854 b.PrependUOffsetTSlot(1, vecend, 0) 855 b.PrependInt16Slot(0, 55, 0) 856 b.EndObject() 857 check([]byte{ 858 8, 0, // vtable bytes 859 12, 0, // length of object 860 6, 0, // start of value 0 from end of vtable 861 8, 0, // start of value 1 from end of buffer 862 8, 0, 0, 0, // offset for start of vtable (int32) 863 0, 0, // padding 864 55, 0, // value 0 865 4, 0, 0, 0, // vector position from here 866 2, 0, 0, 0, // length of vector (uint32) 867 0x78, 0x56, // vector value 1 868 0x34, 0x12, // vector value 0 869 }) 870 871 // test 14: vtable with 1 struct of 1 int8, 1 int16, 1 int32 872 b = flatbuffers.NewBuilder(0) 873 b.StartObject(1) 874 b.Prep(4+4+4, 0) 875 b.PrependInt8(55) 876 b.Pad(3) 877 b.PrependInt16(0x1234) 878 b.Pad(2) 879 b.PrependInt32(0x12345678) 880 structStart := b.Offset() 881 b.PrependStructSlot(0, structStart, 0) 882 b.EndObject() 883 check([]byte{ 884 6, 0, // vtable bytes 885 16, 0, // end of object from here 886 4, 0, // start of struct from here 887 6, 0, 0, 0, // offset for start of vtable (int32) 888 0x78, 0x56, 0x34, 0x12, // value 2 889 0, 0, // padding 890 0x34, 0x12, // value 1 891 0, 0, 0, // padding 892 55, // value 0 893 }) 894 895 // test 15: vtable with 1 vector of 2 struct of 2 int8 896 b = flatbuffers.NewBuilder(0) 897 b.StartVector(flatbuffers.SizeInt8*2, 2, 1) 898 b.PrependInt8(33) 899 b.PrependInt8(44) 900 b.PrependInt8(55) 901 b.PrependInt8(66) 902 vecend = b.EndVector(2) 903 b.StartObject(1) 904 b.PrependUOffsetTSlot(0, vecend, 0) 905 b.EndObject() 906 check([]byte{ 907 6, 0, // vtable bytes 908 8, 0, 909 4, 0, // offset of vector offset 910 6, 0, 0, 0, // offset for start of vtable (int32) 911 4, 0, 0, 0, // vector start offset 912 913 2, 0, 0, 0, // vector length 914 66, // vector value 1,1 915 55, // vector value 1,0 916 44, // vector value 0,1 917 33, // vector value 0,0 918 }) 919 920 // test 16: table with some elements 921 b = flatbuffers.NewBuilder(0) 922 b.StartObject(2) 923 b.PrependInt8Slot(0, 33, 0) 924 b.PrependInt16Slot(1, 66, 0) 925 off := b.EndObject() 926 b.Finish(off) 927 928 check([]byte{ 929 12, 0, 0, 0, // root of table: points to vtable offset 930 931 8, 0, // vtable bytes 932 8, 0, // end of object from here 933 7, 0, // start of value 0 934 4, 0, // start of value 1 935 936 8, 0, 0, 0, // offset for start of vtable (int32) 937 938 66, 0, // value 1 939 0, // padding 940 33, // value 0 941 }) 942 943 // test 17: one unfinished table and one finished table 944 b = flatbuffers.NewBuilder(0) 945 b.StartObject(2) 946 b.PrependInt8Slot(0, 33, 0) 947 b.PrependInt8Slot(1, 44, 0) 948 off = b.EndObject() 949 b.Finish(off) 950 951 b.StartObject(3) 952 b.PrependInt8Slot(0, 55, 0) 953 b.PrependInt8Slot(1, 66, 0) 954 b.PrependInt8Slot(2, 77, 0) 955 off = b.EndObject() 956 b.Finish(off) 957 958 check([]byte{ 959 16, 0, 0, 0, // root of table: points to object 960 0, 0, // padding 961 962 10, 0, // vtable bytes 963 8, 0, // size of object 964 7, 0, // start of value 0 965 6, 0, // start of value 1 966 5, 0, // start of value 2 967 10, 0, 0, 0, // offset for start of vtable (int32) 968 0, // padding 969 77, // value 2 970 66, // value 1 971 55, // value 0 972 973 12, 0, 0, 0, // root of table: points to object 974 975 8, 0, // vtable bytes 976 8, 0, // size of object 977 7, 0, // start of value 0 978 6, 0, // start of value 1 979 8, 0, 0, 0, // offset for start of vtable (int32) 980 0, 0, // padding 981 44, // value 1 982 33, // value 0 983 }) 984 985 // test 18: a bunch of bools 986 b = flatbuffers.NewBuilder(0) 987 b.StartObject(8) 988 b.PrependBoolSlot(0, true, false) 989 b.PrependBoolSlot(1, true, false) 990 b.PrependBoolSlot(2, true, false) 991 b.PrependBoolSlot(3, true, false) 992 b.PrependBoolSlot(4, true, false) 993 b.PrependBoolSlot(5, true, false) 994 b.PrependBoolSlot(6, true, false) 995 b.PrependBoolSlot(7, true, false) 996 off = b.EndObject() 997 b.Finish(off) 998 999 check([]byte{ 1000 24, 0, 0, 0, // root of table: points to vtable offset 1001 1002 20, 0, // vtable bytes 1003 12, 0, // size of object 1004 11, 0, // start of value 0 1005 10, 0, // start of value 1 1006 9, 0, // start of value 2 1007 8, 0, // start of value 3 1008 7, 0, // start of value 4 1009 6, 0, // start of value 5 1010 5, 0, // start of value 6 1011 4, 0, // start of value 7 1012 20, 0, 0, 0, // vtable offset 1013 1014 1, // value 7 1015 1, // value 6 1016 1, // value 5 1017 1, // value 4 1018 1, // value 3 1019 1, // value 2 1020 1, // value 1 1021 1, // value 0 1022 }) 1023 1024 // test 19: three bools 1025 b = flatbuffers.NewBuilder(0) 1026 b.StartObject(3) 1027 b.PrependBoolSlot(0, true, false) 1028 b.PrependBoolSlot(1, true, false) 1029 b.PrependBoolSlot(2, true, false) 1030 off = b.EndObject() 1031 b.Finish(off) 1032 1033 check([]byte{ 1034 16, 0, 0, 0, // root of table: points to vtable offset 1035 1036 0, 0, // padding 1037 1038 10, 0, // vtable bytes 1039 8, 0, // size of object 1040 7, 0, // start of value 0 1041 6, 0, // start of value 1 1042 5, 0, // start of value 2 1043 10, 0, 0, 0, // vtable offset from here 1044 1045 0, // padding 1046 1, // value 2 1047 1, // value 1 1048 1, // value 0 1049 }) 1050 1051 // test 20: some floats 1052 b = flatbuffers.NewBuilder(0) 1053 b.StartObject(1) 1054 b.PrependFloat32Slot(0, 1.0, 0.0) 1055 off = b.EndObject() 1056 1057 check([]byte{ 1058 6, 0, // vtable bytes 1059 8, 0, // size of object 1060 4, 0, // start of value 0 1061 6, 0, 0, 0, // vtable offset 1062 1063 0, 0, 128, 63, // value 0 1064 }) 1065} 1066 1067// CheckManualBuild builds a Monster manually. 1068func CheckManualBuild(fail func(string, ...interface{})) ([]byte, flatbuffers.UOffsetT) { 1069 b := flatbuffers.NewBuilder(0) 1070 str := b.CreateString("MyMonster") 1071 1072 b.StartVector(1, 5, 1) 1073 b.PrependByte(4) 1074 b.PrependByte(3) 1075 b.PrependByte(2) 1076 b.PrependByte(1) 1077 b.PrependByte(0) 1078 inv := b.EndVector(5) 1079 1080 b.StartObject(13) 1081 b.PrependInt16Slot(2, 20, 100) 1082 mon2 := b.EndObject() 1083 1084 // Test4Vector 1085 b.StartVector(4, 2, 1) 1086 1087 // Test 0 1088 b.Prep(2, 4) 1089 b.Pad(1) 1090 b.PlaceInt8(20) 1091 b.PlaceInt16(10) 1092 1093 // Test 1 1094 b.Prep(2, 4) 1095 b.Pad(1) 1096 b.PlaceInt8(40) 1097 b.PlaceInt16(30) 1098 1099 // end testvector 1100 test4 := b.EndVector(2) 1101 1102 b.StartObject(13) 1103 1104 // a vec3 1105 b.Prep(16, 32) 1106 b.Pad(2) 1107 b.Prep(2, 4) 1108 b.Pad(1) 1109 b.PlaceByte(6) 1110 b.PlaceInt16(5) 1111 b.Pad(1) 1112 b.PlaceByte(4) 1113 b.PlaceFloat64(3.0) 1114 b.Pad(4) 1115 b.PlaceFloat32(3.0) 1116 b.PlaceFloat32(2.0) 1117 b.PlaceFloat32(1.0) 1118 vec3Loc := b.Offset() 1119 // end vec3 1120 1121 b.PrependStructSlot(0, vec3Loc, 0) // vec3. noop 1122 b.PrependInt16Slot(2, 80, 100) // hp 1123 b.PrependUOffsetTSlot(3, str, 0) 1124 b.PrependUOffsetTSlot(5, inv, 0) // inventory 1125 b.PrependByteSlot(7, 1, 0) 1126 b.PrependUOffsetTSlot(8, mon2, 0) 1127 b.PrependUOffsetTSlot(9, test4, 0) 1128 mon := b.EndObject() 1129 1130 b.Finish(mon) 1131 1132 return b.Bytes, b.Head() 1133} 1134 1135func CheckGetRootAsForNonRootTable(fail func(string, ...interface{})) { 1136 b := flatbuffers.NewBuilder(0) 1137 str := b.CreateString("MyStat") 1138 example.StatStart(b) 1139 example.StatAddId(b, str) 1140 example.StatAddVal(b, 12345678) 1141 example.StatAddCount(b, 12345) 1142 stat_end := example.StatEnd(b) 1143 b.Finish(stat_end) 1144 1145 stat := example.GetRootAsStat(b.Bytes, b.Head()) 1146 1147 if got := stat.Id(); !bytes.Equal([]byte("MyStat"), got) { 1148 fail(FailString("stat.Id()", "MyStat", got)) 1149 } 1150 1151 if got := stat.Val(); 12345678 != got { 1152 fail(FailString("stat.Val()", 12345678, got)) 1153 } 1154 1155 if got := stat.Count(); 12345 != got { 1156 fail(FailString("stat.Count()", 12345, got)) 1157 } 1158} 1159 1160// CheckGeneratedBuild uses generated code to build the example Monster. 1161func CheckGeneratedBuild(fail func(string, ...interface{})) ([]byte, flatbuffers.UOffsetT) { 1162 b := flatbuffers.NewBuilder(0) 1163 str := b.CreateString("MyMonster") 1164 test1 := b.CreateString("test1") 1165 test2 := b.CreateString("test2") 1166 fred := b.CreateString("Fred") 1167 1168 example.MonsterStartInventoryVector(b, 5) 1169 b.PrependByte(4) 1170 b.PrependByte(3) 1171 b.PrependByte(2) 1172 b.PrependByte(1) 1173 b.PrependByte(0) 1174 inv := b.EndVector(5) 1175 1176 example.MonsterStart(b) 1177 example.MonsterAddName(b, fred) 1178 mon2 := example.MonsterEnd(b) 1179 1180 example.MonsterStartTest4Vector(b, 2) 1181 example.CreateTest(b, 10, 20) 1182 example.CreateTest(b, 30, 40) 1183 test4 := b.EndVector(2) 1184 1185 example.MonsterStartTestarrayofstringVector(b, 2) 1186 b.PrependUOffsetT(test2) 1187 b.PrependUOffsetT(test1) 1188 testArrayOfString := b.EndVector(2) 1189 1190 example.MonsterStart(b) 1191 1192 pos := example.CreateVec3(b, 1.0, 2.0, 3.0, 3.0, example.ColorGreen, 5, 6) 1193 example.MonsterAddPos(b, pos) 1194 1195 example.MonsterAddHp(b, 80) 1196 example.MonsterAddName(b, str) 1197 example.MonsterAddTestbool(b, true) 1198 example.MonsterAddInventory(b, inv) 1199 example.MonsterAddTestType(b, 1) 1200 example.MonsterAddTest(b, mon2) 1201 example.MonsterAddTest4(b, test4) 1202 example.MonsterAddTestarrayofstring(b, testArrayOfString) 1203 mon := example.MonsterEnd(b) 1204 1205 b.Finish(mon) 1206 1207 return b.Bytes, b.Head() 1208} 1209 1210// CheckTableAccessors checks that the table accessors work as expected. 1211func CheckTableAccessors(fail func(string, ...interface{})) { 1212 // test struct accessor 1213 b := flatbuffers.NewBuilder(0) 1214 pos := example.CreateVec3(b, 1.0, 2.0, 3.0, 3.0, 4, 5, 6) 1215 b.Finish(pos) 1216 vec3Bytes := b.FinishedBytes() 1217 vec3 := &example.Vec3{} 1218 flatbuffers.GetRootAs(vec3Bytes, 0, vec3) 1219 1220 if bytes.Compare(vec3Bytes, vec3.Table().Bytes) != 0 { 1221 fail("invalid vec3 table") 1222 } 1223 1224 // test table accessor 1225 b = flatbuffers.NewBuilder(0) 1226 str := b.CreateString("MyStat") 1227 example.StatStart(b) 1228 example.StatAddId(b, str) 1229 example.StatAddVal(b, 12345678) 1230 example.StatAddCount(b, 12345) 1231 pos = example.StatEnd(b) 1232 b.Finish(pos) 1233 statBytes := b.FinishedBytes() 1234 stat := &example.Stat{} 1235 flatbuffers.GetRootAs(statBytes, 0, stat) 1236 1237 if bytes.Compare(statBytes, stat.Table().Bytes) != 0 { 1238 fail("invalid stat table") 1239 } 1240} 1241 1242// CheckVtableDeduplication verifies that vtables are deduplicated. 1243func CheckVtableDeduplication(fail func(string, ...interface{})) { 1244 b := flatbuffers.NewBuilder(0) 1245 1246 b.StartObject(4) 1247 b.PrependByteSlot(0, 0, 0) 1248 b.PrependByteSlot(1, 11, 0) 1249 b.PrependByteSlot(2, 22, 0) 1250 b.PrependInt16Slot(3, 33, 0) 1251 obj0 := b.EndObject() 1252 1253 b.StartObject(4) 1254 b.PrependByteSlot(0, 0, 0) 1255 b.PrependByteSlot(1, 44, 0) 1256 b.PrependByteSlot(2, 55, 0) 1257 b.PrependInt16Slot(3, 66, 0) 1258 obj1 := b.EndObject() 1259 1260 b.StartObject(4) 1261 b.PrependByteSlot(0, 0, 0) 1262 b.PrependByteSlot(1, 77, 0) 1263 b.PrependByteSlot(2, 88, 0) 1264 b.PrependInt16Slot(3, 99, 0) 1265 obj2 := b.EndObject() 1266 1267 got := b.Bytes[b.Head():] 1268 1269 want := []byte{ 1270 240, 255, 255, 255, // == -12. offset to dedupped vtable. 1271 99, 0, 1272 88, 1273 77, 1274 248, 255, 255, 255, // == -8. offset to dedupped vtable. 1275 66, 0, 1276 55, 1277 44, 1278 12, 0, 1279 8, 0, 1280 0, 0, 1281 7, 0, 1282 6, 0, 1283 4, 0, 1284 12, 0, 0, 0, 1285 33, 0, 1286 22, 1287 11, 1288 } 1289 1290 if !bytes.Equal(want, got) { 1291 fail("testVtableDeduplication want:\n%d %v\nbut got:\n%d %v\n", 1292 len(want), want, len(got), got) 1293 } 1294 1295 table0 := &flatbuffers.Table{Bytes: b.Bytes, Pos: flatbuffers.UOffsetT(len(b.Bytes)) - obj0} 1296 table1 := &flatbuffers.Table{Bytes: b.Bytes, Pos: flatbuffers.UOffsetT(len(b.Bytes)) - obj1} 1297 table2 := &flatbuffers.Table{Bytes: b.Bytes, Pos: flatbuffers.UOffsetT(len(b.Bytes)) - obj2} 1298 1299 testTable := func(tab *flatbuffers.Table, a flatbuffers.VOffsetT, b, c, d byte) { 1300 // vtable size 1301 if got := tab.GetVOffsetTSlot(0, 0); 12 != got { 1302 fail("failed 0, 0: %d", got) 1303 } 1304 // object size 1305 if got := tab.GetVOffsetTSlot(2, 0); 8 != got { 1306 fail("failed 2, 0: %d", got) 1307 } 1308 // default value 1309 if got := tab.GetVOffsetTSlot(4, 0); a != got { 1310 fail("failed 4, 0: %d", got) 1311 } 1312 if got := tab.GetByteSlot(6, 0); b != got { 1313 fail("failed 6, 0: %d", got) 1314 } 1315 if val := tab.GetByteSlot(8, 0); c != val { 1316 fail("failed 8, 0: %d", got) 1317 } 1318 if got := tab.GetByteSlot(10, 0); d != got { 1319 fail("failed 10, 0: %d", got) 1320 } 1321 } 1322 1323 testTable(table0, 0, 11, 22, 33) 1324 testTable(table1, 0, 44, 55, 66) 1325 testTable(table2, 0, 77, 88, 99) 1326} 1327 1328// CheckNotInObjectError verifies that `EndObject` fails if not inside an 1329// object. 1330func CheckNotInObjectError(fail func(string, ...interface{})) { 1331 b := flatbuffers.NewBuilder(0) 1332 1333 defer func() { 1334 r := recover() 1335 if r == nil { 1336 fail("expected panic in CheckNotInObjectError") 1337 } 1338 }() 1339 b.EndObject() 1340} 1341 1342// CheckStringIsNestedError verifies that a string can not be created inside 1343// another object. 1344func CheckStringIsNestedError(fail func(string, ...interface{})) { 1345 b := flatbuffers.NewBuilder(0) 1346 b.StartObject(0) 1347 defer func() { 1348 r := recover() 1349 if r == nil { 1350 fail("expected panic in CheckStringIsNestedError") 1351 } 1352 }() 1353 b.CreateString("foo") 1354} 1355 1356// CheckByteStringIsNestedError verifies that a bytestring can not be created 1357// inside another object. 1358func CheckByteStringIsNestedError(fail func(string, ...interface{})) { 1359 b := flatbuffers.NewBuilder(0) 1360 b.StartObject(0) 1361 defer func() { 1362 r := recover() 1363 if r == nil { 1364 fail("expected panic in CheckByteStringIsNestedError") 1365 } 1366 }() 1367 b.CreateByteString([]byte("foo")) 1368} 1369 1370// CheckStructIsNotInlineError verifies that writing a struct in a location 1371// away from where it is used will cause a panic. 1372func CheckStructIsNotInlineError(fail func(string, ...interface{})) { 1373 b := flatbuffers.NewBuilder(0) 1374 b.StartObject(0) 1375 defer func() { 1376 r := recover() 1377 if r == nil { 1378 fail("expected panic in CheckStructIsNotInlineError") 1379 } 1380 }() 1381 b.PrependStructSlot(0, 1, 0) 1382} 1383 1384// CheckFinishedBytesError verifies that `FinishedBytes` panics if the table 1385// is not finished. 1386func CheckFinishedBytesError(fail func(string, ...interface{})) { 1387 b := flatbuffers.NewBuilder(0) 1388 1389 defer func() { 1390 r := recover() 1391 if r == nil { 1392 fail("expected panic in CheckFinishedBytesError") 1393 } 1394 }() 1395 b.FinishedBytes() 1396} 1397 1398// CheckEnumNames checks that the generated enum names are correct. 1399func CheckEnumNames(fail func(string, ...interface{})) { 1400 { 1401 want := map[example.Any]string{ 1402 example.AnyNONE: "NONE", 1403 example.AnyMonster: "Monster", 1404 example.AnyTestSimpleTableWithEnum: "TestSimpleTableWithEnum", 1405 example.AnyMyGame_Example2_Monster: "MyGame_Example2_Monster", 1406 } 1407 got := example.EnumNamesAny 1408 if !reflect.DeepEqual(got, want) { 1409 fail("enum name is not equal") 1410 } 1411 } 1412 { 1413 want := map[example.Color]string{ 1414 example.ColorRed: "Red", 1415 example.ColorGreen: "Green", 1416 example.ColorBlue: "Blue", 1417 } 1418 got := example.EnumNamesColor 1419 if !reflect.DeepEqual(got, want) { 1420 fail("enum name is not equal") 1421 } 1422 } 1423} 1424 1425// CheckEnumString checks the String method on generated enum types. 1426func CheckEnumString(fail func(string, ...interface{})) { 1427 if got := example.AnyMonster.String(); got != "Monster" { 1428 fail("Monster.String: %q != %q", got, "Monster") 1429 } 1430 if got := fmt.Sprintf("color: %s", example.ColorGreen); got != "color: Green" { 1431 fail("color.String: %q != %q", got, "color: Green") 1432 } 1433} 1434 1435// CheckEnumValues checks that the generated enum values maps are correct. 1436func CheckEnumValues(fail func(string, ...interface{})) { 1437 { 1438 want := map[string]example.Any{ 1439 "NONE": example.AnyNONE, 1440 "Monster": example.AnyMonster, 1441 "TestSimpleTableWithEnum": example.AnyTestSimpleTableWithEnum, 1442 "MyGame_Example2_Monster": example.AnyMyGame_Example2_Monster, 1443 } 1444 got := example.EnumValuesAny 1445 if !reflect.DeepEqual(got, want) { 1446 fail("enum name is not equal") 1447 } 1448 } 1449 { 1450 want := map[string]example.Color{ 1451 "Red": example.ColorRed, 1452 "Green": example.ColorGreen, 1453 "Blue": example.ColorBlue, 1454 } 1455 got := example.EnumValuesColor 1456 if !reflect.DeepEqual(got, want) { 1457 fail("enum name is not equal") 1458 } 1459 } 1460} 1461 1462// CheckDocExample checks that the code given in FlatBuffers documentation 1463// is syntactically correct. 1464func CheckDocExample(buf []byte, off flatbuffers.UOffsetT, fail func(string, ...interface{})) { 1465 monster := example.GetRootAsMonster(buf, off) 1466 _ = monster.Hp() 1467 _ = monster.Pos(nil) 1468 for i := 0; i < monster.InventoryLength(); i++ { 1469 _ = monster.Inventory(i) // do something here 1470 } 1471 1472 builder := flatbuffers.NewBuilder(0) 1473 1474 example.MonsterStartInventoryVector(builder, 5) 1475 for i := 4; i >= 0; i-- { 1476 builder.PrependByte(byte(i)) 1477 } 1478 inv := builder.EndVector(5) 1479 1480 str := builder.CreateString("MyMonster") 1481 example.MonsterStart(builder) 1482 example.MonsterAddPos(builder, example.CreateVec3(builder, 1.0, 2.0, 3.0, 3.0, example.Color(4), 5, 6)) 1483 example.MonsterAddHp(builder, 80) 1484 example.MonsterAddName(builder, str) 1485 example.MonsterAddInventory(builder, inv) 1486 example.MonsterAddTestType(builder, 1) 1487 example.MonsterAddColor(builder, example.ColorRed) 1488 // example.MonsterAddTest(builder, mon2) 1489 // example.MonsterAddTest4(builder, test4s) 1490 _ = example.MonsterEnd(builder) 1491} 1492 1493func CheckCreateByteVector(fail func(string, ...interface{})) { 1494 raw := [30]byte{} 1495 for i := 0; i < len(raw); i++ { 1496 raw[i] = byte(i) 1497 } 1498 1499 for size := 0; size < len(raw); size++ { 1500 b1 := flatbuffers.NewBuilder(0) 1501 b2 := flatbuffers.NewBuilder(0) 1502 b1.StartVector(1, size, 1) 1503 for i := size - 1; i >= 0; i-- { 1504 b1.PrependByte(raw[i]) 1505 } 1506 b1.EndVector(size) 1507 b2.CreateByteVector(raw[:size]) 1508 CheckByteEquality(b1.Bytes, b2.Bytes, fail) 1509 } 1510} 1511 1512func CheckParentNamespace(fail func(string, ...interface{})) { 1513 var empty, nonempty []byte 1514 1515 // create monster with an empty parent namespace field 1516 { 1517 builder := flatbuffers.NewBuilder(0) 1518 1519 example.MonsterStart(builder) 1520 m := example.MonsterEnd(builder) 1521 builder.Finish(m) 1522 1523 empty = make([]byte, len(builder.FinishedBytes())) 1524 copy(empty, builder.FinishedBytes()) 1525 } 1526 1527 // create monster with a non-empty parent namespace field 1528 { 1529 builder := flatbuffers.NewBuilder(0) 1530 mygame.InParentNamespaceStart(builder) 1531 pn := mygame.InParentNamespaceEnd(builder) 1532 1533 example.MonsterStart(builder) 1534 example.MonsterAddParentNamespaceTest(builder, pn) 1535 m := example.MonsterEnd(builder) 1536 1537 builder.Finish(m) 1538 1539 nonempty = make([]byte, len(builder.FinishedBytes())) 1540 copy(nonempty, builder.FinishedBytes()) 1541 } 1542 1543 // read monster with empty parent namespace field 1544 { 1545 m := example.GetRootAsMonster(empty, 0) 1546 if m.ParentNamespaceTest(nil) != nil { 1547 fail("expected nil ParentNamespaceTest for empty field") 1548 } 1549 } 1550 1551 // read monster with non-empty parent namespace field 1552 { 1553 m := example.GetRootAsMonster(nonempty, 0) 1554 if m.ParentNamespaceTest(nil) == nil { 1555 fail("expected non-nil ParentNamespaceTest for non-empty field") 1556 } 1557 } 1558} 1559 1560// Include simple random number generator to ensure results will be the 1561// same cross platform. 1562// http://en.wikipedia.org/wiki/Park%E2%80%93Miller_random_number_generator 1563type LCG uint32 1564 1565const InitialLCGSeed = 48271 1566 1567func NewLCG() *LCG { 1568 n := uint32(InitialLCGSeed) 1569 l := LCG(n) 1570 return &l 1571} 1572 1573func (lcg *LCG) Reset() { 1574 *lcg = InitialLCGSeed 1575} 1576 1577func (lcg *LCG) Next() uint32 { 1578 n := uint32((uint64(*lcg) * uint64(279470273)) % uint64(4294967291)) 1579 *lcg = LCG(n) 1580 return n 1581} 1582 1583// CheckByteEquality verifies that two byte buffers are the same. 1584func CheckByteEquality(a, b []byte, fail func(string, ...interface{})) { 1585 if !bytes.Equal(a, b) { 1586 fail("objects are not byte-wise equal") 1587 } 1588} 1589 1590// CheckMutateMethods checks all mutate methods one by one 1591func CheckMutateMethods(fail func(string, ...interface{})) { 1592 b := flatbuffers.NewBuilder(0) 1593 b.StartObject(15) 1594 b.PrependBoolSlot(0, true, false) 1595 b.PrependByteSlot(1, 1, 0) 1596 b.PrependUint8Slot(2, 2, 0) 1597 b.PrependUint16Slot(3, 3, 0) 1598 b.PrependUint32Slot(4, 4, 0) 1599 b.PrependUint64Slot(5, 5, 0) 1600 b.PrependInt8Slot(6, 6, 0) 1601 b.PrependInt16Slot(7, 7, 0) 1602 b.PrependInt32Slot(8, 8, 0) 1603 b.PrependInt64Slot(9, 9, 0) 1604 b.PrependFloat32Slot(10, 10, 0) 1605 b.PrependFloat64Slot(11, 11, 0) 1606 1607 b.PrependUOffsetTSlot(12, 12, 0) 1608 uoVal := b.Offset() - 12 1609 1610 b.PrependVOffsetT(13) 1611 b.Slot(13) 1612 1613 b.PrependSOffsetT(14) 1614 b.Slot(14) 1615 soVal := flatbuffers.SOffsetT(b.Offset() - 14) 1616 1617 offset := b.EndObject() 1618 1619 t := &flatbuffers.Table{ 1620 Bytes: b.Bytes, 1621 Pos: flatbuffers.UOffsetT(len(b.Bytes)) - offset, 1622 } 1623 1624 calcVOffsetT := func(slot int) (vtableOffset flatbuffers.VOffsetT) { 1625 return flatbuffers.VOffsetT((flatbuffers.VtableMetadataFields + slot) * flatbuffers.SizeVOffsetT) 1626 } 1627 calcUOffsetT := func(vtableOffset flatbuffers.VOffsetT) (valueOffset flatbuffers.UOffsetT) { 1628 return t.Pos + flatbuffers.UOffsetT(t.Offset(vtableOffset)) 1629 } 1630 1631 type testcase struct { 1632 field string 1633 testfn func() bool 1634 } 1635 1636 testForOriginalValues := []testcase{ 1637 testcase{"BoolSlot", func() bool { return t.GetBoolSlot(calcVOffsetT(0), true) == true }}, 1638 testcase{"ByteSlot", func() bool { return t.GetByteSlot(calcVOffsetT(1), 1) == 1 }}, 1639 testcase{"Uint8Slot", func() bool { return t.GetUint8Slot(calcVOffsetT(2), 2) == 2 }}, 1640 testcase{"Uint16Slot", func() bool { return t.GetUint16Slot(calcVOffsetT(3), 3) == 3 }}, 1641 testcase{"Uint32Slot", func() bool { return t.GetUint32Slot(calcVOffsetT(4), 4) == 4 }}, 1642 testcase{"Uint64Slot", func() bool { return t.GetUint64Slot(calcVOffsetT(5), 5) == 5 }}, 1643 testcase{"Int8Slot", func() bool { return t.GetInt8Slot(calcVOffsetT(6), 6) == 6 }}, 1644 testcase{"Int16Slot", func() bool { return t.GetInt16Slot(calcVOffsetT(7), 7) == 7 }}, 1645 testcase{"Int32Slot", func() bool { return t.GetInt32Slot(calcVOffsetT(8), 8) == 8 }}, 1646 testcase{"Int64Slot", func() bool { return t.GetInt64Slot(calcVOffsetT(9), 9) == 9 }}, 1647 testcase{"Float32Slot", func() bool { return t.GetFloat32Slot(calcVOffsetT(10), 10) == 10 }}, 1648 testcase{"Float64Slot", func() bool { return t.GetFloat64Slot(calcVOffsetT(11), 11) == 11 }}, 1649 testcase{"UOffsetTSlot", func() bool { return t.GetUOffsetT(calcUOffsetT(calcVOffsetT(12))) == uoVal }}, 1650 testcase{"VOffsetTSlot", func() bool { return t.GetVOffsetT(calcUOffsetT(calcVOffsetT(13))) == 13 }}, 1651 testcase{"SOffsetTSlot", func() bool { return t.GetSOffsetT(calcUOffsetT(calcVOffsetT(14))) == soVal }}, 1652 } 1653 1654 testMutability := []testcase{ 1655 testcase{"BoolSlot", func() bool { return t.MutateBoolSlot(calcVOffsetT(0), false) }}, 1656 testcase{"ByteSlot", func() bool { return t.MutateByteSlot(calcVOffsetT(1), 2) }}, 1657 testcase{"Uint8Slot", func() bool { return t.MutateUint8Slot(calcVOffsetT(2), 4) }}, 1658 testcase{"Uint16Slot", func() bool { return t.MutateUint16Slot(calcVOffsetT(3), 6) }}, 1659 testcase{"Uint32Slot", func() bool { return t.MutateUint32Slot(calcVOffsetT(4), 8) }}, 1660 testcase{"Uint64Slot", func() bool { return t.MutateUint64Slot(calcVOffsetT(5), 10) }}, 1661 testcase{"Int8Slot", func() bool { return t.MutateInt8Slot(calcVOffsetT(6), 12) }}, 1662 testcase{"Int16Slot", func() bool { return t.MutateInt16Slot(calcVOffsetT(7), 14) }}, 1663 testcase{"Int32Slot", func() bool { return t.MutateInt32Slot(calcVOffsetT(8), 16) }}, 1664 testcase{"Int64Slot", func() bool { return t.MutateInt64Slot(calcVOffsetT(9), 18) }}, 1665 testcase{"Float32Slot", func() bool { return t.MutateFloat32Slot(calcVOffsetT(10), 20) }}, 1666 testcase{"Float64Slot", func() bool { return t.MutateFloat64Slot(calcVOffsetT(11), 22) }}, 1667 testcase{"UOffsetTSlot", func() bool { return t.MutateUOffsetT(calcUOffsetT(calcVOffsetT(12)), 24) }}, 1668 testcase{"VOffsetTSlot", func() bool { return t.MutateVOffsetT(calcUOffsetT(calcVOffsetT(13)), 26) }}, 1669 testcase{"SOffsetTSlot", func() bool { return t.MutateSOffsetT(calcUOffsetT(calcVOffsetT(14)), 28) }}, 1670 } 1671 1672 testMutabilityWithoutSlot := []testcase{ 1673 testcase{"BoolSlot", func() bool { return t.MutateBoolSlot(calcVOffsetT(16), false) }}, 1674 testcase{"ByteSlot", func() bool { return t.MutateByteSlot(calcVOffsetT(16), 2) }}, 1675 testcase{"Uint8Slot", func() bool { return t.MutateUint8Slot(calcVOffsetT(16), 2) }}, 1676 testcase{"Uint16Slot", func() bool { return t.MutateUint16Slot(calcVOffsetT(16), 2) }}, 1677 testcase{"Uint32Slot", func() bool { return t.MutateUint32Slot(calcVOffsetT(16), 2) }}, 1678 testcase{"Uint64Slot", func() bool { return t.MutateUint64Slot(calcVOffsetT(16), 2) }}, 1679 testcase{"Int8Slot", func() bool { return t.MutateInt8Slot(calcVOffsetT(16), 2) }}, 1680 testcase{"Int16Slot", func() bool { return t.MutateInt16Slot(calcVOffsetT(16), 2) }}, 1681 testcase{"Int32Slot", func() bool { return t.MutateInt32Slot(calcVOffsetT(16), 2) }}, 1682 testcase{"Int64Slot", func() bool { return t.MutateInt64Slot(calcVOffsetT(16), 2) }}, 1683 testcase{"Float32Slot", func() bool { return t.MutateFloat32Slot(calcVOffsetT(16), 2) }}, 1684 testcase{"Float64Slot", func() bool { return t.MutateFloat64Slot(calcVOffsetT(16), 2) }}, 1685 } 1686 1687 testForMutatedValues := []testcase{ 1688 testcase{"BoolSlot", func() bool { return t.GetBoolSlot(calcVOffsetT(0), true) == false }}, 1689 testcase{"ByteSlot", func() bool { return t.GetByteSlot(calcVOffsetT(1), 1) == 2 }}, 1690 testcase{"Uint8Slot", func() bool { return t.GetUint8Slot(calcVOffsetT(2), 1) == 4 }}, 1691 testcase{"Uint16Slot", func() bool { return t.GetUint16Slot(calcVOffsetT(3), 1) == 6 }}, 1692 testcase{"Uint32Slot", func() bool { return t.GetUint32Slot(calcVOffsetT(4), 1) == 8 }}, 1693 testcase{"Uint64Slot", func() bool { return t.GetUint64Slot(calcVOffsetT(5), 1) == 10 }}, 1694 testcase{"Int8Slot", func() bool { return t.GetInt8Slot(calcVOffsetT(6), 1) == 12 }}, 1695 testcase{"Int16Slot", func() bool { return t.GetInt16Slot(calcVOffsetT(7), 1) == 14 }}, 1696 testcase{"Int32Slot", func() bool { return t.GetInt32Slot(calcVOffsetT(8), 1) == 16 }}, 1697 testcase{"Int64Slot", func() bool { return t.GetInt64Slot(calcVOffsetT(9), 1) == 18 }}, 1698 testcase{"Float32Slot", func() bool { return t.GetFloat32Slot(calcVOffsetT(10), 1) == 20 }}, 1699 testcase{"Float64Slot", func() bool { return t.GetFloat64Slot(calcVOffsetT(11), 1) == 22 }}, 1700 testcase{"UOffsetTSlot", func() bool { return t.GetUOffsetT(calcUOffsetT(calcVOffsetT(12))) == 24 }}, 1701 testcase{"VOffsetTSlot", func() bool { return t.GetVOffsetT(calcUOffsetT(calcVOffsetT(13))) == 26 }}, 1702 testcase{"SOffsetTSlot", func() bool { return t.GetSOffsetT(calcUOffsetT(calcVOffsetT(14))) == 28 }}, 1703 } 1704 1705 // make sure original values are okay 1706 for _, t := range testForOriginalValues { 1707 if !t.testfn() { 1708 fail(t.field + "' field doesn't have the expected original value") 1709 } 1710 } 1711 1712 // try to mutate fields and check mutability 1713 for _, t := range testMutability { 1714 if !t.testfn() { 1715 fail(FailString(t.field+"' field failed mutability test", "passed", "failed")) 1716 } 1717 } 1718 1719 // try to mutate fields and check mutability 1720 // these have wrong slots so should fail 1721 for _, t := range testMutabilityWithoutSlot { 1722 if t.testfn() { 1723 fail(FailString(t.field+"' field failed no slot mutability test", "failed", "passed")) 1724 } 1725 } 1726 1727 // test whether values have changed 1728 for _, t := range testForMutatedValues { 1729 if !t.testfn() { 1730 fail(t.field + "' field doesn't have the expected mutated value") 1731 } 1732 } 1733} 1734 1735// BenchmarkVtableDeduplication measures the speed of vtable deduplication 1736// by creating prePop vtables, then populating b.N objects with a 1737// different single vtable. 1738// 1739// When b.N is large (as in long benchmarks), memory usage may be high. 1740func BenchmarkVtableDeduplication(b *testing.B) { 1741 prePop := 10 1742 builder := flatbuffers.NewBuilder(0) 1743 1744 // pre-populate some vtables: 1745 for i := 0; i < prePop; i++ { 1746 builder.StartObject(i) 1747 for j := 0; j < i; j++ { 1748 builder.PrependInt16Slot(j, int16(j), 0) 1749 } 1750 builder.EndObject() 1751 } 1752 1753 // benchmark deduplication of a new vtable: 1754 b.ResetTimer() 1755 for i := 0; i < b.N; i++ { 1756 lim := prePop 1757 1758 builder.StartObject(lim) 1759 for j := 0; j < lim; j++ { 1760 builder.PrependInt16Slot(j, int16(j), 0) 1761 } 1762 builder.EndObject() 1763 } 1764} 1765 1766// BenchmarkParseGold measures the speed of parsing the 'gold' data 1767// used throughout this test suite. 1768func BenchmarkParseGold(b *testing.B) { 1769 buf, offset := CheckGeneratedBuild(b.Fatalf) 1770 monster := example.GetRootAsMonster(buf, offset) 1771 1772 // use these to prevent allocations: 1773 reuse_pos := example.Vec3{} 1774 reuse_test3 := example.Test{} 1775 reuse_table2 := flatbuffers.Table{} 1776 reuse_monster2 := example.Monster{} 1777 reuse_test4_0 := example.Test{} 1778 reuse_test4_1 := example.Test{} 1779 1780 b.SetBytes(int64(len(buf[offset:]))) 1781 b.ReportAllocs() 1782 b.ResetTimer() 1783 for i := 0; i < b.N; i++ { 1784 monster.Hp() 1785 monster.Mana() 1786 name := monster.Name() 1787 _ = name[0] 1788 _ = name[len(name)-1] 1789 1790 monster.Pos(&reuse_pos) 1791 reuse_pos.X() 1792 reuse_pos.Y() 1793 reuse_pos.Z() 1794 reuse_pos.Test1() 1795 reuse_pos.Test2() 1796 reuse_pos.Test3(&reuse_test3) 1797 reuse_test3.A() 1798 reuse_test3.B() 1799 monster.TestType() 1800 monster.Test(&reuse_table2) 1801 reuse_monster2.Init(reuse_table2.Bytes, reuse_table2.Pos) 1802 name2 := reuse_monster2.Name() 1803 _ = name2[0] 1804 _ = name2[len(name2)-1] 1805 monster.InventoryLength() 1806 l := monster.InventoryLength() 1807 for i := 0; i < l; i++ { 1808 monster.Inventory(i) 1809 } 1810 monster.Test4Length() 1811 monster.Test4(&reuse_test4_0, 0) 1812 monster.Test4(&reuse_test4_1, 1) 1813 1814 reuse_test4_0.A() 1815 reuse_test4_0.B() 1816 reuse_test4_1.A() 1817 reuse_test4_1.B() 1818 1819 monster.TestarrayofstringLength() 1820 str0 := monster.Testarrayofstring(0) 1821 _ = str0[0] 1822 _ = str0[len(str0)-1] 1823 str1 := monster.Testarrayofstring(1) 1824 _ = str1[0] 1825 _ = str1[len(str1)-1] 1826 } 1827} 1828 1829// BenchmarkBuildGold uses generated code to build the example Monster. 1830func BenchmarkBuildGold(b *testing.B) { 1831 buf, offset := CheckGeneratedBuild(b.Fatalf) 1832 bytes_length := int64(len(buf[offset:])) 1833 1834 reuse_str := "MyMonster" 1835 reuse_test1 := "test1" 1836 reuse_test2 := "test2" 1837 reuse_fred := "Fred" 1838 1839 b.SetBytes(bytes_length) 1840 bldr := flatbuffers.NewBuilder(0) 1841 b.ResetTimer() 1842 b.ReportAllocs() 1843 for i := 0; i < b.N; i++ { 1844 bldr.Reset() 1845 1846 str := bldr.CreateString(reuse_str) 1847 test1 := bldr.CreateString(reuse_test1) 1848 test2 := bldr.CreateString(reuse_test2) 1849 fred := bldr.CreateString(reuse_fred) 1850 1851 example.MonsterStartInventoryVector(bldr, 5) 1852 bldr.PrependByte(4) 1853 bldr.PrependByte(3) 1854 bldr.PrependByte(2) 1855 bldr.PrependByte(1) 1856 bldr.PrependByte(0) 1857 inv := bldr.EndVector(5) 1858 1859 example.MonsterStart(bldr) 1860 example.MonsterAddName(bldr, fred) 1861 mon2 := example.MonsterEnd(bldr) 1862 1863 example.MonsterStartTest4Vector(bldr, 2) 1864 example.CreateTest(bldr, 10, 20) 1865 example.CreateTest(bldr, 30, 40) 1866 test4 := bldr.EndVector(2) 1867 1868 example.MonsterStartTestarrayofstringVector(bldr, 2) 1869 bldr.PrependUOffsetT(test2) 1870 bldr.PrependUOffsetT(test1) 1871 testArrayOfString := bldr.EndVector(2) 1872 1873 example.MonsterStart(bldr) 1874 1875 pos := example.CreateVec3(bldr, 1.0, 2.0, 3.0, 3.0, example.ColorGreen, 5, 6) 1876 example.MonsterAddPos(bldr, pos) 1877 1878 example.MonsterAddHp(bldr, 80) 1879 example.MonsterAddName(bldr, str) 1880 example.MonsterAddInventory(bldr, inv) 1881 example.MonsterAddTestType(bldr, 1) 1882 example.MonsterAddTest(bldr, mon2) 1883 example.MonsterAddTest4(bldr, test4) 1884 example.MonsterAddTestarrayofstring(bldr, testArrayOfString) 1885 mon := example.MonsterEnd(bldr) 1886 1887 bldr.Finish(mon) 1888 } 1889} 1890