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