internal/git/gittest/repository_suite.go (226 lines of code) (raw):

package gittest import ( "context" "testing" "github.com/stretchr/testify/require" "gitlab.com/gitlab-org/gitaly/v16/internal/git" "gitlab.com/gitlab-org/gitaly/v16/internal/git/gitcmd" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper" ) // RepositorySuiteState is the state used by TestRepository. type RepositorySuiteState struct { Repository gitcmd.Repository SetReference SetReferenceFunc FirstParentCommit git.ObjectID SecondParentCommit git.ObjectID ChildCommit git.ObjectID } // GetRepositoryFunc is used to get a clean test repository for the different implementations of the // Repository interface in the common test suite TestRepository. type GetRepositoryFunc func(t testing.TB, ctx context.Context) RepositorySuiteState // SetReferenceFunc sets the given reference to the given value. type SetReferenceFunc func(t testing.TB, ctx context.Context, name git.ReferenceName, oid git.ObjectID) // TestRepository tests an implementation of Repository. func TestRepository(t *testing.T, getRepository GetRepositoryFunc) { for _, tc := range []struct { desc string test func(*testing.T, GetRepositoryFunc) }{ { desc: "ResolveRevision", test: testRepositoryResolveRevision, }, { desc: "HasBranches", test: testRepositoryHasBranches, }, { desc: "GetDefaultBranch", test: testRepositoryGetDefaultBranch, }, { desc: "HeadReference", test: testRepositoryHeadReference, }, } { t.Run(tc.desc, func(t *testing.T) { tc.test(t, getRepository) }) } } func testRepositoryResolveRevision(t *testing.T, getRepository GetRepositoryFunc) { ctx := testhelper.Context(t) state := getRepository(t, ctx) state.SetReference(t, ctx, "refs/heads/master", state.ChildCommit) for _, tc := range []struct { desc string revision string expected git.ObjectID }{ { desc: "unqualified master branch", revision: "master", expected: state.ChildCommit, }, { desc: "fully qualified master branch", revision: "refs/heads/master", expected: state.ChildCommit, }, { desc: "typed commit", revision: "refs/heads/master^{commit}", expected: state.ChildCommit, }, { desc: "extended SHA notation", revision: "refs/heads/master^2", expected: state.SecondParentCommit, }, { desc: "nonexistent branch", revision: "refs/heads/foobar", }, { desc: "SHA notation gone wrong", revision: "refs/heads/master^3", }, } { t.Run(tc.desc, func(t *testing.T) { oid, err := state.Repository.ResolveRevision(ctx, git.Revision(tc.revision)) if tc.expected == "" { require.Equal(t, err, git.ErrReferenceNotFound) return } require.NoError(t, err) require.Equal(t, tc.expected, oid) }) } } func testRepositoryHasBranches(t *testing.T, getRepository GetRepositoryFunc) { ctx := testhelper.Context(t) state := getRepository(t, ctx) state.SetReference(t, ctx, "refs/headsbranch", state.ChildCommit) hasBranches, err := state.Repository.HasBranches(ctx) require.NoError(t, err) require.False(t, hasBranches) state.SetReference(t, ctx, "refs/heads/branch", state.ChildCommit) hasBranches, err = state.Repository.HasBranches(ctx) require.NoError(t, err) require.True(t, hasBranches) } func testRepositoryGetDefaultBranch(t *testing.T, getRepository GetRepositoryFunc) { ctx := testhelper.Context(t) for _, tc := range []struct { desc string repo func(t *testing.T) gitcmd.Repository expectedName git.ReferenceName }{ { desc: "default ref", repo: func(t *testing.T) gitcmd.Repository { state := getRepository(t, ctx) state.SetReference(t, ctx, "refs/heads/main", state.ChildCommit) return state.Repository }, expectedName: git.DefaultRef, }, { desc: "legacy default ref", repo: func(t *testing.T) gitcmd.Repository { state := getRepository(t, ctx) state.SetReference(t, ctx, "refs/heads/master", state.ChildCommit) return state.Repository }, expectedName: git.LegacyDefaultRef, }, { desc: "no branches", repo: func(t *testing.T) gitcmd.Repository { return getRepository(t, ctx).Repository }, }, { desc: "one branch", repo: func(t *testing.T) gitcmd.Repository { state := getRepository(t, ctx) state.SetReference(t, ctx, "refs/heads/apple", state.ChildCommit) return state.Repository }, expectedName: git.NewReferenceNameFromBranchName("apple"), }, { desc: "no default branches", repo: func(t *testing.T) gitcmd.Repository { state := getRepository(t, ctx) state.SetReference(t, ctx, "refs/heads/apple", state.FirstParentCommit) state.SetReference(t, ctx, "refs/heads/banana", state.SecondParentCommit) return state.Repository }, expectedName: git.NewReferenceNameFromBranchName("apple"), }, { desc: "test repo HEAD set", repo: func(t *testing.T) gitcmd.Repository { state := getRepository(t, ctx) state.SetReference(t, ctx, "refs/heads/feature", state.ChildCommit) state.SetReference(t, ctx, "HEAD", "refs/heads/feature") return state.Repository }, expectedName: git.NewReferenceNameFromBranchName("feature"), }, } { t.Run(tc.desc, func(t *testing.T) { name, err := tc.repo(t).GetDefaultBranch(ctx) require.NoError(t, err) require.Equal(t, tc.expectedName, name) }) } } func testRepositoryHeadReference(t *testing.T, getRepository GetRepositoryFunc) { t.Parallel() ctx := testhelper.Context(t) for _, tc := range []struct { desc string repo func(t *testing.T) gitcmd.Repository expectedName git.ReferenceName }{ { desc: "default unborn", repo: func(t *testing.T) gitcmd.Repository { return getRepository(t, ctx).Repository }, expectedName: git.DefaultRef, }, { desc: "default exists", repo: func(t *testing.T) gitcmd.Repository { state := getRepository(t, ctx) state.SetReference(t, ctx, git.DefaultRef, state.ChildCommit) return state.Repository }, expectedName: git.DefaultRef, }, { desc: "HEAD set nonexistent", repo: func(t *testing.T) gitcmd.Repository { state := getRepository(t, ctx) state.SetReference(t, ctx, "HEAD", "refs/heads/feature") return state.Repository }, expectedName: git.NewReferenceNameFromBranchName("feature"), }, { desc: "HEAD set exists", repo: func(t *testing.T) gitcmd.Repository { state := getRepository(t, ctx) state.SetReference(t, ctx, "refs/heads/feature", state.ChildCommit) state.SetReference(t, ctx, "HEAD", "refs/heads/feature") return state.Repository }, expectedName: git.NewReferenceNameFromBranchName("feature"), }, } { t.Run(tc.desc, func(t *testing.T) { t.Parallel() name, err := tc.repo(t).HeadReference(ctx) require.NoError(t, err) require.Equal(t, tc.expectedName, name) }) } }