package odb import ( "bytes" "compress/zlib" "encoding/hex" "fmt" "io" "io/ioutil" "strings" "testing" "time" "github.com/git-lfs/git-lfs/git" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestDecodeBlob(t *testing.T) { sha := "af5626b4a114abcb82d63db7c8082c3c4756e51b" contents := "Hello, world!\n" var buf bytes.Buffer zw := zlib.NewWriter(&buf) fmt.Fprintf(zw, "blob 14\x00%s", contents) zw.Close() odb := &ObjectDatabase{s: newMemoryStorer(map[string]io.ReadWriter{ sha: &buf, })} shaHex, _ := hex.DecodeString(sha) blob, err := odb.Blob(shaHex) assert.Nil(t, err) assert.EqualValues(t, 14, blob.Size) got, err := ioutil.ReadAll(blob.Contents) assert.Nil(t, err) assert.Equal(t, contents, string(got)) } func TestDecodeTree(t *testing.T) { sha := "fcb545d5746547a597811b7441ed8eba307be1ff" hexSha, err := hex.DecodeString(sha) require.Nil(t, err) blobSha := "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391" hexBlobSha, err := hex.DecodeString(blobSha) require.Nil(t, err) var buf bytes.Buffer zw := zlib.NewWriter(&buf) fmt.Fprintf(zw, "tree 37\x00") fmt.Fprintf(zw, "100644 hello.txt\x00") zw.Write(hexBlobSha) zw.Close() odb := &ObjectDatabase{s: newMemoryStorer(map[string]io.ReadWriter{ sha: &buf, })} tree, err := odb.Tree(hexSha) assert.Nil(t, err) require.Equal(t, 1, len(tree.Entries)) assert.Equal(t, &TreeEntry{ Name: "hello.txt", Type: BlobObjectType, Oid: hexBlobSha, Filemode: 0100644, }, tree.Entries[0]) } func TestDecodeCommit(t *testing.T) { sha := "d7283480bb6dc90be621252e1001a93871dcf511" commitShaHex, err := hex.DecodeString(sha) assert.Nil(t, err) var buf bytes.Buffer zw := zlib.NewWriter(&buf) fmt.Fprintf(zw, "commit 173\x00") fmt.Fprintf(zw, "tree fcb545d5746547a597811b7441ed8eba307be1ff\n") fmt.Fprintf(zw, "author Taylor Blau 1494620424 -0600\n") fmt.Fprintf(zw, "committer Taylor Blau 1494620424 -0600\n") fmt.Fprintf(zw, "\ninitial commit\n") zw.Close() odb := &ObjectDatabase{s: newMemoryStorer(map[string]io.ReadWriter{ sha: &buf, })} commit, err := odb.Commit(commitShaHex) assert.Nil(t, err) assert.Equal(t, "Taylor Blau 1494620424 -0600", commit.Author) assert.Equal(t, "Taylor Blau 1494620424 -0600", commit.Committer) assert.Equal(t, "initial commit", commit.Message) assert.Equal(t, 0, len(commit.ParentIDs)) assert.Equal(t, "fcb545d5746547a597811b7441ed8eba307be1ff", hex.EncodeToString(commit.TreeID)) } func TestWriteBlob(t *testing.T) { fs := newMemoryStorer(make(map[string]io.ReadWriter)) odb := &ObjectDatabase{s: fs} sha, err := odb.WriteBlob(&Blob{ Size: 14, Contents: strings.NewReader("Hello, world!\n"), }) expected := "af5626b4a114abcb82d63db7c8082c3c4756e51b" assert.Nil(t, err) assert.Equal(t, expected, hex.EncodeToString(sha)) assert.NotNil(t, fs.fs[hex.EncodeToString(sha)]) } func TestWriteTree(t *testing.T) { fs := newMemoryStorer(make(map[string]io.ReadWriter)) odb := &ObjectDatabase{s: fs} blobSha := "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391" hexBlobSha, err := hex.DecodeString(blobSha) require.Nil(t, err) sha, err := odb.WriteTree(&Tree{Entries: []*TreeEntry{ { Name: "hello.txt", Type: BlobObjectType, Oid: hexBlobSha, Filemode: 0100644, }, }}) expected := "fcb545d5746547a597811b7441ed8eba307be1ff" assert.Nil(t, err) assert.Equal(t, expected, hex.EncodeToString(sha)) assert.NotNil(t, fs.fs[hex.EncodeToString(sha)]) } func TestWriteCommit(t *testing.T) { fs := newMemoryStorer(make(map[string]io.ReadWriter)) odb := &ObjectDatabase{s: fs} when := time.Unix(1257894000, 0).UTC() author := &Signature{Name: "John Doe", Email: "john@example.com", When: when} committer := &Signature{Name: "Jane Doe", Email: "jane@example.com", When: when} tree := "fcb545d5746547a597811b7441ed8eba307be1ff" treeHex, err := hex.DecodeString(tree) assert.Nil(t, err) sha, err := odb.WriteCommit(&Commit{ Author: author.String(), Committer: committer.String(), TreeID: treeHex, Message: "initial commit", }) expected := "fee8a35c2890cd6e0e28d24cc457fcecbd460962" assert.Nil(t, err) assert.Equal(t, expected, hex.EncodeToString(sha)) assert.NotNil(t, fs.fs[hex.EncodeToString(sha)]) } func TestReadingAMissingObject(t *testing.T) { sha, _ := hex.DecodeString("af5626b4a114abcb82d63db7c8082c3c4756e51b") out := strings.NewReader(fmt.Sprintf("%x blob 14\nHello, world!\n", sha)) db := &ObjectDatabase{ s: newMemoryStorer(nil), objectScanner: git.NewObjectScannerFrom(out), } blob, err := db.Blob(sha) assert.Nil(t, err) assert.EqualValues(t, 14, blob.Size) contents, err := ioutil.ReadAll(blob.Contents) assert.Nil(t, err) assert.Equal(t, "Hello, world!\n", string(contents)) } func TestReadingAMissingObjectAfterClose(t *testing.T) { sha, _ := hex.DecodeString("af5626b4a114abcb82d63db7c8082c3c4756e51b") db := &ObjectDatabase{ s: newMemoryStorer(nil), closed: 1, } blob, err := db.Blob(sha) assert.EqualError(t, err, "git/odb: cannot use closed *git.ObjectScanner") assert.Nil(t, blob) } func TestClosingAnObjectDatabaseMoreThanOnce(t *testing.T) { db, err := FromFilesystem("/tmp") assert.Nil(t, err) assert.Nil(t, db.Close()) assert.EqualError(t, db.Close(), "git/odb: *ObjectDatabase already closed") } func TestObjectDatabaseRootWithRoot(t *testing.T) { db, err := FromFilesystem("/foo/bar/baz") assert.Nil(t, err) root, ok := db.Root() assert.Equal(t, "/foo/bar/baz", root) assert.True(t, ok) } func TestObjectDatabaseRootWithoutRoot(t *testing.T) { root, ok := new(ObjectDatabase).Root() assert.Equal(t, "", root) assert.False(t, ok) }