repo_testing.go

  1package repository
  2
  3import (
  4	"log"
  5	"math/rand"
  6	"os"
  7	"strings"
  8	"testing"
  9
 10	"github.com/stretchr/testify/assert"
 11	"github.com/stretchr/testify/require"
 12)
 13
 14func CleanupTestRepos(repos ...Repo) {
 15	var firstErr error
 16	for _, repo := range repos {
 17		path := repo.GetPath()
 18		if strings.HasSuffix(path, "/.git") {
 19			// for a normal repository (not --bare), we want to remove everything
 20			// including the parent directory where files are checked out
 21			path = strings.TrimSuffix(path, "/.git")
 22
 23			// Testing non-bare repo should also check path is
 24			// only .git (i.e. ./.git), but doing so, we should
 25			// try to remove the current directory and hav some
 26			// trouble. In the present case, this case should not
 27			// occur.
 28			// TODO consider warning or error when path == ".git"
 29		}
 30		// fmt.Println("Cleaning repo:", path)
 31		err := os.RemoveAll(path)
 32		if err != nil {
 33			log.Println(err)
 34			if firstErr == nil {
 35				firstErr = err
 36			}
 37		}
 38	}
 39
 40	if firstErr != nil {
 41		log.Fatal(firstErr)
 42	}
 43}
 44
 45type RepoCreator func(bare bool) TestedRepo
 46type RepoCleaner func(repos ...Repo)
 47
 48// Test suite for a Repo implementation
 49func RepoTest(t *testing.T, creator RepoCreator, cleaner RepoCleaner) {
 50	t.Run("Blob-Tree-Commit-Ref", func(t *testing.T) {
 51		repo := creator(false)
 52		defer cleaner(repo)
 53
 54		// Blob
 55
 56		data := randomData()
 57
 58		blobHash1, err := repo.StoreData(data)
 59		require.NoError(t, err)
 60		assert.True(t, blobHash1.IsValid())
 61
 62		blob1Read, err := repo.ReadData(blobHash1)
 63		require.NoError(t, err)
 64		assert.Equal(t, data, blob1Read)
 65
 66		// Tree
 67
 68		blobHash2, err := repo.StoreData(randomData())
 69		require.NoError(t, err)
 70		blobHash3, err := repo.StoreData(randomData())
 71		require.NoError(t, err)
 72
 73		tree1 := []TreeEntry{
 74			{
 75				ObjectType: Blob,
 76				Hash:       blobHash1,
 77				Name:       "blob1",
 78			},
 79			{
 80				ObjectType: Blob,
 81				Hash:       blobHash2,
 82				Name:       "blob2",
 83			},
 84		}
 85
 86		treeHash1, err := repo.StoreTree(tree1)
 87		require.NoError(t, err)
 88		assert.True(t, treeHash1.IsValid())
 89
 90		tree1Read, err := repo.ReadTree(treeHash1)
 91		require.NoError(t, err)
 92		assert.ElementsMatch(t, tree1, tree1Read)
 93
 94		tree2 := []TreeEntry{
 95			{
 96				ObjectType: Tree,
 97				Hash:       treeHash1,
 98				Name:       "tree1",
 99			},
100			{
101				ObjectType: Blob,
102				Hash:       blobHash3,
103				Name:       "blob3",
104			},
105		}
106
107		treeHash2, err := repo.StoreTree(tree2)
108		require.NoError(t, err)
109		assert.True(t, treeHash2.IsValid())
110
111		tree2Read, err := repo.ReadTree(treeHash2)
112		require.NoError(t, err)
113		assert.ElementsMatch(t, tree2, tree2Read)
114
115		// Commit
116
117		commit1, err := repo.StoreCommit(treeHash1)
118		require.NoError(t, err)
119		assert.True(t, commit1.IsValid())
120
121		treeHash1Read, err := repo.GetTreeHash(commit1)
122		require.NoError(t, err)
123		assert.Equal(t, treeHash1, treeHash1Read)
124
125		commit2, err := repo.StoreCommitWithParent(treeHash2, commit1)
126		require.NoError(t, err)
127		assert.True(t, commit2.IsValid())
128
129		treeHash2Read, err := repo.GetTreeHash(commit2)
130		require.NoError(t, err)
131		assert.Equal(t, treeHash2, treeHash2Read)
132
133		// Ref
134
135		exist1, err := repo.RefExist("refs/bugs/ref1")
136		require.NoError(t, err)
137		assert.False(t, exist1)
138
139		err = repo.UpdateRef("refs/bugs/ref1", commit2)
140		require.NoError(t, err)
141
142		exist1, err = repo.RefExist("refs/bugs/ref1")
143		require.NoError(t, err)
144		assert.True(t, exist1)
145
146		ls, err := repo.ListRefs("refs/bugs")
147		require.NoError(t, err)
148		assert.ElementsMatch(t, []string{"refs/bugs/ref1"}, ls)
149
150		err = repo.CopyRef("refs/bugs/ref1", "refs/bugs/ref2")
151		require.NoError(t, err)
152
153		ls, err = repo.ListRefs("refs/bugs")
154		require.NoError(t, err)
155		assert.ElementsMatch(t, []string{"refs/bugs/ref1", "refs/bugs/ref2"}, ls)
156
157		commits, err := repo.ListCommits("refs/bugs/ref2")
158		require.NoError(t, err)
159		assert.ElementsMatch(t, []Hash{commit1, commit2}, commits)
160
161		// Graph
162
163		commit3, err := repo.StoreCommitWithParent(treeHash1, commit1)
164		require.NoError(t, err)
165
166		ancestorHash, err := repo.FindCommonAncestor(commit2, commit3)
167		require.NoError(t, err)
168		assert.Equal(t, commit1, ancestorHash)
169
170		err = repo.RemoveRef("refs/bugs/ref1")
171		require.NoError(t, err)
172	})
173
174	t.Run("Local config", func(t *testing.T) {
175		repo := creator(false)
176		defer cleaner(repo)
177
178		testConfig(t, repo.LocalConfig())
179	})
180}
181
182func randomData() []byte {
183	var letterRunes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
184	b := make([]byte, 32)
185	for i := range b {
186		b[i] = letterRunes[rand.Intn(len(letterRunes))]
187	}
188	return b
189}