Skip to content

Commit

Permalink
Change to not save the same HitContext hit twice
Browse files Browse the repository at this point in the history
  • Loading branch information
lucaslorentz committed Oct 30, 2020
1 parent 8344c5d commit a74269a
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 48 deletions.
66 changes: 33 additions & 33 deletions src/MiniCover.HitServices/HitContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ public static HitContext Current
set => _currentAsyncLocal.Value = value;
}

private readonly object _lock = new object();

private int _refCount;
private int _methodCount;

public HitContext(
string assemblyName,
Expand All @@ -29,35 +27,25 @@ public HitContext(
AssemblyName = assemblyName;
ClassName = className;
MethodName = methodName;
Hits = hits ?? new Dictionary<int, int>();
Hits = hits != null
? new Dictionary<int, int>(hits)
: new Dictionary<int, int>();
}

public string AssemblyName { get; }
public string ClassName { get; }
public string MethodName { get; }
public IDictionary<int, int> Hits { get; }

public int IncrementRef()
{
return Interlocked.Increment(ref _refCount);
}
public int DecrementRef()
{
return Interlocked.Decrement(ref _refCount);
}

public void RecordHit(int id)
{
lock (_lock)
if (Hits.TryGetValue(id, out var count))
{
if (Hits.TryGetValue(id, out var count))
{
Hits[id] = count + 1;
}
else
{
Hits[id] = 1;
}
Hits[id] = count + 1;
}
else
{
Hits[id] = 1;
}
}

Expand All @@ -83,21 +71,33 @@ public static IEnumerable<HitContext> MergeDuplicates(IEnumerable<HitContext> so
)).ToArray();
}

public int EnterMethod()
{
return Interlocked.Increment(ref _methodCount);
}

public int ExitMethod()
{
return Interlocked.Decrement(ref _methodCount);
}

public void Reset()
{
Hits.Clear();
}

public void Serialize(Stream stream)
{
lock (_lock)
using (var binaryWriter = new BinaryWriter(stream, Encoding.UTF8, true))
{
using (var binaryWriter = new BinaryWriter(stream, Encoding.UTF8, true))
binaryWriter.Write(ClassName);
binaryWriter.Write(MethodName);
binaryWriter.Write(AssemblyName);
binaryWriter.Write(Hits.Count);
foreach (var hitedInstruction in Hits)
{
binaryWriter.Write(ClassName);
binaryWriter.Write(MethodName);
binaryWriter.Write(AssemblyName);
binaryWriter.Write(Hits.Count);
foreach (var hitedInstruction in Hits)
{
binaryWriter.Write(hitedInstruction.Key);
binaryWriter.Write(hitedInstruction.Value);
}
binaryWriter.Write(hitedInstruction.Key);
binaryWriter.Write(hitedInstruction.Value);
}
}
}
Expand Down
46 changes: 32 additions & 14 deletions src/MiniCover.HitServices/MethodScope.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public class MethodScope : IDisposable
{
private readonly HitContext _hitContext;
private readonly string _hitsPath;
private readonly bool _createdHitContext;
private readonly bool _isEntryMethod;

public MethodScope(
string hitsPath,
Expand All @@ -20,38 +20,56 @@ public MethodScope(
if (_hitContext == null)
{
_hitContext = new HitContext(assemblyName, className, methodName);
_createdHitContext = true;
_isEntryMethod = true;
HitContext.Current = _hitContext;
}

_hitsPath = hitsPath;
_hitContext.IncrementRef();

lock (_hitContext)
{
_hitContext.EnterMethod();
}
}

public void Hit(int id)
{
_hitContext.RecordHit(id);
lock (_hitContext)
{
_hitContext.RecordHit(id);
}
}

public void Dispose()
{
if (_hitContext.DecrementRef() == 0)
SaveHitContext();

if (_createdHitContext)
if (_isEntryMethod)
HitContext.Current = null;

lock (_hitContext)
{
if (_hitContext.ExitMethod() == 0)
SaveHitContext();
}
}

private void SaveHitContext()
{
Directory.CreateDirectory(_hitsPath);
lock (_hitContext)
{
if (_hitContext.Hits.Count == 0)
return;

var fileName = Path.Combine(_hitsPath, $"{Guid.NewGuid()}.hits");
Directory.CreateDirectory(_hitsPath);

using (var fileStream = File.Open(fileName, FileMode.OpenOrCreate))
{
_hitContext.Serialize(fileStream);
fileStream.Flush();
var fileName = Path.Combine(_hitsPath, $"{Guid.NewGuid()}.hits");

using (var fileStream = File.Open(fileName, FileMode.OpenOrCreate))
{
_hitContext.Serialize(fileStream);
fileStream.Flush();
}

_hitContext.Reset();
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion tests/MiniCover.HitServices.UnitTests/HitContextTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,4 @@ public void BinarySerializationShouldWork()
}
}
}
}
}
1 change: 1 addition & 0 deletions tests/MiniCover.UnitTests/Instrumentation/BaseTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ public void Test()
var functionalTestMethod = instrumentedTestType.GetMethod(nameof(FunctionalTest));

HitContext.Current = new HitContext("Assembly", "Class", "Method");
HitContext.Current.EnterMethod();
var instrumentedTest = Activator.CreateInstance(instrumentedTestType);
functionalTestMethod.Invoke(instrumentedTest, new object[0]);

Expand Down

0 comments on commit a74269a

Please sign in to comment.