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