Skip to content

SystemIOFile Adapter #550

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
a6e0687
Merge pull request #1 from tonerdo/master
daveMueller Aug 17, 2019
84c0aff
Merge pull request #2 from tonerdo/master
daveMueller Sep 5, 2019
5b4e316
Merge pull request #3 from tonerdo/master
daveMueller Sep 11, 2019
45075e1
Merge pull request #4 from tonerdo/master
daveMueller Sep 14, 2019
23aeb1c
extended SystemIoFileAdapter and interface
daveMueller Sep 15, 2019
7ca75f2
removed IFileHelper and used IFileSystem instead + refactorings
daveMueller Sep 15, 2019
71af4de
File adapter on Program.cs
daveMueller Sep 15, 2019
8ec57c1
File adapter on Coverage.cs + refactorings
daveMueller Sep 15, 2019
8a4a1f8
File adapter for CoverageResultTask + refactorings
daveMueller Sep 15, 2019
3875965
File adapter on InstumenterHelper
daveMueller Sep 15, 2019
c889d15
File adapter on RemoteExecutor
daveMueller Sep 15, 2019
202f965
changes to CoverletCoverageDataCollectorTests
daveMueller Sep 16, 2019
c58508b
changes to collector
daveMueller Sep 16, 2019
5c11795
changed Test
daveMueller Sep 16, 2019
ef7d0b0
Merge pull request #5 from tonerdo/master
daveMueller Sep 17, 2019
669f042
Merge branch 'master' into 543_SystemIoFileAdapter
daveMueller Sep 17, 2019
2af6fe2
reverted changes to coverlet.collector
daveMueller Sep 17, 2019
b1bf6c9
code review
daveMueller Sep 17, 2019
00de202
adapted failing test
daveMueller Sep 17, 2019
4dca604
updates
MarcoRossignoli Sep 18, 2019
33c7e40
remove not used copy method
Sep 18, 2019
95ca53d
code review changes
Sep 18, 2019
f8ec589
code review
daveMueller Sep 18, 2019
d87ea07
code review; changed parameter order
daveMueller Sep 20, 2019
690d6dc
some nits
MarcoRossignoli Sep 21, 2019
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
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 @@ -94,7 +97,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 @@ -215,9 +218,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 @@ -228,7 +231,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 @@ -249,7 +252,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 = metadataReaderProvider.GetMetadataReader();
foreach (DocumentHandle docHandle in metadataReader.Documents)
Expand Down Expand Up @@ -172,16 +171,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 @@ -200,18 +199,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 @@ -228,8 +227,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 @@ -240,7 +239,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