code.gitea.io/gitea@v1.22.3/models/issues/issue_xref_test.go (about) 1 // Copyright 2019 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package issues_test 5 6 import ( 7 "fmt" 8 "testing" 9 10 "code.gitea.io/gitea/models/db" 11 issues_model "code.gitea.io/gitea/models/issues" 12 repo_model "code.gitea.io/gitea/models/repo" 13 "code.gitea.io/gitea/models/unittest" 14 user_model "code.gitea.io/gitea/models/user" 15 "code.gitea.io/gitea/modules/references" 16 17 "github.com/stretchr/testify/assert" 18 ) 19 20 func TestXRef_AddCrossReferences(t *testing.T) { 21 assert.NoError(t, unittest.PrepareTestDatabase()) 22 23 // Issue #1 to test against 24 itarget := testCreateIssue(t, 1, 2, "title1", "content1", false) 25 26 // PR to close issue #1 27 content := fmt.Sprintf("content2, closes #%d", itarget.Index) 28 pr := testCreateIssue(t, 1, 2, "title2", content, true) 29 ref := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{IssueID: itarget.ID, RefIssueID: pr.ID, RefCommentID: 0}) 30 assert.Equal(t, issues_model.CommentTypePullRef, ref.Type) 31 assert.Equal(t, pr.RepoID, ref.RefRepoID) 32 assert.True(t, ref.RefIsPull) 33 assert.Equal(t, references.XRefActionCloses, ref.RefAction) 34 35 // Comment on PR to reopen issue #1 36 content = fmt.Sprintf("content2, reopens #%d", itarget.Index) 37 c := testCreateComment(t, 1, 2, pr.ID, content) 38 ref = unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{IssueID: itarget.ID, RefIssueID: pr.ID, RefCommentID: c.ID}) 39 assert.Equal(t, issues_model.CommentTypeCommentRef, ref.Type) 40 assert.Equal(t, pr.RepoID, ref.RefRepoID) 41 assert.True(t, ref.RefIsPull) 42 assert.Equal(t, references.XRefActionReopens, ref.RefAction) 43 44 // Issue mentioning issue #1 45 content = fmt.Sprintf("content3, mentions #%d", itarget.Index) 46 i := testCreateIssue(t, 1, 2, "title3", content, false) 47 ref = unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{IssueID: itarget.ID, RefIssueID: i.ID, RefCommentID: 0}) 48 assert.Equal(t, issues_model.CommentTypeIssueRef, ref.Type) 49 assert.Equal(t, pr.RepoID, ref.RefRepoID) 50 assert.False(t, ref.RefIsPull) 51 assert.Equal(t, references.XRefActionNone, ref.RefAction) 52 53 // Issue #4 to test against 54 itarget = testCreateIssue(t, 3, 3, "title4", "content4", false) 55 56 // Cross-reference to issue #4 by admin 57 content = fmt.Sprintf("content5, mentions org3/repo3#%d", itarget.Index) 58 i = testCreateIssue(t, 2, 1, "title5", content, false) 59 ref = unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{IssueID: itarget.ID, RefIssueID: i.ID, RefCommentID: 0}) 60 assert.Equal(t, issues_model.CommentTypeIssueRef, ref.Type) 61 assert.Equal(t, i.RepoID, ref.RefRepoID) 62 assert.False(t, ref.RefIsPull) 63 assert.Equal(t, references.XRefActionNone, ref.RefAction) 64 65 // Cross-reference to issue #4 with no permission 66 content = fmt.Sprintf("content6, mentions org3/repo3#%d", itarget.Index) 67 i = testCreateIssue(t, 4, 5, "title6", content, false) 68 unittest.AssertNotExistsBean(t, &issues_model.Comment{IssueID: itarget.ID, RefIssueID: i.ID, RefCommentID: 0}) 69 } 70 71 func TestXRef_NeuterCrossReferences(t *testing.T) { 72 assert.NoError(t, unittest.PrepareTestDatabase()) 73 74 // Issue #1 to test against 75 itarget := testCreateIssue(t, 1, 2, "title1", "content1", false) 76 77 // Issue mentioning issue #1 78 title := fmt.Sprintf("title2, mentions #%d", itarget.Index) 79 i := testCreateIssue(t, 1, 2, title, "content2", false) 80 ref := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{IssueID: itarget.ID, RefIssueID: i.ID, RefCommentID: 0}) 81 assert.Equal(t, issues_model.CommentTypeIssueRef, ref.Type) 82 assert.Equal(t, references.XRefActionNone, ref.RefAction) 83 84 d := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) 85 i.Title = "title2, no mentions" 86 assert.NoError(t, issues_model.ChangeIssueTitle(db.DefaultContext, i, d, title)) 87 88 ref = unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{IssueID: itarget.ID, RefIssueID: i.ID, RefCommentID: 0}) 89 assert.Equal(t, issues_model.CommentTypeIssueRef, ref.Type) 90 assert.Equal(t, references.XRefActionNeutered, ref.RefAction) 91 } 92 93 func TestXRef_ResolveCrossReferences(t *testing.T) { 94 assert.NoError(t, unittest.PrepareTestDatabase()) 95 96 d := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) 97 98 i1 := testCreateIssue(t, 1, 2, "title1", "content1", false) 99 i2 := testCreateIssue(t, 1, 2, "title2", "content2", false) 100 i3 := testCreateIssue(t, 1, 2, "title3", "content3", false) 101 _, err := issues_model.ChangeIssueStatus(db.DefaultContext, i3, d, true) 102 assert.NoError(t, err) 103 104 pr := testCreatePR(t, 1, 2, "titlepr", fmt.Sprintf("closes #%d", i1.Index)) 105 rp := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{IssueID: i1.ID, RefIssueID: pr.Issue.ID, RefCommentID: 0}) 106 107 c1 := testCreateComment(t, 1, 2, pr.Issue.ID, fmt.Sprintf("closes #%d", i2.Index)) 108 r1 := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{IssueID: i2.ID, RefIssueID: pr.Issue.ID, RefCommentID: c1.ID}) 109 110 // Must be ignored 111 c2 := testCreateComment(t, 1, 2, pr.Issue.ID, fmt.Sprintf("mentions #%d", i2.Index)) 112 unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{IssueID: i2.ID, RefIssueID: pr.Issue.ID, RefCommentID: c2.ID}) 113 114 // Must be superseded by c4/r4 115 c3 := testCreateComment(t, 1, 2, pr.Issue.ID, fmt.Sprintf("reopens #%d", i3.Index)) 116 unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{IssueID: i3.ID, RefIssueID: pr.Issue.ID, RefCommentID: c3.ID}) 117 118 c4 := testCreateComment(t, 1, 2, pr.Issue.ID, fmt.Sprintf("closes #%d", i3.Index)) 119 r4 := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{IssueID: i3.ID, RefIssueID: pr.Issue.ID, RefCommentID: c4.ID}) 120 121 refs, err := pr.ResolveCrossReferences(db.DefaultContext) 122 assert.NoError(t, err) 123 assert.Len(t, refs, 3) 124 assert.Equal(t, rp.ID, refs[0].ID, "bad ref rp: %+v", refs[0]) 125 assert.Equal(t, r1.ID, refs[1].ID, "bad ref r1: %+v", refs[1]) 126 assert.Equal(t, r4.ID, refs[2].ID, "bad ref r4: %+v", refs[2]) 127 } 128 129 func testCreateIssue(t *testing.T, repo, doer int64, title, content string, ispull bool) *issues_model.Issue { 130 r := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repo}) 131 d := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: doer}) 132 133 ctx, committer, err := db.TxContext(db.DefaultContext) 134 assert.NoError(t, err) 135 defer committer.Close() 136 137 idx, err := db.GetNextResourceIndex(ctx, "issue_index", r.ID) 138 assert.NoError(t, err) 139 i := &issues_model.Issue{ 140 RepoID: r.ID, 141 PosterID: d.ID, 142 Poster: d, 143 Title: title, 144 Content: content, 145 IsPull: ispull, 146 Index: idx, 147 } 148 149 err = issues_model.NewIssueWithIndex(ctx, d, issues_model.NewIssueOptions{ 150 Repo: r, 151 Issue: i, 152 }) 153 assert.NoError(t, err) 154 i, err = issues_model.GetIssueByID(ctx, i.ID) 155 assert.NoError(t, err) 156 assert.NoError(t, i.AddCrossReferences(ctx, d, false)) 157 assert.NoError(t, committer.Commit()) 158 return i 159 } 160 161 func testCreatePR(t *testing.T, repo, doer int64, title, content string) *issues_model.PullRequest { 162 r := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repo}) 163 d := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: doer}) 164 i := &issues_model.Issue{RepoID: r.ID, PosterID: d.ID, Poster: d, Title: title, Content: content, IsPull: true} 165 pr := &issues_model.PullRequest{HeadRepoID: repo, BaseRepoID: repo, HeadBranch: "head", BaseBranch: "base", Status: issues_model.PullRequestStatusMergeable} 166 assert.NoError(t, issues_model.NewPullRequest(db.DefaultContext, r, i, nil, nil, pr)) 167 pr.Issue = i 168 return pr 169 } 170 171 func testCreateComment(t *testing.T, repo, doer, issue int64, content string) *issues_model.Comment { 172 d := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: doer}) 173 i := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: issue}) 174 c := &issues_model.Comment{Type: issues_model.CommentTypeComment, PosterID: doer, Poster: d, IssueID: issue, Issue: i, Content: content} 175 176 ctx, committer, err := db.TxContext(db.DefaultContext) 177 assert.NoError(t, err) 178 defer committer.Close() 179 err = db.Insert(ctx, c) 180 assert.NoError(t, err) 181 assert.NoError(t, c.AddCrossReferences(ctx, d, false)) 182 assert.NoError(t, committer.Commit()) 183 return c 184 }