Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions src/coverlet.core/Helpers/InstrumentationHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<string>
{
Path.GetFileName(module)
};
var uniqueModules = new HashSet<string>();

return dirs.SelectMany(d => Directory.EnumerateFiles(d))
.Where(m => IsAssembly(m) && uniqueModules.Add(Path.GetFileName(m)))
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion src/coverlet.core/Instrumentation/Instrumenter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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 });
}
}
}
Expand Down
5 changes: 1 addition & 4 deletions test/coverlet.core.tests/CoverageTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<string>(), Array.Empty<string>(), Array.Empty<string>(), Array.Empty<string>(), Array.Empty<string>(), string.Empty, false);
var coverage = new Coverage(Path.Combine(directory.FullName, Path.GetFileName(module)), Array.Empty<string>(), Array.Empty<string>(), Array.Empty<string>(), Array.Empty<string>(), Array.Empty<string>(), string.Empty, false);
coverage.PrepareModules();

// The module hit tracker must signal to Coverage that it has done its job, so call it manually
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public void TestGetDependencies()
{
string module = typeof(InstrumentationHelperTests).Assembly.Location;
var modules = InstrumentationHelper.GetCoverableModules(module, Array.Empty<string>());
Assert.False(Array.Exists(modules, m => m == module));
Assert.True(Array.Exists(modules, m => m == module));
}

[Fact]
Expand Down
8 changes: 8 additions & 0 deletions test/coverlet.core.tests/Samples/Samples.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,14 @@ public string HasSimpleUsingStatement()
return value;
}

/// <summary>
/// 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.
/// </summary>
[ExcludeFromCodeCoverage]
public void HasSimpleTaskWithLambda()
{
var t = new Task(() => { });
Expand Down