// Zoltan Varga (vargaz@freemail.hu)\r
//\r
// (C) Ximian, Inc. http://www.ximian.com\r
+//\r
+// TODO:\r
+// - implement a mechnanism for easier testing of null argument exceptions\r
+// - with overloaded methods like DefineNestedType (), check the defaults\r
+// on the shorter versions.\r
+// - ToString on enums with the flags attribute set should print all\r
+// values which match, e.g. 0 == AutoLayou,AnsiClass,NotPublic\r
+//\r
+\r
\r
using System;\r
using System.Threading;\r
namespace MonoTests.System.Reflection.Emit\r
{\r
\r
-public class TypeBuilderTest : TestCase\r
+[TestFixture]\r
+public class TypeBuilderTest : Assertion\r
{ \r
+ private interface AnInterface {\r
+ }\r
+\r
private AssemblyBuilder assembly;\r
\r
private ModuleBuilder module;\r
\r
static string ASSEMBLY_NAME = "MonoTests.System.Reflection.Emit.TypeBuilderTest";\r
\r
- protected override void SetUp () {\r
+ [SetUp]\r
+ protected void SetUp () {\r
AssemblyName assemblyName = new AssemblyName();\r
assemblyName.Name = ASSEMBLY_NAME;\r
\r
return "t" + (typeIndexer ++);\r
}\r
\r
+ private string nullName () {\r
+ return String.Format ("{0}", (char)0);\r
+ }\r
+\r
public void TestAssembly () {\r
TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public);\r
AssertEquals ("Assembly works",\r
typeof (int), tb.UnderlyingSystemType);\r
}\r
}\r
+\r
+ public void TestAddInterfaceImplementation () {\r
+ TypeBuilder tb = module.DefineType (genTypeName ());\r
+ try {\r
+ tb.AddInterfaceImplementation (null);\r
+ Fail ();\r
+ }\r
+ catch (ArgumentNullException) {\r
+ }\r
+\r
+ tb.AddInterfaceImplementation (typeof (AnInterface));\r
+ tb.AddInterfaceImplementation (typeof (AnInterface));\r
+\r
+ Type t = tb.CreateType ();\r
+ AssertEquals ("Should merge identical interfaces",\r
+ tb.GetInterfaces ().Length, 1);\r
+\r
+ // Can not be called on a created type\r
+ try {\r
+ tb.AddInterfaceImplementation (typeof (AnInterface));\r
+ Fail ();\r
+ }\r
+ catch (InvalidOperationException) {\r
+ }\r
+ }\r
+\r
+ public void TestCreateType () {\r
+ // TODO: LOTS OF TEST SHOULD GO THERE\r
+ TypeBuilder tb = module.DefineType (genTypeName ());\r
+ tb.CreateType ();\r
+\r
+ // Can not be called on a created type\r
+ try {\r
+ tb.CreateType ();\r
+ Fail ();\r
+ }\r
+ catch (InvalidOperationException) {\r
+ }\r
+ }\r
+\r
+ public void TestDefineConstructor () {\r
+ TypeBuilder tb = module.DefineType (genTypeName ());\r
+\r
+ ConstructorBuilder cb = tb.DefineConstructor (0, 0, null);\r
+ cb.GetILGenerator ().Emit (OpCodes.Ret);\r
+ tb.CreateType ();\r
+\r
+ // Can not be called on a created type\r
+ try {\r
+ tb.DefineConstructor (0, 0, null);\r
+ Fail ();\r
+ }\r
+ catch (InvalidOperationException) {\r
+ }\r
+ }\r
+\r
+ public void TestDefineDefaultConstructor () {\r
+ TypeBuilder tb = module.DefineType (genTypeName ());\r
+\r
+ tb.DefineDefaultConstructor (0);\r
+\r
+ tb.CreateType ();\r
+\r
+ // Can not be called on a created type, altough the MSDN docs does not mention this\r
+ try {\r
+ tb.DefineDefaultConstructor (0);\r
+ Fail ();\r
+ }\r
+ catch (InvalidOperationException) {\r
+ }\r
+ }\r
+\r
+ public void TestDefineEvent () {\r
+ TypeBuilder tb = module.DefineType (genTypeName ());\r
+\r
+ // Test invalid arguments\r
+ try {\r
+ tb.DefineEvent (null, 0, typeof (int));\r
+ Fail ();\r
+ }\r
+ catch (ArgumentNullException) {\r
+ }\r
+\r
+ try {\r
+ tb.DefineEvent ("FOO", 0, null);\r
+ Fail ();\r
+ }\r
+ catch (ArgumentNullException) {\r
+ }\r
+\r
+ try {\r
+ tb.DefineEvent ("", 0, typeof (int));\r
+ Fail ();\r
+ }\r
+ catch (ArgumentException) {\r
+ }\r
+\r
+ tb.CreateType ();\r
+ // Can not be called on a created type\r
+ try {\r
+ tb.DefineEvent ("BAR", 0, typeof (int));\r
+ Fail ();\r
+ }\r
+ catch (InvalidOperationException) {\r
+ }\r
+ }\r
+\r
+ public void TestDefineField () {\r
+ TypeBuilder tb = module.DefineType (genTypeName ());\r
+\r
+ // Check invalid arguments\r
+ try {\r
+ tb.DefineField (null, typeof (int), 0);\r
+ Fail ();\r
+ }\r
+ catch (ArgumentNullException) {\r
+ }\r
+\r
+ try {\r
+ tb.DefineField ("", typeof (int), 0);\r
+ Fail ();\r
+ }\r
+ catch (ArgumentException) {\r
+ }\r
+\r
+ try {\r
+ // Strangely, 'A<NULL>' is accepted...\r
+ string name = String.Format ("{0}", (char)0);\r
+ tb.DefineField (name, typeof (int), 0);\r
+ Fail ("Names with embedded nulls should be rejected");\r
+ }\r
+ catch (ArgumentException) {\r
+ }\r
+\r
+ try {\r
+ tb.DefineField ("A", typeof (void), 0);\r
+ Fail ();\r
+ }\r
+ catch (ArgumentException) {\r
+ }\r
+\r
+ tb.CreateType ();\r
+ // Can not be called on a created type\r
+ try {\r
+ tb.DefineField ("B", typeof (int), 0);\r
+ Fail ();\r
+ }\r
+ catch (InvalidOperationException) {\r
+ }\r
+ }\r
+\r
+ public void TestDefineInitializedData () {\r
+ TypeBuilder tb = module.DefineType (genTypeName ());\r
+ \r
+ // Check invalid arguments\r
+ try {\r
+ tb.DefineInitializedData (null, new byte[1], 0);\r
+ Fail ();\r
+ }\r
+ catch (ArgumentNullException) {\r
+ }\r
+\r
+ try {\r
+ tb.DefineInitializedData ("FOO", null, 0);\r
+ Fail ();\r
+ }\r
+ catch (ArgumentNullException) {\r
+ }\r
+\r
+ try {\r
+ tb.DefineInitializedData ("", new byte[1], 0);\r
+ Fail ();\r
+ }\r
+ catch (ArgumentException) {\r
+ }\r
+\r
+ // The size of the data is less than or equal to zero ???\r
+ try {\r
+ tb.DefineInitializedData ("BAR", new byte[0], 0);\r
+ Fail ();\r
+ }\r
+ catch (ArgumentException) {\r
+ }\r
+\r
+ try {\r
+ string name = String.Format ("{0}", (char)0);\r
+ tb.DefineInitializedData (name, new byte[1], 0);\r
+ Fail ("Names with embedded nulls should be rejected");\r
+ }\r
+ catch (ArgumentException) {\r
+ }\r
+\r
+ tb.CreateType ();\r
+\r
+ // Can not be called on a created type, altough the MSDN docs does not mention this\r
+ try {\r
+ tb.DefineInitializedData ("BAR2", new byte[1], 0);\r
+ Fail ();\r
+ }\r
+ catch (InvalidOperationException) {\r
+ }\r
+ }\r
+\r
+ public void TestDefineMethod () {\r
+ TypeBuilder tb = module.DefineType (genTypeName ());\r
+\r
+ // Check invalid arguments\r
+ try {\r
+ tb.DefineMethod (null, 0, null, null);\r
+ Fail ();\r
+ }\r
+ catch (ArgumentNullException) {\r
+ }\r
+\r
+ try {\r
+ tb.DefineMethod ("", 0, null, null);\r
+ Fail ();\r
+ }\r
+ catch (ArgumentException) {\r
+ }\r
+\r
+ // Check non-virtual methods on an interface\r
+ TypeBuilder tb2 = module.DefineType (genTypeName (), TypeAttributes.Interface | TypeAttributes.Abstract);\r
+ try {\r
+ tb2.DefineMethod ("FOO", MethodAttributes.Abstract, null, null);\r
+ Fail ();\r
+ }\r
+ catch (ArgumentException) {\r
+ }\r
+\r
+ tb.CreateType ();\r
+ // Can not be called on a created type\r
+ try {\r
+ tb.DefineMethod ("bar", 0, null, null);\r
+ Fail ();\r
+ }\r
+ catch (InvalidOperationException) {\r
+ }\r
+ }\r
+\r
+ // TODO: DefineMethodOverride\r
+\r
+ public void TestDefineNestedType () {\r
+ TypeBuilder tb = module.DefineType (genTypeName ());\r
+\r
+ // Check invalid arguments\r
+ try {\r
+ tb.DefineNestedType (null);\r
+ Fail ("Should reject null name");\r
+ }\r
+ catch (ArgumentNullException) {\r
+ }\r
+\r
+ try {\r
+ tb.DefineNestedType ("");\r
+ Fail ("Should reject empty name");\r
+ }\r
+ catch (ArgumentException) {\r
+ }\r
+\r
+ try {\r
+ tb.DefineNestedType (nullName ());\r
+ Fail ("Should reject name with embedded 0s");\r
+ }\r
+ catch (ArgumentException) {\r
+ }\r
+\r
+ // If I fix the code so this works then mcs breaks -> how can mcs\r
+ // works under MS .NET in the first place ???\r
+ /*\r
+ try {\r
+ tb.DefineNestedType ("AA", TypeAttributes.Public, null, null);\r
+ Fail ("Nested visibility must be specified.");\r
+ }\r
+ catch (ArgumentException) {\r
+ }\r
+ */\r
+\r
+ try {\r
+ tb.DefineNestedType ("BB", TypeAttributes.NestedPublic, null,\r
+ new Type[1]);\r
+ Fail ("Should reject empty interface");\r
+ }\r
+ catch (ArgumentException) {\r
+ }\r
+\r
+ // I think this should reject non-interfaces, but it does not\r
+ tb.DefineNestedType ("BB", TypeAttributes.NestedPublic, null,\r
+ new Type[1] { typeof (object) });\r
+\r
+ // Normal invocation\r
+ tb.DefineNestedType ("Nest");\r
+\r
+ tb.CreateType ();\r
+\r
+ // According to the MSDN docs, this cannnot be called after the type\r
+ // is created, but it works.\r
+ tb.DefineNestedType ("Nest2");\r
+\r
+ // According to the MSDN docs, a Sealed class can't contain nested \r
+ // types, but this is not true\r
+ TypeBuilder tb2 = module.DefineType (genTypeName (), TypeAttributes.Sealed);\r
+ tb2.DefineNestedType ("AA");\r
+\r
+ // According to the MSDN docs, interfaces can only contain interfaces,\r
+ // but this is not true\r
+ TypeBuilder tb3 = module.DefineType (genTypeName (), TypeAttributes.Interface | TypeAttributes.Abstract);\r
+\r
+ tb3.DefineNestedType ("AA");\r
+\r
+ // Check shorter versions\r
+ {\r
+ TypeBuilder nested = tb.DefineNestedType ("N1");\r
+\r
+ AssertEquals (nested.Name, "N1");\r
+ AssertEquals (nested.BaseType, typeof (object));\r
+ AssertEquals (nested.Attributes, TypeAttributes.NestedPrivate);\r
+ AssertEquals (nested.GetInterfaces ().Length, 0);\r
+ }\r
+\r
+ // TODO:\r
+ }\r
+\r
+ public void TestDefinePInvokeMethod () {\r
+ TypeBuilder tb = module.DefineType (genTypeName ());\r
+\r
+ tb.DefinePInvokeMethod ("A", "B", "C", 0, 0, null, null, 0, 0);\r
+\r
+ // Try invalid parameters\r
+ try {\r
+ tb.DefinePInvokeMethod (null, "B", "C", 0, 0, null, null, 0, 0);\r
+ Fail ();\r
+ }\r
+ catch (ArgumentNullException) {\r
+ }\r
+ // etc...\r
+\r
+ // Try invalid attributes\r
+ try {\r
+ tb.DefinePInvokeMethod ("A2", "B", "C", MethodAttributes.Abstract, 0, null, null, 0, 0);\r
+ }\r
+ catch (ArgumentException) {\r
+ }\r
+\r
+ // Try an interface parent\r
+ TypeBuilder tb2 = module.DefineType (genTypeName (), TypeAttributes.Interface | TypeAttributes.Abstract);\r
+\r
+ try {\r
+ tb2.DefinePInvokeMethod ("A", "B", "C", 0, 0, null, null, 0, 0);\r
+ }\r
+ catch (ArgumentException) {\r
+ }\r
+ }\r
+\r
+ public void TestDefineProperty () {\r
+ TypeBuilder tb = module.DefineType (genTypeName ());\r
+\r
+ // Check null parameter types\r
+ try {\r
+ tb.DefineProperty ("A", 0, null, new Type[1]);\r
+ }\r
+ catch (ArgumentNullException) {\r
+ }\r
+ }\r
+\r
+ public void TestIsDefined () {\r
+ TypeBuilder tb = module.DefineType (genTypeName ());\r
+\r
+ try {\r
+ tb.IsDefined (typeof (int), true);\r
+ Fail ();\r
+ }\r
+ catch (NotSupportedException) {\r
+ }\r
+ }\r
}\r
}\r
+\r