harness-drone/store/batch2/batch_test.go
2021-05-04 18:59:03 -04:00

397 lines
9.1 KiB
Go

// Copyright 2019 Drone.IO Inc. All rights reserved.
// Use of this source code is governed by the Drone Non-Commercial License
// that can be found in the LICENSE file.
package batch2
import (
"context"
"database/sql"
"testing"
"github.com/drone/drone/core"
"github.com/drone/drone/store/perm"
"github.com/drone/drone/store/repos"
"github.com/drone/drone/store/shared/db"
"github.com/drone/drone/store/shared/db/dbtest"
"github.com/drone/drone/store/shared/encrypt"
"github.com/drone/drone/store/user"
)
var noContext = context.TODO()
func TestBatch(t *testing.T) {
conn, err := dbtest.Connect()
if err != nil {
t.Error(err)
return
}
defer func() {
dbtest.Reset(conn)
dbtest.Disconnect(conn)
}()
batcher := New(conn).(*batchUpdater)
repos := repos.New(conn)
perms := perm.New(conn)
user, err := seedUser(batcher.db)
if err != nil {
t.Error(err)
}
t.Run("Insert", testBatchInsert(batcher, repos, perms, user))
t.Run("Update", testBatchUpdate(batcher, repos, perms, user))
t.Run("Delete", testBatchDelete(batcher, repos, perms, user))
t.Run("DuplicateID", testBatchDuplicateID(batcher, repos, perms, user))
t.Run("DuplicateSlug", testBatchDuplicateSlug(batcher, repos, perms, user))
t.Run("DuplicateRename", testBatchDuplicateRename(batcher, repos, perms, user))
t.Run("DuplicateRecreateRename", testBatchDuplicateRecreateRename(batcher, repos, perms, user))
}
func testBatchInsert(
batcher core.Batcher,
repos core.RepositoryStore,
perms core.PermStore,
user *core.User,
) func(t *testing.T) {
return func(t *testing.T) {
batch := &core.Batch{
Insert: []*core.Repository{
{
UserID: 1,
UID: "42",
Namespace: "octocat",
Name: "hello-world",
Slug: "octocat/hello-world",
Private: false,
Visibility: "public",
},
},
}
err := batcher.Batch(noContext, user, batch)
if err != nil {
t.Error(err)
}
repo, err := repos.FindName(noContext, "octocat", "hello-world")
if err != nil {
t.Errorf("Want repository, got error %q", err)
}
_, err = perms.Find(noContext, repo.UID, user.ID)
if err != nil {
t.Errorf("Want permissions, got error %q", err)
}
}
}
func testBatchUpdate(
batcher core.Batcher,
repos core.RepositoryStore,
perms core.PermStore,
user *core.User,
) func(t *testing.T) {
return func(t *testing.T) {
before, err := repos.FindName(noContext, "octocat", "hello-world")
if err != nil {
t.Errorf("Want repository, got error %q", err)
}
batch := &core.Batch{
Update: []*core.Repository{
{
ID: before.ID,
UserID: 1,
UID: "42",
Namespace: "octocat",
Name: "hello-world",
Slug: "octocat/hello-world",
Private: true,
},
},
}
err = batcher.Batch(noContext, user, batch)
if err != nil {
t.Error(err)
}
after, err := repos.FindName(noContext, "octocat", "hello-world")
if err != nil {
t.Errorf("Want repository, got error %q", err)
}
if got, want := after.Private, true; got != want {
t.Errorf("Want repository Private %v, got %v", want, got)
}
}
}
func testBatchDelete(
batcher core.Batcher,
repos core.RepositoryStore,
perms core.PermStore,
user *core.User,
) func(t *testing.T) {
return func(t *testing.T) {
repo, err := repos.FindName(noContext, "octocat", "hello-world")
if err != nil {
t.Errorf("Want repository, got error %q", err)
}
_, err = perms.Find(noContext, repo.UID, user.ID)
if err != nil {
t.Errorf("Want permissions, got error %q", err)
}
batch := &core.Batch{
Revoke: []*core.Repository{
{
ID: repo.ID,
UserID: 1,
UID: "42",
Namespace: "octocat",
Name: "hello-world",
Slug: "octocat/hello-world",
Private: true,
},
},
}
err = batcher.Batch(noContext, user, batch)
if err != nil {
t.Error(err)
}
_, err = perms.Find(noContext, repo.UID, user.ID)
if err != sql.ErrNoRows {
t.Errorf("Want sql.ErrNoRows got %v", err)
}
}
}
func testBatchDuplicateID(
batcher core.Batcher,
repos core.RepositoryStore,
perms core.PermStore,
user *core.User,
) func(t *testing.T) {
return func(t *testing.T) {
before, err := repos.FindName(noContext, "octocat", "hello-world")
if err != nil {
t.Errorf("Want repository, got error %q", err)
}
batchDuplicate := &core.Batch{
Insert: []*core.Repository{
{
ID: 0,
UserID: 1,
UID: "43", // Updated ID
Namespace: "octocat",
Name: "hello-world",
Slug: "octocat/hello-world",
},
{
ID: 0,
UserID: 1,
UID: "43", // Updated ID
Namespace: "octocat",
Name: "hello-world",
Slug: "octocat/hello-world",
},
},
}
err = batcher.Batch(noContext, user, batchDuplicate)
if err != nil {
t.Error(err)
return
}
batch := &core.Batch{
Insert: []*core.Repository{
{
ID: 0,
UserID: 1,
UID: "64778136",
Namespace: "octocat",
Name: "linguist",
Slug: "octocat/linguist",
},
},
Update: []*core.Repository{
{
ID: before.ID,
UserID: 1,
UID: "44", // Updated ID
Namespace: "octocat",
Name: "hello-world",
Slug: "octocat/hello-world",
Private: true,
},
},
}
err = batcher.Batch(noContext, user, batch)
if err != nil {
t.Error(err)
return
}
added, err := repos.FindName(noContext, "octocat", "linguist")
if err != nil {
t.Errorf("Want inserted repository, got error %q", err)
}
if got, want := added.UID, "64778136"; got != want {
t.Errorf("Want inserted repository UID %v, got %v", want, got)
}
renamed, err := repos.FindName(noContext, "octocat", "hello-world")
if err != nil {
t.Errorf("Want renamed repository, got error %q", err)
}
if got, want := renamed.UID, "44"; got != want {
t.Errorf("Want renamed repository UID %v, got %v", want, got)
}
}
}
// the purpose of this unit test is to understand what happens
// when a repository is deleted, re-created with the same name,
// but has a different unique identifier.
func testBatchDuplicateSlug(
batcher core.Batcher,
repos core.RepositoryStore,
perms core.PermStore,
user *core.User,
) func(t *testing.T) {
return func(t *testing.T) {
_, err := repos.FindName(noContext, "octocat", "hello-world")
if err != nil {
t.Errorf("Want repository, got error %q", err)
return
}
batch := &core.Batch{
Insert: []*core.Repository{
{
ID: 0,
UserID: 1,
UID: "99", // Updated ID
Namespace: "octocat",
Name: "hello-world",
Slug: "octocat/hello-world",
},
},
}
err = batcher.Batch(noContext, user, batch)
if err != nil {
t.Error(err)
}
}
}
// the purpose of this unit test is to understand what happens
// when a repository is deleted, re-created with a different name,
// renamed to the original name, but has a different unique identifier.
func testBatchDuplicateRecreateRename(
batcher core.Batcher,
repos core.RepositoryStore,
perms core.PermStore,
user *core.User,
) func(t *testing.T) {
return func(t *testing.T) {
_, err := repos.FindName(noContext, "octocat", "hello-world")
if err != nil {
t.Errorf("Want repository, got error %q", err)
return
}
batch := &core.Batch{
Update: []*core.Repository{
{
ID: 0,
UserID: 1,
UID: "8888", // Updated ID
Namespace: "octocat",
Name: "hello-world",
Slug: "octocat/hello-world",
},
},
}
err = batcher.Batch(noContext, user, batch)
if err != nil {
t.Error(err)
}
}
}
// the purpose of this unit test is to understand what happens
// when a repository is deleted, re-created with a new name, and
// then updated back to the old name.
//
// TODO(bradrydzewski) for sqlite consider UPDATE OR REPLACE.
// TODO(bradrydzewski) for mysql consider UPDATE IGNORE.
// TODO(bradrydzewski) consider breaking rename into a separate set of logic that checks for existing records.
func testBatchDuplicateRename(
batcher core.Batcher,
repos core.RepositoryStore,
perms core.PermStore,
user *core.User,
) func(t *testing.T) {
return func(t *testing.T) {
batch := &core.Batch{
Insert: []*core.Repository{
{
ID: 0,
UserID: 1,
UID: "200",
Namespace: "octocat",
Name: "test-1",
Slug: "octocat/test-1",
},
{
ID: 0,
UserID: 1,
UID: "201",
Namespace: "octocat",
Name: "test-2",
Slug: "octocat/test-2",
},
},
}
err := batcher.Batch(noContext, user, batch)
if err != nil {
t.Error(err)
return
}
before, err := repos.FindName(noContext, "octocat", "test-2")
if err != nil {
t.Errorf("Want repository, got error %q", err)
return
}
before.Name = "test-1"
before.Slug = "octocat/test-1"
batch = &core.Batch{
Update: []*core.Repository{before},
}
err = batcher.Batch(noContext, user, batch)
if err != nil {
t.Skip(err)
}
}
}
func seedUser(db *db.DB) (*core.User, error) {
enc, _ := encrypt.New("")
out := &core.User{Login: "octocat"}
err := user.New(db, enc).Create(noContext, out)
return out, err
}