PageRenderTime 63ms CodeModel.GetById 13ms app.highlight 45ms RepoModel.GetById 1ms app.codeStats 0ms

/Test/Mono.Cecil.Tests/MethodBodyTests.cs

http://github.com/jbevain/cecil
C# | 453 lines | 380 code | 73 blank | 0 comment | 7 complexity | 877606d83fa2d96ef18aed217caf8439 MD5 | raw file
  1using System;
  2using System.Linq;
  3
  4using Mono.Cecil;
  5using Mono.Cecil.Cil;
  6
  7using NUnit.Framework;
  8
  9namespace Mono.Cecil.Tests {
 10
 11	[TestFixture]
 12	public class MethodBodyTests : BaseTestFixture {
 13
 14		[Test]
 15		public void MultiplyMethod ()
 16		{
 17			TestIL ("hello.il", module => {
 18				var foo = module.GetType ("Foo");
 19				Assert.IsNotNull (foo);
 20
 21				var bar = foo.GetMethod ("Bar");
 22				Assert.IsNotNull (bar);
 23				Assert.IsTrue (bar.IsIL);
 24
 25				AssertCode (@"
 26	.locals init (System.Int32 V_0)
 27	IL_0000: ldarg.0
 28	IL_0001: ldarg.1
 29	IL_0002: mul
 30	IL_0003: stloc.0
 31	IL_0004: ldloc.0
 32	IL_0005: call System.Void Foo::Baz(System.Int32)
 33	IL_000a: ret
 34", bar);
 35			});
 36		}
 37
 38		[Test]
 39		public void PrintStringEmpty ()
 40		{
 41			TestIL ("hello.il", module => {
 42				var foo = module.GetType ("Foo");
 43				Assert.IsNotNull (foo);
 44
 45				var print_empty = foo.GetMethod ("PrintEmpty");
 46				Assert.IsNotNull (print_empty);
 47
 48				AssertCode (@"
 49	.locals ()
 50	IL_0000: ldsfld System.String System.String::Empty
 51	IL_0005: call System.Void System.Console::WriteLine(System.String)
 52	IL_000a: ret
 53", print_empty);
 54			});
 55		}
 56
 57		[Test]
 58		public void Branch ()
 59		{
 60			TestModule ("libhello.dll", module => {
 61				var lib = module.GetType ("Library");
 62				Assert.IsNotNull (lib);
 63
 64				var method = lib.GetMethod ("GetHelloString");
 65				Assert.IsNotNull (method);
 66
 67				AssertCode (@"
 68	.locals init (System.String V_0)
 69	IL_0000: nop
 70	IL_0001: ldstr ""hello world of tomorrow""
 71	IL_0006: stloc.0
 72	IL_0007: br.s IL_0009
 73	IL_0009: ldloc.0
 74	IL_000a: ret
 75", method);
 76			});
 77		}
 78
 79		[Test]
 80		public void Switch ()
 81		{
 82			TestModule ("switch.exe", module => {
 83				var program = module.GetType ("Program");
 84				Assert.IsNotNull (program);
 85
 86				var method = program.GetMethod ("Main");
 87				Assert.IsNotNull (method);
 88
 89				AssertCode (@"
 90	.locals init (System.Int32 V_0)
 91	IL_0000: ldarg.0
 92	IL_0001: ldlen
 93	IL_0002: conv.i4
 94	IL_0003: stloc.0
 95	IL_0004: ldloc.0
 96	IL_0005: ldc.i4.8
 97	IL_0006: bgt.s IL_0026
 98	IL_0008: ldloc.0
 99	IL_0009: ldc.i4.1
100	IL_000a: sub
101	IL_000b: switch (IL_0032, IL_0034, IL_0038, IL_0034)
102	IL_0020: ldloc.0
103	IL_0021: ldc.i4.8
104	IL_0022: beq.s IL_0036
105	IL_0024: br.s IL_0038
106	IL_0026: ldloc.0
107	IL_0027: ldc.i4.s 16
108	IL_0029: beq.s IL_0036
109	IL_002b: ldloc.0
110	IL_002c: ldc.i4.s 32
111	IL_002e: beq.s IL_0036
112	IL_0030: br.s IL_0038
113	IL_0032: ldc.i4.0
114	IL_0033: ret
115	IL_0034: ldc.i4.1
116	IL_0035: ret
117	IL_0036: ldc.i4.2
118	IL_0037: ret
119	IL_0038: ldc.i4.s 42
120	IL_003a: ret
121", method);
122			});
123		}
124
125		[Test]
126		public void MethodSpec ()
127		{
128			TestIL ("methodspecs.il", module => {
129				var tamtam = module.GetType ("Tamtam");
130
131				var bar = tamtam.GetMethod ("Bar");
132				Assert.IsNotNull (bar);
133
134				AssertCode (@"
135	.locals ()
136	IL_0000: ldc.i4.2
137	IL_0001: call System.Void Tamtam::Foo<System.Int32>(TFoo)
138	IL_0006: ret
139", bar);
140			});
141		}
142
143		[Test]
144		public void NestedTryCatchFinally ()
145		{
146			TestModule ("catch.exe", module => {
147				var program = module.GetType ("Program");
148				var main = program.GetMethod ("Main");
149				Assert.IsNotNull (main);
150
151				AssertCode (@"
152	.locals ()
153	IL_0000: call System.Void Program::Foo()
154	IL_0005: leave.s IL_000d
155	IL_0007: call System.Void Program::Baz()
156	IL_000c: endfinally
157	IL_000d: leave.s IL_001f
158	IL_000f: pop
159	IL_0010: call System.Void Program::Bar()
160	IL_0015: leave.s IL_001f
161	IL_0017: pop
162	IL_0018: call System.Void Program::Bar()
163	IL_001d: leave.s IL_001f
164	IL_001f: leave.s IL_0027
165	IL_0021: call System.Void Program::Baz()
166	IL_0026: endfinally
167	IL_0027: ret
168	.try IL_0000 to IL_0007 finally handler IL_0007 to IL_000d
169	.try IL_0000 to IL_000f catch System.ArgumentException handler IL_000f to IL_0017
170	.try IL_0000 to IL_000f catch System.Exception handler IL_0017 to IL_001f
171	.try IL_0000 to IL_0021 finally handler IL_0021 to IL_0027
172", main);
173			});
174		}
175
176		[Test]
177		public void FunctionPointersAndCallSites ()
178		{
179			TestModule ("fptr.exe", module => {
180				var type = module.Types [0];
181				var start = type.GetMethod ("Start");
182				Assert.IsNotNull (start);
183
184				AssertCode (@"
185	.locals init ()
186	IL_0000: ldc.i4.1
187	IL_0001: call method System.Int32 *(System.Int32) MakeDecision::Decide()
188	IL_0006: calli System.Int32(System.Int32)
189	IL_000b: call System.Void System.Console::WriteLine(System.Int32)
190	IL_0010: ldc.i4.1
191	IL_0011: call method System.Int32 *(System.Int32) MakeDecision::Decide()
192	IL_0016: calli System.Int32(System.Int32)
193	IL_001b: call System.Void System.Console::WriteLine(System.Int32)
194	IL_0020: ldc.i4.1
195	IL_0021: call method System.Int32 *(System.Int32) MakeDecision::Decide()
196	IL_0026: calli System.Int32(System.Int32)
197	IL_002b: call System.Void System.Console::WriteLine(System.Int32)
198	IL_0030: ret
199", start);
200			}, verify: false);
201		}
202
203		[Test]
204		public void ThisParameter ()
205		{
206			TestIL ("hello.il", module => {
207				var type = module.GetType ("Foo");
208				var method = type.GetMethod ("Gazonk");
209
210				Assert.IsNotNull (method);
211
212				AssertCode (@"
213	.locals ()
214	IL_0000: ldarg 0
215	IL_0004: pop
216	IL_0005: ret
217", method);
218
219				Assert.AreEqual (method.Body.ThisParameter.ParameterType, type);
220				Assert.AreEqual (method.Body.ThisParameter, method.Body.Instructions [0].Operand);
221			});
222		}
223
224		[Test]
225		public void ThisParameterStaticMethod ()
226		{
227			var static_method = typeof (ModuleDefinition).ToDefinition ().Methods.Where (m => m.IsStatic).First ();
228			Assert.IsNull (static_method.Body.ThisParameter);
229		}
230
231		[Test]
232		public void ThisParameterPrimitive ()
233		{
234			var int32 = typeof (int).ToDefinition ();
235			var int_to_string = int32.Methods.Where (m => m.Name == "ToString" && m.Parameters.Count == 0).First();
236			Assert.IsNotNull (int_to_string);
237
238			var this_parameter_type = int_to_string.Body.ThisParameter.ParameterType;
239			Assert.IsTrue (this_parameter_type.IsByReference);
240
241			var element_type = ((ByReferenceType) this_parameter_type).ElementType;
242			Assert.AreEqual (int32, element_type);
243		}
244
245		[Test]
246		public void ThisParameterValueType ()
247		{
248			var token = typeof (MetadataToken).ToDefinition ();
249			var token_to_string = token.Methods.Where (m => m.Name == "ToString" && m.Parameters.Count == 0).First ();
250			Assert.IsNotNull (token_to_string);
251
252			var this_parameter_type = token_to_string.Body.ThisParameter.ParameterType;
253			Assert.IsTrue (this_parameter_type.IsByReference);
254
255			var element_type = ((ByReferenceType) this_parameter_type).ElementType;
256			Assert.AreEqual (token, element_type);
257		}
258
259		[Test]
260		public void ThisParameterObject ()
261		{
262			var module = typeof (MethodBodyTests).ToDefinition ().Module;
263			var @object = module.TypeSystem.Object.Resolve ();
264			var method = @object.Methods.Where (m => m.HasBody).First ();
265
266			var type = method.Body.ThisParameter.ParameterType;
267			Assert.IsFalse (type.IsValueType);
268			Assert.IsFalse (type.IsPrimitive);
269			Assert.IsFalse (type.IsPointer);
270		}
271
272		[Test]
273		public void FilterMaxStack ()
274		{
275			TestIL ("hello.il", module => {
276				var type = module.GetType ("Foo");
277				var method = type.GetMethod ("TestFilter");
278
279				Assert.IsNotNull (method);
280				Assert.AreEqual (2, method.Body.MaxStackSize);
281			});
282		}
283
284		[Test]
285		public void BranchOutsideMethod ()
286		{
287			OnlyOnWindows (); // Mono's ilasm doesn't support branching outside of method
288
289			TestIL ("branch-out.il", module => {
290				var type = module.GetType ("Foo");
291				var method = type.GetMethod ("BranchOutside");
292
293				Assert.IsNotNull (method);
294				Assert.IsNotNull (method.Body);
295
296				var leave = method.Body.Instructions [0];
297				Assert.AreEqual (OpCodes.Leave, leave.OpCode);
298				Assert.IsNull (leave.Operand);
299				Assert.AreEqual ("IL_0000: leave", leave.ToString ());
300			}, verify: false);
301		}
302
303		[Test]
304		public void Iterator ()
305		{
306			TestModule ("iterator.exe", module => {
307				var method = module.GetType ("Program").GetMethod ("GetLittleArgs");
308				Assert.IsNotNull (method.Body);
309			});
310		}
311
312		[Test]
313		public void LoadString ()
314		{
315			TestCSharp ("CustomAttributes.cs", module => {
316				var type = module.GetType ("FooAttribute");
317				var get_fiou = type.GetMethod ("get_Fiou");
318				Assert.IsNotNull (get_fiou);
319
320				var ldstr = get_fiou.Body.Instructions.Where (i => i.OpCode == OpCodes.Ldstr).First ();
321				Assert.AreEqual ("fiou", ldstr.Operand);
322			});
323		}
324
325		[Test]
326		public void UnattachedMethodBody ()
327		{
328			var system_void = typeof (void).ToDefinition ();
329			var method = new MethodDefinition ("NewMethod", MethodAttributes.Assembly | MethodAttributes.Static, system_void);
330			var body = new MethodBody (method);
331			var il = body.GetILProcessor ();
332			il.Emit (OpCodes.Ret);
333			method.Body = body;
334
335			Assert.AreEqual (body, method.Body);
336		}
337
338		[Test]
339		public void AddInstruction ()
340		{
341			var object_ref = new TypeReference ("System", "Object", null, null, false);
342			var method = new MethodDefinition ("foo", MethodAttributes.Static, object_ref);
343			var body = new MethodBody (method);
344
345			var il = body.GetILProcessor ();
346
347			var first = il.Create (OpCodes.Nop);
348			var second = il.Create (OpCodes.Nop);
349
350			body.Instructions.Add (first);
351			body.Instructions.Add (second);
352
353			Assert.IsNull (first.Previous);
354			Assert.AreEqual (second, first.Next);
355			Assert.AreEqual (first, second.Previous);
356			Assert.IsNull (second.Next);
357		}
358
359		[Test]
360		public void InsertInstruction ()
361		{
362			var object_ref = new TypeReference ("System", "Object", null, null, false);
363			var method = new MethodDefinition ("foo", MethodAttributes.Static, object_ref);
364			var body = new MethodBody (method);
365
366			var il = body.GetILProcessor ();
367
368			var first = il.Create (OpCodes.Nop);
369			var second = il.Create (OpCodes.Nop);
370			var third = il.Create (OpCodes.Nop);
371
372			body.Instructions.Add (first);
373			body.Instructions.Add (third);
374
375			Assert.IsNull (first.Previous);
376			Assert.AreEqual (third, first.Next);
377			Assert.AreEqual (first, third.Previous);
378			Assert.IsNull (third.Next);
379
380			body.Instructions.Insert (1, second);
381
382			Assert.IsNull (first.Previous);
383			Assert.AreEqual (second, first.Next);
384			Assert.AreEqual (first, second.Previous);
385			Assert.AreEqual (third, second.Next);
386			Assert.AreEqual (second, third.Previous);
387			Assert.IsNull (third.Next);
388		}
389
390		[Test]
391		public void InsertAfterLastInstruction ()
392		{
393			var object_ref = new TypeReference ("System", "Object", null, null, false);
394			var method = new MethodDefinition ("foo", MethodAttributes.Static, object_ref);
395			var body = new MethodBody (method);
396
397			var il = body.GetILProcessor ();
398
399			var first = il.Create (OpCodes.Nop);
400			var second = il.Create (OpCodes.Nop);
401			var third = il.Create (OpCodes.Nop);
402
403			body.Instructions.Add (first);
404			body.Instructions.Add (second);
405
406			Assert.IsNull (first.Previous);
407			Assert.AreEqual (second, first.Next);
408			Assert.AreEqual (first, second.Previous);
409			Assert.IsNull (second.Next);
410
411			body.Instructions.Insert (2, third);
412
413			Assert.IsNull (first.Previous);
414			Assert.AreEqual (second, first.Next);
415			Assert.AreEqual (first, second.Previous);
416			Assert.AreEqual (third, second.Next);
417			Assert.AreEqual (second, third.Previous);
418			Assert.IsNull (third.Next);
419		}
420
421		[Test]
422		public void RemoveInstruction ()
423		{
424			var object_ref = new TypeReference ("System", "Object", null, null, false);
425			var method = new MethodDefinition ("foo", MethodAttributes.Static, object_ref);
426			var body = new MethodBody (method);
427
428			var il = body.GetILProcessor ();
429
430			var first = il.Create (OpCodes.Nop);
431			var second = il.Create (OpCodes.Nop);
432			var third = il.Create (OpCodes.Nop);
433
434			body.Instructions.Add (first);
435			body.Instructions.Add (second);
436			body.Instructions.Add (third);
437
438			Assert.IsNull (first.Previous);
439			Assert.AreEqual (second, first.Next);
440			Assert.AreEqual (first, second.Previous);
441			Assert.AreEqual (third, second.Next);
442			Assert.AreEqual (second, third.Previous);
443			Assert.IsNull (third.Next);
444
445			body.Instructions.Remove (second);
446
447			Assert.IsNull (first.Previous);
448			Assert.AreEqual (third, first.Next);
449			Assert.AreEqual (first, third.Previous);
450			Assert.IsNull (third.Next);
451		}
452	}
453}