// 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 repos import ( "context" "encoding/json" "io/ioutil" "testing" "github.com/drone/drone/store/shared/db" "github.com/drone/drone/store/shared/db/dbtest" "github.com/drone/drone/core" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" ) var noContext = context.TODO() func TestRepo(t *testing.T) { conn, err := dbtest.Connect() if err != nil { t.Error(err) return } defer func() { dbtest.Reset(conn) dbtest.Disconnect(conn) }() store := New(conn).(*repoStore) t.Run("Create", testRepoCreate(store)) t.Run("Count", testRepoCount(store)) t.Run("Find", testRepoFind(store)) t.Run("FindName", testRepoFindName(store)) t.Run("List", testRepoList(store)) t.Run("ListLatest", testRepoListLatest(store)) t.Run("Update", testRepoUpdate(store)) t.Run("Activate", testRepoActivate(store)) t.Run("Locking", testRepoLocking(store)) t.Run("Increment", testRepoIncrement(store)) t.Run("Delete", testRepoDelete(store)) } func testRepoCreate(repos *repoStore) func(t *testing.T) { return func(t *testing.T) { out, err := ioutil.ReadFile("testdata/repo.json") if err != nil { t.Error(err) return } repo := &core.Repository{} err = json.Unmarshal(out, repo) if err != nil { t.Error(err) return } err = repos.Create(noContext, repo) if err != nil { t.Error(err) } if got := repo.ID; got == 0 { t.Errorf("Want non-zero ID") } if got, want := repo.Version, int64(1); got != want { t.Errorf("Want Version %d, got %d", want, got) } err = repos.db.Update(func(execer db.Execer, binder db.Binder) error { query, args, _ := binder.BindNamed(stmtPermInsert, map[string]interface{}{ "perm_user_id": 1, "perm_repo_uid": repo.UID, "perm_read": true, "perm_write": true, "perm_admin": true, "perm_synced": 0, "perm_created": 0, "perm_updated": 0, }) _, err = execer.Exec(query, args...) return err }) if err != nil { t.Error(err) } } } func testRepoCount(repos *repoStore) func(t *testing.T) { return func(t *testing.T) { count, err := repos.Count(noContext) if err != nil { t.Error(err) } if got, want := count, int64(1); got != want { t.Errorf("Want count %d, got %d", want, got) } } } func testRepoFind(repos *repoStore) func(t *testing.T) { return func(t *testing.T) { named, err := repos.FindName(noContext, "octocat", "hello-world") if err != nil { t.Error(err) return } got, err := repos.Find(noContext, named.ID) if err != nil { t.Error(err) return } want := &core.Repository{} raw, err := ioutil.ReadFile("testdata/repo.json.golden") if err != nil { t.Error(err) return } err = json.Unmarshal(raw, want) if err != nil { t.Error(err) return } ignore := cmpopts.IgnoreFields(core.Repository{}, "ID") if diff := cmp.Diff(got, want, ignore); len(diff) != 0 { t.Errorf(diff) } } } func testRepoFindName(repos *repoStore) func(t *testing.T) { return func(t *testing.T) { got, err := repos.FindName(noContext, "octocat", "hello-world") if err != nil { t.Error(err) return } want := &core.Repository{} raw, err := ioutil.ReadFile("testdata/repo.json.golden") if err != nil { t.Error(err) return } err = json.Unmarshal(raw, want) if err != nil { t.Error(err) return } ignore := cmpopts.IgnoreFields(core.Repository{}, "ID") if diff := cmp.Diff(got, want, ignore); len(diff) != 0 { t.Errorf(diff) } } } func testRepoList(repos *repoStore) func(t *testing.T) { return func(t *testing.T) { repos, err := repos.List(noContext, 1) if err != nil { t.Error(err) return } if got, want := len(repos), 1; got != want { t.Errorf("Want Repo count %d, got %d", want, got) return } if err != nil { t.Error(err) return } got, want := repos[0], &core.Repository{} raw, err := ioutil.ReadFile("testdata/repo.json.golden") if err != nil { t.Error(err) return } err = json.Unmarshal(raw, want) if err != nil { t.Error(err) return } ignore := cmpopts.IgnoreFields(core.Repository{}, "ID") if diff := cmp.Diff(got, want, ignore); len(diff) != 0 { t.Errorf(diff) } } } func testRepoListLatest(repos *repoStore) func(t *testing.T) { return func(t *testing.T) { repos, err := repos.ListLatest(noContext, 1) if err != nil { t.Error(err) return } if got, want := len(repos), 1; got != want { t.Errorf("Want Repo count %d, got %d", want, got) } else if repos[0].Build != nil { t.Errorf("Expect nil build") } else { t.Run("Fields", testRepo(repos[0])) } } } func testRepoUpdate(repos *repoStore) func(t *testing.T) { return func(t *testing.T) { before, err := repos.FindName(noContext, "octocat", "hello-world") if err != nil { t.Error(err) return } version := before.Version before.Private = true err = repos.Update(noContext, before) if err != nil { t.Error(err) return } after, err := repos.Find(noContext, before.ID) if err != nil { t.Error(err) return } if got, want := after.Version, version+1; got != want { t.Errorf("Want version incremented on update") } if got, want := before.Private, after.Private; got != want { t.Errorf("Want updated Repo private %v, got %v", want, got) } } } func testRepoActivate(repos *repoStore) func(t *testing.T) { return func(t *testing.T) { before, err := repos.FindName(noContext, "octocat", "hello-world") if err != nil { t.Error(err) return } before.Active = true err = repos.Activate(noContext, before) if err != nil { t.Error(err) return } after, err := repos.Find(noContext, before.ID) if err != nil { t.Error(err) return } if got, want := before.Active, after.Active; got != want { t.Errorf("Want updated Repo Active %v, got %v", want, got) } } } func testRepoLocking(repos *repoStore) func(t *testing.T) { return func(t *testing.T) { repo, err := repos.FindName(noContext, "octocat", "hello-world") if err != nil { t.Error(err) return } repo.Version = 1 err = repos.Update(noContext, repo) if err == nil { t.Errorf("Want Optimistic Lock Error, got nil") } else if err != db.ErrOptimisticLock { t.Errorf("Want Optimistic Lock Error") } } } func testRepoIncrement(repos *repoStore) func(t *testing.T) { return func(t *testing.T) { repo, err := repos.FindName(noContext, "octocat", "hello-world") if err != nil { t.Error(err) return } before := repo.Counter repo.Version-- repo, err = repos.Increment(noContext, repo) if err != nil { t.Error(err) return } if got, want := repo.Counter, before+1; got != want { t.Errorf("Want count incremented to %d, got %d", want, got) } } } func testRepoDelete(repos *repoStore) func(t *testing.T) { return func(t *testing.T) { count, _ := repos.Count(noContext) if got, want := count, int64(1); got != want { t.Errorf("Want Repo table count %d, got %d", want, got) return } repo, err := repos.FindName(noContext, "octocat", "hello-world") if err != nil { return } err = repos.Delete(noContext, repo) if err != nil { t.Error(err) } count, _ = repos.Count(noContext) if got, want := count, int64(0); got != want { t.Errorf("Want Repo table count %d, got %d", want, got) return } } } func testRepo(repo *core.Repository) func(t *testing.T) { return func(t *testing.T) { if got, want := repo.UserID, int64(1); got != want { t.Errorf("Want UserID %d, got %d", want, got) } if got, want := repo.Namespace, "octocat"; got != want { t.Errorf("Want Namespace %q, got %q", want, got) } if got, want := repo.Name, "hello-world"; got != want { t.Errorf("Want Name %q, got %q", want, got) } if got, want := repo.Slug, "octocat/hello-world"; got != want { t.Errorf("Want Slug %q, got %q", want, got) } if got, want := repo.UID, "42"; got != want { t.Errorf("Want UID %q, got %q", want, got) } } }