In System.Reflection.Emit:
[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                 static TypeBuilder DefineDynType ()
24                 {
25                         AssemblyName assemblyName = new AssemblyName ();
26                         assemblyName.Name = "MonoTests.System.Reflection.Emit.ILGeneratorTest";
27
28                         AssemblyBuilder assembly = Thread.GetDomain ().DefineDynamicAssembly (
29                                 assemblyName, AssemblyBuilderAccess.Run);
30
31                         ModuleBuilder module = assembly.DefineDynamicModule ("module1");
32                         return module.DefineType ("T", TypeAttributes.Public);                  
33                 }
34                 
35                 void DefineBasicMethod ()
36                 {
37                         MethodBuilder mb = tb.DefineMethod("F",
38                                 MethodAttributes.Public, typeof(string), null);
39                         il_gen = mb.GetILGenerator ();
40                 }
41
42                 [SetUp]
43                 public void SetUp ()
44                 {                       
45                         tb = DefineDynType ();
46                 }
47
48                 [Test]
49                 [ExpectedException (typeof (ArgumentNullException))]
50                 public void DeclareLocal_NULL ()
51                 {
52                         DefineBasicMethod ();
53
54                         il_gen.DeclareLocal (null);
55                 }
56
57                 [Test]
58                 [ExpectedException (typeof (ArgumentException))]
59                 public void DefineFilterBodyWithTypeNotNull ()
60                 {
61                         DefineBasicMethod ();
62
63                         il_gen.BeginExceptionBlock ();
64                         il_gen.EmitWriteLine ("in try");
65                         il_gen.BeginExceptFilterBlock ();
66                         il_gen.EmitWriteLine ("in filter head");
67                         il_gen.BeginCatchBlock (typeof (Exception));
68                         il_gen.EmitWriteLine ("in filter body");
69                         il_gen.EndExceptionBlock ();
70                 }
71                 
72                 // Bug 81431
73                 [Test]
74                 public void FilterAndCatchBlock ()
75                 {
76                         DefineBasicMethod ();
77                         ILGenerator il = il_gen;
78                         il.BeginExceptionBlock ();
79                         il.BeginExceptFilterBlock ();
80                         il.BeginCatchBlock (null);
81                         il.BeginCatchBlock (typeof (SystemException));
82                 }
83                 
84                 [Test]
85                 [ExpectedException (typeof (InvalidOperationException))]
86                 public void InvalidFilterBlock1 ()
87                 {
88                         DefineBasicMethod ();
89                         ILGenerator il = il_gen;
90                         il.BeginExceptionBlock ();
91                         il.BeginExceptFilterBlock ();
92                         il.EndExceptionBlock ();
93                 }
94                 
95                 [Test]
96                 public void ValidFilterBlock1 ()
97                 {
98                         DefineBasicMethod ();
99                         ILGenerator il = il_gen;
100                         il.BeginExceptionBlock ();
101                         il.BeginExceptFilterBlock ();
102                         il.BeginFaultBlock ();
103                         il.EndExceptionBlock ();
104                 }
105                 
106                 [Test]
107                 public void ValidFilterBlock2 ()
108                 {
109                         DefineBasicMethod ();
110                         ILGenerator il = il_gen;
111                         il.BeginExceptionBlock ();
112                         il.BeginExceptFilterBlock ();
113                         il.BeginFinallyBlock ();
114                         il.EndExceptionBlock ();
115                 }
116                 
117                 /// <summary>
118                 /// Try to emit something like that:
119                 ///
120                 /// .method public static bool TestFilter (bool execute_handler)
121                 /// {
122                 ///     .locals init(bool)
123                 ///     try {
124                 ///             newobj  instance void [mscorlib]System.Exception::.ctor()
125                 ///             throw
126                 ///     } filter {
127                 ///             pop
128                 ///             ldarg.0
129                 ///             endfilter
130                 ///     } {
131                 ///             ldc.i4.1
132                 ///             stloc.0
133                 ///             leave quit
134                 ///     }
135                 ///     ldc.i4.0
136                 ///     stloc.0
137                 /// quit:
138                 ///     ldloc.0
139                 ///     ret
140                 /// }
141                 ///
142                 /// It should return true if the handler has been executed
143                 /// Otherwise, the exception should not be catched
144                 /// </summary>
145                 void DefineTestFilterMethod ()
146                 {
147                         MethodBuilder mb = tb.DefineMethod("TestFilter",
148                                 MethodAttributes.Public | MethodAttributes.Static, typeof(bool), new Type [] { typeof (bool) });
149
150                         ConstructorInfo exCtor = typeof (Exception).GetConstructor (new Type [0]);
151
152                         il_gen = mb.GetILGenerator ();
153                         il_gen.DeclareLocal (typeof (bool));
154                         Label quit = il_gen.DefineLabel ();
155                         il_gen.BeginExceptionBlock ();
156                         il_gen.Emit (OpCodes.Newobj, exCtor);
157                         il_gen.Emit (OpCodes.Throw);
158                         il_gen.BeginExceptFilterBlock ();
159                         il_gen.Emit (OpCodes.Pop);
160                         il_gen.Emit (OpCodes.Ldarg_0);
161                         il_gen.BeginCatchBlock (null);
162                         il_gen.Emit (OpCodes.Ldc_I4_1);
163                         il_gen.Emit (OpCodes.Stloc_0);
164                         il_gen.Emit (OpCodes.Leave, quit);
165                         il_gen.EndExceptionBlock ();
166                         il_gen.Emit (OpCodes.Ldc_I4_0);
167                         il_gen.Emit (OpCodes.Stloc_0);
168                         il_gen.MarkLabel (quit);
169                         il_gen.Emit (OpCodes.Ldloc_0);
170                         il_gen.Emit (OpCodes.Ret);
171                 }
172
173                 [Test]
174                 public void TestFilterEmittingWithHandlerExecution ()
175                 {
176                         DefineTestFilterMethod ();
177                         Type dynt = tb.CreateType ();
178                         
179                         MethodInfo tf = dynt.GetMethod ("TestFilter");
180                         Assert.IsTrue ((bool) tf.Invoke (null, new object [] { true }));
181                 }
182
183                 [Test]
184                 [ExpectedException (typeof (Exception))]
185                 public void TestFilterEmittingWithoutHandlerExecution ()
186                 {
187                         DefineTestFilterMethod ();
188                         Type dynt = tb.CreateType ();
189                         
190                         MethodInfo tf = dynt.GetMethod ("TestFilter");
191                         try {
192                                 tf.Invoke (null, new object [] { false });
193                         } catch (TargetInvocationException tie) {
194                                 throw tie.InnerException;
195                         }
196                 }
197         }
198 }