1 /* 2 * Copyright 2015 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 17 using System; 18 using Google.FlatBuffers; 19 20 namespace Google.FlatBuffers.Test 21 { 22 [FlatBuffersTestClass] 23 public class FlatBuffersFuzzTests 24 { 25 private readonly Lcg _lcg = new Lcg(); 26 27 [FlatBuffersTestMethod] TestObjects()28 public void TestObjects() 29 { 30 CheckObjects(11, 100); 31 } 32 33 [FlatBuffersTestMethod] TestNumbers()34 public void TestNumbers() 35 { 36 var builder = new FlatBufferBuilder(1); 37 Assert.ArrayEqual(new byte[] { 0 }, builder.DataBuffer.ToFullArray()); 38 builder.AddBool(true); 39 Assert.ArrayEqual(new byte[] { 1 }, builder.DataBuffer.ToFullArray()); 40 builder.AddSbyte(-127); 41 Assert.ArrayEqual(new byte[] { 129, 1 }, builder.DataBuffer.ToFullArray()); 42 builder.AddByte(255); 43 Assert.ArrayEqual(new byte[] { 0, 255, 129, 1 }, builder.DataBuffer.ToFullArray()); // First pad 44 builder.AddShort(-32222); 45 Assert.ArrayEqual(new byte[] { 0, 0, 0x22, 0x82, 0, 255, 129, 1 }, builder.DataBuffer.ToFullArray()); // Second pad 46 builder.AddUshort(0xFEEE); 47 Assert.ArrayEqual(new byte[] { 0xEE, 0xFE, 0x22, 0x82, 0, 255, 129, 1 }, builder.DataBuffer.ToFullArray()); // no pad 48 builder.AddInt(-53687092); 49 Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 204, 204, 204, 252, 0xEE, 0xFE, 0x22, 0x82, 0, 255, 129, 1 }, builder.DataBuffer.ToFullArray()); // third pad 50 builder.AddUint(0x98765432); 51 Assert.ArrayEqual(new byte[] { 0x32, 0x54, 0x76, 0x98, 204, 204, 204, 252, 0xEE, 0xFE, 0x22, 0x82, 0, 255, 129, 1 }, builder.DataBuffer.ToFullArray()); // no pad 52 } 53 54 [FlatBuffersTestMethod] TestNumbers64()55 public void TestNumbers64() 56 { 57 var builder = new FlatBufferBuilder(1); 58 builder.AddUlong(0x1122334455667788); 59 Assert.ArrayEqual(new byte[] { 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11 }, builder.DataBuffer.ToFullArray()); 60 61 builder = new FlatBufferBuilder(1); 62 builder.AddLong(0x1122334455667788); 63 Assert.ArrayEqual(new byte[] { 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11 }, builder.DataBuffer.ToFullArray()); 64 } 65 66 [FlatBuffersTestMethod] TestVector_1xUInt8()67 public void TestVector_1xUInt8() 68 { 69 var builder = new FlatBufferBuilder(1); 70 builder.StartVector(sizeof(byte), 1, 1); 71 Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, builder.DataBuffer.ToFullArray()); 72 builder.AddByte(1); 73 Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, builder.DataBuffer.ToFullArray()); 74 builder.EndVector(); 75 Assert.ArrayEqual(new byte[] { 1, 0, 0, 0, 1, 0, 0, 0 }, builder.DataBuffer.ToFullArray()); 76 } 77 78 [FlatBuffersTestMethod] TestVector_2xUint8()79 public void TestVector_2xUint8() 80 { 81 var builder = new FlatBufferBuilder(1); 82 builder.StartVector(sizeof(byte), 2, 1); 83 Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, builder.DataBuffer.ToFullArray()); 84 builder.AddByte(1); 85 Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }, builder.DataBuffer.ToFullArray()); 86 builder.AddByte(2); 87 Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 2, 1, 0, 0 }, builder.DataBuffer.ToFullArray()); 88 builder.EndVector(); 89 Assert.ArrayEqual(new byte[] { 2, 0, 0, 0, 2, 1, 0, 0 }, builder.DataBuffer.ToFullArray()); 90 } 91 92 [FlatBuffersTestMethod] TestVector_1xUInt16()93 public void TestVector_1xUInt16() 94 { 95 var builder = new FlatBufferBuilder(1); 96 builder.StartVector(sizeof(ushort), 1, 1); 97 Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, builder.DataBuffer.ToFullArray()); 98 builder.AddUshort(1); 99 Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, builder.DataBuffer.ToFullArray()); 100 builder.EndVector(); 101 Assert.ArrayEqual(new byte[] { 1, 0, 0, 0, 1, 0, 0, 0 }, builder.DataBuffer.ToFullArray()); 102 } 103 104 [FlatBuffersTestMethod] TestVector_2xUInt16()105 public void TestVector_2xUInt16() 106 { 107 var builder = new FlatBufferBuilder(1); 108 builder.StartVector(sizeof(ushort), 2, 1); 109 Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, builder.DataBuffer.ToFullArray()); 110 builder.AddUshort(0xABCD); 111 Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 0, 0, 0xCD, 0xAB }, builder.DataBuffer.ToFullArray()); 112 builder.AddUshort(0xDCBA); 113 Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 0xBA, 0xDC, 0xCD, 0xAB }, builder.DataBuffer.ToFullArray()); 114 builder.EndVector(); 115 Assert.ArrayEqual(new byte[] { 2, 0, 0, 0, 0xBA, 0xDC, 0xCD, 0xAB }, builder.DataBuffer.ToFullArray()); 116 } 117 118 [FlatBuffersTestMethod] TestCreateAsciiString()119 public void TestCreateAsciiString() 120 { 121 var builder = new FlatBufferBuilder(1); 122 builder.CreateString("foo"); 123 Assert.ArrayEqual(new byte[] { 3, 0, 0, 0, (byte)'f', (byte)'o', (byte)'o', 0 }, builder.DataBuffer.ToFullArray()); 124 125 builder.CreateString("moop"); 126 Assert.ArrayEqual(new byte[] 127 { 128 0, 0, 0, 0, 129 0, 0, 0, 0, 130 0, 0, 0, 0, // Padding to 32 bytes 131 4, 0, 0, 0, 132 (byte)'m', (byte)'o', (byte)'o', (byte)'p', 133 0, 0, 0, 0, // zero terminator with 3 byte pad 134 3, 0, 0, 0, 135 (byte)'f', (byte)'o', (byte)'o', 0 136 }, builder.DataBuffer.ToFullArray()); 137 } 138 139 [FlatBuffersTestMethod] TestCreateSharedAsciiString()140 public void TestCreateSharedAsciiString() 141 { 142 var builder = new FlatBufferBuilder(1); 143 builder.CreateSharedString("foo"); 144 Assert.ArrayEqual(new byte[] { 3, 0, 0, 0, (byte)'f', (byte)'o', (byte)'o', 0 }, builder.DataBuffer.ToFullArray()); 145 146 builder.CreateSharedString("foo"); 147 Assert.ArrayEqual(new byte[] { 3, 0, 0, 0, (byte)'f', (byte)'o', (byte)'o', 0 }, builder.DataBuffer.ToFullArray()); 148 } 149 150 [FlatBuffersTestMethod] TestCreateArbitarytring()151 public void TestCreateArbitarytring() 152 { 153 var builder = new FlatBufferBuilder(1); 154 builder.CreateString("\x01\x02\x03"); 155 Assert.ArrayEqual(new byte[] 156 { 157 3, 0, 0, 0, 158 0x01, 0x02, 0x03, 0 159 }, builder.DataBuffer.ToFullArray()); // No padding 160 builder.CreateString("\x04\x05\x06\x07"); 161 Assert.ArrayEqual(new byte[] 162 { 163 0, 0, 0, 0, 164 0, 0, 0, 0, 165 0, 0, 0, 0, // Padding to 32 bytes 166 4, 0, 0, 0, 167 0x04, 0x05, 0x06, 0x07, 168 0, 0, 0, 0, // zero terminator with 3 byte pad 169 3, 0, 0, 0, 170 0x01, 0x02, 0x03, 0 171 }, builder.DataBuffer.ToFullArray()); // No padding 172 } 173 174 [FlatBuffersTestMethod] TestEmptyVTable()175 public void TestEmptyVTable() 176 { 177 var builder = new FlatBufferBuilder(1); 178 builder.StartTable(0); 179 Assert.ArrayEqual(new byte[] { 0 }, builder.DataBuffer.ToFullArray()); 180 builder.EndTable(); 181 Assert.ArrayEqual(new byte[] 182 { 183 4, 0, 4, 0, 184 4, 0, 0, 0 185 }, 186 builder.DataBuffer.ToFullArray()); 187 } 188 189 [FlatBuffersTestMethod] TestVTableWithOneBool()190 public void TestVTableWithOneBool() 191 { 192 var builder = new FlatBufferBuilder(1); 193 builder.StartTable(1); 194 Assert.ArrayEqual(new byte[] { 0 }, builder.DataBuffer.ToFullArray()); 195 builder.AddBool(0, true, false); 196 builder.EndTable(); 197 Assert.ArrayEqual(new byte[] 198 { 199 0, 0, // padding to 16 bytes 200 6, 0, // vtable bytes 201 8, 0, // object length inc vtable offset 202 7, 0, // start of bool value 203 6, 0, 0, 0, // int32 offset for start of vtable 204 0, 0, 0, // padding 205 1, // value 0 206 }, 207 builder.DataBuffer.ToFullArray()); 208 var verifier = new Verifier(builder.DataBuffer); 209 var offset = 8; 210 // table must be ok 211 Assert.IsTrue(verifier.VerifyTableStart((uint)offset)); 212 // First field must be bool 213 Assert.IsTrue(verifier.VerifyField((uint)offset, 4, 1, 1, true)); 214 // Check Error: Second field 215 Assert.IsFalse(verifier.VerifyField((uint)offset, 6, 1, 1, true)); 216 // Check Error: First field too big alignment 217 Assert.IsFalse(verifier.VerifyField((uint)offset, 4, 1, 2, true)); 218 // Check Error: First size to big 219 Assert.IsFalse(verifier.VerifyField((uint)offset, 4, 2, 1, true)); 220 } 221 222 [FlatBuffersTestMethod] TestVTableWithOneBool_DefaultValue()223 public void TestVTableWithOneBool_DefaultValue() 224 { 225 var builder = new FlatBufferBuilder(1); 226 builder.StartTable(1); 227 Assert.ArrayEqual(new byte[] { 0 }, builder.DataBuffer.ToFullArray()); 228 builder.AddBool(0, false, false); 229 builder.EndTable(); 230 Assert.ArrayEqual(new byte[] 231 { 232 // No padding. 233 4, 0, // vtable bytes 234 4, 0, // end of object from here 235 // entry 0 is not stored (trimmed end of vtable) 236 4, 0, 0, 0, // int32 offset for start of vtable 237 }, 238 builder.DataBuffer.ToFullArray()); 239 var verifier = new Verifier(builder.DataBuffer); 240 var offset = 4; 241 // table must be ok 242 Assert.IsTrue(verifier.VerifyTableStart((uint)offset)); 243 // First field must be bool 244 Assert.IsTrue(verifier.VerifyField((uint)offset, 4, 1, 1, false)); 245 // Error Check: First field not present 246 Assert.IsFalse(verifier.VerifyField((uint)offset, 4, 1, 1, true)); 247 } 248 249 [FlatBuffersTestMethod] TestVTableWithOneInt16()250 public void TestVTableWithOneInt16() 251 { 252 var builder = new FlatBufferBuilder(1); 253 builder.StartTable(1); 254 Assert.ArrayEqual(new byte[] { 0 }, builder.DataBuffer.ToFullArray()); 255 builder.AddShort(0, 0x789A, 0); 256 int offset = builder.EndTable(); 257 Assert.ArrayEqual(new byte[] 258 { 259 0, 0, // padding to 16 bytes 260 6, 0, // vtable bytes 261 8, 0, // object length inc vtable offset 262 6, 0, // start of int16 value 263 6, 0, 0, 0, // int32 offset for start of vtable 264 0, 0, // padding 265 0x9A, 0x78, //value 0 266 }, 267 builder.DataBuffer.ToFullArray()); 268 var verifier = new Verifier(builder.DataBuffer); 269 offset += builder.DataBuffer.Position; 270 // table must be ok 271 Assert.IsTrue(verifier.VerifyTableStart((uint)offset)); 272 // First field must be ushort 273 Assert.IsTrue(verifier.VerifyField((uint)offset, 4, 2, 2, true)); 274 // Check Error: Second field 275 Assert.IsFalse(verifier.VerifyField((uint)offset, 6, 2, 2, true)); 276 // Check Error: First field too big alignment 277 Assert.IsFalse(verifier.VerifyField((uint)offset, 4, 4, 2, true)); 278 // Check Error: First field size to big 279 Assert.IsFalse(verifier.VerifyField((uint)offset, 4, 2, 4, true)); 280 } 281 282 [FlatBuffersTestMethod] TestVTableWithTwoInt16()283 public void TestVTableWithTwoInt16() 284 { 285 var builder = new FlatBufferBuilder(1); 286 builder.StartTable(2); 287 Assert.ArrayEqual(new byte[] { 0 }, builder.DataBuffer.ToFullArray()); 288 builder.AddShort(0, 0x3456, 0); 289 builder.AddShort(1, 0x789A, 0); 290 int offset = builder.EndTable(); 291 Assert.ArrayEqual(new byte[] 292 { 293 8, 0, // vtable bytes 294 8, 0, // object length inc vtable offset 295 6, 0, // start of int16 value 0 296 4, 0, // start of int16 value 1 297 8, 0, 0, 0, // int32 offset for start of vtable 298 0x9A, 0x78, // value 1 299 0x56, 0x34, // value 0 300 }, 301 builder.DataBuffer.ToFullArray()); 302 var verifier = new Verifier(builder.DataBuffer); 303 offset += builder.DataBuffer.Position; 304 // table must be ok 305 Assert.IsTrue(verifier.VerifyTableStart((uint)offset)); 306 // First field must be ushort 307 Assert.IsTrue(verifier.VerifyField((uint)offset, 4, 2, 2, true)); 308 // Check Error: Second field 309 Assert.IsTrue(verifier.VerifyField((uint)offset, 6, 2, 2, true)); 310 // Check Error: Second field too big alignment 311 Assert.IsFalse(verifier.VerifyField((uint)offset, 4, 4, 2, true)); 312 // Check Error: Second field size to big 313 Assert.IsFalse(verifier.VerifyField((uint)offset, 4, 2, 4, true)); 314 } 315 316 [FlatBuffersTestMethod] TestVTableWithInt16AndBool()317 public void TestVTableWithInt16AndBool() 318 { 319 var builder = new FlatBufferBuilder(1); 320 builder.StartTable(2); 321 Assert.ArrayEqual(new byte[] { 0 }, builder.DataBuffer.ToFullArray()); 322 builder.AddShort(0, 0x3456, 0); 323 builder.AddBool(1, true, false); 324 int offset = builder.EndTable(); 325 Assert.ArrayEqual(new byte[] 326 { 327 8, 0, // vtable bytes 328 8, 0, // object length inc vtable offset 329 6, 0, // start of int16 value 0 330 5, 0, // start of bool value 1 331 8, 0, 0, 0, // int32 offset for start of vtable 332 0, 1, // padding + value 1 333 0x56, 0x34, // value 0 334 }, 335 builder.DataBuffer.ToFullArray()); 336 var verifier = new Verifier(builder.DataBuffer); 337 offset += builder.DataBuffer.Position; 338 // table must be ok 339 Assert.IsTrue(verifier.VerifyTableStart((uint)offset)); 340 // First field must be ushort 341 Assert.IsTrue(verifier.VerifyField((uint)offset, 4, 2, 2, true)); 342 // Check Error: Second field must be bool 343 Assert.IsTrue(verifier.VerifyField((uint)offset, 6, 1, 1, true)); 344 // Check Error: Second field too big alignment 345 Assert.IsFalse(verifier.VerifyField((uint)offset, 4, 4, 2, true)); 346 // Check Error: Second field size to big 347 Assert.IsFalse(verifier.VerifyField((uint)offset, 4, 2, 4, true)); 348 } 349 350 [FlatBuffersTestMethod] TestVTableWithEmptyVector()351 public void TestVTableWithEmptyVector() 352 { 353 var builder = new FlatBufferBuilder(1); 354 builder.StartVector(sizeof(byte), 0, 1); 355 var vecEnd = builder.EndVector(); 356 357 builder.StartTable(1); 358 359 builder.AddOffset(0, vecEnd.Value, 0); 360 builder.EndTable(); 361 Assert.ArrayEqual(new byte[] 362 { 363 0, 0, 0, 0, 364 0, 0, 0, 0, 365 0, 0, 0, 0, 366 0, 0, // Padding to 32 bytes 367 6, 0, // vtable bytes 368 8, 0, // object length inc vtable offset 369 4, 0, // start of vector offset value 0 370 6, 0, 0, 0, // int32 offset for start of vtable 371 4, 0, 0, 0, 372 0, 0, 0, 0, 373 }, 374 builder.DataBuffer.ToFullArray()); 375 var verifier = new Verifier(builder.DataBuffer); 376 uint checkOffset = 20; 377 // table must be ok 378 Assert.IsTrue(verifier.VerifyTableStart(checkOffset)); 379 // First field must be vector with element size 1 380 Assert.IsTrue(verifier.VerifyVectorOfData(checkOffset, 4, 1, true)); 381 } 382 383 [FlatBuffersTestMethod] TestVTableWithEmptyVectorAndScalars()384 public void TestVTableWithEmptyVectorAndScalars() 385 { 386 var builder = new FlatBufferBuilder(1); 387 builder.StartVector(sizeof(byte), 0, 1); 388 var vecEnd = builder.EndVector(); 389 390 builder.StartTable(2); 391 builder.AddShort(0, 55, 0); 392 builder.AddOffset(1, vecEnd.Value, 0); 393 builder.EndTable(); 394 Assert.ArrayEqual(new byte[] 395 { 396 0, 0, 0, 0, 397 0, 0, 0, 0, // Padding to 32 bytes 398 8, 0, // vtable bytes 399 12, 0, // object length inc vtable offset 400 10, 0, // offset to int16 value 0 401 4, 0, // start of vector offset value 1 402 8, 0, 0, 0, // int32 offset for start of vtable 403 8, 0, 0, 0, // value 1 404 0, 0, 55, 0, // value 0 405 0, 0, 0, 0, // length of vector (not in sctruc) 406 }, 407 builder.DataBuffer.ToFullArray()); 408 var verifier = new Verifier(builder.DataBuffer); 409 uint checkOffset = 16; 410 // table must be ok 411 Assert.IsTrue(verifier.VerifyTableStart(checkOffset)); 412 // First field must be short 413 Assert.IsTrue(verifier.VerifyField(checkOffset, 4, 2, 2, true)); 414 // Second field must be vector with element size 1 415 Assert.IsTrue(verifier.VerifyVectorOfData(checkOffset, 6, 2, true)); 416 } 417 418 419 [FlatBuffersTestMethod] TestVTableWith_1xInt16_and_Vector_or_2xInt16()420 public void TestVTableWith_1xInt16_and_Vector_or_2xInt16() 421 { 422 var builder = new FlatBufferBuilder(1); 423 builder.StartVector(sizeof(short), 2, 1); 424 builder.AddShort(0x1234); 425 builder.AddShort(0x5678); 426 var vecEnd = builder.EndVector(); 427 428 builder.StartTable(2); 429 builder.AddOffset(1, vecEnd.Value, 0); 430 builder.AddShort(0, 55, 0); 431 builder.EndTable(); 432 Assert.ArrayEqual(new byte[] 433 { 434 0, 0, 0, 0, // Padding to 32 bytes 435 8, 0, // vtable bytes 436 12, 0, // object length 437 6, 0, // start of value 0 from end of vtable 438 8, 0, // start of value 1 from end of buffer 439 8, 0, 0, 0, // int32 offset for start of vtable 440 0, 0, 55, 0, // padding + value 0 441 4, 0, 0, 0, // position of vector from here 442 2, 0, 0, 0, // length of vector 443 0x78, 0x56, // vector value 0 444 0x34, 0x12, // vector value 1 445 }, 446 builder.DataBuffer.ToFullArray()); 447 var verifier = new Verifier(builder.DataBuffer); 448 uint checkOffset = 12; 449 // table must be ok 450 Assert.IsTrue(verifier.VerifyTableStart(checkOffset)); 451 // Second field must be vector with element size 2 452 Assert.IsTrue(verifier.VerifyVectorOfData(checkOffset, 6, 2, true)); 453 // Check Error: Second field with too big size 454 Assert.IsFalse(verifier.VerifyVectorOfData(checkOffset, 6, 4, true)); 455 // First field must be short 456 Assert.IsTrue(verifier.VerifyField(checkOffset, 4, 2, 2, true)); 457 } 458 459 [FlatBuffersTestMethod] TestVTableWithAStruct_of_int8_int16_int32()460 public void TestVTableWithAStruct_of_int8_int16_int32() 461 { 462 var builder = new FlatBufferBuilder(1); 463 builder.StartTable(1); 464 builder.Prep(4+4+4, 0); 465 builder.AddSbyte(55); 466 builder.Pad(3); 467 builder.AddShort(0x1234); 468 builder.Pad(2); 469 builder.AddInt(0x12345678); 470 var structStart = builder.Offset; 471 builder.AddStruct(0, structStart, 0); 472 builder.EndTable(); 473 Assert.ArrayEqual(new byte[] 474 { 475 0, 0, 0, 0, 476 0, 0, 0, 0, 477 0, 0, // Padding to 32 bytes 478 6, 0, // vtable bytes 479 16, 0, // object length 480 4, 0, // start of struct from here 481 6, 0, 0, 0, // int32 offset for start of vtable 482 0x78, 0x56, 0x34, 0x12, // struct value 2 483 0x00, 0x00, 0x34, 0x12, // struct value 1 484 0x00, 0x00, 0x00, 55, // struct value 0 485 }, 486 builder.DataBuffer.ToFullArray()); 487 var verifier = new Verifier(builder.DataBuffer); 488 uint checkOffset = 16; 489 // table must be ok 490 Assert.IsTrue(verifier.VerifyTableStart(checkOffset)); 491 // First field must be a struct with 12 bytes 492 Assert.IsTrue(verifier.VerifyField(checkOffset, 4, 12, 4, true)); 493 // Check Error: First field with more than 12 bytes 494 Assert.IsFalse(verifier.VerifyField(checkOffset, 4, 16, 4, true)); 495 } 496 497 498 [FlatBuffersTestMethod] TestVTableWithAVectorOf_2xStructOf_2xInt8()499 public void TestVTableWithAVectorOf_2xStructOf_2xInt8() 500 { 501 var builder = new FlatBufferBuilder(1); 502 builder.StartVector(sizeof(byte)*2, 2, 1); 503 builder.AddByte(33); 504 builder.AddByte(44); 505 builder.AddByte(55); 506 builder.AddByte(66); 507 var vecEnd = builder.EndVector(); 508 509 builder.StartTable(1); 510 builder.AddOffset(0, vecEnd.Value, 0); 511 builder.EndTable(); 512 513 Assert.ArrayEqual(new byte[] 514 { 515 0, 0, 0, 0, 516 0, 0, 0, 0, 517 0, 0, // Padding to 32 bytes 518 6, 0, // vtable bytes 519 8, 0, // object length 520 4, 0, // offset of vector offset 521 6, 0, 0, 0, // int32 offset for start of vtable 522 4, 0, 0, 0, // Vector start offset 523 2, 0, 0, 0, // Vector len 524 66, // vector 1, 1 525 55, // vector 1, 0 526 44, // vector 0, 1 527 33, // vector 0, 0 528 }, 529 builder.DataBuffer.ToFullArray()); 530 var verifier = new Verifier(builder.DataBuffer); 531 uint checkOffset = 16; 532 // table must be ok 533 Assert.IsTrue(verifier.VerifyTableStart(checkOffset)); 534 // First field must be vector with element size 2 535 Assert.IsTrue(verifier.VerifyVectorOfData(checkOffset, 4, 2, true)); 536 } 537 538 [FlatBuffersTestMethod] TestVTableWithSomeElements()539 public void TestVTableWithSomeElements() 540 { 541 var builder = new FlatBufferBuilder(1); 542 builder.StartTable(2); 543 builder.AddByte(0, 33, 0); 544 builder.AddShort(1, 66, 0); 545 var off = builder.EndTable(); 546 builder.Finish(off); 547 548 byte[] padded = new byte[] 549 { 550 0, 0, 0, 0, 551 0, 0, 0, 0, 552 0, 0, 0, 0, //Padding to 32 bytes 553 12, 0, 0, 0, // root of table, pointing to vtable offset 554 8, 0, // vtable bytes 555 8, 0, // object length 556 7, 0, // start of value 0 557 4, 0, // start of value 1 558 8, 0, 0, 0, // int32 offset for start of vtable 559 66, 0, // value 1 560 0, 33, // value 0 561 562 }; 563 Assert.ArrayEqual(padded, builder.DataBuffer.ToFullArray()); 564 565 // no padding in sized array 566 byte[] unpadded = new byte[padded.Length - 12]; 567 Buffer.BlockCopy(padded, 12, unpadded, 0, unpadded.Length); 568 Assert.ArrayEqual(unpadded, builder.DataBuffer.ToSizedArray()); 569 570 var verifier = new Verifier(builder.DataBuffer); 571 uint checkOffset = builder.DataBuffer.GetUint(builder.DataBuffer.Position) + (uint)builder.DataBuffer.Position; 572 // table must be ok 573 Assert.IsTrue(verifier.VerifyTableStart(checkOffset)); 574 // First field must be a struct with 12 bytes 575 Assert.IsTrue(verifier.VerifyField(checkOffset, 4, 1, 1, true)); 576 // Second field must be a struct with 12 bytes 577 Assert.IsTrue(verifier.VerifyField(checkOffset, 6, 2, 2, true)); 578 } 579 580 [FlatBuffersTestMethod] TestVTableWithStrings()581 public void TestVTableWithStrings() 582 { 583 var builder = new FlatBufferBuilder(64); 584 var str1 = builder.CreateString("foo"); 585 var str2 = builder.CreateString("foobar"); 586 builder.StartTable(2); 587 builder.AddOffset(0, str1.Value, 0); 588 builder.AddOffset(1, str2.Value, 0); 589 var off = builder.EndTable(); 590 builder.Finish(off); 591 592 byte[] padded = new byte[] 593 { 594 0, 0, 0, 0, 595 0, 0, 0, 0, 596 0, 0, 0, 0, 597 0, 0, 0, 0, 598 0, 0, 0, 0, //Padding to 32 bytes 599 12, 0, 0, 0, // root of table, pointing to vtable offset 600 8, 0, // vtable bytes 601 12, 0, // object length 602 8, 0, // start of value 0 603 4, 0, // start of value 1 604 8, 0, 0, 0, // int32 offset for start of vtable 605 8, 0, 0, 0, // pointer to string 606 16, 0, 0, 0, // pointer to string 607 6, 0, 0, 0, // length of string 608 102, 111, 111, 98, 97, 114, 0, 0, // "foobar" + padding 609 3, 0, 0, 0, // length of string 610 102, 111, 111, 0 // "bar" 611 }; 612 Assert.ArrayEqual(padded, builder.DataBuffer.ToFullArray()); 613 614 var verifier = new Verifier(builder.DataBuffer); 615 uint checkOffset = builder.DataBuffer.GetUint(builder.DataBuffer.Position) + (uint)builder.DataBuffer.Position; 616 // table must be ok 617 Assert.IsTrue(verifier.VerifyTableStart(checkOffset)); 618 // First field string check 619 Assert.IsTrue(verifier.VerifyString(checkOffset, 4, true)); 620 // Second field string check 621 Assert.IsTrue(verifier.VerifyString(checkOffset, 6, true)); 622 } 623 624 [FlatBuffersTestMethod] TestVTableWithVectorOfStrings()625 public void TestVTableWithVectorOfStrings() 626 { 627 var builder = new FlatBufferBuilder(64); 628 var str1 = builder.CreateString("foo"); 629 var str2 = builder.CreateString("foobar"); 630 builder.StartVector(sizeof(int), 2, 1); 631 builder.AddOffset(str1.Value); 632 builder.AddOffset(str2.Value); 633 var vec = builder.EndVector(); 634 builder.StartTable(1); 635 builder.AddOffset(0, vec.Value, 0); 636 var off = builder.EndTable(); 637 builder.Finish(off); 638 639 byte[] padded = new byte[] 640 { 641 0, 0, 0, 0, 642 0, 0, 0, 0, 643 0, 0, 0, 0, //Padding to 32 bytes 644 12, 0, 0, 0, // root of table, pointing to vtable offset 645 0, 0, // padding 646 6, 0, // vtable bytes 647 8, 0, // object length 648 4, 0, // start of value 0 649 6, 0, 0, 0, // int32 offset for start of vtable 650 4, 0, 0, 0, // pointer to vector 651 2, 0, 0, 0, // length of vector 652 8, 0, 0, 0, // int32 offset to string 1 653 16, 0, 0, 0, // int32 offset to string 2 654 6, 0, 0, 0, // length of string 655 102, 111, 111, 98, 97, 114, 0, 0, // "foobar" + padding 656 3, 0, 0, 0, // length of string 657 102, 111, 111, 0 // "bar" 658 }; 659 Assert.ArrayEqual(padded, builder.DataBuffer.ToFullArray()); 660 661 var verifier = new Verifier(builder.DataBuffer); 662 uint checkOffset = builder.DataBuffer.GetUint(builder.DataBuffer.Position) + (uint)builder.DataBuffer.Position; 663 // table must be ok 664 Assert.IsTrue(verifier.VerifyTableStart(checkOffset)); 665 // First field string check 666 Assert.IsTrue(verifier.VerifyVectorOfStrings(checkOffset, 4, true)); 667 } 668 669 [FlatBuffersTestMethod] TestTwoFinishTable()670 public void TestTwoFinishTable() 671 { 672 var builder = new FlatBufferBuilder(1); 673 builder.StartTable(2); 674 builder.AddByte(0, 33, 0); 675 builder.AddByte(1, 44, 0); 676 var off0 = builder.EndTable(); 677 builder.Finish(off0); 678 679 builder.StartTable(3); 680 builder.AddByte(0, 55, 0); 681 builder.AddByte(1, 66, 0); 682 builder.AddByte(2, 77, 0); 683 var off1 = builder.EndTable(); 684 builder.Finish(off1); 685 686 Assert.ArrayEqual(new byte[] 687 { 688 0, 0, 0, 0, 689 0, 0, 0, 0, 690 0, 0, 0, 0, 691 0, 0, 0, 0, 692 0, 0, 0, 0, // padding to 64 bytes 693 16, 0, 0, 0, // root of table, pointing to vtable offset (obj1) 694 0, 0, // padding 695 696 10, 0, // vtable bytes 697 8, 0, // object length 698 7, 0, // start of value 0 699 6, 0, // start of value 1 700 5, 0, // start of value 2 701 10, 0, 0, 0, // int32 offset for start of vtable 702 0, // pad 703 77, // values 2, 1, 0 704 66, 705 55, 706 707 12, 0, 0, 0, // root of table, pointing to vtable offset (obj0) 708 8, 0, // vtable bytes 709 8, 0, // object length 710 7, 0, // start of value 0 711 6, 0, // start of value 1 712 8, 0, 0, 0, // int32 offset for start of vtable 713 0, 0, // pad 714 44, // value 1, 0 715 33, 716 }, 717 builder.DataBuffer.ToFullArray()); 718 719 // check obj1 720 var verifier = new Verifier(builder.DataBuffer); 721 uint checkOffset = builder.DataBuffer.GetUint(builder.DataBuffer.Position) + (uint)builder.DataBuffer.Position; 722 // table must be ok 723 Assert.IsTrue(verifier.VerifyTableStart(checkOffset)); 724 // First field must be a struct with 12 bytes 725 Assert.IsTrue(verifier.VerifyField(checkOffset, 4, 1, 1, true)); 726 // Second field must be a struct with 12 bytes 727 Assert.IsTrue(verifier.VerifyField(checkOffset, 6, 1, 1, true)); 728 // Third field must be a struct with 12 bytes 729 Assert.IsTrue(verifier.VerifyField(checkOffset, 8, 1, 1, true)); 730 // Check Error: 4. field did not exist 731 Assert.IsFalse(verifier.VerifyField(checkOffset, 10, 1, 1, true)); 732 733 // check obj0 734 checkOffset = 56; 735 // table must be ok 736 Assert.IsTrue(verifier.VerifyTableStart(checkOffset)); 737 // First field must be a struct with 12 bytes 738 Assert.IsTrue(verifier.VerifyField(checkOffset, 4, 1, 1, true)); 739 // Second field must be a struct with 12 bytes 740 Assert.IsTrue(verifier.VerifyField(checkOffset, 6, 1, 1, true)); 741 // Check Error: 3. field did not exist 742 Assert.IsFalse(verifier.VerifyField(checkOffset, 8, 1, 1, true)); 743 // Check Error: 4. field did not exist 744 Assert.IsFalse(verifier.VerifyField(checkOffset, 10, 1, 1, true)); 745 } 746 747 [FlatBuffersTestMethod] TestBunchOfBools()748 public void TestBunchOfBools() 749 { 750 var builder = new FlatBufferBuilder(1); 751 builder.StartTable(8); 752 for (var i = 0; i < 8; i++) 753 { 754 builder.AddBool(i, true, false); 755 } 756 var off = builder.EndTable(); 757 builder.Finish(off); 758 759 byte[] padded = new byte[] 760 { 761 0, 0, 0, 0, 762 0, 0, 0, 0, 763 0, 0, 0, 0, 764 0, 0, 0, 0, 765 0, 0, 0, 0, 766 0, 0, 0, 0, 767 0, 0, 0, 0, // padding to 64 bytes 768 769 24, 0, 0, 0, // root of table, pointing to vtable offset (obj0) 770 20, 0, // vtable bytes 771 12, 0, // object length 772 11, 0, // start of value 0 773 10, 0, // start of value 1 774 9, 0, // start of value 2 775 8, 0, // start of value 3 776 7, 0, // start of value 4 777 6, 0, // start of value 5 778 5, 0, // start of value 6 779 4, 0, // start of value 7 780 781 20, 0, 0, 0, // int32 offset for start of vtable 782 783 1, 1, 1, 1, // values 784 1, 1, 1, 1, 785 786 }; 787 Assert.ArrayEqual(padded, builder.DataBuffer.ToFullArray()); 788 789 // no padding in sized array 790 byte[] unpadded = new byte[padded.Length - 28]; 791 Buffer.BlockCopy(padded, 28, unpadded, 0, unpadded.Length); 792 Assert.ArrayEqual(unpadded, builder.DataBuffer.ToSizedArray()); 793 794 var verifier = new Verifier(builder.DataBuffer); 795 uint checkOffset = builder.DataBuffer.GetUint(builder.DataBuffer.Position) + (uint)builder.DataBuffer.Position; 796 // table must be ok 797 Assert.IsTrue(verifier.VerifyTableStart(checkOffset)); 798 for (var i = 0; i < 8; i++) 799 { 800 Assert.IsTrue(verifier.VerifyField(checkOffset, (short)(4 + i * 2), 1, 1, true)); 801 } 802 Assert.IsFalse(verifier.VerifyField(checkOffset, (short)(4 + 8 * 2), 1, 1, true)); 803 } 804 805 [FlatBuffersTestMethod] TestBunchOfBoolsSizePrefixed()806 public void TestBunchOfBoolsSizePrefixed() 807 { 808 var builder = new FlatBufferBuilder(1); 809 builder.StartTable(8); 810 for (var i = 0; i < 8; i++) 811 { 812 builder.AddBool(i, true, false); 813 } 814 var off = builder.EndTable(); 815 builder.FinishSizePrefixed(off); 816 817 byte[] padded = new byte[] 818 { 819 0, 0, 0, 0, 820 0, 0, 0, 0, 821 0, 0, 0, 0, 822 0, 0, 0, 0, 823 0, 0, 0, 0, 824 0, 0, 0, 0, // padding to 64 bytes 825 826 36, 0, 0, 0, // size prefix 827 24, 0, 0, 0, // root of table, pointing to vtable offset (obj0) 828 20, 0, // vtable bytes 829 12, 0, // object length 830 11, 0, // start of value 0 831 10, 0, // start of value 1 832 9, 0, // start of value 2 833 8, 0, // start of value 3 834 7, 0, // start of value 4 835 6, 0, // start of value 5 836 5, 0, // start of value 6 837 4, 0, // start of value 7 838 839 20, 0, 0, 0, // int32 offset for start of vtable 840 841 1, 1, 1, 1, // values 842 1, 1, 1, 1, 843 844 }; 845 Assert.ArrayEqual(padded, builder.DataBuffer.ToFullArray()); 846 847 // no padding in sized array 848 byte[] unpadded = new byte[padded.Length - 24]; 849 Buffer.BlockCopy(padded, 24, unpadded, 0, unpadded.Length); 850 Assert.ArrayEqual(unpadded, builder.DataBuffer.ToSizedArray()); 851 } 852 853 [FlatBuffersTestMethod] TestWithFloat()854 public void TestWithFloat() 855 { 856 var builder = new FlatBufferBuilder(1); 857 builder.StartTable(1); 858 builder.AddFloat(0, 1, 0); 859 builder.EndTable(); 860 861 862 Assert.ArrayEqual(new byte[] 863 { 864 0, 0, 865 6, 0, // vtable bytes 866 8, 0, // object length 867 4, 0, // start of value 0 868 6, 0, 0, 0, // int32 offset for start of vtable 869 0, 0, 128, 63, // value 870 871 }, 872 builder.DataBuffer.ToFullArray()); 873 var verifier = new Verifier(builder.DataBuffer); 874 uint checkOffset = 8; 875 // table must be ok 876 Assert.IsTrue(verifier.VerifyTableStart(checkOffset)); 877 // First Field must be float 878 Assert.IsTrue(verifier.VerifyField(checkOffset, 4, 4, 4, true)); 879 // Check Error: First Field with to big size 880 Assert.IsFalse(verifier.VerifyField(checkOffset, 4, 8, 4, true)); 881 // Check Error: First Field with to big padding 882 Assert.IsFalse(verifier.VerifyField(checkOffset, 4, 4, 8, true)); 883 } 884 CheckObjects(int fieldCount, int objectCount)885 private void CheckObjects(int fieldCount, int objectCount) 886 { 887 _lcg.Reset(); 888 889 const int testValuesMax = 11; 890 891 var builder = new FlatBufferBuilder(1); 892 893 var objects = new int[objectCount]; 894 895 for (var i = 0; i < objectCount; ++i) 896 { 897 builder.StartTable(fieldCount); 898 899 for (var j = 0; j < fieldCount; ++j) 900 { 901 var fieldType = _lcg.Next()%testValuesMax; 902 903 switch (fieldType) 904 { 905 case 0: 906 { 907 builder.AddBool(j, FuzzTestData.BoolValue, false); 908 break; 909 } 910 case 1: 911 { 912 builder.AddSbyte(j, FuzzTestData.Int8Value, 0); 913 break; 914 } 915 case 2: 916 { 917 builder.AddByte(j, FuzzTestData.UInt8Value, 0); 918 break; 919 } 920 case 3: 921 { 922 builder.AddShort(j, FuzzTestData.Int16Value, 0); 923 break; 924 } 925 case 4: 926 { 927 builder.AddUshort(j, FuzzTestData.UInt16Value, 0); 928 break; 929 } 930 case 5: 931 { 932 builder.AddInt(j, FuzzTestData.Int32Value, 0); 933 break; 934 } 935 case 6: 936 { 937 builder.AddUint(j, FuzzTestData.UInt32Value, 0); 938 break; 939 } 940 case 7: 941 { 942 builder.AddLong(j, FuzzTestData.Int64Value, 0); 943 break; 944 } 945 case 8: 946 { 947 builder.AddUlong(j, FuzzTestData.UInt64Value, 0); 948 break; 949 } 950 case 9: 951 { 952 builder.AddFloat(j, FuzzTestData.Float32Value, 0); 953 break; 954 } 955 case 10: 956 { 957 builder.AddDouble(j, FuzzTestData.Float64Value, 0); 958 break; 959 } 960 default: 961 throw new Exception("Unreachable"); 962 } 963 964 } 965 966 var offset = builder.EndTable(); 967 968 // Store the object offset 969 objects[i] = offset; 970 } 971 972 _lcg.Reset(); 973 974 // Test all objects are readable and return expected values... 975 for (var i = 0; i < objectCount; ++i) 976 { 977 var table = new TestTable(builder.DataBuffer, builder.DataBuffer.Length - objects[i]); 978 979 for (var j = 0; j < fieldCount; ++j) 980 { 981 var fieldType = _lcg.Next() % testValuesMax; 982 var fc = 2 + j; // 2 == VtableMetadataFields 983 var f = fc * 2; 984 985 switch (fieldType) 986 { 987 case 0: 988 { 989 Assert.AreEqual(FuzzTestData.BoolValue, table.GetSlot(f, false)); 990 break; 991 } 992 case 1: 993 { 994 Assert.AreEqual(FuzzTestData.Int8Value, table.GetSlot(f, (sbyte)0)); 995 break; 996 } 997 case 2: 998 { 999 Assert.AreEqual(FuzzTestData.UInt8Value, table.GetSlot(f, (byte)0)); 1000 break; 1001 } 1002 case 3: 1003 { 1004 Assert.AreEqual(FuzzTestData.Int16Value, table.GetSlot(f, (short)0)); 1005 break; 1006 } 1007 case 4: 1008 { 1009 Assert.AreEqual(FuzzTestData.UInt16Value, table.GetSlot(f, (ushort)0)); 1010 break; 1011 } 1012 case 5: 1013 { 1014 Assert.AreEqual(FuzzTestData.Int32Value, table.GetSlot(f, (int)0)); 1015 break; 1016 } 1017 case 6: 1018 { 1019 Assert.AreEqual(FuzzTestData.UInt32Value, table.GetSlot(f, (uint)0)); 1020 break; 1021 } 1022 case 7: 1023 { 1024 Assert.AreEqual(FuzzTestData.Int64Value, table.GetSlot(f, (long)0)); 1025 break; 1026 } 1027 case 8: 1028 { 1029 Assert.AreEqual(FuzzTestData.UInt64Value, table.GetSlot(f, (ulong)0)); 1030 break; 1031 } 1032 case 9: 1033 { 1034 Assert.AreEqual(FuzzTestData.Float32Value, table.GetSlot(f, (float)0)); 1035 break; 1036 } 1037 case 10: 1038 { 1039 Assert.AreEqual(FuzzTestData.Float64Value, table.GetSlot(f, (double)0)); 1040 break; 1041 } 1042 default: 1043 throw new Exception("Unreachable"); 1044 } 1045 1046 } 1047 1048 } 1049 1050 } 1051 } 1052 } 1053