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