336 lines
7.6 KiB
Go
336 lines
7.6 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 batch
|
|
|
|
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/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))
|
|
}
|
|
|
|
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)
|
|
}
|
|
|
|
batch := &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",
|
|
},
|
|
{
|
|
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)
|
|
}
|
|
|
|
added, err := repos.FindName(noContext, "octocat", "linguist")
|
|
if err != nil {
|
|
t.Errorf("Want repository, got error %q", err)
|
|
}
|
|
|
|
if got, want := added.UID, "64778136"; got != want {
|
|
t.Errorf("Want added 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)
|
|
}
|
|
|
|
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 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) {
|
|
out := &core.User{Login: "octocat"}
|
|
err := user.New(db).Create(noContext, out)
|
|
return out, err
|
|
}
|