blob: e7a232ad195eab8cce052976f1918c55ac2843fb [file] [log] [blame]
package db
import (
"fmt"
"testing"
"time"
assert "github.com/stretchr/testify/require"
"go.skia.org/infra/go/testutils"
)
func TestCopyTaskComment(t *testing.T) {
testutils.SmallTest(t)
v := makeTaskComment(1, 1, 1, 1, time.Now())
testutils.AssertCopy(t, v, v.Copy())
}
func TestCopyTaskSpecComment(t *testing.T) {
testutils.SmallTest(t)
v := makeTaskSpecComment(1, 1, 1, time.Now())
v.Flaky = true
v.IgnoreFailure = true
testutils.AssertCopy(t, v, v.Copy())
}
func TestCopyCommitComment(t *testing.T) {
testutils.SmallTest(t)
v := makeCommitComment(1, 1, 1, time.Now())
v.IgnoreFailure = true
testutils.AssertCopy(t, v, v.Copy())
}
func TestCopyRepoComments(t *testing.T) {
testutils.SmallTest(t)
v := &RepoComments{
Repo: "r1",
TaskComments: map[string]map[string][]*TaskComment{
"c1": {
"n1": {makeTaskComment(1, 1, 1, 1, time.Now())},
},
},
TaskSpecComments: map[string][]*TaskSpecComment{
"n1": {makeTaskSpecComment(1, 1, 1, time.Now())},
},
CommitComments: map[string][]*CommitComment{
"c1": {makeCommitComment(1, 1, 1, time.Now())},
},
}
testutils.AssertCopy(t, v, v.Copy())
}
// TestCommentBox checks that CommentBox correctly implements CommentDB.
func TestCommentBox(t *testing.T) {
testutils.SmallTest(t)
TestCommentDB(t, &CommentBox{})
}
// TestCommentBoxWithPersistence checks that NewCommentBoxWithPersistence can be
// initialized with a persisted map and will correctly write changes to the
// provided writer.
func TestCommentBoxWithPersistence(t *testing.T) {
testutils.SmallTest(t)
expected := map[string]*RepoComments{}
callCount := 0
testWriter := func(actual map[string]*RepoComments) error {
callCount++
testutils.AssertDeepEqual(t, expected, actual)
return nil
}
db := NewCommentBoxWithPersistence(nil, testWriter)
now := time.Now()
assert.Equal(t, 0, callCount)
// Add some comments.
tc1 := makeTaskComment(1, 1, 1, 1, now)
expected["r1"] = &RepoComments{
Repo: "r1",
TaskComments: map[string]map[string][]*TaskComment{"c1": {"n1": {tc1}}},
TaskSpecComments: map[string][]*TaskSpecComment{},
CommitComments: map[string][]*CommitComment{},
}
assert.NoError(t, db.PutTaskComment(tc1))
tc2 := makeTaskComment(2, 1, 1, 1, now.Add(2*time.Second))
expected["r1"].TaskComments["c1"]["n1"] = []*TaskComment{tc1, tc2}
assert.NoError(t, db.PutTaskComment(tc2))
tc3 := makeTaskComment(3, 1, 1, 1, now.Add(time.Second))
expected["r1"].TaskComments["c1"]["n1"] = []*TaskComment{tc1, tc3, tc2}
assert.NoError(t, db.PutTaskComment(tc3))
tc4 := makeTaskComment(4, 1, 1, 2, now)
expected["r1"].TaskComments["c2"] = map[string][]*TaskComment{"n1": {tc4}}
assert.NoError(t, db.PutTaskComment(tc4))
tc5 := makeTaskComment(5, 1, 2, 2, now)
expected["r1"].TaskComments["c2"]["n2"] = []*TaskComment{tc5}
assert.NoError(t, db.PutTaskComment(tc5))
tc6 := makeTaskComment(6, 2, 3, 3, now)
expected["r2"] = &RepoComments{
Repo: "r2",
TaskComments: map[string]map[string][]*TaskComment{"c3": {"n3": {tc6.Copy()}}},
TaskSpecComments: map[string][]*TaskSpecComment{},
CommitComments: map[string][]*CommitComment{},
}
assert.NoError(t, db.PutTaskComment(tc6))
tc6copy := tc6.Copy() // Adding identical comment should be ignored.
assert.NoError(t, db.PutTaskComment(tc6copy))
tc6.Message = "modifying after Put shouldn't affect stored comment"
assert.True(t, callCount >= 6)
sc1 := makeTaskSpecComment(1, 1, 1, now)
expected["r1"].TaskSpecComments["n1"] = []*TaskSpecComment{sc1}
assert.NoError(t, db.PutTaskSpecComment(sc1))
cc1 := makeCommitComment(1, 1, 1, now)
expected["r1"].CommitComments["c1"] = []*CommitComment{cc1}
assert.NoError(t, db.PutCommitComment(cc1))
assert.True(t, callCount >= 8)
callCount = 0
// Check that if there's an error adding, testWriter is not called.
tc1different := tc1.Copy()
tc1different.Message = "not the same"
assert.True(t, IsAlreadyExists(db.PutTaskComment(tc1different)))
sc1different := sc1.Copy()
sc1different.Message = "not the same"
assert.True(t, IsAlreadyExists(db.PutTaskSpecComment(sc1different)))
cc1different := cc1.Copy()
cc1different.Message = "not the same"
assert.True(t, IsAlreadyExists(db.PutCommitComment(cc1different)))
assert.Equal(t, 0, callCount)
// Reload DB from persistent.
init := map[string]*RepoComments{
"r1": expected["r1"].Copy(),
"r2": expected["r2"].Copy(),
}
db = NewCommentBoxWithPersistence(init, testWriter)
{
actual, err := db.GetCommentsForRepos([]string{"r0", "r1", "r2"}, now.Add(-10000*time.Hour))
assert.NoError(t, err)
expectedSlice := []*RepoComments{
&RepoComments{Repo: "r0"},
expected["r1"],
expected["r2"],
}
testutils.AssertDeepEqual(t, expectedSlice, actual)
}
assert.Equal(t, 0, callCount)
// Delete some comments.
expected["r1"].TaskComments["c1"]["n1"] = []*TaskComment{tc1, tc2}
assert.NoError(t, db.DeleteTaskComment(tc3))
expected["r1"].TaskSpecComments = map[string][]*TaskSpecComment{}
assert.NoError(t, db.DeleteTaskSpecComment(sc1))
expected["r1"].CommitComments = map[string][]*CommitComment{}
assert.NoError(t, db.DeleteCommitComment(cc1))
assert.Equal(t, 3, callCount)
// Delete of nonexistent task should succeed.
assert.NoError(t, db.DeleteTaskComment(makeTaskComment(99, 1, 1, 1, now.Add(99*time.Second))))
assert.NoError(t, db.DeleteTaskComment(makeTaskComment(99, 1, 1, 99, now)))
assert.NoError(t, db.DeleteTaskComment(makeTaskComment(99, 1, 99, 1, now)))
assert.NoError(t, db.DeleteTaskComment(makeTaskComment(99, 99, 1, 1, now)))
assert.NoError(t, db.DeleteTaskSpecComment(makeTaskSpecComment(99, 1, 1, now.Add(99*time.Second))))
assert.NoError(t, db.DeleteTaskSpecComment(makeTaskSpecComment(99, 1, 99, now)))
assert.NoError(t, db.DeleteTaskSpecComment(makeTaskSpecComment(99, 99, 1, now)))
assert.NoError(t, db.DeleteCommitComment(makeCommitComment(99, 1, 1, now.Add(99*time.Second))))
assert.NoError(t, db.DeleteCommitComment(makeCommitComment(99, 1, 99, now)))
assert.NoError(t, db.DeleteCommitComment(makeCommitComment(99, 99, 1, now)))
{
actual, err := db.GetCommentsForRepos([]string{"r0", "r1", "r2"}, now.Add(-10000*time.Hour))
assert.NoError(t, err)
expectedSlice := []*RepoComments{
&RepoComments{Repo: "r0"},
expected["r1"],
expected["r2"],
}
testutils.AssertDeepEqual(t, expectedSlice, actual)
}
// Reload DB from persistent again.
init = map[string]*RepoComments{
"r1": expected["r1"].Copy(),
"r2": expected["r2"].Copy(),
}
db = NewCommentBoxWithPersistence(init, testWriter)
{
actual, err := db.GetCommentsForRepos([]string{"r0", "r1", "r2"}, now.Add(-10000*time.Hour))
assert.NoError(t, err)
expectedSlice := []*RepoComments{
&RepoComments{Repo: "r0"},
expected["r1"],
expected["r2"],
}
testutils.AssertDeepEqual(t, expectedSlice, actual)
}
}
// TestCommentBoxWithPersistenceError verifies that when the writer passed to
// NewCommentBoxWithPersistence returns an error, the modification does not take
// effect.
func TestCommentBoxWithPersistenceError(t *testing.T) {
testutils.SmallTest(t)
callCount := 0
var injectedError error = nil
testWriter := func(actual map[string]*RepoComments) error {
callCount++
return injectedError
}
db := NewCommentBoxWithPersistence(nil, testWriter)
now := time.Now()
// Add some comments.
tc1 := makeTaskComment(1, 1, 1, 1, now)
tc2 := makeTaskComment(2, 1, 1, 1, now.Add(2*time.Second))
tc3 := makeTaskComment(3, 1, 1, 1, now.Add(time.Second))
tc4 := makeTaskComment(4, 1, 1, 2, now)
tc5 := makeTaskComment(5, 1, 2, 2, now)
tc6 := makeTaskComment(6, 2, 3, 3, now)
for _, c := range []*TaskComment{tc1, tc2, tc3, tc4, tc5, tc6} {
assert.NoError(t, db.PutTaskComment(c))
}
sc1 := makeTaskSpecComment(1, 1, 1, now)
assert.NoError(t, db.PutTaskSpecComment(sc1))
cc1 := makeCommitComment(1, 1, 1, now)
assert.NoError(t, db.PutCommitComment(cc1))
expected := []*RepoComments{
&RepoComments{
Repo: "r1",
TaskComments: map[string]map[string][]*TaskComment{
"c1": {
"n1": {tc1, tc3, tc2},
},
"c2": {
"n1": {tc4},
"n2": {tc5},
},
},
TaskSpecComments: map[string][]*TaskSpecComment{
"n1": {sc1},
},
CommitComments: map[string][]*CommitComment{
"c1": {cc1},
},
},
&RepoComments{
Repo: "r2",
TaskComments: map[string]map[string][]*TaskComment{
"c3": {
"n3": {tc6},
},
},
TaskSpecComments: map[string][]*TaskSpecComment{},
CommitComments: map[string][]*CommitComment{},
},
}
{
actual, err := db.GetCommentsForRepos([]string{"r1", "r2"}, now.Add(-10000*time.Hour))
assert.NoError(t, err)
testutils.AssertDeepEqual(t, expected, actual)
}
callCount = 0
injectedError = fmt.Errorf("No comments from the peanut gallery.")
assert.Error(t, db.PutTaskComment(makeTaskComment(99, 1, 1, 1, now.Add(99*time.Second))))
assert.Error(t, db.PutTaskComment(makeTaskComment(99, 1, 1, 99, now)))
assert.Error(t, db.PutTaskComment(makeTaskComment(99, 1, 99, 1, now)))
assert.Error(t, db.PutTaskComment(makeTaskComment(99, 99, 1, 1, now)))
assert.Error(t, db.PutTaskSpecComment(makeTaskSpecComment(99, 1, 1, now.Add(99*time.Second))))
assert.Error(t, db.PutTaskSpecComment(makeTaskSpecComment(99, 1, 99, now)))
assert.Error(t, db.PutTaskSpecComment(makeTaskSpecComment(99, 99, 1, now)))
assert.Error(t, db.PutCommitComment(makeCommitComment(99, 1, 1, now.Add(99*time.Second))))
assert.Error(t, db.PutCommitComment(makeCommitComment(99, 1, 99, now)))
assert.Error(t, db.PutCommitComment(makeCommitComment(99, 99, 1, now)))
assert.Equal(t, 10, callCount)
// Assert nothing has changed.
{
actual, err := db.GetCommentsForRepos([]string{"r1", "r2"}, now.Add(-10000*time.Hour))
assert.NoError(t, err)
testutils.AssertDeepEqual(t, expected, actual)
}
assert.Error(t, db.DeleteTaskComment(tc1))
assert.Error(t, db.DeleteTaskSpecComment(sc1))
assert.Error(t, db.DeleteCommitComment(cc1))
// Assert nothing has changed.
{
actual, err := db.GetCommentsForRepos([]string{"r1", "r2"}, now.Add(-10000*time.Hour))
assert.NoError(t, err)
testutils.AssertDeepEqual(t, expected, actual)
}
}