Commit 524c5c7b by Ben Clayton

Regres: Keep coverage span groups stable.

Update tests. Bug: b/152192800 Change-Id: I4e57f0d2b049f0bce7459b29f7ffc3a2ca03534a Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/43309 Kokoro-Presubmit: kokoro <noreply+kokoro@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com> Tested-by: 's avatarBen Clayton <bclayton@google.com>
parent f5da9d9c
......@@ -88,7 +88,7 @@ func TestTree(t *testing.T) {
// i
checkSpans(t, tree.Spans(), span0, span1, span2)
checkTests(t, tree, `{a:{b:{d:{i} e}}}`)
checkCoverage(t, tree, fileA, `a:{[0,1] b:{[] e:{[2]}}}`)
checkCoverage(t, tree, fileA, `a:{[0,1] b:{e:{[2]}}}`)
t.Log("Add 'n' with the coverage [0,3]")
tree.Add(cov.Path{"a", "c", "g", "n"}, coverage(fileA, span0, span3))
......@@ -132,7 +132,7 @@ func TestTree(t *testing.T) {
// i n o
checkSpans(t, tree.Spans(), span0, span1, span2, span3)
checkTests(t, tree, `{a:{b:{d:{i} e} c:{f g:{n o}}}}`)
checkCoverage(t, tree, fileA, `a:{[] b:{[0,1] e:{[2]}} c:{[] f:{[1]} g:{[0,3]}}}`)
checkCoverage(t, tree, fileA, `a:{b:{[0,1] e:{[2]}} c:{f:{[1]} g:{[0,3]}}}`)
t.Log("Add 'j' with the coverage [3]")
tree.Add(cov.Path{"a", "b", "e", "j"}, coverage(fileA, span3))
......@@ -146,7 +146,7 @@ func TestTree(t *testing.T) {
// i j n o
checkSpans(t, tree.Spans(), span0, span1, span2, span3)
checkTests(t, tree, `{a:{b:{d:{i} e:{j}} c:{f g:{n o}}}}`)
checkCoverage(t, tree, fileA, `a:{[] b:{[] d:{[0,1]} e:{[3]}} c:{[] f:{[1]} g:{[0,3]}}}`)
checkCoverage(t, tree, fileA, `a:{b:{d:{[0,1]} e:{[3]}} c:{f:{[1]} g:{[0,3]}}}`)
t.Log("Add 'k' with the coverage [3]")
tree.Add(cov.Path{"a", "b", "e", "k"}, coverage(fileA, span3))
......@@ -160,7 +160,7 @@ func TestTree(t *testing.T) {
// i j k n o
checkSpans(t, tree.Spans(), span0, span1, span2, span3)
checkTests(t, tree, `{a:{b:{d:{i} e:{j k}} c:{f g:{n o}}}}`)
checkCoverage(t, tree, fileA, `a:{[] b:{[] d:{[0,1]} e:{[3]}} c:{[] f:{[1]} g:{[0,3]}}}`)
checkCoverage(t, tree, fileA, `a:{b:{d:{[0,1]} e:{[3]}} c:{f:{[1]} g:{[0,3]}}}`)
t.Log("Add 'v' with the coverage [1,2]")
tree.Add(cov.Path{"a", "c", "f", "l", "v"}, coverage(fileA, span1, span2))
......@@ -176,7 +176,7 @@ func TestTree(t *testing.T) {
// v
checkSpans(t, tree.Spans(), span0, span1, span2, span3)
checkTests(t, tree, `{a:{b:{d:{i} e:{j k}} c:{f:{l:{v}} g:{n o}}}}`)
checkCoverage(t, tree, fileA, `a:{[] b:{[] d:{[0,1]} e:{[3]}} c:{[] f:{[1,2]} g:{[0,3]}}}`)
checkCoverage(t, tree, fileA, `a:{b:{d:{[0,1]} e:{[3]}} c:{f:{[1,2]} g:{[0,3]}}}`)
t.Log("Add 'x' with the coverage [1,2]")
tree.Add(cov.Path{"a", "c", "f", "l", "x"}, coverage(fileA, span1, span2))
......@@ -192,7 +192,7 @@ func TestTree(t *testing.T) {
// v x
checkSpans(t, tree.Spans(), span0, span1, span2, span3)
checkTests(t, tree, `{a:{b:{d:{i} e:{j k}} c:{f:{l:{v x}} g:{n o}}}}`)
checkCoverage(t, tree, fileA, `a:{[] b:{[] d:{[0,1]} e:{[3]}} c:{[] f:{[1,2]} g:{[0,3]}}}`)
checkCoverage(t, tree, fileA, `a:{b:{d:{[0,1]} e:{[3]}} c:{f:{[1,2]} g:{[0,3]}}}`)
t.Log("Add 'z' with the coverage [2]")
tree.Add(cov.Path{"a", "c", "g", "n", "z"}, coverage(fileA, span2))
......@@ -208,7 +208,22 @@ func TestTree(t *testing.T) {
// v x z
checkSpans(t, tree.Spans(), span0, span1, span2, span3)
checkTests(t, tree, `{a:{b:{d:{i} e:{j k}} c:{f:{l:{v x}} g:{n: {z} o}}}}`)
checkCoverage(t, tree, fileA, `a:{[] b:{[] d:{[0,1]} e:{[3]}} c:{[] f:{[1,2]} g:{[] n:{[2]} o:{[0,3]}}}}`)
checkCoverage(t, tree, fileA, `a:{b:{d:{[0,1]} e:{[3]}} c:{f:{[1,2]} g:{n:{[2]} o:{[0,3]}}}}`)
tree.Optimize()
// (a)
// ┏━━━━━━━━┻━━━━━━━━━━━━┓
// (b) (c)
// ┏━━━┻━━━┓ ┏━━━━┻━━━━┓
// <0>(d) (e)[3] <2>(f) (g)
// ╰─╮ ╭─┴─╮ ╭─╯ ┏━┻━┓
// i j k l [2](n) (o)<1>
// ╭┴╮ ╭╯
// v x z
checkSpans(t, tree.Spans(), span0, span1, span2, span3)
checkTests(t, tree, `{a:{b:{d:{i} e:{j k}} c:{f:{l:{v x}} g:{n: {z} o}}}}`)
checkCoverage(t, tree, fileA, `a:{b:{d:{<0>} e:{[3]}} c:{f:{<2>} g:{n:{[2]} o:{<1>}}}}`)
}
func checkSpans(t *testing.T, got []cov.Span, expect ...cov.Span) {
......
......@@ -37,15 +37,47 @@ func (l Location) String() string {
return fmt.Sprintf("%v:%v", l.Line, l.Column)
}
// Compare returns -1 if l comes before o, 1 if l comes after o, otherwise 0.
func (l Location) Compare(o Location) int {
switch {
case l.Line < o.Line:
return -1
case l.Line > o.Line:
return 1
}
return 0
}
// Before returns true if l comes before o.
func (l Location) Before(o Location) bool { return l.Compare(o) == -1 }
// Span describes a start and end interval in a source file.
type Span struct {
Start, End Location
}
func (l Span) String() string {
return fmt.Sprintf("%v-%v", l.Start, l.End)
func (s Span) String() string {
return fmt.Sprintf("%v-%v", s.Start, s.End)
}
// Compare returns -1 if l comes before o, 1 if l comes after o, otherwise 0.
func (s Span) Compare(o Span) int {
switch {
case s.Start.Before(o.Start):
return -1
case o.Start.Before(s.Start):
return 1
case s.End.Before(o.End):
return -1
case o.End.Before(s.End):
return 1
}
return 0
}
// Before returns true if span s comes before o.
func (s Span) Before(o Span) bool { return s.Compare(o) == -1 }
// File describes the coverage spans in a single source file.
type File struct {
Path string
......
......@@ -54,21 +54,35 @@ func (t *Tree) init() {
}
}
// SpanList is a list of Spans
type SpanList []Span
// Compare returns -1 if l comes before o, 1 if l comes after o, otherwise 0.
func (l SpanList) Compare(o SpanList) int {
switch {
case len(l) < len(o):
return -1
case len(l) > len(o):
return 1
}
for i, a := range l {
switch a.Compare(o[i]) {
case -1:
return -1
case 1:
return 1
}
}
return 0
}
// Spans returns all the spans used by the tree
func (t *Tree) Spans() []Span {
out := make([]Span, 0, len(t.spans))
func (t *Tree) Spans() SpanList {
out := make(SpanList, 0, len(t.spans))
for span := range t.spans {
out = append(out, span)
}
sort.Slice(out, func(i, j int) bool {
if out[i].Start.Line < out[j].Start.Line {
return true
}
if out[i].Start.Line > out[j].Start.Line {
return false
}
return out[i].Start.Column < out[j].Start.Column
})
sort.Slice(out, func(i, j int) bool { return out[i].Before(out[j]) })
return out
}
......@@ -259,7 +273,15 @@ type TestCoverage struct {
func (tc TestCoverage) String(t *Test, s Strings) string {
sb := strings.Builder{}
sb.WriteString(fmt.Sprintf("{%v", tc.Spans))
sb.WriteString("{")
if len(tc.Spans) > 0 {
sb.WriteString(tc.Spans.String())
}
if tc.Group != nil {
sb.WriteString(" <")
sb.WriteString(fmt.Sprintf("%v", *tc.Group))
sb.WriteString(">")
}
if len(tc.Children) > 0 {
sb.WriteString(" ")
sb.WriteString(tc.Children.String(t, s))
......@@ -313,9 +335,32 @@ type SpanID int
// SpanSet is a set of SpanIDs.
type SpanSet map[SpanID]struct{}
// SpanIDList is a list of SpanIDs
type SpanIDList []SpanID
// Compare returns -1 if l comes before o, 1 if l comes after o, otherwise 0.
func (l SpanIDList) Compare(o SpanIDList) int {
switch {
case len(l) < len(o):
return -1
case len(l) > len(o):
return 1
}
for i, a := range l {
b := o[i]
switch {
case a < b:
return -1
case a > b:
return 1
}
}
return 0
}
// List returns the full list of sorted span ids.
func (s SpanSet) List() []SpanID {
out := make([]SpanID, 0, len(s))
func (s SpanSet) List() SpanIDList {
out := make(SpanIDList, 0, len(s))
for span := range s {
out = append(out, span)
}
......@@ -422,7 +467,6 @@ func (f *treeFile) optimize() {
return
}
// Sort by number of spans in each sets.
type spansetInfo struct {
key spansetKey
set SpanSet // fully expanded set
......@@ -435,10 +479,25 @@ func (f *treeFile) optimize() {
key: key,
set: set,
grp: SpanGroup{spans: set},
id: SpanGroupID(len(spansets)),
})
}
sort.Slice(spansets, func(i, j int) bool { return len(spansets[i].set) > len(spansets[j].set) })
// Sort by number of spans in each sets starting with the largest.
sort.Slice(spansets, func(i, j int) bool {
a, b := spansets[i].set, spansets[j].set
switch {
case len(a) > len(b):
return true
case len(a) < len(b):
return false
}
return a.List().Compare(b.List()) == -1 // Just to keep output stable
})
// Assign IDs now that we have stable order.
for i := range spansets {
spansets[i].id = SpanGroupID(i)
}
// Loop over the spanGroups starting from the largest, and try to fold them
// into the larger sets.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment