aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZubin Mithra <zsm@chromium.org>2019-08-27 15:06:58 -0700
committerDmitry Vyukov <dvyukov@google.com>2019-08-28 15:34:44 -0700
commitcd626f3ba9f85027426d4fbed73e79e523e8e138 (patch)
tree7fa491ebe2f5cb428095e5e40fe9abc08da7d0e6
parent40203c152e000af463142886c75e346fbaaae7a7 (diff)
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.
-rw-r--r--dashboard/app/jobs.go11
-rw-r--r--dashboard/app/jobs_test.go64
2 files changed, 75 insertions, 0 deletions
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))
+}