Skip to content
This repository was archived by the owner on Nov 15, 2021. It is now read-only.
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
115 changes: 76 additions & 39 deletions main/OpenCover.Framework/Persistance/BasePersistance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -230,8 +230,13 @@ private void RemoveUnreferencedFiles()
}
}

private static readonly SequencePoint[] emptySeqPoints = new SequencePoint[0];
private static readonly BranchPoint[] emptyBranchPoints = new BranchPoint[0];
private static readonly List<BranchPoint> emptyBranchList = new List<BranchPoint>(0);

private void PopulateInstrumentedPoints()
{

if (CoverageSession.Modules == null) return;

foreach (var method in from @class in
Expand Down Expand Up @@ -264,67 +269,92 @@ from method in @class.Methods.Where(x => !x.ShouldSerializeSkippedDueTo())

foreach (var method in (@class.Methods ?? new Method[0]).Where(x => !x.ShouldSerializeSkippedDueTo()))
{
var sequencePoints = method.SequencePoints ?? new SequencePoint[0];
var branchPoints = method.BranchPoints ?? new BranchPoint[0];
if (method.SequencePoints == null) method.SequencePoints = emptySeqPoints;
if (method.BranchPoints == null) method.BranchPoints = emptyBranchPoints;

// use shorter names
var sPoints = method.SequencePoints;
var bPoints = method.BranchPoints;

// No sequences in method, but branches present? => remove branches
if (sPoints.Length == 0 && bPoints.Length != 0) {
bPoints = emptyBranchPoints;
}

MapFileReferences(sequencePoints, filesDictionary);
MapFileReferences(branchPoints, filesDictionary);
if (sPoints.Length != 0) MapFileReferences(sPoints, filesDictionary);
if (bPoints.Length != 0) MapFileReferences(bPoints, filesDictionary);

#region Merge branch-exits

// SP & BP are sorted by offset and code below expect both SP & BP to be sorted by offset
// ATTN: Sorted again to prevent future bugs if order of SP & BP is changed!
sPoints = sPoints.OrderBy( sp => sp.Offset ).ToArray();
bPoints = bPoints.OrderBy( bp => bp.Offset ).ToArray();

// anything to merge?
if (sequencePoints.Length != 0 && branchPoints.Length != 0) {
if (sPoints.Length != 0 && bPoints.Length != 0) {

#region Join Sequences and Branches
// Quick match branches to sequence using SP&BP sort order by IL offset

var index = 0;

// get first sequencePoint and prepare list for Add(branchPoint)
var parent = sequencePoints[index];
parent.BranchPoints = new List<BranchPoint>();
var currentSp = sPoints[index];
currentSp.BranchPoints = new List<BranchPoint>();

// get nextOffset
int nextOffset = index + 1 < sequencePoints.Length ? sequencePoints[index + 1].Offset : int.MaxValue;
int nextSpOffset = index + 1 < sPoints.Length ? sPoints[index + 1].Offset : int.MinValue;

foreach (var branchPoint in branchPoints) {
foreach (var currentBp in bPoints) {

// while branchPoint belongs to next sequencePoint
// nextOffset is offset of next sequencePoint
// or unreachable int.MinValue
while (branchPoint.Offset > nextOffset) {
/*
* As long as current_BP_offset is between
* current_SP_offset and [next_SP_offset],
* current_BP belongs to current_SP
*/

// Is currentBp outside of scope of current_SP?
while (nextSpOffset != int.MinValue && currentBp.Offset >= nextSpOffset) {

/*
* Find next sequence points pair where
* currentSp_offset <= currentBp_offset < nextSp_offset
*/

// increment index to next sequencePoint
++index;

// get next sequencePoint and prepare list for Add(branchPoint)
parent = sequencePoints[index];
parent.BranchPoints = new List<BranchPoint>();
currentSp = sPoints[index];
currentSp.BranchPoints = new List<BranchPoint>();

// get nextOffset
if (index + 1 < sequencePoints.Length) {
nextOffset = sequencePoints[index + 1].Offset;
}
else {
nextOffset = int.MaxValue;
}
// get nextSpOffset
nextSpOffset = index + 1 < sPoints.Length ? sPoints[index + 1].Offset : int.MinValue;
}

// Add BranchPoint to curent SequencePoint
if (currentBp.Offset >= currentSp.Offset) {
currentSp.BranchPoints.Add(currentBp);
}
// join BranchPoint to SequencePoint
parent.BranchPoints.Add(branchPoint);
}

#endregion

#region Merge each Sequence Branch-Exits
#region Merge Branch-Exits for each Sequence

// Collection of validBranchPoints (child/connected to parent SequencePoint)
var validBranchPoints = new List<BranchPoint>();

var branchExits = new Dictionary<int, BranchPoint>();
foreach (var sequencePoint in sequencePoints) {
foreach (var sp in sPoints) {

// SequencePoint has branches attached?
if (sequencePoint.BranchPoints != null && sequencePoint.BranchPoints.Count != 0) {
if (sp.BranchPoints != null && sp.BranchPoints.Count != 0) {

// Merge SP.BranchPoints using EndOffset as branchExits key
// Merge sp.BranchPoints using EndOffset as branchExits key
branchExits.Clear();
foreach (var branchPoint in sequencePoint.BranchPoints) {
foreach (var branchPoint in sp.BranchPoints) {
if (!branchExits.ContainsKey(branchPoint.EndOffset)) {
branchExits[branchPoint.EndOffset] = branchPoint; // insert branch
} else {
Expand All @@ -333,16 +363,23 @@ from method in @class.Methods.Where(x => !x.ShouldSerializeSkippedDueTo())
}

// Update SequencePoint properties/attributes
sequencePoint.BranchExitsCount = 0;
sequencePoint.BranchExitsVisit = 0;
sp.BranchExitsCount = 0;
sp.BranchExitsVisit = 0;
foreach (var branchPoint in branchExits.Values) {
sequencePoint.BranchExitsCount += 1;
sequencePoint.BranchExitsVisit += branchPoint.VisitCount == 0 ? 0 : 1;
sp.BranchExitsCount += 1;
sp.BranchExitsVisit += branchPoint.VisitCount == 0 ? 0 : 1;
}

// Add validBranchPoints
validBranchPoints.AddRange(sp.BranchPoints);
sp.BranchPoints = emptyBranchList; // clear
}
sequencePoint.BranchPoints = null; // release memory
}


// Replace original branchPoints with branches connected to sequence point(s)
bPoints = validBranchPoints.ToArray();
validBranchPoints = emptyBranchList; // clear

#endregion

}
Expand All @@ -354,10 +391,10 @@ from method in @class.Methods.Where(x => !x.ShouldSerializeSkippedDueTo())
method.Visited = (method.MethodPoint.VisitCount > 0);
}

method.Summary.NumBranchPoints = branchPoints.Count();
method.Summary.VisitedBranchPoints = branchPoints.Count(pt => pt.VisitCount != 0);
method.Summary.NumSequencePoints = sequencePoints.Count();
method.Summary.VisitedSequencePoints = sequencePoints.Count(pt => pt.VisitCount != 0);
method.Summary.NumBranchPoints = bPoints.Count();
method.Summary.VisitedBranchPoints = bPoints.Count(pt => pt.VisitCount != 0);
method.Summary.NumSequencePoints = sPoints.Count();
method.Summary.VisitedSequencePoints = sPoints.Count(pt => pt.VisitCount != 0);

if (method.Summary.NumSequencePoints > 0)
method.Summary.NumBranchPoints += 1;
Expand Down
16 changes: 5 additions & 11 deletions main/OpenCover.Installer/Components.wxs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,15 @@
<Component Id="MainProduct" Guid="{D451E3FE-35A6-4946-B0C5-FFE22580891C}">
<File Id="OPENCOVER_CONSOLE_EXE" Source="..\bin\Release\OpenCover.Console.exe" KeyPath="yes" />
<File Id="OPENCOVER_CONSOLE_EXE_CONFIG" Source="..\bin\Release\OpenCover.Console.exe.config" />
<File Id="OPENCOVER_CONSOLE_PDB" Source="..\bin\Release\OpenCover.Console.pdb" />
</Component>
<Component Id="MainFramework" Guid="{6AA473E5-13D3-4963-983E-3F5B007A29D9}">
<File Id="OPENCOVER_FRAMEWORK_DLL" Source="..\bin\Release\OpenCover.Framework.dll" KeyPath="yes" />
<File Id="OPENCOVER_FRAMEWORK_PDB" Source="..\bin\Release\OpenCover.Framework.pdb" />
</Component>
<Component Id="Extensions" Guid="{B34740C7-1432-4AD0-A205-A036CBC8EAE4}">
<File Id="OPENCOVER_EXTENSIONS_DLL" Source="..\bin\Release\OpenCover.Extensions.dll" KeyPath="yes" />
<File Id="OPENCOVER_EXTENSIONS_PDB" Source="..\bin\Release\OpenCover.Extensions.pdb" />
</Component>
<Component Id="Autofac_3rdParty" Guid="{C0CB1F5D-38BF-4B20-94F4-CD74C349CD79}">
<File Id="AUTOFAC_DLL" Source="..\bin\Release\Autofac.dll" KeyPath="yes" />
Expand All @@ -43,11 +46,6 @@
<File Id="LOG4NET_DLL" Source="..\bin\Release\log4net.dll" KeyPath="yes" />
<File Id="LOG4NET_CONFIG" Source="..\bin\Release\log4net.config" />
</Component>
<Component Id="MainProductSymbols" Guid="6A175C94-446D-49B0-8D29-184F091B5582">
<File Id="OPENCOVER_CONSOLE_PDB" Source="..\bin\Release\OpenCover.Console.pdb" KeyPath="yes" />
<File Id="OPENCOVER_FRAMEWORK_PDB" Source="..\bin\Release\OpenCover.Framework.pdb" />
<File Id="OPENCOVER_EXTENSIONS_PDB" Source="..\bin\Release\OpenCover.Extensions.pdb" />
</Component>
<Component Id="SampleCmds" Guid="4D7F8200-EC80-49A2-92FB-2083E8FC469D">
<File Id="SAMPLE_CMD" Source="Assets\Sample.cmd" Name="Sample.cmd" KeyPath="yes" />
<File Id="SAMPLE64_CMD" Source="Assets\Sample64.cmd" Name="Sample64.cmd" />
Expand Down Expand Up @@ -87,9 +85,7 @@
</TypeLib>
-->
</File>
</Component>
<Component Id="X86ProfilerSymbols" Guid="E3397930-DC37-46E8-B8D4-9BDC184B8472" >
<File Id="OPENCOVER_PROFILER_PDB_X86" Source="..\bin\Release\x86\OpenCover.Profiler.pdb" KeyPath="yes" />
<File Id="OPENCOVER_PROFILER_PDB_X86" Source="..\bin\Release\x86\OpenCover.Profiler.pdb" />
</Component>
</DirectoryRef>

Expand All @@ -105,9 +101,7 @@
</TypeLib>
-->
</File>
</Component>
<Component Id="X64ProfilerSymbols" Guid="608C08DE-43A9-488D-A5C6-AC9CDF39A7DA" >
<File Id="OPENCOVER_PROFILER_PDB_X64" Source="..\bin\Release\x64\OpenCover.Profiler.pdb" KeyPath="yes" />
<File Id="OPENCOVER_PROFILER_PDB_X64" Source="..\bin\Release\x64\OpenCover.Profiler.pdb" />
</Component>
</DirectoryRef>

Expand Down
11 changes: 2 additions & 9 deletions main/OpenCover.Installer/Product.wxs
Original file line number Diff line number Diff line change
Expand Up @@ -56,20 +56,13 @@
<ComponentRef Id="PromptShortcut" />
<ComponentRef Id="TransformScript" />
<ComponentRef Id="SimpleTransform" />
<ComponentRef Id="Documentation" />
<ComponentRef Id="DocumentationShortcut"/>
<Feature Id="SamplesFeature" Title="Samples" Level="1" Description="Install 32-bit and 64-bit samples. NOTE: Useful for testing the installation.">
<ComponentRef Id="X86Samples" />
<ComponentRef Id="X64Samples" />
<ComponentRef Id="SampleCmds" />
</Feature>
<Feature Id="DocumentationFeature" Title="Documentation" Level="1" Description="Install the documentation for OpenCover. NOTE: If you are new to OpenCover you may find this information useful.">
<ComponentRef Id="Documentation" />
<ComponentRef Id="DocumentationShortcut"/>
</Feature>
<Feature Id="SymbolsFeature" Title="Debug Symbols" Level="100" Description="The Debug Symbols, useful if you are having issues and need to report a bug, with a stack trace, but not necessary for normal operation.">
<ComponentRef Id="MainProductSymbols" />
<ComponentRef Id="X64ProfilerSymbols" />
<ComponentRef Id="X86ProfilerSymbols" />
</Feature>
</Feature>

<InstallExecuteSequence>
Expand Down
18 changes: 9 additions & 9 deletions main/OpenCover.Profiler/CodeCoverage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ HRESULT CCodeCoverage::OpenCoverInitialise(IUnknown *pICorProfilerInfoUnk){
ATLTRACE(_T("::OpenCoverInitialise"));

OLECHAR szGuid[40]={0};
int nCount = ::StringFromGUID2(CLSID_CodeCoverage, szGuid, 40);
::StringFromGUID2(CLSID_CodeCoverage, szGuid, 40);
RELTRACE(L" ::Initialize(...) => CLSID == %s", szGuid);
//::OutputDebugStringW(szGuid);

Expand Down Expand Up @@ -351,14 +351,14 @@ void CCodeCoverage::InstrumentMethod(ModuleID moduleId, Method& method, std::ve
CoverageInstrumentation::InsertFunctionCall(instructions, pvsig, (FPTR)pt, seqPoints[0].UniqueId);
if (method.IsInstrumented(0, instructions)) return;

CoverageInstrumentation::AddBranchCoverage([pvsig, pt](InstructionList& instructions, ULONG uniqueId)->Instruction*
CoverageInstrumentation::AddBranchCoverage([pvsig, pt](InstructionList& brinstructions, ULONG uniqueId)->Instruction*
{
return CoverageInstrumentation::InsertFunctionCall(instructions, pvsig, (FPTR)pt, uniqueId);
return CoverageInstrumentation::InsertFunctionCall(brinstructions, pvsig, (FPTR)pt, uniqueId);
}, method, brPoints, seqPoints);

CoverageInstrumentation::AddSequenceCoverage([pvsig, pt](InstructionList& instructions, ULONG uniqueId)->Instruction*
CoverageInstrumentation::AddSequenceCoverage([pvsig, pt](InstructionList& seqinstructions, ULONG uniqueId)->Instruction*
{
return CoverageInstrumentation::InsertFunctionCall(instructions, pvsig, (FPTR)pt, uniqueId);
return CoverageInstrumentation::InsertFunctionCall(seqinstructions, pvsig, (FPTR)pt, uniqueId);
}, method, seqPoints);
}
else
Expand All @@ -370,14 +370,14 @@ void CCodeCoverage::InstrumentMethod(ModuleID moduleId, Method& method, std::ve
CoverageInstrumentation::InsertInjectedMethod(instructions, injectedVisitedMethod, seqPoints[0].UniqueId);
if (method.IsInstrumented(0, instructions)) return;

CoverageInstrumentation::AddBranchCoverage([injectedVisitedMethod](InstructionList& instructions, ULONG uniqueId)->Instruction*
CoverageInstrumentation::AddBranchCoverage([injectedVisitedMethod](InstructionList& brinstructions, ULONG uniqueId)->Instruction*
{
return CoverageInstrumentation::InsertInjectedMethod(instructions, injectedVisitedMethod, uniqueId);
return CoverageInstrumentation::InsertInjectedMethod(brinstructions, injectedVisitedMethod, uniqueId);
}, method, brPoints, seqPoints);

CoverageInstrumentation::AddSequenceCoverage([injectedVisitedMethod](InstructionList& instructions, ULONG uniqueId)->Instruction*
CoverageInstrumentation::AddSequenceCoverage([injectedVisitedMethod](InstructionList& seqinstructions, ULONG uniqueId)->Instruction*
{
return CoverageInstrumentation::InsertInjectedMethod(instructions, injectedVisitedMethod, uniqueId);
return CoverageInstrumentation::InsertInjectedMethod(seqinstructions, injectedVisitedMethod, uniqueId);
}, method, seqPoints);
}
}
Expand Down
Loading