Skip to content

Commit

Permalink
Complete IFileSystem injection (#550)
Browse files Browse the repository at this point in the history
Complete IFileSystem injection
  • Loading branch information
daveMueller authored and MarcoRossignoli committed Sep 21, 2019
1 parent 82a9208 commit 182766e
Show file tree
Hide file tree
Showing 13 changed files with 140 additions and 63 deletions.
3 changes: 2 additions & 1 deletion src/coverlet.collector/DataCollection/CoverageWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ public Coverage CreateCoverage(CoverletSettings settings, ILogger coverletLogger
settings.MergeWith,
settings.UseSourceLink,
coverletLogger,
(IInstrumentationHelper)DependencyInjection.Current.GetService(typeof(IInstrumentationHelper)));
(IInstrumentationHelper)DependencyInjection.Current.GetService(typeof(IInstrumentationHelper)),
(IFileSystem)DependencyInjection.Current.GetService(typeof(IFileSystem)));
}

/// <summary>
Expand Down
7 changes: 4 additions & 3 deletions src/coverlet.console/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ static int Main(string[] args)
// Adjust log level based on user input.
logger.Level = verbosity.ParsedValue;
}

var fileSystem = (IFileSystem)DependencyInjection.Current.GetService(typeof(IFileSystem));
Coverage coverage = new Coverage(module.Value,
includeFilters.Values.ToArray(),
includeDirectories.Values.ToArray(),
Expand All @@ -71,7 +71,8 @@ static int Main(string[] args)
mergeWith.Value(),
useSourceLink.HasValue(),
logger,
(IInstrumentationHelper)DependencyInjection.Current.GetService(typeof(IInstrumentationHelper)));
(IInstrumentationHelper)DependencyInjection.Current.GetService(typeof(IInstrumentationHelper)),
fileSystem);
coverage.PrepareModules();

Process process = new Process();
Expand Down Expand Up @@ -140,7 +141,7 @@ static int Main(string[] args)

var report = Path.Combine(directory, filename);
logger.LogInformation($" Generating report '{report}'", important: true);
File.WriteAllText(report, reporter.Report(result));
fileSystem.WriteAllText(report, reporter.Report(result));
}
}

Expand Down
20 changes: 18 additions & 2 deletions src/coverlet.core/Abstracts/IFileSystem.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,23 @@
namespace Coverlet.Core.Abstracts
using System.IO;

namespace Coverlet.Core.Abstracts
{
internal interface IFileSystem
public interface IFileSystem
{
bool Exists(string path);

void WriteAllText(string path, string contents);

string ReadAllText(string path);

Stream OpenRead(string path);

void Copy(string sourceFileName, string destFileName, bool overwrite);

void Delete(string path);

Stream NewFileStream(string path, FileMode mode);

Stream NewFileStream(string path, FileMode mode, FileAccess access);
}
}
19 changes: 11 additions & 8 deletions src/coverlet.core/Coverage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using System.IO;
using System.Linq;
using Coverlet.Core.Abstracts;
using Coverlet.Core.Helpers;
using Coverlet.Core.Instrumentation;
using Coverlet.Core.Logging;

Expand All @@ -27,6 +26,7 @@ public class Coverage
private bool _useSourceLink;
private ILogger _logger;
private IInstrumentationHelper _instrumentationHelper;
private IFileSystem _fileSystem;
private List<InstrumenterResult> _results;

public string Identifier
Expand All @@ -45,7 +45,8 @@ public Coverage(string module,
string mergeWith,
bool useSourceLink,
ILogger logger,
IInstrumentationHelper instrumentationHelper)
IInstrumentationHelper instrumentationHelper,
IFileSystem fileSystem)
{
_module = module;
_includeFilters = includeFilters;
Expand All @@ -59,12 +60,13 @@ public Coverage(string module,
_useSourceLink = useSourceLink;
_logger = logger;
_instrumentationHelper = instrumentationHelper;
_fileSystem = fileSystem;

_identifier = Guid.NewGuid().ToString();
_results = new List<InstrumenterResult>();
}

public Coverage(CoveragePrepareResult prepareResult, ILogger logger, IInstrumentationHelper instrumentationHelper)
public Coverage(CoveragePrepareResult prepareResult, ILogger logger, IInstrumentationHelper instrumentationHelper, IFileSystem fileSystem)
{
_identifier = prepareResult.Identifier;
_module = prepareResult.Module;
Expand All @@ -73,6 +75,7 @@ public Coverage(CoveragePrepareResult prepareResult, ILogger logger, IInstrument
_results = new List<InstrumenterResult>(prepareResult.Results);
_logger = logger;
_instrumentationHelper = instrumentationHelper;
_fileSystem = fileSystem;
}

public CoveragePrepareResult PrepareModules()
Expand All @@ -95,7 +98,7 @@ public CoveragePrepareResult PrepareModules()
continue;
}

var instrumenter = new Instrumenter(module, _identifier, _excludeFilters, _includeFilters, _excludedSourceFiles, _excludeAttributes, _singleHit, _logger, _instrumentationHelper);
var instrumenter = new Instrumenter(module, _identifier, _excludeFilters, _includeFilters, _excludedSourceFiles, _excludeAttributes, _singleHit, _logger, _instrumentationHelper, _fileSystem);
if (instrumenter.CanInstrument())
{
_instrumentationHelper.BackupOriginalModule(module, _identifier);
Expand Down Expand Up @@ -216,9 +219,9 @@ public CoverageResult GetCoverageResult()

var coverageResult = new CoverageResult { Identifier = _identifier, Modules = modules, InstrumentedResults = _results };

if (!string.IsNullOrEmpty(_mergeWith) && !string.IsNullOrWhiteSpace(_mergeWith) && File.Exists(_mergeWith))
if (!string.IsNullOrEmpty(_mergeWith) && !string.IsNullOrWhiteSpace(_mergeWith) && _fileSystem.Exists(_mergeWith))
{
string json = File.ReadAllText(_mergeWith);
string json = _fileSystem.ReadAllText(_mergeWith);
coverageResult.Merge(JsonConvert.DeserializeObject<Modules>(json));
}

Expand All @@ -229,7 +232,7 @@ private void CalculateCoverage()
{
foreach (var result in _results)
{
if (!File.Exists(result.HitsFilePath))
if (!_fileSystem.Exists(result.HitsFilePath))
{
// Hits file could be missed mainly for two reason
// 1) Issue during module Unload()
Expand All @@ -250,7 +253,7 @@ private void CalculateCoverage()
}
}

using (var fs = new FileStream(result.HitsFilePath, FileMode.Open))
using (var fs = _fileSystem.NewFileStream(result.HitsFilePath, FileMode.Open))
using (var br = new BinaryReader(fs))
{
int hitCandidatesCount = br.ReadInt32();
Expand Down
40 changes: 38 additions & 2 deletions src/coverlet.core/Helpers/FileSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,47 @@

namespace Coverlet.Core.Helpers
{
internal class FileSystem : IFileSystem
public class FileSystem : IFileSystem
{
public bool Exists(string path)
// We need to partial mock this class on tests
public virtual bool Exists(string path)
{
return File.Exists(path);
}

public void WriteAllText(string path, string contents)
{
File.WriteAllText(path, contents);
}

public string ReadAllText(string path)
{
return File.ReadAllText(path);
}

public Stream OpenRead(string path)
{
return File.OpenRead(path);
}

public void Copy(string sourceFileName, string destFileName, bool overwrite)
{
File.Copy(sourceFileName, destFileName, overwrite);
}

public void Delete(string path)
{
File.Delete(path);
}

public Stream NewFileStream(string path, FileMode mode)
{
return new FileStream(path, mode);
}

public Stream NewFileStream(string path, FileMode mode, FileAccess access)
{
return new FileStream(path, mode, access);
}
}
}
35 changes: 17 additions & 18 deletions src/coverlet.core/Helpers/InstrumentationHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
using System.Reflection.PortableExecutable;
using System.Text.RegularExpressions;
using Coverlet.Core.Abstracts;
using Coverlet.Core.Logging;

namespace Coverlet.Core.Helpers
{
Expand Down Expand Up @@ -73,7 +72,7 @@ public string[] GetCoverableModules(string module, string[] directories, bool in
public bool HasPdb(string module, out bool embedded)
{
embedded = false;
using (var moduleStream = File.OpenRead(module))
using (var moduleStream = _fileSystem.OpenRead(module))
using (var peReader = new PEReader(moduleStream))
{
foreach (var entry in peReader.ReadDebugDirectory())
Expand All @@ -88,7 +87,7 @@ public bool HasPdb(string module, out bool embedded)
return true;
}

return File.Exists(codeViewData.Path);
return _fileSystem.Exists(codeViewData.Path);
}
}

Expand All @@ -99,7 +98,7 @@ public bool HasPdb(string module, out bool embedded)
public bool EmbeddedPortablePdbHasLocalSource(string module, out string firstNotFoundDocument)
{
firstNotFoundDocument = "";
using (FileStream moduleStream = File.OpenRead(module))
using (Stream moduleStream = _fileSystem.OpenRead(module))
using (var peReader = new PEReader(moduleStream))
{
foreach (DebugDirectoryEntry entry in peReader.ReadDebugDirectory())
Expand All @@ -117,7 +116,7 @@ public bool EmbeddedPortablePdbHasLocalSource(string module, out string firstNot
// We verify all docs and return false if not all are present in local
// We could have false negative if doc is not a source
// Btw check for all possible extension could be weak approach
if (!File.Exists(docName))
if (!_fileSystem.Exists(docName))
{
firstNotFoundDocument = docName;
return false;
Expand All @@ -136,15 +135,15 @@ public bool EmbeddedPortablePdbHasLocalSource(string module, out string firstNot
public bool PortablePdbHasLocalSource(string module, out string firstNotFoundDocument)
{
firstNotFoundDocument = "";
using (var moduleStream = File.OpenRead(module))
using (var moduleStream = _fileSystem.OpenRead(module))
using (var peReader = new PEReader(moduleStream))
{
foreach (var entry in peReader.ReadDebugDirectory())
{
if (entry.Type == DebugDirectoryEntryType.CodeView)
{
var codeViewData = peReader.ReadCodeViewDebugDirectoryData(entry);
using FileStream pdbStream = new FileStream(codeViewData.Path, FileMode.Open);
using Stream pdbStream = _fileSystem.NewFileStream(codeViewData.Path, FileMode.Open);
using MetadataReaderProvider metadataReaderProvider = MetadataReaderProvider.FromPortablePdbStream(pdbStream);
MetadataReader metadataReader = null;
try
Expand Down Expand Up @@ -182,16 +181,16 @@ public void BackupOriginalModule(string module, string identifier)
{
var backupPath = GetBackupPath(module, identifier);
var backupSymbolPath = Path.ChangeExtension(backupPath, ".pdb");
File.Copy(module, backupPath, true);
_fileSystem.Copy(module, backupPath, true);
if (!_backupList.TryAdd(module, backupPath))
{
throw new ArgumentException($"Key already added '{module}'");
}

var symbolFile = Path.ChangeExtension(module, ".pdb");
if (File.Exists(symbolFile))
if (_fileSystem.Exists(symbolFile))
{
File.Copy(symbolFile, backupSymbolPath, true);
_fileSystem.Copy(symbolFile, backupSymbolPath, true);
if (!_backupList.TryAdd(symbolFile, backupSymbolPath))
{
throw new ArgumentException($"Key already added '{module}'");
Expand All @@ -210,18 +209,18 @@ public void RestoreOriginalModule(string module, string identifier)

_retryHelper.Retry(() =>
{
File.Copy(backupPath, module, true);
File.Delete(backupPath);
_fileSystem.Copy(backupPath, module, true);
_fileSystem.Delete(backupPath);
_backupList.TryRemove(module, out string _);
}, retryStrategy, 10);

_retryHelper.Retry(() =>
{
if (File.Exists(backupSymbolPath))
if (_fileSystem.Exists(backupSymbolPath))
{
string symbolFile = Path.ChangeExtension(module, ".pdb");
File.Copy(backupSymbolPath, symbolFile, true);
File.Delete(backupSymbolPath);
_fileSystem.Copy(backupSymbolPath, symbolFile, true);
_fileSystem.Delete(backupSymbolPath);
_backupList.TryRemove(symbolFile, out string _);
}
}, retryStrategy, 10);
Expand All @@ -238,8 +237,8 @@ public void RestoreOriginalModules()
string backupPath = _backupList[key];
_retryHelper.Retry(() =>
{
File.Copy(backupPath, key, true);
File.Delete(backupPath);
_fileSystem.Copy(backupPath, key, true);
_fileSystem.Delete(backupPath);
_backupList.TryRemove(key, out string _);
}, retryStrategy, 10);
}
Expand All @@ -250,7 +249,7 @@ public void DeleteHitsFile(string path)
// Retry hitting the hits file - retry up to 10 times, since the file could be locked
// See: https://github.com/tonerdo/coverlet/issues/25
var retryStrategy = CreateRetryStrategy();
_retryHelper.Retry(() => File.Delete(path), retryStrategy, 10);
_retryHelper.Retry(() => _fileSystem.Delete(path), retryStrategy, 10);
}

public bool IsValidFilterExpression(string filter)
Expand Down
8 changes: 5 additions & 3 deletions src/coverlet.core/Instrumentation/Instrumenter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
using System.Linq;
using Coverlet.Core.Abstracts;
using Coverlet.Core.Attributes;
using Coverlet.Core.Helpers;
using Coverlet.Core.Logging;
using Coverlet.Core.Symbols;
using Microsoft.Extensions.FileSystemGlobbing;
Expand All @@ -28,6 +27,7 @@ internal class Instrumenter
private readonly bool _isCoreLibrary;
private readonly ILogger _logger;
private readonly IInstrumentationHelper _instrumentationHelper;
private readonly IFileSystem _fileSystem;
private InstrumenterResult _result;
private FieldDefinition _customTrackerHitsArray;
private FieldDefinition _customTrackerHitsFilePath;
Expand All @@ -48,7 +48,8 @@ public Instrumenter(
string[] excludedAttributes,
bool singleHit,
ILogger logger,
IInstrumentationHelper instrumentationHelper)
IInstrumentationHelper instrumentationHelper,
IFileSystem fileSystem)
{
_module = module;
_identifier = identifier;
Expand All @@ -60,6 +61,7 @@ public Instrumenter(
_isCoreLibrary = Path.GetFileNameWithoutExtension(_module) == "System.Private.CoreLib";
_logger = logger;
_instrumentationHelper = instrumentationHelper;
_fileSystem = fileSystem;
}

public bool CanInstrument()
Expand Down Expand Up @@ -136,7 +138,7 @@ public InstrumenterResult Instrument()

private void InstrumentModule()
{
using (var stream = new FileStream(_module, FileMode.Open, FileAccess.ReadWrite))
using (var stream = _fileSystem.NewFileStream(_module, FileMode.Open, FileAccess.ReadWrite))
using (var resolver = new NetstandardAwareAssemblyResolver())
{
resolver.AddSearchDirectory(Path.GetDirectoryName(_module));
Expand Down
Loading

0 comments on commit 182766e

Please sign in to comment.