blob: f884e5c2f89a4ce6a1479365dd29b0974ec486f4 [file] [log] [blame]
package fs_clstore
import (
"context"
"strconv"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.skia.org/infra/go/firestore"
"go.skia.org/infra/go/testutils/unittest"
"go.skia.org/infra/golden/go/clstore"
"go.skia.org/infra/golden/go/code_review"
)
func TestPutGetChangelist(t *testing.T) {
unittest.LargeTest(t)
c, cleanup := firestore.NewClientForTesting(context.Background(), t)
defer cleanup()
f := New(c, "gerrit")
ctx := context.Background()
expectedID := "987654"
// Should not exist initially
_, err := f.GetChangelist(ctx, expectedID)
require.Error(t, err)
require.Equal(t, clstore.ErrNotFound, err)
cl := code_review.Changelist{
SystemID: expectedID,
Owner: "test@example.com",
Status: code_review.Abandoned,
Subject: "some code",
Updated: time.Date(2019, time.August, 13, 12, 11, 10, 0, time.UTC),
}
err = f.PutChangelist(ctx, cl)
require.NoError(t, err)
actual, err := f.GetChangelist(ctx, expectedID)
require.NoError(t, err)
require.Equal(t, cl, actual)
}
func TestPutGetPatchset(t *testing.T) {
unittest.LargeTest(t)
c, cleanup := firestore.NewClientForTesting(context.Background(), t)
defer cleanup()
f := New(c, "gerrit")
ctx := context.Background()
expectedCLID := "987654"
expectedPSID := "abcdef012345"
// Should not exist initially
_, err := f.GetPatchset(ctx, expectedCLID, expectedPSID)
require.Error(t, err)
require.Equal(t, clstore.ErrNotFound, err)
ps := code_review.Patchset{
SystemID: expectedPSID,
ChangelistID: expectedCLID,
Order: 3,
GitHash: "fedcba98765443321",
LastCheckedIfCommentNecessary: time.Date(2020, time.May, 1, 2, 3, 4, 0, time.UTC),
CommentedOnCL: true,
}
err = f.PutPatchset(ctx, ps)
require.NoError(t, err)
actual, err := f.GetPatchset(ctx, expectedCLID, expectedPSID)
require.NoError(t, err)
require.Equal(t, ps, actual)
}
func TestPutGetPatchsetByOrder(t *testing.T) {
unittest.LargeTest(t)
c, cleanup := firestore.NewClientForTesting(context.Background(), t)
defer cleanup()
f := New(c, "gerrit")
ctx := context.Background()
expectedCLID := "987654"
expectedPSOrder := 3
otherPSOrder := 117
// Should not exist initially
_, err := f.GetPatchsetByOrder(ctx, expectedCLID, expectedPSOrder)
require.Error(t, err)
require.Equal(t, clstore.ErrNotFound, err)
ps := code_review.Patchset{
SystemID: "abcdef012345",
ChangelistID: expectedCLID,
Order: expectedPSOrder,
GitHash: "fedcba98765443321",
}
err = f.PutPatchset(ctx, ps)
require.NoError(t, err)
ps2 := code_review.Patchset{
SystemID: "zyx9876",
ChangelistID: expectedCLID,
Order: otherPSOrder,
GitHash: "notthisone",
}
err = f.PutPatchset(ctx, ps2)
require.NoError(t, err)
actual, err := f.GetPatchsetByOrder(ctx, expectedCLID, expectedPSOrder)
require.NoError(t, err)
require.Equal(t, ps, actual)
actual, err = f.GetPatchsetByOrder(ctx, expectedCLID, otherPSOrder)
require.NoError(t, err)
require.Equal(t, ps2, actual)
}
// TestDifferentSystems makes sure that two systems in the same
// firestore namespace don't overlap.
func TestDifferentSystems(t *testing.T) {
unittest.LargeTest(t)
c, cleanup := firestore.NewClientForTesting(context.Background(), t)
defer cleanup()
gerrit := New(c, "gerrit")
github := New(c, "github")
ctx := context.Background()
expectedCLID := "987654"
gerritCL := code_review.Changelist{
SystemID: expectedCLID,
Owner: "test@example.com",
Status: code_review.Abandoned,
Subject: "some code on gerrit",
Updated: time.Date(2019, time.August, 13, 12, 11, 10, 0, time.UTC),
}
githubCL := code_review.Changelist{
SystemID: expectedCLID,
Owner: "test2@example.com",
Status: code_review.Open,
Subject: "some code on github",
Updated: time.Date(2019, time.August, 15, 12, 11, 10, 0, time.UTC),
}
// Both systems have a CL with the same ID
err := gerrit.PutChangelist(ctx, gerritCL)
require.NoError(t, err)
err = github.PutChangelist(ctx, githubCL)
require.NoError(t, err)
actualGerrit, err := gerrit.GetChangelist(ctx, expectedCLID)
require.NoError(t, err)
actualGithub, err := github.GetChangelist(ctx, expectedCLID)
require.NoError(t, err)
require.NotEqual(t, actualGerrit, actualGithub)
require.Equal(t, gerritCL, actualGerrit)
require.Equal(t, githubCL, actualGithub)
}
// TestGetPatchsets stores several patchsets and then makes sure we can fetch the ones
// for a specific CL and they arrive sorted by Order, even if the Patchsets are sparse.
func TestGetPatchsets(t *testing.T) {
unittest.LargeTest(t)
c, cleanup := firestore.NewClientForTesting(context.Background(), t)
defer cleanup()
f := New(c, "gerrit")
ctx := context.Background()
expectedID := "987654"
sparseID := "sparse"
// None should exist initially
xps, err := f.GetPatchsets(ctx, expectedID)
require.NoError(t, err)
require.Empty(t, xps)
// Create the Changelist, but don't add any Patchsets yet.
err = f.PutChangelist(ctx, code_review.Changelist{SystemID: expectedID})
require.NoError(t, err)
// Still no Patchsets
xps, err = f.GetPatchsets(ctx, expectedID)
require.NoError(t, err)
require.Empty(t, xps)
for i := 0; i < 3; i++ {
ps := code_review.Patchset{
SystemID: "other_id" + strconv.Itoa(i),
ChangelistID: "not this CL",
GitHash: "nope",
Order: i + 1,
}
require.NoError(t, f.PutPatchset(ctx, ps))
}
// use random ids to make sure the we are truly sorting on ids
randIDs := []string{"zkdf", "bkand", "d-sd9f9s3n", "csdfksdfn1"}
// put them in backwards to make sure they get resorted by order
for i := 4; i > 0; i-- {
ps := code_review.Patchset{
// use an ID
SystemID: randIDs[i-1],
ChangelistID: expectedID,
GitHash: "whatever",
Order: i,
}
require.NoError(t, f.PutPatchset(ctx, ps))
}
for i := 0; i < 9; i += 3 {
ps := code_review.Patchset{
SystemID: "other_other_id" + strconv.Itoa(20-i),
ChangelistID: sparseID,
GitHash: "sparse",
Order: i + 1,
}
require.NoError(t, f.PutPatchset(ctx, ps))
}
// Check that sequential orders work
xps, err = f.GetPatchsets(ctx, expectedID)
require.NoError(t, err)
require.Len(t, xps, 4)
// Make sure they are in order
for i, ps := range xps {
require.Equal(t, i+1, ps.Order)
require.Equal(t, expectedID, ps.ChangelistID)
require.Equal(t, "whatever", ps.GitHash)
}
// Check that sparse patchsets work.
xps, err = f.GetPatchsets(ctx, sparseID)
require.NoError(t, err)
require.Len(t, xps, 3)
// Make sure they are in order
for i, ps := range xps {
require.Equal(t, i*3+1, ps.Order)
require.Equal(t, sparseID, ps.ChangelistID)
require.Equal(t, "sparse", ps.GitHash)
}
}
func TestGetChangelists(t *testing.T) {
unittest.LargeTest(t)
c, cleanup := firestore.NewClientForTesting(context.Background(), t)
defer cleanup()
f := New(c, "gerrit")
ctx := context.Background()
// None to start
cls, total, err := f.GetChangelists(ctx, clstore.SearchOptions{
StartIdx: 0,
Limit: 50,
})
require.NoError(t, err)
require.Len(t, cls, 0)
require.Equal(t, 0, total)
for i := 0; i < 40; i += 2 {
cl := code_review.Changelist{
SystemID: "cl" + strconv.Itoa(i),
Owner: "test@example.com",
Status: code_review.Open,
Subject: "blarg",
Updated: time.Date(2019, time.August, 31, 14, i, i, 0, time.UTC),
}
require.NoError(t, f.PutChangelist(ctx, cl))
}
// Put in a few other ones:
for i := 1; i < 10; i += 2 {
cl := code_review.Changelist{
SystemID: "cl" + strconv.Itoa(i),
Owner: "test@example.com",
Status: code_review.Abandoned,
Subject: "blarg",
Updated: time.Date(2019, time.September, 1, 4, i, i, 0, time.UTC),
}
require.NoError(t, f.PutChangelist(ctx, cl))
}
for i := 31; i < 40; i += 2 {
cl := code_review.Changelist{
SystemID: "cl" + strconv.Itoa(i),
Owner: "test@example.com",
Status: code_review.Landed,
Subject: "blarg",
Updated: time.Date(2019, time.September, 1, 2, i, i, 0, time.UTC),
}
require.NoError(t, f.PutChangelist(ctx, cl))
}
// Get all of them
cls, total, err = f.GetChangelists(ctx, clstore.SearchOptions{
StartIdx: 0,
Limit: 50,
})
require.NoError(t, err)
require.Len(t, cls, 30)
require.Equal(t, 30, total)
// Get the first ones
cls, total, err = f.GetChangelists(ctx, clstore.SearchOptions{
StartIdx: 0,
Limit: 3,
})
require.NoError(t, err)
require.Len(t, cls, 3)
require.Equal(t, clstore.CountMany, total)
// spot check the dates to make sure the CLs are in the right order.
require.Equal(t, time.Date(2019, time.September, 1, 4, 9, 9, 0, time.UTC), cls[0].Updated)
require.Equal(t, time.Date(2019, time.September, 1, 4, 7, 7, 0, time.UTC), cls[1].Updated)
require.Equal(t, time.Date(2019, time.September, 1, 4, 5, 5, 0, time.UTC), cls[2].Updated)
// Get some in the middle
cls, total, err = f.GetChangelists(ctx, clstore.SearchOptions{
StartIdx: 5,
Limit: 2,
})
require.NoError(t, err)
require.Len(t, cls, 2)
require.Equal(t, clstore.CountMany, total)
require.Equal(t, time.Date(2019, time.September, 1, 2, 39, 39, 0, time.UTC), cls[0].Updated)
require.Equal(t, time.Date(2019, time.September, 1, 2, 37, 37, 0, time.UTC), cls[1].Updated)
// Get some at the end.
cls, total, err = f.GetChangelists(ctx, clstore.SearchOptions{
StartIdx: 28,
Limit: 10,
})
require.NoError(t, err)
require.Len(t, cls, 2)
require.Equal(t, 30, total)
require.Equal(t, time.Date(2019, time.August, 31, 14, 2, 2, 0, time.UTC), cls[0].Updated)
require.Equal(t, time.Date(2019, time.August, 31, 14, 0, 0, 0, time.UTC), cls[1].Updated)
// If we query off the end, we don't know how many there are, so 0 is a fine response.
cls, total, err = f.GetChangelists(ctx, clstore.SearchOptions{
StartIdx: 999,
Limit: 3,
})
require.NoError(t, err)
require.Len(t, cls, 0)
require.Equal(t, 999, total)
}
// TestGetChangelistsOptions checks that various search options function.
func TestGetChangelistsOptions(t *testing.T) {
unittest.LargeTest(t)
c, cleanup := firestore.NewClientForTesting(context.Background(), t)
defer cleanup()
f := New(c, "gerrit")
ctx := context.Background()
clA := code_review.Changelist{
SystemID: "abc",
Owner: "first@example.com",
Status: code_review.Open,
Subject: "Open sesame",
Updated: time.Date(2019, time.October, 5, 4, 3, 2, 0, time.UTC),
}
clB := code_review.Changelist{
SystemID: "def",
Owner: "second@example.com",
Status: code_review.Landed,
Subject: "Landed Panda",
Updated: time.Date(2019, time.October, 10, 4, 3, 2, 0, time.UTC),
}
clC := code_review.Changelist{
SystemID: "ghi",
Owner: "third@example.com",
Status: code_review.Open,
Subject: "Open again",
Updated: time.Date(2019, time.October, 15, 4, 3, 2, 0, time.UTC),
}
require.NoError(t, f.PutChangelist(ctx, clA))
require.NoError(t, f.PutChangelist(ctx, clB))
require.NoError(t, f.PutChangelist(ctx, clC))
xcl, _, err := f.GetChangelists(ctx, clstore.SearchOptions{
Limit: 10,
})
require.NoError(t, err)
assert.Equal(t, []code_review.Changelist{clC, clB, clA}, xcl)
xcl, _, err = f.GetChangelists(ctx, clstore.SearchOptions{
OpenCLsOnly: true,
Limit: 10,
})
require.NoError(t, err)
assert.Equal(t, []code_review.Changelist{clC, clA}, xcl)
xcl, _, err = f.GetChangelists(ctx, clstore.SearchOptions{
After: time.Date(2019, time.September, 28, 0, 0, 0, 0, time.UTC),
Limit: 10,
})
require.NoError(t, err)
assert.Equal(t, []code_review.Changelist{clC, clB, clA}, xcl)
xcl, _, err = f.GetChangelists(ctx, clstore.SearchOptions{
After: time.Date(2019, time.November, 28, 0, 0, 0, 0, time.UTC),
Limit: 10,
})
require.NoError(t, err)
assert.Empty(t, xcl)
xcl, _, err = f.GetChangelists(ctx, clstore.SearchOptions{
After: time.Date(2019, time.October, 7, 0, 0, 0, 0, time.UTC),
Limit: 10,
})
require.NoError(t, err)
assert.Equal(t, []code_review.Changelist{clC, clB}, xcl)
xcl, _, err = f.GetChangelists(ctx, clstore.SearchOptions{
OpenCLsOnly: true,
After: time.Date(2019, time.October, 7, 0, 0, 0, 0, time.UTC),
Limit: 10,
})
require.NoError(t, err)
assert.Equal(t, []code_review.Changelist{clC}, xcl)
}
func TestGetChangelistsNoLimit(t *testing.T) {
unittest.LargeTest(t)
c, cleanup := firestore.NewClientForTesting(context.Background(), t)
defer cleanup()
f := New(c, "gerrit")
ctx := context.Background()
_, _, err := f.GetChangelists(ctx, clstore.SearchOptions{})
require.Error(t, err)
assert.Contains(t, err.Error(), "limit")
}