blob: 803642675e009aea9250e082a023377967e2f2bd [file] [log] [blame]
// Copyright 2022 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"
"sort"
"testing"
"time"
"github.com/google/syzkaller/dashboard/dashapi"
"github.com/google/syzkaller/pkg/email"
)
func TestBuildAssetLifetime(t *testing.T) {
c := NewCtx(t)
defer c.Close()
build := testBuild(1)
build.Manager = "test_manager"
// Embed one of the assets right away.
build.Assets = []dashapi.NewAsset{
{
Type: dashapi.KernelObject,
DownloadURL: "http://google.com/vmlinux",
},
}
c.client2.UploadBuild(build)
// Add one more build, so that the assets of the previous one could be deprecated.
c.advanceTime(time.Minute)
build2 := testBuild(2)
build2.Manager = "test_manager"
c.client2.UploadBuild(build2)
// "Upload" several more assets.
c.expectOK(c.client2.AddBuildAssets(&dashapi.AddBuildAssetsReq{
BuildID: build.ID,
Assets: []dashapi.NewAsset{
{
Type: dashapi.BootableDisk,
DownloadURL: "http://google.com/bootable_disk",
},
},
}))
c.expectOK(c.client2.AddBuildAssets(&dashapi.AddBuildAssetsReq{
BuildID: build.ID,
Assets: []dashapi.NewAsset{
{
Type: dashapi.HTMLCoverageReport,
DownloadURL: "http://google.com/coverage.html",
},
},
}))
crash := testCrash(build, 1)
crash.Maintainers = []string{`"Foo Bar" <foo@bar.com>`, `bar@foo.com`, `idont@want.EMAILS`}
c.client2.ReportCrash(crash)
// Test that the reporting email is correct.
msg := c.pollEmailBug()
sender, extBugID, err := email.RemoveAddrContext(msg.Sender)
c.expectOK(err)
_, dbCrash, dbBuild := c.loadBug(extBugID)
crashLogLink := externalLink(c.ctx, textCrashLog, dbCrash.Log)
kernelConfigLink := externalLink(c.ctx, textKernelConfig, dbBuild.KernelConfig)
c.expectEQ(sender, fromAddr(c.ctx))
to := c.config().Namespaces["test2"].Reporting[0].Config.(*EmailConfig).Email
c.expectEQ(msg.To, []string{to})
c.expectEQ(msg.Subject, crash.Title)
c.expectEQ(len(msg.Attachments), 0)
c.expectEQ(msg.Body, fmt.Sprintf(`Hello,
syzbot found the following issue on:
HEAD commit: 111111111111 kernel_commit_title1
git tree: repo1 branch1
console output: %[2]v
kernel config: %[3]v
dashboard link: https://testapp.appspot.com/bug?extid=%[1]v
compiler: compiler1
CC: [bar@foo.com foo@bar.com idont@want.EMAILS]
Unfortunately, I don't have any reproducer for this issue yet.
Downloadable assets:
disk image: http://google.com/bootable_disk
vmlinux: http://google.com/vmlinux
IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+%[1]v@testapp.appspotmail.com
report1
---
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.
syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.
If the report is already addressed, let syzbot know by replying with:
#syz fix: exact-commit-title
If you want to overwrite report's subsystems, reply with:
#syz set subsystems: new-subsystem
(See the list of subsystem names on the web dashboard)
If the report is a duplicate of another one, reply with:
#syz dup: exact-subject-of-another-report
If you want to undo deduplication, reply with:
#syz undup`,
extBugID, crashLogLink, kernelConfigLink))
c.checkURLContents(crashLogLink, crash.Log)
c.checkURLContents(kernelConfigLink, build.KernelConfig)
// We query the needed assets. We need all 3.
needed, err := c.client2.NeededAssetsList()
c.expectOK(err)
sort.Strings(needed.DownloadURLs)
allDownloadURLs := []string{
"http://google.com/bootable_disk",
"http://google.com/coverage.html",
"http://google.com/vmlinux",
}
c.expectEQ(needed.DownloadURLs, allDownloadURLs)
// Invalidate the bug.
c.client.updateBug(extBugID, dashapi.BugStatusInvalid, "")
_, err = c.GET("/cron/deprecate_assets")
c.expectOK(err)
// Query the needed assets once more, so far there should be no change.
needed, err = c.client2.NeededAssetsList()
c.expectOK(err)
sort.Strings(needed.DownloadURLs)
c.expectEQ(needed.DownloadURLs, allDownloadURLs)
// Skip one month and deprecate assets.
c.advanceTime(time.Hour * 24 * 31)
_, err = c.GET("/cron/deprecate_assets")
c.expectOK(err)
// Only the html asset should have persisted.
needed, err = c.client2.NeededAssetsList()
c.expectOK(err)
c.expectEQ(needed.DownloadURLs, []string{"http://google.com/coverage.html"})
}
func TestCoverReportDisplay(t *testing.T) {
c := NewCtx(t)
defer c.Close()
build := testBuild(1)
c.client.UploadBuild(build)
// Upload the second build to just make sure coverage reports are assigned per-manager.
c.client.UploadBuild(testBuild(2))
// We expect no coverage reports to be present.
uiManagers, err := loadManagers(c.ctx, AccessAdmin, "test1", nil)
c.expectOK(err)
c.expectEQ(len(uiManagers), 2)
c.expectEQ(uiManagers[0].CoverLink, "")
c.expectEQ(uiManagers[1].CoverLink, "")
// Upload an asset.
origHTMLAsset := "http://google.com/coverage0.html"
c.expectOK(c.client.AddBuildAssets(&dashapi.AddBuildAssetsReq{
BuildID: build.ID,
Assets: []dashapi.NewAsset{
{
Type: dashapi.HTMLCoverageReport,
DownloadURL: origHTMLAsset,
},
},
}))
uiManagers, err = loadManagers(c.ctx, AccessAdmin, "test1", nil)
c.expectOK(err)
c.expectEQ(len(uiManagers), 2)
c.expectEQ(uiManagers[0].CoverLink, origHTMLAsset)
c.expectEQ(uiManagers[1].CoverLink, "")
// Upload a newer coverage.
newHTMLAsset := "http://google.com/coverage1.html"
c.expectOK(c.client.AddBuildAssets(&dashapi.AddBuildAssetsReq{
BuildID: build.ID,
Assets: []dashapi.NewAsset{
{
Type: dashapi.HTMLCoverageReport,
DownloadURL: newHTMLAsset,
},
},
}))
uiManagers, err = loadManagers(c.ctx, AccessAdmin, "test1", nil)
c.expectOK(err)
c.expectEQ(len(uiManagers), 2)
c.expectEQ(uiManagers[0].CoverLink, newHTMLAsset)
c.expectEQ(uiManagers[1].CoverLink, "")
}
func TestCoverReportDeprecation(t *testing.T) {
c := NewCtx(t)
defer c.Close()
ensureNeeded := func(needed []string) {
_, err := c.GET("/cron/deprecate_assets")
c.expectOK(err)
neededResp, err := c.client.NeededAssetsList()
c.expectOK(err)
sort.Strings(neededResp.DownloadURLs)
sort.Strings(needed)
c.expectEQ(neededResp.DownloadURLs, needed)
}
build := testBuild(1)
c.client.UploadBuild(build)
uploadReport := func(url string) {
c.expectOK(c.client.AddBuildAssets(&dashapi.AddBuildAssetsReq{
BuildID: build.ID,
Assets: []dashapi.NewAsset{
{
Type: dashapi.HTMLCoverageReport,
DownloadURL: url,
},
},
}))
}
// Week 1. Saturday Jan 1st, 2000.
weekOneFirst := "http://google.com/coverage1_1.html"
uploadReport(weekOneFirst)
// Week 1. Sunday Jan 2nd, 2000.
weekOneSecond := "http://google.com/coverage1_2.html"
c.advanceTime(time.Hour * 24)
uploadReport(weekOneSecond)
ensureNeeded([]string{weekOneFirst, weekOneSecond})
// Week 2. Tuesday Jan 4nd, 2000.
weekTwoFirst := "http://google.com/coverage2_1.html"
c.advanceTime(time.Hour * 24 * 2)
uploadReport(weekTwoFirst)
ensureNeeded([]string{weekOneFirst, weekOneSecond, weekTwoFirst})
// Week 2. Thu Jan 6nd, 2000.
weekTwoSecond := "http://google.com/coverage2_2.html"
c.advanceTime(time.Hour * 24 * 2)
uploadReport(weekTwoSecond)
ensureNeeded([]string{weekOneFirst, weekOneSecond, weekTwoFirst, weekTwoSecond})
// Week 3. Monday Jan 10th, 2000.
weekThreeFirst := "http://google.com/coverage3_1.html"
c.advanceTime(time.Hour * 24 * 4)
uploadReport(weekThreeFirst)
ensureNeeded([]string{weekOneFirst, weekOneSecond, weekTwoFirst, weekTwoSecond, weekThreeFirst})
// Week 4. Monday Jan 17th, 2000.
weekFourFirst := "http://google.com/coverage4_1.html"
c.advanceTime(time.Hour * 24 * 7)
uploadReport(weekFourFirst)
t.Logf("embargo is over, time is %s", timeNow(c.ctx))
// Note that now that the two week deletion embargo has passed, the first asset
// begins to falls out.
ensureNeeded([]string{weekOneSecond, weekTwoFirst, weekTwoSecond, weekThreeFirst, weekFourFirst})
// Week 5. Monday Jan 24th, 2000.
c.advanceTime(time.Hour * 24 * 7)
ensureNeeded([]string{weekOneSecond, weekTwoSecond, weekThreeFirst, weekFourFirst})
// A year later.
c.advanceTime(time.Hour * 24 * 365)
ensureNeeded([]string{weekOneSecond, weekTwoSecond, weekThreeFirst, weekFourFirst})
}
func TestFreshBuildAssets(t *testing.T) {
c := NewCtx(t)
defer c.Close()
ensureNeeded := func(needed []string) {
_, err := c.GET("/cron/deprecate_assets")
c.expectOK(err)
neededResp, err := c.client.NeededAssetsList()
c.expectOK(err)
sort.Strings(neededResp.DownloadURLs)
sort.Strings(needed)
c.expectEQ(neededResp.DownloadURLs, needed)
}
build := testBuild(1)
build.Manager = "manager"
build.Assets = []dashapi.NewAsset{
{
Type: dashapi.KernelObject,
DownloadURL: "http://google.com/vmlinux",
},
}
c.client.UploadBuild(build)
// No crashes yet, but it's the latest build, so the assets must be preserved.
ensureNeeded([]string{"http://google.com/vmlinux"})
// Upload one more build for the same manager.
c.advanceTime(time.Minute)
build2 := testBuild(2)
build2.Manager = "manager"
build2.Assets = []dashapi.NewAsset{
{
Type: dashapi.KernelObject,
DownloadURL: "http://google.com/vmlinux2",
},
}
c.client.UploadBuild(build2)
// The assets of the previous build are reasonably new, so they must be kept.
ensureNeeded([]string{"http://google.com/vmlinux", "http://google.com/vmlinux2"})
// The assets of the first build must be deprecated now.
c.advanceTime(time.Hour * 24 * 14)
ensureNeeded([]string{"http://google.com/vmlinux2"})
// But even if a lot of time passes, but there are no new builds, the assets must stay.
c.advanceTime(time.Hour * 24 * 365)
ensureNeeded([]string{"http://google.com/vmlinux2"})
}
func TestCrashAssetLifetime(t *testing.T) {
c := NewCtx(t)
defer c.Close()
build := testBuild(1)
c.client2.UploadBuild(build)
crash := testCrash(build, 1)
crash.Maintainers = []string{`"Foo Bar" <foo@bar.com>`, `bar@foo.com`, `idont@want.EMAILS`}
crash.Assets = []dashapi.NewAsset{
{
Type: dashapi.MountInRepro,
DownloadURL: "http://google.com/disk_image",
},
{
Type: dashapi.MountInRepro,
DownloadURL: "http://google.com/disk_image2",
},
}
c.client2.ReportCrash(crash)
// Test that the reported email is correct.
msg := c.pollEmailBug()
sender, extBugID, err := email.RemoveAddrContext(msg.Sender)
c.expectOK(err)
_, dbCrash, dbBuild := c.loadBug(extBugID)
crashLogLink := externalLink(c.ctx, textCrashLog, dbCrash.Log)
kernelConfigLink := externalLink(c.ctx, textKernelConfig, dbBuild.KernelConfig)
c.expectEQ(sender, fromAddr(c.ctx))
to := c.config().Namespaces["test2"].Reporting[0].Config.(*EmailConfig).Email
c.expectEQ(msg.To, []string{to})
c.expectEQ(msg.Subject, crash.Title)
c.expectEQ(len(msg.Attachments), 0)
c.expectEQ(msg.Body, fmt.Sprintf(`Hello,
syzbot found the following issue on:
HEAD commit: 111111111111 kernel_commit_title1
git tree: repo1 branch1
console output: %[2]v
kernel config: %[3]v
dashboard link: https://testapp.appspot.com/bug?extid=%[1]v
compiler: compiler1
CC: [bar@foo.com foo@bar.com idont@want.EMAILS]
Unfortunately, I don't have any reproducer for this issue yet.
Downloadable assets:
mounted in repro #1: http://google.com/disk_image
mounted in repro #2: http://google.com/disk_image2
IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+%[1]v@testapp.appspotmail.com
report1
---
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.
syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.
If the report is already addressed, let syzbot know by replying with:
#syz fix: exact-commit-title
If you want to overwrite report's subsystems, reply with:
#syz set subsystems: new-subsystem
(See the list of subsystem names on the web dashboard)
If the report is a duplicate of another one, reply with:
#syz dup: exact-subject-of-another-report
If you want to undo deduplication, reply with:
#syz undup`,
extBugID, crashLogLink, kernelConfigLink))
c.checkURLContents(crashLogLink, crash.Log)
c.checkURLContents(kernelConfigLink, build.KernelConfig)
// We query the needed assets. We need all 2.
needed, err := c.client2.NeededAssetsList()
c.expectOK(err)
sort.Strings(needed.DownloadURLs)
allDownloadURLs := []string{
"http://google.com/disk_image",
"http://google.com/disk_image2",
}
c.expectEQ(needed.DownloadURLs, allDownloadURLs)
// Invalidate the bug.
c.client.updateBug(extBugID, dashapi.BugStatusInvalid, "")
_, err = c.GET("/cron/deprecate_assets")
c.expectOK(err)
// Query the needed assets once more, so far there should be no change.
needed, err = c.client2.NeededAssetsList()
c.expectOK(err)
sort.Strings(needed.DownloadURLs)
c.expectEQ(needed.DownloadURLs, allDownloadURLs)
// Skip one month and deprecate assets.
c.advanceTime(time.Hour * 24 * 31)
_, err = c.GET("/cron/deprecate_assets")
c.expectOK(err)
// Nothing should have been persisted.
needed, err = c.client2.NeededAssetsList()
c.expectOK(err)
c.expectEQ(needed.DownloadURLs, []string{})
}