2009-12-09 Jb Evain <jbevain@novell.com>
[mcs.git] / class / corlib / Test / System.Reflection.Emit / ILGeneratorTest.cs
blobc300d3d293079e4bca40b8a7fefd2a0cc38ae65c
1 //
2 // ILGeneratorTest.cs - NUnit Test Cases for the ILGenerator class
3 //
4 // Marek Safar (marek.safar@seznam.cz)
5 //
6 // (C) Novell, Inc. http://www.novell.com
8 using System;
9 using System.Reflection;
10 using System.Reflection.Emit;
11 using System.Runtime.InteropServices;
12 using System.Threading;
14 using NUnit.Framework;
16 namespace MonoTests.System.Reflection.Emit
18 [TestFixture]
19 public class ILGeneratorTest
21 TypeBuilder tb;
22 ILGenerator il_gen;
24 void DefineBasicMethod ()
26 MethodBuilder mb = tb.DefineMethod("F",
27 MethodAttributes.Public, typeof(string), null);
28 il_gen = mb.GetILGenerator ();
31 [SetUp]
32 public void SetUp ()
34 AssemblyName assemblyName = new AssemblyName ();
35 assemblyName.Name = "MonoTests.System.Reflection.Emit.ILGeneratorTest";
37 AssemblyBuilder assembly = Thread.GetDomain ().DefineDynamicAssembly (
38 assemblyName, AssemblyBuilderAccess.Run);
40 ModuleBuilder module = assembly.DefineDynamicModule ("module1");
41 tb = module.DefineType ("T", TypeAttributes.Public);
44 [Test]
45 public void DeclareLocal_LocalType_Null ()
47 DefineBasicMethod ();
49 try {
50 il_gen.DeclareLocal (null);
51 Assert.Fail ("#A1");
52 } catch (ArgumentNullException ex) {
53 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#A2");
54 Assert.IsNull (ex.InnerException, "#A3");
55 Assert.IsNotNull (ex.Message, "#A4");
56 Assert.IsNotNull (ex.ParamName, "#A5");
57 Assert.AreEqual ("localType", ex.ParamName, "#A");
60 #if NET_2_0
61 try {
62 il_gen.DeclareLocal (null, false);
63 Assert.Fail ("#B1");
64 } catch (ArgumentNullException ex) {
65 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#B2");
66 Assert.IsNull (ex.InnerException, "#B3");
67 Assert.IsNotNull (ex.Message, "#B4");
68 Assert.IsNotNull (ex.ParamName, "#B5");
69 Assert.AreEqual ("localType", ex.ParamName, "#B6");
71 #endif
74 [Test]
75 [ExpectedException (typeof (ArgumentException))]
76 public void DefineFilterBodyWithTypeNotNull ()
78 DefineBasicMethod ();
79 il_gen.BeginExceptionBlock ();
80 il_gen.EmitWriteLine ("in try");
81 il_gen.BeginExceptFilterBlock ();
82 il_gen.EmitWriteLine ("in filter head");
83 il_gen.BeginCatchBlock (typeof (Exception));
84 il_gen.EmitWriteLine ("in filter body");
85 il_gen.EndExceptionBlock ();
88 [Test] // bug #81431
89 public void FilterAndCatchBlock ()
91 DefineBasicMethod ();
92 ILGenerator il = il_gen;
93 il.BeginExceptionBlock ();
94 il.BeginExceptFilterBlock ();
95 il.BeginCatchBlock (null);
96 il.BeginCatchBlock (typeof (SystemException));
99 [Test]
100 [ExpectedException (typeof (InvalidOperationException))]
101 public void InvalidFilterBlock1 ()
103 DefineBasicMethod ();
104 ILGenerator il = il_gen;
105 il.BeginExceptionBlock ();
106 il.BeginExceptFilterBlock ();
107 il.EndExceptionBlock ();
110 [Test]
111 public void ValidFilterBlock1 ()
113 DefineBasicMethod ();
114 ILGenerator il = il_gen;
115 il.BeginExceptionBlock ();
116 il.BeginExceptFilterBlock ();
117 il.BeginFaultBlock ();
118 il.EndExceptionBlock ();
121 [Test]
122 public void ValidFilterBlock2 ()
124 DefineBasicMethod ();
125 ILGenerator il = il_gen;
126 il.BeginExceptionBlock ();
127 il.BeginExceptFilterBlock ();
128 il.BeginFinallyBlock ();
129 il.EndExceptionBlock ();
132 /// <summary>
133 /// Try to emit something like that:
135 /// .method public static bool TestFilter (bool execute_handler)
136 /// {
137 /// .locals init(bool)
138 /// try {
139 /// newobj instance void [mscorlib]System.Exception::.ctor()
140 /// throw
141 /// } filter {
142 /// pop
143 /// ldarg.0
144 /// endfilter
145 /// } {
146 /// ldc.i4.1
147 /// stloc.0
148 /// leave quit
149 /// }
150 /// ldc.i4.0
151 /// stloc.0
152 /// quit:
153 /// ldloc.0
154 /// ret
155 /// }
157 /// It should return true if the handler has been executed
158 /// Otherwise, the exception should not be catched
159 /// </summary>
160 void DefineTestFilterMethod ()
162 MethodBuilder mb = tb.DefineMethod("TestFilter",
163 MethodAttributes.Public | MethodAttributes.Static, typeof(bool), new Type [] { typeof (bool) });
165 ConstructorInfo exCtor = typeof (Exception).GetConstructor (new Type [0]);
167 il_gen = mb.GetILGenerator ();
168 il_gen.DeclareLocal (typeof (bool));
169 Label quit = il_gen.DefineLabel ();
170 il_gen.BeginExceptionBlock ();
171 il_gen.Emit (OpCodes.Newobj, exCtor);
172 il_gen.Emit (OpCodes.Throw);
173 il_gen.BeginExceptFilterBlock ();
174 il_gen.Emit (OpCodes.Pop);
175 il_gen.Emit (OpCodes.Ldarg_0);
176 il_gen.BeginCatchBlock (null);
177 il_gen.Emit (OpCodes.Ldc_I4_1);
178 il_gen.Emit (OpCodes.Stloc_0);
179 il_gen.Emit (OpCodes.Leave, quit);
180 il_gen.EndExceptionBlock ();
181 il_gen.Emit (OpCodes.Ldc_I4_0);
182 il_gen.Emit (OpCodes.Stloc_0);
183 il_gen.MarkLabel (quit);
184 il_gen.Emit (OpCodes.Ldloc_0);
185 il_gen.Emit (OpCodes.Ret);
188 [Test] // Emit (OpCode, ConstructorInfo)
189 #if NET_2_0
190 [Category ("NotDotNet")] // MS bug: https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=304610
191 #endif
192 public void Emit3_Constructor_Null ()
194 DefineBasicMethod ();
195 try {
196 il_gen.Emit (OpCodes.Newobj, (ConstructorInfo) null);
197 Assert.Fail ("#1");
198 } catch (ArgumentNullException ex) {
199 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
200 Assert.IsNull (ex.InnerException, "#3");
201 Assert.IsNotNull (ex.Message, "#4");
202 Assert.IsNotNull (ex.ParamName, "#5");
206 #if NET_2_0
207 [Test] // Emit (OpCode, ConstructorInfo)
208 [Category ("NotWorking")] // MS bug: https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=304610
209 public void Emit3_Constructor_Null_MS ()
211 DefineBasicMethod ();
212 try {
213 il_gen.Emit (OpCodes.Newobj, (ConstructorInfo) null);
214 Assert.Fail ("#1");
215 } catch (NullReferenceException) {
218 #endif
220 [Test] // Emit (OpCode, FieldInfo)
221 public void Emit5_Field_Null ()
223 DefineBasicMethod ();
224 try {
225 il_gen.Emit (OpCodes.Ldsfld, (FieldInfo) null);
226 Assert.Fail ("#1");
227 } catch (ArgumentNullException ex) {
228 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
229 Assert.IsNull (ex.InnerException, "#3");
230 Assert.IsNotNull (ex.Message, "#4");
231 Assert.IsNotNull (ex.ParamName, "#5");
235 [Test] // Emit (OpCode, Label [])
236 [Category ("NotDotNet")] // MS bug: https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=304610
237 public void Emit10_Labels_Null ()
239 DefineBasicMethod ();
240 try {
241 il_gen.Emit (OpCodes.Switch, (Label []) null);
242 Assert.Fail ("#1");
243 } catch (ArgumentNullException ex) {
244 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
245 Assert.IsNull (ex.InnerException, "#3");
246 Assert.IsNotNull (ex.Message, "#4");
247 Assert.IsNotNull (ex.ParamName, "#5");
248 Assert.AreEqual ("labels", ex.ParamName, "#6");
252 [Test]
253 [Category ("NotWorking")] // MS bug: https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=304610
254 public void Emit10_Labels_Null_MS ()
256 DefineBasicMethod ();
257 try {
258 il_gen.Emit (OpCodes.Switch, (Label []) null);
259 Assert.Fail ("#1");
260 } catch (NullReferenceException) {
264 [Test] // Emit (OpCode, LocalBuilder)
265 public void Emit11_Local_Null ()
267 DefineBasicMethod ();
268 try {
269 il_gen.Emit (OpCodes.Switch, (LocalBuilder) null);
270 Assert.Fail ("#1");
271 } catch (ArgumentNullException ex) {
272 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
273 Assert.IsNull (ex.InnerException, "#3");
274 Assert.IsNotNull (ex.Message, "#4");
275 Assert.IsNotNull (ex.ParamName, "#5");
276 Assert.AreEqual ("local", ex.ParamName, "#6");
280 [Test] // Emit (OpCode, MethodInfo)
281 public void Emit12_Method_Null ()
283 DefineBasicMethod ();
284 try {
285 il_gen.Emit (OpCodes.Switch, (MethodInfo) null);
286 Assert.Fail ("#1");
287 } catch (ArgumentNullException ex) {
288 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
289 Assert.IsNull (ex.InnerException, "#3");
290 Assert.IsNotNull (ex.Message, "#4");
291 Assert.IsNotNull (ex.ParamName, "#5");
292 Assert.AreEqual ("meth", ex.ParamName, "#6");
296 [Test] // Emit (OpCode, SignatureHelper)
297 public void Emit14_Signature_Null ()
299 DefineBasicMethod ();
300 try {
301 il_gen.Emit (OpCodes.Switch, (SignatureHelper) null);
302 Assert.Fail ("#1");
303 } catch (ArgumentNullException ex) {
304 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
305 Assert.IsNull (ex.InnerException, "#3");
306 Assert.IsNotNull (ex.Message, "#4");
307 Assert.IsNotNull (ex.ParamName, "#5");
311 [Test] // Emit (OpCode, String)
312 public void Emit16_String_Null ()
314 DefineBasicMethod ();
315 try {
316 il_gen.Emit (OpCodes.Switch, (String) null);
317 Assert.Fail ("#1");
318 } catch (ArgumentNullException ex) {
319 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
320 Assert.IsNull (ex.InnerException, "#3");
321 Assert.IsNotNull (ex.Message, "#4");
325 [Test] // Emit (OpCode, Type)
326 public void Emit16_Type_Null ()
328 DefineBasicMethod ();
329 try {
330 il_gen.Emit (OpCodes.Switch, (Type) null);
331 Assert.Fail ("#1");
332 } catch (ArgumentNullException ex) {
333 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
334 Assert.IsNull (ex.InnerException, "#3");
335 Assert.IsNotNull (ex.Message, "#4");
336 Assert.IsNotNull (ex.ParamName, "#5");
340 [Test]
341 public void EmitCall_MethodInfo_Null ()
343 DefineBasicMethod ();
344 try {
345 il_gen.EmitCall (OpCodes.Call, (MethodInfo) null, null);
346 Assert.Fail ("#1");
347 } catch (ArgumentNullException ex) {
348 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
349 Assert.IsNull (ex.InnerException, "#3");
350 Assert.IsNotNull (ex.Message, "#4");
351 Assert.IsNotNull (ex.ParamName, "#5");
352 Assert.AreEqual ("methodInfo", ex.ParamName, "#6");
356 [Test]
357 public void TestFilterEmittingWithHandlerExecution ()
359 DefineTestFilterMethod ();
360 Type dynt = tb.CreateType ();
362 MethodInfo tf = dynt.GetMethod ("TestFilter");
363 Assert.IsTrue ((bool) tf.Invoke (null, new object [] { true }));
366 #if NET_2_0
367 delegate void FooFoo ();
369 static void Foo ()
373 [Test]
374 public void TestEmitCalliWithNullReturnType ()
376 MethodBuilder mb = tb.DefineMethod ("F",
377 MethodAttributes.Public | MethodAttributes.Static, null, new Type [] { typeof (IntPtr) });
378 mb.SetImplementationFlags (MethodImplAttributes.NoInlining);
379 il_gen = mb.GetILGenerator ();
380 il_gen.Emit (OpCodes.Ldarg_0);
381 il_gen.EmitCalli (OpCodes.Calli, CallingConvention.StdCall, null, Type.EmptyTypes);
382 il_gen.Emit (OpCodes.Ret);
384 Type dynt = tb.CreateType ();
385 dynt.GetMethod ("F", BindingFlags.Public | BindingFlags.Static).Invoke (
386 null, new object [] { Marshal.GetFunctionPointerForDelegate (new FooFoo (Foo)) });
388 #endif
390 #if NET_2_0
391 //Test for #509131
392 [Test]
393 public void TestEmitCallIgnoresOptionalArgsForNonVarargMethod ()
395 DefineBasicMethod ();
396 try {
397 il_gen.EmitCall (OpCodes.Call, typeof (object).GetMethod ("GetHashCode"), new Type[] { typeof (string) });
398 } catch (InvalidOperationException ex) {
399 Assert.Fail ("#1");
402 #else
403 [Test]
404 public void TestEmitCallThrowsOnOptionalArgsForNonVarargMethod ()
406 DefineBasicMethod ();
407 try {
408 il_gen.EmitCall (OpCodes.Call, typeof (object).GetMethod ("GetHashCode"), new Type[] { typeof (string) });
409 Assert.Fail ("#1");
410 } catch (InvalidOperationException ex) {
413 #endif
415 [Test]
416 [ExpectedException (typeof (Exception))]
417 public void TestFilterEmittingWithoutHandlerExecution ()
419 DefineTestFilterMethod ();
420 Type dynt = tb.CreateType ();
422 MethodInfo tf = dynt.GetMethod ("TestFilter");
423 try {
424 tf.Invoke (null, new object [] { false });
425 } catch (TargetInvocationException tie) {
426 throw tie.InnerException;
430 [Test]
431 public void TestEmitLocalInfoWithNopOpCode ()
433 var method_builder = tb.DefineMethod ("linop", MethodAttributes.Public | MethodAttributes.Static, typeof (bool), Type.EmptyTypes);
434 il_gen = method_builder.GetILGenerator ();
436 var local = il_gen.DeclareLocal (typeof (int));
437 il_gen.Emit (OpCodes.Nop, local);
438 il_gen.Emit (OpCodes.Ldc_I4_1);
439 il_gen.Emit (OpCodes.Ret);
441 var type = tb.CreateType ();
442 var method = type.GetMethod ("linop");
444 Assert.IsNotNull (method);
445 Assert.IsTrue ((bool) method.Invoke (null, new object [0]));