From 9d66af6efc0498e90e2757659761ae0c4f797eee Mon Sep 17 00:00:00 2001 From: evolutional Date: Sun, 18 Oct 2015 17:08:39 -0400 Subject: [PATCH] Ported some of the python fuzz tests to C# * Refactored the test runner to use attribute based test discovery * Ported value and vtable/object fuzzing tests from python to C# --- tests/FlatBuffers.Test/Assert.cs | 35 + tests/FlatBuffers.Test/ByteBufferTests.cs | 49 +- .../FlatBuffers.Test/FlatBuffers.Test.csproj | 12 +- .../FlatBuffersExampleTests.cs | 4 + .../FlatBuffers.Test/FlatBuffersFuzzTests.cs | 742 ++++++++++++++++++ .../FlatBuffersTestClassAttribute.cs | 12 + .../FlatBuffersTestMethodAttribute.cs | 9 + tests/FlatBuffers.Test/FuzzTestData.cs | 22 + tests/FlatBuffers.Test/Lcg.cs | 26 + tests/FlatBuffers.Test/Program.cs | 61 +- tests/FlatBuffers.Test/TestTable.cs | 135 ++++ 11 files changed, 1067 insertions(+), 40 deletions(-) create mode 100644 tests/FlatBuffers.Test/FlatBuffersFuzzTests.cs create mode 100644 tests/FlatBuffers.Test/FlatBuffersTestClassAttribute.cs create mode 100644 tests/FlatBuffers.Test/FlatBuffersTestMethodAttribute.cs create mode 100644 tests/FlatBuffers.Test/FuzzTestData.cs create mode 100644 tests/FlatBuffers.Test/Lcg.cs create mode 100644 tests/FlatBuffers.Test/TestTable.cs diff --git a/tests/FlatBuffers.Test/Assert.cs b/tests/FlatBuffers.Test/Assert.cs index 932f05747..1bcf95f28 100644 --- a/tests/FlatBuffers.Test/Assert.cs +++ b/tests/FlatBuffers.Test/Assert.cs @@ -39,6 +39,25 @@ namespace FlatBuffers.Test } } + public class AssertArrayFailedException : Exception + { + private readonly int _index; + private readonly object _expected; + private readonly object _actual; + + public AssertArrayFailedException(int index, object expected, object actual) + { + _index = index; + _expected = expected; + _actual = actual; + } + + public override string Message + { + get { return string.Format("Expected {0} at index {1} but saw {2}", _expected, _index, _actual); } + } + } + public class AssertUnexpectedThrowException : Exception { private readonly object _expected; @@ -64,6 +83,22 @@ namespace FlatBuffers.Test } } + public static void ArrayEqual(T[] expected, T[] actual) + { + if (expected.Length != actual.Length) + { + throw new AssertFailedException(expected, actual); + } + + for(var i = 0; i < expected.Length; ++i) + { + if (!expected[i].Equals(actual[i])) + { + throw new AssertArrayFailedException(i, expected, actual); + } + } + } + public static void IsTrue(bool value) { if (!value) diff --git a/tests/FlatBuffers.Test/ByteBufferTests.cs b/tests/FlatBuffers.Test/ByteBufferTests.cs index d5899a968..0241e96e2 100644 --- a/tests/FlatBuffers.Test/ByteBufferTests.cs +++ b/tests/FlatBuffers.Test/ByteBufferTests.cs @@ -18,9 +18,11 @@ using System; namespace FlatBuffers.Test { + [FlatBuffersTestClass] public class ByteBufferTests { + [FlatBuffersTestMethod] public void ByteBuffer_Length_MatchesBufferLength() { var buffer = new byte[1000]; @@ -28,6 +30,7 @@ namespace FlatBuffers.Test Assert.AreEqual(buffer.Length, uut.Length); } + [FlatBuffersTestMethod] public void ByteBuffer_PutBytePopulatesBufferAtZeroOffset() { var buffer = new byte[1]; @@ -37,6 +40,7 @@ namespace FlatBuffers.Test Assert.AreEqual((byte)99, buffer[0]); } + [FlatBuffersTestMethod] public void ByteBuffer_PutByteCannotPutAtOffsetPastLength() { var buffer = new byte[1]; @@ -44,6 +48,7 @@ namespace FlatBuffers.Test Assert.Throws(() => uut.PutByte(1, 99)); } + [FlatBuffersTestMethod] public void ByteBuffer_PutShortPopulatesBufferCorrectly() { var buffer = new byte[2]; @@ -55,6 +60,7 @@ namespace FlatBuffers.Test Assert.AreEqual((byte)0, buffer[1]); } + [FlatBuffersTestMethod] public void ByteBuffer_PutShortCannotPutAtOffsetPastLength() { var buffer = new byte[2]; @@ -62,6 +68,7 @@ namespace FlatBuffers.Test Assert.Throws(() => uut.PutShort(2, 99)); } + [FlatBuffersTestMethod] public void ByteBuffer_PutShortChecksLength() { var buffer = new byte[1]; @@ -69,6 +76,7 @@ namespace FlatBuffers.Test Assert.Throws(() => uut.PutShort(0, 99)); } + [FlatBuffersTestMethod] public void ByteBuffer_PutShortChecksLengthAndOffset() { var buffer = new byte[2]; @@ -76,6 +84,7 @@ namespace FlatBuffers.Test Assert.Throws(() => uut.PutShort(1, 99)); } + [FlatBuffersTestMethod] public void ByteBuffer_PutIntPopulatesBufferCorrectly() { var buffer = new byte[4]; @@ -89,6 +98,7 @@ namespace FlatBuffers.Test Assert.AreEqual(0x0A, buffer[3]); } + [FlatBuffersTestMethod] public void ByteBuffer_PutIntCannotPutAtOffsetPastLength() { var buffer = new byte[4]; @@ -96,6 +106,7 @@ namespace FlatBuffers.Test Assert.Throws(() => uut.PutInt(2, 0x0A0B0C0D)); } + [FlatBuffersTestMethod] public void ByteBuffer_PutIntChecksLength() { var buffer = new byte[1]; @@ -103,6 +114,7 @@ namespace FlatBuffers.Test Assert.Throws(() => uut.PutInt(0, 0x0A0B0C0D)); } + [FlatBuffersTestMethod] public void ByteBuffer_PutIntChecksLengthAndOffset() { var buffer = new byte[4]; @@ -110,6 +122,7 @@ namespace FlatBuffers.Test Assert.Throws(() => uut.PutInt(2, 0x0A0B0C0D)); } + [FlatBuffersTestMethod] public void ByteBuffer_PutLongPopulatesBufferCorrectly() { var buffer = new byte[8]; @@ -127,6 +140,7 @@ namespace FlatBuffers.Test Assert.AreEqual(0x01, buffer[7]); } + [FlatBuffersTestMethod] public void ByteBuffer_PutLongCannotPutAtOffsetPastLength() { var buffer = new byte[8]; @@ -134,6 +148,7 @@ namespace FlatBuffers.Test Assert.Throws(() => uut.PutLong(2, 0x010203040A0B0C0D)); } + [FlatBuffersTestMethod] public void ByteBuffer_PutLongChecksLength() { var buffer = new byte[1]; @@ -141,6 +156,7 @@ namespace FlatBuffers.Test Assert.Throws(() => uut.PutLong(0, 0x010203040A0B0C0D)); } + [FlatBuffersTestMethod] public void ByteBuffer_PutLongChecksLengthAndOffset() { var buffer = new byte[8]; @@ -148,6 +164,7 @@ namespace FlatBuffers.Test Assert.Throws(() => uut.PutLong(2, 0x010203040A0B0C0D)); } + [FlatBuffersTestMethod] public void ByteBuffer_GetByteReturnsCorrectData() { var buffer = new byte[1]; @@ -156,6 +173,7 @@ namespace FlatBuffers.Test Assert.AreEqual((byte)99, uut.Get(0)); } + [FlatBuffersTestMethod] public void ByteBuffer_GetByteChecksOffset() { var buffer = new byte[1]; @@ -163,6 +181,7 @@ namespace FlatBuffers.Test Assert.Throws(()=>uut.Get(1)); } + [FlatBuffersTestMethod] public void ByteBuffer_GetShortReturnsCorrectData() { var buffer = new byte[2]; @@ -172,6 +191,7 @@ namespace FlatBuffers.Test Assert.AreEqual(1, uut.GetShort(0)); } + [FlatBuffersTestMethod] public void ByteBuffer_GetShortChecksOffset() { var buffer = new byte[2]; @@ -179,6 +199,7 @@ namespace FlatBuffers.Test Assert.Throws(() => uut.GetShort(2)); } + [FlatBuffersTestMethod] public void ByteBuffer_GetShortChecksLength() { var buffer = new byte[2]; @@ -186,6 +207,7 @@ namespace FlatBuffers.Test Assert.Throws(() => uut.GetShort(1)); } + [FlatBuffersTestMethod] public void ByteBuffer_GetIntReturnsCorrectData() { var buffer = new byte[4]; @@ -197,6 +219,7 @@ namespace FlatBuffers.Test Assert.AreEqual(0x0A0B0C0D, uut.GetInt(0)); } + [FlatBuffersTestMethod] public void ByteBuffer_GetIntChecksOffset() { var buffer = new byte[4]; @@ -204,6 +227,7 @@ namespace FlatBuffers.Test Assert.Throws(() => uut.GetInt(4)); } + [FlatBuffersTestMethod] public void ByteBuffer_GetIntChecksLength() { var buffer = new byte[2]; @@ -211,6 +235,7 @@ namespace FlatBuffers.Test Assert.Throws(() => uut.GetInt(0)); } + [FlatBuffersTestMethod] public void ByteBuffer_GetLongReturnsCorrectData() { var buffer = new byte[8]; @@ -226,6 +251,7 @@ namespace FlatBuffers.Test Assert.AreEqual(0x010203040A0B0C0D, uut.GetLong(0)); } + [FlatBuffersTestMethod] public void ByteBuffer_GetLongChecksOffset() { var buffer = new byte[8]; @@ -233,39 +259,44 @@ namespace FlatBuffers.Test Assert.Throws(() => uut.GetLong(8)); } + [FlatBuffersTestMethod] public void ByteBuffer_GetLongChecksLength() { var buffer = new byte[7]; var uut = new ByteBuffer(buffer); Assert.Throws(() => uut.GetLong(0)); } + + [FlatBuffersTestMethod] public void ByteBuffer_ReverseBytesUshort() { - ushort original = (ushort)0x1234U; - ushort reverse = ByteBuffer.ReverseBytes(original); + const ushort original = (ushort)0x1234U; + var reverse = ByteBuffer.ReverseBytes(original); Assert.AreEqual(0x3412U, reverse); - ushort rereverse = ByteBuffer.ReverseBytes(reverse); + var rereverse = ByteBuffer.ReverseBytes(reverse); Assert.AreEqual(original, rereverse); } + [FlatBuffersTestMethod] public void ByteBuffer_ReverseBytesUint() { - uint original = 0x12345678; - uint reverse = ByteBuffer.ReverseBytes(original); + const uint original = 0x12345678; + var reverse = ByteBuffer.ReverseBytes(original); Assert.AreEqual(0x78563412U, reverse); - uint rereverse = ByteBuffer.ReverseBytes(reverse); + var rereverse = ByteBuffer.ReverseBytes(reverse); Assert.AreEqual(original, rereverse); } + [FlatBuffersTestMethod] public void ByteBuffer_ReverseBytesUlong() { - ulong original = 0x1234567890ABCDEFUL; - ulong reverse = ByteBuffer.ReverseBytes(original); + const ulong original = 0x1234567890ABCDEFUL; + var reverse = ByteBuffer.ReverseBytes(original); Assert.AreEqual(0xEFCDAB9078563412UL, reverse); - ulong rereverse = ByteBuffer.ReverseBytes(reverse); + var rereverse = ByteBuffer.ReverseBytes(reverse); Assert.AreEqual(original, rereverse); } } diff --git a/tests/FlatBuffers.Test/FlatBuffers.Test.csproj b/tests/FlatBuffers.Test/FlatBuffers.Test.csproj index bfc0fe18a..c292a9c9c 100644 --- a/tests/FlatBuffers.Test/FlatBuffers.Test.csproj +++ b/tests/FlatBuffers.Test/FlatBuffers.Test.csproj @@ -41,9 +41,9 @@ FlatBuffers\ByteBuffer.cs - - FlatBuffers\Offset.cs - + + FlatBuffers\Offset.cs + FlatBuffers\FlatBufferBuilder.cs @@ -79,9 +79,15 @@ + + + + + + diff --git a/tests/FlatBuffers.Test/FlatBuffersExampleTests.cs b/tests/FlatBuffers.Test/FlatBuffersExampleTests.cs index 666ac1c6a..53d74c395 100644 --- a/tests/FlatBuffers.Test/FlatBuffersExampleTests.cs +++ b/tests/FlatBuffers.Test/FlatBuffersExampleTests.cs @@ -19,6 +19,7 @@ using MyGame.Example; namespace FlatBuffers.Test { + [FlatBuffersTestClass] public class FlatBuffersExampleTests { public void RunTests() @@ -28,6 +29,7 @@ namespace FlatBuffers.Test TestEnums(); } + [FlatBuffersTestMethod] public void CanCreateNewFlatBufferFromScratch() { // Second, let's create a FlatBuffer from scratch in C#, and test it also. @@ -184,6 +186,7 @@ namespace FlatBuffers.Test Assert.AreEqual(false, monster.Testbool); } + [FlatBuffersTestMethod] public void CanReadCppGeneratedWireFile() { var data = File.ReadAllBytes(@"Resources/monsterdata_test.mon"); @@ -191,6 +194,7 @@ namespace FlatBuffers.Test TestBuffer(bb); } + [FlatBuffersTestMethod] public void TestEnums() { Assert.AreEqual("Red", Color.Red.ToString()); diff --git a/tests/FlatBuffers.Test/FlatBuffersFuzzTests.cs b/tests/FlatBuffers.Test/FlatBuffersFuzzTests.cs new file mode 100644 index 000000000..744575119 --- /dev/null +++ b/tests/FlatBuffers.Test/FlatBuffersFuzzTests.cs @@ -0,0 +1,742 @@ +/* + * Copyright 2015 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; + +namespace FlatBuffers.Test +{ + [FlatBuffersTestClass] + public class FlatBuffersFuzzTests + { + private readonly Lcg _lcg = new Lcg(); + + [FlatBuffersTestMethod] + public void TestObjects() + { + CheckObjects(11, 100); + } + + [FlatBuffersTestMethod] + public void TestNumbers() + { + var builder = new FlatBufferBuilder(1); + Assert.ArrayEqual(new byte[] { 0 }, builder.DataBuffer.Data); + builder.AddBool(true); + Assert.ArrayEqual(new byte[] { 1 }, builder.DataBuffer.Data); + builder.AddSbyte(-127); + Assert.ArrayEqual(new byte[] { 129, 1 }, builder.DataBuffer.Data); + builder.AddByte(255); + Assert.ArrayEqual(new byte[] { 0, 255, 129, 1 }, builder.DataBuffer.Data); // First pad + builder.AddShort(-32222); + Assert.ArrayEqual(new byte[] { 0, 0, 0x22, 0x82, 0, 255, 129, 1 }, builder.DataBuffer.Data); // Second pad + builder.AddUshort(0xFEEE); + Assert.ArrayEqual(new byte[] { 0xEE, 0xFE, 0x22, 0x82, 0, 255, 129, 1 }, builder.DataBuffer.Data); // no pad + builder.AddInt(-53687092); + Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 204, 204, 204, 252, 0xEE, 0xFE, 0x22, 0x82, 0, 255, 129, 1 }, builder.DataBuffer.Data); // third pad + builder.AddUint(0x98765432); + Assert.ArrayEqual(new byte[] { 0x32, 0x54, 0x76, 0x98, 204, 204, 204, 252, 0xEE, 0xFE, 0x22, 0x82, 0, 255, 129, 1 }, builder.DataBuffer.Data); // no pad + } + + [FlatBuffersTestMethod] + public void TestNumbers64() + { + var builder = new FlatBufferBuilder(1); + builder.AddUlong(0x1122334455667788); + Assert.ArrayEqual(new byte[] { 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11 }, builder.DataBuffer.Data); + + builder = new FlatBufferBuilder(1); + builder.AddLong(0x1122334455667788); + Assert.ArrayEqual(new byte[] { 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11 }, builder.DataBuffer.Data); + } + + [FlatBuffersTestMethod] + public void TestVector_1xUInt8() + { + var builder = new FlatBufferBuilder(1); + builder.StartVector(sizeof(byte), 1, 1); + Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, builder.DataBuffer.Data); + builder.AddByte(1); + Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, builder.DataBuffer.Data); + builder.EndVector(); + Assert.ArrayEqual(new byte[] { 1, 0, 0, 0, 1, 0, 0, 0 }, builder.DataBuffer.Data); + } + + [FlatBuffersTestMethod] + public void TestVector_2xUint8() + { + var builder = new FlatBufferBuilder(1); + builder.StartVector(sizeof(byte), 2, 1); + Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, builder.DataBuffer.Data); + builder.AddByte(1); + Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }, builder.DataBuffer.Data); + builder.AddByte(2); + Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 2, 1, 0, 0 }, builder.DataBuffer.Data); + builder.EndVector(); + Assert.ArrayEqual(new byte[] { 2, 0, 0, 0, 2, 1, 0, 0 }, builder.DataBuffer.Data); + } + + [FlatBuffersTestMethod] + public void TestVector_1xUInt16() + { + var builder = new FlatBufferBuilder(1); + builder.StartVector(sizeof(ushort), 1, 1); + Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, builder.DataBuffer.Data); + builder.AddUshort(1); + Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, builder.DataBuffer.Data); + builder.EndVector(); + Assert.ArrayEqual(new byte[] { 1, 0, 0, 0, 1, 0, 0, 0 }, builder.DataBuffer.Data); + } + + [FlatBuffersTestMethod] + public void TestVector_2xUInt16() + { + var builder = new FlatBufferBuilder(1); + builder.StartVector(sizeof(ushort), 2, 1); + Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, builder.DataBuffer.Data); + builder.AddUshort(0xABCD); + Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 0, 0, 0xCD, 0xAB }, builder.DataBuffer.Data); + builder.AddUshort(0xDCBA); + Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 0xBA, 0xDC, 0xCD, 0xAB }, builder.DataBuffer.Data); + builder.EndVector(); + Assert.ArrayEqual(new byte[] { 2, 0, 0, 0, 0xBA, 0xDC, 0xCD, 0xAB }, builder.DataBuffer.Data); + } + + [FlatBuffersTestMethod] + public void TestCreateAsciiString() + { + var builder = new FlatBufferBuilder(1); + builder.CreateString("foo"); + Assert.ArrayEqual(new byte[] { 3, 0, 0, 0, (byte)'f', (byte)'o', (byte)'o', 0 }, builder.DataBuffer.Data); + + builder.CreateString("moop"); + Assert.ArrayEqual(new byte[] + { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, // Padding to 32 bytes + 4, 0, 0, 0, + (byte)'m', (byte)'o', (byte)'o', (byte)'p', + 0, 0, 0, 0, // zero terminator with 3 byte pad + 3, 0, 0, 0, + (byte)'f', (byte)'o', (byte)'o', 0 + }, builder.DataBuffer.Data); + } + + [FlatBuffersTestMethod] + public void TestCreateArbitarytring() + { + var builder = new FlatBufferBuilder(1); + builder.CreateString("\x01\x02\x03"); + Assert.ArrayEqual(new byte[] + { + 3, 0, 0, 0, + 0x01, 0x02, 0x03, 0 + }, builder.DataBuffer.Data); // No padding + builder.CreateString("\x04\x05\x06\x07"); + Assert.ArrayEqual(new byte[] + { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, // Padding to 32 bytes + 4, 0, 0, 0, + 0x04, 0x05, 0x06, 0x07, + 0, 0, 0, 0, // zero terminator with 3 byte pad + 3, 0, 0, 0, + 0x01, 0x02, 0x03, 0 + }, builder.DataBuffer.Data); // No padding + } + + [FlatBuffersTestMethod] + public void TestEmptyVTable() + { + var builder = new FlatBufferBuilder(1); + builder.StartObject(0); + Assert.ArrayEqual(new byte[] { 0 }, builder.DataBuffer.Data); + builder.EndObject(); + Assert.ArrayEqual(new byte[] + { + 4, 0, 4, 0, + 4, 0, 0, 0 + }, + builder.DataBuffer.Data); + } + + [FlatBuffersTestMethod] + public void TestVTableWithOneBool() + { + var builder = new FlatBufferBuilder(1); + builder.StartObject(1); + Assert.ArrayEqual(new byte[] { 0 }, builder.DataBuffer.Data); + builder.AddBool(0, true, false); + builder.EndObject(); + Assert.ArrayEqual(new byte[] + { + 0, 0, // padding to 16 bytes + 6, 0, // vtable bytes + 8, 0, // object length inc vtable offset + 7, 0, // start of bool value + 6, 0, 0, 0, // int32 offset for start of vtable + 0, 0, 0, // padding + 1, // value 0 + }, + builder.DataBuffer.Data); + } + + [FlatBuffersTestMethod] + public void TestVTableWithOneBool_DefaultValue() + { + var builder = new FlatBufferBuilder(1); + builder.StartObject(1); + Assert.ArrayEqual(new byte[] { 0 }, builder.DataBuffer.Data); + builder.AddBool(0, false, false); + builder.EndObject(); + Assert.ArrayEqual(new byte[] + { + 0, 0, 0, 0, 0, 0, // padding to 16 bytes + 6, 0, // vtable bytes + 4, 0, // end of object from here + 0, 0, // entry 0 is empty (default value) + 6, 0, 0, 0, // int32 offset for start of vtable + }, + builder.DataBuffer.Data); + } + + [FlatBuffersTestMethod] + public void TestVTableWithOneInt16() + { + var builder = new FlatBufferBuilder(1); + builder.StartObject(1); + Assert.ArrayEqual(new byte[] { 0 }, builder.DataBuffer.Data); + builder.AddShort(0, 0x789A, 0); + builder.EndObject(); + Assert.ArrayEqual(new byte[] + { + 0, 0, // padding to 16 bytes + 6, 0, // vtable bytes + 8, 0, // object length inc vtable offset + 6, 0, // start of int16 value + 6, 0, 0, 0, // int32 offset for start of vtable + 0, 0, // padding + 0x9A, 0x78, //value 0 + }, + builder.DataBuffer.Data); + } + + [FlatBuffersTestMethod] + public void TestVTableWithTwoInt16() + { + var builder = new FlatBufferBuilder(1); + builder.StartObject(2); + Assert.ArrayEqual(new byte[] { 0 }, builder.DataBuffer.Data); + builder.AddShort(0, 0x3456, 0); + builder.AddShort(1, 0x789A, 0); + builder.EndObject(); + Assert.ArrayEqual(new byte[] + { + 8, 0, // vtable bytes + 8, 0, // object length inc vtable offset + 6, 0, // start of int16 value 0 + 4, 0, // start of int16 value 1 + 8, 0, 0, 0, // int32 offset for start of vtable + 0x9A, 0x78, // value 1 + 0x56, 0x34, // value 0 + }, + builder.DataBuffer.Data); + } + + [FlatBuffersTestMethod] + public void TestVTableWithInt16AndBool() + { + var builder = new FlatBufferBuilder(1); + builder.StartObject(2); + Assert.ArrayEqual(new byte[] { 0 }, builder.DataBuffer.Data); + builder.AddShort(0, 0x3456, 0); + builder.AddBool(1, true, false); + builder.EndObject(); + Assert.ArrayEqual(new byte[] + { + 8, 0, // vtable bytes + 8, 0, // object length inc vtable offset + 6, 0, // start of int16 value 0 + 5, 0, // start of bool value 1 + 8, 0, 0, 0, // int32 offset for start of vtable + 0, 1, // padding + value 1 + 0x56, 0x34, // value 0 + }, + builder.DataBuffer.Data); + } + + [FlatBuffersTestMethod] + public void TestVTableWithEmptyVector() + { + var builder = new FlatBufferBuilder(1); + builder.StartVector(sizeof(byte), 0, 1); + var vecEnd = builder.EndVector(); + + builder.StartObject(1); + + builder.AddOffset(0, vecEnd.Value, 0); + builder.EndObject(); + Assert.ArrayEqual(new byte[] + { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, // Padding to 32 bytes + 6, 0, // vtable bytes + 8, 0, // object length inc vtable offset + 4, 0, // start of vector offset value 0 + 6, 0, 0, 0, // int32 offset for start of vtable + 4, 0, 0, 0, + 0, 0, 0, 0, + }, + builder.DataBuffer.Data); + } + + [FlatBuffersTestMethod] + public void TestVTableWithEmptyVectorAndScalars() + { + var builder = new FlatBufferBuilder(1); + builder.StartVector(sizeof(byte), 0, 1); + var vecEnd = builder.EndVector(); + + builder.StartObject(2); + builder.AddShort(0, 55, 0); + builder.AddOffset(1, vecEnd.Value, 0); + builder.EndObject(); + Assert.ArrayEqual(new byte[] + { + 0, 0, 0, 0, + 0, 0, 0, 0, // Padding to 32 bytes + 8, 0, // vtable bytes + 12, 0, // object length inc vtable offset + 10, 0, // offset to int16 value 0 + 4, 0, // start of vector offset value 1 + 8, 0, 0, 0, // int32 offset for start of vtable + 8, 0, 0, 0, // value 1 + 0, 0, 55, 0, // value 0 + 0, 0, 0, 0, // length of vector (not in sctruc) + }, + builder.DataBuffer.Data); + } + + + [FlatBuffersTestMethod] + public void TestVTableWith_1xInt16_and_Vector_or_2xInt16() + { + var builder = new FlatBufferBuilder(1); + builder.StartVector(sizeof(short), 2, 1); + builder.AddShort(0x1234); + builder.AddShort(0x5678); + var vecEnd = builder.EndVector(); + + builder.StartObject(2); + builder.AddOffset(1, vecEnd.Value, 0); + builder.AddShort(0, 55, 0); + builder.EndObject(); + Assert.ArrayEqual(new byte[] + { + 0, 0, 0, 0, // Padding to 32 bytes + 8, 0, // vtable bytes + 12, 0, // object length + 6, 0, // start of value 0 from end of vtable + 8, 0, // start of value 1 from end of buffer + 8, 0, 0, 0, // int32 offset for start of vtable + 0, 0, 55, 0, // padding + value 0 + 4, 0, 0, 0, // position of vector from here + 2, 0, 0, 0, // length of vector + 0x78, 0x56, // vector value 0 + 0x34, 0x12, // vector value 1 + }, + builder.DataBuffer.Data); + } + + [FlatBuffersTestMethod] + public void TestVTableWithAStruct_of_int8_int16_int32() + { + var builder = new FlatBufferBuilder(1); + builder.StartObject(1); + builder.Prep(4+4+4, 0); + builder.AddSbyte(55); + builder.Pad(3); + builder.AddShort(0x1234); + builder.Pad(2); + builder.AddInt(0x12345678); + var structStart = builder.Offset; + builder.AddStruct(0, structStart, 0); + builder.EndObject(); + Assert.ArrayEqual(new byte[] + { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, // Padding to 32 bytes + 6, 0, // vtable bytes + 16, 0, // object length + 4, 0, // start of struct from here + 6, 0, 0, 0, // int32 offset for start of vtable + 0x78, 0x56, 0x34, 0x12, // struct value 2 + 0x00, 0x00, 0x34, 0x12, // struct value 1 + 0x00, 0x00, 0x00, 55, // struct value 0 + }, + builder.DataBuffer.Data); + } + + [FlatBuffersTestMethod] + public void TestVTableWithAVectorOf_2xStructOf_2xInt8() + { + var builder = new FlatBufferBuilder(1); + builder.StartVector(sizeof(byte)*2, 2, 1); + builder.AddByte(33); + builder.AddByte(44); + builder.AddByte(55); + builder.AddByte(66); + var vecEnd = builder.EndVector(); + + builder.StartObject(1); + builder.AddOffset(0, vecEnd.Value, 0); + builder.EndObject(); + + Assert.ArrayEqual(new byte[] + { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, // Padding to 32 bytes + 6, 0, // vtable bytes + 8, 0, // object length + 4, 0, // offset of vector offset + 6, 0, 0, 0, // int32 offset for start of vtable + 4, 0, 0, 0, // Vector start offset + 2, 0, 0, 0, // Vector len + 66, // vector 1, 1 + 55, // vector 1, 0 + 44, // vector 0, 1 + 33, // vector 0, 0 + }, + builder.DataBuffer.Data); + } + + [FlatBuffersTestMethod] + public void TestVTableWithSomeElements() + { + var builder = new FlatBufferBuilder(1); + builder.StartObject(2); + builder.AddByte(0, 33, 0); + builder.AddShort(1, 66, 0); + var off = builder.EndObject(); + builder.Finish(off); + + Assert.ArrayEqual(new byte[] + { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, //Padding to 32 bytes + 12, 0, 0, 0, // root of table, pointing to vtable offset + 8, 0, // vtable bytes + 8, 0, // object length + 7, 0, // start of value 0 + 4, 0, // start of value 1 + 8, 0, 0, 0, // int32 offset for start of vtable + 66, 0, // value 1 + 0, 33, // value 0 + + }, + builder.DataBuffer.Data); + } + + [FlatBuffersTestMethod] + public void TestTwoFinishTable() + { + var builder = new FlatBufferBuilder(1); + builder.StartObject(2); + builder.AddByte(0, 33, 0); + builder.AddByte(1, 44, 0); + var off0 = builder.EndObject(); + builder.Finish(off0); + + builder.StartObject(3); + builder.AddByte(0, 55, 0); + builder.AddByte(1, 66, 0); + builder.AddByte(2, 77, 0); + var off1 = builder.EndObject(); + builder.Finish(off1); + + Assert.ArrayEqual(new byte[] + { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, // padding to 64 bytes + 16, 0, 0, 0, // root of table, pointing to vtable offset (obj1) + 0, 0, // padding + + 10, 0, // vtable bytes + 8, 0, // object length + 7, 0, // start of value 0 + 6, 0, // start of value 1 + 5, 0, // start of value 2 + 10, 0, 0, 0, // int32 offset for start of vtable + 0, // pad + 77, // values 2, 1, 0 + 66, + 55, + + 12, 0, 0, 0, // root of table, pointing to vtable offset (obj0) + 8, 0, // vtable bytes + 8, 0, // object length + 7, 0, // start of value 0 + 6, 0, // start of value 1 + 8, 0, 0, 0, // int32 offset for start of vtable + 0, 0, // pad + 44, // value 1, 0 + 33, + }, + builder.DataBuffer.Data); + } + + [FlatBuffersTestMethod] + public void TestBunchOfBools() + { + var builder = new FlatBufferBuilder(1); + builder.StartObject(8); + for (var i = 0; i < 8; i++) + { + builder.AddBool(i, true, false); + } + var off = builder.EndObject(); + builder.Finish(off); + + Assert.ArrayEqual(new byte[] + { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, // padding to 64 bytes + + 24, 0, 0, 0, // root of table, pointing to vtable offset (obj0) + 20, 0, // vtable bytes + 12, 0, // object length + 11, 0, // start of value 0 + 10, 0, // start of value 1 + 9, 0, // start of value 2 + 8, 0, // start of value 3 + 7, 0, // start of value 4 + 6, 0, // start of value 5 + 5, 0, // start of value 6 + 4, 0, // start of value 7 + + 20, 0, 0, 0, // int32 offset for start of vtable + + 1, 1, 1, 1, // values + 1, 1, 1, 1, + + }, + builder.DataBuffer.Data); + } + + [FlatBuffersTestMethod] + public void TestWithFloat() + { + var builder = new FlatBufferBuilder(1); + builder.StartObject(1); + builder.AddFloat(0, 1, 0); + builder.EndObject(); + + + Assert.ArrayEqual(new byte[] + { + 0, 0, + 6, 0, // vtable bytes + 8, 0, // object length + 4, 0, // start of value 0 + 6, 0, 0, 0, // int32 offset for start of vtable + 0, 0, 128, 63, // value + + }, + builder.DataBuffer.Data); + } + + private void CheckObjects(int fieldCount, int objectCount) + { + _lcg.Reset(); + + const int testValuesMax = 11; + + var builder = new FlatBufferBuilder(1); + + var objects = new int[objectCount]; + + for (var i = 0; i < objectCount; ++i) + { + builder.StartObject(fieldCount); + + for (var j = 0; j < fieldCount; ++j) + { + var fieldType = _lcg.Next()%testValuesMax; + + switch (fieldType) + { + case 0: + { + builder.AddBool(j, FuzzTestData.BoolValue, false); + break; + } + case 1: + { + builder.AddSbyte(j, FuzzTestData.Int8Value, 0); + break; + } + case 2: + { + builder.AddByte(j, FuzzTestData.UInt8Value, 0); + break; + } + case 3: + { + builder.AddShort(j, FuzzTestData.Int16Value, 0); + break; + } + case 4: + { + builder.AddUshort(j, FuzzTestData.UInt16Value, 0); + break; + } + case 5: + { + builder.AddInt(j, FuzzTestData.Int32Value, 0); + break; + } + case 6: + { + builder.AddUint(j, FuzzTestData.UInt32Value, 0); + break; + } + case 7: + { + builder.AddLong(j, FuzzTestData.Int64Value, 0); + break; + } + case 8: + { + builder.AddUlong(j, FuzzTestData.UInt64Value, 0); + break; + } + case 9: + { + builder.AddFloat(j, FuzzTestData.Float32Value, 0); + break; + } + case 10: + { + builder.AddDouble(j, FuzzTestData.Float64Value, 0); + break; + } + default: + throw new Exception("Unreachable"); + } + + } + + var offset = builder.EndObject(); + + // Store the object offset + objects[i] = offset; + } + + _lcg.Reset(); + + // Test all objects are readable and return expected values... + for (var i = 0; i < objectCount; ++i) + { + var table = new TestTable(builder.DataBuffer, builder.DataBuffer.Length - objects[i]); + + for (var j = 0; j < fieldCount; ++j) + { + var fieldType = _lcg.Next() % testValuesMax; + var fc = 2 + j; // 2 == VtableMetadataFields + var f = fc * 2; + + switch (fieldType) + { + case 0: + { + Assert.AreEqual(FuzzTestData.BoolValue, table.GetSlot(f, false)); + break; + } + case 1: + { + Assert.AreEqual(FuzzTestData.Int8Value, table.GetSlot(f, (sbyte)0)); + break; + } + case 2: + { + Assert.AreEqual(FuzzTestData.UInt8Value, table.GetSlot(f, (byte)0)); + break; + } + case 3: + { + Assert.AreEqual(FuzzTestData.Int16Value, table.GetSlot(f, (short)0)); + break; + } + case 4: + { + Assert.AreEqual(FuzzTestData.UInt16Value, table.GetSlot(f, (ushort)0)); + break; + } + case 5: + { + Assert.AreEqual(FuzzTestData.Int32Value, table.GetSlot(f, (int)0)); + break; + } + case 6: + { + Assert.AreEqual(FuzzTestData.UInt32Value, table.GetSlot(f, (uint)0)); + break; + } + case 7: + { + Assert.AreEqual(FuzzTestData.Int64Value, table.GetSlot(f, (long)0)); + break; + } + case 8: + { + Assert.AreEqual(FuzzTestData.UInt64Value, table.GetSlot(f, (ulong)0)); + break; + } + case 9: + { + Assert.AreEqual(FuzzTestData.Float32Value, table.GetSlot(f, (float)0)); + break; + } + case 10: + { + Assert.AreEqual(FuzzTestData.Float64Value, table.GetSlot(f, (double)0)); + break; + } + default: + throw new Exception("Unreachable"); + } + + } + + } + + } + } +} diff --git a/tests/FlatBuffers.Test/FlatBuffersTestClassAttribute.cs b/tests/FlatBuffers.Test/FlatBuffersTestClassAttribute.cs new file mode 100644 index 000000000..f43b8ce79 --- /dev/null +++ b/tests/FlatBuffers.Test/FlatBuffersTestClassAttribute.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace FlatBuffers.Test +{ + [AttributeUsage(AttributeTargets.Class)] + public class FlatBuffersTestClassAttribute : Attribute + { + } +} diff --git a/tests/FlatBuffers.Test/FlatBuffersTestMethodAttribute.cs b/tests/FlatBuffers.Test/FlatBuffersTestMethodAttribute.cs new file mode 100644 index 000000000..38d448868 --- /dev/null +++ b/tests/FlatBuffers.Test/FlatBuffersTestMethodAttribute.cs @@ -0,0 +1,9 @@ +using System; + +namespace FlatBuffers.Test +{ + [AttributeUsage(AttributeTargets.Method)] + public class FlatBuffersTestMethodAttribute : Attribute + { + } +} \ No newline at end of file diff --git a/tests/FlatBuffers.Test/FuzzTestData.cs b/tests/FlatBuffers.Test/FuzzTestData.cs new file mode 100644 index 000000000..b0447adbf --- /dev/null +++ b/tests/FlatBuffers.Test/FuzzTestData.cs @@ -0,0 +1,22 @@ +using System; + +namespace FlatBuffers.Test +{ + internal static class FuzzTestData + { + private static readonly byte[] _overflowInt32 = new byte[] {0x83, 0x33, 0x33, 0x33}; + private static readonly byte[] _overflowInt64 = new byte[] { 0x84, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 }; + + public static readonly bool BoolValue = true; + public static readonly sbyte Int8Value = -127; // 0x81 + public static readonly byte UInt8Value = 255; // 0xFF + public static readonly short Int16Value = -32222; // 0x8222; + public static readonly ushort UInt16Value = 65262; // 0xFEEE + public static readonly int Int32Value = BitConverter.ToInt32(_overflowInt32, 0); + public static readonly uint UInt32Value = 0xFDDDDDDD; + public static readonly long Int64Value = BitConverter.ToInt64(_overflowInt64, 0); + public static readonly ulong UInt64Value = 0xFCCCCCCCCCCCCCCC; + public static readonly float Float32Value = 3.14159f; + public static readonly double Float64Value = 3.14159265359; + } +} \ No newline at end of file diff --git a/tests/FlatBuffers.Test/Lcg.cs b/tests/FlatBuffers.Test/Lcg.cs new file mode 100644 index 000000000..1182640dc --- /dev/null +++ b/tests/FlatBuffers.Test/Lcg.cs @@ -0,0 +1,26 @@ +namespace FlatBuffers.Test +{ + /// + /// Lcg Pseudo RNG + /// + internal sealed class Lcg + { + private const uint InitialValue = 10000; + private uint _state; + + public Lcg() + { + _state = InitialValue; + } + + public uint Next() + { + return (_state = 69069 * _state + 362437); + } + + public void Reset() + { + _state = InitialValue; + } + } +} \ No newline at end of file diff --git a/tests/FlatBuffers.Test/Program.cs b/tests/FlatBuffers.Test/Program.cs index 91cb6941e..aa497cef4 100644 --- a/tests/FlatBuffers.Test/Program.cs +++ b/tests/FlatBuffers.Test/Program.cs @@ -15,6 +15,7 @@ */ using System; +using System.Collections.Generic; using System.Linq; using System.Reflection; @@ -24,39 +25,43 @@ namespace FlatBuffers.Test { public static int Main(string[] args) { - var tests = new FlatBuffersExampleTests(); - try + var testResults = new List(); + + var testClasses = Assembly.GetExecutingAssembly().GetExportedTypes() + .Where(t => t.IsClass && t.GetCustomAttributes(typeof (FlatBuffersTestClassAttribute), false).Length > 0); + + foreach (var testClass in testClasses) { - tests.RunTests(); + var methods = testClass.GetMethods(BindingFlags.Public | + BindingFlags.Instance) + .Where(m => m.GetCustomAttributes(typeof(FlatBuffersTestMethodAttribute), false).Length > 0); + + var inst = Activator.CreateInstance(testClass); + + foreach (var method in methods) + { + try + { + method.Invoke(inst, new object[] { }); + testResults.Add(true); + } + catch (Exception ex) + { + Console.WriteLine("{0}: FAILED when invoking {1} with error {2}", + testClass.Name ,method.Name, ex.GetBaseException()); + testResults.Add(false); + } + } } - catch (Exception ex) + + var failedCount = testResults.Count(i => i == false); + + Console.WriteLine("{0} tests run, {1} failed", testResults.Count, failedCount); + + if (failedCount > 0) { - Console.WriteLine("FlatBuffersExampleTests FAILED - {0}", ex.GetBaseException()); return -1; } - - // Run ByteBuffers Tests - var testClass = new ByteBufferTests(); - - var methods = testClass.GetType().GetMethods(BindingFlags.Public | - BindingFlags.Instance) - .Where(m => m.Name.StartsWith("ByteBuffer_")); - foreach (var method in methods) - { - try - { - method.Invoke(testClass, new object[] { }); - } - catch (Exception ex) - { - Console.WriteLine("ByteBufferTests FAILED when invoking {0} with error {1}", - method.Name, ex.GetBaseException()); - return -1; - } - - } - - Console.WriteLine("FlatBuffers test: completed successfully"); return 0; } } diff --git a/tests/FlatBuffers.Test/TestTable.cs b/tests/FlatBuffers.Test/TestTable.cs new file mode 100644 index 000000000..89a507ec7 --- /dev/null +++ b/tests/FlatBuffers.Test/TestTable.cs @@ -0,0 +1,135 @@ +namespace FlatBuffers.Test +{ + /// + /// A test Table object that gives easy access to the slot data + /// + internal class TestTable : Table + { + public TestTable(ByteBuffer bb, int pos) + { + base.bb = bb; + base.bb_pos = pos; + } + + public bool GetSlot(int slot, bool def) + { + var off = base.__offset(slot); + + if (off == 0) + { + return def; + } + return bb.GetSbyte(bb_pos + off) != 0; + } + + public sbyte GetSlot(int slot, sbyte def) + { + var off = base.__offset(slot); + + if (off == 0) + { + return def; + } + return bb.GetSbyte(bb_pos + off); + } + + public byte GetSlot(int slot, byte def) + { + var off = base.__offset(slot); + + if (off == 0) + { + return def; + } + return bb.Get(bb_pos + off); + } + + public short GetSlot(int slot, short def) + { + var off = base.__offset(slot); + + if (off == 0) + { + return def; + } + return bb.GetShort(bb_pos + off); + } + + public ushort GetSlot(int slot, ushort def) + { + var off = base.__offset(slot); + + if (off == 0) + { + return def; + } + return bb.GetUshort(bb_pos + off); + } + + public int GetSlot(int slot, int def) + { + var off = base.__offset(slot); + + if (off == 0) + { + return def; + } + return bb.GetInt(bb_pos + off); + } + + public uint GetSlot(int slot, uint def) + { + var off = base.__offset(slot); + + if (off == 0) + { + return def; + } + return bb.GetUint(bb_pos + off); + } + + public long GetSlot(int slot, long def) + { + var off = base.__offset(slot); + + if (off == 0) + { + return def; + } + return bb.GetLong(bb_pos + off); + } + + public ulong GetSlot(int slot, ulong def) + { + var off = base.__offset(slot); + + if (off == 0) + { + return def; + } + return bb.GetUlong(bb_pos + off); + } + + public float GetSlot(int slot, float def) + { + var off = base.__offset(slot); + + if (off == 0) + { + return def; + } + return bb.GetFloat(bb_pos + off); + } + + public double GetSlot(int slot, double def) + { + var off = base.__offset(slot); + + if (off == 0) + { + return def; + } + return bb.GetDouble(bb_pos + off); + } + } +} \ No newline at end of file