diff options
author | Anthony Wang | 2023-01-20 18:14:48 +0000 |
---|---|---|
committer | Anthony Wang | 2023-01-20 18:14:48 +0000 |
commit | a86a11f874ccabf1639142107f40cd3f2cb567ac (patch) | |
tree | c68a6849c0b4787a45d742cfe7b22b5f8ba568ca /tests | |
parent | 508a8486167e5202a2abee00294719ec3f803dfa (diff) | |
parent | 3510d7e33ace5302691b6e96b9bde71148ed6e4c (diff) |
Merge remote-tracking branch 'origin/main' into forgejo-federation
Diffstat (limited to 'tests')
-rw-r--r-- | tests/integration/api_branch_test.go | 12 | ||||
-rw-r--r-- | tests/integration/api_packages_container_test.go | 41 | ||||
-rw-r--r-- | tests/integration/api_repo_teams_test.go | 2 | ||||
-rw-r--r-- | tests/integration/editor_test.go | 27 | ||||
-rw-r--r-- | tests/integration/git_test.go | 10 | ||||
-rw-r--r-- | tests/integration/incoming_email_test.go | 249 | ||||
-rw-r--r-- | tests/mysql.ini.tmpl | 10 |
7 files changed, 315 insertions, 36 deletions
diff --git a/tests/integration/api_branch_test.go b/tests/integration/api_branch_test.go index c176a144c..278edfbf9 100644 --- a/tests/integration/api_branch_test.go +++ b/tests/integration/api_branch_test.go @@ -38,21 +38,21 @@ func testAPIGetBranchProtection(t *testing.T, branchName string, expectedHTTPSta if resp.Code == http.StatusOK { var branchProtection api.BranchProtection DecodeJSON(t, resp, &branchProtection) - assert.EqualValues(t, branchName, branchProtection.BranchName) + assert.EqualValues(t, branchName, branchProtection.RuleName) } } func testAPICreateBranchProtection(t *testing.T, branchName string, expectedHTTPStatus int) { token := getUserToken(t, "user2") req := NewRequestWithJSON(t, "POST", "/api/v1/repos/user2/repo1/branch_protections?token="+token, &api.BranchProtection{ - BranchName: branchName, + RuleName: branchName, }) resp := MakeRequest(t, req, expectedHTTPStatus) if resp.Code == http.StatusCreated { var branchProtection api.BranchProtection DecodeJSON(t, resp, &branchProtection) - assert.EqualValues(t, branchName, branchProtection.BranchName) + assert.EqualValues(t, branchName, branchProtection.RuleName) } } @@ -64,7 +64,7 @@ func testAPIEditBranchProtection(t *testing.T, branchName string, body *api.Bran if resp.Code == http.StatusOK { var branchProtection api.BranchProtection DecodeJSON(t, resp, &branchProtection) - assert.EqualValues(t, branchName, branchProtection.BranchName) + assert.EqualValues(t, branchName, branchProtection.RuleName) } } @@ -169,8 +169,8 @@ func testAPICreateBranch(t testing.TB, session *TestSession, user, repo, oldBran func TestAPIBranchProtection(t *testing.T) { defer tests.PrepareTestEnv(t)() - // Branch protection only on branch that exist - testAPICreateBranchProtection(t, "master/doesnotexist", http.StatusNotFound) + // Branch protection on branch that not exist + testAPICreateBranchProtection(t, "master/doesnotexist", http.StatusCreated) // Get branch protection on branch that exist but not branch protection testAPIGetBranchProtection(t, "master", http.StatusNotFound) diff --git a/tests/integration/api_packages_container_test.go b/tests/integration/api_packages_container_test.go index 851021da1..1dcd76a31 100644 --- a/tests/integration/api_packages_container_test.go +++ b/tests/integration/api_packages_container_test.go @@ -256,6 +256,32 @@ func TestPackageContainer(t *testing.T) { }) }) + t.Run("UploadBlob/Mount", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + req := NewRequest(t, "POST", fmt.Sprintf("%s/blobs/uploads?mount=%s", url, unknownDigest)) + addTokenAuthHeader(req, userToken) + MakeRequest(t, req, http.StatusAccepted) + + req = NewRequest(t, "POST", fmt.Sprintf("%s/blobs/uploads?mount=%s", url, blobDigest)) + addTokenAuthHeader(req, userToken) + resp := MakeRequest(t, req, http.StatusCreated) + + assert.Equal(t, fmt.Sprintf("/v2/%s/%s/blobs/%s", user.Name, image, blobDigest), resp.Header().Get("Location")) + assert.Equal(t, blobDigest, resp.Header().Get("Docker-Content-Digest")) + + req = NewRequest(t, "POST", fmt.Sprintf("%s/blobs/uploads?mount=%s&from=%s", url, unknownDigest, "unknown/image")) + addTokenAuthHeader(req, userToken) + MakeRequest(t, req, http.StatusAccepted) + + req = NewRequest(t, "POST", fmt.Sprintf("%s/blobs/uploads?mount=%s&from=%s/%s", url, blobDigest, user.Name, image)) + addTokenAuthHeader(req, userToken) + resp = MakeRequest(t, req, http.StatusCreated) + + assert.Equal(t, fmt.Sprintf("/v2/%s/%s/blobs/%s", user.Name, image, blobDigest), resp.Header().Get("Location")) + assert.Equal(t, blobDigest, resp.Header().Get("Docker-Content-Digest")) + }) + for _, tag := range tags { t.Run(fmt.Sprintf("[Tag:%s]", tag), func(t *testing.T) { t.Run("UploadManifest", func(t *testing.T) { @@ -444,21 +470,6 @@ func TestPackageContainer(t *testing.T) { assert.Equal(t, indexManifestDigest, pd.Files[0].Properties.GetByName(container_module.PropertyDigest)) }) - t.Run("UploadBlob/Mount", func(t *testing.T) { - defer tests.PrintCurrentTest(t)() - - req := NewRequest(t, "POST", fmt.Sprintf("%s/blobs/uploads?mount=%s", url, unknownDigest)) - addTokenAuthHeader(req, userToken) - MakeRequest(t, req, http.StatusAccepted) - - req = NewRequest(t, "POST", fmt.Sprintf("%s/blobs/uploads?mount=%s", url, blobDigest)) - addTokenAuthHeader(req, userToken) - resp := MakeRequest(t, req, http.StatusCreated) - - assert.Equal(t, fmt.Sprintf("/v2/%s/%s/blobs/%s", user.Name, image, blobDigest), resp.Header().Get("Location")) - assert.Equal(t, blobDigest, resp.Header().Get("Docker-Content-Digest")) - }) - t.Run("HeadBlob", func(t *testing.T) { defer tests.PrintCurrentTest(t)() diff --git a/tests/integration/api_repo_teams_test.go b/tests/integration/api_repo_teams_test.go index e4d054aaf..102f170d9 100644 --- a/tests/integration/api_repo_teams_test.go +++ b/tests/integration/api_repo_teams_test.go @@ -38,7 +38,7 @@ func TestAPIRepoTeams(t *testing.T) { if assert.Len(t, teams, 2) { assert.EqualValues(t, "Owners", teams[0].Name) assert.True(t, teams[0].CanCreateOrgRepo) - assert.True(t, util.IsEqualSlice(unit.AllUnitKeyNames(), teams[0].Units), fmt.Sprintf("%v == %v", unit.AllUnitKeyNames(), teams[0].Units)) + assert.True(t, util.SliceSortedEqual(unit.AllUnitKeyNames(), teams[0].Units), fmt.Sprintf("%v == %v", unit.AllUnitKeyNames(), teams[0].Units)) assert.EqualValues(t, "owner", teams[0].Permission) assert.EqualValues(t, "test_team", teams[1].Name) diff --git a/tests/integration/editor_test.go b/tests/integration/editor_test.go index 4355dd0a4..791506d8f 100644 --- a/tests/integration/editor_test.go +++ b/tests/integration/editor_test.go @@ -10,6 +10,8 @@ import ( "path" "testing" + "code.gitea.io/gitea/modules/json" + "github.com/stretchr/testify/assert" ) @@ -43,15 +45,16 @@ func TestCreateFileOnProtectedBranch(t *testing.T) { csrf := GetCSRF(t, session, "/user2/repo1/settings/branches") // Change master branch to protected - req := NewRequestWithValues(t, "POST", "/user2/repo1/settings/branches/master", map[string]string{ - "_csrf": csrf, - "protected": "on", + req := NewRequestWithValues(t, "POST", "/user2/repo1/settings/branches/edit", map[string]string{ + "_csrf": csrf, + "rule_name": "master", + "enable_push": "true", }) session.MakeRequest(t, req, http.StatusSeeOther) // Check if master branch has been locked successfully flashCookie := session.GetCookie("macaron_flash") assert.NotNil(t, flashCookie) - assert.EqualValues(t, "success%3DBranch%2Bprotection%2Bfor%2Bbranch%2B%2527master%2527%2Bhas%2Bbeen%2Bupdated.", flashCookie.Value) + assert.EqualValues(t, "success%3DBranch%2Bprotection%2Bfor%2Brule%2B%2527master%2527%2Bhas%2Bbeen%2Bupdated.", flashCookie.Value) // Request editor page req = NewRequest(t, "GET", "/user2/repo1/_new/master/") @@ -76,16 +79,22 @@ func TestCreateFileOnProtectedBranch(t *testing.T) { // remove the protected branch csrf = GetCSRF(t, session, "/user2/repo1/settings/branches") + // Change master branch to protected - req = NewRequestWithValues(t, "POST", "/user2/repo1/settings/branches/master", map[string]string{ - "_csrf": csrf, - "protected": "off", + req = NewRequestWithValues(t, "POST", "/user2/repo1/settings/branches/1/delete", map[string]string{ + "_csrf": csrf, }) - session.MakeRequest(t, req, http.StatusSeeOther) + + resp = session.MakeRequest(t, req, http.StatusOK) + + res := make(map[string]string) + assert.NoError(t, json.NewDecoder(resp.Body).Decode(&res)) + assert.EqualValues(t, "/user2/repo1/settings/branches", res["redirect"]) + // Check if master branch has been locked successfully flashCookie = session.GetCookie("macaron_flash") assert.NotNil(t, flashCookie) - assert.EqualValues(t, "success%3DBranch%2Bprotection%2Bfor%2Bbranch%2B%2527master%2527%2Bhas%2Bbeen%2Bdisabled.", flashCookie.Value) + assert.EqualValues(t, "error%3DRemoving%2Bbranch%2Bprotection%2Brule%2B%25271%2527%2Bfailed.", flashCookie.Value) }) } diff --git a/tests/integration/git_test.go b/tests/integration/git_test.go index 8d29a161d..f7e1e04b1 100644 --- a/tests/integration/git_test.go +++ b/tests/integration/git_test.go @@ -414,9 +414,9 @@ func doProtectBranch(ctx APITestContext, branch, userToWhitelist, unprotectedFil if userToWhitelist == "" { // Change branch to protected - req := NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/%s/settings/branches/%s", url.PathEscape(ctx.Username), url.PathEscape(ctx.Reponame), url.PathEscape(branch)), map[string]string{ + req := NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/%s/settings/branches/edit", url.PathEscape(ctx.Username), url.PathEscape(ctx.Reponame)), map[string]string{ "_csrf": csrf, - "protected": "on", + "rule_name": branch, "unprotected_file_patterns": unprotectedFilePatterns, }) ctx.Session.MakeRequest(t, req, http.StatusSeeOther) @@ -424,9 +424,9 @@ func doProtectBranch(ctx APITestContext, branch, userToWhitelist, unprotectedFil user, err := user_model.GetUserByName(db.DefaultContext, userToWhitelist) assert.NoError(t, err) // Change branch to protected - req := NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/%s/settings/branches/%s", url.PathEscape(ctx.Username), url.PathEscape(ctx.Reponame), url.PathEscape(branch)), map[string]string{ + req := NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/%s/settings/branches/edit", url.PathEscape(ctx.Username), url.PathEscape(ctx.Reponame)), map[string]string{ "_csrf": csrf, - "protected": "on", + "rule_name": branch, "enable_push": "whitelist", "enable_whitelist": "on", "whitelist_users": strconv.FormatInt(user.ID, 10), @@ -437,7 +437,7 @@ func doProtectBranch(ctx APITestContext, branch, userToWhitelist, unprotectedFil // Check if master branch has been locked successfully flashCookie := ctx.Session.GetCookie("macaron_flash") assert.NotNil(t, flashCookie) - assert.EqualValues(t, "success%3DBranch%2Bprotection%2Bfor%2Bbranch%2B%2527"+url.QueryEscape(branch)+"%2527%2Bhas%2Bbeen%2Bupdated.", flashCookie.Value) + assert.EqualValues(t, "success%3DBranch%2Bprotection%2Bfor%2Brule%2B%2527"+url.QueryEscape(branch)+"%2527%2Bhas%2Bbeen%2Bupdated.", flashCookie.Value) } } diff --git a/tests/integration/incoming_email_test.go b/tests/integration/incoming_email_test.go new file mode 100644 index 000000000..b4478f578 --- /dev/null +++ b/tests/integration/incoming_email_test.go @@ -0,0 +1,249 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package integration + +import ( + "io" + "net" + "net/smtp" + "strings" + "testing" + "time" + + "code.gitea.io/gitea/models/db" + issues_model "code.gitea.io/gitea/models/issues" + "code.gitea.io/gitea/models/unittest" + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/services/mailer/incoming" + incoming_payload "code.gitea.io/gitea/services/mailer/incoming/payload" + token_service "code.gitea.io/gitea/services/mailer/token" + "code.gitea.io/gitea/tests" + + "github.com/stretchr/testify/assert" + "gopkg.in/gomail.v2" +) + +func TestIncomingEmail(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) + issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1}) + + t.Run("Payload", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + comment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: 1}) + + _, err := incoming_payload.CreateReferencePayload(user) + assert.Error(t, err) + + issuePayload, err := incoming_payload.CreateReferencePayload(issue) + assert.NoError(t, err) + commentPayload, err := incoming_payload.CreateReferencePayload(comment) + assert.NoError(t, err) + + _, err = incoming_payload.GetReferenceFromPayload(db.DefaultContext, []byte{1, 2, 3}) + assert.Error(t, err) + + ref, err := incoming_payload.GetReferenceFromPayload(db.DefaultContext, issuePayload) + assert.NoError(t, err) + assert.IsType(t, ref, new(issues_model.Issue)) + assert.EqualValues(t, issue.ID, ref.(*issues_model.Issue).ID) + + ref, err = incoming_payload.GetReferenceFromPayload(db.DefaultContext, commentPayload) + assert.NoError(t, err) + assert.IsType(t, ref, new(issues_model.Comment)) + assert.EqualValues(t, comment.ID, ref.(*issues_model.Comment).ID) + }) + + t.Run("Token", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + payload := []byte{1, 2, 3, 4, 5} + + token, err := token_service.CreateToken(token_service.ReplyHandlerType, user, payload) + assert.NoError(t, err) + assert.NotEmpty(t, token) + + ht, u, p, err := token_service.ExtractToken(db.DefaultContext, token) + assert.NoError(t, err) + assert.Equal(t, token_service.ReplyHandlerType, ht) + assert.Equal(t, user.ID, u.ID) + assert.Equal(t, payload, p) + }) + + t.Run("Handler", func(t *testing.T) { + t.Run("Reply", func(t *testing.T) { + t.Run("Comment", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + handler := &incoming.ReplyHandler{} + + payload, err := incoming_payload.CreateReferencePayload(issue) + assert.NoError(t, err) + + assert.Error(t, handler.Handle(db.DefaultContext, &incoming.MailContent{}, nil, payload)) + assert.NoError(t, handler.Handle(db.DefaultContext, &incoming.MailContent{}, user, payload)) + + content := &incoming.MailContent{ + Content: "reply by mail", + Attachments: []*incoming.Attachment{ + { + Name: "attachment.txt", + Content: []byte("test"), + }, + }, + } + + assert.NoError(t, handler.Handle(db.DefaultContext, content, user, payload)) + + comments, err := issues_model.FindComments(db.DefaultContext, &issues_model.FindCommentsOptions{ + IssueID: issue.ID, + Type: issues_model.CommentTypeComment, + }) + assert.NoError(t, err) + assert.NotEmpty(t, comments) + comment := comments[len(comments)-1] + assert.Equal(t, user.ID, comment.PosterID) + assert.Equal(t, content.Content, comment.Content) + assert.NoError(t, comment.LoadAttachments(db.DefaultContext)) + assert.Len(t, comment.Attachments, 1) + attachment := comment.Attachments[0] + assert.Equal(t, content.Attachments[0].Name, attachment.Name) + assert.EqualValues(t, 4, attachment.Size) + }) + + t.Run("CodeComment", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + comment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: 6}) + issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: comment.IssueID}) + + handler := &incoming.ReplyHandler{} + content := &incoming.MailContent{ + Content: "code reply by mail", + Attachments: []*incoming.Attachment{ + { + Name: "attachment.txt", + Content: []byte("test"), + }, + }, + } + + payload, err := incoming_payload.CreateReferencePayload(comment) + assert.NoError(t, err) + + assert.NoError(t, handler.Handle(db.DefaultContext, content, user, payload)) + + comments, err := issues_model.FindComments(db.DefaultContext, &issues_model.FindCommentsOptions{ + IssueID: issue.ID, + Type: issues_model.CommentTypeCode, + }) + assert.NoError(t, err) + assert.NotEmpty(t, comments) + comment = comments[len(comments)-1] + assert.Equal(t, user.ID, comment.PosterID) + assert.Equal(t, content.Content, comment.Content) + assert.NoError(t, comment.LoadAttachments(db.DefaultContext)) + assert.Empty(t, comment.Attachments) + }) + }) + + t.Run("Unsubscribe", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + watching, err := issues_model.CheckIssueWatch(user, issue) + assert.NoError(t, err) + assert.True(t, watching) + + handler := &incoming.UnsubscribeHandler{} + + content := &incoming.MailContent{ + Content: "unsub me", + } + + payload, err := incoming_payload.CreateReferencePayload(issue) + assert.NoError(t, err) + + assert.NoError(t, handler.Handle(db.DefaultContext, content, user, payload)) + + watching, err = issues_model.CheckIssueWatch(user, issue) + assert.NoError(t, err) + assert.False(t, watching) + }) + }) + + if setting.IncomingEmail.Enabled { + // This test connects to the configured email server and is currently only enabled for MySql integration tests. + // It sends a reply to create a comment. If the comment is not detected after 10 seconds the test fails. + t.Run("IMAP", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + payload, err := incoming_payload.CreateReferencePayload(issue) + assert.NoError(t, err) + token, err := token_service.CreateToken(token_service.ReplyHandlerType, user, payload) + assert.NoError(t, err) + + msg := gomail.NewMessage() + msg.SetHeader("To", strings.Replace(setting.IncomingEmail.ReplyToAddress, setting.IncomingEmail.TokenPlaceholder, token, 1)) + msg.SetHeader("From", user.Email) + msg.SetBody("text/plain", token) + err = gomail.Send(&smtpTestSender{}, msg) + assert.NoError(t, err) + + assert.Eventually(t, func() bool { + comments, err := issues_model.FindComments(db.DefaultContext, &issues_model.FindCommentsOptions{ + IssueID: issue.ID, + Type: issues_model.CommentTypeComment, + }) + assert.NoError(t, err) + assert.NotEmpty(t, comments) + + comment := comments[len(comments)-1] + + return comment.PosterID == user.ID && comment.Content == token + }, 10*time.Second, 1*time.Second) + }) + } +} + +// A simple SMTP mail sender used for integration tests. +type smtpTestSender struct{} + +func (s *smtpTestSender) Send(from string, to []string, msg io.WriterTo) error { + conn, err := net.Dial("tcp", net.JoinHostPort(setting.IncomingEmail.Host, "25")) + if err != nil { + return err + } + defer conn.Close() + + client, err := smtp.NewClient(conn, setting.IncomingEmail.Host) + if err != nil { + return err + } + + if err = client.Mail(from); err != nil { + return err + } + + for _, rec := range to { + if err = client.Rcpt(rec); err != nil { + return err + } + } + + w, err := client.Data() + if err != nil { + return err + } + if _, err := msg.WriteTo(w); err != nil { + return err + } + if err := w.Close(); err != nil { + return err + } + + return client.Quit() +} diff --git a/tests/mysql.ini.tmpl b/tests/mysql.ini.tmpl index 24a9a02dc..44914d087 100644 --- a/tests/mysql.ini.tmpl +++ b/tests/mysql.ini.tmpl @@ -124,3 +124,13 @@ INTERNAL_TOKEN = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE0OTU1NTE2MTh9.h [packages] ENABLED = true + +[email.incoming] +ENABLED = true +HOST = smtpimap +PORT = 993 +USERNAME = debug@localdomain.test +PASSWORD = debug +USE_TLS = true +SKIP_TLS_VERIFY = true +REPLY_TO_ADDRESS = incoming+%{token}@localhost |