Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitaly.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Steinhardt <psteinhardt@gitlab.com>2021-06-17 15:53:17 +0300
committerPatrick Steinhardt <psteinhardt@gitlab.com>2021-06-17 15:53:17 +0300
commit044aac4db415ebc9fb1cc77f39d8bd5e3bdc823e (patch)
tree6d05b0f0d3352ea23b9dc934964f843b26bf4827
parent92aea29d1f67436a080670c16e9cc859f6b642dc (diff)
repository: Add test to exercise CreateFromBundle with transactions
We recently got a bug report about `CreateFromBundle()` seemingly misbehaving when transactions are enabled. Symptoms are that voters drop out at seemingly random steps with weird error messages like e.g. "Unable to read current working directory". While this likely indicates some kind of external race, I still took the opportunity to write a test verifying that `CreateFromBundle()` works as expect with transactions enabled and that the votes are in fact computed deterministically.
-rw-r--r--internal/gitaly/service/repository/create_from_bundle_test.go72
1 files changed, 72 insertions, 0 deletions
diff --git a/internal/gitaly/service/repository/create_from_bundle_test.go b/internal/gitaly/service/repository/create_from_bundle_test.go
index 16c6ba2fc..2b530ff29 100644
--- a/internal/gitaly/service/repository/create_from_bundle_test.go
+++ b/internal/gitaly/service/repository/create_from_bundle_test.go
@@ -2,6 +2,8 @@ package repository
import (
"bytes"
+ "context"
+ "fmt"
"io"
"os"
"path/filepath"
@@ -9,12 +11,19 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ "gitlab.com/gitlab-org/gitaly/v14/internal/git"
"gitlab.com/gitlab-org/gitaly/v14/internal/git/gittest"
"gitlab.com/gitlab-org/gitaly/v14/internal/git/localrepo"
"gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/config"
+ "gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/transaction"
+ "gitlab.com/gitlab-org/gitaly/v14/internal/helper"
+ "gitlab.com/gitlab-org/gitaly/v14/internal/helper/text"
"gitlab.com/gitlab-org/gitaly/v14/internal/tempdir"
"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper"
"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper/testassert"
+ "gitlab.com/gitlab-org/gitaly/v14/internal/testhelper/testserver"
+ "gitlab.com/gitlab-org/gitaly/v14/internal/transaction/txinfo"
+ "gitlab.com/gitlab-org/gitaly/v14/internal/transaction/voting"
"gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb"
"gitlab.com/gitlab-org/gitaly/v14/streamio"
"google.golang.org/grpc/codes"
@@ -83,6 +92,69 @@ func TestServer_CreateRepositoryFromBundle_successful(t *testing.T) {
require.NotNil(t, commit)
}
+func TestServer_CreateRepositoryFromBundle_transactional(t *testing.T) {
+ var votes []voting.Vote
+ txManager := &transaction.MockManager{
+ VoteFn: func(ctx context.Context, tx txinfo.Transaction, vote voting.Vote) error {
+ votes = append(votes, vote)
+ return nil
+ },
+ }
+
+ cfg, repoProto, repoPath, client := setupRepositoryService(t,
+ testserver.WithTransactionManager(txManager))
+
+ ctx, cancel := testhelper.Context()
+ defer cancel()
+ ctx, err := txinfo.InjectTransaction(ctx, 1, "primary", true)
+ require.NoError(t, err)
+ ctx = helper.IncomingToOutgoing(ctx)
+
+ stream, err := client.CreateRepositoryFromBundle(ctx)
+ require.NoError(t, err)
+
+ require.NoError(t, stream.Send(&gitalypb.CreateRepositoryFromBundleRequest{
+ Repository: &gitalypb.Repository{
+ StorageName: repoProto.GetStorageName(),
+ RelativePath: "create.git",
+ },
+ }))
+
+ bundle := gittest.Exec(t, cfg, "-C", repoPath, "bundle", "create", "-", "master", "feature")
+ require.Greater(t, len(bundle), 100*1024)
+
+ _, err = io.Copy(streamio.NewWriter(func(p []byte) error {
+ require.NoError(t, stream.Send(&gitalypb.CreateRepositoryFromBundleRequest{
+ Data: p,
+ }))
+ return nil
+ }), bytes.NewReader(bundle))
+ require.NoError(t, err)
+
+ _, err = stream.CloseAndRecv()
+ require.NoError(t, err)
+
+ masterOID := text.ChompBytes(gittest.Exec(t, cfg, "-C", repoPath, "rev-parse", "master"))
+ featureOID := text.ChompBytes(gittest.Exec(t, cfg, "-C", repoPath, "rev-parse", "feature"))
+
+ // This accounts for the first two votes which first do a git-clone(1) followed by a fetch.
+ // Given that voting is done via git's reference-transaction hook, the format is `<oldrev>
+ // <newrev> <reference>`.
+ fetchInput := fmt.Sprintf("%s %s refs/heads/feature\n%s %s refs/heads/master\n",
+ git.ZeroOID, featureOID, git.ZeroOID, masterOID)
+
+ // And this accounts for the final vote in `Create()`, which does vote on all references in
+ // the target repo as listed by git-for-each-ref(1).
+ refsInput := fmt.Sprintf("%s commit\trefs/heads/feature\n%s commit\trefs/heads/master\n",
+ featureOID, masterOID)
+
+ require.Equal(t, []voting.Vote{
+ voting.VoteFromData([]byte(fetchInput)),
+ voting.VoteFromData([]byte(fetchInput)),
+ voting.VoteFromData([]byte(refsInput)),
+ }, votes)
+}
+
func TestServer_CreateRepositoryFromBundle_failed_invalid_bundle(t *testing.T) {
cfg, client := setupRepositoryServiceWithoutRepo(t)