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:
authorSami Hiltunen <shiltunen@gitlab.com>2020-09-28 11:46:33 +0300
committerSami Hiltunen <shiltunen@gitlab.com>2020-10-13 10:40:11 +0300
commit31953a811f40d0ef9a9b1722ecd4611336e4c66f (patch)
treec6a87d0282701c0fdb43f16a6d870e57855034ca
parent0fc40ef439ae4bbf91da2a5b454dfad5cb815a17 (diff)
extend UserCommitFiles test suite
Add more tests for UserCommitFiles as a preparation for porting the RPC to Go. More tests helps pinning down the exact behavior of the endpoint. Additionally adds plumbing for testing running the tests for both implementations. There's no behavioral or assertion changes in the tests.
-rw-r--r--internal/gitaly/service/operations/commit_files_test.go936
1 files changed, 878 insertions, 58 deletions
diff --git a/internal/gitaly/service/operations/commit_files_test.go b/internal/gitaly/service/operations/commit_files_test.go
index 391ba9c24..5ef05f171 100644
--- a/internal/gitaly/service/operations/commit_files_test.go
+++ b/internal/gitaly/service/operations/commit_files_test.go
@@ -1,7 +1,9 @@
package operations
import (
+ "bytes"
"context"
+ "encoding/base64"
"fmt"
"strconv"
"testing"
@@ -13,13 +15,784 @@ import (
"gitlab.com/gitlab-org/gitaly/proto/go/gitalypb"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
+ "google.golang.org/grpc/status"
)
var (
commitFilesMessage = []byte("Change files")
)
-func testSuccessfulUserCommitFilesRequest(t *testing.T, ctxWithFeatureFlags context.Context) {
+func testImplementations(t *testing.T, test func(t *testing.T, ctx context.Context)) {
+ ctx, cancel := testhelper.Context()
+ defer cancel()
+
+ for _, tc := range []struct {
+ desc string
+ context context.Context
+ }{
+ {desc: "ruby", context: ctx},
+ } {
+ t.Run(tc.desc, func(t *testing.T) { test(t, tc.context) })
+ }
+}
+
+func TestUserCommitFiles(t *testing.T) {
+ testImplementations(t, testUserCommitFiles)
+}
+
+func testUserCommitFiles(t *testing.T, ctx context.Context) {
+ type treeEntry struct {
+ Mode string
+ Path string
+ Content string
+ }
+
+ requireTreeEntries := func(t testing.TB, repoPath, branch string, expectedEntries []treeEntry) {
+ t.Helper()
+
+ var actualEntries []treeEntry
+
+ output := bytes.TrimSpace(testhelper.MustRunCommand(t, nil, "git", "-C", repoPath, "ls-tree", "-r", branch))
+
+ if len(output) > 0 {
+ for _, line := range bytes.Split(output, []byte("\n")) {
+ // Format: <mode> SP <type> SP <object> TAB <file>
+ tabSplit := bytes.Split(line, []byte("\t"))
+ spaceSplit := bytes.Split(tabSplit[0], []byte(" "))
+ path := string(tabSplit[1])
+ actualEntries = append(actualEntries, treeEntry{
+ Mode: string(spaceSplit[0]),
+ Path: path,
+ Content: string(testhelper.MustRunCommand(t, nil, "git", "-C", repoPath, "show", branch+":"+path)),
+ })
+ }
+ }
+
+ require.Equal(t, expectedEntries, actualEntries)
+ }
+
+ const (
+ DefaultMode = "100644"
+ ExecutableMode = "100755"
+ )
+
+ type step struct {
+ actions []*gitalypb.UserCommitFilesRequest
+ error error
+ indexError string
+ repoCreated bool
+ branchCreated bool
+ treeEntries []treeEntry
+ }
+
+ for _, tc := range []struct {
+ desc string
+ steps []step
+ }{
+ {
+ desc: "create directory",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createDirHeaderRequest("directory-1"),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "directory-1/.gitkeep"},
+ },
+ },
+ },
+ },
+ {
+ desc: "create directory ignores mode and content",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ actionRequest(&gitalypb.UserCommitFilesAction{
+ UserCommitFilesActionPayload: &gitalypb.UserCommitFilesAction_Header{
+ Header: &gitalypb.UserCommitFilesActionHeader{
+ Action: gitalypb.UserCommitFilesActionHeader_CREATE_DIR,
+ FilePath: []byte("directory-1"),
+ ExecuteFilemode: true,
+ Base64Content: true,
+ },
+ },
+ }),
+ actionContentRequest("content-1"),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "directory-1/.gitkeep"},
+ },
+ },
+ },
+ },
+ {
+ desc: "create directory created duplicate",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createDirHeaderRequest("directory-1"),
+ createDirHeaderRequest("directory-1"),
+ },
+ indexError: "A directory with this name already exists",
+ },
+ },
+ },
+ {
+ desc: "create directory with traversal",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createDirHeaderRequest("../directory-1"),
+ },
+ indexError: "Path cannot include directory traversal",
+ },
+ },
+ },
+ {
+ desc: "create directory existing duplicate",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createDirHeaderRequest("directory-1"),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "directory-1/.gitkeep"},
+ },
+ },
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createDirHeaderRequest("directory-1"),
+ },
+ indexError: "A directory with this name already exists",
+ },
+ },
+ },
+ {
+ desc: "create directory with files name",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("file-1"),
+ actionContentRequest("content-1"),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "file-1", Content: "content-1"},
+ },
+ },
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createDirHeaderRequest("file-1"),
+ },
+ indexError: "A file with this name already exists",
+ },
+ },
+ },
+ {
+ desc: "create file with directory traversal",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("../file-1"),
+ actionContentRequest("content-1"),
+ },
+ indexError: "Path cannot include directory traversal",
+ },
+ },
+ },
+ {
+ desc: "create file without content",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("file-1"),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "file-1"},
+ },
+ },
+ },
+ },
+ {
+ desc: "create file",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("file-1"),
+ actionContentRequest("content-1"),
+ actionContentRequest(" content-2"),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "file-1", Content: "content-1 content-2"},
+ },
+ },
+ },
+ },
+ {
+ desc: "create file with base64 content",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createBase64FileHeaderRequest("file-1"),
+ actionContentRequest(base64.StdEncoding.EncodeToString([]byte("content-1"))),
+ actionContentRequest(base64.StdEncoding.EncodeToString([]byte(" content-2"))),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "file-1", Content: "content-1 content-2"},
+ },
+ },
+ },
+ },
+ {
+ desc: "create duplicate file",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("file-1"),
+ actionContentRequest("content-1"),
+ createFileHeaderRequest("file-1"),
+ },
+ indexError: "A file with this name already exists",
+ },
+ },
+ },
+ {
+ desc: "create file overwrites directory",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createDirHeaderRequest("file-1"),
+ createFileHeaderRequest("file-1"),
+ actionContentRequest("content-1"),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "file-1", Content: "content-1"},
+ },
+ },
+ },
+ },
+ {
+ desc: "update created file",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("file-1"),
+ actionContentRequest("content-1"),
+ updateFileHeaderRequest("file-1"),
+ actionContentRequest("content-2"),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "file-1", Content: "content-2"},
+ },
+ },
+ },
+ },
+ {
+ desc: "update base64 content",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("file-1"),
+ actionContentRequest("content-1"),
+ updateBase64FileHeaderRequest("file-1"),
+ actionContentRequest(base64.StdEncoding.EncodeToString([]byte("content-2"))),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "file-1", Content: "content-2"},
+ },
+ },
+ },
+ },
+ {
+ desc: "update ignores mode",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("file-1"),
+ actionContentRequest("content-1"),
+ actionRequest(&gitalypb.UserCommitFilesAction{
+ UserCommitFilesActionPayload: &gitalypb.UserCommitFilesAction_Header{
+ Header: &gitalypb.UserCommitFilesActionHeader{
+ Action: gitalypb.UserCommitFilesActionHeader_UPDATE,
+ FilePath: []byte("file-1"),
+ ExecuteFilemode: true,
+ },
+ },
+ }),
+ actionContentRequest("content-2"),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "file-1", Content: "content-2"},
+ },
+ },
+ },
+ },
+ {
+ desc: "update existing file",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("file-1"),
+ actionContentRequest("content-1"),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "file-1", Content: "content-1"},
+ },
+ },
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ updateFileHeaderRequest("file-1"),
+ actionContentRequest("content-2"),
+ },
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "file-1", Content: "content-2"},
+ },
+ },
+ },
+ },
+ {
+ desc: "update non-existing file",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ updateFileHeaderRequest("non-existing"),
+ actionContentRequest("content"),
+ },
+ indexError: "A file with this name doesn't exist",
+ },
+ },
+ },
+ {
+ desc: "move file with traversal in source",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ moveFileHeaderRequest("../original-file", "moved-file", true),
+ },
+ indexError: "Path cannot include directory traversal",
+ },
+ },
+ },
+ {
+ desc: "move file with traversal in destination",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ moveFileHeaderRequest("original-file", "../moved-file", true),
+ },
+ indexError: "Path cannot include directory traversal",
+ },
+ },
+ },
+ {
+ desc: "move created file",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("original-file"),
+ actionContentRequest("content-1"),
+ moveFileHeaderRequest("original-file", "moved-file", true),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "moved-file", Content: "content-1"},
+ },
+ },
+ },
+ },
+ {
+ desc: "move ignores mode",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("original-file"),
+ actionContentRequest("content-1"),
+ actionRequest(&gitalypb.UserCommitFilesAction{
+ UserCommitFilesActionPayload: &gitalypb.UserCommitFilesAction_Header{
+ Header: &gitalypb.UserCommitFilesActionHeader{
+ Action: gitalypb.UserCommitFilesActionHeader_MOVE,
+ FilePath: []byte("moved-file"),
+ PreviousPath: []byte("original-file"),
+ ExecuteFilemode: true,
+ InferContent: true,
+ },
+ },
+ }),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "moved-file", Content: "content-1"},
+ },
+ },
+ },
+ },
+ {
+ desc: "moving directory fails",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createDirHeaderRequest("directory"),
+ moveFileHeaderRequest("directory", "moved-directory", true),
+ },
+ indexError: "A file with this name doesn't exist",
+ },
+ },
+ },
+ {
+ desc: "move file inferring content",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("original-file"),
+ actionContentRequest("original-content"),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "original-file", Content: "original-content"},
+ },
+ },
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ moveFileHeaderRequest("original-file", "moved-file", true),
+ actionContentRequest("ignored-content"),
+ },
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "moved-file", Content: "original-content"},
+ },
+ },
+ },
+ },
+ {
+ desc: "move file with non-existing source",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ moveFileHeaderRequest("non-existing", "destination-file", true),
+ },
+ indexError: "A file with this name doesn't exist",
+ },
+ },
+ },
+ {
+ desc: "move file with already existing destination file",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("source-file"),
+ createFileHeaderRequest("already-existing"),
+ moveFileHeaderRequest("source-file", "already-existing", true),
+ },
+ indexError: "A file with this name already exists",
+ },
+ },
+ },
+ {
+ // seems like a bug in the original implementation to allow overwriting a
+ // directory
+ desc: "move file with already existing destination directory",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("source-file"),
+ actionContentRequest("source-content"),
+ createDirHeaderRequest("already-existing"),
+ moveFileHeaderRequest("source-file", "already-existing", true),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "already-existing", Content: "source-content"},
+ },
+ },
+ },
+ },
+ {
+ desc: "move file providing content",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("original-file"),
+ actionContentRequest("original-content"),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "original-file", Content: "original-content"},
+ },
+ },
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ moveFileHeaderRequest("original-file", "moved-file", false),
+ actionContentRequest("new-content"),
+ },
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "moved-file", Content: "new-content"},
+ },
+ },
+ },
+ },
+ {
+ desc: "mark non-existing file executable",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ chmodFileHeaderRequest("file-1", true),
+ },
+ indexError: "A file with this name doesn't exist",
+ },
+ },
+ },
+ {
+ desc: "mark executable file executable",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("file-1"),
+ chmodFileHeaderRequest("file-1", true),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: ExecutableMode, Path: "file-1"},
+ },
+ },
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ chmodFileHeaderRequest("file-1", true),
+ },
+ treeEntries: []treeEntry{
+ {Mode: ExecutableMode, Path: "file-1"},
+ },
+ },
+ },
+ },
+ {
+ desc: "mark file executable with directory traversal",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ chmodFileHeaderRequest("../file-1", true),
+ },
+ indexError: "Path cannot include directory traversal",
+ },
+ },
+ },
+ {
+ desc: "mark created file executable",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("file-1"),
+ actionContentRequest("content-1"),
+ chmodFileHeaderRequest("file-1", true),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: ExecutableMode, Path: "file-1", Content: "content-1"},
+ },
+ },
+ },
+ },
+ {
+ desc: "mark existing file executable",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("file-1"),
+ actionContentRequest("content-1"),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "file-1", Content: "content-1"},
+ },
+ },
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ chmodFileHeaderRequest("file-1", true),
+ },
+ treeEntries: []treeEntry{
+ {Mode: ExecutableMode, Path: "file-1", Content: "content-1"},
+ },
+ },
+ },
+ },
+ {
+ desc: "move non-existing file",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ moveFileHeaderRequest("non-existing", "should-not-be-created", true),
+ },
+ indexError: "A file with this name doesn't exist",
+ },
+ },
+ },
+ {
+ desc: "move doesn't overwrite a file",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("file-1"),
+ actionContentRequest("content-1"),
+ createFileHeaderRequest("file-2"),
+ actionContentRequest("content-2"),
+ moveFileHeaderRequest("file-1", "file-2", true),
+ },
+ indexError: "A file with this name already exists",
+ },
+ },
+ },
+ {
+ desc: "delete non-existing file",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ deleteFileHeaderRequest("non-existing"),
+ },
+ indexError: "A file with this name doesn't exist",
+ },
+ },
+ },
+ {
+ desc: "delete file with directory traversal",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ deleteFileHeaderRequest("../file-1"),
+ },
+ indexError: "Path cannot include directory traversal",
+ },
+ },
+ },
+ {
+ desc: "delete created file",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("file-1"),
+ actionContentRequest("content-1"),
+ deleteFileHeaderRequest("file-1"),
+ },
+ branchCreated: true,
+ repoCreated: true,
+ },
+ },
+ },
+ {
+ desc: "delete existing file",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("file-1"),
+ actionContentRequest("content-1"),
+ },
+ branchCreated: true,
+ repoCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "file-1", Content: "content-1"},
+ },
+ },
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ deleteFileHeaderRequest("file-1"),
+ },
+ },
+ },
+ },
+ {
+ desc: "invalid action",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ actionRequest(&gitalypb.UserCommitFilesAction{
+ UserCommitFilesActionPayload: &gitalypb.UserCommitFilesAction_Header{
+ Header: &gitalypb.UserCommitFilesActionHeader{
+ Action: -1,
+ },
+ },
+ }),
+ },
+ error: status.Error(codes.Unknown, "NoMethodError: undefined method `downcase' for -1:Integer"),
+ },
+ },
+ },
+ } {
+ t.Run(tc.desc, func(t *testing.T) {
+ repo, repoPath, clean := testhelper.InitBareRepo(t)
+ defer clean()
+
+ serverSocketPath, stop := runOperationServiceServer(t)
+ defer stop()
+
+ client, conn := newOperationClient(t, serverSocketPath)
+ defer conn.Close()
+
+ const branch = "master"
+
+ for i, step := range tc.steps {
+ stream, err := client.UserCommitFiles(ctx)
+ require.NoError(t, err)
+
+ headerRequest := headerRequest(repo, testhelper.TestUser, branch, []byte("commit message"))
+ setAuthorAndEmail(headerRequest, []byte("Author Name"), []byte("author.email@example.com"))
+ require.NoError(t, stream.Send(headerRequest))
+
+ for j, action := range step.actions {
+ require.NoError(t, stream.Send(action), "step %d, action %d", i+1, j+1)
+ }
+
+ resp, err := stream.CloseAndRecv()
+ require.Equal(t, step.error, err)
+ if step.error != nil {
+ continue
+ }
+
+ require.Equal(t, step.indexError, resp.IndexError, "step %d", i+1)
+ if step.indexError != "" {
+ continue
+ }
+
+ require.Equal(t, step.branchCreated, resp.BranchUpdate.BranchCreated, "step %d", i+1)
+ require.Equal(t, step.repoCreated, resp.BranchUpdate.RepoCreated, "step %d", i+1)
+ requireTreeEntries(t, repoPath, branch, step.treeEntries)
+ }
+ })
+ }
+}
+
+func TestSuccessfulUserCommitFilesRequest(t *testing.T) {
+ testImplementations(t, testSuccessfulUserCommitFilesRequest)
+}
+
+func testSuccessfulUserCommitFilesRequest(t *testing.T, ctx context.Context) {
testRepo, testRepoPath, cleanup := testhelper.NewTestRepo(t)
defer cleanup()
@@ -32,7 +805,6 @@ func testSuccessfulUserCommitFilesRequest(t *testing.T, ctxWithFeatureFlags cont
newRepo, newRepoPath, newRepoCleanupFn := testhelper.InitBareRepo(t)
defer newRepoCleanupFn()
- md := testhelper.GitalyServersMetadata(t, serverSocketPath)
filePath := "héllo/wörld"
authorName := []byte("Jane Doe")
authorEmail := []byte("janedoe@gitlab.com")
@@ -82,7 +854,6 @@ func testSuccessfulUserCommitFilesRequest(t *testing.T, ctxWithFeatureFlags cont
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
- ctx := metadata.NewOutgoingContext(ctxWithFeatureFlags, md)
headerRequest := headerRequest(tc.repo, testhelper.TestUser, tc.branchName, commitFilesMessage)
setAuthorAndEmail(headerRequest, authorName, authorEmail)
@@ -104,7 +875,7 @@ func testSuccessfulUserCommitFilesRequest(t *testing.T, ctxWithFeatureFlags cont
require.Equal(t, tc.repoCreated, resp.GetBranchUpdate().GetRepoCreated())
require.Equal(t, tc.branchCreated, resp.GetBranchUpdate().GetBranchCreated())
- headCommit, err := log.GetCommit(ctxWithFeatureFlags, tc.repo, tc.branchName)
+ headCommit, err := log.GetCommit(ctx, tc.repo, tc.branchName)
require.NoError(t, err)
require.Equal(t, authorName, headCommit.Author.Name)
require.Equal(t, testhelper.TestUser.Name, headCommit.Committer.Name)
@@ -125,23 +896,17 @@ func testSuccessfulUserCommitFilesRequest(t *testing.T, ctxWithFeatureFlags cont
}
}
-func TestSuccessfulUserCommitFilesRequest(t *testing.T) {
- ctx, cancel := testhelper.Context()
- defer cancel()
-
- testSuccessfulUserCommitFilesRequest(t, ctx)
+func TestSuccessfulUserCommitFilesRequestMove(t *testing.T) {
+ testImplementations(t, testSuccessfulUserCommitFilesRequestMove)
}
-func TestSuccessfulUserCommitFilesRequestMove(t *testing.T) {
+func testSuccessfulUserCommitFilesRequestMove(t *testing.T, ctx context.Context) {
serverSocketPath, stop := runOperationServiceServer(t)
defer stop()
client, conn := newOperationClient(t, serverSocketPath)
defer conn.Close()
- ctxOuter, cancel := testhelper.Context()
- defer cancel()
-
branchName := "master"
previousFilePath := "README"
filePath := "NEWREADME"
@@ -162,8 +927,6 @@ func TestSuccessfulUserCommitFilesRequestMove(t *testing.T) {
defer cleanupFn()
origFileContent := testhelper.MustRunCommand(t, nil, "git", "-C", testRepoPath, "show", branchName+":"+previousFilePath)
- md := testhelper.GitalyServersMetadata(t, serverSocketPath)
- ctx := metadata.NewOutgoingContext(ctxOuter, md)
headerRequest := headerRequest(testRepo, testhelper.TestUser, branchName, commitFilesMessage)
setAuthorAndEmail(headerRequest, authorName, authorEmail)
actionsRequest1 := moveFileHeaderRequest(previousFilePath, filePath, tc.infer)
@@ -196,6 +959,10 @@ func TestSuccessfulUserCommitFilesRequestMove(t *testing.T) {
}
func TestSuccessfulUserCommitFilesRequestForceCommit(t *testing.T) {
+ testImplementations(t, testSuccessfulUserCommitFilesRequestForceCommit)
+}
+
+func testSuccessfulUserCommitFilesRequestForceCommit(t *testing.T, ctx context.Context) {
serverSocketPath, stop := runOperationServiceServer(t)
defer stop()
@@ -205,20 +972,15 @@ func TestSuccessfulUserCommitFilesRequestForceCommit(t *testing.T) {
testRepo, testRepoPath, cleanupFn := testhelper.NewTestRepo(t)
defer cleanupFn()
- ctxOuter, cancel := testhelper.Context()
- defer cancel()
-
- md := testhelper.GitalyServersMetadata(t, serverSocketPath)
- ctx := metadata.NewOutgoingContext(ctxOuter, md)
authorName := []byte("Jane Doe")
authorEmail := []byte("janedoe@gitlab.com")
targetBranchName := "feature"
startBranchName := []byte("master")
- startBranchCommit, err := log.GetCommit(ctxOuter, testRepo, string(startBranchName))
+ startBranchCommit, err := log.GetCommit(ctx, testRepo, string(startBranchName))
require.NoError(t, err)
- targetBranchCommit, err := log.GetCommit(ctxOuter, testRepo, targetBranchName)
+ targetBranchCommit, err := log.GetCommit(ctx, testRepo, targetBranchName)
require.NoError(t, err)
mergeBaseOut := testhelper.MustRunCommand(t, nil, "git", "-C", testRepoPath, "merge-base", targetBranchCommit.Id, startBranchCommit.Id)
@@ -240,7 +1002,7 @@ func TestSuccessfulUserCommitFilesRequestForceCommit(t *testing.T) {
require.NoError(t, err)
update := resp.GetBranchUpdate()
- newTargetBranchCommit, err := log.GetCommit(ctxOuter, testRepo, targetBranchName)
+ newTargetBranchCommit, err := log.GetCommit(ctx, testRepo, targetBranchName)
require.NoError(t, err)
require.Equal(t, newTargetBranchCommit.Id, update.CommitId)
@@ -248,6 +1010,10 @@ func TestSuccessfulUserCommitFilesRequestForceCommit(t *testing.T) {
}
func TestSuccessfulUserCommitFilesRequestStartSha(t *testing.T) {
+ testImplementations(t, testSuccessfulUserCommitFilesRequestStartSha)
+}
+
+func testSuccessfulUserCommitFilesRequestStartSha(t *testing.T, ctx context.Context) {
serverSocketPath, stop := runOperationServiceServer(t)
defer stop()
@@ -257,14 +1023,9 @@ func TestSuccessfulUserCommitFilesRequestStartSha(t *testing.T) {
testRepo, _, cleanupFn := testhelper.NewTestRepo(t)
defer cleanupFn()
- ctxOuter, cancel := testhelper.Context()
- defer cancel()
-
- md := testhelper.GitalyServersMetadata(t, serverSocketPath)
- ctx := metadata.NewOutgoingContext(ctxOuter, md)
targetBranchName := "new"
- startCommit, err := log.GetCommit(ctxOuter, testRepo, "master")
+ startCommit, err := log.GetCommit(ctx, testRepo, "master")
require.NoError(t, err)
headerRequest := headerRequest(testRepo, testhelper.TestUser, targetBranchName, commitFilesMessage)
@@ -280,7 +1041,7 @@ func TestSuccessfulUserCommitFilesRequestStartSha(t *testing.T) {
require.NoError(t, err)
update := resp.GetBranchUpdate()
- newTargetBranchCommit, err := log.GetCommit(ctxOuter, testRepo, targetBranchName)
+ newTargetBranchCommit, err := log.GetCommit(ctx, testRepo, targetBranchName)
require.NoError(t, err)
require.Equal(t, newTargetBranchCommit.Id, update.CommitId)
@@ -288,6 +1049,10 @@ func TestSuccessfulUserCommitFilesRequestStartSha(t *testing.T) {
}
func TestSuccessfulUserCommitFilesRequestStartShaRemoteRepository(t *testing.T) {
+ testImplementations(t, testSuccessfulUserCommitFilesRequestStartShaRemoteRepository)
+}
+
+func testSuccessfulUserCommitFilesRequestStartShaRemoteRepository(t *testing.T, ctx context.Context) {
serverSocketPath, stop := runOperationServiceServer(t)
defer stop()
@@ -297,17 +1062,18 @@ func TestSuccessfulUserCommitFilesRequestStartShaRemoteRepository(t *testing.T)
testRepo, _, cleanupFn := testhelper.NewTestRepo(t)
defer cleanupFn()
- ctxOuter, cancel := testhelper.Context()
- defer cancel()
-
newRepo, _, newRepoCleanupFn := testhelper.InitBareRepo(t)
defer newRepoCleanupFn()
- md := testhelper.GitalyServersMetadata(t, serverSocketPath)
- ctx := metadata.NewOutgoingContext(ctxOuter, md)
+ for key, values := range testhelper.GitalyServersMetadata(t, serverSocketPath) {
+ for _, value := range values {
+ ctx = metadata.AppendToOutgoingContext(ctx, key, value)
+ }
+ }
+
targetBranchName := "new"
- startCommit, err := log.GetCommit(ctxOuter, testRepo, "master")
+ startCommit, err := log.GetCommit(ctx, testRepo, "master")
require.NoError(t, err)
headerRequest := headerRequest(newRepo, testhelper.TestUser, targetBranchName, commitFilesMessage)
@@ -324,7 +1090,7 @@ func TestSuccessfulUserCommitFilesRequestStartShaRemoteRepository(t *testing.T)
require.NoError(t, err)
update := resp.GetBranchUpdate()
- newTargetBranchCommit, err := log.GetCommit(ctxOuter, newRepo, targetBranchName)
+ newTargetBranchCommit, err := log.GetCommit(ctx, newRepo, targetBranchName)
require.NoError(t, err)
require.Equal(t, newTargetBranchCommit.Id, update.CommitId)
@@ -332,6 +1098,10 @@ func TestSuccessfulUserCommitFilesRequestStartShaRemoteRepository(t *testing.T)
}
func TestSuccessfulUserCommitFilesRequestWithSpecialCharactersInSignature(t *testing.T) {
+ testImplementations(t, testSuccessfulUserCommitFilesRequestWithSpecialCharactersInSignature)
+}
+
+func testSuccessfulUserCommitFilesRequestWithSpecialCharactersInSignature(t *testing.T, ctx context.Context) {
serverSocketPath, stop := runOperationServiceServer(t)
defer stop()
@@ -341,10 +1111,6 @@ func TestSuccessfulUserCommitFilesRequestWithSpecialCharactersInSignature(t *tes
testRepo, _, cleanupFn := testhelper.InitBareRepo(t)
defer cleanupFn()
- ctxOuter, cancel := testhelper.Context()
- defer cancel()
-
- md := testhelper.GitalyServersMetadata(t, serverSocketPath)
targetBranchName := "master"
testCases := []struct {
@@ -366,7 +1132,6 @@ func TestSuccessfulUserCommitFilesRequestWithSpecialCharactersInSignature(t *tes
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
- ctx := metadata.NewOutgoingContext(ctxOuter, md)
headerRequest := headerRequest(testRepo, tc.user, targetBranchName, commitFilesMessage)
setAuthorAndEmail(headerRequest, tc.user.Name, tc.user.Email)
@@ -377,7 +1142,7 @@ func TestSuccessfulUserCommitFilesRequestWithSpecialCharactersInSignature(t *tes
_, err = stream.CloseAndRecv()
require.NoError(t, err)
- newCommit, err := log.GetCommit(ctxOuter, testRepo, targetBranchName)
+ newCommit, err := log.GetCommit(ctx, testRepo, targetBranchName)
require.NoError(t, err)
require.Equal(t, tc.author.Name, newCommit.Author.Name, "author name")
@@ -389,6 +1154,10 @@ func TestSuccessfulUserCommitFilesRequestWithSpecialCharactersInSignature(t *tes
}
func TestFailedUserCommitFilesRequestDueToHooks(t *testing.T) {
+ testImplementations(t, testFailedUserCommitFilesRequestDueToHooks)
+}
+
+func testFailedUserCommitFilesRequestDueToHooks(t *testing.T, ctx context.Context) {
serverSocketPath, stop := runOperationServiceServer(t)
defer stop()
@@ -398,9 +1167,6 @@ func TestFailedUserCommitFilesRequestDueToHooks(t *testing.T) {
testRepo, testRepoPath, cleanupFn := testhelper.NewTestRepo(t)
defer cleanupFn()
- ctxOuter, cancel := testhelper.Context()
- defer cancel()
-
branchName := "feature"
filePath := "my/file.txt"
headerRequest := headerRequest(testRepo, testhelper.TestUser, branchName, commitFilesMessage)
@@ -413,8 +1179,7 @@ func TestFailedUserCommitFilesRequestDueToHooks(t *testing.T) {
remove, err := testhelper.WriteCustomHook(testRepoPath, hookName, hookContent)
require.NoError(t, err)
defer remove()
- md := testhelper.GitalyServersMetadata(t, serverSocketPath)
- ctx := metadata.NewOutgoingContext(ctxOuter, md)
+
stream, err := client.UserCommitFiles(ctx)
require.NoError(t, err)
require.NoError(t, stream.Send(headerRequest))
@@ -431,6 +1196,10 @@ func TestFailedUserCommitFilesRequestDueToHooks(t *testing.T) {
}
func TestFailedUserCommitFilesRequestDueToIndexError(t *testing.T) {
+ testImplementations(t, testFailedUserCommitFilesRequestDueToIndexError)
+}
+
+func testFailedUserCommitFilesRequestDueToIndexError(t *testing.T, ctx context.Context) {
serverSocketPath, stop := runOperationServiceServer(t)
defer stop()
@@ -440,11 +1209,6 @@ func TestFailedUserCommitFilesRequestDueToIndexError(t *testing.T) {
testRepo, _, cleanupFn := testhelper.NewTestRepo(t)
defer cleanupFn()
- ctxOuter, cancel := testhelper.Context()
- defer cancel()
-
- md := testhelper.GitalyServersMetadata(t, serverSocketPath)
- ctx := metadata.NewOutgoingContext(ctxOuter, md)
testCases := []struct {
desc string
requests []*gitalypb.UserCommitFilesRequest
@@ -503,6 +1267,10 @@ func TestFailedUserCommitFilesRequestDueToIndexError(t *testing.T) {
}
func TestFailedUserCommitFilesRequest(t *testing.T) {
+ testImplementations(t, testFailedUserCommitFilesRequest)
+}
+
+func testFailedUserCommitFilesRequest(t *testing.T, ctx context.Context) {
serverSocketPath, stop := runOperationServiceServer(t)
defer stop()
@@ -512,11 +1280,6 @@ func TestFailedUserCommitFilesRequest(t *testing.T) {
testRepo, _, cleanupFn := testhelper.NewTestRepo(t)
defer cleanupFn()
- ctxOuter, cancel := testhelper.Context()
- defer cancel()
-
- md := testhelper.GitalyServersMetadata(t, serverSocketPath)
- ctx := metadata.NewOutgoingContext(ctxOuter, md)
branchName := "feature"
testCases := []struct {
@@ -626,6 +1389,17 @@ func getHeader(headerRequest *gitalypb.UserCommitFilesRequest) *gitalypb.UserCom
return headerRequest.UserCommitFilesRequestPayload.(*gitalypb.UserCommitFilesRequest_Header).Header
}
+func createDirHeaderRequest(filePath string) *gitalypb.UserCommitFilesRequest {
+ return actionRequest(&gitalypb.UserCommitFilesAction{
+ UserCommitFilesActionPayload: &gitalypb.UserCommitFilesAction_Header{
+ Header: &gitalypb.UserCommitFilesActionHeader{
+ Action: gitalypb.UserCommitFilesActionHeader_CREATE_DIR,
+ FilePath: []byte(filePath),
+ },
+ },
+ })
+}
+
func createFileHeaderRequest(filePath string) *gitalypb.UserCommitFilesRequest {
return actionRequest(&gitalypb.UserCommitFilesAction{
UserCommitFilesActionPayload: &gitalypb.UserCommitFilesAction_Header{
@@ -638,6 +1412,41 @@ func createFileHeaderRequest(filePath string) *gitalypb.UserCommitFilesRequest {
})
}
+func createBase64FileHeaderRequest(filePath string) *gitalypb.UserCommitFilesRequest {
+ return actionRequest(&gitalypb.UserCommitFilesAction{
+ UserCommitFilesActionPayload: &gitalypb.UserCommitFilesAction_Header{
+ Header: &gitalypb.UserCommitFilesActionHeader{
+ Action: gitalypb.UserCommitFilesActionHeader_CREATE,
+ Base64Content: true,
+ FilePath: []byte(filePath),
+ },
+ },
+ })
+}
+
+func updateFileHeaderRequest(filePath string) *gitalypb.UserCommitFilesRequest {
+ return actionRequest(&gitalypb.UserCommitFilesAction{
+ UserCommitFilesActionPayload: &gitalypb.UserCommitFilesAction_Header{
+ Header: &gitalypb.UserCommitFilesActionHeader{
+ Action: gitalypb.UserCommitFilesActionHeader_UPDATE,
+ FilePath: []byte(filePath),
+ },
+ },
+ })
+}
+
+func updateBase64FileHeaderRequest(filePath string) *gitalypb.UserCommitFilesRequest {
+ return actionRequest(&gitalypb.UserCommitFilesAction{
+ UserCommitFilesActionPayload: &gitalypb.UserCommitFilesAction_Header{
+ Header: &gitalypb.UserCommitFilesActionHeader{
+ Action: gitalypb.UserCommitFilesActionHeader_UPDATE,
+ FilePath: []byte(filePath),
+ Base64Content: true,
+ },
+ },
+ })
+}
+
func chmodFileHeaderRequest(filePath string, executeFilemode bool) *gitalypb.UserCommitFilesRequest {
return actionRequest(&gitalypb.UserCommitFilesAction{
UserCommitFilesActionPayload: &gitalypb.UserCommitFilesAction_Header{
@@ -663,6 +1472,17 @@ func moveFileHeaderRequest(previousPath, filePath string, infer bool) *gitalypb.
})
}
+func deleteFileHeaderRequest(filePath string) *gitalypb.UserCommitFilesRequest {
+ return actionRequest(&gitalypb.UserCommitFilesAction{
+ UserCommitFilesActionPayload: &gitalypb.UserCommitFilesAction_Header{
+ Header: &gitalypb.UserCommitFilesActionHeader{
+ Action: gitalypb.UserCommitFilesActionHeader_DELETE,
+ FilePath: []byte(filePath),
+ },
+ },
+ })
+}
+
func actionContentRequest(content string) *gitalypb.UserCommitFilesRequest {
return actionRequest(&gitalypb.UserCommitFilesAction{
UserCommitFilesActionPayload: &gitalypb.UserCommitFilesAction_Content{