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