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