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