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