2 // ModuleBuilderTest - NUnit Test Cases for the ModuleBuilder class
4 // Zoltan Varga (vargaz@freemail.hu)
6 // (C) Ximian, Inc. http://www.ximian.com
12 using System
.Threading
;
13 using System
.Reflection
;
14 using System
.Reflection
.Emit
;
16 using System
.Collections
;
17 using System
.Diagnostics
.SymbolStore
;
18 using System
.Runtime
.InteropServices
;
20 using NUnit
.Framework
;
22 namespace MonoTests
.System
.Reflection
.Emit
25 public class ModuleBuilderTest
27 static string tempDir
= Path
.Combine (Path
.GetTempPath (), typeof (ModuleBuilderTest
).FullName
);
28 static int nameIndex
= 0;
33 Random AutoRand
= new Random ();
34 string basePath
= tempDir
;
35 while (Directory
.Exists (tempDir
))
36 tempDir
= Path
.Combine (basePath
, AutoRand
.Next ().ToString ());
37 Directory
.CreateDirectory (tempDir
);
41 public void TearDown ()
44 // This throws an exception under MS.NET, since the directory contains loaded
46 Directory
.Delete (tempDir
, true);
51 private AssemblyName
genAssemblyName ()
53 AssemblyName assemblyName
= new AssemblyName();
54 assemblyName
.Name
= typeof (ModuleBuilderTest
).FullName
+ (nameIndex
++);
58 private AssemblyBuilder
genAssembly ()
60 return Thread
.GetDomain ().DefineDynamicAssembly (genAssemblyName (),
61 AssemblyBuilderAccess
.RunAndSave
,
66 public void TestIsTransient ()
68 AssemblyBuilder ab
= genAssembly ();
69 ModuleBuilder mb1
= ab
.DefineDynamicModule ("foo.dll");
70 Assert
.IsTrue (mb1
.IsTransient (), "#1");
71 ModuleBuilder mb2
= ab
.DefineDynamicModule ("foo2.dll", "foo2.dll");
72 Assert
.IsFalse (mb2
.IsTransient (), "#2");
75 // Some of these tests overlap with the tests for Module
78 public void TestGlobalData ()
80 AssemblyBuilder ab
= genAssembly ();
82 string resfile
= Path
.Combine (tempDir
, "res");
83 using (StreamWriter sw
= new StreamWriter (resfile
)) {
87 ModuleBuilder mb
= ab
.DefineDynamicModule ("foo.dll", "foo.dll");
89 mb
.DefineInitializedData ("DATA", new byte [100], FieldAttributes
.Public
);
90 mb
.DefineInitializedData ("DATA2", new byte [100], FieldAttributes
.Public
);
91 mb
.DefineInitializedData ("DATA3", new byte [99], FieldAttributes
.Public
);
92 mb
.DefineUninitializedData ("DATA4", 101, FieldAttributes
.Public
);
93 mb
.DefineInitializedData ("DATA_PRIVATE", new byte [100], 0);
94 mb
.CreateGlobalFunctions ();
98 Assembly assembly
= Assembly
.LoadFrom (Path
.Combine (tempDir
, "foo.dll"));
100 Module module
= assembly
.GetLoadedModules () [0];
102 string [] expectedFieldNames
= new string [] {
103 "DATA", "DATA2", "DATA3", "DATA4" };
104 ArrayList fieldNames
= new ArrayList ();
105 foreach (FieldInfo fi
in module
.GetFields ()) {
106 fieldNames
.Add (fi
.Name
);
108 AssertArrayEqualsSorted (expectedFieldNames
, fieldNames
.ToArray (typeof (string)));
110 Assert
.IsNotNull (module
.GetField ("DATA"), "#1");
111 Assert
.IsNotNull (module
.GetField ("DATA2"), "#2");
112 Assert
.IsNotNull (module
.GetField ("DATA3"), "#3");
113 Assert
.IsNotNull (module
.GetField ("DATA4"), "#4");
114 Assert
.IsNull (module
.GetField ("DATA_PRIVATE"), "#5");
115 Assert
.IsNotNull (module
.GetField ("DATA_PRIVATE", BindingFlags
.NonPublic
| BindingFlags
.Static
), "#6");
119 public void TestGlobalMethods ()
121 AssemblyBuilder builder
= genAssembly ();
122 ModuleBuilder module
= builder
.DefineDynamicModule ("MessageModule");
123 MethodBuilder method
= module
.DefinePInvokeMethod ("printf", "libc.so",
124 MethodAttributes
.PinvokeImpl
| MethodAttributes
.Static
| MethodAttributes
.Public
,
125 CallingConventions
.Standard
, typeof (void), new Type
[] { typeof (string) }
, CallingConvention
.Winapi
,
127 method
.SetImplementationFlags (MethodImplAttributes
.PreserveSig
|
128 method
.GetMethodImplementationFlags ());
129 module
.CreateGlobalFunctions ();
131 Assert
.IsNotNull (module
.GetMethod ("printf"));
135 public void DefineType_Name_Null ()
137 AssemblyBuilder ab
= genAssembly ();
138 ModuleBuilder mb
= ab
.DefineDynamicModule ("foo.dll", "foo.dll", true);
140 mb
.DefineType ((string) null);
142 } catch (ArgumentNullException ex
) {
143 Assert
.AreEqual (typeof (ArgumentNullException
), ex
.GetType (), "#2");
144 Assert
.IsNull (ex
.InnerException
, "#3");
145 Assert
.IsNotNull (ex
.Message
, "#4");
146 Assert
.AreEqual ("fullname", ex
.ParamName
, "#5");
151 public void DefineType_Name_Empty ()
153 AssemblyBuilder ab
= genAssembly ();
154 ModuleBuilder mb
= ab
.DefineDynamicModule ("foo.dll", "foo.dll", true);
156 mb
.DefineType (string.Empty
);
158 } catch (ArgumentException ex
) {
159 // Empty name is not legal
160 Assert
.AreEqual (typeof (ArgumentException
), ex
.GetType (), "#2");
161 Assert
.IsNull (ex
.InnerException
, "#3");
162 Assert
.IsNotNull (ex
.Message
, "#4");
163 Assert
.AreEqual ("fullname", ex
.ParamName
, "#5");
168 public void DefineType_Name_NullChar ()
170 AssemblyBuilder ab
= genAssembly ();
171 ModuleBuilder mb
= ab
.DefineDynamicModule ("foo.dll", "foo.dll", true);
173 mb
.DefineType ("\0test");
175 } catch (ArgumentException ex
) {
177 Assert
.AreEqual (typeof (ArgumentException
), ex
.GetType (), "#2");
178 Assert
.IsNull (ex
.InnerException
, "#3");
179 Assert
.IsNotNull (ex
.Message
, "#4");
180 Assert
.AreEqual ("fullname", ex
.ParamName
, "#5");
183 mb
.DefineType ("te\0st");
187 public void DefineType_InterfaceNotAbstract ()
189 AssemblyBuilder ab
= genAssembly ();
190 ModuleBuilder mb
= ab
.DefineDynamicModule ("foo.dll", "foo.dll", true);
193 mb
.DefineType ("ITest1", TypeAttributes
.Interface
);
195 } catch (InvalidOperationException ex
) {
196 // Interface must be declared abstract
197 Assert
.AreEqual (typeof (InvalidOperationException
), ex
.GetType (), "#A2");
198 Assert
.IsNull (ex
.InnerException
, "#A3");
199 Assert
.IsNotNull (ex
.Message
, "#A4");
203 mb
.DefineType ("ITest2", TypeAttributes
.Interface
, (Type
) null);
205 } catch (InvalidOperationException ex
) {
206 // Interface must be declared abstract
207 Assert
.AreEqual (typeof (InvalidOperationException
), ex
.GetType (), "#B2");
208 Assert
.IsNull (ex
.InnerException
, "#B3");
209 Assert
.IsNotNull (ex
.Message
, "#B4");
212 // fail on MS .NET 1.1
214 TypeBuilder tb
= mb
.DefineType ("ITest2", TypeAttributes
.Interface
,
216 Assert
.AreEqual (typeof (object), tb
.BaseType
, "#C1");
218 tb
= mb
.DefineType ("ITest3", TypeAttributes
.Interface
,
219 typeof (IDisposable
));
220 Assert
.AreEqual (typeof (IDisposable
), tb
.BaseType
, "#D1");
226 [Category ("NotDotNet")] // Parent type was not extensible by the given type
228 public void DefineType_Parent_Interface ()
232 AssemblyBuilder ab
= genAssembly ();
233 ModuleBuilder mb
= ab
.DefineDynamicModule ("foo.dll", "foo.dll", true);
235 tb
= mb
.DefineType ("Foo", TypeAttributes
.Class
,
236 typeof (ICollection
));
237 Assert
.AreEqual (typeof (ICollection
), tb
.BaseType
, "#1");
239 tb
= mb
.DefineType ("Bar", TypeAttributes
.Interface
,
240 typeof (ICollection
));
241 Assert
.AreEqual (typeof (ICollection
), tb
.BaseType
, "#2");
245 public void DuplicateSymbolDocument ()
247 AssemblyBuilder ab
= genAssembly ();
248 ModuleBuilder mb
= ab
.DefineDynamicModule ("foo.dll", "foo.dll", true);
250 // Check that it is possible to redefine a symbol document
251 ISymbolDocumentWriter doc1
=
252 mb
.DefineDocument ("foo.il", SymDocumentType
.Text
,
253 SymLanguageType
.ILAssembly
, SymLanguageVendor
.Microsoft
);
254 ISymbolDocumentWriter doc2
=
255 mb
.DefineDocument ("foo.il", SymDocumentType
.Text
,
256 SymLanguageType
.ILAssembly
, SymLanguageVendor
.Microsoft
);
259 [Test
] // Test case for #80435.
260 public void GetArrayMethodToStringTest ()
262 AssemblyBuilder assembly
= genAssembly ();
263 ModuleBuilder module
= assembly
.DefineDynamicModule ("m", "test.dll");
265 Type
[] myArrayClass
= new Type
[1];
266 Type
[] parameterTypes
= { typeof (Array) }
;
267 MethodInfo myMethodInfo
= module
.GetArrayMethod (myArrayClass
.GetType (), "Sort", CallingConventions
.Standard
, null, parameterTypes
);
269 string str
= myMethodInfo
.ToString ();
270 Assert
.IsNotNull (str
);
271 // Don't compare string, since MS returns System.Reflection.Emit.SymbolMethod here
272 // (they do not provide an implementation of ToString).
275 private static void AssertArrayEqualsSorted (Array o1
, Array o2
)
277 Array s1
= (Array
) o1
.Clone ();
278 Array s2
= (Array
) o2
.Clone ();
283 Assert
.AreEqual (s1
.Length
, s2
.Length
, "#1");
284 for (int i
= 0; i
< s1
.Length
; ++i
)
285 Assert
.AreEqual (s1
.GetValue (i
), s2
.GetValue (i
), "#2: " + i
);
290 public void ResolveFieldTokenFieldBuilder ()
292 AssemblyBuilder ab
= genAssembly ();
293 ModuleBuilder mb
= ab
.DefineDynamicModule ("foo.dll", "foo.dll");
295 TypeBuilder tb
= mb
.DefineType ("foo");
296 FieldBuilder fb
= tb
.DefineField ("foo", typeof (int), 0);
299 FieldInfo fi
= mb
.ResolveField (fb
.GetToken ().Token
);
300 Assert
.IsNotNull (fi
);
301 Assert
.AreEqual ("foo", fi
.Name
);
305 [ExpectedException (typeof (ArgumentException
))]
306 public void ResolveFieldTokenInvalidToken ()
308 AssemblyBuilder ab
= genAssembly ();
309 ModuleBuilder mb
= ab
.DefineDynamicModule ("foo.dll", "foo.dll");
311 mb
.ResolveField (0x4001234);
315 public void ResolveMethodTokenMethodBuilder ()
317 AssemblyBuilder ab
= genAssembly ();
318 ModuleBuilder moduleb
= ab
.DefineDynamicModule ("foo.dll", "foo.dll");
320 TypeBuilder tb
= moduleb
.DefineType ("foo");
321 MethodBuilder mb
= tb
.DefineMethod("Frub", MethodAttributes
.Static
, null, new Type
[] { typeof(IntPtr) }
);
322 int tok
= mb
.GetToken().Token
;
323 mb
.SetImplementationFlags(MethodImplAttributes
.NoInlining
);
324 ILGenerator ilgen
= mb
.GetILGenerator();
325 ilgen
.Emit(OpCodes
.Ret
);
329 MethodBase mi
= moduleb
.ResolveMethod (tok
);
330 Assert
.IsNotNull (mi
);
331 Assert
.AreEqual ("Frub", mi
.Name
);
336 public void GetTypes ()
338 AssemblyBuilder ab
= genAssembly ();
339 ModuleBuilder mb
= ab
.DefineDynamicModule ("foo.dll", "foo.dll");
341 TypeBuilder tb1
= mb
.DefineType("Foo", TypeAttributes
.Public
);
343 Type
[] types
= mb
.GetTypes ();
344 Assert
.AreEqual (1, types
.Length
);
345 Assert
.AreEqual (tb1
, types
[0]);
347 // After the type is created, MS seems to return the created type
350 types
= mb
.GetTypes ();
351 Assert
.AreEqual (tb1
.CreateType (), types
[0]);
354 [Test
] // GetTypeToken (Type)
356 [Category ("NotDotNet")] // http://support.microsoft.com/kb/950986
358 public void GetTypeToken2_Type_Array ()
364 AssemblyName aname
= genAssemblyName ();
365 AssemblyBuilder ab
= AppDomain
.CurrentDomain
.DefineDynamicAssembly (
366 aname
, AssemblyBuilderAccess
.RunAndSave
);
367 ModuleBuilder mb
= ab
.DefineDynamicModule ("MyModule");
369 type
= typeof (object []);
370 typeToken
= mb
.GetTypeToken (type
);
372 Assert
.IsFalse (typeToken
== TypeToken
.Empty
, "#A1");
373 resolved_type
= mb
.ResolveType (typeToken
.Token
);
374 Assert
.AreEqual (type
, resolved_type
, "#A2");
376 Assert
.IsFalse (typeToken
.Token
== TypeToken
.Empty
.Token
, "#A1");
380 type
= typeof (object).MakeArrayType ();
381 typeToken
= mb
.GetTypeToken (type
);
382 Assert
.IsFalse (typeToken
== TypeToken
.Empty
, "#B1");
383 resolved_type
= mb
.ResolveType (typeToken
.Token
);
384 Assert
.AreEqual (type
, resolved_type
, "#B2");
388 [Test
] // GetTypeToken (Type)
389 public void GetTypeToken2_Type_String ()
391 AssemblyName aname
= genAssemblyName ();
392 AssemblyBuilder ab
= AppDomain
.CurrentDomain
.DefineDynamicAssembly (
393 aname
, AssemblyBuilderAccess
.RunAndSave
);
394 ModuleBuilder mb
= ab
.DefineDynamicModule ("MyModule");
395 Type type
= typeof (string);
396 TypeToken typeToken
= mb
.GetTypeToken (type
);
398 Assert
.IsFalse (typeToken
== TypeToken
.Empty
, "#1");
399 Type resolved_type
= mb
.ResolveType (typeToken
.Token
);
400 Assert
.AreEqual (type
, resolved_type
, "#2");
402 Assert
.IsFalse (typeToken
.Token
== TypeToken
.Empty
.Token
, "#1");
407 [Test
] // bug #471302
408 public void ModuleBuilder_ModuleVersionId ()
410 var name
= new AssemblyName () { Name = "Foo" }
;
411 var assembly
= AppDomain
.CurrentDomain
.DefineDynamicAssembly (
412 name
, AssemblyBuilderAccess
.Run
);
414 var module
= assembly
.DefineDynamicModule ("Foo");
416 Assert
.AreNotEqual (new Guid (), module
.ModuleVersionId
);
421 public void GetGenericArguments_Returns_Null_For_Non_Generic_Methods ()