2 // ILGeneratorTest.cs - NUnit Test Cases for the ILGenerator class
4 // Marek Safar (marek.safar@seznam.cz)
6 // (C) Novell, Inc. http://www.novell.com
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
19 public class ILGeneratorTest
24 void DefineBasicMethod ()
26 MethodBuilder mb
= tb
.DefineMethod("F",
27 MethodAttributes
.Public
, typeof(string), null);
28 il_gen
= mb
.GetILGenerator ();
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
);
45 public void DeclareLocal_LocalType_Null ()
50 il_gen
.DeclareLocal (null);
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");
62 il_gen
.DeclareLocal (null, false);
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");
75 [ExpectedException (typeof (ArgumentException
))]
76 public void DefineFilterBodyWithTypeNotNull ()
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 ();
89 public void FilterAndCatchBlock ()
92 ILGenerator il
= il_gen
;
93 il
.BeginExceptionBlock ();
94 il
.BeginExceptFilterBlock ();
95 il
.BeginCatchBlock (null);
96 il
.BeginCatchBlock (typeof (SystemException
));
100 [ExpectedException (typeof (InvalidOperationException
))]
101 public void InvalidFilterBlock1 ()
103 DefineBasicMethod ();
104 ILGenerator il
= il_gen
;
105 il
.BeginExceptionBlock ();
106 il
.BeginExceptFilterBlock ();
107 il
.EndExceptionBlock ();
111 public void ValidFilterBlock1 ()
113 DefineBasicMethod ();
114 ILGenerator il
= il_gen
;
115 il
.BeginExceptionBlock ();
116 il
.BeginExceptFilterBlock ();
117 il
.BeginFaultBlock ();
118 il
.EndExceptionBlock ();
122 public void ValidFilterBlock2 ()
124 DefineBasicMethod ();
125 ILGenerator il
= il_gen
;
126 il
.BeginExceptionBlock ();
127 il
.BeginExceptFilterBlock ();
128 il
.BeginFinallyBlock ();
129 il
.EndExceptionBlock ();
133 /// Try to emit something like that:
135 /// .method public static bool TestFilter (bool execute_handler)
137 /// .locals init(bool)
139 /// newobj instance void [mscorlib]System.Exception::.ctor()
157 /// It should return true if the handler has been executed
158 /// Otherwise, the exception should not be catched
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)
190 [Category ("NotDotNet")] // MS bug: https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=304610
192 public void Emit3_Constructor_Null ()
194 DefineBasicMethod ();
196 il_gen
.Emit (OpCodes
.Newobj
, (ConstructorInfo
) null);
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");
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 ();
213 il_gen
.Emit (OpCodes
.Newobj
, (ConstructorInfo
) null);
215 } catch (NullReferenceException
) {
220 [Test
] // Emit (OpCode, FieldInfo)
221 public void Emit5_Field_Null ()
223 DefineBasicMethod ();
225 il_gen
.Emit (OpCodes
.Ldsfld
, (FieldInfo
) null);
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 ();
241 il_gen
.Emit (OpCodes
.Switch
, (Label
[]) null);
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");
253 [Category ("NotWorking")] // MS bug: https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=304610
254 public void Emit10_Labels_Null_MS ()
256 DefineBasicMethod ();
258 il_gen
.Emit (OpCodes
.Switch
, (Label
[]) null);
260 } catch (NullReferenceException
) {
264 [Test
] // Emit (OpCode, LocalBuilder)
265 public void Emit11_Local_Null ()
267 DefineBasicMethod ();
269 il_gen
.Emit (OpCodes
.Switch
, (LocalBuilder
) null);
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 ();
285 il_gen
.Emit (OpCodes
.Switch
, (MethodInfo
) null);
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 ();
301 il_gen
.Emit (OpCodes
.Switch
, (SignatureHelper
) null);
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 ();
316 il_gen
.Emit (OpCodes
.Switch
, (String
) null);
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 ();
330 il_gen
.Emit (OpCodes
.Switch
, (Type
) null);
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");
341 public void EmitCall_MethodInfo_Null ()
343 DefineBasicMethod ();
345 il_gen
.EmitCall (OpCodes
.Call
, (MethodInfo
) null, null);
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");
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 }
));
367 delegate void FooFoo ();
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)) }
);
393 public void TestEmitCallIgnoresOptionalArgsForNonVarargMethod ()
395 DefineBasicMethod ();
397 il_gen
.EmitCall (OpCodes
.Call
, typeof (object).GetMethod ("GetHashCode"), new Type
[] { typeof (string) }
);
398 } catch (InvalidOperationException ex
) {
404 public void TestEmitCallThrowsOnOptionalArgsForNonVarargMethod ()
406 DefineBasicMethod ();
408 il_gen
.EmitCall (OpCodes
.Call
, typeof (object).GetMethod ("GetHashCode"), new Type
[] { typeof (string) }
);
410 } catch (InvalidOperationException ex
) {
416 [ExpectedException (typeof (Exception
))]
417 public void TestFilterEmittingWithoutHandlerExecution ()
419 DefineTestFilterMethod ();
420 Type dynt
= tb
.CreateType ();
422 MethodInfo tf
= dynt
.GetMethod ("TestFilter");
424 tf
.Invoke (null, new object [] { false }
);
425 } catch (TargetInvocationException tie
) {
426 throw tie
.InnerException
;
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]));