Squashed 'third_party/flatbuffers/' content from commit acc9990ab

Change-Id: I48550d40d78fea996ebe74e9723a5d1f910de491
git-subtree-dir: third_party/flatbuffers
git-subtree-split: acc9990abd2206491480291b0f85f925110102ea
diff --git a/tests/FlatBuffers.Test/Assert.cs b/tests/FlatBuffers.Test/Assert.cs
new file mode 100644
index 0000000..488c338
--- /dev/null
+++ b/tests/FlatBuffers.Test/Assert.cs
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2014 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;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace FlatBuffers.Test
+{
+
+    public class AssertFailedException : Exception
+    {
+        private readonly object _expected;
+        private readonly object _actual;
+
+        public AssertFailedException(object expected, object actual)
+        {
+            _expected = expected;
+            _actual = actual;
+        }
+
+        public override string Message
+        {
+            get { return string.Format("Expected {0} but saw {1}", _expected, _actual); }
+        }
+    }
+
+    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;
+
+        public AssertUnexpectedThrowException(object expected)
+        {
+            _expected = expected;
+        }
+
+        public override string Message
+        {
+            get { return string.Format("Expected exception of type {0}", _expected); }
+        }
+    }
+
+    public static class Assert
+    {
+        public static void AreEqual<T>(T expected, T actual)
+        {
+            if (!expected.Equals(actual))
+            {
+                throw new AssertFailedException(expected, actual);
+            }
+        }
+
+        public static void ArrayEqual<T>(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)
+            {
+                throw new AssertFailedException(true, value);
+            }
+        }
+
+        public static void IsFalse(bool value)
+        {
+            if (value)
+            {
+                throw new AssertFailedException(false, value);
+            }
+        }
+
+        public static void Throws<T>(Action action) where T : Exception
+        {
+            var caught = false;
+            try
+            {
+                action();
+            }
+            catch (T)
+            {
+                caught = true;
+            }
+
+            if (!caught)
+            {
+                throw new AssertUnexpectedThrowException(typeof (T));
+            }
+        }
+    }
+}
diff --git a/tests/FlatBuffers.Test/ByteBufferTests.cs b/tests/FlatBuffers.Test/ByteBufferTests.cs
new file mode 100644
index 0000000..1c33a2f
--- /dev/null
+++ b/tests/FlatBuffers.Test/ByteBufferTests.cs
@@ -0,0 +1,612 @@
+/*
+ * Copyright 2014 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 ByteBufferTests
+    {
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_Length_MatchesBufferLength()
+        {
+            var buffer = new byte[1000];
+            var uut = new ByteBuffer(buffer);
+            Assert.AreEqual(buffer.Length, uut.Length);
+        }
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_PutBytePopulatesBufferAtZeroOffset()
+        {
+            var buffer = new byte[1];
+            var uut = new ByteBuffer(buffer);
+            uut.PutByte(0, (byte)99);
+
+            Assert.AreEqual((byte)99, buffer[0]);
+        }
+
+#if !BYTEBUFFER_NO_BOUNDS_CHECK
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_PutByteCannotPutAtOffsetPastLength()
+        {
+            var uut = new ByteBuffer(1);
+            Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutByte(1, 99));
+        }
+#endif
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_PutShortPopulatesBufferCorrectly()
+        {
+            var buffer = new byte[2];
+            var uut = new ByteBuffer(buffer);
+            uut.PutShort(0, (short)1);
+
+            // Ensure Endianness was written correctly
+            Assert.AreEqual((byte)1, buffer[0]);
+            Assert.AreEqual((byte)0, buffer[1]);
+        }
+
+#if !BYTEBUFFER_NO_BOUNDS_CHECK
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_PutShortCannotPutAtOffsetPastLength()
+        {
+            var uut = new ByteBuffer(2);
+            Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutShort(2, 99));
+        }
+#endif
+
+#if !BYTEBUFFER_NO_BOUNDS_CHECK
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_PutShortChecksLength()
+        {
+            var uut = new ByteBuffer(1);
+            Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutShort(0, 99));
+        }
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_PutShortChecksLengthAndOffset()
+        {
+            var uut = new ByteBuffer(2);
+            Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutShort(1, 99));
+        }
+#endif
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_PutIntPopulatesBufferCorrectly()
+        {
+            var buffer = new byte[4];
+            var uut = new ByteBuffer(buffer);
+            uut.PutInt(0, 0x0A0B0C0D);
+
+            // Ensure Endianness was written correctly
+            Assert.AreEqual(0x0D, buffer[0]);
+            Assert.AreEqual(0x0C, buffer[1]);
+            Assert.AreEqual(0x0B, buffer[2]);
+            Assert.AreEqual(0x0A, buffer[3]);
+        }
+
+#if !BYTEBUFFER_NO_BOUNDS_CHECK
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_PutIntCannotPutAtOffsetPastLength()
+        {
+            var uut = new ByteBuffer(4);
+            Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutInt(2, 0x0A0B0C0D));
+        }
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_PutIntChecksLength()
+        {
+            var uut = new ByteBuffer(1);
+            Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutInt(0, 0x0A0B0C0D));
+        }
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_PutIntChecksLengthAndOffset()
+        {
+            var uut = new ByteBuffer(4);
+            Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutInt(2, 0x0A0B0C0D));
+        }
+#endif
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_PutLongPopulatesBufferCorrectly()
+        {
+            var buffer = new byte[8];
+            var uut = new ByteBuffer(buffer);
+            uut.PutLong(0, 0x010203040A0B0C0D);
+
+            // Ensure Endianness was written correctly
+            Assert.AreEqual(0x0D, buffer[0]);
+            Assert.AreEqual(0x0C, buffer[1]);
+            Assert.AreEqual(0x0B, buffer[2]);
+            Assert.AreEqual(0x0A, buffer[3]);
+            Assert.AreEqual(0x04, buffer[4]);
+            Assert.AreEqual(0x03, buffer[5]);
+            Assert.AreEqual(0x02, buffer[6]);
+            Assert.AreEqual(0x01, buffer[7]);
+        }
+
+#if !BYTEBUFFER_NO_BOUNDS_CHECK
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_PutLongCannotPutAtOffsetPastLength()
+        {
+            var uut = new ByteBuffer(8);
+            Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutLong(2, 0x010203040A0B0C0D));
+        }
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_PutLongChecksLength()
+        {
+            var uut = new ByteBuffer(1);
+            Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutLong(0, 0x010203040A0B0C0D));
+        }
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_PutLongChecksLengthAndOffset()
+        {
+            var uut = new ByteBuffer(8);
+            Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutLong(2, 0x010203040A0B0C0D));
+        }
+#endif
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_GetByteReturnsCorrectData()
+        {
+            var buffer = new byte[1];
+            buffer[0] = 99;
+            var uut = new ByteBuffer(buffer);
+            Assert.AreEqual((byte)99, uut.Get(0));
+        }
+
+#if !BYTEBUFFER_NO_BOUNDS_CHECK
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_GetByteChecksOffset()
+        {
+            var uut = new ByteBuffer(1);
+            Assert.Throws<ArgumentOutOfRangeException>(() => uut.Get(1));
+        }
+#endif
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_GetShortReturnsCorrectData()
+        {
+            var buffer = new byte[2];
+            buffer[0] = 1;
+            buffer[1] = 0;
+            var uut = new ByteBuffer(buffer);
+            Assert.AreEqual(1, uut.GetShort(0));
+        }
+
+#if !BYTEBUFFER_NO_BOUNDS_CHECK
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_GetShortChecksOffset()
+        {
+            var uut = new ByteBuffer(2);
+            Assert.Throws<ArgumentOutOfRangeException>(() => uut.GetShort(2));
+        }
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_GetShortChecksLength()
+        {
+            var uut = new ByteBuffer(2);
+            Assert.Throws<ArgumentOutOfRangeException>(() => uut.GetShort(1));
+        }
+#endif
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_GetIntReturnsCorrectData()
+        {
+            var buffer = new byte[4];
+            buffer[0] = 0x0D;
+            buffer[1] = 0x0C;
+            buffer[2] = 0x0B;
+            buffer[3] = 0x0A;
+            var uut = new ByteBuffer(buffer);
+            Assert.AreEqual(0x0A0B0C0D, uut.GetInt(0));
+        }
+
+#if !BYTEBUFFER_NO_BOUNDS_CHECK
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_GetIntChecksOffset()
+        {
+            var uut = new ByteBuffer(4);
+            Assert.Throws<ArgumentOutOfRangeException>(() => uut.GetInt(4));
+        }
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_GetIntChecksLength()
+        {
+            var uut = new ByteBuffer(2);
+            Assert.Throws<ArgumentOutOfRangeException>(() => uut.GetInt(0));
+        }
+#endif
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_GetLongReturnsCorrectData()
+        {
+            var buffer = new byte[8];
+            buffer[0] = 0x0D;
+            buffer[1] = 0x0C;
+            buffer[2] = 0x0B;
+            buffer[3] = 0x0A;
+            buffer[4] = 0x04;
+            buffer[5] = 0x03;
+            buffer[6] = 0x02;
+            buffer[7] = 0x01;
+            var uut = new ByteBuffer(buffer);
+            Assert.AreEqual(0x010203040A0B0C0D, uut.GetLong(0));
+        }
+
+#if !BYTEBUFFER_NO_BOUNDS_CHECK
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_GetLongChecksOffset()
+        {
+            var uut = new ByteBuffer(8);
+            Assert.Throws<ArgumentOutOfRangeException>(() => uut.GetLong(8));
+        }
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_GetLongChecksLength()
+        {
+            var uut = new ByteBuffer(7);
+            Assert.Throws<ArgumentOutOfRangeException>(() => uut.GetLong(0));
+        }
+#endif
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_ReverseBytesUshort()
+        {
+            const ushort original = (ushort)0x1234U;
+            var reverse = ByteBuffer.ReverseBytes(original);
+            Assert.AreEqual(0x3412U, reverse);
+
+            var rereverse = ByteBuffer.ReverseBytes(reverse);
+            Assert.AreEqual(original, rereverse);
+        }
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_ReverseBytesUint()
+        {
+            const uint original = 0x12345678;
+            var reverse = ByteBuffer.ReverseBytes(original);
+            Assert.AreEqual(0x78563412U, reverse);
+
+            var rereverse = ByteBuffer.ReverseBytes(reverse);
+            Assert.AreEqual(original, rereverse);
+        }
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_ReverseBytesUlong()
+        {
+            const ulong original = 0x1234567890ABCDEFUL;
+            var reverse = ByteBuffer.ReverseBytes(original);
+            Assert.AreEqual(0xEFCDAB9078563412UL, reverse);
+
+            var rereverse = ByteBuffer.ReverseBytes(reverse);
+            Assert.AreEqual(original, rereverse);
+        }
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_ToFullArray_MatchesBuffer()
+        {
+            var buffer = new byte[4];
+            buffer[0] = 0x0D;
+            buffer[1] = 0x0C;
+            buffer[2] = 0x0B;
+            buffer[3] = 0x0A;
+            var uut = new ByteBuffer(buffer);
+            Assert.ArrayEqual(buffer, uut.ToFullArray());
+        }
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_ToSizedArray_MatchesBuffer()
+        {
+            var buffer = new byte[4];
+            buffer[0] = 0x0D;
+            buffer[1] = 0x0C;
+            buffer[2] = 0x0B;
+            buffer[3] = 0x0A;
+            var uut = new ByteBuffer(buffer);
+            Assert.ArrayEqual(buffer, uut.ToFullArray());
+        }
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_Duplicate_MatchesBuffer()
+        {
+            var buffer = new byte[4];
+            buffer[0] = 0x0D;
+            buffer[1] = 0x0C;
+            buffer[2] = 0x0B;
+            buffer[3] = 0x0A;
+            var uut = new ByteBuffer(buffer);
+            Assert.AreEqual(0x0A0B0C0D, uut.GetInt(0));
+
+            // Advance by two bytes
+            uut.Position = 2; uut = uut.Duplicate();
+            Assert.AreEqual(0x0A0B, uut.GetShort(2));
+
+            // Advance by one more byte
+            uut.Position = 1; uut = uut.Duplicate();
+            Assert.AreEqual(0x0A, uut.Get(3));
+        }
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_To_Array_Float()
+        {
+            const int len = 9;
+
+            // Construct the data array
+            var fData = new float[len];
+            fData[0] = 1.0079F;
+            fData[1] = 4.0026F;
+            fData[2] = 6.941F;
+            fData[3] = 9.0122F;
+            fData[4] = 10.811F;
+            fData[5] = 12.0107F;
+            fData[6] = 14.0067F;
+            fData[7] = 15.9994F;
+            fData[8] = 18.9984F;
+
+            // Tranfer it to a byte array
+            var buffer = new byte[sizeof(float) * fData.Length];
+            Buffer.BlockCopy(fData, 0, buffer, 0, buffer.Length);
+
+            // Create the Byte Buffer from byte array
+            var uut = new ByteBuffer(buffer);
+
+            // Get the full array back out and ensure they are equivalent
+            var bbArray = uut.ToArray<float>(0, len);
+            Assert.ArrayEqual(fData, bbArray);
+
+            // Get a portion of the full array back out and ensure the
+            // subrange agrees
+            var bbArray2 = uut.ToArray<float>(4, len - 1);
+            Assert.AreEqual(bbArray2.Length, len - 1);
+            for (int i = 1; i < len - 1; i++)
+            {
+                Assert.AreEqual(fData[i], bbArray2[i - 1]);
+            }
+
+            // Get a sub portion of the full array back out and ensure the
+            // subrange agrees
+            var bbArray3 = uut.ToArray<float>(8, len - 4);
+            Assert.AreEqual(bbArray3.Length, len - 4);
+            for (int i = 2; i < len - 4; i++)
+            {
+                Assert.AreEqual(fData[i], bbArray3[i - 2]);
+            }
+        }
+
+        public void ByteBuffer_Put_Array_Helper<T>(T[] data, int typeSize)
+            where T : struct
+        {
+            // Create the Byte Buffer
+            var uut = new ByteBuffer(1024);
+
+            // Put the data into the buffer and make sure the offset is
+            // calculated correctly
+            int nOffset = uut.Put(1024, data);
+            Assert.AreEqual(1024 - typeSize * data.Length, nOffset);
+
+            // Get the full array back out and ensure they are equivalent
+            var bbArray = uut.ToArray<T>(nOffset, data.Length);
+            Assert.ArrayEqual(data, bbArray);
+        }
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_Put_Array_Float()
+        {
+            const int len = 9;
+
+            // Construct the data array
+            var data = new float[len];
+            data[0] = 1.0079F;
+            data[1] = 4.0026F;
+            data[2] = 6.941F;
+            data[3] = 9.0122F;
+            data[4] = 10.811F;
+            data[5] = 12.0107F;
+            data[6] = 14.0067F;
+            data[7] = 15.9994F;
+            data[8] = 18.9984F;
+
+            ByteBuffer_Put_Array_Helper(data, sizeof(float));
+        }
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_Put_Array_Double()
+        {
+            const int len = 9;
+
+            // Construct the data array
+            var data = new double[len];
+            data[0] = 1.0079;
+            data[1] = 4.0026;
+            data[2] = 6.941;
+            data[3] = 9.0122;
+            data[4] = 10.811;
+            data[5] = 12.0107;
+            data[6] = 14.0067;
+            data[7] = 15.9994;
+            data[8] = 18.9984;
+
+            ByteBuffer_Put_Array_Helper(data, sizeof(double));
+        }
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_Put_Array_Int()
+        {
+            const int len = 9;
+
+            // Construct the data array
+            var data = new int[len];
+            data[0] = 1;
+            data[1] = 4;
+            data[2] = 6;
+            data[3] = 9;
+            data[4] = 10;
+            data[5] = 12;
+            data[6] = 14;
+            data[7] = 15;
+            data[8] = 18;
+
+            ByteBuffer_Put_Array_Helper(data, sizeof(int));
+        }
+
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_Put_Array_UInt()
+        {
+            const int len = 9;
+
+            // Construct the data array
+            var data = new uint[len];
+            data[0] = 1;
+            data[1] = 4;
+            data[2] = 6;
+            data[3] = 9;
+            data[4] = 10;
+            data[5] = 12;
+            data[6] = 14;
+            data[7] = 15;
+            data[8] = 18;
+
+            ByteBuffer_Put_Array_Helper(data, sizeof(uint));
+        }
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_Put_Array_Bool()
+        {
+            const int len = 9;
+
+            // Construct the data array
+            var data = new bool[len];
+            data[0] = true;
+            data[1] = true;
+            data[2] = false;
+            data[3] = true;
+            data[4] = false;
+            data[5] = true;
+            data[6] = true;
+            data[7] = true;
+            data[8] = false;
+
+            ByteBuffer_Put_Array_Helper(data, sizeof(bool));
+        }
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_Put_Array_Long()
+        {
+            const int len = 9;
+
+            // Construct the data array
+            var data = new long[len];
+            data[0] = 1;
+            data[1] = 4;
+            data[2] = 6;
+            data[3] = 9;
+            data[4] = 10;
+            data[5] = 12;
+            data[6] = 14;
+            data[7] = 15;
+            data[8] = 18;
+
+            ByteBuffer_Put_Array_Helper(data, sizeof(long));
+        }
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_Put_Array_Byte()
+        {
+            const int len = 9;
+
+            // Construct the data array
+            var data = new byte[len];
+            data[0] = 1;
+            data[1] = 4;
+            data[2] = 6;
+            data[3] = 9;
+            data[4] = 10;
+            data[5] = 12;
+            data[6] = 14;
+            data[7] = 15;
+            data[8] = 18;
+
+            ByteBuffer_Put_Array_Helper(data, sizeof(byte));
+        }
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_Put_Array_SByte()
+        {
+            const int len = 9;
+
+            // Construct the data array
+            var data = new sbyte[len];
+            data[0] = 1;
+            data[1] = 4;
+            data[2] = 6;
+            data[3] = 9;
+            data[4] = 10;
+            data[5] = 12;
+            data[6] = 14;
+            data[7] = 15;
+            data[8] = 18;
+
+            ByteBuffer_Put_Array_Helper(data, sizeof(sbyte));
+        }
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_Put_Array_Null_Throws()
+        {
+            // Create the Byte Buffer
+            var uut = new ByteBuffer(1024);
+
+            // create a null array and try to put it into the buffer
+            float[] data = null;
+            Assert.Throws<ArgumentNullException>(() => uut.Put(1024, data));
+        }
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_Put_Array_Empty_Throws()
+        {
+            // Create the Byte Buffer
+            var uut = new ByteBuffer(1024);
+
+            // create an array of length == 0, and try to put it into the buffer
+            float[] data = new float[0];
+            Assert.Throws<ArgumentException>(() => uut.Put(1024, data));
+        }
+
+        private struct dummyStruct
+        {
+            int a;
+            float b;
+        }
+
+        [FlatBuffersTestMethod]
+        public void ByteBuffer_Put_Array_IncorrectType_Throws()
+        {
+            // Create the Byte Buffer
+            var uut = new ByteBuffer(1024);
+
+            // Create an array of dummy structures that shouldn't be
+            // able to be put into the buffer
+            var data = new dummyStruct[10];
+            Assert.Throws<ArgumentException>(() => uut.Put(1024, data));
+        }
+    }
+}
diff --git a/tests/FlatBuffers.Test/FlatBufferBuilderTests.cs b/tests/FlatBuffers.Test/FlatBufferBuilderTests.cs
new file mode 100644
index 0000000..d2f49f7
--- /dev/null
+++ b/tests/FlatBuffers.Test/FlatBufferBuilderTests.cs
@@ -0,0 +1,354 @@
+/*
+ * Copyright 2016 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 FlatBufferBuilderTests
+    {
+        private FlatBufferBuilder CreateBuffer(bool forceDefaults = true)
+        {
+            var fbb = new FlatBufferBuilder(16) {ForceDefaults = forceDefaults};
+            fbb.StartTable(1);
+            return fbb;
+        }
+
+        [FlatBuffersTestMethod]
+        public void FlatBufferBuilder_WithForceDefaults_WhenAddBool_AndDefaultValue_OffsetIncreasesBySize()
+        {
+            var fbb = CreateBuffer();
+            var storedOffset = fbb.Offset;
+            fbb.AddBool(0, false, false);
+            var endOffset = fbb.Offset;
+            Assert.AreEqual(sizeof(bool), endOffset-storedOffset);
+        }
+
+        [FlatBuffersTestMethod]
+        public void FlatBufferBuilder_WithForceDefaults_WhenAddSByte_AndDefaultValue_OffsetIncreasesBySize()
+        {
+            var fbb = CreateBuffer();
+            var storedOffset = fbb.Offset;
+            fbb.AddSbyte(0, 0, 0);
+            var endOffset = fbb.Offset;
+            Assert.AreEqual(sizeof(sbyte), endOffset - storedOffset);
+        }
+
+        [FlatBuffersTestMethod]
+        public void FlatBufferBuilder_WithForceDefaults_WhenAddByte_AndDefaultValue_OffsetIncreasesBySize()
+        {
+            var fbb = CreateBuffer();
+            var storedOffset = fbb.Offset;
+            fbb.AddByte(0, 0, 0);
+            var endOffset = fbb.Offset;
+            Assert.AreEqual(sizeof(byte), endOffset - storedOffset);
+        }
+
+        [FlatBuffersTestMethod]
+        public void FlatBufferBuilder_WithForceDefaults_WhenAddShort_AndDefaultValue_OffsetIncreasesBySize()
+        {
+            var fbb = CreateBuffer();
+            var storedOffset = fbb.Offset;
+            fbb.AddShort(0, 0, 0);
+            var endOffset = fbb.Offset;
+            Assert.AreEqual(sizeof(short), endOffset - storedOffset);
+        }
+
+        [FlatBuffersTestMethod]
+        public void FlatBufferBuilder_WithForceDefaults_WhenAddUShort_AndDefaultValue_OffsetIncreasesBySize()
+        {
+            var fbb = CreateBuffer();
+            var storedOffset = fbb.Offset;
+            fbb.AddUshort(0, 0, 0);
+            var endOffset = fbb.Offset;
+            Assert.AreEqual(sizeof(ushort), endOffset - storedOffset);
+        }
+
+        [FlatBuffersTestMethod]
+        public void FlatBufferBuilder_WithForceDefaults_WhenAddInt_AndDefaultValue_OffsetIncreasesBySize()
+        {
+            var fbb = CreateBuffer();
+            var storedOffset = fbb.Offset;
+            fbb.AddInt(0, 0, 0);
+            var endOffset = fbb.Offset;
+            Assert.AreEqual(sizeof(int), endOffset - storedOffset);
+        }
+
+        [FlatBuffersTestMethod]
+        public void FlatBufferBuilder_WithForceDefaults_WhenAddUInt_AndDefaultValue_OffsetIncreasesBySize()
+        {
+            var fbb = CreateBuffer();
+            var storedOffset = fbb.Offset;
+            fbb.AddUint(0, 0, 0);
+            var endOffset = fbb.Offset;
+            Assert.AreEqual(sizeof(uint), endOffset - storedOffset);
+        }
+
+        [FlatBuffersTestMethod]
+        public void FlatBufferBuilder_WithForceDefaults_WhenAddLong_AndDefaultValue_OffsetIncreasesBySize()
+        {
+            var fbb = CreateBuffer();
+            var storedOffset = fbb.Offset;
+            fbb.AddLong(0, 0, 0);
+            var endOffset = fbb.Offset;
+            Assert.AreEqual(sizeof(long), endOffset - storedOffset);
+        }
+
+        [FlatBuffersTestMethod]
+        public void FlatBufferBuilder_WithForceDefaults_WhenAddULong_AndDefaultValue_OffsetIncreasesBySize()
+        {
+            var fbb = CreateBuffer();
+            var storedOffset = fbb.Offset;
+            fbb.AddUlong(0, 0, 0);
+            var endOffset = fbb.Offset;
+            Assert.AreEqual(sizeof(ulong), endOffset - storedOffset);
+        }
+
+        [FlatBuffersTestMethod]
+        public void FlatBufferBuilder_WithForceDefaults_WhenAddFloat_AndDefaultValue_OffsetIncreasesBySize()
+        {
+            var fbb = CreateBuffer();
+            var storedOffset = fbb.Offset;
+            fbb.AddFloat(0, 0, 0);
+            var endOffset = fbb.Offset;
+            Assert.AreEqual(sizeof(float), endOffset - storedOffset);
+        }
+
+        [FlatBuffersTestMethod]
+        public void FlatBufferBuilder_WithForceDefaults_WhenAddDouble_AndDefaultValue_OffsetIncreasesBySize()
+        {
+            var fbb = CreateBuffer();
+            var storedOffset = fbb.Offset;
+            fbb.AddDouble(0, 0, 0);
+            var endOffset = fbb.Offset;
+            Assert.AreEqual(sizeof(double), endOffset - storedOffset);
+        }
+
+        [FlatBuffersTestMethod]
+        public void FlatBufferBuilder_WhenAddBool_AndDefaultValue_OffsetIsUnchanged()
+        {
+            var fbb = CreateBuffer(false);
+            var storedOffset = fbb.Offset;
+            fbb.AddBool(0, false, false);
+            var endOffset = fbb.Offset;
+            Assert.AreEqual(endOffset, storedOffset);
+        }
+
+        [FlatBuffersTestMethod]
+        public void FlatBufferBuilder_WhenAddSByte_AndDefaultValue_OffsetIsUnchanged()
+        {
+            var fbb = CreateBuffer(false);
+            var storedOffset = fbb.Offset;
+            fbb.AddSbyte(0, 0, 0);
+            var endOffset = fbb.Offset;
+            Assert.AreEqual(endOffset, storedOffset);
+        }
+
+        [FlatBuffersTestMethod]
+        public void FlatBufferBuilder_WhenAddByte_AndDefaultValue_OffsetIsUnchanged()
+        {
+            var fbb = CreateBuffer(false);
+            var storedOffset = fbb.Offset;
+            fbb.AddByte(0, 0, 0);
+            var endOffset = fbb.Offset;
+            Assert.AreEqual(endOffset, storedOffset);
+        }
+
+        [FlatBuffersTestMethod]
+        public void FlatBufferBuilder_WhenAddShort_AndDefaultValue_OffsetIsUnchanged()
+        {
+            var fbb = CreateBuffer(false);
+            var storedOffset = fbb.Offset;
+            fbb.AddShort(0, 0, 0);
+            var endOffset = fbb.Offset;
+            Assert.AreEqual(endOffset, storedOffset);
+        }
+
+        [FlatBuffersTestMethod]
+        public void FlatBufferBuilder_WhenAddUShort_AndDefaultValue_OffsetIsUnchanged()
+        {
+            var fbb = CreateBuffer(false);
+            var storedOffset = fbb.Offset;
+            fbb.AddUshort(0, 0, 0);
+            var endOffset = fbb.Offset;
+            Assert.AreEqual(endOffset, storedOffset);
+        }
+
+        [FlatBuffersTestMethod]
+        public void FlatBufferBuilder_WhenAddInt_AndDefaultValue_OffsetIsUnchanged()
+        {
+            var fbb = CreateBuffer(false);
+            var storedOffset = fbb.Offset;
+            fbb.AddInt(0, 0, 0);
+            var endOffset = fbb.Offset;
+            Assert.AreEqual(endOffset, storedOffset);
+        }
+
+        [FlatBuffersTestMethod]
+        public void FlatBufferBuilder_WhenAddUInt_AndDefaultValue_OffsetIsUnchanged()
+        {
+            var fbb = CreateBuffer(false);
+            var storedOffset = fbb.Offset;
+            fbb.AddUint(0, 0, 0);
+            var endOffset = fbb.Offset;
+            Assert.AreEqual(endOffset, storedOffset);
+        }
+
+        [FlatBuffersTestMethod]
+        public void FlatBufferBuilder_WhenAddLong_AndDefaultValue_OffsetIsUnchanged()
+        {
+            var fbb = CreateBuffer(false);
+            var storedOffset = fbb.Offset;
+            fbb.AddLong(0, 0, 0);
+            var endOffset = fbb.Offset;
+            Assert.AreEqual(endOffset, storedOffset);
+        }
+
+        [FlatBuffersTestMethod]
+        public void FlatBufferBuilder_WhenAddULong_AndDefaultValue_OffsetIsUnchanged()
+        {
+            var fbb = CreateBuffer(false);
+            var storedOffset = fbb.Offset;
+            fbb.AddUlong(0, 0, 0);
+            var endOffset = fbb.Offset;
+            Assert.AreEqual(endOffset, storedOffset);
+        }
+
+        [FlatBuffersTestMethod]
+        public void FlatBufferBuilder_WhenAddFloat_AndDefaultValue_OffsetIsUnchanged()
+        {
+            var fbb = CreateBuffer(false);
+            var storedOffset = fbb.Offset;
+            fbb.AddFloat(0, 0, 0);
+            var endOffset = fbb.Offset;
+            Assert.AreEqual(endOffset, storedOffset);
+        }
+
+        [FlatBuffersTestMethod]
+        public void FlatBufferBuilder_WhenAddDouble_AndDefaultValue_OffsetIsUnchanged()
+        {
+            var fbb = CreateBuffer(false);
+            var storedOffset = fbb.Offset;
+            fbb.AddDouble(0, 0, 0);
+            var endOffset = fbb.Offset;
+            Assert.AreEqual(endOffset, storedOffset);
+        }
+
+        [FlatBuffersTestMethod]
+        public void FlatBufferBuilder_Add_Array_Float()
+        {
+            var fbb = CreateBuffer(false);
+            var storedOffset = fbb.Offset;
+
+            const int len = 9;
+
+            // Construct the data array
+            var data = new float[len];
+            data[0] = 1.0079F;
+            data[1] = 4.0026F;
+            data[2] = 6.941F;
+            data[3] = 9.0122F;
+            data[4] = 10.811F;
+            data[5] = 12.0107F;
+            data[6] = 14.0067F;
+            data[7] = 15.9994F;
+            data[8] = 18.9984F;
+
+            fbb.Add(data);
+            var endOffset = fbb.Offset;
+            Assert.AreEqual(endOffset, storedOffset + sizeof(float) * data.Length);
+        }
+
+        [FlatBuffersTestMethod]
+        public void FlatBufferBuilder_Add_Array_Bool()
+        {
+            var fbb = CreateBuffer(false);
+            var storedOffset = fbb.Offset;
+
+            const int len = 9;
+
+            // Construct the data array
+            var data = new bool[len];
+            data[0] = true;
+            data[1] = true;
+            data[2] = false;
+            data[3] = true;
+            data[4] = false;
+            data[5] = true;
+            data[6] = true;
+            data[7] = true;
+            data[8] = false;
+
+            fbb.Add(data);
+            var endOffset = fbb.Offset;
+            Assert.AreEqual(endOffset, storedOffset + sizeof(bool) * data.Length);
+        }
+
+        [FlatBuffersTestMethod]
+        public void FlatBufferBuilder_Add_Array_Double()
+        {
+            var fbb = CreateBuffer(false);
+            var storedOffset = fbb.Offset;
+
+            const int len = 9;
+
+            // Construct the data array
+            var data = new double[len];
+            data[0] = 1.0079;
+            data[1] = 4.0026;
+            data[2] = 6.941;
+            data[3] = 9.0122;
+            data[4] = 10.811;
+            data[5] = 12.0107;
+            data[6] = 14.0067;
+            data[7] = 15.9994;
+            data[8] = 18.9984;
+
+            fbb.Add(data);
+            var endOffset = fbb.Offset;
+            Assert.AreEqual(endOffset, storedOffset + sizeof(double) * data.Length);
+        }
+
+        [FlatBuffersTestMethod]
+        public void FlatBufferBuilder_Add_Array_Null_Throws()
+        {
+            var fbb = CreateBuffer(false);
+
+            // Construct the data array
+            float[] data = null;
+
+            Assert.Throws<ArgumentNullException>(() => fbb.Add(data));
+        }
+
+        [FlatBuffersTestMethod]
+        public void FlatBufferBuilder_Add_Array_Empty_Noop()
+        {
+            var fbb = CreateBuffer(false);
+
+            var storedOffset = fbb.Offset;
+
+            // Construct an empty data array
+            float[] data = new float[0];
+            fbb.Add(data);
+
+            // Make sure the offset didn't change since nothing
+            // was really added
+            var endOffset = fbb.Offset;
+            Assert.AreEqual(endOffset, storedOffset);
+        }
+    }
+}
diff --git a/tests/FlatBuffers.Test/FlatBuffers.Test.csproj b/tests/FlatBuffers.Test/FlatBuffers.Test.csproj
new file mode 100644
index 0000000..d698d20
--- /dev/null
+++ b/tests/FlatBuffers.Test/FlatBuffers.Test.csproj
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{9DB0B5E7-757E-4BD1-A5F6-279390331254}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>FlatBuffers.Test</RootNamespace>
+    <AssemblyName>FlatBuffers.Test</AssemblyName>
+    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup>
+    <StartupObject />
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(UnsafeByteBuffer)' == 'true'">
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+    <DefineConstants>$(DefineConstants);UNSAFE_BYTEBUFFER</DefineConstants>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\..\net\FlatBuffers\ByteBuffer.cs">
+      <Link>FlatBuffers\ByteBuffer.cs</Link>
+    </Compile>
+    <Compile Include="..\..\net\FlatBuffers\ByteBufferUtil.cs">
+      <Link>FlatBuffers\ByteBufferUtil.cs</Link>
+    </Compile>
+    <Compile Include="..\..\net\FlatBuffers\IFlatbufferObject.cs">
+      <Link>FlatBuffers\IFlatbufferObject.cs</Link>
+    </Compile>
+    <Compile Include="..\..\net\FlatBuffers\Offset.cs">
+      <Link>FlatBuffers\Offset.cs</Link>
+    </Compile>
+    <Compile Include="..\..\net\FlatBuffers\FlatBufferBuilder.cs">
+      <Link>FlatBuffers\FlatBufferBuilder.cs</Link>
+    </Compile>
+    <Compile Include="..\..\net\FlatBuffers\FlatBufferConstants.cs">
+      <Link>FlatBuffers\FlatBufferConstants.cs</Link>
+    </Compile>
+    <Compile Include="..\..\net\FlatBuffers\Struct.cs">
+      <Link>FlatBuffers\Struct.cs</Link>
+    </Compile>
+    <Compile Include="..\..\net\FlatBuffers\Table.cs">
+      <Link>FlatBuffers\Table.cs</Link>
+    </Compile>
+    <Compile Include="..\MyGame\Example\Any.cs">
+      <Link>MyGame\Example\Any.cs</Link>
+    </Compile>
+    <Compile Include="..\MyGame\Example\AnyAmbiguousAliases.cs">
+      <Link>MyGame\Example\AnyAmbiguousAliases.cs</Link>
+    </Compile>
+    <Compile Include="..\MyGame\Example\AnyUniqueAliases.cs">
+      <Link>MyGame\Example\AnyUniqueAliases.cs</Link>
+    </Compile>
+    <Compile Include="..\MyGame\Example\Color.cs">
+      <Link>MyGame\Example\Color.cs</Link>
+    </Compile>
+    <Compile Include="..\MyGame\Example\Monster.cs">
+      <Link>MyGame\Example\Monster.cs</Link>
+    </Compile>
+    <Compile Include="..\MyGame\Example\Referrable.cs">
+      <Link>MyGame\Example\Referrable.cs</Link>
+    </Compile>
+    <Compile Include="..\MyGame\Example\Stat.cs">
+      <Link>MyGame\Example\Stat.cs</Link>
+    </Compile>
+    <Compile Include="..\MyGame\Example\Test.cs">
+      <Link>MyGame\Example\Test.cs</Link>
+    </Compile>
+    <Compile Include="..\MyGame\Example\TestSimpleTableWithEnum.cs">
+      <Link>MyGame\Example\TestSimpleTableWithEnum.cs</Link>
+    </Compile>
+    <Compile Include="..\MyGame\Example\Vec3.cs">
+      <Link>MyGame\Example\Vec3.cs</Link>
+    </Compile>
+    <Compile Include="..\MyGame\Example\Ability.cs">
+      <Link>MyGame\Example\Ability.cs</Link>
+    </Compile>
+    <Compile Include="..\MyGame\Example\ArrayTable.cs">
+      <Link>MyGame\Example\ArrayTable.cs</Link>
+    </Compile>
+    <Compile Include="..\MyGame\Example\ArrayStruct.cs">
+      <Link>MyGame\Example\ArrayStruct.cs</Link>
+    </Compile>
+    <Compile Include="..\MyGame\Example\NestedStruct.cs">
+      <Link>MyGame\Example\NestedStruct.cs</Link>
+    </Compile>
+    <Compile Include="..\MyGame\Example\TestEnum.cs">
+      <Link>MyGame\Example\TestEnum.cs</Link>
+    </Compile>
+    <Compile Include="..\MyGame\InParentNamespace.cs">
+      <Link>MyGame\InParentNamespace.cs</Link>
+    </Compile>
+    <Compile Include="..\namespace_test\NamespaceA\NamespaceB\EnumInNestedNS.cs">
+      <Link>NamespaceA\NamespaceB\EnumInNestedNS.cs</Link>
+    </Compile>
+    <Compile Include="..\namespace_test\NamespaceA\NamespaceB\StructInNestedNS.cs">
+      <Link>NamespaceA\NamespaceB\StructInNestedNS.cs</Link>
+    </Compile>
+    <Compile Include="..\namespace_test\NamespaceA\NamespaceB\TableInNestedNS.cs">
+      <Link>NamespaceA\NamespaceB\TableInNestedNS.cs</Link>
+    </Compile>
+    <Compile Include="..\namespace_test\NamespaceA\TableInFirstNS.cs">
+      <Link>NamespaceA\TableInFirstNS.cs</Link>
+    </Compile>
+    <Compile Include="Assert.cs" />
+    <Compile Include="ByteBufferTests.cs" />
+    <Compile Include="FlatBufferBuilderTests.cs" />
+    <Compile Include="FlatBuffersFuzzTests.cs" />
+    <Compile Include="FlatBuffersTestClassAttribute.cs" />
+    <Compile Include="FlatBuffersTestMethodAttribute.cs" />
+    <Compile Include="FuzzTestData.cs" />
+    <Compile Include="Lcg.cs" />
+    <Compile Include="Program.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="FlatBuffersExampleTests.cs" />
+    <Compile Include="TestTable.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="..\monsterdata_test.mon">
+      <Link>Resources\monsterdata_test.mon</Link>
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
diff --git a/tests/FlatBuffers.Test/FlatBuffersExampleTests.cs b/tests/FlatBuffers.Test/FlatBuffersExampleTests.cs
new file mode 100644
index 0000000..b09119c
--- /dev/null
+++ b/tests/FlatBuffers.Test/FlatBuffersExampleTests.cs
@@ -0,0 +1,387 @@
+/*
+ * Copyright 2014 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.IO;
+using System.Text;
+using MyGame.Example;
+
+namespace FlatBuffers.Test
+{
+    [FlatBuffersTestClass]
+    public class FlatBuffersExampleTests
+    {
+        public void RunTests()
+        {
+            CanCreateNewFlatBufferFromScratch();
+            CanReadCppGeneratedWireFile();
+            TestEnums();
+        }
+
+        [FlatBuffersTestMethod]
+        public void CanCreateNewFlatBufferFromScratch()
+        {
+            CanCreateNewFlatBufferFromScratch(true);
+            CanCreateNewFlatBufferFromScratch(false);
+        }
+
+        private void CanCreateNewFlatBufferFromScratch(bool sizePrefix)
+        {
+            // Second, let's create a FlatBuffer from scratch in C#, and test it also.
+            // We use an initial size of 1 to exercise the reallocation algorithm,
+            // normally a size larger than the typical FlatBuffer you generate would be
+            // better for performance.
+            var fbb = new FlatBufferBuilder(1);
+
+            StringOffset[] names = { fbb.CreateString("Frodo"), fbb.CreateString("Barney"), fbb.CreateString("Wilma") };
+            Offset<Monster>[] off = new Offset<Monster>[3];
+            Monster.StartMonster(fbb);
+            Monster.AddName(fbb, names[0]);
+            off[0] = Monster.EndMonster(fbb);
+            Monster.StartMonster(fbb);
+            Monster.AddName(fbb, names[1]);
+            off[1] = Monster.EndMonster(fbb);
+            Monster.StartMonster(fbb);
+            Monster.AddName(fbb, names[2]);
+            off[2] = Monster.EndMonster(fbb);
+            var sortMons = Monster.CreateSortedVectorOfMonster(fbb, off);
+
+            // We set up the same values as monsterdata.json:
+
+            var str = fbb.CreateString("MyMonster");
+            var test1 = fbb.CreateString("test1");
+            var test2 = fbb.CreateString("test2");
+
+
+            Monster.StartInventoryVector(fbb, 5);
+            for (int i = 4; i >= 0; i--)
+            {
+                fbb.AddByte((byte)i);
+            }
+            var inv = fbb.EndVector();
+
+            var fred = fbb.CreateString("Fred");
+            Monster.StartMonster(fbb);
+            Monster.AddName(fbb, fred);
+            var mon2 = Monster.EndMonster(fbb);
+
+            Monster.StartTest4Vector(fbb, 2);
+            MyGame.Example.Test.CreateTest(fbb, (short)10, (sbyte)20);
+            MyGame.Example.Test.CreateTest(fbb, (short)30, (sbyte)40);
+            var test4 = fbb.EndVector();
+
+            Monster.StartTestarrayofstringVector(fbb, 2);
+            fbb.AddOffset(test2.Value);
+            fbb.AddOffset(test1.Value);
+            var testArrayOfString = fbb.EndVector();
+
+            Monster.StartMonster(fbb);
+            Monster.AddPos(fbb, Vec3.CreateVec3(fbb, 1.0f, 2.0f, 3.0f, 3.0,
+                                                     Color.Green, (short)5, (sbyte)6));
+            Monster.AddHp(fbb, (short)80);
+            Monster.AddName(fbb, str);
+            Monster.AddInventory(fbb, inv);
+            Monster.AddTestType(fbb, Any.Monster);
+            Monster.AddTest(fbb, mon2.Value);
+            Monster.AddTest4(fbb, test4);
+            Monster.AddTestarrayofstring(fbb, testArrayOfString);
+            Monster.AddTestbool(fbb, true);
+            Monster.AddTestarrayoftables(fbb, sortMons);
+            var mon = Monster.EndMonster(fbb);
+
+            if (sizePrefix)
+            {
+                Monster.FinishSizePrefixedMonsterBuffer(fbb, mon);
+            }
+            else
+            {
+                Monster.FinishMonsterBuffer(fbb, mon);
+            }
+
+            // Dump to output directory so we can inspect later, if needed
+#if ENABLE_SPAN_T
+            var data = fbb.DataBuffer.ToSizedArray();
+            string filename = @"Resources/monsterdata_cstest" + (sizePrefix ? "_sp" : "") + ".mon";
+            File.WriteAllBytes(filename, data);
+#else
+            using (var ms = fbb.DataBuffer.ToMemoryStream(fbb.DataBuffer.Position, fbb.Offset))
+            {
+                var data = ms.ToArray();
+                string filename = @"Resources/monsterdata_cstest" + (sizePrefix ? "_sp" : "") + ".mon";
+                File.WriteAllBytes(filename, data);
+            }
+#endif
+
+            // Remove the size prefix if necessary for further testing
+            ByteBuffer dataBuffer = fbb.DataBuffer;
+            if (sizePrefix)
+            {
+                Assert.AreEqual(ByteBufferUtil.GetSizePrefix(dataBuffer) + FlatBufferConstants.SizePrefixLength,
+                                dataBuffer.Length - dataBuffer.Position);
+                dataBuffer = ByteBufferUtil.RemoveSizePrefix(dataBuffer);
+            }
+
+            // Now assert the buffer
+            TestBuffer(dataBuffer);
+
+            //Attempt to mutate Monster fields and check whether the buffer has been mutated properly
+            // revert to original values after testing
+            Monster monster = Monster.GetRootAsMonster(dataBuffer);
+            
+
+            // mana is optional and does not exist in the buffer so the mutation should fail
+            // the mana field should retain its default value
+            Assert.AreEqual(monster.MutateMana((short)10), false);
+            Assert.AreEqual(monster.Mana, (short)150);
+
+            // Accessing a vector of sorted by the key tables
+            Assert.AreEqual(monster.Testarrayoftables(0).Value.Name, "Barney");
+            Assert.AreEqual(monster.Testarrayoftables(1).Value.Name, "Frodo");
+            Assert.AreEqual(monster.Testarrayoftables(2).Value.Name, "Wilma");
+
+            // Example of searching for a table by the key
+            Assert.IsTrue(monster.TestarrayoftablesByKey("Frodo") != null);
+            Assert.IsTrue(monster.TestarrayoftablesByKey("Barney") != null);
+            Assert.IsTrue(monster.TestarrayoftablesByKey("Wilma") != null);
+
+            // testType is an existing field and mutating it should succeed
+            Assert.AreEqual(monster.TestType, Any.Monster);
+            Assert.AreEqual(monster.MutateTestType(Any.NONE), true);
+            Assert.AreEqual(monster.TestType, Any.NONE);
+            Assert.AreEqual(monster.MutateTestType(Any.Monster), true);
+            Assert.AreEqual(monster.TestType, Any.Monster);
+
+            //mutate the inventory vector
+            Assert.AreEqual(monster.MutateInventory(0, 1), true);
+            Assert.AreEqual(monster.MutateInventory(1, 2), true);
+            Assert.AreEqual(monster.MutateInventory(2, 3), true);
+            Assert.AreEqual(monster.MutateInventory(3, 4), true);
+            Assert.AreEqual(monster.MutateInventory(4, 5), true);
+
+            for (int i = 0; i < monster.InventoryLength; i++)
+            {
+                Assert.AreEqual(monster.Inventory(i), i + 1);
+            }
+
+            //reverse mutation
+            Assert.AreEqual(monster.MutateInventory(0, 0), true);
+            Assert.AreEqual(monster.MutateInventory(1, 1), true);
+            Assert.AreEqual(monster.MutateInventory(2, 2), true);
+            Assert.AreEqual(monster.MutateInventory(3, 3), true);
+            Assert.AreEqual(monster.MutateInventory(4, 4), true);
+
+            // get a struct field and edit one of its fields
+            Vec3 pos = (Vec3)monster.Pos;
+            Assert.AreEqual(pos.X, 1.0f);
+            pos.MutateX(55.0f);
+            Assert.AreEqual(pos.X, 55.0f);
+            pos.MutateX(1.0f);
+            Assert.AreEqual(pos.X, 1.0f);
+
+            TestBuffer(dataBuffer);
+        }
+
+        private void TestBuffer(ByteBuffer bb)
+        {
+            Monster monster = Monster.GetRootAsMonster(bb);
+
+            Assert.AreEqual(80, monster.Hp);
+            Assert.AreEqual(150, monster.Mana);
+            Assert.AreEqual("MyMonster", monster.Name);
+
+            var pos = monster.Pos.Value;
+            Assert.AreEqual(1.0f, pos.X);
+            Assert.AreEqual(2.0f, pos.Y);
+            Assert.AreEqual(3.0f, pos.Z);
+
+            Assert.AreEqual(3.0f, pos.Test1);
+            Assert.AreEqual(Color.Green, pos.Test2);
+            var t = (MyGame.Example.Test)pos.Test3;
+            Assert.AreEqual((short)5, t.A);
+            Assert.AreEqual((sbyte)6, t.B);
+
+            Assert.AreEqual(Any.Monster, monster.TestType);
+
+            var monster2 = monster.Test<Monster>().Value;
+            Assert.AreEqual("Fred", monster2.Name);
+
+
+            Assert.AreEqual(5, monster.InventoryLength);
+            var invsum = 0;
+            for (var i = 0; i < monster.InventoryLength; i++)
+            {
+                invsum += monster.Inventory(i);
+            }
+            Assert.AreEqual(10, invsum);
+
+            // Get the inventory as an array and subtract the
+            // sum to get it back to 0
+            var inventoryArray = monster.GetInventoryArray();
+            Assert.AreEqual(5, inventoryArray.Length);
+            foreach(var inv in inventoryArray)
+            {
+                invsum -= inv;
+            }
+            Assert.AreEqual(0, invsum);
+
+            var test0 = monster.Test4(0).Value;
+            var test1 = monster.Test4(1).Value;
+            Assert.AreEqual(2, monster.Test4Length);
+
+            Assert.AreEqual(100, test0.A + test0.B + test1.A + test1.B);
+
+            Assert.AreEqual(2, monster.TestarrayofstringLength);
+            Assert.AreEqual("test1", monster.Testarrayofstring(0));
+            Assert.AreEqual("test2", monster.Testarrayofstring(1));
+
+            Assert.AreEqual(true, monster.Testbool);
+
+#if ENABLE_SPAN_T
+            var nameBytes = monster.GetNameBytes();
+            Assert.AreEqual("MyMonster", Encoding.UTF8.GetString(nameBytes.ToArray(), 0, nameBytes.Length));
+
+            if (0 == monster.TestarrayofboolsLength)
+            {
+                Assert.IsFalse(monster.GetTestarrayofboolsBytes().Length != 0);
+            }
+            else
+            {
+                Assert.IsTrue(monster.GetTestarrayofboolsBytes().Length != 0);
+            }
+#else
+            var nameBytes = monster.GetNameBytes().Value;
+            Assert.AreEqual("MyMonster", Encoding.UTF8.GetString(nameBytes.Array, nameBytes.Offset, nameBytes.Count));
+
+            if (0 == monster.TestarrayofboolsLength)
+            {
+                Assert.IsFalse(monster.GetTestarrayofboolsBytes().HasValue);
+            }
+            else
+            {
+                Assert.IsTrue(monster.GetTestarrayofboolsBytes().HasValue);
+            }
+#endif
+        }
+
+        [FlatBuffersTestMethod]
+        public void CanReadCppGeneratedWireFile()
+        {
+            var data = File.ReadAllBytes(@"Resources/monsterdata_test.mon");
+            var bb = new ByteBuffer(data);
+            TestBuffer(bb);
+        }
+
+        [FlatBuffersTestMethod]
+        public void TestEnums()
+        {
+            Assert.AreEqual("Red", Color.Red.ToString());
+            Assert.AreEqual("Blue", Color.Blue.ToString());
+            Assert.AreEqual("NONE", Any.NONE.ToString());
+            Assert.AreEqual("Monster", Any.Monster.ToString());
+        }
+
+        [FlatBuffersTestMethod]
+        public void TestNestedFlatBuffer()
+        {
+            const string nestedMonsterName = "NestedMonsterName";
+            const short nestedMonsterHp = 600;
+            const short nestedMonsterMana = 1024;
+            // Create nested buffer as a Monster type
+            var fbb1 = new FlatBufferBuilder(16);
+            var str1 = fbb1.CreateString(nestedMonsterName);
+            Monster.StartMonster(fbb1);
+            Monster.AddName(fbb1, str1);
+            Monster.AddHp(fbb1, nestedMonsterHp);
+            Monster.AddMana(fbb1, nestedMonsterMana);
+            var monster1 = Monster.EndMonster(fbb1);
+            Monster.FinishMonsterBuffer(fbb1, monster1);
+            var fbb1Bytes = fbb1.SizedByteArray();
+            fbb1 = null;
+
+            // Create a Monster which has the first buffer as a nested buffer
+            var fbb2 = new FlatBufferBuilder(16);
+            var str2 = fbb2.CreateString("My Monster");
+            var nestedBuffer = Monster.CreateTestnestedflatbufferVector(fbb2, fbb1Bytes);
+            Monster.StartMonster(fbb2);
+            Monster.AddName(fbb2, str2);
+            Monster.AddHp(fbb2, 50);
+            Monster.AddMana(fbb2, 32);
+            Monster.AddTestnestedflatbuffer(fbb2, nestedBuffer);
+            var monster = Monster.EndMonster(fbb2);
+            Monster.FinishMonsterBuffer(fbb2, monster);
+
+            // Now test the data extracted from the nested buffer
+            var mons = Monster.GetRootAsMonster(fbb2.DataBuffer);
+            var nestedMonster = mons.GetTestnestedflatbufferAsMonster().Value;
+
+            Assert.AreEqual(nestedMonsterMana, nestedMonster.Mana);
+            Assert.AreEqual(nestedMonsterHp, nestedMonster.Hp);
+            Assert.AreEqual(nestedMonsterName, nestedMonster.Name);
+        }
+
+        [FlatBuffersTestMethod]
+        public void TestFixedLenghtArrays()
+        {
+            FlatBufferBuilder builder = new FlatBufferBuilder(100);
+
+            float   a;
+            int[]   b = new int[15];
+            sbyte   c;
+            int[,]  d_a = new int[2, 2];
+            TestEnum[]  d_b = new TestEnum[2];
+            TestEnum[,] d_c = new TestEnum[2, 2];
+
+            a = 0.5f;
+            for (int i = 0; i < 15; i++) b[i] = i;
+            c = 1;
+            d_a[0, 0] = 1;
+            d_a[0, 1] = 2;
+            d_a[1, 0] = 3;
+            d_a[1, 1] = 4;
+            d_b[0] = TestEnum.B;
+            d_b[1] = TestEnum.C;
+            d_c[0, 0] = TestEnum.A;
+            d_c[0, 1] = TestEnum.B;
+            d_c[1, 0] = TestEnum.C;
+            d_c[1, 1] = TestEnum.B;
+
+            Offset<ArrayStruct> arrayOffset = ArrayStruct.CreateArrayStruct(
+                builder, a, b, c, d_a, d_b, d_c);
+
+            // Create a table with the ArrayStruct.
+            ArrayTable.StartArrayTable(builder);
+            ArrayTable.AddA(builder, arrayOffset);
+            Offset<ArrayTable> tableOffset = ArrayTable.EndArrayTable(builder);
+
+            ArrayTable.FinishArrayTableBuffer(builder, tableOffset);
+
+            ArrayTable table = ArrayTable.GetRootAsArrayTable(builder.DataBuffer);
+
+            Assert.AreEqual(table.A?.A, 0.5f);
+            for (int i = 0; i < 15; i++) Assert.AreEqual(table.A?.B(i), i);
+            Assert.AreEqual(table.A?.C, (sbyte)1);
+            Assert.AreEqual(table.A?.D(0).A(0), 1);
+            Assert.AreEqual(table.A?.D(0).A(1), 2);
+            Assert.AreEqual(table.A?.D(1).A(0), 3);
+            Assert.AreEqual(table.A?.D(1).A(1), 4);
+            Assert.AreEqual(table.A?.D(0).B, TestEnum.B);
+            Assert.AreEqual(table.A?.D(1).B, TestEnum.C);
+            Assert.AreEqual(table.A?.D(0).C(0), TestEnum.A);
+            Assert.AreEqual(table.A?.D(0).C(1), TestEnum.B);
+            Assert.AreEqual(table.A?.D(1).C(0), TestEnum.C);
+            Assert.AreEqual(table.A?.D(1).C(1), TestEnum.B);
+        }
+    }
+}
diff --git a/tests/FlatBuffers.Test/FlatBuffersFuzzTests.cs b/tests/FlatBuffers.Test/FlatBuffersFuzzTests.cs
new file mode 100644
index 0000000..b6c60ea
--- /dev/null
+++ b/tests/FlatBuffers.Test/FlatBuffersFuzzTests.cs
@@ -0,0 +1,811 @@
+/*
+ * 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.ToFullArray());
+            builder.AddBool(true);
+            Assert.ArrayEqual(new byte[] { 1 }, builder.DataBuffer.ToFullArray());
+            builder.AddSbyte(-127);
+            Assert.ArrayEqual(new byte[] { 129, 1 }, builder.DataBuffer.ToFullArray());
+            builder.AddByte(255);
+            Assert.ArrayEqual(new byte[] { 0, 255, 129, 1 }, builder.DataBuffer.ToFullArray()); // First pad
+            builder.AddShort(-32222);
+            Assert.ArrayEqual(new byte[] { 0, 0, 0x22, 0x82, 0, 255, 129, 1 }, builder.DataBuffer.ToFullArray()); // Second pad
+            builder.AddUshort(0xFEEE);
+            Assert.ArrayEqual(new byte[] { 0xEE, 0xFE, 0x22, 0x82, 0, 255, 129, 1 }, builder.DataBuffer.ToFullArray()); // 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.ToFullArray()); // 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.ToFullArray()); // 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.ToFullArray());
+
+            builder = new FlatBufferBuilder(1);
+            builder.AddLong(0x1122334455667788);
+            Assert.ArrayEqual(new byte[] { 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11 }, builder.DataBuffer.ToFullArray());
+        }
+
+        [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.ToFullArray());
+            builder.AddByte(1);
+            Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, builder.DataBuffer.ToFullArray());
+            builder.EndVector();
+            Assert.ArrayEqual(new byte[] { 1, 0, 0, 0, 1, 0, 0, 0 }, builder.DataBuffer.ToFullArray());
+        }
+
+        [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.ToFullArray());
+            builder.AddByte(1);
+            Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 0, 1, 0, 0 }, builder.DataBuffer.ToFullArray());
+            builder.AddByte(2);
+            Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 2, 1, 0, 0 }, builder.DataBuffer.ToFullArray());
+            builder.EndVector();
+            Assert.ArrayEqual(new byte[] { 2, 0, 0, 0, 2, 1, 0, 0 }, builder.DataBuffer.ToFullArray());
+        }
+
+        [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.ToFullArray());
+            builder.AddUshort(1);
+            Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 1, 0, 0, 0 }, builder.DataBuffer.ToFullArray());
+            builder.EndVector();
+            Assert.ArrayEqual(new byte[] { 1, 0, 0, 0, 1, 0, 0, 0 }, builder.DataBuffer.ToFullArray());
+        }
+
+        [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.ToFullArray());
+            builder.AddUshort(0xABCD);
+            Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 0, 0, 0xCD, 0xAB }, builder.DataBuffer.ToFullArray());
+            builder.AddUshort(0xDCBA);
+            Assert.ArrayEqual(new byte[] { 0, 0, 0, 0, 0xBA, 0xDC, 0xCD, 0xAB }, builder.DataBuffer.ToFullArray());
+            builder.EndVector();
+            Assert.ArrayEqual(new byte[] { 2, 0, 0, 0, 0xBA, 0xDC, 0xCD, 0xAB }, builder.DataBuffer.ToFullArray());
+        }
+
+        [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.ToFullArray());
+
+            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.ToFullArray());
+        }
+
+        [FlatBuffersTestMethod]
+        public void TestCreateSharedAsciiString()
+        {
+            var builder = new FlatBufferBuilder(1);
+            builder.CreateSharedString("foo");
+            Assert.ArrayEqual(new byte[] { 3, 0, 0, 0, (byte)'f', (byte)'o', (byte)'o', 0 }, builder.DataBuffer.ToFullArray());
+
+            builder.CreateSharedString("foo");
+            Assert.ArrayEqual(new byte[] { 3, 0, 0, 0, (byte)'f', (byte)'o', (byte)'o', 0 }, builder.DataBuffer.ToFullArray());
+        }
+
+        [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.ToFullArray()); // 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.ToFullArray()); // No padding
+        }
+
+        [FlatBuffersTestMethod]
+        public void TestEmptyVTable()
+        {
+            var builder = new FlatBufferBuilder(1);
+            builder.StartTable(0);
+            Assert.ArrayEqual(new byte[] { 0 }, builder.DataBuffer.ToFullArray());
+            builder.EndTable();
+            Assert.ArrayEqual(new byte[]
+            {
+                4, 0, 4, 0,
+                4, 0, 0, 0
+            },
+                builder.DataBuffer.ToFullArray());
+        }
+
+        [FlatBuffersTestMethod]
+        public void TestVTableWithOneBool()
+        {
+            var builder = new FlatBufferBuilder(1);
+            builder.StartTable(1);
+            Assert.ArrayEqual(new byte[] { 0 }, builder.DataBuffer.ToFullArray());
+            builder.AddBool(0, true, false);
+            builder.EndTable();
+            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.ToFullArray());
+        }
+
+        [FlatBuffersTestMethod]
+        public void TestVTableWithOneBool_DefaultValue()
+        {
+            var builder = new FlatBufferBuilder(1);
+            builder.StartTable(1);
+            Assert.ArrayEqual(new byte[] { 0 }, builder.DataBuffer.ToFullArray());
+            builder.AddBool(0, false, false);
+            builder.EndTable();
+            Assert.ArrayEqual(new byte[]
+            {
+                // No padding.
+                4, 0, // vtable bytes
+                4, 0, // end of object from here
+                // entry 0 is not stored (trimmed end of vtable)
+                4, 0, 0, 0, // int32 offset for start of vtable
+            },
+                builder.DataBuffer.ToFullArray());
+        }
+
+        [FlatBuffersTestMethod]
+        public void TestVTableWithOneInt16()
+        {
+            var builder = new FlatBufferBuilder(1);
+            builder.StartTable(1);
+            Assert.ArrayEqual(new byte[] { 0 }, builder.DataBuffer.ToFullArray());
+            builder.AddShort(0, 0x789A, 0);
+            builder.EndTable();
+            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.ToFullArray());
+        }
+
+        [FlatBuffersTestMethod]
+        public void TestVTableWithTwoInt16()
+        {
+            var builder = new FlatBufferBuilder(1);
+            builder.StartTable(2);
+            Assert.ArrayEqual(new byte[] { 0 }, builder.DataBuffer.ToFullArray());
+            builder.AddShort(0, 0x3456, 0);
+            builder.AddShort(1, 0x789A, 0);
+            builder.EndTable();
+            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.ToFullArray());
+        }
+
+        [FlatBuffersTestMethod]
+        public void TestVTableWithInt16AndBool()
+        {
+            var builder = new FlatBufferBuilder(1);
+            builder.StartTable(2);
+            Assert.ArrayEqual(new byte[] { 0 }, builder.DataBuffer.ToFullArray());
+            builder.AddShort(0, 0x3456, 0);
+            builder.AddBool(1, true, false);
+            builder.EndTable();
+            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.ToFullArray());
+        }
+
+        [FlatBuffersTestMethod]
+        public void TestVTableWithEmptyVector()
+        {
+            var builder = new FlatBufferBuilder(1);
+            builder.StartVector(sizeof(byte), 0, 1);
+            var vecEnd = builder.EndVector();
+
+            builder.StartTable(1);
+
+            builder.AddOffset(0, vecEnd.Value, 0);
+            builder.EndTable();
+            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.ToFullArray());
+        }
+
+        [FlatBuffersTestMethod]
+        public void TestVTableWithEmptyVectorAndScalars()
+        {
+            var builder = new FlatBufferBuilder(1);
+            builder.StartVector(sizeof(byte), 0, 1);
+            var vecEnd = builder.EndVector();
+
+            builder.StartTable(2);
+            builder.AddShort(0, 55, 0);
+            builder.AddOffset(1, vecEnd.Value, 0);
+            builder.EndTable();
+            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.ToFullArray());
+        }
+
+
+        [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.StartTable(2);
+            builder.AddOffset(1, vecEnd.Value, 0);
+            builder.AddShort(0, 55, 0);
+            builder.EndTable();
+            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.ToFullArray());
+        }
+
+        [FlatBuffersTestMethod]
+        public void TestVTableWithAStruct_of_int8_int16_int32()
+        {
+            var builder = new FlatBufferBuilder(1);
+            builder.StartTable(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.EndTable();
+            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.ToFullArray());
+        }
+
+        [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.StartTable(1);
+            builder.AddOffset(0, vecEnd.Value, 0);
+            builder.EndTable();
+
+            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.ToFullArray());
+        }
+
+        [FlatBuffersTestMethod]
+        public void TestVTableWithSomeElements()
+        {
+            var builder = new FlatBufferBuilder(1);
+            builder.StartTable(2);
+            builder.AddByte(0, 33, 0);
+            builder.AddShort(1, 66, 0);
+            var off = builder.EndTable();
+            builder.Finish(off);
+
+            byte[] padded = 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
+
+            };
+            Assert.ArrayEqual(padded, builder.DataBuffer.ToFullArray());
+
+            // no padding in sized array
+            byte[] unpadded = new byte[padded.Length - 12];
+            Buffer.BlockCopy(padded, 12, unpadded, 0, unpadded.Length);
+            Assert.ArrayEqual(unpadded, builder.DataBuffer.ToSizedArray());
+        }
+
+        [FlatBuffersTestMethod]
+        public void TestTwoFinishTable()
+        {
+            var builder = new FlatBufferBuilder(1);
+            builder.StartTable(2);
+            builder.AddByte(0, 33, 0);
+            builder.AddByte(1, 44, 0);
+            var off0 = builder.EndTable();
+            builder.Finish(off0);
+
+            builder.StartTable(3);
+            builder.AddByte(0, 55, 0);
+            builder.AddByte(1, 66, 0);
+            builder.AddByte(2, 77, 0);
+            var off1 = builder.EndTable();
+            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.ToFullArray());
+        }
+
+        [FlatBuffersTestMethod]
+        public void TestBunchOfBools()
+        {
+            var builder = new FlatBufferBuilder(1);
+            builder.StartTable(8);
+            for (var i = 0; i < 8; i++)
+            {
+                builder.AddBool(i, true, false);
+            }
+            var off = builder.EndTable();
+            builder.Finish(off);
+
+            byte[] padded = 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,
+
+            };
+            Assert.ArrayEqual(padded, builder.DataBuffer.ToFullArray());
+
+            // no padding in sized array
+            byte[] unpadded = new byte[padded.Length - 28];
+            Buffer.BlockCopy(padded, 28, unpadded, 0, unpadded.Length);
+            Assert.ArrayEqual(unpadded, builder.DataBuffer.ToSizedArray());
+        }
+
+        [FlatBuffersTestMethod]
+        public void TestBunchOfBoolsSizePrefixed()
+        {
+            var builder = new FlatBufferBuilder(1);
+            builder.StartTable(8);
+            for (var i = 0; i < 8; i++)
+            {
+                builder.AddBool(i, true, false);
+            }
+            var off = builder.EndTable();
+            builder.FinishSizePrefixed(off);
+
+            byte[] padded = 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,      // padding to 64 bytes
+
+                36, 0, 0, 0,     // size prefix
+                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,
+
+            };
+            Assert.ArrayEqual(padded, builder.DataBuffer.ToFullArray());
+
+            // no padding in sized array
+            byte[] unpadded = new byte[padded.Length - 24];
+            Buffer.BlockCopy(padded, 24, unpadded, 0, unpadded.Length);
+            Assert.ArrayEqual(unpadded, builder.DataBuffer.ToSizedArray());
+        }
+
+        [FlatBuffersTestMethod]
+        public void TestWithFloat()
+        {
+            var builder = new FlatBufferBuilder(1);
+            builder.StartTable(1);
+            builder.AddFloat(0, 1, 0);
+            builder.EndTable();
+
+
+            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.ToFullArray());
+        }
+
+        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.StartTable(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.EndTable();
+
+                // 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 0000000..f31e38b
--- /dev/null
+++ b/tests/FlatBuffers.Test/FlatBuffersTestClassAttribute.cs
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2016 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;
+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 0000000..989dae5
--- /dev/null
+++ b/tests/FlatBuffers.Test/FlatBuffersTestMethodAttribute.cs
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2016 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
+{
+    [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 0000000..119e44e
--- /dev/null
+++ b/tests/FlatBuffers.Test/FuzzTestData.cs
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2016 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
+{
+    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 0000000..c329ed8
--- /dev/null
+++ b/tests/FlatBuffers.Test/Lcg.cs
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2016 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.
+ */
+
+namespace FlatBuffers.Test
+{
+    /// <summary>
+    /// Lcg Pseudo RNG
+    /// </summary>
+    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/NetTest.sh b/tests/FlatBuffers.Test/NetTest.sh
new file mode 100644
index 0000000..3822b49
--- /dev/null
+++ b/tests/FlatBuffers.Test/NetTest.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+# Testing C# on Linux using Mono.
+
+mcs -debug -out:./fbnettest.exe \
+  ../../net/FlatBuffers/*.cs ../MyGame/Example/*.cs ../MyGame/*.cs ../union_vector/*.cs \
+  FlatBuffersTestClassAttribute.cs FlatBuffersTestMethodAttribute.cs Assert.cs FlatBuffersExampleTests.cs Program.cs ByteBufferTests.cs FlatBufferBuilderTests.cs FlatBuffersFuzzTests.cs FuzzTestData.cs Lcg.cs TestTable.cs
+mono --debug ./fbnettest.exe
+rm fbnettest.exe
+rm Resources/monsterdata_cstest.mon
+rm Resources/monsterdata_cstest_sp.mon
+
+# Repeat with unsafe versions
+
+mcs -debug -out:./fbnettest.exe \
+  -unsafe -d:UNSAFE_BYTEBUFFER \
+  ../../net/FlatBuffers/*.cs ../MyGame/Example/*.cs ../MyGame/*.cs ../union_vector/*.cs\
+  FlatBuffersTestClassAttribute.cs FlatBuffersTestMethodAttribute.cs Assert.cs FlatBuffersExampleTests.cs Program.cs ByteBufferTests.cs FlatBufferBuilderTests.cs FlatBuffersFuzzTests.cs FuzzTestData.cs Lcg.cs TestTable.cs
+mono --debug ./fbnettest.exe
+rm fbnettest.exe
+rm Resources/monsterdata_cstest.mon
+rm Resources/monsterdata_cstest_sp.mon
+
diff --git a/tests/FlatBuffers.Test/Program.cs b/tests/FlatBuffers.Test/Program.cs
new file mode 100644
index 0000000..f8cec4e
--- /dev/null
+++ b/tests/FlatBuffers.Test/Program.cs
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2014 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;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+namespace FlatBuffers.Test
+{
+    static class Program
+    {
+        public static int Main(string[] args)
+        {
+            var testResults = new List<bool>();
+
+            var testClasses = Assembly.GetExecutingAssembly().GetExportedTypes()
+                .Where(t => t.IsClass && t.GetCustomAttributes(typeof (FlatBuffersTestClassAttribute), false).Length > 0);
+
+            foreach (var testClass in testClasses)
+            {
+                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);
+                    }
+                }
+            }
+
+            var failedCount = testResults.Count(i => i == false);
+
+            Console.WriteLine("{0} tests run, {1} failed", testResults.Count, failedCount);
+
+            if (failedCount > 0)
+            {
+                return -1;
+            }
+            return 0;
+        }
+    }
+}
diff --git a/tests/FlatBuffers.Test/Properties/AssemblyInfo.cs b/tests/FlatBuffers.Test/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..2e33f08
--- /dev/null
+++ b/tests/FlatBuffers.Test/Properties/AssemblyInfo.cs
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2014 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.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("FlatBuffers.Test")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("FlatBuffers.Test")]
+[assembly: AssemblyCopyright("Copyright (c) 2014  Google Inc")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components.  If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("a1d58a51-3e74-4ae9-aac7-5a399c9eed1a")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/tests/FlatBuffers.Test/Resources/monsterdata_test.mon b/tests/FlatBuffers.Test/Resources/monsterdata_test.mon
new file mode 100644
index 0000000..3f83972
--- /dev/null
+++ b/tests/FlatBuffers.Test/Resources/monsterdata_test.mon
Binary files differ
diff --git a/tests/FlatBuffers.Test/TestTable.cs b/tests/FlatBuffers.Test/TestTable.cs
new file mode 100644
index 0000000..4f663f0
--- /dev/null
+++ b/tests/FlatBuffers.Test/TestTable.cs
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2016 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.
+ */
+
+namespace FlatBuffers.Test
+{
+    /// <summary>
+    /// A test Table object that gives easy access to the slot data
+    /// </summary>
+    internal struct TestTable
+    {
+        Table t;
+
+        public TestTable(ByteBuffer bb, int pos)
+        {
+          t = new Table(pos, bb);
+        }
+
+        public bool GetSlot(int slot, bool def)
+        {
+            var off = t.__offset(slot);
+
+            if (off == 0)
+            {
+                return def;
+            }
+            return t.bb.GetSbyte(t.bb_pos + off) != 0;
+        }
+
+        public sbyte GetSlot(int slot, sbyte def)
+        {
+            var off = t.__offset(slot);
+
+            if (off == 0)
+            {
+                return def;
+            }
+            return t.bb.GetSbyte(t.bb_pos + off);
+        }
+
+        public byte GetSlot(int slot, byte def)
+        {
+            var off = t.__offset(slot);
+
+            if (off == 0)
+            {
+                return def;
+            }
+            return t.bb.Get(t.bb_pos + off);
+        }
+
+        public short GetSlot(int slot, short def)
+        {
+            var off = t.__offset(slot);
+
+            if (off == 0)
+            {
+                return def;
+            }
+            return t.bb.GetShort(t.bb_pos + off);
+        }
+
+        public ushort GetSlot(int slot, ushort def)
+        {
+            var off = t.__offset(slot);
+
+            if (off == 0)
+            {
+                return def;
+            }
+            return t.bb.GetUshort(t.bb_pos + off);
+        }
+
+        public int GetSlot(int slot, int def)
+        {
+            var off = t.__offset(slot);
+
+            if (off == 0)
+            {
+                return def;
+            }
+            return t.bb.GetInt(t.bb_pos + off);
+        }
+
+        public uint GetSlot(int slot, uint def)
+        {
+            var off = t.__offset(slot);
+
+            if (off == 0)
+            {
+                return def;
+            }
+            return t.bb.GetUint(t.bb_pos + off);
+        }
+
+        public long GetSlot(int slot, long def)
+        {
+            var off = t.__offset(slot);
+
+            if (off == 0)
+            {
+                return def;
+            }
+            return t.bb.GetLong(t.bb_pos + off);
+        }
+
+        public ulong GetSlot(int slot, ulong def)
+        {
+            var off = t.__offset(slot);
+
+            if (off == 0)
+            {
+                return def;
+            }
+            return t.bb.GetUlong(t.bb_pos + off);
+        }
+
+        public float GetSlot(int slot, float def)
+        {
+            var off = t.__offset(slot);
+
+            if (off == 0)
+            {
+                return def;
+            }
+            return t.bb.GetFloat(t.bb_pos + off);
+        }
+
+        public double GetSlot(int slot, double def)
+        {
+            var off = t.__offset(slot);
+
+            if (off == 0)
+            {
+                return def;
+            }
+            return t.bb.GetDouble(t.bb_pos + off);
+        }
+    }
+}