diff --git a/src/coverlet.core/Helpers/InstrumentationHelper.cs b/src/coverlet.core/Helpers/InstrumentationHelper.cs index fcc54d5ff..8e9bdc38f 100644 --- a/src/coverlet.core/Helpers/InstrumentationHelper.cs +++ b/src/coverlet.core/Helpers/InstrumentationHelper.cs @@ -48,11 +48,7 @@ public static string[] GetCoverableModules(string module, string[] directories) } // The module's name must be unique. - // Add the test module itself to exclude it from the files enumeration. - var uniqueModules = new HashSet - { - Path.GetFileName(module) - }; + var uniqueModules = new HashSet(); return dirs.SelectMany(d => Directory.EnumerateFiles(d)) .Where(m => IsAssembly(m) && uniqueModules.Add(Path.GetFileName(m))) @@ -86,12 +82,20 @@ public static bool HasPdb(string module) public static void BackupOriginalModule(string module, string identifier) { var backupPath = GetBackupPath(module, identifier); + var backupSymbolPath = Path.ChangeExtension(backupPath, ".pdb"); File.Copy(module, backupPath, true); + + var symbolFile = Path.ChangeExtension(module, ".pdb"); + if (File.Exists(symbolFile)) + { + File.Copy(symbolFile, backupSymbolPath, true); + } } public static void RestoreOriginalModule(string module, string identifier) { var backupPath = GetBackupPath(module, identifier); + var backupSymbolPath = Path.ChangeExtension(backupPath, ".pdb"); // Restore the original module - retry up to 10 times, since the destination file could be locked // See: https://github.com/tonerdo/coverlet/issues/25 @@ -102,6 +106,12 @@ public static void RestoreOriginalModule(string module, string identifier) File.Copy(backupPath, module, true); File.Delete(backupPath); }, retryStrategy, 10); + + RetryHelper.Retry(() => + { + File.Copy(backupSymbolPath, Path.ChangeExtension(module, ".pdb"), true); + File.Delete(backupSymbolPath); + }, retryStrategy, 10); } public static void DeleteHitsFile(string path) diff --git a/src/coverlet.core/Instrumentation/Instrumenter.cs b/src/coverlet.core/Instrumentation/Instrumenter.cs index 9c05bc313..86261adfc 100644 --- a/src/coverlet.core/Instrumentation/Instrumenter.cs +++ b/src/coverlet.core/Instrumentation/Instrumenter.cs @@ -149,7 +149,7 @@ private void InstrumentModule() onProcessExitIl.InsertBefore(lastInstr, Instruction.Create(OpCodes.Call, customTrackerUnloadModule)); } - module.Write(stream); + module.Write(stream, new WriterParameters { WriteSymbols = true }); } } } diff --git a/test/coverlet.core.tests/CoverageTests.cs b/test/coverlet.core.tests/CoverageTests.cs index eed0eb55a..314bff5c7 100644 --- a/test/coverlet.core.tests/CoverageTests.cs +++ b/test/coverlet.core.tests/CoverageTests.cs @@ -28,10 +28,7 @@ public void TestCoverage() // TODO: Mimic hits by calling ModuleTrackerTemplate.RecordHit before Unload - // Since Coverage only instruments dependancies, we need a fake module here - var testModule = Path.Combine(directory.FullName, "test.module.dll"); - - var coverage = new Coverage(testModule, Array.Empty(), Array.Empty(), Array.Empty(), Array.Empty(), Array.Empty(), string.Empty, false); + var coverage = new Coverage(Path.Combine(directory.FullName, Path.GetFileName(module)), Array.Empty(), Array.Empty(), Array.Empty(), Array.Empty(), Array.Empty(), string.Empty, false); coverage.PrepareModules(); // The module hit tracker must signal to Coverage that it has done its job, so call it manually diff --git a/test/coverlet.core.tests/Helpers/InstrumentationHelperTests.cs b/test/coverlet.core.tests/Helpers/InstrumentationHelperTests.cs index af6fa7387..82d2d6049 100644 --- a/test/coverlet.core.tests/Helpers/InstrumentationHelperTests.cs +++ b/test/coverlet.core.tests/Helpers/InstrumentationHelperTests.cs @@ -13,7 +13,7 @@ public void TestGetDependencies() { string module = typeof(InstrumentationHelperTests).Assembly.Location; var modules = InstrumentationHelper.GetCoverableModules(module, Array.Empty()); - Assert.False(Array.Exists(modules, m => m == module)); + Assert.True(Array.Exists(modules, m => m == module)); } [Fact] diff --git a/test/coverlet.core.tests/Samples/Samples.cs b/test/coverlet.core.tests/Samples/Samples.cs index 43b9bcbe9..2c178c903 100644 --- a/test/coverlet.core.tests/Samples/Samples.cs +++ b/test/coverlet.core.tests/Samples/Samples.cs @@ -122,6 +122,14 @@ public string HasSimpleUsingStatement() return value; } + /// + /// This method is used by a unit test that verifies the behavior of the instrumentation process on an assembly + /// which is not instrumented. Excluding this method from code coverage prevents the bytecode for this reference + /// method from getting modified prior to test execution so it retains its original form for the test. This is + /// not a problem for the test because the instrumentation process only runs on assemblies which have not + /// already been instrumented. + /// + [ExcludeFromCodeCoverage] public void HasSimpleTaskWithLambda() { var t = new Task(() => { });