diff options
author | Patrick Steinhardt <psteinhardt@gitlab.com> | 2023-01-03 14:43:38 +0300 |
---|---|---|
committer | Patrick Steinhardt <psteinhardt@gitlab.com> | 2023-01-03 16:48:38 +0300 |
commit | 33cf1476d920e6465924b4433aaa85c0c36981c6 (patch) | |
tree | 74923f1dd451022748896e888839bb28c6cec370 | |
parent | 41cf4b0a0e54929c668d34d08bba59410dc524e3 (diff) |
repository: Modernize tests for `Fsck` RPC
Modernize tests for the `Fsck` RPC to use table-driven tests. Stop using
a seed repository and generate test data at runtime instead.
-rw-r--r-- | internal/gitaly/service/repository/fsck_test.go | 169 |
1 files changed, 112 insertions, 57 deletions
diff --git a/internal/gitaly/service/repository/fsck_test.go b/internal/gitaly/service/repository/fsck_test.go index 8fddbb1f5..174aec129 100644 --- a/internal/gitaly/service/repository/fsck_test.go +++ b/internal/gitaly/service/repository/fsck_test.go @@ -3,74 +3,129 @@ package repository import ( + "fmt" "os" "path/filepath" "strings" "testing" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gitlab.com/gitlab-org/gitaly/v15/internal/git/gittest" + "gitlab.com/gitlab-org/gitaly/v15/internal/structerr" "gitlab.com/gitlab-org/gitaly/v15/internal/testhelper" "gitlab.com/gitlab-org/gitaly/v15/proto/go/gitalypb" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" ) -func TestFsckSuccess(t *testing.T) { +func TestFsck(t *testing.T) { t.Parallel() - ctx := testhelper.Context(t) - - _, repo, _, client := setupRepositoryService(t, ctx) - - c, err := client.Fsck(ctx, &gitalypb.FsckRequest{Repository: repo}) - assert.NoError(t, err) - assert.NotNil(t, c) - assert.Empty(t, c.GetError()) -} -func TestFsckFailureSeverelyBrokenRepo(t *testing.T) { - t.Parallel() ctx := testhelper.Context(t) - - _, repo, repoPath, client := setupRepositoryService(t, ctx) - - // This makes the repo severely broken so that `git` does not identify it as a - // proper repo. - require.NoError(t, os.RemoveAll(filepath.Join(repoPath, "objects"))) - fd, err := os.Create(filepath.Join(repoPath, "objects")) - require.NoError(t, err) - require.NoError(t, fd.Close()) - - c, err := client.Fsck(ctx, &gitalypb.FsckRequest{Repository: repo}) - assert.NoError(t, err) - assert.NotNil(t, c) - assert.Contains(t, strings.ToLower(string(c.GetError())), "not a git repository") -} - -func TestFsckFailureSlightlyBrokenRepo(t *testing.T) { - t.Parallel() - ctx := testhelper.Context(t) - - _, repo, repoPath, client := setupRepositoryService(t, ctx) - - // This makes the repo slightly broken so that `git` still identify it as a - // proper repo, but `fsck` complains about broken refs... - require.NoError(t, os.RemoveAll(filepath.Join(repoPath, "objects", "pack"))) - - c, err := client.Fsck(ctx, &gitalypb.FsckRequest{Repository: repo}) - assert.NoError(t, err) - assert.NotNil(t, c) - assert.NotEmpty(t, string(c.GetError())) - assert.Contains(t, string(c.GetError()), "error: HEAD: invalid sha1 pointer") -} - -func TestFsck_validate(t *testing.T) { - t.Parallel() - ctx := testhelper.Context(t) - - _, client := setupRepositoryServiceWithoutRepo(t) - - _, err := client.Fsck(ctx, &gitalypb.FsckRequest{Repository: nil}) - msg := testhelper.GitalyOrPraefect("empty Repository", "repo scoped: empty Repository") - testhelper.RequireGrpcError(t, status.Error(codes.InvalidArgument, msg), err) + cfg, client := setupRepositoryServiceWithoutRepo(t) + + type setupData struct { + repo *gitalypb.Repository + expectedErr error + expectedResponse *gitalypb.FsckResponse + } + + for _, tc := range []struct { + desc string + setup func(t *testing.T) setupData + }{ + { + desc: "request is missing repository", + setup: func(t *testing.T) setupData { + return setupData{ + repo: nil, + expectedErr: structerr.NewInvalidArgument( + testhelper.GitalyOrPraefect( + "empty Repository", + "repo scoped: empty Repository", + ), + ), + } + }, + }, + { + desc: "empty repository", + setup: func(t *testing.T) setupData { + repo, _ := gittest.CreateRepository(t, ctx, cfg) + + return setupData{ + repo: repo, + expectedResponse: &gitalypb.FsckResponse{}, + } + }, + }, + { + desc: "repository with commit", + setup: func(t *testing.T) setupData { + repo, repoPath := gittest.CreateRepository(t, ctx, cfg) + gittest.WriteCommit(t, cfg, repoPath, gittest.WithBranch("main")) + + return setupData{ + repo: repo, + expectedResponse: &gitalypb.FsckResponse{}, + } + }, + }, + { + desc: "invalid object directory", + setup: func(t *testing.T) setupData { + repo, repoPath := gittest.CreateRepository(t, ctx, cfg) + + // This makes the repo severely broken so that `git` does not + // identify it as a proper repository anymore. + require.NoError(t, os.RemoveAll(filepath.Join(repoPath, "objects"))) + require.NoError(t, os.WriteFile(filepath.Join(repoPath, "objects"), nil, 0o644)) + + return setupData{ + repo: repo, + expectedResponse: &gitalypb.FsckResponse{ + Error: []byte(fmt.Sprintf("fatal: not a git repository: '%s'\n", repoPath)), + }, + } + }, + }, + { + desc: "missing objects", + setup: func(t *testing.T) setupData { + repo, repoPath := gittest.CreateRepository(t, ctx, cfg) + + // We write a commit and repack it into a packfile... + commitID := gittest.WriteCommit(t, cfg, repoPath, gittest.WithBranch("main")) + gittest.Exec(t, cfg, "-C", repoPath, "repack", "-Ad") + // ... but then subsequently delete all the packfiles. This should + // lead to git-fsck(1) complaining about missing objects. + require.NoError(t, os.RemoveAll(filepath.Join(repoPath, "objects", "pack"))) + + expectedErr := strings.Join([]string{ + "error: refs/heads/main: invalid sha1 pointer " + commitID.String(), + "error: HEAD: invalid sha1 pointer " + commitID.String(), + "notice: No default references", + }, "\n") + "\n" + + return setupData{ + repo: repo, + expectedResponse: &gitalypb.FsckResponse{ + Error: []byte(expectedErr), + }, + } + }, + }, + } { + tc := tc + + t.Run(tc.desc, func(t *testing.T) { + t.Parallel() + + setupData := tc.setup(t) + + response, err := client.Fsck(ctx, &gitalypb.FsckRequest{ + Repository: setupData.repo, + }) + testhelper.RequireGrpcError(t, setupData.expectedErr, err) + testhelper.ProtoEqual(t, setupData.expectedResponse, response) + }) + } } |