mirror of
https://github.com/reactos/syzkaller.git
synced 2025-02-23 13:10:44 +00:00
532 lines
16 KiB
Go
532 lines
16 KiB
Go
// Copyright 2017 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 (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/google/syzkaller/dashboard/dashapi"
|
|
)
|
|
|
|
// Basic scenario of marking a bug as fixed by a particular commit,
|
|
// discovering this commit on builder and marking the bug as ultimately fixed.
|
|
func TestFixBasic(t *testing.T) {
|
|
c := NewCtx(t)
|
|
defer c.Close()
|
|
|
|
build1 := testBuild(1)
|
|
c.client.UploadBuild(build1)
|
|
|
|
crash1 := testCrash(build1, 1)
|
|
c.client.ReportCrash(crash1)
|
|
|
|
builderPollResp, _ := c.client.BuilderPoll(build1.Manager)
|
|
c.expectEQ(len(builderPollResp.PendingCommits), 0)
|
|
|
|
needRepro, _ := c.client.NeedRepro(testCrashID(crash1))
|
|
c.expectEQ(needRepro, true)
|
|
|
|
rep := c.client.pollBug()
|
|
|
|
// Specify fixing commit for 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)
|
|
|
|
// Don't need repro once there are fixing commits.
|
|
needRepro, _ = c.client.NeedRepro(testCrashID(crash1))
|
|
c.expectEQ(needRepro, false)
|
|
|
|
// Check that the commit is now passed to builders.
|
|
builderPollResp, _ = c.client.BuilderPoll(build1.Manager)
|
|
c.expectEQ(len(builderPollResp.PendingCommits), 1)
|
|
c.expectEQ(builderPollResp.PendingCommits[0], "foo: fix the crash")
|
|
|
|
// Patches must not be reset on other actions.
|
|
c.client.updateBug(rep.ID, dashapi.BugStatusOpen, "")
|
|
|
|
// Upstream commands must fail if patches are already present.
|
|
// Right course of action is unclear in this situation,
|
|
// so this test merely documents the current behavior.
|
|
reply, _ = c.client.ReportingUpdate(&dashapi.BugUpdate{
|
|
ID: rep.ID,
|
|
Status: dashapi.BugStatusUpstream,
|
|
})
|
|
c.expectEQ(reply.OK, false)
|
|
|
|
c.client.ReportCrash(crash1)
|
|
c.client.pollBugs(0)
|
|
|
|
// Upload another build with the commit present.
|
|
build2 := testBuild(2)
|
|
build2.Manager = build1.Manager
|
|
build2.Commits = []string{"foo: fix the crash"}
|
|
c.client.UploadBuild(build2)
|
|
|
|
// Check that the commit is now not passed to this builder.
|
|
builderPollResp, _ = c.client.BuilderPoll(build1.Manager)
|
|
c.expectEQ(len(builderPollResp.PendingCommits), 0)
|
|
|
|
// Ensure that a new crash creates a new bug (the old one must be marked as fixed).
|
|
c.client.ReportCrash(crash1)
|
|
rep2 := c.client.pollBug()
|
|
c.expectEQ(rep2.Title, "title1 (2)")
|
|
|
|
// Regression test: previously upstreamming failed because the new bug had fixing commits.
|
|
c.client.ReportCrash(crash1)
|
|
c.client.updateBug(rep2.ID, dashapi.BugStatusUpstream, "")
|
|
}
|
|
|
|
// Test bug that is fixed by 2 commits.
|
|
func TestFixedByTwoCommits(t *testing.T) {
|
|
c := NewCtx(t)
|
|
defer c.Close()
|
|
|
|
build1 := testBuild(1)
|
|
c.client.UploadBuild(build1)
|
|
|
|
crash1 := testCrash(build1, 1)
|
|
c.client.ReportCrash(crash1)
|
|
|
|
builderPollResp, _ := c.client.BuilderPoll(build1.Manager)
|
|
c.expectEQ(len(builderPollResp.PendingCommits), 0)
|
|
|
|
rep := c.client.pollBug()
|
|
|
|
// Specify fixing commit for the bug.
|
|
reply, _ := c.client.ReportingUpdate(&dashapi.BugUpdate{
|
|
ID: rep.ID,
|
|
Status: dashapi.BugStatusOpen,
|
|
FixCommits: []string{"bar: prepare for fixing", "\"foo: fix the crash\""},
|
|
})
|
|
c.expectEQ(reply.OK, true)
|
|
|
|
// Check that the commit is now passed to builders.
|
|
builderPollResp, _ = c.client.BuilderPoll(build1.Manager)
|
|
c.expectEQ(len(builderPollResp.PendingCommits), 2)
|
|
c.expectEQ(builderPollResp.PendingCommits[0], "bar: prepare for fixing")
|
|
c.expectEQ(builderPollResp.PendingCommits[1], "foo: fix the crash")
|
|
|
|
// Upload another build with only one of the commits.
|
|
build2 := testBuild(2)
|
|
build2.Manager = build1.Manager
|
|
build2.Commits = []string{"bar: prepare for fixing"}
|
|
c.client.UploadBuild(build2)
|
|
|
|
// Check that it has not fixed the bug.
|
|
builderPollResp, _ = c.client.BuilderPoll(build1.Manager)
|
|
c.expectEQ(len(builderPollResp.PendingCommits), 2)
|
|
c.expectEQ(builderPollResp.PendingCommits[0], "bar: prepare for fixing")
|
|
c.expectEQ(builderPollResp.PendingCommits[1], "foo: fix the crash")
|
|
|
|
c.client.ReportCrash(crash1)
|
|
c.client.pollBugs(0)
|
|
|
|
// Now upload build with both commits.
|
|
build3 := testBuild(3)
|
|
build3.Manager = build1.Manager
|
|
build3.Commits = []string{"foo: fix the crash", "bar: prepare for fixing"}
|
|
c.client.UploadBuild(build3)
|
|
|
|
// Check that the commit is now not passed to this builder.
|
|
builderPollResp, _ = c.client.BuilderPoll(build1.Manager)
|
|
c.expectEQ(len(builderPollResp.PendingCommits), 0)
|
|
|
|
// Ensure that a new crash creates a new bug (the old one must be marked as fixed).
|
|
c.client.ReportCrash(crash1)
|
|
rep2 := c.client.pollBug()
|
|
c.expectEQ(rep2.Title, "title1 (2)")
|
|
}
|
|
|
|
// A bug is marked as fixed by one commit and then remarked as fixed by another.
|
|
func TestReFixed(t *testing.T) {
|
|
c := NewCtx(t)
|
|
defer c.Close()
|
|
|
|
build1 := testBuild(1)
|
|
c.client.UploadBuild(build1)
|
|
|
|
crash1 := testCrash(build1, 1)
|
|
c.client.ReportCrash(crash1)
|
|
|
|
builderPollResp, _ := c.client.BuilderPoll(build1.Manager)
|
|
c.expectEQ(len(builderPollResp.PendingCommits), 0)
|
|
|
|
rep := c.client.pollBug()
|
|
|
|
// Specify fixing commit for the bug.
|
|
reply, _ := c.client.ReportingUpdate(&dashapi.BugUpdate{
|
|
ID: rep.ID,
|
|
Status: dashapi.BugStatusOpen,
|
|
FixCommits: []string{"a wrong one"},
|
|
})
|
|
c.expectEQ(reply.OK, true)
|
|
|
|
reply, _ = c.client.ReportingUpdate(&dashapi.BugUpdate{
|
|
ID: rep.ID,
|
|
Status: dashapi.BugStatusOpen,
|
|
FixCommits: []string{"the right one"},
|
|
})
|
|
c.expectEQ(reply.OK, true)
|
|
|
|
builderPollResp, _ = c.client.BuilderPoll(build1.Manager)
|
|
c.expectEQ(len(builderPollResp.PendingCommits), 1)
|
|
c.expectEQ(builderPollResp.PendingCommits[0], "the right one")
|
|
|
|
// Upload another build with the wrong commit.
|
|
build2 := testBuild(2)
|
|
build2.Manager = build1.Manager
|
|
build2.Commits = []string{"a wrong one"}
|
|
c.client.UploadBuild(build2)
|
|
|
|
// Check that it has not fixed the bug.
|
|
builderPollResp, _ = c.client.BuilderPoll(build1.Manager)
|
|
c.expectEQ(len(builderPollResp.PendingCommits), 1)
|
|
c.expectEQ(builderPollResp.PendingCommits[0], "the right one")
|
|
|
|
c.client.ReportCrash(crash1)
|
|
c.client.pollBugs(0)
|
|
|
|
// Now upload build with the right commit.
|
|
build3 := testBuild(3)
|
|
build3.Manager = build1.Manager
|
|
build3.Commits = []string{"the right one"}
|
|
c.client.UploadBuild(build3)
|
|
|
|
// Check that the commit is now not passed to this builder.
|
|
builderPollResp, _ = c.client.BuilderPoll(build1.Manager)
|
|
c.expectEQ(len(builderPollResp.PendingCommits), 0)
|
|
}
|
|
|
|
// Fixing commit is present on one manager, but missing on another.
|
|
func TestFixTwoManagers(t *testing.T) {
|
|
c := NewCtx(t)
|
|
defer c.Close()
|
|
|
|
build1 := testBuild(1)
|
|
c.client.UploadBuild(build1)
|
|
|
|
crash1 := testCrash(build1, 1)
|
|
c.client.ReportCrash(crash1)
|
|
|
|
builderPollResp, _ := c.client.BuilderPoll(build1.Manager)
|
|
c.expectEQ(len(builderPollResp.PendingCommits), 0)
|
|
|
|
rep := c.client.pollBug()
|
|
|
|
// Specify fixing commit for 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)
|
|
|
|
// Now the second manager appears.
|
|
build2 := testBuild(2)
|
|
c.client.UploadBuild(build2)
|
|
|
|
// Check that the commit is now passed to builders.
|
|
builderPollResp, _ = c.client.BuilderPoll(build1.Manager)
|
|
c.expectEQ(len(builderPollResp.PendingCommits), 1)
|
|
c.expectEQ(builderPollResp.PendingCommits[0], "foo: fix the crash")
|
|
|
|
builderPollResp, _ = c.client.BuilderPoll(build2.Manager)
|
|
c.expectEQ(len(builderPollResp.PendingCommits), 1)
|
|
c.expectEQ(builderPollResp.PendingCommits[0], "foo: fix the crash")
|
|
|
|
// Now first manager picks up the commit.
|
|
build3 := testBuild(3)
|
|
build3.Manager = build1.Manager
|
|
build3.Commits = []string{"foo: fix the crash"}
|
|
c.client.UploadBuild(build3)
|
|
|
|
// Check that the commit is now not passed to this builder.
|
|
builderPollResp, _ = c.client.BuilderPoll(build1.Manager)
|
|
c.expectEQ(len(builderPollResp.PendingCommits), 0)
|
|
|
|
// But still passed to another.
|
|
builderPollResp, _ = c.client.BuilderPoll(build2.Manager)
|
|
c.expectEQ(len(builderPollResp.PendingCommits), 1)
|
|
c.expectEQ(builderPollResp.PendingCommits[0], "foo: fix the crash")
|
|
|
|
// Check that the bug is still open.
|
|
c.client.ReportCrash(crash1)
|
|
c.client.pollBugs(0)
|
|
|
|
// Now the second manager picks up the commit.
|
|
build4 := testBuild(4)
|
|
build4.Manager = build2.Manager
|
|
build4.Commits = []string{"foo: fix the crash"}
|
|
c.client.UploadBuild(build4)
|
|
|
|
// Now the bug must be fixed.
|
|
builderPollResp, _ = c.client.BuilderPoll(build2.Manager)
|
|
c.expectEQ(len(builderPollResp.PendingCommits), 0)
|
|
|
|
c.client.ReportCrash(crash1)
|
|
rep2 := c.client.pollBug()
|
|
c.expectEQ(rep2.Title, "title1 (2)")
|
|
}
|
|
|
|
func TestReFixedTwoManagers(t *testing.T) {
|
|
c := NewCtx(t)
|
|
defer c.Close()
|
|
|
|
build1 := testBuild(1)
|
|
c.client.UploadBuild(build1)
|
|
|
|
crash1 := testCrash(build1, 1)
|
|
c.client.ReportCrash(crash1)
|
|
|
|
builderPollResp, _ := c.client.BuilderPoll(build1.Manager)
|
|
c.expectEQ(len(builderPollResp.PendingCommits), 0)
|
|
|
|
rep := c.client.pollBug()
|
|
|
|
// Specify fixing commit for 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)
|
|
|
|
// Now the second manager appears.
|
|
build2 := testBuild(2)
|
|
c.client.UploadBuild(build2)
|
|
|
|
// Now first manager picks up the commit.
|
|
build3 := testBuild(3)
|
|
build3.Manager = build1.Manager
|
|
build3.Commits = []string{"foo: fix the crash"}
|
|
c.client.UploadBuild(build3)
|
|
|
|
builderPollResp, _ = c.client.BuilderPoll(build1.Manager)
|
|
c.expectEQ(len(builderPollResp.PendingCommits), 0)
|
|
|
|
// Now we change the fixing commit.
|
|
reply, _ = c.client.ReportingUpdate(&dashapi.BugUpdate{
|
|
ID: rep.ID,
|
|
Status: dashapi.BugStatusOpen,
|
|
FixCommits: []string{"the right one"},
|
|
})
|
|
c.expectEQ(reply.OK, true)
|
|
|
|
// Now it must again appear on both managers.
|
|
builderPollResp, _ = c.client.BuilderPoll(build1.Manager)
|
|
c.expectEQ(len(builderPollResp.PendingCommits), 1)
|
|
c.expectEQ(builderPollResp.PendingCommits[0], "the right one")
|
|
|
|
builderPollResp, _ = c.client.BuilderPoll(build1.Manager)
|
|
c.expectEQ(len(builderPollResp.PendingCommits), 1)
|
|
c.expectEQ(builderPollResp.PendingCommits[0], "the right one")
|
|
|
|
// Now the second manager picks up the second commit.
|
|
build4 := testBuild(4)
|
|
build4.Manager = build2.Manager
|
|
build4.Commits = []string{"the right one"}
|
|
c.client.UploadBuild(build4)
|
|
|
|
// The bug must be still open.
|
|
c.client.ReportCrash(crash1)
|
|
c.client.pollBugs(0)
|
|
|
|
// Specify fixing commit again, but it's the same one as before, so nothing changed.
|
|
reply, _ = c.client.ReportingUpdate(&dashapi.BugUpdate{
|
|
ID: rep.ID,
|
|
Status: dashapi.BugStatusOpen,
|
|
FixCommits: []string{"the right one"},
|
|
})
|
|
c.expectEQ(reply.OK, true)
|
|
|
|
// Now the first manager picks up the second commit.
|
|
build5 := testBuild(5)
|
|
build5.Manager = build1.Manager
|
|
build5.Commits = []string{"the right one"}
|
|
c.client.UploadBuild(build5)
|
|
|
|
// Now the bug must be fixed.
|
|
builderPollResp, _ = c.client.BuilderPoll(build1.Manager)
|
|
c.expectEQ(len(builderPollResp.PendingCommits), 0)
|
|
|
|
c.client.ReportCrash(crash1)
|
|
rep2 := c.client.pollBug()
|
|
c.expectEQ(rep2.Title, "title1 (2)")
|
|
}
|
|
|
|
// TestFixedWithCommitTags tests fixing of bugs with Reported-by commit tags.
|
|
func TestFixedWithCommitTags(t *testing.T) {
|
|
c := NewCtx(t)
|
|
defer c.Close()
|
|
|
|
build1 := testBuild(1)
|
|
c.client.UploadBuild(build1)
|
|
|
|
build2 := testBuild(2)
|
|
c.client.UploadBuild(build2)
|
|
|
|
crash1 := testCrash(build1, 1)
|
|
c.client.ReportCrash(crash1)
|
|
|
|
rep := c.client.pollBug()
|
|
|
|
// Upload build with 2 fixing commits for this bug.
|
|
build1.FixCommits = []dashapi.FixCommit{{"fix commit 1", rep.ID}, {"fix commit 2", rep.ID}}
|
|
c.client.UploadBuild(build1)
|
|
|
|
// Now the commits must be associated with the bug and the second
|
|
// manager must get them as pending.
|
|
builderPollResp, _ := c.client.BuilderPoll(build2.Manager)
|
|
c.expectEQ(len(builderPollResp.PendingCommits), 2)
|
|
c.expectEQ(builderPollResp.PendingCommits[0], "fix commit 1")
|
|
c.expectEQ(builderPollResp.PendingCommits[1], "fix commit 2")
|
|
|
|
// The first manager must not get them.
|
|
builderPollResp, _ = c.client.BuilderPoll(build1.Manager)
|
|
c.expectEQ(len(builderPollResp.PendingCommits), 0)
|
|
|
|
// The bug is still not fixed.
|
|
c.client.ReportCrash(crash1)
|
|
c.client.pollBugs(0)
|
|
|
|
// Now the second manager reports the same commits.
|
|
// This must close the bug.
|
|
build2.FixCommits = build1.FixCommits
|
|
c.client.UploadBuild(build2)
|
|
|
|
// Commits must not be passed to managers.
|
|
builderPollResp, _ = c.client.BuilderPoll(build2.Manager)
|
|
c.expectEQ(len(builderPollResp.PendingCommits), 0)
|
|
|
|
// Ensure that a new crash creates a new bug.
|
|
c.client.ReportCrash(crash1)
|
|
rep2 := c.client.pollBug()
|
|
c.expectEQ(rep2.Title, "title1 (2)")
|
|
}
|
|
|
|
// TestFixedDup tests Reported-by commit tag that comes for a dup.
|
|
// In such case we need to associate it with the canonical bugs.
|
|
func TestFixedDup(t *testing.T) {
|
|
c := NewCtx(t)
|
|
defer c.Close()
|
|
|
|
build := testBuild(1)
|
|
c.client.UploadBuild(build)
|
|
|
|
crash1 := testCrash(build, 1)
|
|
c.client.ReportCrash(crash1)
|
|
rep1 := c.client.pollBug()
|
|
|
|
crash2 := testCrash(build, 2)
|
|
c.client.ReportCrash(crash2)
|
|
rep2 := c.client.pollBug()
|
|
|
|
// rep2 is a dup of rep1.
|
|
c.client.updateBug(rep2.ID, dashapi.BugStatusDup, rep1.ID)
|
|
|
|
// Upload build that fixes rep2.
|
|
build.FixCommits = []dashapi.FixCommit{{"fix commit 1", rep2.ID}}
|
|
c.client.UploadBuild(build)
|
|
|
|
// This must fix rep1.
|
|
c.client.ReportCrash(crash1)
|
|
rep3 := c.client.pollBug()
|
|
c.expectEQ(rep3.Title, rep1.Title+" (2)")
|
|
}
|
|
|
|
// TestFixedDup2 tests Reported-by commit tag that comes for a dup.
|
|
// Ensure that non-canonical bug gets fixing commit too.
|
|
func TestFixedDup2(t *testing.T) {
|
|
c := NewCtx(t)
|
|
defer c.Close()
|
|
|
|
build1 := testBuild(1)
|
|
c.client.UploadBuild(build1)
|
|
|
|
build2 := testBuild(2)
|
|
c.client.UploadBuild(build2)
|
|
|
|
crash1 := testCrash(build1, 1)
|
|
c.client.ReportCrash(crash1)
|
|
rep1 := c.client.pollBug()
|
|
|
|
crash2 := testCrash(build1, 2)
|
|
c.client.ReportCrash(crash2)
|
|
rep2 := c.client.pollBug()
|
|
|
|
// rep2 is a dup of rep1.
|
|
c.client.updateBug(rep2.ID, dashapi.BugStatusDup, rep1.ID)
|
|
|
|
// Upload build that fixes rep2.
|
|
build1.FixCommits = []dashapi.FixCommit{{"fix commit 1", rep2.ID}}
|
|
c.client.UploadBuild(build1)
|
|
|
|
/*
|
|
dbBug1, _, _ := c.loadBug(rep1.ID)
|
|
t.Logf("BUG1: status=%v, commits: %+v, patched: %+v", dbBug1.Status, dbBug1.Commits, dbBug1.PatchedOn)
|
|
dbBug2, _, _ := c.loadBug(rep2.ID)
|
|
t.Logf("BUG2: status=%v, commits: %+v, patched: %+v", dbBug2.Status, dbBug2.Commits, dbBug2.PatchedOn)
|
|
*/
|
|
|
|
// Now undup the bugs. They are still unfixed as only 1 manager uploaded the commit.
|
|
c.client.updateBug(rep2.ID, dashapi.BugStatusOpen, "")
|
|
|
|
// Now the second manager reports the same commits. This must close both bugs.
|
|
build2.FixCommits = build1.FixCommits
|
|
c.client.UploadBuild(build2)
|
|
c.client.pollBugs(0)
|
|
|
|
c.advanceTime(24 * time.Hour)
|
|
c.client.ReportCrash(crash1)
|
|
rep3 := c.client.pollBug()
|
|
c.expectEQ(rep3.Title, rep1.Title+" (2)")
|
|
|
|
c.client.ReportCrash(crash2)
|
|
rep4 := c.client.pollBug()
|
|
c.expectEQ(rep4.Title, rep2.Title+" (2)")
|
|
}
|
|
|
|
// TestFixedDup3 tests Reported-by commit tag that comes for both dup and canonical bug.
|
|
func TestFixedDup3(t *testing.T) {
|
|
c := NewCtx(t)
|
|
defer c.Close()
|
|
|
|
build1 := testBuild(1)
|
|
c.client.UploadBuild(build1)
|
|
|
|
build2 := testBuild(2)
|
|
c.client.UploadBuild(build2)
|
|
|
|
crash1 := testCrash(build1, 1)
|
|
c.client.ReportCrash(crash1)
|
|
rep1 := c.client.pollBug()
|
|
|
|
crash2 := testCrash(build1, 2)
|
|
c.client.ReportCrash(crash2)
|
|
rep2 := c.client.pollBug()
|
|
|
|
// rep2 is a dup of rep1.
|
|
c.client.updateBug(rep2.ID, dashapi.BugStatusDup, rep1.ID)
|
|
|
|
// Upload builds that fix rep1 and rep2 with different commits.
|
|
// This must fix rep1 eventually and we must not livelock in such scenario.
|
|
build1.FixCommits = []dashapi.FixCommit{{"fix commit 1", rep1.ID}, {"fix commit 2", rep2.ID}}
|
|
build2.FixCommits = build1.FixCommits
|
|
c.client.UploadBuild(build1)
|
|
c.client.UploadBuild(build2)
|
|
c.client.UploadBuild(build1)
|
|
c.client.UploadBuild(build2)
|
|
|
|
c.client.ReportCrash(crash1)
|
|
rep3 := c.client.pollBug()
|
|
c.expectEQ(rep3.Title, rep1.Title+" (2)")
|
|
}
|