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