static void Test(FlatBufferDeserializationOption option) { string schema = $@" {MetadataHelpers.AllAttributes} namespace ForceWriteTests; table Table ({MetadataKeys.SerializerKind}:""{option}"") {{ Struct:Struct; }} struct Struct ({MetadataKeys.WriteThrough}) {{ foo:int; bar:int ({MetadataKeys.WriteThrough}:""false""); }} "; Assembly asm = FlatSharpCompiler.CompileAndLoadAssembly(schema, new()); Type tableType = asm.GetType("ForceWriteTests.Table"); Type structType = asm.GetType("ForceWriteTests.Struct"); ISerializer serializer = (ISerializer)tableType.GetProperty("Serializer", BindingFlags.Public | BindingFlags.Static).GetValue(null); dynamic table = Activator.CreateInstance(tableType); table.Struct = (dynamic)Activator.CreateInstance(structType); table.Struct.foo = 42; table.Struct.bar = 65; byte[] data = new byte[100]; serializer.Write(data, (object)table); dynamic parsed = serializer.Parse(data); parsed.Struct.foo = 100; Assert.Throws <NotMutableException>(() => parsed.Struct.bar = 22); dynamic parsed2 = serializer.Parse(data); Assert.Equal(100, (int)parsed2.Struct.foo); Assert.Equal(65, (int)parsed2.Struct.bar); }
public void InvalidEnumTest_DuplicateNames_BitFlags() { string fbs = $"{MetadataHelpers.AllAttributes}namespace Foo.Bar; enum MyEnum : ubyte (bit_flags) {{ Red, Blue, Yellow, Red }}"; var ex = Assert.Throws <InvalidFbsFileException>(() => FlatSharpCompiler.CompileAndLoadAssembly(fbs, new())); Assert.Contains("error: enum value already exists: Red", ex.Message); }
public void InvalidEnumTest_ValueOutOfRangeOfUnderlyingType_Below() { string fbs = $"{MetadataHelpers.AllAttributes}namespace Foo.Bar; enum MyEnum : ulong {{ Red = -1, Blue = 255, Yellow = 256 }}"; var ex = Assert.Throws <InvalidFbsFileException>(() => FlatSharpCompiler.CompileAndLoadAssembly(fbs, new())); Assert.Contains("error: enum value does not fit, \"-1\"", ex.Message); }
public void FlagsTest_TooMany() { string fbs = $"{MetadataHelpers.AllAttributes}namespace Foo.Bar; enum MyEnum : ubyte (bit_flags) {{ A, B, C, D, E, F, G, H, I }}"; var ex = Assert.Throws <InvalidFbsFileException>(() => FlatSharpCompiler.CompileAndLoadAssembly(fbs, new())); Assert.Contains("error: bit flag out of range of underlying integral type", ex.Message); }
public void InvalidEnumTest_NaturalOverflow() { string fbs = $"{MetadataHelpers.AllAttributes}namespace Foo.Bar; enum MyEnum : ubyte {{ Red = 255, Blue }}"; var ex = Assert.Throws <InvalidFbsFileException>(() => FlatSharpCompiler.CompileAndLoadAssembly(fbs, new())); Assert.Contains("error: enum value does not fit, \"255 + 1\" out of [0; 255]", ex.Message); }
public void NullableAnnotations() { string schema = $@" {MetadataHelpers.AllAttributes} namespace NullableAnnotationTests; table Table ({MetadataKeys.SerializerKind}) {{ foo:Foo; defaultInt:int32 = 3; str:string; nullableInt:int32 = null; arrayVector:[int32] ({MetadataKeys.VectorKind}:""Array""); memoryVector:[ubyte] ({MetadataKeys.VectorKind}:""Memory""); listVector:[int32] ({MetadataKeys.VectorKind}:""IList""); nestedTable:InnerTable; }} table InnerTable {{ str:string; }} struct Foo {{ id:ulong; count:short; prefix:byte; length:uint; }}"; Assembly asm = FlatSharpCompiler.CompileAndLoadAssembly( schema, new()); }
public void StructVector_NestedStruct() { int length = 7; string schema = $@" namespace StructVectorTests; table Table ({MetadataKeys.SerializerKind}) {{ foo:Foo; }} struct Bar {{ A:ubyte; B:ulong; }} struct Foo {{ V:[Bar:{length}] ({MetadataKeys.NonVirtualProperty}); }}"; Assembly asm = FlatSharpCompiler.CompileAndLoadAssembly( schema, new()); Type tableType = asm.GetType("StructVectorTests.Table"); Type fooType = asm.GetType("StructVectorTests.Foo"); Assert.IsFalse(fooType.GetProperty("__flatsharp__V_0").GetMethod.IsVirtual); Assert.IsFalse(fooType.GetProperty("__flatsharp__V_0").SetMethod.IsVirtual); Type barType = asm.GetType("StructVectorTests.Bar"); dynamic table = Activator.CreateInstance(tableType); dynamic foo = Activator.CreateInstance(fooType); table.foo = foo; Assert.AreEqual(length, foo.V.Count); for (int i = 0; i < length; ++i) { dynamic bar = Activator.CreateInstance(barType); bar.A = (byte)i; bar.B = (ulong)i; foo.V[i] = bar; } byte[] data = new byte[1024]; var serializer = CompilerTestHelpers.CompilerTestSerializer.Compile((object)table); serializer.Write(data, (object)table); dynamic parsed = serializer.Parse(data); dynamic copy = Activator.CreateInstance(tableType, (object)parsed); Assert.AreEqual(length, parsed.foo.V.Count); for (int i = 0; i < length; ++i) { Assert.AreEqual((byte)i, parsed.foo.V[i].A); Assert.AreEqual((byte)i, copy.foo.V[i].A); Assert.AreEqual((ulong)i, parsed.foo.V[i].B); Assert.AreEqual((ulong)i, copy.foo.V[i].B); } }
public void BasicEnumTest_Byte() { string schema = @" namespace Foo.Bar; table Request { str:string; } table Response { str:string; } rpc_service Service { HelloUnary(Request):Response (streaming:unary); HelloServer(Request):Response (streaming:""server""); HelloClient(Request):Response (streaming:client); HelloBidi(Request):Response (streaming:""bidi""); HelloUnaryImplicit(Request):Response; } "; BaseSchemaMember member = FlatSharpCompiler.TestHookParseSyntax(schema); var rpcDef = member.Children["Foo"].Children["Bar"].Children["Service"] as RpcDefinition; Assert.IsNotNull(rpcDef); Assert.AreEqual(5, rpcDef.Methods.Count); Assert.AreEqual(("Request", "Response", RpcStreamingType.Unary), rpcDef.Methods["HelloUnary"]); Assert.AreEqual(("Request", "Response", RpcStreamingType.Unary), rpcDef.Methods["HelloUnaryImplicit"]); Assert.AreEqual(("Request", "Response", RpcStreamingType.Server), rpcDef.Methods["HelloServer"]); Assert.AreEqual(("Request", "Response", RpcStreamingType.Client), rpcDef.Methods["HelloClient"]); Assert.AreEqual(("Request", "Response", RpcStreamingType.Bidirectional), rpcDef.Methods["HelloBidi"]); }
public void EnumTest <T>(string flatBufferType) where T : struct { string fbs = $"namespace Foo.Bar; enum MyEnum : {flatBufferType} {{ Red, Blue = 3, Green, Yellow }}"; Assembly asm = FlatSharpCompiler.CompileAndLoadAssembly(fbs, new()); Type t = asm.GetTypes().Single(x => x.FullName == "Foo.Bar.MyEnum"); Assert.IsTrue(t.IsEnum); Assert.AreEqual(typeof(T), Enum.GetUnderlyingType(t)); Assert.IsTrue(t.GetCustomAttribute <FlatSharp.Attributes.FlatBufferEnumAttribute>() != null); string[] names = Enum.GetNames(t); Assert.AreEqual(4, names.Length); Assert.AreEqual("Red", names[0]); Assert.AreEqual("Blue", names[1]); Assert.AreEqual("Green", names[2]); Assert.AreEqual("Yellow", names[3]); Array values = Enum.GetValues(t); Assert.AreEqual(Convert.ChangeType(0, typeof(T)), (T)values.GetValue(0)); Assert.AreEqual(Convert.ChangeType(3, typeof(T)), (T)values.GetValue(1)); Assert.AreEqual(Convert.ChangeType(4, typeof(T)), (T)values.GetValue(2)); Assert.AreEqual(Convert.ChangeType(5, typeof(T)), (T)values.GetValue(3)); }
private void RunSingleTest <T>(string fbsType, bool deprecated = false, bool hasDefaultValue = false, T expectedDefaultValue = default) { try { string schema = $@"namespace TableMemberTests; table Table {{ member:{fbsType}; member2:int; }}"; Assembly asm = FlatSharpCompiler.CompileAndLoadAssembly(schema); Type tableType = asm.GetType("TableMemberTests.Table"); PropertyInfo property = tableType.GetProperty("member"); Assert.AreEqual(typeof(T), property.PropertyType); var attribute = property.GetCustomAttribute <FlatBufferItemAttribute>(); Assert.AreEqual(0, attribute.Index); Assert.AreEqual(deprecated, attribute.Deprecated); Assert.AreEqual(hasDefaultValue, attribute.DefaultValue != null); if (hasDefaultValue) { Assert.IsInstanceOfType(attribute.DefaultValue, typeof(T)); T actualDefault = (T)attribute.DefaultValue; Assert.AreEqual(0, Comparer <T> .Default.Compare(expectedDefaultValue, actualDefault)); } byte[] data = new byte[100]; CompilerTestHelpers.CompilerTestSerializer.ReflectionSerialize(Activator.CreateInstance(tableType), data); CompilerTestHelpers.CompilerTestSerializer.ReflectionParse(tableType, data); } catch (TargetInvocationException ex) { throw ex.InnerException; } }
public void InvalidEnumTest_NotAnInt() { // Quirk of the grammar allows this. string fbs = $"{MetadataHelpers.AllAttributes}namespace Foo.Bar; enum MyEnum : uint {{ Red = 1.2 }}"; var ex = Assert.Throws <InvalidFbsFileException>(() => FlatSharpCompiler.CompileAndLoadAssembly(fbs, new())); Assert.Contains("error: enum value does not fit, \"1.2\"", ex.Message); }
public void LegacyObsoleteDefaultConstructor() { string schema = $@" namespace Foo; table Table ({MetadataKeys.ObsoleteDefaultConstructorLegacy}) {{ Int:int; }}"; var ex = Assert.ThrowsException <InvalidFbsFileException>(() => FlatSharpCompiler.CompileAndLoadAssembly(schema, new())); Assert.IsTrue(ex.Errors[0].StartsWith("Message='The 'ObsoleteDefaultConstructor' metadata attribute has been deprecated. Please use the 'fs_defaultCtor' attribute instead.'")); }
public void DefaultCtorKind_None_Struct() { string schema = $@" namespace Foo; struct InnerStruct ({MetadataKeys.DefaultConstructorKind}:""{DefaultConstructorKind.None}"") {{ Int:int; }}"; var ex = Assert.ThrowsException <InvalidFbsFileException>(() => FlatSharpCompiler.CompileAndLoadAssembly(schema, new())); Assert.AreEqual("Message='Structs must have default constructors.', Scope=$..Foo.InnerStruct", ex.Errors[0]); }
public void ForceWrite_OnOptionalScalar() { string schema = $@" namespace ForceWriteTests; table Table {{ optInt:int = null ({MetadataKeys.ForceWrite}); }} "; var ex = Assert.ThrowsException <InvalidFbsFileException>(() => FlatSharpCompiler.CompileAndLoadAssembly(schema, new())); Assert.IsTrue(ex.Errors[0].StartsWith("Message='Property 'optInt' on table 'ForceWriteTests.Table' declares the ForceWrite option, but the type is not supported for force write.', Scope=$")); }
public void ObsoleteConstructorExplicitFalse() { string schema = "namespace Foo; table BaseTable (obsoleteDefaultConstructor:\"false\") { Int:int; }"; Assembly asm = FlatSharpCompiler.CompileAndLoadAssembly(schema, new()); Type baseTableType = asm.GetTypes().Single(x => x.Name == "BaseTable"); var constructor = baseTableType.GetConstructor(new Type[0]); Assert.IsNull(constructor.GetCustomAttribute <ObsoleteAttribute>()); }
public void UnsupportedAttribute_ForceAlign_TableField() { string schema = @" namespace ns; table Foo { Value : int (force_align: 2); } "; var ex = Assert.Throws <InvalidFbsFileException>(() => FlatSharpCompiler.CompileAndLoadAssembly(schema, new())); Assert.Contains("FlatSharp does not support the 'force_align' attribute.", ex.Message); }
public void DefaultCtorKind_None_Struct() { string schema = $@" {MetadataHelpers.AllAttributes} namespace Foo; struct InnerStruct ({MetadataKeys.DefaultConstructorKind}:""{DefaultConstructorKind.None}"") {{ Int:int; }}"; var ex = Assert.Throws <InvalidFbsFileException>(() => FlatSharpCompiler.CompileAndLoadAssembly(schema, new())); Assert.Contains("The attribute 'fs_defaultCtor' value None is not valid on Struct elements.", ex.Errors[0]); }
public void TestMultipleNamespaces() { Assembly asm = FlatSharpCompiler.CompileAndLoadAssembly(Schema, new()); Assert.IsNotNull(asm.GetType("NamespaceA.NamespaceB.TableInNestedNS")); Assert.IsNotNull(asm.GetType("NamespaceA.NamespaceB.EnumInNestedNS")); Assert.IsNotNull(asm.GetType("NamespaceA.NamespaceB.StructInNestedNS")); Assert.IsNotNull(asm.GetType("NamespaceA.TableInFirstNS")); Assert.IsNotNull(asm.GetType("NamespaceC.TableInC")); Assert.IsNotNull(asm.GetType("NamespaceA.SecondTableInA")); }
public void DuplicateTypesDifferentFiles() { string baseFbs = "include \"A.fbs\"; namespace Foo; table BaseTable (PrecompiledSerializer) { BaseTable:BaseTable; }"; var includes = new Dictionary <string, string> { { "A.fbs", "namespace Foo; table BaseTable { BaseTable:BaseTable; }" }, }; var ex = Assert.ThrowsException <InvalidFbsFileException>(() => FlatSharpCompiler.TestHookCreateCSharp(baseFbs, includes)); Assert.IsTrue(ex.Message.Contains("Duplicate member name")); }
public void StructMember_with_id() { try { const string Schema = "namespace TableMemberTests; struct Struct { member:string (id:1); member2:int (id:0); }"; Assert.ThrowsException <InvalidFbsFileException>(() => FlatSharpCompiler.CompileAndLoadAssembly(Schema, new())); } catch (TargetInvocationException ex) { throw ex.InnerException; } }
public void TableMember_has_id_attribute_but_with_no_value() { try { const string Schema = "namespace TableMemberTests; table Table { member:string (id:0); member2:int (id); }"; Assert.ThrowsException <InvalidFbsFileException>(() => FlatSharpCompiler.CompileAndLoadAssembly(Schema, new())); } catch (TargetInvocationException ex) { throw ex.InnerException; } }
public void TableMember_only_some_fields_have_id() { try { const string Schema = "namespace TableMemberTests; table Table { member:string (id:1); member2:int; }"; Assert.ThrowsException <InvalidFbsFileException>(() => FlatSharpCompiler.CompileAndLoadAssembly(Schema, new())); } catch (TargetInvocationException ex) { throw ex.InnerException; } }
public void Unknown_Root_Type_No_File_Identifier() { string schema = $@" namespace FileIdTests.A; table Table {{ foo:int; }} root_type Something; "; var ex = Assert.ThrowsException <InvalidFbsFileException>(() => FlatSharpCompiler.CompileAndLoadAssembly(schema, new())); Assert.IsTrue(ex.Errors[0].StartsWith("Message='Unable to resolve root_type 'Something'.', Scope=$")); }
public void Manually_Specified_Id_TooLong() { string schema = $@" namespace FileIdTests.A; table Table ({MetadataKeys.FileIdentifier}:AbCdefg) {{ foo:int; }} root_type Table; "; var ex = Assert.ThrowsException <InvalidFbsFileException>(() => FlatSharpCompiler.CompileAndLoadAssembly(schema, new())); Assert.AreEqual(ex.Errors[0], "Message='File identifier 'AbCdefg' is invalid. FileIdentifiers must be exactly 4 ASCII characters.', Scope=$."); }
public void SortedVector_Dictionary_NoKey() { string schema = $@" table Monster (PrecompiledSerializer) {{ Vector:[VectorMember] (VectorType:IDictionary); }} table VectorMember {{ Data:string; }}"; Assert.ThrowsException <InvalidFbsFileException>(() => FlatSharpCompiler.CompileAndLoadAssembly(schema)); }
public void SortedVector_IndexedVector_NoKey() { string schema = $@" table Monster ({MetadataKeys.SerializerKind}) {{ Vector:[VectorMember] ({MetadataKeys.VectorKind}:IIndexedVector); }} table VectorMember {{ Data:string; }}"; Assert.ThrowsException <InvalidFbsFileException>(() => FlatSharpCompiler.CompileAndLoadAssembly(schema, new())); }
public void DefaultCtorKind_NoValue_Struct() { string schema = $"{MetadataHelpers.AllAttributes}namespace Foo; struct BaseTable ({MetadataKeys.DefaultConstructorKind}) {{ Int:int; }}"; Assembly asm = FlatSharpCompiler.CompileAndLoadAssembly(schema, new()); Type baseTableType = asm.GetTypes().Single(x => x.Name == "BaseTable"); var constructor = baseTableType.GetConstructor(new Type[0]); Assert.NotNull(constructor); Assert.True(constructor.IsPublic); Assert.Null(constructor.GetCustomAttribute <ObsoleteAttribute>()); }
public void Root_Type_With_No_File_Identifier() { string schema = $@" namespace FileIdTests.A; table Table {{ foo:int; }} root_type Table; "; Assembly asm = FlatSharpCompiler.CompileAndLoadAssembly(schema, new()); Assert.Null( asm.GetType("FileIdTests.A.Table").GetCustomAttribute <FlatBufferTableAttribute>().FileIdentifier); }
public void Enum_Root_Type() { string schema = $@" namespace FileIdTests.A; table Table {{ foo:int; }} enum Enum : ubyte {{ Foo, Bar, Baz }} root_type Enum; "; var ex = Assert.Throws <InvalidFbsFileException>(() => FlatSharpCompiler.CompileAndLoadAssembly(schema, new())); Assert.Contains("error: unknown root type: Enum", ex.Errors[0]); }
public void Struct_Root_Type() { string schema = $@" namespace FileIdTests.A; table Table {{ foo:int; }} struct Struct {{ foo:int; }} root_type Struct; "; var ex = Assert.Throws <InvalidFbsFileException>(() => FlatSharpCompiler.CompileAndLoadAssembly(schema, new())); Assert.Contains("error: root type must be a table", ex.Errors[0]); }