test: improve pkg/gitinterface coverage from 69.4% to 76.2%

This PR adds focused tests for error paths and edge cases across
pkg/gitinterface, raising coverage from 69.4% to 76.2%.
Files changed:
- references_test.go: TestAbsoluteReference with branch/tag/custom/ref lookups
- tag_test.go: TestEnsureIsTag, error paths for GetTagTarget and verifyTagSignature
- commit_test.go: TestEnsureIsCommit, error paths for commit inspection helpers
- object_test.go: Error paths for GetObjectType and GetObjectSize
- blob_test.go: Error path for ReadBlob with non-blob object
- status_test.go: Tests for Status errors and StatusCode helpers
- sync_test.go: Tests for WithFetchDepth, CreateRemote, push/fetch errors
- config_test.go: Error path for SetGitConfig
- utils_test.go: TestResetDueToError
Closes #1244

Signed-off-by: dawgdevv <nraj02415@gmail.com>
This commit is contained in:
dawgdevv 2026-04-25 02:44:19 +05:30
parent 86a4ea6a7c
commit 8374150f3f
9 changed files with 406 additions and 1 deletions

View file

@ -32,7 +32,16 @@ func TestRepositoryReadBlob(t *testing.T) {
t.Run("read non-existing blob", func(t *testing.T) {
_, err := repo.ReadBlob(ZeroHash)
assert.NotNil(t, err)
assert.ErrorContains(t, err, "unable to inspect if object is blob")
})
t.Run("read non-blob object", func(t *testing.T) {
treeBuilder := NewTreeBuilder(repo)
treeID, err := treeBuilder.WriteTreeFromEntries(nil)
require.Nil(t, err)
_, err = repo.ReadBlob(treeID)
assert.ErrorContains(t, err, "is not a blob object")
})
}

View file

@ -18,7 +18,9 @@ import (
artifacts "github.com/gittuf/gittuf/internal/testartifacts"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/secure-systems-lab/go-securesystemslib/signerverifier"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestRepositoryCommit(t *testing.T) {
@ -247,6 +249,12 @@ func TestRepositoryVerifyCommit(t *testing.T) {
err = repo.verifyCommitSignature(context.Background(), gitsignSignedCommitID, sshKey)
assert.ErrorIs(t, err, ErrIncorrectVerificationKey)
})
t.Run("unknown signing method", func(t *testing.T) {
unknownKey := &signerverifier.SSLibKey{KeyType: "unknown"}
err = repo.verifyCommitSignature(t.Context(), sshSignedCommitID, unknownKey)
assert.ErrorIs(t, err, ErrUnknownSigningMethod)
})
}
func TestKnowsCommit(t *testing.T) {
@ -304,6 +312,22 @@ func TestKnowsCommit(t *testing.T) {
knows, _ := repo.KnowsCommit(unknownCommitID, firstCommitID)
assert.False(t, knows)
})
t.Run("non-commit object as first arg", func(t *testing.T) {
blobID, err := repo.WriteBlob([]byte("test"))
require.Nil(t, err)
_, err = repo.KnowsCommit(blobID, firstCommitID)
assert.ErrorContains(t, err, "is not a commit object")
})
t.Run("non-commit object as second arg", func(t *testing.T) {
blobID, err := repo.WriteBlob([]byte("test"))
require.Nil(t, err)
_, err = repo.KnowsCommit(firstCommitID, blobID)
assert.ErrorContains(t, err, "is not a commit object")
})
}
func createTestGPGSignedCommit(t *testing.T, repo *Repository) Hash {
@ -457,6 +481,14 @@ func TestRepositoryGetCommitMessage(t *testing.T) {
commitMessage, err := repo.GetCommitMessage(commit)
assert.Nil(t, err)
assert.Equal(t, message, commitMessage)
t.Run("non-commit object", func(t *testing.T) {
blobID, err := repo.WriteBlob([]byte("test"))
require.Nil(t, err)
_, err = repo.GetCommitMessage(blobID)
assert.ErrorContains(t, err, "is not a commit object")
})
}
func TestGetCommitTreeID(t *testing.T) {
@ -501,6 +533,14 @@ func TestGetCommitTreeID(t *testing.T) {
secondCommitTreeID, err := repo.GetCommitTreeID(secondCommitID)
assert.Nil(t, err)
assert.Equal(t, treeWithContentsID, secondCommitTreeID)
t.Run("non-commit object", func(t *testing.T) {
blobID, err := repo.WriteBlob([]byte("test"))
require.Nil(t, err)
_, err = repo.GetCommitTreeID(blobID)
assert.ErrorContains(t, err, "is not a commit object")
})
}
func TestGetCommitParentIDs(t *testing.T) {
@ -537,6 +577,11 @@ func TestGetCommitParentIDs(t *testing.T) {
secondCommitParentIDs, err := repo.GetCommitParentIDs(secondCommitID)
assert.Nil(t, err)
assert.Equal(t, []Hash{initialCommitID}, secondCommitParentIDs)
blobID, err := repo.WriteBlob([]byte("test"))
require.Nil(t, err)
_, err = repo.GetCommitParentIDs(blobID)
assert.ErrorContains(t, err, "is not a commit object")
}
func TestGetCommonAncestor(t *testing.T) {
@ -577,4 +622,50 @@ func TestGetCommonAncestor(t *testing.T) {
_, err = repo.GetCommonAncestor(commitDisconnected, commitA)
assert.NotNil(t, err)
t.Run("non-commit object as first arg", func(t *testing.T) {
blobID, err := repo.WriteBlob([]byte("test"))
require.Nil(t, err)
_, err = repo.GetCommonAncestor(blobID, commitA)
assert.ErrorContains(t, err, "is not a commit object")
})
t.Run("non-commit object as second arg", func(t *testing.T) {
blobID, err := repo.WriteBlob([]byte("test"))
require.Nil(t, err)
_, err = repo.GetCommonAncestor(commitA, blobID)
assert.ErrorContains(t, err, "is not a commit object")
})
}
func TestEnsureIsCommit(t *testing.T) {
tmpDir := t.TempDir()
repo := CreateTestGitRepository(t, tmpDir, false)
treeBuilder := NewTreeBuilder(repo)
emptyTreeID, err := treeBuilder.WriteTreeFromEntries(nil)
require.Nil(t, err)
commitID, err := repo.Commit(emptyTreeID, "refs/heads/main", "Initial commit\n", false)
require.Nil(t, err)
blobID, err := repo.WriteBlob([]byte("test"))
require.Nil(t, err)
t.Run("valid commit", func(t *testing.T) {
err := repo.ensureIsCommit(commitID)
assert.Nil(t, err)
})
t.Run("non-commit object", func(t *testing.T) {
err := repo.ensureIsCommit(blobID)
assert.ErrorContains(t, err, "is not a commit object")
})
t.Run("non-existent object", func(t *testing.T) {
err := repo.ensureIsCommit(ZeroHash)
assert.ErrorContains(t, err, "unable to inspect if object is commit")
})
}

View file

@ -71,4 +71,12 @@ func TestSetGitConfig(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, "", config["gpg.format"])
})
t.Run("invalid key", func(t *testing.T) {
tmpDir := t.TempDir()
repo := CreateTestGitRepository(t, tmpDir, false)
err := repo.SetGitConfig("", "value")
assert.ErrorContains(t, err, "unable to set")
})
}

View file

@ -98,6 +98,9 @@ func TestGetObjectType(t *testing.T) {
objType, err = repo.GetObjectType(tagID)
assert.Nil(t, err)
assert.Equal(t, TagObjectType, objType)
_, err = repo.GetObjectType(ZeroHash)
assert.ErrorContains(t, err, "unable to inspect object type")
}
func TestGetObjectSize(t *testing.T) {
@ -110,4 +113,7 @@ func TestGetObjectSize(t *testing.T) {
objSize, err := repo.GetObjectSize(blobID)
assert.Nil(t, err)
assert.Equal(t, uint64(6), objSize)
_, err = repo.GetObjectSize(ZeroHash)
assert.ErrorContains(t, err, "unable to inspect object size")
}

View file

@ -7,6 +7,7 @@ import (
"fmt"
"testing"
artifacts "github.com/gittuf/gittuf/internal/testartifacts"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@ -389,3 +390,74 @@ func TestRemoteReferenceName(t *testing.T) {
assert.Equal(t, test.expected, referenceName, fmt.Sprintf("unexpected remote reference for input %s", name))
}
}
func TestAbsoluteReference(t *testing.T) {
tmpDir := t.TempDir()
repo := CreateTestGitRepository(t, tmpDir, false)
treeBuilder := NewTreeBuilder(repo)
emptyTreeID, err := treeBuilder.WriteTreeFromEntries(nil)
require.Nil(t, err)
commitID, err := repo.Commit(emptyTreeID, "refs/heads/main", "Initial commit\n", false)
require.Nil(t, err)
_, err = repo.TagUsingSpecificKey(commitID, "v1.0", "v1.0\n", artifacts.SSHED25519Private)
require.Nil(t, err)
err = repo.SetReference("refs/custom/myref", commitID)
require.Nil(t, err)
err = repo.SetReference("refs/remotes/origin/main", commitID)
require.Nil(t, err)
err = repo.SetSymbolicReference("refs/remotes/origin/HEAD", "refs/remotes/origin/main")
require.Nil(t, err)
t.Run("symbolic ref HEAD", func(t *testing.T) {
ref, err := repo.AbsoluteReference("HEAD")
assert.Nil(t, err)
assert.Equal(t, "refs/heads/main", ref)
})
t.Run("fully qualified branch", func(t *testing.T) {
ref, err := repo.AbsoluteReference("refs/heads/main")
assert.Nil(t, err)
assert.Equal(t, "refs/heads/main", ref)
})
t.Run("short branch name", func(t *testing.T) {
ref, err := repo.AbsoluteReference("main")
assert.Nil(t, err)
assert.Equal(t, "refs/heads/main", ref)
})
t.Run("tag name", func(t *testing.T) {
ref, err := repo.AbsoluteReference("v1.0")
assert.Nil(t, err)
assert.Equal(t, "refs/tags/v1.0", ref)
})
t.Run("custom ref", func(t *testing.T) {
ref, err := repo.AbsoluteReference("custom/myref")
assert.Nil(t, err)
assert.Equal(t, "refs/custom/myref", ref)
})
t.Run("remote tracking ref", func(t *testing.T) {
ref, err := repo.AbsoluteReference("origin/main")
assert.Nil(t, err)
assert.Equal(t, "refs/remotes/origin/main", ref)
})
t.Run("remote HEAD", func(t *testing.T) {
ref, err := repo.AbsoluteReference("origin")
assert.Nil(t, err)
assert.Equal(t, "refs/remotes/origin/HEAD", ref)
})
t.Run("non-existent ref", func(t *testing.T) {
_, err := repo.AbsoluteReference("nonexistent")
assert.ErrorIs(t, err, ErrReferenceNotFound)
})
}

View file

@ -139,3 +139,85 @@ func TestStatus(t *testing.T) {
assert.Nil(t, err)
assert.Empty(t, statuses)
}
func TestStatusError(t *testing.T) {
tmpDir := t.TempDir()
repo := CreateTestGitRepository(t, tmpDir, true) // bare repo
_, err := repo.Status()
assert.ErrorContains(t, err, "unable to check status of repository")
}
func TestNewStatusCodeFromByte(t *testing.T) {
t.Run("invalid status code", func(t *testing.T) {
_, err := NewStatusCodeFromByte('X')
assert.ErrorIs(t, err, ErrInvalidStatusCode)
})
t.Run("valid status codes", func(t *testing.T) {
testCases := []struct {
input byte
expected StatusCode
}{
{' ', StatusCodeUnmodified},
{'M', StatusCodeModified},
{'T', StatusCodeTypeChanged},
{'A', StatusCodeAdded},
{'D', StatusCodeDeleted},
{'C', StatusCodeCopied},
{'U', StatusCodeUpdatedUnmerged},
{'?', StatusCodeUntracked},
{'!', StatusCodeIgnored},
}
for _, tc := range testCases {
code, err := NewStatusCodeFromByte(tc.input)
assert.Nil(t, err)
assert.Equal(t, tc.expected, code)
}
})
}
func TestStatusCodeString(t *testing.T) {
t.Run("invalid status code", func(t *testing.T) {
assert.Equal(t, "invalid-code", StatusCode(999).String())
})
t.Run("valid status codes", func(t *testing.T) {
testCases := []struct {
code StatusCode
expected string
}{
{StatusCodeUnmodified, " "},
{StatusCodeModified, "M"},
{StatusCodeTypeChanged, "T"},
{StatusCodeAdded, "A"},
{StatusCodeDeleted, "D"},
{StatusCodeRenamed, "R"},
{StatusCodeCopied, "C"},
{StatusCodeUpdatedUnmerged, "U"},
{StatusCodeUntracked, "?"},
{StatusCodeIgnored, "!"},
}
for _, tc := range testCases {
assert.Equal(t, tc.expected, tc.code.String())
}
})
}
func TestFileStatusUntracked(t *testing.T) {
t.Run("untracked when X is untracked", func(t *testing.T) {
fs := FileStatus{X: StatusCodeUntracked, Y: StatusCodeUnmodified}
assert.True(t, fs.Untracked())
})
t.Run("untracked when Y is untracked", func(t *testing.T) {
fs := FileStatus{X: StatusCodeUnmodified, Y: StatusCodeUntracked}
assert.True(t, fs.Untracked())
})
t.Run("not untracked when neither is untracked", func(t *testing.T) {
fs := FileStatus{X: StatusCodeModified, Y: StatusCodeUnmodified}
assert.False(t, fs.Untracked())
})
}

View file

@ -153,6 +153,14 @@ func TestPushRefSpecRepository(t *testing.T) {
err = localRepo.PushRefSpec(remoteName, []string{refSpecs})
assert.Nil(t, err)
})
t.Run("push to non-existent remote", func(t *testing.T) {
localTmpDir := t.TempDir()
localRepo := CreateTestGitRepository(t, localTmpDir, false)
err := localRepo.PushRefSpec("nonexistent", []string{refSpecs})
assert.ErrorContains(t, err, "unable to push")
})
}
func TestPushRepository(t *testing.T) {
@ -294,6 +302,22 @@ func TestPushRepository(t *testing.T) {
err = localRepo.Push(remoteName, []string{refName})
assert.Nil(t, err)
})
t.Run("push to non-existent remote", func(t *testing.T) {
localTmpDir := t.TempDir()
localRepo := CreateTestGitRepository(t, localTmpDir, false)
err := localRepo.Push("nonexistent", []string{refName})
assert.ErrorContains(t, err, "unable to push")
})
t.Run("push with invalid ref", func(t *testing.T) {
localTmpDir := t.TempDir()
localRepo := CreateTestGitRepository(t, localTmpDir, false)
err := localRepo.Push("origin", []string{"nonexistent-ref"})
assert.ErrorIs(t, err, ErrReferenceNotFound)
})
}
func TestFetchRefSpecRepository(t *testing.T) {
@ -443,6 +467,14 @@ func TestFetchRefSpecRepository(t *testing.T) {
require.Nil(t, err)
assert.Equal(t, localRef, newLocalRef)
})
t.Run("fetch from non-existent remote", func(t *testing.T) {
localTmpDir := t.TempDir()
localRepo := CreateTestGitRepository(t, localTmpDir, true)
err := localRepo.FetchRefSpec("nonexistent", []string{refSpecs})
assert.ErrorContains(t, err, "unable to fetch")
})
}
func TestFetchRepository(t *testing.T) {
@ -591,6 +623,27 @@ func TestFetchRepository(t *testing.T) {
require.Nil(t, err)
assert.Equal(t, localRef, newLocalRef)
})
t.Run("fetch from non-existent remote", func(t *testing.T) {
localTmpDir := t.TempDir()
localRepo := CreateTestGitRepository(t, localTmpDir, true)
err := localRepo.Fetch("nonexistent", []string{refName}, true)
assert.ErrorContains(t, err, "unable to fetch")
})
t.Run("fetch with invalid ref", func(t *testing.T) {
localTmpDir := t.TempDir()
remoteTmpDir := t.TempDir()
localRepo := CreateTestGitRepository(t, localTmpDir, true)
_ = CreateTestGitRepository(t, remoteTmpDir, false)
err := localRepo.CreateRemote(remoteName, remoteTmpDir)
require.Nil(t, err)
err = localRepo.Fetch(remoteName, []string{"nonexistent-ref"}, true)
assert.ErrorIs(t, err, ErrReferenceNotFound)
})
}
func TestFetchObject(t *testing.T) {
@ -617,6 +670,11 @@ func TestFetchObject(t *testing.T) {
has = downstreamRepo.HasObject(commitID)
assert.True(t, has)
t.Run("fetch from non-existent remote", func(t *testing.T) {
err := downstreamRepo.FetchObject("nonexistent", ZeroHash)
assert.ErrorContains(t, err, "unable to fetch object")
})
}
func TestCloneAndFetchRepository(t *testing.T) {
@ -913,3 +971,13 @@ func TestCloneAndFetchRepository(t *testing.T) {
assert.Equal(t, "FETCH_HEAD", dirEntries[0].Name())
})
}
func TestCreateRemote(t *testing.T) {
tmpDir := t.TempDir()
repo := CreateTestGitRepository(t, tmpDir, false)
err := repo.CreateRemote("origin", tmpDir)
assert.Nil(t, err)
err = repo.CreateRemote("origin", tmpDir)
assert.ErrorContains(t, err, "unable to add remote")
}

View file

@ -12,7 +12,9 @@ import (
"github.com/gittuf/gittuf/internal/signerverifier/gpg"
"github.com/gittuf/gittuf/internal/signerverifier/ssh"
artifacts "github.com/gittuf/gittuf/internal/testartifacts"
"github.com/secure-systems-lab/go-securesystemslib/signerverifier"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestGetTagTarget(t *testing.T) {
@ -40,6 +42,11 @@ func TestGetTagTarget(t *testing.T) {
targetID, err := repo.GetTagTarget(tagID)
assert.Nil(t, err)
assert.Equal(t, commitID, targetID)
t.Run("non-existent tag", func(t *testing.T) {
_, err := repo.GetTagTarget(ZeroHash)
assert.ErrorContains(t, err, "unable to resolve tag's target ID")
})
}
func TestRepositoryVerifyTag(t *testing.T) {
@ -92,4 +99,31 @@ func TestRepositoryVerifyTag(t *testing.T) {
err = repo.verifyTagSignature(context.Background(), gpgSignedTag, gpgKey)
assert.Nil(t, err)
})
t.Run("unknown signing method", func(t *testing.T) {
unknownKey := &signerverifier.SSLibKey{KeyType: "unknown"}
err = repo.verifyTagSignature(context.Background(), gpgSignedTag, unknownKey)
assert.ErrorIs(t, err, ErrUnknownSigningMethod)
})
}
func TestEnsureIsTag(t *testing.T) {
tmpDir := t.TempDir()
repo := CreateTestGitRepository(t, tmpDir, false)
treeBuilder := NewTreeBuilder(repo)
emptyTreeID, err := treeBuilder.WriteTreeFromEntries(nil)
require.Nil(t, err)
commitID, err := repo.Commit(emptyTreeID, "refs/heads/main", "Initial commit\n", false)
require.Nil(t, err)
tagID, err := repo.TagUsingSpecificKey(commitID, "test-tag", "test-tag\n", artifacts.SSHED25519Private)
require.Nil(t, err)
err = repo.ensureIsTag(tagID)
assert.Nil(t, err)
err = repo.ensureIsTag(commitID)
assert.ErrorContains(t, err, "is not a tag object")
}

View file

@ -0,0 +1,35 @@
// Copyright The gittuf Authors
// SPDX-License-Identifier: Apache-2.0
package gitinterface
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestResetDueToError(t *testing.T) {
tmpDir := t.TempDir()
repo := CreateTestGitRepository(t, tmpDir, false)
treeBuilder := NewTreeBuilder(repo)
emptyTreeID, err := treeBuilder.WriteTreeFromEntries(nil)
require.Nil(t, err)
commitID, err := repo.Commit(emptyTreeID, "refs/heads/main", "Initial commit\n", false)
require.Nil(t, err)
t.Run("successful reset", func(t *testing.T) {
cause := assert.AnError
err := repo.ResetDueToError(cause, "refs/heads/main", commitID)
assert.ErrorIs(t, err, cause)
})
t.Run("invalid ref name", func(t *testing.T) {
cause := assert.AnError
err := repo.ResetDueToError(cause, "invalid ref with spaces", commitID)
assert.ErrorContains(t, err, "unable to reset")
assert.ErrorIs(t, err, cause)
})
}