Browse Source

CodeCoverage: Corner cases / refactoring

pull/67/head
Dragan 12 years ago
parent
commit
2c134f190e
  1. 73
      src/AddIns/Analysis/CodeCoverage/Project/Src/CodeCoverageMethodElement.cs

73
src/AddIns/Analysis/CodeCoverage/Project/Src/CodeCoverageMethodElement.cs

@ -151,7 +151,31 @@ namespace ICSharpCode.CodeCoverage @@ -151,7 +151,31 @@ namespace ICSharpCode.CodeCoverage
}
return bps;
}
// Find method-body first SequencePoint "{"
public static CodeCoverageSequencePoint getBodyStartSP(IEnumerable<CodeCoverageSequencePoint> sps) {
CodeCoverageSequencePoint startSeqPoint = null;
foreach (CodeCoverageSequencePoint sp in sps) {
if ( sp.Content == "{") {
startSeqPoint = sp;
break;
}
}
return startSeqPoint;
}
// Find method-body final SequencePoint "}"
public static CodeCoverageSequencePoint getBodyFinalSP(IEnumerable<CodeCoverageSequencePoint> sps) {
CodeCoverageSequencePoint finalSeqPoint = null;
foreach (CodeCoverageSequencePoint sp in Enumerable.Reverse(sps)) {
if ( sp.Content == "}") {
finalSeqPoint = sp;
break;
}
}
return finalSeqPoint;
}
Tuple<int,int> GetBranchRatio () {
// goal: Get branch ratio and exclude (rewriten) Code Contracts branches
@ -165,33 +189,14 @@ namespace ICSharpCode.CodeCoverage @@ -165,33 +189,14 @@ namespace ICSharpCode.CodeCoverage
return null;
}
// Find method-body first SequencePoint "{"
// and then first next sequencePoint (and offset of that instruction in body)
// This is used to skip CCRewrite(n) BranchPoint's (Requires)
// This sequence point offset is used to skip CCRewrite(n) BranchPoint's (Requires)
// and '{' branches at static methods
bool startSPFound = false;
CodeCoverageSequencePoint startSeqPoint = null;
foreach (CodeCoverageSequencePoint sp in this.SequencePoints) {
if (startSPFound) {
startSeqPoint = sp;
break;
}
if ( sp.Content == "{") {
startSPFound = true;
}
}
CodeCoverageSequencePoint startSeqPoint = getBodyStartSP(this.SequencePoints);
Debug.Assert (!Object.ReferenceEquals(null, startSeqPoint));
if (Object.ReferenceEquals(null, startSeqPoint)) { return null; }
// Find method-body last SequencePoint "}" and offset
// This is used to skip CCRewrite(n) BranchPoint's (Ensures)
CodeCoverageSequencePoint finalSeqPoint = null;
foreach (CodeCoverageSequencePoint sp in Enumerable.Reverse(this.SequencePoints)) {
if ( sp.Content == "}") {
finalSeqPoint = sp;
break;
}
}
// This sequence point offset is used to skip CCRewrite(n) BranchPoint's (Ensures)
CodeCoverageSequencePoint finalSeqPoint = getBodyFinalSP(this.SequencePoints);
Debug.Assert ( !Object.ReferenceEquals( null, finalSeqPoint) );
if (Object.ReferenceEquals(null, finalSeqPoint)) { return null; }
@ -202,7 +207,7 @@ namespace ICSharpCode.CodeCoverage @@ -202,7 +207,7 @@ namespace ICSharpCode.CodeCoverage
foreach (var bp in this.BranchPoints) {
// exclude CCRewrite(n) contracts
// ignore branches outside of method body
if (bp.Offset < startSeqPoint.Offset)
continue;
if (bp.Offset > finalSeqPoint.Offset)
@ -224,12 +229,6 @@ namespace ICSharpCode.CodeCoverage @@ -224,12 +229,6 @@ namespace ICSharpCode.CodeCoverage
currSeqPoint.Branches.Add(bp);
}
// for (int i = this.SequencePoints.Count-1; i >= 0; i--) {
// if (this.SequencePoints[i].Content.StartsWith("Assert")) {
// this.SequencePoints.RemoveAt(i);
// }
// }
// Merge sp.Branches on exit-offset
// Calculate Method Branch coverage
int totalBranchVisit = 0;
@ -242,12 +241,14 @@ namespace ICSharpCode.CodeCoverage @@ -242,12 +241,14 @@ namespace ICSharpCode.CodeCoverage
// SequencePoint covered & has branches?
if (sp.VisitCount != 0 && sp.Branches != null) {
// Generated "in" code for IEnumerables contains hidden "try/catch/finally" branches that
// 1) Generated "in" code for IEnumerables contains hidden "try/catch/finally" branches that
// one do not want or cannot cover by test-case because is handled earlier at same method.
// ie: NullReferenceException in foreach loop is pre-handled at method entry, ie. by Contract.Require(items!=null)
// exclude Contract class (EnsuresOnThrow)
// exclude NUnit Assert class
if (sp.Content == "in" ||
// 2) Branches within sequence points "{" and "}" are not source branches but compiler generated branches
// ie: static methods start sequence point "{" contains compiler generated branches
// 3) Exclude Contract class (EnsuresOnThrow/Assert/Assume is inside method body)
// 4) Exclude NUnit Assert(.Throws) class
if (sp.Content == "in" || sp.Content == "{" || sp.Content == "}" ||
sp.Content.StartsWith("Assert.") ||
sp.Content.StartsWith("Assert ") ||
sp.Content.StartsWith("Contract.") ||
@ -274,9 +275,9 @@ namespace ICSharpCode.CodeCoverage @@ -274,9 +275,9 @@ namespace ICSharpCode.CodeCoverage
pointBranchVisit += bp.VisitCount == 0? 0 : 1 ;
pointBranchCount += 1;
}
// Not full coverage?
// Not full coverage?
if (pointBranchVisit != pointBranchCount) {
sp.BranchCoverage = false; // part-covered
sp.BranchCoverage = false; // => part-covered
}
totalBranchVisit += pointBranchVisit;
totalBranchCount += pointBranchCount;

Loading…
Cancel
Save