Skip to content

Commit

Permalink
neotest: fix coverage blocks overlapping
Browse files Browse the repository at this point in the history
Signed-off-by: Slava0135 <[email protected]>
  • Loading branch information
Slava0135 committed Sep 14, 2024
1 parent d9a6a7c commit 650f9a3
Show file tree
Hide file tree
Showing 2 changed files with 361 additions and 17 deletions.
77 changes: 60 additions & 17 deletions pkg/neotest/coverage.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ type coverBlock struct {
// documentName makes it clear when a `string` maps path to the script file.
type documentName = string

type interval struct {
compiler.DebugSeqPoint
remove bool
}

func isCoverageEnabled() bool {
coverageLock.Lock()
defer coverageLock.Unlock()
Expand Down Expand Up @@ -150,31 +155,33 @@ func processCover() map[documentName][]coverBlock {
for documentName := range documents {
mappedBlocks := make(map[int]*coverBlock)

var allDocumentSeqPoints []compiler.DebugSeqPoint
for _, scriptRawCoverage := range rawCoverage {
di := scriptRawCoverage.debugInfo
documentSeqPoints := documentSeqPoints(di, documentName)

for _, point := range documentSeqPoints {
b := coverBlock{
startLine: uint(point.StartLine),
startCol: uint(point.StartCol),
endLine: uint(point.EndLine),
endCol: uint(point.EndCol),
stmts: 1 + uint(point.EndLine) - uint(point.StartLine),
counts: 0,
}
mappedBlocks[point.Opcode] = &b
documentSeqPoints := documentSeqPoints(scriptRawCoverage.debugInfo, documentName)
allDocumentSeqPoints = append(allDocumentSeqPoints, documentSeqPoints...)
}
allDocumentSeqPoints = resolveOverlaps(allDocumentSeqPoints)

for _, point := range allDocumentSeqPoints {
b := coverBlock{
startLine: uint(point.StartLine),
startCol: uint(point.StartCol),
endLine: uint(point.EndLine),
endCol: uint(point.EndCol),
stmts: 1 + uint(point.EndLine) - uint(point.StartLine),
counts: 0,
}
mappedBlocks[point.Opcode] = &b
}

for _, scriptRawCoverage := range rawCoverage {
di := scriptRawCoverage.debugInfo
documentSeqPoints := documentSeqPoints(di, documentName)

documentSeqPoints := documentSeqPoints(scriptRawCoverage.debugInfo, documentName)
for _, offset := range scriptRawCoverage.offsetsVisited {
for _, point := range documentSeqPoints {
if point.Opcode == offset {
mappedBlocks[point.Opcode].counts++
if _, ok := mappedBlocks[offset]; ok {
mappedBlocks[offset].counts++
}
}
}
}
Expand Down Expand Up @@ -202,6 +209,42 @@ func documentSeqPoints(di *compiler.DebugInfo, doc documentName) []compiler.Debu
return res
}

// resolveOverlaps removes overlaps from debug points.
// Its assumed that intervals can never overlap partially.
func resolveOverlaps(points []compiler.DebugSeqPoint) []compiler.DebugSeqPoint {
var intervals []interval
for _, p := range points {
intervals = append(intervals, interval{DebugSeqPoint: p})
}
for i := range intervals {
for j := range intervals {
inner := &intervals[i]
outer := &intervals[j]
// If interval 'i' is already removed than there exists an even smaller interval that is also included by 'j'.
// This also ensures that if there are 2 equal intervals then at least 1 will remain.
if i == j || inner.remove {
continue
}
// Outer interval start can't be after inner interval start.
if !(outer.StartLine < inner.StartLine || outer.StartLine == inner.StartLine && outer.StartCol <= inner.StartCol) {
continue
}
// Outer interval end can't be before inner interval end.
if !(outer.EndLine > inner.EndLine || outer.EndLine == inner.EndLine && outer.EndCol >= inner.EndCol) {
continue
}
outer.remove = true
}
}
var res []compiler.DebugSeqPoint
for i, v := range intervals {
if !v.remove {
res = append(res, points[i])
}
}
return res
}

func addScriptToCoverage(c *Contract) {
coverageLock.Lock()
defer coverageLock.Unlock()
Expand Down
Loading

0 comments on commit 650f9a3

Please sign in to comment.