dashboard/app: allow main UI to show bisect results

* Modify uiBug type. Rename BisectCause to BisectCauseDone. Introduce
BisectFixDone.
* Modify createUIBug() and MergeUIBug() to set the above fields
appropriately.
* Modify bug_list to display the bisection status; remove yesSort() as
it is not used anymore. Adjust ".list_table .stat" to appropriate width.
* Add TestBugBisectionStatus() to check bisection status on main page.
* Add file from running "make generate": pkg/html/generated.go
This commit is contained in:
Zubin Mithra 2019-08-01 15:19:59 -07:00 committed by Dmitry Vyukov
parent 657092bddf
commit a02b5bcae2
6 changed files with 151 additions and 43 deletions

View File

@ -819,3 +819,102 @@ func TestBugBisectionResults(t *testing.T) {
c.expectTrue(bytes.Contains(content, []byte("Bisection: fixed by")))
c.expectTrue(bytes.Contains(content, []byte("kernel: add a fix")))
}
// Test that bisection status shows up on main page
func TestBugBisectionStatus(t *testing.T) {
c := NewCtx(t)
defer c.Close()
// Upload a crash report
build := testBuild(1)
c.client2.UploadBuild(build)
crash := testCrashWithRepro(build, 1)
c.client2.ReportCrash(crash)
c.client2.pollEmailBug()
// Receive the JobBisectCause and send cause information
resp := c.client2.pollJobs(build.Manager)
c.client2.expectNE(resp.ID, "")
c.client2.expectEQ(resp.Type, dashapi.JobBisectCause)
jobID := resp.ID
done := &dashapi.JobDoneReq{
ID: jobID,
Build: *build,
Log: []byte("bisectfix log 4"),
CrashTitle: "bisectfix crash title 4",
CrashLog: []byte("bisectfix crash log 4"),
CrashReport: []byte("bisectfix crash report 4"),
Commits: []dashapi.Commit{
{
Hash: "36e65cb4a0448942ec316b24d60446bbd5cc7827",
Title: "kernel: add a bug",
Author: "author@kernel.org",
AuthorName: "Author Kernelov",
CC: []string{
"reviewer1@kernel.org", "\"Reviewer2\" <reviewer2@kernel.org>",
// These must be filtered out:
"syzbot@testapp.appspotmail.com",
"syzbot+1234@testapp.appspotmail.com",
"\"syzbot\" <syzbot+1234@testapp.appspotmail.com>",
},
Date: time.Date(2000, 2, 9, 4, 5, 6, 7, time.UTC),
},
},
}
c.expectOK(c.client2.JobDone(done))
// Fetch bug, namespace details
var bugs []*Bug
_, err := db.NewQuery("Bug").GetAll(c.ctx, &bugs)
c.expectEQ(err, nil)
c.expectEQ(len(bugs), 1)
url := fmt.Sprintf("/%v", bugs[0].Namespace)
content, err := c.httpRequest("GET", url, "", AccessAdmin)
c.expectEQ(err, nil)
c.expectTrue(bytes.Contains(content, []byte("cause")))
// Advance time by 30 days and read out any notification emails
{
c.advanceTime(30 * 24 * time.Hour)
msg := c.client2.pollEmailBug()
c.expectTrue(strings.Contains(msg.Body, "syzbot has bisected this bug to:"))
msg = c.client2.pollEmailBug()
c.expectTrue(strings.Contains(msg.Body, "Sending this report upstream."))
msg = c.client2.pollEmailBug()
c.expectTrue(strings.Contains(msg.Body, "syzbot found the following crash"))
}
// Receive a JobBisectfix and send fix information.
resp = c.client2.pollJobs(build.Manager)
c.client2.expectNE(resp.ID, "")
c.client2.expectEQ(resp.Type, dashapi.JobBisectFix)
jobID = resp.ID
done = &dashapi.JobDoneReq{
ID: jobID,
Build: *build,
Log: []byte("bisectfix log 4"),
CrashTitle: "bisectfix crash title 4",
CrashLog: []byte("bisectfix crash log 4"),
CrashReport: []byte("bisectfix crash report 4"),
Commits: []dashapi.Commit{
{
Hash: "46e65cb4a0448942ec316b24d60446bbd5cc7827",
Title: "kernel: add a fix",
Author: "author@kernel.org",
AuthorName: "Author Kernelov",
CC: []string{
"reviewer1@kernel.org", "\"Reviewer2\" <reviewer2@kernel.org>",
// These must be filtered out:
"syzbot@testapp.appspotmail.com",
"syzbot+1234@testapp.appspotmail.com",
"\"syzbot\" <syzbot+1234@testapp.appspotmail.com>",
},
Date: time.Date(2000, 2, 9, 4, 5, 6, 7, time.UTC),
},
},
}
c.expectOK(c.client2.JobDone(done))
content, err = c.httpRequest("GET", url, "", AccessAdmin)
c.expectEQ(err, nil)
c.expectTrue(bytes.Contains(content, []byte("cause+fix")))
}

View File

@ -134,25 +134,26 @@ type uiBugGroup struct {
}
type uiBug struct {
Namespace string
Title string
NumCrashes int64
NumCrashesBad bool
BisectCause bool
FirstTime time.Time
LastTime time.Time
ReportedTime time.Time
ClosedTime time.Time
ReproLevel dashapi.ReproLevel
ReportingIndex int
Status string
Link string
ExternalLink string
CreditEmail string
Commits []*uiCommit
PatchedOn []string
MissingOn []string
NumManagers int
Namespace string
Title string
NumCrashes int64
NumCrashesBad bool
BisectCauseDone bool
BisectFixDone bool
FirstTime time.Time
LastTime time.Time
ReportedTime time.Time
ClosedTime time.Time
ReproLevel dashapi.ReproLevel
ReportingIndex int
Status string
Link string
ExternalLink string
CreditEmail string
Commits []*uiCommit
PatchedOn []string
MissingOn []string
NumManagers int
}
type uiCrash struct {
@ -734,21 +735,22 @@ func createUIBug(c context.Context, bug *Bug, state *ReportingState, managers []
}
id := bug.keyHash()
uiBug := &uiBug{
Namespace: bug.Namespace,
Title: bug.displayTitle(),
BisectCause: bug.BisectCause > BisectPending,
NumCrashes: bug.NumCrashes,
FirstTime: bug.FirstTime,
LastTime: bug.LastTime,
ReportedTime: reported,
ClosedTime: bug.Closed,
ReproLevel: bug.ReproLevel,
ReportingIndex: reportingIdx,
Status: status,
Link: bugLink(id),
ExternalLink: link,
CreditEmail: creditEmail,
NumManagers: len(managers),
Namespace: bug.Namespace,
Title: bug.displayTitle(),
BisectCauseDone: bug.BisectCause > BisectPending,
BisectFixDone: bug.BisectFix > BisectPending,
NumCrashes: bug.NumCrashes,
FirstTime: bug.FirstTime,
LastTime: bug.LastTime,
ReportedTime: reported,
ClosedTime: bug.Closed,
ReproLevel: bug.ReproLevel,
ReportingIndex: reportingIdx,
Status: status,
Link: bugLink(id),
ExternalLink: link,
CreditEmail: creditEmail,
NumManagers: len(managers),
}
updateBugBadness(c, uiBug)
if len(bug.Commits) != 0 {
@ -783,7 +785,8 @@ func createUIBug(c context.Context, bug *Bug, state *ReportingState, managers []
func mergeUIBug(c context.Context, bug *uiBug, dup *Bug) {
bug.NumCrashes += dup.NumCrashes
bug.BisectCause = bug.BisectCause || dup.BisectCause > BisectPending
bug.BisectCauseDone = bug.BisectCauseDone || dup.BisectCause > BisectPending
bug.BisectFixDone = bug.BisectFixDone || dup.BisectFix > BisectPending
if bug.LastTime.Before(dup.LastTime) {
bug.LastTime = dup.LastTime
}

View File

@ -41,7 +41,6 @@ function isSorted(values) {
function textSort(v) { return v.toLowerCase(); }
function numSort(v) { return -parseInt(v); }
function floatSort(v) { return -parseFloat(v); }
function yesSort(v) { return v == "yes" ? 0 : 1; }
function reproSort(v) { return v == "C" ? 0 : v == "syz" ? 1 : 2; }
function patchedSort(v) { return v == "" ? -1 : parseInt(v); }

View File

@ -127,8 +127,8 @@ table td, table th {
}
.list_table .stat {
width: 50pt;
max-width: 50pt;
width: 55pt;
max-width: 55pt;
font-family: monospace;
text-align: right;
}

View File

@ -79,7 +79,7 @@ Use of this source code is governed by Apache 2 LICENSE that can be found in the
{{end}}
<th><a onclick="return sortTable(this, 'Title', textSort)" href="#">Title</a></th>
<th><a onclick="return sortTable(this, 'Repro', reproSort)" href="#">Repro</a></th>
<th><a onclick="return sortTable(this, 'Bisected', yesSort)" href="#">Bisected</a></th>
<th><a onclick="return sortTable(this, 'Bisected', textSort)" href="#">Bisected</a></th>
<th><a onclick="return sortTable(this, 'Count', numSort)" href="#">Count</a></th>
<th><a onclick="return sortTable(this, 'Last', timeSort)" href="#">Last</a></th>
<th><a onclick="return sortTable(this, 'Reported', timeSort)" href="#">Reported</a></th>
@ -101,7 +101,15 @@ Use of this source code is governed by Apache 2 LICENSE that can be found in the
{{if $.ShowNamespace}}<td>{{$b.Namespace}}</td>{{end}}
<td class="title"><a href="{{$b.Link}}">{{$b.Title}}</a></td>
<td class="stat">{{formatReproLevel $b.ReproLevel}}</td>
<td class="stat">{{if $b.BisectCause}}yes{{end}}</td>
<td class="stat">
{{if and $b.BisectCauseDone $b.BisectFixDone}}
cause+fix
{{else if $b.BisectCauseDone}}
cause
{{else if $b.BisectFixDone}}
fix
{{end}}
</td>
<td class="stat {{if $b.NumCrashesBad}}bad{{end}}">{{$b.NumCrashes}}</td>
<td class="stat">{{formatLateness $.Now $b.LastTime}}</td>
<td class="stat">

View File

@ -130,8 +130,8 @@ table td, table th {
}
.list_table .stat {
width: 50pt;
max-width: 50pt;
width: 55pt;
max-width: 55pt;
font-family: monospace;
text-align: right;
}
@ -221,7 +221,6 @@ function isSorted(values) {
function textSort(v) { return v.toLowerCase(); }
function numSort(v) { return -parseInt(v); }
function floatSort(v) { return -parseFloat(v); }
function yesSort(v) { return v == "yes" ? 0 : 1; }
function reproSort(v) { return v == "C" ? 0 : v == "syz" ? 1 : 2; }
function patchedSort(v) { return v == "" ? -1 : parseInt(v); }