New tests, message update
[mono.git] / mcs / class / corlib / Test / System.Reflection.Emit / ILGeneratorTest.cs
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
7
8 using System;
9 using System.Reflection;
10 using System.Reflection.Emit;
11 using System.Threading;
12
13 using NUnit.Framework;
14
15 namespace MonoTests.System.Reflection.Emit
16 {
17         [TestFixture]
18         public class ILGeneratorTest
19         {
20                 TypeBuilder tb;
21                 ILGenerator il_gen;
22
23                 void DefineBasicMethod ()
24                 {
25                         MethodBuilder mb = tb.DefineMethod("F",
26                                 MethodAttributes.Public, typeof(string), null);
27                         il_gen = mb.GetILGenerator ();
28                 }
29
30                 [SetUp]
31                 public void SetUp ()
32                 {
33                         AssemblyName assemblyName = new AssemblyName ();
34                         assemblyName.Name = "MonoTests.System.Reflection.Emit.ILGeneratorTest";
35
36                         AssemblyBuilder assembly = Thread.GetDomain ().DefineDynamicAssembly (
37                                 assemblyName, AssemblyBuilderAccess.Run);
38
39                         ModuleBuilder module = assembly.DefineDynamicModule ("module1");
40                         tb = module.DefineType ("T", TypeAttributes.Public);
41                 }
42
43                 [Test]
44                 public void DeclareLocal_LocalType_Null ()
45                 {
46                         DefineBasicMethod ();
47
48                         try {
49                                 il_gen.DeclareLocal (null);
50                                 Assert.Fail ("#A1");
51                         } catch (ArgumentNullException ex) {
52                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#A2");
53                                 Assert.IsNull (ex.InnerException, "#A3");
54                                 Assert.IsNotNull (ex.Message, "#A4");
55                                 Assert.IsNotNull (ex.ParamName, "#A5");
56                                 Assert.AreEqual ("localType", ex.ParamName, "#A");
57                         }
58
59 #if NET_2_0
60                         try {
61                                 il_gen.DeclareLocal (null, false);
62                                 Assert.Fail ("#B1");
63                         } catch (ArgumentNullException ex) {
64                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#B2");
65                                 Assert.IsNull (ex.InnerException, "#B3");
66                                 Assert.IsNotNull (ex.Message, "#B4");
67                                 Assert.IsNotNull (ex.ParamName, "#B5");
68                                 Assert.AreEqual ("localType", ex.ParamName, "#B6");
69                         }
70 #endif
71                 }
72
73                 [Test]
74                 [ExpectedException (typeof (ArgumentException))]
75                 public void DefineFilterBodyWithTypeNotNull ()
76                 {
77                         DefineBasicMethod ();
78                         il_gen.BeginExceptionBlock ();
79                         il_gen.EmitWriteLine ("in try");
80                         il_gen.BeginExceptFilterBlock ();
81                         il_gen.EmitWriteLine ("in filter head");
82                         il_gen.BeginCatchBlock (typeof (Exception));
83                         il_gen.EmitWriteLine ("in filter body");
84                         il_gen.EndExceptionBlock ();
85                 }
86
87                 [Test] // bug #81431
88                 public void FilterAndCatchBlock ()
89                 {
90                         DefineBasicMethod ();
91                         ILGenerator il = il_gen;
92                         il.BeginExceptionBlock ();
93                         il.BeginExceptFilterBlock ();
94                         il.BeginCatchBlock (null);
95                         il.BeginCatchBlock (typeof (SystemException));
96                 }
97                 
98                 [Test]
99                 [ExpectedException (typeof (InvalidOperationException))]
100                 public void InvalidFilterBlock1 ()
101                 {
102                         DefineBasicMethod ();
103                         ILGenerator il = il_gen;
104                         il.BeginExceptionBlock ();
105                         il.BeginExceptFilterBlock ();
106                         il.EndExceptionBlock ();
107                 }
108                 
109                 [Test]
110                 public void ValidFilterBlock1 ()
111                 {
112                         DefineBasicMethod ();
113                         ILGenerator il = il_gen;
114                         il.BeginExceptionBlock ();
115                         il.BeginExceptFilterBlock ();
116                         il.BeginFaultBlock ();
117                         il.EndExceptionBlock ();
118                 }
119                 
120                 [Test]
121                 public void ValidFilterBlock2 ()
122                 {
123                         DefineBasicMethod ();
124                         ILGenerator il = il_gen;
125                         il.BeginExceptionBlock ();
126                         il.BeginExceptFilterBlock ();
127                         il.BeginFinallyBlock ();
128                         il.EndExceptionBlock ();
129                 }
130                 
131                 /// <summary>
132                 /// Try to emit something like that:
133                 ///
134                 /// .method public static bool TestFilter (bool execute_handler)
135                 /// {
136                 ///     .locals init(bool)
137                 ///     try {
138                 ///             newobj  instance void [mscorlib]System.Exception::.ctor()
139                 ///             throw
140                 ///     } filter {
141                 ///             pop
142                 ///             ldarg.0
143                 ///             endfilter
144                 ///     } {
145                 ///             ldc.i4.1
146                 ///             stloc.0
147                 ///             leave quit
148                 ///     }
149                 ///     ldc.i4.0
150                 ///     stloc.0
151                 /// quit:
152                 ///     ldloc.0
153                 ///     ret
154                 /// }
155                 ///
156                 /// It should return true if the handler has been executed
157                 /// Otherwise, the exception should not be catched
158                 /// </summary>
159                 void DefineTestFilterMethod ()
160                 {
161                         MethodBuilder mb = tb.DefineMethod("TestFilter",
162                                 MethodAttributes.Public | MethodAttributes.Static, typeof(bool), new Type [] { typeof (bool) });
163
164                         ConstructorInfo exCtor = typeof (Exception).GetConstructor (new Type [0]);
165
166                         il_gen = mb.GetILGenerator ();
167                         il_gen.DeclareLocal (typeof (bool));
168                         Label quit = il_gen.DefineLabel ();
169                         il_gen.BeginExceptionBlock ();
170                         il_gen.Emit (OpCodes.Newobj, exCtor);
171                         il_gen.Emit (OpCodes.Throw);
172                         il_gen.BeginExceptFilterBlock ();
173                         il_gen.Emit (OpCodes.Pop);
174                         il_gen.Emit (OpCodes.Ldarg_0);
175                         il_gen.BeginCatchBlock (null);
176                         il_gen.Emit (OpCodes.Ldc_I4_1);
177                         il_gen.Emit (OpCodes.Stloc_0);
178                         il_gen.Emit (OpCodes.Leave, quit);
179                         il_gen.EndExceptionBlock ();
180                         il_gen.Emit (OpCodes.Ldc_I4_0);
181                         il_gen.Emit (OpCodes.Stloc_0);
182                         il_gen.MarkLabel (quit);
183                         il_gen.Emit (OpCodes.Ldloc_0);
184                         il_gen.Emit (OpCodes.Ret);
185                 }
186
187                 [Test] // Emit (OpCode, ConstructorInfo)
188 #if NET_2_0
189                 [Category ("NotDotNet")] // MS bug: https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=304610
190 #endif
191                 public void Emit3_Constructor_Null ()
192                 {
193                         DefineBasicMethod ();
194                         try {
195                                 il_gen.Emit (OpCodes.Newobj, (ConstructorInfo) null);
196                                 Assert.Fail ("#1");
197                         } catch (ArgumentNullException ex) {
198                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
199                                 Assert.IsNull (ex.InnerException, "#3");
200                                 Assert.IsNotNull (ex.Message, "#4");
201                                 Assert.IsNotNull (ex.ParamName, "#5");
202                         }
203                 }
204
205 #if NET_2_0
206                 [Test] // Emit (OpCode, ConstructorInfo)
207                 [Category ("NotWorking")] // MS bug: https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=304610
208                 public void Emit3_Constructor_Null_MS ()
209                 {
210                         DefineBasicMethod ();
211                         try {
212                                 il_gen.Emit (OpCodes.Newobj, (ConstructorInfo) null);
213                                 Assert.Fail ("#1");
214                         } catch (NullReferenceException) {
215                         }
216                 }
217 #endif
218
219                 [Test] // Emit (OpCode, FieldInfo)
220                 public void Emit5_Field_Null ()
221                 {
222                         DefineBasicMethod ();
223                         try {
224                                 il_gen.Emit (OpCodes.Ldsfld, (FieldInfo) null);
225                                 Assert.Fail ("#1");
226                         } catch (ArgumentNullException ex) {
227                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
228                                 Assert.IsNull (ex.InnerException, "#3");
229                                 Assert.IsNotNull (ex.Message, "#4");
230                                 Assert.IsNotNull (ex.ParamName, "#5");
231                         }
232                 }
233
234                 [Test] // Emit (OpCode, Label [])
235                 [Category ("NotDotNet")] // MS bug: https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=304610
236                 public void Emit10_Labels_Null ()
237                 {
238                         DefineBasicMethod ();
239                         try {
240                                 il_gen.Emit (OpCodes.Switch, (Label []) null);
241                                 Assert.Fail ("#1");
242                         } catch (ArgumentNullException ex) {
243                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
244                                 Assert.IsNull (ex.InnerException, "#3");
245                                 Assert.IsNotNull (ex.Message, "#4");
246                                 Assert.IsNotNull (ex.ParamName, "#5");
247                                 Assert.AreEqual ("labels", ex.ParamName, "#6");
248                         }
249                 }
250
251                 [Test]
252                 [Category ("NotWorking")] // MS bug: https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=304610
253                 public void Emit10_Labels_Null_MS ()
254                 {
255                         DefineBasicMethod ();
256                         try {
257                                 il_gen.Emit (OpCodes.Switch, (Label []) null);
258                                 Assert.Fail ("#1");
259                         } catch (NullReferenceException) {
260                         }
261                 }
262
263                 [Test] // Emit (OpCode, LocalBuilder)
264                 public void Emit11_Local_Null ()
265                 {
266                         DefineBasicMethod ();
267                         try {
268                                 il_gen.Emit (OpCodes.Switch, (LocalBuilder) null);
269                                 Assert.Fail ("#1");
270                         } catch (ArgumentNullException ex) {
271                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
272                                 Assert.IsNull (ex.InnerException, "#3");
273                                 Assert.IsNotNull (ex.Message, "#4");
274                                 Assert.IsNotNull (ex.ParamName, "#5");
275                                 Assert.AreEqual ("local", ex.ParamName, "#6");
276                         }
277                 }
278
279                 [Test] // Emit (OpCode, MethodInfo)
280                 public void Emit12_Method_Null ()
281                 {
282                         DefineBasicMethod ();
283                         try {
284                                 il_gen.Emit (OpCodes.Switch, (MethodInfo) null);
285                                 Assert.Fail ("#1");
286                         } catch (ArgumentNullException ex) {
287                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
288                                 Assert.IsNull (ex.InnerException, "#3");
289                                 Assert.IsNotNull (ex.Message, "#4");
290                                 Assert.IsNotNull (ex.ParamName, "#5");
291                                 Assert.AreEqual ("meth", ex.ParamName, "#6");
292                         }
293                 }
294
295                 [Test] // Emit (OpCode, SignatureHelper)
296                 public void Emit14_Signature_Null ()
297                 {
298                         DefineBasicMethod ();
299                         try {
300                                 il_gen.Emit (OpCodes.Switch, (SignatureHelper) null);
301                                 Assert.Fail ("#1");
302                         } catch (ArgumentNullException ex) {
303                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
304                                 Assert.IsNull (ex.InnerException, "#3");
305                                 Assert.IsNotNull (ex.Message, "#4");
306                                 Assert.IsNotNull (ex.ParamName, "#5");
307                         }
308                 }
309
310                 [Test] // Emit (OpCode, String)
311                 public void Emit16_String_Null ()
312                 {
313                         DefineBasicMethod ();
314                         try {
315                                 il_gen.Emit (OpCodes.Switch, (String) null);
316                                 Assert.Fail ("#1");
317                         } catch (ArgumentNullException ex) {
318                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
319                                 Assert.IsNull (ex.InnerException, "#3");
320                                 Assert.IsNotNull (ex.Message, "#4");
321                         }
322                 }
323
324                 [Test] // Emit (OpCode, Type)
325                 public void Emit16_Type_Null ()
326                 {
327                         DefineBasicMethod ();
328                         try {
329                                 il_gen.Emit (OpCodes.Switch, (Type) null);
330                                 Assert.Fail ("#1");
331                         } catch (ArgumentNullException ex) {
332                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
333                                 Assert.IsNull (ex.InnerException, "#3");
334                                 Assert.IsNotNull (ex.Message, "#4");
335                                 Assert.IsNotNull (ex.ParamName, "#5");
336                         }
337                 }
338
339                 [Test]
340                 public void EmitCall_MethodInfo_Null ()
341                 {
342                         DefineBasicMethod ();
343                         try {
344                                 il_gen.EmitCall (OpCodes.Call, (MethodInfo) null, null);
345                                 Assert.Fail ("#1");
346                         } catch (ArgumentNullException ex) {
347                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
348                                 Assert.IsNull (ex.InnerException, "#3");
349                                 Assert.IsNotNull (ex.Message, "#4");
350                                 Assert.IsNotNull (ex.ParamName, "#5");
351                                 Assert.AreEqual ("methodInfo", ex.ParamName, "#6");
352                         }
353                 }
354
355                 [Test]
356                 public void TestFilterEmittingWithHandlerExecution ()
357                 {
358                         DefineTestFilterMethod ();
359                         Type dynt = tb.CreateType ();
360                         
361                         MethodInfo tf = dynt.GetMethod ("TestFilter");
362                         Assert.IsTrue ((bool) tf.Invoke (null, new object [] { true }));
363                 }
364
365                 [Test]
366                 [ExpectedException (typeof (Exception))]
367                 public void TestFilterEmittingWithoutHandlerExecution ()
368                 {
369                         DefineTestFilterMethod ();
370                         Type dynt = tb.CreateType ();
371                         
372                         MethodInfo tf = dynt.GetMethod ("TestFilter");
373                         try {
374                                 tf.Invoke (null, new object [] { false });
375                         } catch (TargetInvocationException tie) {
376                                 throw tie.InnerException;
377                         }
378                 }
379         }
380 }