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