repo: more tests

This commit is contained in:
Michael Muré 2020-06-27 22:00:15 +02:00
parent 1e3dd82fd6
commit 939bcd57b9
No known key found for this signature in database
GPG Key ID: A4457C029293126F
7 changed files with 181 additions and 28 deletions

View File

@ -138,7 +138,7 @@ func readBug(repo repository.ClockedRepo, ref string) (*Bug, error) {
// Load each OperationPack
for _, hash := range hashes {
entries, err := repo.ListEntries(hash)
entries, err := repo.ReadTree(hash)
if err != nil {
return nil, errors.Wrap(err, "can't list git tree entries")
}

View File

@ -118,7 +118,7 @@ func read(repo repository.Repo, ref string) (*Identity, error) {
}
for _, hash := range hashes {
entries, err := repo.ListEntries(hash)
entries, err := repo.ReadTree(hash)
if err != nil {
return nil, errors.Wrap(err, "can't list git tree entries")
}

View File

@ -5,10 +5,11 @@ import (
"strings"
"time"
"github.com/icrowley/fake"
"github.com/MichaelMure/git-bug/bug"
"github.com/MichaelMure/git-bug/identity"
"github.com/MichaelMure/git-bug/repository"
"github.com/icrowley/fake"
)
type opsGenerator func(bug.Interface, identity.Interface, int64)

View File

@ -337,8 +337,8 @@ func (repo *GitRepo) ListCommits(ref string) ([]git.Hash, error) {
}
// ListEntries will return the list of entries in a Git tree
func (repo *GitRepo) ListEntries(hash git.Hash) ([]TreeEntry, error) {
// ReadTree will return the list of entries in a Git tree
func (repo *GitRepo) ReadTree(hash git.Hash) ([]TreeEntry, error) {
stdout, err := repo.runGitCommand("ls-tree", string(hash))
if err != nil {

View File

@ -3,6 +3,7 @@ package repository
import (
"crypto/sha1"
"fmt"
"strings"
"github.com/MichaelMure/git-bug/util/git"
"github.com/MichaelMure/git-bug/util/lamport"
@ -151,12 +152,12 @@ func (r *mockRepoForTest) CopyRef(source string, dest string) error {
}
func (r *mockRepoForTest) ListRefs(refspec string) ([]string, error) {
keys := make([]string, len(r.refs))
var keys []string
i := 0
for k := range r.refs {
keys[i] = k
i++
if strings.HasPrefix(k, refspec) {
keys = append(keys, k)
}
}
return keys, nil
@ -181,7 +182,7 @@ func (r *mockRepoForTest) ListCommits(ref string) ([]git.Hash, error) {
return hashes, nil
}
func (r *mockRepoForTest) ListEntries(hash git.Hash) ([]TreeEntry, error) {
func (r *mockRepoForTest) ReadTree(hash git.Hash) ([]TreeEntry, error) {
var data string
data, ok := r.trees[hash]
@ -205,11 +206,44 @@ func (r *mockRepoForTest) ListEntries(hash git.Hash) ([]TreeEntry, error) {
}
func (r *mockRepoForTest) FindCommonAncestor(hash1 git.Hash, hash2 git.Hash) (git.Hash, error) {
panic("implement me")
ancestor1 := []git.Hash{hash1}
for hash1 != "" {
c, ok := r.commits[hash1]
if !ok {
return "", fmt.Errorf("unknown commit %v", hash1)
}
ancestor1 = append(ancestor1, c.parent)
hash1 = c.parent
}
for {
for _, ancestor := range ancestor1 {
if ancestor == hash2 {
return ancestor, nil
}
}
c, ok := r.commits[hash2]
if !ok {
return "", fmt.Errorf("unknown commit %v", hash1)
}
if c.parent == "" {
return "", fmt.Errorf("no ancestor found")
}
hash2 = c.parent
}
}
func (r *mockRepoForTest) GetTreeHash(commit git.Hash) (git.Hash, error) {
panic("implement me")
c, ok := r.commits[commit]
if !ok {
return "", fmt.Errorf("unknown commit")
}
return c.treeHash, nil
}
func (r *mockRepoForTest) GetOrCreateClock(name string) (lamport.Clock, error) {

View File

@ -66,12 +66,21 @@ type Repo interface {
// StoreTree will store a mapping key-->Hash as a Git tree
StoreTree(mapping []TreeEntry) (git.Hash, error)
// ReadTree will return the list of entries in a Git tree
ReadTree(hash git.Hash) ([]TreeEntry, error)
// StoreCommit will store a Git commit with the given Git tree
StoreCommit(treeHash git.Hash) (git.Hash, error)
// StoreCommit will store a Git commit with the given Git tree
StoreCommitWithParent(treeHash git.Hash, parent git.Hash) (git.Hash, error)
// GetTreeHash return the git tree hash referenced in a commit
GetTreeHash(commit git.Hash) (git.Hash, error)
// FindCommonAncestor will return the last common ancestor of two chain of commit
FindCommonAncestor(hash1 git.Hash, hash2 git.Hash) (git.Hash, error)
// UpdateRef will create or update a Git reference
UpdateRef(ref string, hash git.Hash) error
@ -86,15 +95,6 @@ type Repo interface {
// ListCommits will return the list of tree hashes of a ref, in chronological order
ListCommits(ref string) ([]git.Hash, error)
// ListEntries will return the list of entries in a Git tree
ListEntries(hash git.Hash) ([]TreeEntry, error)
// FindCommonAncestor will return the last common ancestor of two chain of commit
FindCommonAncestor(hash1 git.Hash, hash2 git.Hash) (git.Hash, error)
// GetTreeHash return the git tree hash referenced in a commit
GetTreeHash(commit git.Hash) (git.Hash, error)
}
// ClockedRepo is a Repo that also has Lamport clocks

View File

@ -2,12 +2,15 @@ package repository
import (
"log"
"math/rand"
"os"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/MichaelMure/git-bug/util/git"
)
func CleanupTestRepos(repos ...Repo) {
@ -46,19 +49,125 @@ type RepoCleaner func(repos ...Repo)
// Test suite for a Repo implementation
func RepoTest(t *testing.T, creator RepoCreator, cleaner RepoCleaner) {
t.Run("Read/Write data", func(t *testing.T) {
t.Run("Blob-Tree-Commit-Ref", func(t *testing.T) {
repo := creator(false)
defer cleaner(repo)
data := []byte("hello")
// Blob
h, err := repo.StoreData(data)
require.NoError(t, err)
assert.NotEmpty(t, h)
data := randomData()
read, err := repo.ReadData(h)
blobHash1, err := repo.StoreData(data)
require.NoError(t, err)
assert.Equal(t, data, read)
assert.True(t, blobHash1.IsValid())
blob1Read, err := repo.ReadData(blobHash1)
require.NoError(t, err)
assert.Equal(t, data, blob1Read)
// Tree
blobHash2, err := repo.StoreData(randomData())
require.NoError(t, err)
blobHash3, err := repo.StoreData(randomData())
require.NoError(t, err)
tree1 := []TreeEntry{
{
ObjectType: Blob,
Hash: blobHash1,
Name: "blob1",
},
{
ObjectType: Blob,
Hash: blobHash2,
Name: "blob2",
},
}
treeHash1, err := repo.StoreTree(tree1)
require.NoError(t, err)
assert.True(t, treeHash1.IsValid())
tree1Read, err := repo.ReadTree(treeHash1)
require.NoError(t, err)
assert.ElementsMatch(t, tree1, tree1Read)
tree2 := []TreeEntry{
{
ObjectType: Tree,
Hash: treeHash1,
Name: "tree1",
},
{
ObjectType: Blob,
Hash: blobHash3,
Name: "blob3",
},
}
treeHash2, err := repo.StoreTree(tree2)
require.NoError(t, err)
assert.True(t, treeHash2.IsValid())
tree2Read, err := repo.ReadTree(treeHash2)
require.NoError(t, err)
assert.ElementsMatch(t, tree2, tree2Read)
// Commit
commit1, err := repo.StoreCommit(treeHash1)
require.NoError(t, err)
assert.True(t, commit1.IsValid())
treeHash1Read, err := repo.GetTreeHash(commit1)
require.NoError(t, err)
assert.Equal(t, treeHash1, treeHash1Read)
commit2, err := repo.StoreCommitWithParent(treeHash2, commit1)
require.NoError(t, err)
assert.True(t, commit2.IsValid())
treeHash2Read, err := repo.GetTreeHash(commit2)
require.NoError(t, err)
assert.Equal(t, treeHash2, treeHash2Read)
// Ref
exist1, err := repo.RefExist("refs/bugs/ref1")
require.NoError(t, err)
assert.False(t, exist1)
err = repo.UpdateRef("refs/bugs/ref1", commit2)
require.NoError(t, err)
exist1, err = repo.RefExist("refs/bugs/ref1")
require.NoError(t, err)
assert.True(t, exist1)
ls, err := repo.ListRefs("refs/bugs")
require.NoError(t, err)
assert.Equal(t, []string{"refs/bugs/ref1"}, ls)
err = repo.CopyRef("refs/bugs/ref1", "refs/bugs/ref2")
require.NoError(t, err)
ls, err = repo.ListRefs("refs/bugs")
require.NoError(t, err)
assert.Equal(t, []string{"refs/bugs/ref1", "refs/bugs/ref2"}, ls)
commits, err := repo.ListCommits("refs/bugs/ref2")
require.NoError(t, err)
assert.Equal(t, []git.Hash{commit1, commit2}, commits)
// Graph
commit3, err := repo.StoreCommitWithParent(treeHash1, commit1)
require.NoError(t, err)
ancestorHash, err := repo.FindCommonAncestor(commit2, commit3)
require.NoError(t, err)
assert.Equal(t, commit1, ancestorHash)
})
t.Run("Local config", func(t *testing.T) {
@ -68,3 +177,12 @@ func RepoTest(t *testing.T, creator RepoCreator, cleaner RepoCleaner) {
testConfig(t, repo.LocalConfig())
})
}
func randomData() []byte {
var letterRunes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
b := make([]byte, 32)
for i := range b {
b[i] = letterRunes[rand.Intn(len(letterRunes))]
}
return b
}