blob: 093c6a73ed9ddc77390d82f03869f918745efb7e [file] [log] [blame]
// Copyright 2019 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
// +build aetest
package dash
import (
"strings"
"testing"
"time"
"github.com/google/syzkaller/dashboard/dashapi"
)
func TestEmailNotifUpstreamEmbargo(t *testing.T) {
c := NewCtx(t)
defer c.Close()
build := testBuild(1)
c.client2.UploadBuild(build)
crash := testCrash(build, 1)
c.client2.ReportCrash(crash)
report := c.pollEmailBug()
c.expectEQ(report.To, []string{"test@syzkaller.com"})
// Upstreaming happens after 14 days, so no emails yet.
c.advanceTime(13 * 24 * time.Hour)
c.expectNoEmail()
// Now we should get notification about upstreaming and upstream report:
c.advanceTime(2 * 24 * time.Hour)
notifUpstream := c.pollEmailBug()
upstreamReport := c.pollEmailBug()
c.expectEQ(notifUpstream.Sender, report.Sender)
c.expectEQ(notifUpstream.Body, "Sending this report upstream.")
c.expectNE(upstreamReport.Sender, report.Sender)
c.expectEQ(upstreamReport.To, []string{"bugs@syzkaller.com", "default@maintainers.com"})
}
func TestEmailNotifUpstreamSkip(t *testing.T) {
c := NewCtx(t)
defer c.Close()
build := testBuild(1)
c.client2.UploadBuild(build)
crash := testCrash(build, 1)
crash.Title = "skip with repro 1"
c.client2.ReportCrash(crash)
report := c.pollEmailBug()
c.expectEQ(report.To, []string{"test@syzkaller.com"})
// No emails yet.
c.expectNoEmail()
// Now upload repro and it should be auto-upstreamed.
crash.ReproOpts = []byte("repro opts")
crash.ReproSyz = []byte("getpid()")
c.client2.ReportCrash(crash)
notifUpstream := c.pollEmailBug()
upstreamReport := c.pollEmailBug()
c.expectEQ(notifUpstream.Sender, report.Sender)
c.expectEQ(notifUpstream.Body, "Sending this report upstream.")
c.expectNE(upstreamReport.Sender, report.Sender)
c.expectEQ(upstreamReport.To, []string{"bugs@syzkaller.com", "default@maintainers.com"})
}
func TestEmailNotifBadFix(t *testing.T) {
c := NewCtx(t)
defer c.Close()
build := testBuild(1)
c.client2.UploadBuild(build)
crash := testCrash(build, 1)
c.client2.ReportCrash(crash)
report := c.pollEmailBug()
c.expectEQ(report.To, []string{"test@syzkaller.com"})
c.incomingEmail(report.Sender, "#syz fix some: commit title")
c.expectNoEmail()
// Notification about bad fixing commit should be send after 90 days.
c.advanceTime(50 * 24 * time.Hour)
c.expectNoEmail()
c.advanceTime(35 * 24 * time.Hour)
c.expectNoEmail()
c.advanceTime(10 * 24 * time.Hour)
notif := c.pollEmailBug()
if !strings.Contains(notif.Body, "This bug is marked as fixed by commit:\nsome: commit title\n") {
t.Fatalf("bad notification text: %q", notif.Body)
}
// No notifications for another 14 days, then another one.
c.advanceTime(13 * 24 * time.Hour)
c.expectNoEmail()
c.advanceTime(2 * 24 * time.Hour)
notif = c.pollEmailBug()
if !strings.Contains(notif.Body, "This bug is marked as fixed by commit:\nsome: commit title\n") {
t.Fatalf("bad notification text: %q", notif.Body)
}
}
func TestEmailNotifObsoleted(t *testing.T) {
c := NewCtx(t)
defer c.Close()
build := testBuild(1)
c.client2.UploadBuild(build)
crash := testCrash(build, 1)
crash.Maintainers = []string{"maintainer@syzkaller.com"}
c.client2.ReportCrash(crash)
report := c.pollEmailBug()
// Need to upstream so that it's not auto-upstreamed before obsoleted.
c.incomingEmail(report.Sender, "#syz upstream")
report = c.pollEmailBug()
// Add more people to bug CC.
c.incomingEmail(report.Sender, "wow", EmailOptCC([]string{"somebody@else.com"}))
// Bug is open, new crashes don't create new bug.
c.client2.ReportCrash(crash)
c.expectNoEmail()
// Not yet.
c.advanceTime(179 * 24 * time.Hour)
c.expectNoEmail()
// Now!
c.advanceTime(2 * 24 * time.Hour)
notif := c.pollEmailBug()
if !strings.Contains(notif.Body, "Auto-closing this bug as obsolete") {
t.Fatalf("bad notification text: %q", notif.Body)
}
c.expectEQ(notif.To, []string{"bugs@syzkaller.com", "default@sender.com", "somebody@else.com"})
// New crash must create new bug.
c.client2.ReportCrash(crash)
report = c.pollEmailBug()
c.expectEQ(report.Subject, "title1 (2)")
// Now the same, but for the last reporting (must have smaller CC list).
c.incomingEmail(report.Sender, "#syz upstream")
report = c.pollEmailBug()
c.incomingEmail(report.Sender, "#syz upstream")
report = c.pollEmailBug()
c.advanceTime(181 * 24 * time.Hour)
notif = c.pollEmailBug()
if !strings.Contains(notif.Body, "Auto-closing this bug as obsolete") {
t.Fatalf("bad notification text: %q", notif.Body)
}
c.expectEQ(notif.To, []string{"bugs2@syzkaller.com"})
}
func TestEmailNotifNotObsoleted(t *testing.T) {
c := NewCtx(t)
defer c.Close()
build := testBuild(1)
c.client2.UploadBuild(build)
// Crashes with repro are not auto-obsoleted.
crash1 := testCrash(build, 1)
crash1.ReproSyz = []byte("repro")
c.client2.ReportCrash(crash1)
report1 := c.pollEmailBug()
c.incomingEmail(report1.Sender, "#syz upstream")
report1 = c.pollEmailBug()
// This crash will get another crash later.
crash2 := testCrash(build, 2)
c.client2.ReportCrash(crash2)
report2 := c.pollEmailBug()
c.incomingEmail(report2.Sender, "#syz upstream")
report2 = c.pollEmailBug()
// This crash will get some activity later.
crash3 := testCrash(build, 3)
c.client2.ReportCrash(crash3)
report3 := c.pollEmailBug()
c.incomingEmail(report3.Sender, "#syz upstream")
report3 = c.pollEmailBug()
// This will be obsoleted (just to check that we have timings right).
c.advanceTime(24 * time.Hour)
crash4 := testCrash(build, 4)
c.client2.ReportCrash(crash4)
report4 := c.pollEmailBug()
c.incomingEmail(report4.Sender, "#syz upstream")
report4 = c.pollEmailBug()
c.advanceTime(179 * 24 * time.Hour)
c.expectNoEmail()
c.client2.ReportCrash(crash2)
c.incomingEmail(report3.Sender, "I am looking at it")
c.advanceTime(5 * 24 * time.Hour)
// Only crash 4 is obsoleted.
notif := c.pollEmailBug()
c.expectEQ(notif.Sender, report4.Sender)
c.expectNoEmail()
// Crash 3 also obsoleted after some time.
c.advanceTime(20 * 24 * time.Hour)
notif = c.pollEmailBug()
c.expectEQ(notif.Sender, report3.Sender)
}
func TestExtNotifUpstreamEmbargo(t *testing.T) {
c := NewCtx(t)
defer c.Close()
build1 := testBuild(1)
c.client.UploadBuild(build1)
crash1 := testCrash(build1, 1)
c.client.ReportCrash(crash1)
rep := c.client.pollBug()
// Specify fixing commit for the bug.
reply, _ := c.client.ReportingUpdate(&dashapi.BugUpdate{
ID: rep.ID,
Status: dashapi.BugStatusOpen,
})
c.expectEQ(reply.OK, true)
c.client.pollNotifs(0)
c.advanceTime(20 * 24 * time.Hour)
notif := c.client.pollNotifs(1)[0]
c.expectEQ(notif.ID, rep.ID)
c.expectEQ(notif.Type, dashapi.BugNotifUpstream)
}
func TestExtNotifUpstreamOnHold(t *testing.T) {
c := NewCtx(t)
defer c.Close()
build1 := testBuild(1)
c.client.UploadBuild(build1)
crash1 := testCrash(build1, 1)
c.client.ReportCrash(crash1)
rep := c.client.pollBug()
// Specify fixing commit for the bug.
reply, _ := c.client.ReportingUpdate(&dashapi.BugUpdate{
ID: rep.ID,
Status: dashapi.BugStatusOpen,
OnHold: true,
})
c.expectEQ(reply.OK, true)
c.advanceTime(20 * 24 * time.Hour)
c.client.pollNotifs(0)
}