From a02b5bcae215e4be280b1dac121948eaac1023e9 Mon Sep 17 00:00:00 2001 From: Zubin Mithra Date: Thu, 1 Aug 2019 15:19:59 -0700 Subject: 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 --- dashboard/app/bisect_test.go | 99 ++++++++++++++++++++++++++++++++++++++++++ dashboard/app/main.go | 73 ++++++++++++++++--------------- dashboard/app/static/common.js | 1 - dashboard/app/static/style.css | 4 +- dashboard/app/templates.html | 12 ++++- 5 files changed, 149 insertions(+), 40 deletions(-) (limited to 'dashboard') diff --git a/dashboard/app/bisect_test.go b/dashboard/app/bisect_test.go index 3650d65ed..d6f24fd50 100644 --- a/dashboard/app/bisect_test.go +++ b/dashboard/app/bisect_test.go @@ -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\" ", + // These must be filtered out: + "syzbot@testapp.appspotmail.com", + "syzbot+1234@testapp.appspotmail.com", + "\"syzbot\" ", + }, + 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\" ", + // These must be filtered out: + "syzbot@testapp.appspotmail.com", + "syzbot+1234@testapp.appspotmail.com", + "\"syzbot\" ", + }, + 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"))) +} diff --git a/dashboard/app/main.go b/dashboard/app/main.go index c1e47c6d0..cc73a88a8 100644 --- a/dashboard/app/main.go +++ b/dashboard/app/main.go @@ -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 } diff --git a/dashboard/app/static/common.js b/dashboard/app/static/common.js index f501d61da..6d03cf78d 100644 --- a/dashboard/app/static/common.js +++ b/dashboard/app/static/common.js @@ -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); } diff --git a/dashboard/app/static/style.css b/dashboard/app/static/style.css index ee5ef5fe1..da32203bc 100644 --- a/dashboard/app/static/style.css +++ b/dashboard/app/static/style.css @@ -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; } diff --git a/dashboard/app/templates.html b/dashboard/app/templates.html index 9ab19d680..335b87772 100644 --- a/dashboard/app/templates.html +++ b/dashboard/app/templates.html @@ -79,7 +79,7 @@ Use of this source code is governed by Apache 2 LICENSE that can be found in the {{end}} Title Repro - Bisected + Bisected Count Last Reported @@ -101,7 +101,15 @@ Use of this source code is governed by Apache 2 LICENSE that can be found in the {{if $.ShowNamespace}}{{$b.Namespace}}{{end}} {{$b.Title}} {{formatReproLevel $b.ReproLevel}} - {{if $b.BisectCause}}yes{{end}} + + {{if and $b.BisectCauseDone $b.BisectFixDone}} + cause+fix + {{else if $b.BisectCauseDone}} + cause + {{else if $b.BisectFixDone}} + fix + {{end}} + {{$b.NumCrashes}} {{formatLateness $.Now $b.LastTime}} -- cgit mrf-deployment