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

Conversation

daveMueller
Copy link
Collaborator

closes #543

@daveMueller daveMueller changed the title 543 system io file adapter SystemIOFile Adapter Sep 16, 2019
@daveMueller
Copy link
Collaborator Author

Can anyone help out here? Can't really figure out why one test is failing on the build server. I can execute them all locally without failing.

image

@MarcoRossignoli
Copy link
Collaborator

I think you need to align to master yesterday I changed one behaviour of logs and amended tests #548

@MarcoRossignoli MarcoRossignoli added the enhancement General enhancement request label Sep 17, 2019
@MarcoRossignoli
Copy link
Collaborator

MarcoRossignoli commented Sep 17, 2019

@daveMueller for the moment I would avoid to update collectors code, because could live alone(I mean the infrastructure to load coverage core), so could you revert all changes under coverlet.collector project?
I think is premature here for now(consolidate under one interface different context).
Sorry I didn't specify that on issue 😞
The idea is to make core more testable...collectors are born recently and follow that pattern yet.

{
_logger.LogError("Result of instrumentation task not found");
return false;
}

var coverage = new Coverage(CoveragePrepareResult.Deserialize(new FileStream(InstrumenterState.ItemSpec, FileMode.Open)), this._logger, (IInstrumentationHelper)DependencyInjection.Current.GetService(typeof(IInstrumentationHelper)));
var coverage = new Coverage(CoveragePrepareResult.Deserialize(new FileStream(InstrumenterState.ItemSpec, FileMode.Open)), this._logger, (IInstrumentationHelper)DependencyInjection.Current.GetService(typeof(IInstrumentationHelper)), fileSystem);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not also for new FileStream(InstrumenterState.ItemSpec, FileMode.Open)?
And we should surround by a using to close handle asap(my past error).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -30,7 +30,7 @@ public void TestCoverage()

// TODO: Find a way to mimick hits

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>(), false, false, string.Empty, false, _mockLogger.Object, _instrumentationHelper);
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>(), false, false, string.Empty, false, _mockLogger.Object, new Mock<IFileSystem>().Object, _instrumentationHelper);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move mock instantiation of mock under private readonly Mock<ILogger> _mockLogger = new Mock<ILogger>(); and reuse

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


Stream OpenRead(string path);

void Copy(string sourceFileName, string destFileName);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why?Where is used?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry this was used in the coverlet.collector and I missed to revert it.

{
_logger.LogError("Result of instrumentation task not found");
return false;
}

var coverage = new Coverage(CoveragePrepareResult.Deserialize(new FileStream(InstrumenterState.ItemSpec, FileMode.Open)), this._logger, (IInstrumentationHelper)DependencyInjection.Current.GetService(typeof(IInstrumentationHelper)));
var coverage = new Coverage(CoveragePrepareResult.Deserialize(new FileStream(InstrumenterState.ItemSpec, FileMode.Open)), this._logger, fileSystem, (IInstrumentationHelper)DependencyInjection.Current.GetService(typeof(IInstrumentationHelper)));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also for new FileStream(InstrumenterState.ItemSpec, FileMode.Open) and surround by using please(my past error)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok I changed it but I don't know how to surround this by a using.

Copy link
Collaborator

@MarcoRossignoli MarcoRossignoli Sep 18, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

something like

Coverage coverage = null;
using(Stream instrumenterStateStream = fileSystem.NewFileStream(InstrumenterState.ItemSpec, FileMode.Open))
{
     coverage = new Coverage(CoveragePrepareResult.Deserialize(instrumenterStateStream), this._logger, fileSystem,...
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

_logger,
(IFileSystem) DependencyInjection.Current.GetService(typeof(IFileSystem)),
(IInstrumentationHelper) DependencyInjection.Current.GetService(typeof(IInstrumentationHelper)));

CoveragePrepareResult prepareResult = coverage.PrepareModules();
InstrumenterState = new TaskItem(System.IO.Path.GetTempFileName());
using (var instrumentedStateFile = new FileStream(InstrumenterState.ItemSpec, FileMode.Open, FileAccess.Write))
Copy link
Collaborator

@MarcoRossignoli MarcoRossignoli Sep 18, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also for new FileStream(InstrumenterState.ItemSpec, FileMode.Open, FileAccess.Write) and surround by using please(my past error)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

string coverletLib = Directory.GetFiles(Directory.GetCurrentDirectory(), "coverlet.core.dll").First();
var instrumentationHelperMock = new Mock<IInstrumentationHelper>();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why you've changed this test?
Here I want to test InstrumentationHelper logic and I have to mock only file system to simulate "file not found".
Revert please.

Copy link
Collaborator Author

@daveMueller daveMueller Sep 18, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't exactly know what you mean or how I can make this test run again by only mocking the FileSystem. When I revert the test to how it was before the test fails. This is because I now also use the FileSystem adapter for the streams. Thus I also must setup e.g. _fileSystem.OpenRead()....

And wouldn't it be better to test the InstrumentationHelper logic in the class InstrumentationHelperTests.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And wouldn't it be better to test the InstrumentationHelper logic in the class InstrumentationHelperTests.

Here we have a bit of integration...I mean we need to test the interaction between InstrumentationHelper and Instrumenter.
You should do partial mock of concrete implementation and redefine only Exists something like
https://stackoverflow.com/questions/4769928/using-moq-to-mock-only-some-methods

var mock = new Mock<YourTestClass>();
 mock.CallBase = true;
 mock.Setup(x => x.GetCurrentUser()).Returns(lUnauthorizedUser);
 mockedTest.Object.MyMethod();

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this test we need to simulate to find pdb file but return false when we try to understand if sources are present on local hard drive, so we did it with coverlet.core.dll to avoid new dependency and we need to return false also if we have sources in local.

Copy link
Collaborator Author

@daveMueller daveMueller Sep 18, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok done. Thanks for the information with the partial mock. 👍

@MarcoRossignoli
Copy link
Collaborator

MarcoRossignoli commented Sep 18, 2019

@MarcoRossignoli I have a hard time fixing those two test. I pass a real instance of FileSystem() to Coverage ctor. When the test then executes coverage.GetCoverageResult() the field _fileSystem is null.

@daveMueller because you added two new constructor to Coverage class that are unuseful.
Coverage class has got 2 contructor used in two phases:

  1. Instrumentation
  2. Calculate coverage using hit files at the end of tests.

These two constructor accept different set of parameters but both use file system, so we need only to pass new service.

Copy link
Collaborator Author

@daveMueller daveMueller left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two constructor accept different set of parameters but both use file system, so we need only to pass new service.

Yes sorry. I felt really ashamed when I saw your commit this morning. I was probably way to tired yesterday night. Sorry.

@MarcoRossignoli
Copy link
Collaborator

MarcoRossignoli commented Sep 18, 2019

Yes sorry. I felt really ashamed when I saw your commit this morning. I was probably way to tired yesterday night. Sorry.

You don't have to apologize, you're great contributor!We're all human and happen also to me when I work in the night...actually also in the morning 😄

YOUR HELP HERE IS VERY WELCOME!

@@ -136,7 +136,9 @@ public InstrumenterResult Instrument()

private void InstrumentModule()
{
using (var stream = new FileStream(_module, FileMode.Open, FileAccess.ReadWrite))
var fileSystem = (IFileSystem)DependencyInjection.Current.GetService(typeof(IFileSystem));
Copy link
Collaborator

@MarcoRossignoli MarcoRossignoli Sep 18, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shoud avoid DependencyInjection reference in code...we need to inject throught contructor and update al callers.
The idea is to have testabililty and the possibility to "change every implementation" also for DependencyInjection(the container).
So the principle here is to have a "container" where we register dependences, and in our case is DependencyInjection class.
And we inject every dependence in constructors...the only place where we directly use DependencyInjection class is when we don't have an "instance", but we removed all statics for this reason(testability).
DependencyInjection is only the place where we chose the implementation and keep them aligned in every driver(collector, msbuild, console).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -72,6 +73,8 @@ public static void RecordSingleHit(int hitLocationIndex)

public static void UnloadModule(object sender, EventArgs e)
{
var fileSystem = (IFileSystem)DependencyInjection.Current.GetService(typeof(IFileSystem));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revert update in this file please.
This is a key piece of instrumentation, this class is injected inside users dll so we have to try to pollute less possible and use "runtime" only class.
In this case is not a problem..I mean core lib and instrumented lib are in same directory so we don't have issue with load...but I don't know how this evolve in future so I prefer keep this class(tracker) "light".

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI I'm trying to get logs also for it #553
And the idea si to enable instrumentation throught enviroment variables, this is the only static part needed today.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok done, reverted the changes.

{
_logger.LogError("Result of instrumentation task not found");
return false;
}

var coverage = new Coverage(CoveragePrepareResult.Deserialize(new FileStream(InstrumenterState.ItemSpec, FileMode.Open)), this._logger, (IInstrumentationHelper)DependencyInjection.Current.GetService(typeof(IInstrumentationHelper)));
var coverage = new Coverage(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

format inline please here the contructor parameter is not so bad, I mean keep old formatting here

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

_instrumentationHelper = instrumentationHelper;

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

public Coverage(CoveragePrepareResult prepareResult, ILogger logger, IInstrumentationHelper instrumentationHelper)
public Coverage(CoveragePrepareResult prepareResult, ILogger logger, IFileSystem fileSystem, IInstrumentationHelper instrumentationHelper)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please keep IFileSystem as last parameter we'll add new service at the end of the signature as a rule of thumb

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Coverage coverage = null;
using (Stream instrumenterStateStream = fileSystem.NewFileStream(InstrumenterState.ItemSpec, FileMode.Open))
{
coverage = new Coverage(CoveragePrepareResult.Deserialize(instrumenterStateStream), this._logger, fileSystem, (IInstrumentationHelper)DependencyInjection.Current.GetService(typeof(IInstrumentationHelper)));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

file system service for last param due to above comment

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -30,7 +31,7 @@ public void TestCoverage()

// TODO: Find a way to mimick hits

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>(), false, false, string.Empty, false, _mockLogger.Object, _instrumentationHelper);
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>(), false, false, string.Empty, false, _mockLogger.Object, _mockFileSystem.Object, _instrumentationHelper);
Copy link
Collaborator

@MarcoRossignoli MarcoRossignoli Sep 20, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix constructors param order here and below

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

InstrumentationHelper instrumentationHelper = new InstrumentationHelper(new ProcessExitHandler(), new RetryHelper(), mockFileSystem.Object);
Mock<FileSystem> partialMockFileSystem = new Mock<FileSystem>();
partialMockFileSystem.CallBase = true;
partialMockFileSystem.Setup(fs => fs.Exists(It.IsAny<string>())).Returns((string path) =>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well done!

Copy link
Collaborator

@MarcoRossignoli MarcoRossignoli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM Thank's Dave!

@MarcoRossignoli MarcoRossignoli merged commit 182766e into coverlet-coverage:master Sep 21, 2019
@daveMueller daveMueller deleted the 543_SystemIoFileAdapter branch September 24, 2019 20:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement General enhancement request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Complete IFileSystem injection
2 participants