Add integration tests for GetRootSpace, CountAll and GetSize spc and repo store methods (#969)

eb/code-1016-2
Darko Draskovic 2024-01-22 16:44:15 +00:00 committed by Harness
parent 29f781201f
commit a4d47e12b2
5 changed files with 329 additions and 8 deletions

View File

@ -16,6 +16,7 @@ package cache
import (
"context"
"time"
"github.com/harness/gitness/app/paths"
"github.com/harness/gitness/app/store"
@ -29,6 +30,20 @@ type pathCacheGetter struct {
spacePathStore store.SpacePathStore
}
func New(
pathStore store.SpacePathStore,
spacePathTransformation store.SpacePathTransformation,
) store.SpacePathCache {
return &pathCache{
inner: cache.New[string, *types.SpacePath](
&pathCacheGetter{
spacePathStore: pathStore,
},
1*time.Minute),
spacePathTransformation: spacePathTransformation,
}
}
func (g *pathCacheGetter) Find(ctx context.Context, key string) (*types.SpacePath, error) {
path, err := g.spacePathStore.FindByPath(ctx, key)
if err != nil {

View File

@ -41,14 +41,7 @@ func ProvidePathCache(
pathStore store.SpacePathStore,
spacePathTransformation store.SpacePathTransformation,
) store.SpacePathCache {
return &pathCache{
inner: cache.New[string, *types.SpacePath](
&pathCacheGetter{
spacePathStore: pathStore,
},
1*time.Minute),
spacePathTransformation: spacePathTransformation,
}
return New(pathStore, spacePathTransformation)
}
// ProvideRepoGitInfoCache provides a cache for storing types.RepositoryGitInfo objects.

View File

@ -0,0 +1,128 @@
// Copyright 2023 Harness, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package database_test
import (
"context"
"math/rand"
"strconv"
"testing"
"github.com/harness/gitness/app/store/database"
"github.com/harness/gitness/types"
)
const repoSize = int64(100)
func TestDatabase_GetSize(t *testing.T) {
db, teardown := setupDB(t)
defer teardown()
principalStore, spaceStore, spacePathStore, repoStore := setupStores(t, db)
ctx := context.Background()
createUser(t, &ctx, principalStore, 1)
createSpace(t, &ctx, spaceStore, spacePathStore, userID, 1, 0)
repoID := int64(1)
createRepo(t, &ctx, repoStore, repoID, 1, repoSize)
tests := []struct {
name string
Size int64
areSizesEq bool
}{
{
name: "size equal to repo size",
Size: repoSize,
areSizesEq: true,
},
{
name: "size less than repo size",
Size: repoSize / 2,
areSizesEq: false,
},
{
name: "size greater than repo size",
Size: repoSize * 2,
areSizesEq: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
size, err := repoStore.GetSize(ctx, repoID)
if err != nil {
t.Errorf("GetSize() error = %v, want error = %v", err, nil)
}
areSizesEq := size == tt.Size
if areSizesEq != tt.areSizesEq {
t.Errorf("size == tt.Size = %v, want %v", areSizesEq, tt.areSizesEq)
}
})
}
}
func TestDatabase_CountAll(t *testing.T) {
db, teardown := setupDB(t)
defer teardown()
principalStore, spaceStore, spacePathStore, repoStore := setupStores(t, db)
ctx := context.Background()
createUser(t, &ctx, principalStore, 1)
var numRepos int64
spaceTree, numSpaces := createSpaceTree()
createSpace(t, &ctx, spaceStore, spacePathStore, userID, 1, 0)
for i := 1; i < numSpaces; i++ {
parentID := int64(i)
for _, spaceID := range spaceTree[parentID] {
createSpace(t, &ctx, spaceStore, spacePathStore, userID, spaceID, parentID)
for j := 0; j < rand.Intn(4); j++ {
numRepos++
createRepo(t, &ctx, repoStore, numRepos, spaceID, 0)
}
}
}
count, err := repoStore.CountAll(ctx, 1)
if err != nil {
t.Fatalf("failed to count repos %v", err)
}
if count != numRepos {
t.Errorf("count = %v, want %v", count, numRepos)
}
}
func createRepo(
t *testing.T,
ctx *context.Context,
repoStore *database.RepoStore,
id int64,
spaceID int64,
size int64,
) {
t.Helper()
uid := "repo_" + strconv.FormatInt(id, 10)
repo := types.Repository{UID: uid, ID: id, ParentID: spaceID, GitUID: uid, Size: size}
if err := repoStore.Create(*ctx, &repo); err != nil {
t.Fatalf("failed to create repo %v", err)
}
}

View File

@ -0,0 +1,134 @@
// Copyright 2023 Harness, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package database_test
import (
"context"
"fmt"
"strconv"
"testing"
"github.com/harness/gitness/app/store"
"github.com/harness/gitness/app/store/cache"
"github.com/harness/gitness/app/store/database"
"github.com/harness/gitness/app/store/database/migrate"
"github.com/harness/gitness/types"
"github.com/jmoiron/sqlx"
"github.com/rs/xid"
)
var userID int64 = 1
func New(dsn string) (*sqlx.DB, error) {
if dsn == ":memory:" {
dsn = fmt.Sprintf("file:%s.db?mode=memory&cache=shared", xid.New().String())
}
db, err := sqlx.Connect("sqlite3", dsn)
if err != nil {
return nil, err
}
if _, err := db.Exec(`PRAGMA foreign_keys = ON;`); err != nil {
return nil, fmt.Errorf("foreign keys pragma: %w", err)
}
return db, nil
}
func setupDB(t *testing.T) (*sqlx.DB, func()) {
t.Helper()
db, err := New(":memory:")
if err != nil {
t.Fatalf("Error opening db, err: %v", err)
}
if err = migrate.Migrate(context.Background(), db); err != nil {
t.Fatalf("Error migrating db, err: %v", err)
}
return db, func() {
db.Close()
}
}
func setupStores(t *testing.T, db *sqlx.DB) (
*database.PrincipalStore,
*database.SpaceStore,
store.SpacePathStore,
*database.RepoStore,
) {
t.Helper()
principalStore := database.NewPrincipalStore(db, store.ToLowerPrincipalUIDTransformation)
spacePathTransformation := store.ToLowerSpacePathTransformation
spacePathStore := database.NewSpacePathStore(db, store.ToLowerSpacePathTransformation)
spacePathCache := cache.New(spacePathStore, spacePathTransformation)
spaceStore := database.NewSpaceStore(db, spacePathCache, spacePathStore)
repoStore := database.NewRepoStore(db, spacePathCache, spacePathStore)
return principalStore, spaceStore, spacePathStore, repoStore
}
func createUser(
t *testing.T,
ctx *context.Context,
principalStore *database.PrincipalStore,
userID int64,
) {
t.Helper()
uid := "user_" + strconv.FormatInt(userID, 10)
if err := principalStore.CreateUser(*ctx,
&types.User{ID: userID, UID: uid}); err != nil {
t.Fatalf("failed to create user %v", err)
}
}
func createSpace(
t *testing.T,
ctx *context.Context,
spaceStore *database.SpaceStore,
spacePathStore store.SpacePathStore,
userID int64,
spaceID int64,
parentID int64,
) {
t.Helper()
uid := "space_" + strconv.FormatInt(spaceID, 10)
space := types.Space{ID: spaceID, UID: uid, CreatedBy: userID, ParentID: parentID}
if err := spaceStore.Create(*ctx, &space); err != nil {
t.Fatalf("failed to create space %v", err)
}
if err := spacePathStore.InsertSegment(*ctx, &types.SpacePathSegment{
ID: space.ID, UID: uid, CreatedBy: userID, SpaceID: spaceID, IsPrimary: true,
}); err != nil {
t.Fatalf("failed to insert segment %v", err)
}
}
func createSpaceTree() (map[int64][]int64, int) {
spaceTree := make(map[int64][]int64)
spaceTree[1] = []int64{2, 3}
spaceTree[2] = []int64{4, 5, 6}
spaceTree[3] = []int64{7, 8}
spaceTree[4] = []int64{9, 10}
spaceTree[5] = []int64{11}
return spaceTree, 11
}

View File

@ -0,0 +1,51 @@
// Copyright 2023 Harness, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package database_test
import (
"context"
"testing"
)
func TestDatabase_GetRootSpace(t *testing.T) {
db, teardown := setupDB(t)
defer teardown()
principalStore, spaceStore, spacePathStore, _ := setupStores(t, db)
ctx := context.Background()
createUser(t, &ctx, principalStore, 1)
spaceTree, numSpaces := createSpaceTree()
createSpace(t, &ctx, spaceStore, spacePathStore, userID, 1, 0)
for i := 1; i < numSpaces; i++ {
parentID := int64(i)
for _, spaceID := range spaceTree[parentID] {
createSpace(t, &ctx, spaceStore, spacePathStore, 1, spaceID, parentID)
}
}
for i := 1; i <= numSpaces; i++ {
rootSpc, err := spaceStore.GetRootSpace(ctx, int64(i))
if err != nil {
t.Fatalf("failed to get root space %v", err)
}
if rootSpc.ID != 1 {
t.Errorf("rootSpc.ID = %v, want %v", rootSpc.ID, 1)
}
}
}