From cd626f3ba9f85027426d4fbed73e79e523e8e138 Mon Sep 17 00:00:00 2001 From: Zubin Mithra Date: Tue, 27 Aug 2019 15:06:58 -0700 Subject: dashboard/app: retry BisectFix if crash still occurs on ToT If a crash occurs on ToT when doing fix bisection, retry the job after 30 days. Add TestBisectFixRetry() to ensure that jobs are retried after 30 days if bisection results in crash on ToT. --- dashboard/app/jobs.go | 11 ++++++++ dashboard/app/jobs_test.go | 64 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/dashboard/app/jobs.go b/dashboard/app/jobs.go index 9f8dab51e..b8846cc59 100644 --- a/dashboard/app/jobs.go +++ b/dashboard/app/jobs.go @@ -507,6 +507,9 @@ func doneJob(c context.Context, req *dashapi.JobDoneReq) error { } else { bug.BisectFix = result } + // If the crash still occurs on HEAD, update the bug's LastTime so that it will be + // retried after 30 days. + crashesOnHead(c, bug, job, req, now) if _, err := db.Put(c, bugKey, bug); err != nil { return fmt.Errorf("failed to put bug: %v", err) } @@ -536,6 +539,14 @@ func doneJob(c context.Context, req *dashapi.JobDoneReq) error { return db.RunInTransaction(c, tx, &db.TransactionOptions{XG: true, Attempts: 30}) } +func crashesOnHead(c context.Context, bug *Bug, job *Job, req *dashapi.JobDoneReq, now time.Time) { + if job.Type != JobBisectFix || req.Error != nil || len(req.Commits) != 0 || len(req.CrashLog) == 0 { + return + } + bug.BisectFix = BisectNot + bug.LastTime = now +} + func pollCompletedJobs(c context.Context, typ string) ([]*dashapi.BugReport, error) { var jobs []*Job keys, err := db.NewQuery("Job"). diff --git a/dashboard/app/jobs_test.go b/dashboard/app/jobs_test.go index 54f2a679f..d52f93b30 100644 --- a/dashboard/app/jobs_test.go +++ b/dashboard/app/jobs_test.go @@ -405,3 +405,67 @@ func TestBisectFixJob(t *testing.T) { } c.client2.expectOK(c.client2.JobDone(done)) } + +// Test that JobBisectFix jobs are re-tried if crash occurs on ToT +func TestBisectFixRetry(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 + resp := c.client2.pollJobs(build.Manager) + c.client2.expectNE(resp.ID, "") + c.client2.expectEQ(resp.Type, dashapi.JobBisectCause) + done := &dashapi.JobDoneReq{ + ID: resp.ID, + Error: []byte("testBisectFixRetry:JobBisectCause"), + } + c.client2.expectOK(c.client2.JobDone(done)) + + // Advance time by 30 days and read out any notification emails + { + c.advanceTime(30 * 24 * time.Hour) + msg := c.client2.pollEmailBug() + c.expectEQ(msg.Subject, "title1") + c.expectTrue(strings.Contains(msg.Body, "Sending this report upstream.")) + + msg = c.client2.pollEmailBug() + c.expectEQ(msg.Subject, "title1") + c.expectTrue(strings.Contains(msg.Body, "syzbot found the following crash")) + } + + // Ensure that we get a JobBisectFix. We send back a crashlog, no error, no commits + resp = c.client2.pollJobs(build.Manager) + c.client2.expectNE(resp.ID, "") + c.client2.expectEQ(resp.Type, dashapi.JobBisectFix) + done = &dashapi.JobDoneReq{ + Build: dashapi.Build{ + ID: "build1", + }, + ID: resp.ID, + CrashLog: []byte("this is a crashlog"), + CrashReport: []byte("this is a crashreport"), + } + c.client2.expectOK(c.client2.JobDone(done)) + + // Advance time by 30 days. No notification emails + { + c.advanceTime(30 * 24 * time.Hour) + } + + // Ensure that we get a JobBisectFix retry + resp = c.client2.pollJobs(build.Manager) + c.client2.expectNE(resp.ID, "") + c.client2.expectEQ(resp.Type, dashapi.JobBisectFix) + done = &dashapi.JobDoneReq{ + ID: resp.ID, + Error: []byte("testBisectFixRetry:JobBisectFix"), + } + c.client2.expectOK(c.client2.JobDone(done)) +} -- cgit mrf-deployment