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 TestDefineType_InterfaceNotAbstract ()
137 AssemblyBuilder ab = genAssembly ();
138 ModuleBuilder mb = ab.DefineDynamicModule ("foo.dll", "foo.dll", true);
141 mb.DefineType ("ITest1", TypeAttributes.Interface);
143 } catch (InvalidOperationException ex) {
144 // Interface must be declared abstract
145 Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#A2");
146 Assert.IsNull (ex.InnerException, "#A3");
147 Assert.IsNotNull (ex.Message, "#A4");
151 mb.DefineType ("ITest2", TypeAttributes.Interface, (Type) null);
153 } catch (InvalidOperationException ex) {
154 // Interface must be declared abstract
155 Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#B2");
156 Assert.IsNull (ex.InnerException, "#B3");
157 Assert.IsNotNull (ex.Message, "#B4");
160 // fail on MS .NET 1.1
162 TypeBuilder tb = mb.DefineType ("ITest2", TypeAttributes.Interface,
164 Assert.AreEqual (typeof (object), tb.BaseType, "#C1");
166 tb = mb.DefineType ("ITest3", TypeAttributes.Interface,
167 typeof (IDisposable));
168 Assert.AreEqual (typeof (IDisposable), tb.BaseType, "#D1");
173 public void DuplicateSymbolDocument ()
175 AssemblyBuilder ab = genAssembly ();
176 ModuleBuilder mb = ab.DefineDynamicModule ("foo.dll", "foo.dll", true);
178 // Check that it is possible to redefine a symbol document
179 ISymbolDocumentWriter doc1 =
180 mb.DefineDocument ("foo.il", SymDocumentType.Text,
181 SymLanguageType.ILAssembly, SymLanguageVendor.Microsoft);
182 ISymbolDocumentWriter doc2 =
183 mb.DefineDocument ("foo.il", SymDocumentType.Text,
184 SymLanguageType.ILAssembly, SymLanguageVendor.Microsoft);
187 [Test] // Test case for #80435.
188 public void GetArrayMethodToStringTest ()
190 AssemblyBuilder assembly = genAssembly ();
191 ModuleBuilder module = assembly.DefineDynamicModule ("m", "test.dll");
193 Type [] myArrayClass = new Type [1];
194 Type [] parameterTypes = { typeof (Array) };
195 MethodInfo myMethodInfo = module.GetArrayMethod (myArrayClass.GetType (), "Sort", CallingConventions.Standard, null, parameterTypes);
197 string str = myMethodInfo.ToString ();
198 Assert.IsNotNull (str);
199 // Don't compare string, since MS returns System.Reflection.Emit.SymbolMethod here
200 // (they do not provide an implementation of ToString).
203 private static void AssertArrayEqualsSorted (Array o1, Array o2)
205 Array s1 = (Array) o1.Clone ();
206 Array s2 = (Array) o2.Clone ();
211 Assert.AreEqual (s1.Length, s2.Length, "#1");
212 for (int i = 0; i < s1.Length; ++i)
213 Assert.AreEqual (s1.GetValue (i), s2.GetValue (i), "#2: " + i);
218 public void ResolveFieldTokenFieldBuilder ()
220 AssemblyBuilder ab = genAssembly ();
221 ModuleBuilder mb = ab.DefineDynamicModule ("foo.dll", "foo.dll");
223 TypeBuilder tb = mb.DefineType ("foo");
224 FieldBuilder fb = tb.DefineField ("foo", typeof (int), 0);
227 FieldInfo fi = mb.ResolveField (fb.GetToken ().Token);
228 Assert.IsNotNull (fi);
229 Assert.AreEqual ("foo", fi.Name);
233 [ExpectedException (typeof (ArgumentException))]
234 public void ResolveFieldTokenInvalidToken ()
236 AssemblyBuilder ab = genAssembly ();
237 ModuleBuilder mb = ab.DefineDynamicModule ("foo.dll", "foo.dll");
239 mb.ResolveField (0x4001234);
243 public void ResolveMethodTokenMethodBuilder ()
245 AssemblyBuilder ab = genAssembly ();
246 ModuleBuilder moduleb = ab.DefineDynamicModule ("foo.dll", "foo.dll");
248 TypeBuilder tb = moduleb.DefineType ("foo");
249 MethodBuilder mb = tb.DefineMethod("Frub", MethodAttributes.Static, null, new Type[] { typeof(IntPtr) });
250 int tok = mb.GetToken().Token;
251 mb.SetImplementationFlags(MethodImplAttributes.NoInlining);
252 ILGenerator ilgen = mb.GetILGenerator();
253 ilgen.Emit(OpCodes.Ret);
257 MethodBase mi = moduleb.ResolveMethod (tok);
258 Assert.IsNotNull (mi);
259 Assert.AreEqual ("Frub", mi.Name);
264 public void GetTypes ()
266 AssemblyBuilder ab = genAssembly ();
267 ModuleBuilder mb = ab.DefineDynamicModule ("foo.dll", "foo.dll");
269 TypeBuilder tb1 = mb.DefineType("Foo", TypeAttributes.Public);
271 Type[] types = mb.GetTypes ();
272 Assert.AreEqual (1, types.Length);
273 Assert.AreEqual (tb1, types [0]);
275 // After the type is created, MS seems to return the created type
278 types = mb.GetTypes ();
279 Assert.AreEqual (tb1.CreateType (), types [0]);