/symbols/pdb/Test/Mono.Cecil.Tests/PdbTests.cs

http://github.com/jbevain/cecil · C# · 469 lines · 366 code · 103 blank · 0 comment · 5 complexity · d75e4610ed0f6179ead8d26262210cc4 MD5 · raw file

  1. using System.IO;
  2. using System.Linq;
  3. using Mono.Cecil.Cil;
  4. using Mono.Cecil.Pdb;
  5. using NUnit.Framework;
  6. namespace Mono.Cecil.Tests {
  7. [TestFixture]
  8. public class PdbTests : BaseTestFixture {
  9. [Test]
  10. public void Main ()
  11. {
  12. TestModule ("test.exe", module => {
  13. var type = module.GetType ("Program");
  14. var main = type.GetMethod ("Main");
  15. AssertCode (@"
  16. .locals init (System.Int32 i, System.Int32 CS$1$0000, System.Boolean CS$4$0001)
  17. .line 6,6:2,3 'c:\sources\cecil\symbols\Mono.Cecil.Pdb\Test\Resources\assemblies\test.cs'
  18. IL_0000: nop
  19. .line 7,7:8,18 'c:\sources\cecil\symbols\Mono.Cecil.Pdb\Test\Resources\assemblies\test.cs'
  20. IL_0001: ldc.i4.0
  21. IL_0002: stloc.0
  22. .line hidden 'c:\sources\cecil\symbols\Mono.Cecil.Pdb\Test\Resources\assemblies\test.cs'
  23. IL_0003: br.s IL_0012
  24. .line 8,8:4,21 'c:\sources\cecil\symbols\Mono.Cecil.Pdb\Test\Resources\assemblies\test.cs'
  25. IL_0005: ldarg.0
  26. IL_0006: ldloc.0
  27. IL_0007: ldelem.ref
  28. IL_0008: call System.Void Program::Print(System.String)
  29. IL_000d: nop
  30. .line 7,7:36,39 'c:\sources\cecil\symbols\Mono.Cecil.Pdb\Test\Resources\assemblies\test.cs'
  31. IL_000e: ldloc.0
  32. IL_000f: ldc.i4.1
  33. IL_0010: add
  34. IL_0011: stloc.0
  35. .line 7,7:19,34 'c:\sources\cecil\symbols\Mono.Cecil.Pdb\Test\Resources\assemblies\test.cs'
  36. IL_0012: ldloc.0
  37. IL_0013: ldarg.0
  38. IL_0014: ldlen
  39. IL_0015: conv.i4
  40. IL_0016: clt
  41. IL_0018: stloc.2
  42. .line hidden 'c:\sources\cecil\symbols\Mono.Cecil.Pdb\Test\Resources\assemblies\test.cs'
  43. IL_0019: ldloc.2
  44. IL_001a: brtrue.s IL_0005
  45. .line 10,10:3,12 'c:\sources\cecil\symbols\Mono.Cecil.Pdb\Test\Resources\assemblies\test.cs'
  46. IL_001c: ldc.i4.0
  47. IL_001d: stloc.1
  48. IL_001e: br.s IL_0020
  49. .line 11,11:2,3 'c:\sources\cecil\symbols\Mono.Cecil.Pdb\Test\Resources\assemblies\test.cs'
  50. IL_0020: ldloc.1
  51. IL_0021: ret
  52. ", main);
  53. }, readOnly: !Platform.HasNativePdbSupport, symbolReaderProvider: typeof(PdbReaderProvider), symbolWriterProvider: typeof(PdbWriterProvider));
  54. }
  55. [Test]
  56. public void DebuggerHiddenVariable ()
  57. {
  58. TestModule ("test.exe", module => {
  59. var type = module.GetType ("Program");
  60. var method = type.GetMethod ("Main");
  61. var scope = method.DebugInformation.Scope;
  62. Assert.IsTrue (scope.HasVariables);
  63. var variables = scope.Variables;
  64. Assert.AreEqual ("CS$1$0000", variables [0].Name);
  65. Assert.IsTrue (variables [0].IsDebuggerHidden);
  66. Assert.AreEqual ("CS$4$0001", variables [1].Name);
  67. Assert.IsTrue (variables [1].IsDebuggerHidden);
  68. Assert.AreEqual (1, scope.Scopes.Count);
  69. scope = scope.Scopes [0];
  70. variables = scope.Variables;
  71. Assert.AreEqual ("i", variables [0].Name);
  72. Assert.IsFalse (variables [0].IsDebuggerHidden);
  73. }, readOnly: !Platform.HasNativePdbSupport, symbolReaderProvider: typeof(PdbReaderProvider), symbolWriterProvider: typeof(PdbWriterProvider));
  74. }
  75. [Test]
  76. public void Document ()
  77. {
  78. TestModule ("test.exe", module => {
  79. var type = module.GetType ("Program");
  80. var method = type.GetMethod ("Main");
  81. var sequence_point = method.DebugInformation.SequencePoints.First (sp => sp != null);
  82. var document = sequence_point.Document;
  83. Assert.IsNotNull (document);
  84. Assert.AreEqual (@"c:\sources\cecil\symbols\Mono.Cecil.Pdb\Test\Resources\assemblies\test.cs", document.Url);
  85. Assert.AreEqual (DocumentType.Text, document.Type);
  86. Assert.AreEqual (DocumentHashAlgorithm.MD5, document.HashAlgorithm);
  87. Assert.AreEqual (new byte [] { 228, 176, 152, 54, 82, 238, 238, 68, 237, 156, 5, 142, 118, 160, 118, 245 }, document.Hash);
  88. Assert.AreEqual (DocumentLanguage.CSharp, document.Language);
  89. Assert.AreEqual (DocumentLanguageVendor.Microsoft, document.LanguageVendor);
  90. }, readOnly: !Platform.HasNativePdbSupport, symbolReaderProvider: typeof(PdbReaderProvider), symbolWriterProvider: typeof(PdbWriterProvider));
  91. }
  92. [Test]
  93. public void BasicDocument ()
  94. {
  95. TestModule ("VBConsApp.exe", module => {
  96. var type = module.GetType ("VBConsApp.Program");
  97. var method = type.GetMethod ("Main");
  98. var sequence_point = method.DebugInformation.SequencePoints.First (sp => sp != null);
  99. var document = sequence_point.Document;
  100. Assert.IsNotNull (document);
  101. Assert.AreEqual (@"c:\tmp\VBConsApp\Program.vb", document.Url);
  102. Assert.AreEqual (DocumentType.Text, document.Type);
  103. Assert.AreEqual (DocumentHashAlgorithm.MD5, document.HashAlgorithm);
  104. Assert.AreEqual (new byte [] { 184, 188, 100, 23, 27, 123, 187, 201, 175, 206, 110, 198, 242, 139, 154, 119 }, document.Hash);
  105. Assert.AreEqual (DocumentLanguage.Basic, document.Language);
  106. Assert.AreEqual (DocumentLanguageVendor.Microsoft, document.LanguageVendor);
  107. }, readOnly: !Platform.HasNativePdbSupport, symbolReaderProvider: typeof(PdbReaderProvider), symbolWriterProvider: typeof(PdbWriterProvider));
  108. }
  109. [Test]
  110. public void FSharpDocument ()
  111. {
  112. TestModule ("fsapp.exe", module => {
  113. var type = module.GetType ("Program");
  114. var method = type.GetMethod ("fact");
  115. var sequence_point = method.DebugInformation.SequencePoints.First (sp => sp != null);
  116. var document = sequence_point.Document;
  117. Assert.IsNotNull (document);
  118. Assert.AreEqual (@"c:\tmp\fsapp\Program.fs", document.Url);
  119. Assert.AreEqual (DocumentType.Text, document.Type);
  120. Assert.AreEqual (DocumentHashAlgorithm.None, document.HashAlgorithm);
  121. Assert.AreEqual (DocumentLanguage.FSharp, document.Language);
  122. Assert.AreEqual (DocumentLanguageVendor.Microsoft, document.LanguageVendor);
  123. }, readOnly: !Platform.HasNativePdbSupport, symbolReaderProvider: typeof (PdbReaderProvider), symbolWriterProvider: typeof (PdbWriterProvider));
  124. }
  125. [Test]
  126. public void EmptyEnumerable ()
  127. {
  128. TestModule ("empty-iterator.dll", module => {
  129. }, readOnly: !Platform.HasNativePdbSupport, symbolReaderProvider: typeof (PdbReaderProvider), symbolWriterProvider: typeof (PdbWriterProvider));
  130. }
  131. [Test]
  132. public void EmptyRootNamespace ()
  133. {
  134. TestModule ("EmptyRootNamespace.dll", module => {
  135. }, readOnly: !Platform.HasNativePdbSupport, symbolReaderProvider: typeof (PdbReaderProvider), symbolWriterProvider: typeof (PdbWriterProvider));
  136. }
  137. [Test]
  138. public void VisualBasicNamespace ()
  139. {
  140. TestModule ("AVbTest.exe", module => {
  141. }, readOnly: !Platform.HasNativePdbSupport, symbolReaderProvider: typeof (PdbReaderProvider), symbolWriterProvider: typeof (PdbWriterProvider));
  142. }
  143. [Test]
  144. public void LocalVariables ()
  145. {
  146. TestModule ("ComplexPdb.dll", module => {
  147. var type = module.GetType ("ComplexPdb.Program");
  148. var method = type.GetMethod ("Bar");
  149. var debug_info = method.DebugInformation;
  150. Assert.IsNotNull (debug_info.Scope);
  151. Assert.IsTrue (debug_info.Scope.HasScopes);
  152. Assert.AreEqual (2, debug_info.Scope.Scopes.Count);
  153. var scope = debug_info.Scope.Scopes [0];
  154. Assert.IsNotNull (scope);
  155. Assert.IsTrue (scope.HasVariables);
  156. Assert.AreEqual (1, scope.Variables.Count);
  157. var variable = scope.Variables [0];
  158. Assert.AreEqual ("s", variable.Name);
  159. Assert.IsFalse (variable.IsDebuggerHidden);
  160. Assert.AreEqual (2, variable.Index);
  161. scope = debug_info.Scope.Scopes [1];
  162. Assert.IsNotNull (scope);
  163. Assert.IsTrue (scope.HasVariables);
  164. Assert.AreEqual (1, scope.Variables.Count);
  165. variable = scope.Variables [0];
  166. Assert.AreEqual ("s", variable.Name);
  167. Assert.IsFalse (variable.IsDebuggerHidden);
  168. Assert.AreEqual (3, variable.Index);
  169. Assert.IsTrue (scope.HasScopes);
  170. Assert.AreEqual (1, scope.Scopes.Count);
  171. scope = scope.Scopes [0];
  172. Assert.IsNotNull (scope);
  173. Assert.IsTrue (scope.HasVariables);
  174. Assert.AreEqual (1, scope.Variables.Count);
  175. variable = scope.Variables [0];
  176. Assert.AreEqual ("u", variable.Name);
  177. Assert.IsFalse (variable.IsDebuggerHidden);
  178. Assert.AreEqual (5, variable.Index);
  179. }, readOnly: !Platform.HasNativePdbSupport, symbolReaderProvider: typeof (PdbReaderProvider), symbolWriterProvider: typeof (PdbWriterProvider));
  180. }
  181. [Test]
  182. public void LocalConstants ()
  183. {
  184. TestModule ("ComplexPdb.dll", module => {
  185. var type = module.GetType ("ComplexPdb.Program");
  186. var method = type.GetMethod ("Bar");
  187. var debug_info = method.DebugInformation;
  188. Assert.IsNotNull (debug_info.Scope);
  189. Assert.IsTrue (debug_info.Scope.HasScopes);
  190. Assert.AreEqual (2, debug_info.Scope.Scopes.Count);
  191. var scope = debug_info.Scope.Scopes [1];
  192. Assert.IsNotNull (scope);
  193. Assert.IsTrue (scope.HasConstants);
  194. Assert.AreEqual (2, scope.Constants.Count);
  195. var constant = scope.Constants [0];
  196. Assert.AreEqual ("b", constant.Name);
  197. Assert.AreEqual (12, constant.Value);
  198. Assert.AreEqual (MetadataType.Int32, constant.ConstantType.MetadataType);
  199. constant = scope.Constants [1];
  200. Assert.AreEqual ("c", constant.Name);
  201. Assert.AreEqual ((decimal) 74, constant.Value);
  202. Assert.AreEqual (MetadataType.ValueType, constant.ConstantType.MetadataType);
  203. method = type.GetMethod ("Foo");
  204. debug_info = method.DebugInformation;
  205. Assert.IsNotNull (debug_info.Scope);
  206. Assert.IsTrue (debug_info.Scope.HasConstants);
  207. Assert.AreEqual (4, debug_info.Scope.Constants.Count);
  208. constant = debug_info.Scope.Constants [0];
  209. Assert.AreEqual ("s", constant.Name);
  210. Assert.AreEqual ("const string", constant.Value);
  211. Assert.AreEqual (MetadataType.String, constant.ConstantType.MetadataType);
  212. constant = debug_info.Scope.Constants [1];
  213. Assert.AreEqual ("f", constant.Name);
  214. Assert.AreEqual (1, constant.Value);
  215. Assert.AreEqual (MetadataType.Int32, constant.ConstantType.MetadataType);
  216. constant = debug_info.Scope.Constants [2];
  217. Assert.AreEqual ("o", constant.Name);
  218. Assert.AreEqual (null, constant.Value);
  219. Assert.AreEqual (MetadataType.Object, constant.ConstantType.MetadataType);
  220. constant = debug_info.Scope.Constants [3];
  221. Assert.AreEqual ("u", constant.Name);
  222. Assert.AreEqual (null, constant.Value);
  223. Assert.AreEqual (MetadataType.String, constant.ConstantType.MetadataType);
  224. }, readOnly: !Platform.HasNativePdbSupport, symbolReaderProvider: typeof (PdbReaderProvider), symbolWriterProvider: typeof (PdbWriterProvider));
  225. }
  226. [Test]
  227. public void ImportScope ()
  228. {
  229. TestModule ("ComplexPdb.dll", module => {
  230. var type = module.GetType ("ComplexPdb.Program");
  231. var method = type.GetMethod ("Bar");
  232. var debug_info = method.DebugInformation;
  233. Assert.IsNotNull (debug_info.Scope);
  234. var import = debug_info.Scope.Import;
  235. Assert.IsNotNull (import);
  236. Assert.IsTrue (import.HasTargets);
  237. Assert.AreEqual (6, import.Targets.Count);
  238. var target = import.Targets [0];
  239. Assert.AreEqual (ImportTargetKind.ImportNamespace, target.Kind);
  240. Assert.AreEqual ("System", target.Namespace);
  241. target = import.Targets [1];
  242. Assert.AreEqual (ImportTargetKind.ImportNamespace, target.Kind);
  243. Assert.AreEqual ("System.Collections.Generic", target.Namespace);
  244. target = import.Targets [2];
  245. Assert.AreEqual (ImportTargetKind.ImportNamespace, target.Kind);
  246. Assert.AreEqual ("System.Threading.Tasks", target.Namespace);
  247. target = import.Targets [3];
  248. Assert.AreEqual (ImportTargetKind.ImportType, target.Kind);
  249. Assert.AreEqual ("System.Console", target.Type.FullName);
  250. target = import.Targets [4];
  251. Assert.AreEqual (ImportTargetKind.DefineTypeAlias, target.Kind);
  252. Assert.AreEqual ("Foo1", target.Alias);
  253. Assert.AreEqual ("System.Console", target.Type.FullName);
  254. target = import.Targets [5];
  255. Assert.AreEqual (ImportTargetKind.DefineNamespaceAlias, target.Kind);
  256. Assert.AreEqual ("Foo2", target.Alias);
  257. Assert.AreEqual ("System.Reflection", target.Namespace);
  258. }, readOnly: !Platform.HasNativePdbSupport, symbolReaderProvider: typeof (PdbReaderProvider), symbolWriterProvider: typeof (PdbWriterProvider));
  259. }
  260. [Test]
  261. public void StateMachineKickOff ()
  262. {
  263. TestModule ("ComplexPdb.dll", module => {
  264. var state_machine = module.GetType ("ComplexPdb.Program/<TestAsync>d__2");
  265. var move_next = state_machine.GetMethod ("MoveNext");
  266. var symbol = move_next.DebugInformation;
  267. Assert.IsNotNull (symbol);
  268. Assert.IsNotNull (symbol.StateMachineKickOffMethod);
  269. Assert.AreEqual ("System.Threading.Tasks.Task ComplexPdb.Program::TestAsync()", symbol.StateMachineKickOffMethod.FullName);
  270. }, readOnly: !Platform.HasNativePdbSupport, symbolReaderProvider: typeof (PdbReaderProvider), symbolWriterProvider: typeof (PdbWriterProvider));
  271. }
  272. [Test]
  273. public void Iterators ()
  274. {
  275. TestModule ("ComplexPdb.dll", module => {
  276. var state_machine = module.GetType ("ComplexPdb.Program/<TestAsync>d__2");
  277. var move_next = state_machine.GetMethod ("MoveNext");
  278. Assert.IsTrue (move_next.DebugInformation.HasCustomDebugInformations);
  279. Assert.AreEqual (2, move_next.DebugInformation.CustomDebugInformations.Count);
  280. var state_machine_scope = move_next.DebugInformation.CustomDebugInformations [0] as StateMachineScopeDebugInformation;
  281. Assert.IsNotNull (state_machine_scope);
  282. Assert.AreEqual (1, state_machine_scope.Scopes.Count);
  283. Assert.AreEqual (142, state_machine_scope.Scopes [0].Start.Offset);
  284. Assert.AreEqual (319, state_machine_scope.Scopes [0].End.Offset);
  285. var async_body = move_next.DebugInformation.CustomDebugInformations [1] as AsyncMethodBodyDebugInformation;
  286. Assert.IsNotNull (async_body);
  287. Assert.AreEqual (-1, async_body.CatchHandler.Offset);
  288. Assert.AreEqual (2, async_body.Yields.Count);
  289. Assert.AreEqual (68, async_body.Yields [0].Offset);
  290. Assert.AreEqual (197, async_body.Yields [1].Offset);
  291. Assert.AreEqual (2, async_body.Resumes.Count);
  292. Assert.AreEqual (98, async_body.Resumes [0].Offset);
  293. Assert.AreEqual (227, async_body.Resumes [1].Offset);
  294. Assert.AreEqual (move_next, async_body.ResumeMethods [0]);
  295. Assert.AreEqual (move_next, async_body.ResumeMethods [1]);
  296. }, readOnly: !Platform.HasNativePdbSupport, symbolReaderProvider: typeof (PdbReaderProvider), symbolWriterProvider: typeof (PdbWriterProvider));
  297. }
  298. [Test]
  299. public void ImportsForFirstMethod ()
  300. {
  301. TestModule ("CecilTest.exe", module => {
  302. var type = module.GetType ("CecilTest.Program");
  303. var method = type.GetMethod ("Main");
  304. var debug = method.DebugInformation;
  305. var scope = debug.Scope;
  306. Assert.IsTrue (scope.End.IsEndOfMethod);
  307. var import = scope.Import;
  308. Assert.IsNotNull (import);
  309. Assert.AreEqual (5, import.Targets.Count);
  310. var ns = new [] {
  311. "System",
  312. "System.Collections.Generic",
  313. "System.Linq",
  314. "System.Text",
  315. "System.Threading.Tasks",
  316. };
  317. for (int i = 0; i < import.Targets.Count; i++) {
  318. var target = import.Targets [i];
  319. Assert.AreEqual (ImportTargetKind.ImportNamespace, target.Kind);
  320. Assert.AreEqual (ns [i], target.Namespace);
  321. }
  322. Assert.AreEqual ("System", import.Targets [0].Namespace);
  323. }, readOnly: !Platform.HasNativePdbSupport, symbolReaderProvider: typeof (PdbReaderProvider), symbolWriterProvider: typeof (PdbWriterProvider));
  324. }
  325. [Test]
  326. public void CreateMethodFromScratch ()
  327. {
  328. if (!Platform.HasNativePdbSupport)
  329. Assert.Ignore ();
  330. var module = ModuleDefinition.CreateModule ("Pan", ModuleKind.Dll);
  331. var type = new TypeDefinition ("Pin", "Pon", TypeAttributes.Public | TypeAttributes.Abstract | TypeAttributes.Sealed, module.ImportReference (typeof (object)));
  332. module.Types.Add (type);
  333. var method = new MethodDefinition ("Pang", MethodAttributes.Public | MethodAttributes.Static, module.ImportReference (typeof (string)));
  334. type.Methods.Add (method);
  335. var body = method.Body;
  336. body.InitLocals = true;
  337. var il = body.GetILProcessor ();
  338. var temp = new VariableDefinition (module.ImportReference (typeof (string)));
  339. body.Variables.Add (temp);
  340. il.Emit (OpCodes.Nop);
  341. il.Emit (OpCodes.Ldstr, "hello");
  342. il.Emit (OpCodes.Stloc, temp);
  343. il.Emit (OpCodes.Ldloc, temp);
  344. il.Emit (OpCodes.Ret);
  345. var sequence_point = new SequencePoint (body.Instructions [0], new Document (@"C:\test.cs")) {
  346. StartLine = 0,
  347. StartColumn = 0,
  348. EndLine = 0,
  349. EndColumn = 4,
  350. };
  351. method.DebugInformation.SequencePoints.Add (sequence_point);
  352. method.DebugInformation.Scope = new ScopeDebugInformation (body.Instructions [0], null) {
  353. Variables = { new VariableDebugInformation (temp, "temp") }
  354. };
  355. var file = Path.Combine (Path.GetTempPath (), "Pan.dll");
  356. module.Write (file, new WriterParameters {
  357. SymbolWriterProvider = new PdbWriterProvider (),
  358. });
  359. module = ModuleDefinition.ReadModule (file, new ReaderParameters {
  360. SymbolReaderProvider = new PdbReaderProvider (),
  361. });
  362. method = module.GetType ("Pin.Pon").GetMethod ("Pang");
  363. Assert.AreEqual ("temp", method.DebugInformation.Scope.Variables [0].Name);
  364. }
  365. }
  366. }