blob: 644d58d3fde374ee838e6721487358e60b2d914d [file] [log] [blame] [edit]
// Copyright 2023 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.
package main
import (
"fmt"
"strings"
"testing"
"time"
"github.com/google/syzkaller/dashboard/dashapi"
"github.com/google/syzkaller/pkg/email"
"github.com/google/syzkaller/pkg/subsystem"
"github.com/stretchr/testify/assert"
)
const subsystemTestNs = "test1"
func TestSubsytemMaintainers(t *testing.T) {
c := NewCtx(t)
defer c.Close()
// This also indirectly tests getSubsystemService.
assert.ElementsMatch(t,
subsystemMaintainers(c.ctx, subsystemTestNs, "subsystemA"),
[]string{
"subsystemA@list.com", "subsystemA@person.com",
},
)
assert.ElementsMatch(t, subsystemMaintainers(c.ctx, subsystemTestNs, "does-not-exist"), []string{})
}
func TestPeriodicSubsystemRefresh(t *testing.T) {
c := NewCtx(t)
defer c.Close()
client := c.client
ns := subsystemTestNs
build := testBuild(1)
client.UploadBuild(build)
// Create a bug without any subsystems.
c.setSubsystems(ns, nil, 1)
crash := testCrash(build, 1)
crash.Title = "WARNING: abcd"
crash.GuiltyFiles = []string{"test.c"}
client.ReportCrash(crash)
rep := client.pollBug()
extID := rep.ID
// Initially there should be no subsystems.
expectLabels(t, client, extID)
// Update subsystems.
item := &subsystem.Subsystem{
Name: "first",
PathRules: []subsystem.PathRule{{IncludeRegexp: `test\.c`}},
}
// Keep revision the same.
c.setSubsystems(ns, []*subsystem.Subsystem{item}, 1)
// Refresh subsystems.
c.advanceTime(time.Hour)
_, err := c.AuthGET(AccessUser, "/cron/refresh_subsystems")
c.expectOK(err)
expectLabels(t, client, extID) // Not enough time has passed yet.
// Wait until the refresh period is over.
c.advanceTime(openBugsUpdateTime)
_, err = c.AuthGET(AccessUser, "/cron/refresh_subsystems")
c.expectOK(err)
expectLabels(t, client, extID, "subsystems:first")
}
func TestOpenBugRevRefresh(t *testing.T) {
c := NewCtx(t)
defer c.Close()
client := c.client
ns := subsystemTestNs
build := testBuild(1)
client.UploadBuild(build)
// Create a bug without any subsystems.
c.setSubsystems(ns, nil, 0)
crash := testCrash(build, 1)
crash.GuiltyFiles = []string{"test.c"}
client.ReportCrash(crash)
rep := client.pollBug()
extID := rep.ID
// Initially there should be no subsystems.
expectLabels(t, client, extID)
// Update subsystems.
c.advanceTime(time.Hour)
item := &subsystem.Subsystem{
Name: "first",
PathRules: []subsystem.PathRule{{IncludeRegexp: `test\.c`}},
}
// Update the revision number as well.
c.setSubsystems(ns, []*subsystem.Subsystem{item}, 1)
// Refresh subsystems.
_, err := c.AuthGET(AccessUser, "/cron/refresh_subsystems")
c.expectOK(err)
expectLabels(t, client, extID, "subsystems:first")
}
func TestClosedBugSubsystemRefresh(t *testing.T) {
c := NewCtx(t)
defer c.Close()
client := c.client
ns := subsystemTestNs
build := testBuild(1)
client.UploadBuild(build)
// Create a bug without any subsystems.
c.setSubsystems(ns, nil, 0)
crash := testCrash(build, 1)
crash.GuiltyFiles = []string{"test.c"}
client.ReportCrash(crash)
rep := client.pollBug()
extID := rep.ID
// "Fix" the bug.
reply, _ := c.client.ReportingUpdate(&dashapi.BugUpdate{
ID: rep.ID,
Status: dashapi.BugStatusOpen,
FixCommits: []string{"foo: fix the crash"},
})
c.expectEQ(reply.OK, true)
build2 := testBuild(2)
build2.Manager = build.Manager
build2.Commits = []string{"foo: fix the crash"}
client.UploadBuild(build2)
client.pollNotifs(0)
bug, _, _ := c.loadBug(rep.ID)
c.expectEQ(bug.Status, BugStatusFixed)
// Initially there should be no subsystems.
expectLabels(t, client, extID)
// Update subsystems.
c.advanceTime(time.Hour)
item := &subsystem.Subsystem{
Name: "first",
PathRules: []subsystem.PathRule{{IncludeRegexp: `test\.c`}},
}
c.setSubsystems(ns, []*subsystem.Subsystem{item}, 1)
// Refresh subsystems.
c.advanceTime(time.Hour)
_, err := c.AuthGET(AccessUser, "/cron/refresh_subsystems")
c.expectOK(err)
expectLabels(t, client, extID, "subsystems:first")
}
func TestInvalidBugSubsystemRefresh(t *testing.T) {
c := NewCtx(t)
defer c.Close()
client := c.client
build := testBuild(1)
client.UploadBuild(build)
// Create a bug without any subsystems.
c.setSubsystems(subsystemTestNs, nil, 0)
crash := testCrash(build, 1)
crash.GuiltyFiles = []string{"test.c"}
client.ReportCrash(crash)
rep := client.pollBug()
extID := rep.ID
// Invalidate the bug.
reply, _ := c.client.ReportingUpdate(&dashapi.BugUpdate{
ID: rep.ID,
Status: dashapi.BugStatusInvalid,
})
c.expectEQ(reply.OK, true)
bug, _, _ := c.loadBug(rep.ID)
c.expectEQ(bug.Status, BugStatusInvalid)
// Initially there should be no subsystems.
expectLabels(t, client, extID)
// Update subsystems.
c.advanceTime(time.Hour)
item := &subsystem.Subsystem{
Name: "first",
PathRules: []subsystem.PathRule{{IncludeRegexp: `test\.c`}},
}
c.setSubsystems(subsystemTestNs, []*subsystem.Subsystem{item}, 1)
// Refresh subsystems.
c.advanceTime(time.Hour)
_, err := c.AuthGET(AccessUser, "/cron/refresh_subsystems")
c.expectOK(err)
expectLabels(t, client, extID, "subsystems:first")
}
func TestUserSubsystemsRefresh(t *testing.T) {
c := NewCtx(t)
defer c.Close()
client := c.makeClient(clientPublicEmail, keyPublicEmail, true)
ns := "access-public-email"
build := testBuild(1)
client.UploadBuild(build)
// Create a bug with subsystemA.
crash := testCrash(build, 1)
crash.GuiltyFiles = []string{"a.c"}
client.ReportCrash(crash)
c.incomingEmail(c.pollEmailBug().Sender, "#syz upstream\n")
sender := c.pollEmailBug().Sender
_, extID, err := email.RemoveAddrContext(sender)
c.expectOK(err)
// Make sure we've set the right subsystem.
expectLabels(t, client, extID, "subsystems:subsystemA")
// Manually set another subsystem.
c.incomingEmail(sender, "#syz set subsystems: subsystemB\n",
EmailOptFrom("test@requester.com"))
expectLabels(t, client, extID, "subsystems:subsystemB")
// Refresh subsystems.
c.advanceTime(openBugsUpdateTime + time.Hour)
_, err = c.AuthGET(AccessUser, "/cron/refresh_subsystems")
c.expectOK(err)
// The subsystems must stay the same.
expectLabels(t, client, extID, "subsystems:subsystemB")
// Bump the subsystem revision and refresh subsystems.
c.setSubsystems(ns, testSubsystems, 2)
c.advanceTime(time.Hour)
_, err = c.AuthGET(AccessUser, "/cron/refresh_subsystems")
c.expectOK(err)
// The subsystem must still stay the same.
expectLabels(t, client, extID, "subsystems:subsystemB")
}
func TestNoUserSubsystemOverwrite(t *testing.T) {
c := NewCtx(t)
defer c.Close()
client := c.makeClient(clientPublicEmail, keyPublicEmail, true)
build := testBuild(1)
client.UploadBuild(build)
// Create a bug without subsystems.
crash := testCrash(build, 1)
client.ReportCrash(crash)
c.incomingEmail(c.pollEmailBug().Sender, "#syz upstream\n")
sender := c.pollEmailBug().Sender
_, extID, err := email.RemoveAddrContext(sender)
c.expectOK(err)
// Manually set subsystemA.
c.incomingEmail(sender, "#syz set subsystems: subsystemA\n",
EmailOptFrom("test@requester.com"))
expectLabels(t, client, extID, "subsystems:subsystemA")
// Now we find a reproducer that indicates it's subsystemB.
crash.GuiltyFiles = []string{"b.c"}
crash.ReproOpts = []byte("some opts")
crash.ReproSyz = []byte("getpid()")
client.ReportCrash(crash)
c.pollEmailBug()
// Make sure subsystem stayed unchanged.
expectLabels(t, client, extID, "subsystems:subsystemA")
}
// nolint: goconst
func TestPeriodicSubsystemReminders(t *testing.T) {
c := NewCtx(t)
defer c.Close()
client := c.makeClient(clientSubsystemRemind, keySubsystemRemind, true)
build := testBuild(1)
client.UploadBuild(build)
bugToExtID := map[string]string{}
// WARNING: a first (3 crashes)
aFirst := testCrash(build, 1)
aFirst.Title = `WARNING: a first`
aFirst.GuiltyFiles = []string{"a.c"}
client.ReportCrash(aFirst)
bugToExtID[aFirst.Title] = client.pollEmailExtID()
for i := 0; i < 2; i++ {
client.ReportCrash(aFirst)
c.advanceTime(time.Hour)
}
// WARNING: a second (1 crash)
aSecond := testCrash(build, 1)
aSecond.Title = `WARNING: a second`
aSecond.GuiltyFiles = []string{"a.c"}
client.ReportCrash(aSecond)
bugToExtID[aSecond.Title] = client.pollEmailExtID()
c.advanceTime(time.Hour)
// WARNING: b first (1 crashes)
bFirst := testCrash(build, 1)
bFirst.Title = `WARNING: b first`
bFirst.GuiltyFiles = []string{"b.c"}
client.ReportCrash(bFirst)
bugToExtID[bFirst.Title] = client.pollEmailExtID()
c.advanceTime(time.Hour)
// WARNING: b first (5 crashes)
bSecond := testCrash(build, 1)
bSecond.Title = `WARNING: b second`
bSecond.GuiltyFiles = []string{"b.c"}
client.ReportCrash(bSecond)
bugToExtID[bSecond.Title] = client.pollEmailExtID()
for i := 0; i < 4; i++ {
client.ReportCrash(bSecond)
c.advanceTime(time.Hour)
}
// Report bugs once more to pretend they're still valid.
c.advanceTime(time.Hour * 24 * 14)
client.ReportCrash(aFirst)
client.ReportCrash(bFirst)
client.ReportCrash(aSecond)
client.ReportCrash(bSecond)
c.advanceTime(time.Hour)
// Make sure we don't report crashes at other reporting stages.
crash := testCrash(build, 1)
crash.Title = `WARNING: a third, keep in moderation` // see the config in app_test.go
crash.GuiltyFiles = []string{"a.c"}
client.ReportCrash(crash)
client.pollBug()
c.advanceTime(time.Hour)
_, err := c.GET("/cron/subsystem_reports")
c.expectOK(err)
// Expect the reminder for subsystemA.
reply := client.pollEmailBug()
c.expectEQ(reply.Subject, "[moderation] Monthly subsystemA report (Jan 2000)")
c.expectEQ(reply.To, []string{"moderation@syzkaller.com"})
c.expectEQ(reply.Cc, []string(nil))
c.expectEQ(reply.Body, fmt.Sprintf(`Hello subsystemA maintainers/developers,
This is a 30-day syzbot report for the subsystemA subsystem.
All related reports/information can be found at:
https://testapp.appspot.com/subsystem-reminders/s/subsystemA
During the period, 2 new issues were detected and 0 were fixed.
In total, 2 issues are still open.
Some of the still happening issues:
Ref Crashes Repro Title
<1> 4 No WARNING: a first
https://testapp.appspot.com/bug?extid=%[1]v
<2> 2 No WARNING: a second
https://testapp.appspot.com/bug?extid=%[2]v
The report will be sent to: [subsystemA@list.com subsystemA@person.com].
---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.
To disable reminders for individual bugs, reply with the following command:
#syz set <Ref> no-reminders
To change bug's subsystems, reply with:
#syz set <Ref> subsystems: new-subsystem
If the report looks fine to you, reply with:
#syz upstream
To regenerate the report, reply with:
#syz regenerate
You may send multiple commands in a single email message.
`, bugToExtID["WARNING: a first"], bugToExtID["WARNING: a second"]))
// Expect the reminder for subsystemB.
reply = client.pollEmailBug()
c.expectEQ(reply.Subject, "[moderation] Monthly subsystemB report (Jan 2000)")
c.expectEQ(reply.To, []string{"moderation@syzkaller.com"})
c.expectEQ(reply.Cc, []string(nil))
c.expectEQ(reply.Body, fmt.Sprintf(`Hello subsystemB maintainers/developers,
This is a 30-day syzbot report for the subsystemB subsystem.
All related reports/information can be found at:
https://testapp.appspot.com/subsystem-reminders/s/subsystemB
During the period, 2 new issues were detected and 0 were fixed.
In total, 2 issues are still open.
Some of the still happening issues:
Ref Crashes Repro Title
<1> 6 No WARNING: b second
https://testapp.appspot.com/bug?extid=%[1]v
<2> 2 No WARNING: b first
https://testapp.appspot.com/bug?extid=%[2]v
The report will be sent to: [subsystemB@list.com subsystemB@person.com].
---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.
To disable reminders for individual bugs, reply with the following command:
#syz set <Ref> no-reminders
To change bug's subsystems, reply with:
#syz set <Ref> subsystems: new-subsystem
If the report looks fine to you, reply with:
#syz upstream
To regenerate the report, reply with:
#syz regenerate
You may send multiple commands in a single email message.
`, bugToExtID["WARNING: b second"], bugToExtID["WARNING: b first"]))
// Wait the next pair of reminders.
c.advanceTime(time.Hour * 24 * 31)
_, err = c.GET("/cron/subsystem_reports")
c.expectOK(err)
}
func TestSubsystemRemindersModeration(t *testing.T) {
c := NewCtx(t)
defer c.Close()
client := c.makeClient(clientSubsystemRemind, keySubsystemRemind, true)
build := testBuild(1)
client.UploadBuild(build)
bugToExtID := map[string]string{}
aFirst := testCrash(build, 1)
aFirst.Title = `WARNING: a first`
aFirst.GuiltyFiles = []string{"a.c"}
client.ReportCrash(aFirst)
bugToExtID[aFirst.Title] = client.pollEmailExtID()
c.advanceTime(time.Hour)
aSecond := testCrash(build, 1)
aSecond.Title = `WARNING: a second`
aSecond.GuiltyFiles = []string{"a.c"}
client.ReportCrash(aSecond)
bugToExtID[aSecond.Title] = client.pollEmailExtID()
c.advanceTime(time.Hour)
// Report them again.
c.advanceTime(time.Hour * 24 * 14)
client.ReportCrash(aFirst)
client.ReportCrash(aSecond)
_, err := c.GET("/cron/subsystem_reports")
c.expectOK(err)
// Expect the reminder for subsystemA.
replyA := client.pollEmailBug()
c.expectEQ(replyA.Subject, "[moderation] Monthly subsystemA report (Jan 2000)")
// Moderate the subsystemA list.
c.advanceTime(time.Hour)
c.incomingEmail(replyA.Sender, "#syz upstream\n")
// Also emulate the second email that would come from the mailing list.
// The email should be silently ignored.
c.incomingEmail(replyA.Sender, "#syz upstream\n",
EmailOptFrom("moderation@syzkaller.com"), EmailOptOrigFrom("user@user.com"))
// Expect the normal report.
reply := client.pollEmailBug()
c.expectEQ(reply.Subject, "[syzbot] Monthly subsystemA report (Jan 2000)")
c.expectEQ(reply.To, []string{"bugs@syzkaller.com", "subsystemA@list.com", "subsystemA@person.com"})
c.expectEQ(reply.Cc, []string(nil))
c.expectEQ(reply.Body, fmt.Sprintf(`Hello subsystemA maintainers/developers,
This is a 30-day syzbot report for the subsystemA subsystem.
All related reports/information can be found at:
https://testapp.appspot.com/subsystem-reminders/s/subsystemA
During the period, 2 new issues were detected and 0 were fixed.
In total, 2 issues are still open.
Some of the still happening issues:
Ref Crashes Repro Title
<1> 2 No WARNING: a first
https://testapp.appspot.com/bug?extid=%[1]v
<2> 2 No WARNING: a second
https://testapp.appspot.com/bug?extid=%[2]v
---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.
To disable reminders for individual bugs, reply with the following command:
#syz set <Ref> no-reminders
To change bug's subsystems, reply with:
#syz set <Ref> subsystems: new-subsystem
You may send multiple commands in a single email message.
`, bugToExtID["WARNING: a first"], bugToExtID["WARNING: a second"]))
}
func TestSubsystemReportGeneration(t *testing.T) {
c := NewCtx(t)
defer c.Close()
client := c.makeClient(clientSubsystemRemind, keySubsystemRemind, true)
build := testBuild(1)
client.UploadBuild(build)
bugToExtID := map[string]string{}
// This crash will be too old.
crash := testCrash(build, 1)
crash.Title = `WARNING: old crash`
crash.GuiltyFiles = []string{"a.c"}
client.ReportCrash(crash)
client.pollEmailBug()
c.advanceTime(time.Hour * 24 * 40)
// Emulate one fixed bug.
aFixed := testCrash(build, 1)
aFixed.Title = `WARNING: fixed bug`
aFixed.GuiltyFiles = []string{"a.c"}
client.ReportCrash(aFixed)
bugToExtID[aFixed.Title] = client.pollEmailExtID()
c.advanceTime(time.Hour)
updReply, _ := client.ReportingUpdate(&dashapi.BugUpdate{
ID: bugToExtID[aFixed.Title],
Status: dashapi.BugStatusOpen,
FixCommits: []string{"foo: fix1"},
})
c.expectEQ(updReply.OK, true)
c.expectOK(client.UploadCommits([]dashapi.Commit{
{Hash: "hash1", Title: "foo: fix1", Date: timeNow(c.ctx)},
}))
allCrashes := []*dashapi.Crash{}
// Report 4 crashes with a reproducer.
var biggestReproCrash *dashapi.Crash
for i := 2; i <= 5; i++ {
crash := testCrash(build, 1)
crash.Title = fmt.Sprintf(`WARNING: has repro %d`, i+1)
crash.GuiltyFiles = []string{"a.c"}
client.ReportCrash(crash)
bugToExtID[crash.Title] = client.pollEmailExtID()
c.advanceTime(time.Hour)
crash.ReproOpts = []byte("some opts")
crash.ReproSyz = []byte("getpid()")
client.ReportCrash(crash)
client.pollEmailBug()
c.advanceTime(time.Hour)
for j := 3; j <= i; j++ {
client.ReportCrash(crash)
c.advanceTime(time.Hour)
}
allCrashes = append(allCrashes, crash)
biggestReproCrash = crash
}
// Report 5 crashes without a reproducer.
for i := 1; i <= 5; i++ {
crash := testCrash(build, 1)
crash.Title = fmt.Sprintf(`WARNING: no repro %d`, i+1)
crash.GuiltyFiles = []string{"a.c"}
client.ReportCrash(crash)
bugToExtID[crash.Title] = client.pollEmailExtID()
c.advanceTime(time.Hour)
for j := 2; j <= i; j++ {
client.ReportCrash(crash)
c.advanceTime(time.Hour)
}
allCrashes = append(allCrashes, crash)
}
c.advanceTime(time.Hour * 24 * 14)
for _, crash := range allCrashes {
client.ReportCrash(crash)
c.advanceTime(time.Hour)
}
// Now query the report.
_, err := c.GET("/cron/subsystem_reports")
c.expectOK(err)
reply := client.pollEmailBug()
c.expectEQ(reply.Subject, "[moderation] Monthly subsystemA report (Feb 2000)")
c.expectEQ(reply.To, []string{"moderation@syzkaller.com"})
c.expectEQ(reply.Cc, []string(nil))
c.expectEQ(reply.Body, fmt.Sprintf(`Hello subsystemA maintainers/developers,
This is a 30-day syzbot report for the subsystemA subsystem.
All related reports/information can be found at:
https://testapp.appspot.com/subsystem-reminders/s/subsystemA
During the period, 9 new issues were detected and 1 were fixed.
In total, 10 issues are still open and 1 has been fixed so far.
Some of the still happening issues:
Ref Crashes Repro Title
<1> 6 Yes WARNING: has repro 6
https://testapp.appspot.com/bug?extid=%[1]v
<2> 6 No WARNING: no repro 6
https://testapp.appspot.com/bug?extid=%[2]v
<3> 5 Yes WARNING: has repro 5
https://testapp.appspot.com/bug?extid=%[3]v
<4> 5 No WARNING: no repro 5
https://testapp.appspot.com/bug?extid=%[4]v
<5> 4 Yes WARNING: has repro 4
https://testapp.appspot.com/bug?extid=%[5]v
<6> 3 Yes WARNING: has repro 3
https://testapp.appspot.com/bug?extid=%[6]v
The report will be sent to: [subsystemA@list.com subsystemA@person.com].
---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.
To disable reminders for individual bugs, reply with the following command:
#syz set <Ref> no-reminders
To change bug's subsystems, reply with:
#syz set <Ref> subsystems: new-subsystem
If the report looks fine to you, reply with:
#syz upstream
To regenerate the report, reply with:
#syz regenerate
You may send multiple commands in a single email message.
`,
bugToExtID["WARNING: has repro 6"],
bugToExtID["WARNING: no repro 6"],
bugToExtID["WARNING: has repro 5"],
bugToExtID["WARNING: no repro 5"],
bugToExtID["WARNING: has repro 4"],
bugToExtID["WARNING: has repro 3"],
))
// Add one more crash and regenerate.
client.ReportCrash(biggestReproCrash)
c.advanceTime(time.Hour)
c.incomingEmail(reply.Sender, "#syz regenerate\n")
c.advanceTime(time.Hour)
_, err = c.GET("/cron/subsystem_reports")
c.expectOK(err)
secondReply := client.pollEmailBug()
c.expectEQ(secondReply.Subject, "[moderation] Monthly subsystemA report (Feb 2000)")
c.expectNE(reply.Sender, secondReply.Sender)
c.expectTrue(strings.Contains(secondReply.Body, `7 Yes WARNING: has repro 6`))
}
func TestSubsystemRemindersNoReport(t *testing.T) {
c := NewCtx(t)
defer c.Close()
client := c.makeClient(clientSubsystemRemind, keySubsystemRemind, true)
build := testBuild(1)
client.UploadBuild(build)
cFirst := testCrash(build, 1)
cFirst.Title = `WARNING: c first`
cFirst.GuiltyFiles = []string{"c.c"}
client.ReportCrash(cFirst)
client.pollEmailBug()
c.advanceTime(time.Hour)
cSecond := testCrash(build, 1)
cSecond.Title = `WARNING: c second`
cSecond.GuiltyFiles = []string{"c.c"}
client.ReportCrash(cSecond)
client.pollEmailBug()
c.advanceTime(time.Hour)
// Report them again.
c.advanceTime(time.Hour * 24 * 14)
client.ReportCrash(cFirst)
client.ReportCrash(cSecond)
_, err := c.GET("/cron/subsystem_reports")
c.expectOK(err)
// Expect no reminders for subsystemC.
client.expectNoEmail()
}
// nolint: goconst
func TestNoRemindersWithDiscussions(t *testing.T) {
c := NewCtx(t)
defer c.Close()
client := c.makeClient(clientSubsystemRemind, keySubsystemRemind, true)
build := testBuild(1)
client.UploadBuild(build)
bugToExtID := map[string]string{}
// WARNING: a first
aFirst := testCrash(build, 1)
aFirst.Title = `WARNING: a first`
aFirst.GuiltyFiles = []string{"a.c"}
client.ReportCrash(aFirst)
bugToExtID[aFirst.Title] = client.pollEmailExtID()
c.advanceTime(time.Hour)
// WARNING: a second (1 crash)
aSecond := testCrash(build, 1)
aSecond.Title = `WARNING: a second`
aSecond.GuiltyFiles = []string{"a.c"}
client.ReportCrash(aSecond)
bugToExtID[aSecond.Title] = client.pollEmailExtID()
c.advanceTime(time.Hour)
// WARNING: a third (1 crash)
aThird := testCrash(build, 1)
aThird.Title = `WARNING: a third`
aThird.GuiltyFiles = []string{"a.c"}
client.ReportCrash(aThird)
bugToExtID[aThird.Title] = client.pollEmailExtID()
c.advanceTime(time.Hour)
// Report bugs once more to pretend they're still valid.
c.advanceTime(time.Hour * 24 * 10)
client.ReportCrash(aFirst)
client.ReportCrash(aSecond)
client.ReportCrash(aThird)
// Add a recent discussion to the second bug.
c.expectOK(client.SaveDiscussion(&dashapi.SaveDiscussionReq{
Discussion: &dashapi.Discussion{
ID: "123",
Source: dashapi.DiscussionLore,
Type: dashapi.DiscussionReport,
Subject: "Some discussion",
BugIDs: []string{bugToExtID[aSecond.Title]},
Messages: []dashapi.DiscussionMessage{
{
ID: "123",
External: true,
Time: timeNow(c.ctx),
},
},
},
}))
c.advanceTime(time.Hour)
_, err := c.GET("/cron/subsystem_reports")
c.expectOK(err)
reply := client.pollEmailBug()
// Verify that the second bug is not present.
c.expectEQ(reply.Body, fmt.Sprintf(`Hello subsystemA maintainers/developers,
This is a 30-day syzbot report for the subsystemA subsystem.
All related reports/information can be found at:
https://testapp.appspot.com/subsystem-reminders/s/subsystemA
During the period, 3 new issues were detected and 0 were fixed.
In total, 3 issues are still open.
Some of the still happening issues:
Ref Crashes Repro Title
<1> 2 No WARNING: a first
https://testapp.appspot.com/bug?extid=%[1]v
<2> 2 No WARNING: a third
https://testapp.appspot.com/bug?extid=%[2]v
The report will be sent to: [subsystemA@list.com subsystemA@person.com].
---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.
To disable reminders for individual bugs, reply with the following command:
#syz set <Ref> no-reminders
To change bug's subsystems, reply with:
#syz set <Ref> subsystems: new-subsystem
If the report looks fine to you, reply with:
#syz upstream
To regenerate the report, reply with:
#syz regenerate
You may send multiple commands in a single email message.
`, bugToExtID["WARNING: a first"], bugToExtID["WARNING: a third"]))
}
// nolint: goconst
func TestSkipSubsystemReminders(t *testing.T) {
c := NewCtx(t)
defer c.Close()
client := c.makeClient(clientSubsystemRemind, keySubsystemRemind, true)
build := testBuild(1)
client.UploadBuild(build)
bugToExtID := map[string]string{}
// WARNING: a first
aFirst := testCrash(build, 1)
aFirst.Title = `WARNING: a first`
aFirst.GuiltyFiles = []string{"a.c"}
client.ReportCrash(aFirst)
bugToExtID[aFirst.Title] = client.pollEmailExtID()
c.advanceTime(time.Hour)
// WARNING: a second (1 crash)
aSecond := testCrash(build, 1)
aSecond.Title = `WARNING: a second`
aSecond.GuiltyFiles = []string{"a.c"}
client.ReportCrash(aSecond)
bugToExtID[aSecond.Title] = client.pollEmailExtID()
c.advanceTime(time.Hour)
// WARNING: a third (1 crash)
aThird := testCrash(build, 1)
aThird.Title = `WARNING: a third`
aThird.GuiltyFiles = []string{"a.c"}
client.ReportCrash(aThird)
bugToExtID[aThird.Title] = client.pollEmailExtID()
c.advanceTime(time.Hour)
// WARNING: a fourth (1 crash)
aFourth := testCrash(build, 1)
aFourth.Title = `WARNING: a fourth`
aFourth.GuiltyFiles = []string{"a.c"}
client.ReportCrash(aFourth)
bugToExtID[aFourth.Title] = client.pollEmailExtID()
c.advanceTime(time.Hour)
// Report bugs once more to pretend they're still valid.
c.advanceTime(time.Hour * 24 * 14)
client.ReportCrash(aFirst)
client.ReportCrash(aSecond)
client.ReportCrash(aThird)
client.ReportCrash(aFourth)
c.advanceTime(time.Hour)
_, err := c.GET("/cron/subsystem_reports")
c.expectOK(err)
// Expect the reminder for subsystemA.
reply := client.pollEmailBug()
c.expectEQ(reply.Subject, "[moderation] Monthly subsystemA report (Jan 2000)")
c.expectEQ(reply.To, []string{"moderation@syzkaller.com"})
c.expectEQ(reply.Cc, []string(nil))
c.expectEQ(reply.Body, fmt.Sprintf(`Hello subsystemA maintainers/developers,
This is a 30-day syzbot report for the subsystemA subsystem.
All related reports/information can be found at:
https://testapp.appspot.com/subsystem-reminders/s/subsystemA
During the period, 4 new issues were detected and 0 were fixed.
In total, 4 issues are still open.
Some of the still happening issues:
Ref Crashes Repro Title
<1> 2 No WARNING: a first
https://testapp.appspot.com/bug?extid=%[1]v
<2> 2 No WARNING: a fourth
https://testapp.appspot.com/bug?extid=%[4]v
<3> 2 No WARNING: a second
https://testapp.appspot.com/bug?extid=%[2]v
<4> 2 No WARNING: a third
https://testapp.appspot.com/bug?extid=%[3]v
The report will be sent to: [subsystemA@list.com subsystemA@person.com].
---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.
To disable reminders for individual bugs, reply with the following command:
#syz set <Ref> no-reminders
To change bug's subsystems, reply with:
#syz set <Ref> subsystems: new-subsystem
If the report looks fine to you, reply with:
#syz upstream
To regenerate the report, reply with:
#syz regenerate
You may send multiple commands in a single email message.
`, bugToExtID["WARNING: a first"], bugToExtID["WARNING: a second"],
bugToExtID["WARNING: a third"], bugToExtID["WARNING: a fourth"]))
c.incomingEmail(reply.Sender, `> In total, 4 issues are still open.
>
> Some of the still happening issues:
>
> Ref Crashes Repro Title
> <1> 2 No WARNING: a first
> https://testapp.appspot.com/bug?extid=%[1]v
> <2> 2 No WARNING: a fourth
> https://testapp.appspot.com/bug?extid=%[4]v
#syz set <2> no-reminders
> <3> 2 No WARNING: a second
> https://testapp.appspot.com/bug?extid=%[2]v
> <4> 2 No WARNING: a third
> https://testapp.appspot.com/bug?extid=%[3]v
#syz set <4> no-reminders
`)
// Prepare for the next monthly report.
c.advanceTime(time.Hour * 24 * 31)
client.ReportCrash(aFirst)
client.ReportCrash(aSecond)
client.ReportCrash(aThird)
client.ReportCrash(aFourth)
c.advanceTime(time.Hour)
_, err = c.GET("/cron/subsystem_reports")
c.expectOK(err)
reply = client.pollEmailBug()
c.expectEQ(reply.Body, fmt.Sprintf(`Hello subsystemA maintainers/developers,
This is a 30-day syzbot report for the subsystemA subsystem.
All related reports/information can be found at:
https://testapp.appspot.com/subsystem-reminders/s/subsystemA
During the period, 0 new issues were detected and 0 were fixed.
In total, 4 issues are still open.
Some of the still happening issues:
Ref Crashes Repro Title
<1> 3 No WARNING: a first
https://testapp.appspot.com/bug?extid=%[1]v
<2> 3 No WARNING: a second
https://testapp.appspot.com/bug?extid=%[2]v
The report will be sent to: [subsystemA@list.com subsystemA@person.com].
---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.
To disable reminders for individual bugs, reply with the following command:
#syz set <Ref> no-reminders
To change bug's subsystems, reply with:
#syz set <Ref> subsystems: new-subsystem
If the report looks fine to you, reply with:
#syz upstream
To regenerate the report, reply with:
#syz regenerate
You may send multiple commands in a single email message.
`, bugToExtID["WARNING: a first"], bugToExtID["WARNING: a second"]))
}
// nolint: goconst
func TestRemindersPriority(t *testing.T) {
c := NewCtx(t)
defer c.Close()
client := c.makeClient(clientSubsystemRemind, keySubsystemRemind, true)
cc := EmailOptCC([]string{"bugs@syzkaller.com", "default@maintainers.com"})
build := testBuild(1)
client.UploadBuild(build)
// WARNING: a first, low prio, has repro
aFirst := testCrash(build, 1)
aFirst.Title = `WARNING: a first`
aFirst.GuiltyFiles = []string{"a.c"}
aFirst.ReproOpts = []byte("some opts")
aFirst.ReproSyz = []byte("getpid()")
client.ReportCrash(aFirst)
sender, firstExtID := client.pollEmailAndExtID()
c.incomingEmail(sender, "#syz set prio: low\n",
EmailOptFrom("test@requester.com"), cc)
c.advanceTime(time.Hour)
// WARNING: a second, normal prio
aSecond := testCrash(build, 1)
aSecond.Title = `WARNING: a second`
aSecond.GuiltyFiles = []string{"a.c"}
client.ReportCrash(aSecond)
secondExtID := client.pollEmailExtID()
c.advanceTime(time.Hour)
// WARNING: a third, high prio
aThird := testCrash(build, 1)
aThird.Title = `WARNING: a third`
aThird.GuiltyFiles = []string{"a.c"}
client.ReportCrash(aThird)
sender, thirdExtID := client.pollEmailAndExtID()
c.incomingEmail(sender, "#syz set prio: high\n",
EmailOptFrom("test@requester.com"), cc)
c.advanceTime(time.Hour)
// Report bugs once more to pretend they're still valid.
c.advanceTime(time.Hour * 24 * 10)
client.ReportCrash(aFirst)
client.ReportCrash(aSecond)
client.ReportCrash(aThird)
_, err := c.GET("/cron/subsystem_reports")
c.expectOK(err)
reply := client.pollEmailBug()
// Verify that the second bug is not present.
c.expectEQ(reply.Body, fmt.Sprintf(`Hello subsystemA maintainers/developers,
This is a 30-day syzbot report for the subsystemA subsystem.
All related reports/information can be found at:
https://testapp.appspot.com/subsystem-reminders/s/subsystemA
During the period, 2 new issues were detected and 0 were fixed.
In total, 2 issues are still open.
There is also 1 low-priority issue.
Some of the still happening issues:
Ref Crashes Repro Title
<1> 2 No WARNING: a third
https://testapp.appspot.com/bug?extid=%[1]v
<2> 2 No WARNING: a second
https://testapp.appspot.com/bug?extid=%[2]v
The report will be sent to: [subsystemA@list.com subsystemA@person.com].
---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.
To disable reminders for individual bugs, reply with the following command:
#syz set <Ref> no-reminders
To change bug's subsystems, reply with:
#syz set <Ref> subsystems: new-subsystem
If the report looks fine to you, reply with:
#syz upstream
To regenerate the report, reply with:
#syz regenerate
You may send multiple commands in a single email message.
`, thirdExtID, secondExtID, firstExtID))
}