New test.
[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                 /// <summary>
73                 /// Try to emit something like that:
74                 ///
75                 /// .method public static bool TestFilter (bool execute_handler)
76                 /// {
77                 ///     .locals init(bool)
78                 ///     try {
79                 ///             newobj  instance void [mscorlib]System.Exception::.ctor()
80                 ///             throw
81                 ///     } filter {
82                 ///             pop
83                 ///             ldarg.0
84                 ///             endfilter
85                 ///     } {
86                 ///             ldc.i4.1
87                 ///             stloc.0
88                 ///             leave quit
89                 ///     }
90                 ///     ldc.i4.0
91                 ///     stloc.0
92                 /// quit:
93                 ///     ldloc.0
94                 ///     ret
95                 /// }
96                 ///
97                 /// It should return true if the handler has been executed
98                 /// Otherwise, the exception should not be catched
99                 /// </summary>
100                 void DefineTestFilterMethod ()
101                 {
102                         MethodBuilder mb = tb.DefineMethod("TestFilter",
103                                 MethodAttributes.Public | MethodAttributes.Static, typeof(bool), new Type [] { typeof (bool) });
104
105                         ConstructorInfo exCtor = typeof (Exception).GetConstructor (new Type [0]);
106
107                         il_gen = mb.GetILGenerator ();
108                         il_gen.DeclareLocal (typeof (bool));
109                         Label quit = il_gen.DefineLabel ();
110                         il_gen.BeginExceptionBlock ();
111                         il_gen.Emit (OpCodes.Newobj, exCtor);
112                         il_gen.Emit (OpCodes.Throw);
113                         il_gen.BeginExceptFilterBlock ();
114                         il_gen.Emit (OpCodes.Pop);
115                         il_gen.Emit (OpCodes.Ldarg_0);
116                         il_gen.BeginCatchBlock (null);
117                         il_gen.Emit (OpCodes.Ldc_I4_1);
118                         il_gen.Emit (OpCodes.Stloc_0);
119                         il_gen.Emit (OpCodes.Leave, quit);
120                         il_gen.EndExceptionBlock ();
121                         il_gen.Emit (OpCodes.Ldc_I4_0);
122                         il_gen.Emit (OpCodes.Stloc_0);
123                         il_gen.MarkLabel (quit);
124                         il_gen.Emit (OpCodes.Ldloc_0);
125                         il_gen.Emit (OpCodes.Ret);
126                 }
127
128                 [Test]
129                 public void TestFilterEmittingWithHandlerExecution ()
130                 {
131                         DefineTestFilterMethod ();
132                         Type dynt = tb.CreateType ();
133                         
134                         MethodInfo tf = dynt.GetMethod ("TestFilter");
135                         Assert.IsTrue ((bool) tf.Invoke (null, new object [] { true }));
136                 }
137
138                 [Test]
139                 [ExpectedException (typeof (Exception))]
140                 public void TestFilterEmittingWithoutHandlerExecution ()
141                 {
142                         DefineTestFilterMethod ();
143                         Type dynt = tb.CreateType ();
144                         
145                         MethodInfo tf = dynt.GetMethod ("TestFilter");
146                         try {
147                                 tf.Invoke (null, new object [] { false });
148                         } catch (TargetInvocationException tie) {
149                                 throw tie.InnerException;
150                         }
151                 }
152         }
153 }