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