You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

action_test.go 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  1. package models
  2. import (
  3. "fmt"
  4. "path"
  5. "strings"
  6. "testing"
  7. "code.gitea.io/gitea/modules/setting"
  8. "github.com/stretchr/testify/assert"
  9. )
  10. func TestAction_GetRepoPath(t *testing.T) {
  11. assert.NoError(t, PrepareTestDatabase())
  12. repo := AssertExistsAndLoadBean(t, &Repository{}).(*Repository)
  13. owner := AssertExistsAndLoadBean(t, &User{ID: repo.OwnerID}).(*User)
  14. action := &Action{RepoID: repo.ID}
  15. assert.Equal(t, path.Join(owner.Name, repo.Name), action.GetRepoPath())
  16. }
  17. func TestAction_GetRepoLink(t *testing.T) {
  18. assert.NoError(t, PrepareTestDatabase())
  19. repo := AssertExistsAndLoadBean(t, &Repository{}).(*Repository)
  20. owner := AssertExistsAndLoadBean(t, &User{ID: repo.OwnerID}).(*User)
  21. action := &Action{RepoID: repo.ID}
  22. setting.AppSubURL = "/suburl/"
  23. expected := path.Join(setting.AppSubURL, owner.Name, repo.Name)
  24. assert.Equal(t, expected, action.GetRepoLink())
  25. }
  26. func TestNewRepoAction(t *testing.T) {
  27. assert.NoError(t, PrepareTestDatabase())
  28. user := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
  29. repo := AssertExistsAndLoadBean(t, &Repository{OwnerID: user.ID}).(*Repository)
  30. repo.Owner = user
  31. actionBean := &Action{
  32. OpType: ActionCreateRepo,
  33. ActUserID: user.ID,
  34. RepoID: repo.ID,
  35. ActUser: user,
  36. Repo: repo,
  37. IsPrivate: repo.IsPrivate,
  38. }
  39. AssertNotExistsBean(t, actionBean)
  40. assert.NoError(t, NewRepoAction(user, repo))
  41. AssertExistsAndLoadBean(t, actionBean)
  42. CheckConsistencyFor(t, &Action{})
  43. }
  44. func TestRenameRepoAction(t *testing.T) {
  45. assert.NoError(t, PrepareTestDatabase())
  46. user := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
  47. repo := AssertExistsAndLoadBean(t, &Repository{OwnerID: user.ID}).(*Repository)
  48. repo.Owner = user
  49. oldRepoName := repo.Name
  50. const newRepoName = "newRepoName"
  51. repo.Name = newRepoName
  52. repo.LowerName = strings.ToLower(newRepoName)
  53. actionBean := &Action{
  54. OpType: ActionRenameRepo,
  55. ActUserID: user.ID,
  56. ActUser: user,
  57. RepoID: repo.ID,
  58. Repo: repo,
  59. IsPrivate: repo.IsPrivate,
  60. Content: oldRepoName,
  61. }
  62. AssertNotExistsBean(t, actionBean)
  63. assert.NoError(t, RenameRepoAction(user, oldRepoName, repo))
  64. AssertExistsAndLoadBean(t, actionBean)
  65. _, err := x.ID(repo.ID).Cols("name", "lower_name").Update(repo)
  66. assert.NoError(t, err)
  67. CheckConsistencyFor(t, &Action{})
  68. }
  69. func TestPushCommits_ToAPIPayloadCommits(t *testing.T) {
  70. pushCommits := NewPushCommits()
  71. pushCommits.Commits = []*PushCommit{
  72. {
  73. Sha1: "69554a6",
  74. CommitterEmail: "user2@example.com",
  75. CommitterName: "User2",
  76. AuthorEmail: "user2@example.com",
  77. AuthorName: "User2",
  78. Message: "not signed commit",
  79. },
  80. {
  81. Sha1: "27566bd",
  82. CommitterEmail: "user2@example.com",
  83. CommitterName: "User2",
  84. AuthorEmail: "user2@example.com",
  85. AuthorName: "User2",
  86. Message: "good signed commit (with not yet validated email)",
  87. },
  88. {
  89. Sha1: "5099b81",
  90. CommitterEmail: "user2@example.com",
  91. CommitterName: "User2",
  92. AuthorEmail: "user2@example.com",
  93. AuthorName: "User2",
  94. Message: "good signed commit",
  95. },
  96. }
  97. pushCommits.Len = len(pushCommits.Commits)
  98. repo := AssertExistsAndLoadBean(t, &Repository{ID: 16}).(*Repository)
  99. payloadCommits, err := pushCommits.ToAPIPayloadCommits(repo.RepoPath(), "/user2/repo16")
  100. assert.NoError(t, err)
  101. assert.EqualValues(t, 3, len(payloadCommits))
  102. assert.Equal(t, "69554a6", payloadCommits[0].ID)
  103. assert.Equal(t, "not signed commit", payloadCommits[0].Message)
  104. assert.Equal(t, "/user2/repo16/commit/69554a6", payloadCommits[0].URL)
  105. assert.Equal(t, "User2", payloadCommits[0].Committer.Name)
  106. assert.Equal(t, "user2", payloadCommits[0].Committer.UserName)
  107. assert.Equal(t, "User2", payloadCommits[0].Author.Name)
  108. assert.Equal(t, "user2", payloadCommits[0].Author.UserName)
  109. assert.EqualValues(t, []string{}, payloadCommits[0].Added)
  110. assert.EqualValues(t, []string{}, payloadCommits[0].Removed)
  111. assert.EqualValues(t, []string{"readme.md"}, payloadCommits[0].Modified)
  112. assert.Equal(t, "27566bd", payloadCommits[1].ID)
  113. assert.Equal(t, "good signed commit (with not yet validated email)", payloadCommits[1].Message)
  114. assert.Equal(t, "/user2/repo16/commit/27566bd", payloadCommits[1].URL)
  115. assert.Equal(t, "User2", payloadCommits[1].Committer.Name)
  116. assert.Equal(t, "user2", payloadCommits[1].Committer.UserName)
  117. assert.Equal(t, "User2", payloadCommits[1].Author.Name)
  118. assert.Equal(t, "user2", payloadCommits[1].Author.UserName)
  119. assert.EqualValues(t, []string{}, payloadCommits[1].Added)
  120. assert.EqualValues(t, []string{}, payloadCommits[1].Removed)
  121. assert.EqualValues(t, []string{"readme.md"}, payloadCommits[1].Modified)
  122. assert.Equal(t, "5099b81", payloadCommits[2].ID)
  123. assert.Equal(t, "good signed commit", payloadCommits[2].Message)
  124. assert.Equal(t, "/user2/repo16/commit/5099b81", payloadCommits[2].URL)
  125. assert.Equal(t, "User2", payloadCommits[2].Committer.Name)
  126. assert.Equal(t, "user2", payloadCommits[2].Committer.UserName)
  127. assert.Equal(t, "User2", payloadCommits[2].Author.Name)
  128. assert.Equal(t, "user2", payloadCommits[2].Author.UserName)
  129. assert.EqualValues(t, []string{"readme.md"}, payloadCommits[2].Added)
  130. assert.EqualValues(t, []string{}, payloadCommits[2].Removed)
  131. assert.EqualValues(t, []string{}, payloadCommits[2].Modified)
  132. }
  133. func TestPushCommits_AvatarLink(t *testing.T) {
  134. pushCommits := NewPushCommits()
  135. pushCommits.Commits = []*PushCommit{
  136. {
  137. Sha1: "abcdef1",
  138. CommitterEmail: "user2@example.com",
  139. CommitterName: "User Two",
  140. AuthorEmail: "user4@example.com",
  141. AuthorName: "User Four",
  142. Message: "message1",
  143. },
  144. {
  145. Sha1: "abcdef2",
  146. CommitterEmail: "user2@example.com",
  147. CommitterName: "User Two",
  148. AuthorEmail: "user2@example.com",
  149. AuthorName: "User Two",
  150. Message: "message2",
  151. },
  152. }
  153. pushCommits.Len = len(pushCommits.Commits)
  154. assert.Equal(t,
  155. "https://secure.gravatar.com/avatar/ab53a2911ddf9b4817ac01ddcd3d975f?d=identicon",
  156. pushCommits.AvatarLink("user2@example.com"))
  157. assert.Equal(t,
  158. "https://secure.gravatar.com/avatar/19ade630b94e1e0535b3df7387434154?d=identicon",
  159. pushCommits.AvatarLink("nonexistent@example.com"))
  160. }
  161. func TestRegExp_issueReferenceKeywordsPat(t *testing.T) {
  162. trueTestCases := []string{
  163. "#2",
  164. "[#2]",
  165. "please see go-gitea/gitea#5",
  166. }
  167. falseTestCases := []string{
  168. "kb#2",
  169. "#2xy",
  170. }
  171. for _, testCase := range trueTestCases {
  172. assert.True(t, issueReferenceKeywordsPat.MatchString(testCase))
  173. }
  174. for _, testCase := range falseTestCases {
  175. assert.False(t, issueReferenceKeywordsPat.MatchString(testCase))
  176. }
  177. }
  178. func Test_getIssueFromRef(t *testing.T) {
  179. assert.NoError(t, PrepareTestDatabase())
  180. repo := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository)
  181. for _, test := range []struct {
  182. Ref string
  183. ExpectedIssueID int64
  184. }{
  185. {"#2", 2},
  186. {"reopen #2", 2},
  187. {"user2/repo2#1", 4},
  188. {"fixes user2/repo2#1", 4},
  189. {"fixes: user2/repo2#1", 4},
  190. } {
  191. issue, err := getIssueFromRef(repo, test.Ref)
  192. assert.NoError(t, err)
  193. if assert.NotNil(t, issue) {
  194. assert.EqualValues(t, test.ExpectedIssueID, issue.ID)
  195. }
  196. }
  197. for _, badRef := range []string{
  198. "doesnotexist/doesnotexist#1",
  199. fmt.Sprintf("#%d", NonexistentID),
  200. } {
  201. issue, err := getIssueFromRef(repo, badRef)
  202. assert.NoError(t, err)
  203. assert.Nil(t, issue)
  204. }
  205. }
  206. func TestUpdateIssuesCommit(t *testing.T) {
  207. assert.NoError(t, PrepareTestDatabase())
  208. pushCommits := []*PushCommit{
  209. {
  210. Sha1: "abcdef1",
  211. CommitterEmail: "user2@example.com",
  212. CommitterName: "User Two",
  213. AuthorEmail: "user4@example.com",
  214. AuthorName: "User Four",
  215. Message: "start working on #FST-1, #1",
  216. },
  217. {
  218. Sha1: "abcdef2",
  219. CommitterEmail: "user2@example.com",
  220. CommitterName: "User Two",
  221. AuthorEmail: "user2@example.com",
  222. AuthorName: "User Two",
  223. Message: "a plain message",
  224. },
  225. {
  226. Sha1: "abcdef2",
  227. CommitterEmail: "user2@example.com",
  228. CommitterName: "User Two",
  229. AuthorEmail: "user2@example.com",
  230. AuthorName: "User Two",
  231. Message: "close #2",
  232. },
  233. }
  234. user := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
  235. repo := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository)
  236. repo.Owner = user
  237. commentBean := &Comment{
  238. Type: CommentTypeCommitRef,
  239. CommitSHA: "abcdef1",
  240. PosterID: user.ID,
  241. IssueID: 1,
  242. }
  243. issueBean := &Issue{RepoID: repo.ID, Index: 2}
  244. AssertNotExistsBean(t, commentBean)
  245. AssertNotExistsBean(t, &Issue{RepoID: repo.ID, Index: 2}, "is_closed=1")
  246. assert.NoError(t, UpdateIssuesCommit(user, repo, pushCommits, repo.DefaultBranch))
  247. AssertExistsAndLoadBean(t, commentBean)
  248. AssertExistsAndLoadBean(t, issueBean, "is_closed=1")
  249. CheckConsistencyFor(t, &Action{})
  250. // Test that push to a non-default branch closes no issue.
  251. pushCommits = []*PushCommit{
  252. {
  253. Sha1: "abcdef1",
  254. CommitterEmail: "user2@example.com",
  255. CommitterName: "User Two",
  256. AuthorEmail: "user4@example.com",
  257. AuthorName: "User Four",
  258. Message: "close #1",
  259. },
  260. }
  261. repo = AssertExistsAndLoadBean(t, &Repository{ID: 3}).(*Repository)
  262. commentBean = &Comment{
  263. Type: CommentTypeCommitRef,
  264. CommitSHA: "abcdef1",
  265. PosterID: user.ID,
  266. IssueID: 6,
  267. }
  268. issueBean = &Issue{RepoID: repo.ID, Index: 1}
  269. AssertNotExistsBean(t, commentBean)
  270. AssertNotExistsBean(t, &Issue{RepoID: repo.ID, Index: 1}, "is_closed=1")
  271. assert.NoError(t, UpdateIssuesCommit(user, repo, pushCommits, "non-existing-branch"))
  272. AssertExistsAndLoadBean(t, commentBean)
  273. AssertNotExistsBean(t, issueBean, "is_closed=1")
  274. CheckConsistencyFor(t, &Action{})
  275. }
  276. func TestUpdateIssuesCommit_Colon(t *testing.T) {
  277. assert.NoError(t, PrepareTestDatabase())
  278. pushCommits := []*PushCommit{
  279. {
  280. Sha1: "abcdef2",
  281. CommitterEmail: "user2@example.com",
  282. CommitterName: "User Two",
  283. AuthorEmail: "user2@example.com",
  284. AuthorName: "User Two",
  285. Message: "close: #2",
  286. },
  287. }
  288. user := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
  289. repo := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository)
  290. repo.Owner = user
  291. issueBean := &Issue{RepoID: repo.ID, Index: 2}
  292. AssertNotExistsBean(t, &Issue{RepoID: repo.ID, Index: 2}, "is_closed=1")
  293. assert.NoError(t, UpdateIssuesCommit(user, repo, pushCommits, repo.DefaultBranch))
  294. AssertExistsAndLoadBean(t, issueBean, "is_closed=1")
  295. CheckConsistencyFor(t, &Action{})
  296. }
  297. func TestUpdateIssuesCommit_Issue5957(t *testing.T) {
  298. assert.NoError(t, PrepareTestDatabase())
  299. user := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
  300. // Test that push to a non-default branch closes an issue.
  301. pushCommits := []*PushCommit{
  302. {
  303. Sha1: "abcdef1",
  304. CommitterEmail: "user2@example.com",
  305. CommitterName: "User Two",
  306. AuthorEmail: "user4@example.com",
  307. AuthorName: "User Four",
  308. Message: "close #2",
  309. },
  310. }
  311. repo := AssertExistsAndLoadBean(t, &Repository{ID: 2}).(*Repository)
  312. commentBean := &Comment{
  313. Type: CommentTypeCommitRef,
  314. CommitSHA: "abcdef1",
  315. PosterID: user.ID,
  316. IssueID: 7,
  317. }
  318. issueBean := &Issue{RepoID: repo.ID, Index: 2, ID: 7}
  319. AssertNotExistsBean(t, commentBean)
  320. AssertNotExistsBean(t, issueBean, "is_closed=1")
  321. assert.NoError(t, UpdateIssuesCommit(user, repo, pushCommits, "non-existing-branch"))
  322. AssertExistsAndLoadBean(t, commentBean)
  323. AssertExistsAndLoadBean(t, issueBean, "is_closed=1")
  324. CheckConsistencyFor(t, &Action{})
  325. }
  326. func TestUpdateIssuesCommit_AnotherRepo(t *testing.T) {
  327. assert.NoError(t, PrepareTestDatabase())
  328. user := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
  329. // Test that a push to default branch closes issue in another repo
  330. // If the user also has push permissions to that repo
  331. pushCommits := []*PushCommit{
  332. {
  333. Sha1: "abcdef1",
  334. CommitterEmail: "user2@example.com",
  335. CommitterName: "User Two",
  336. AuthorEmail: "user2@example.com",
  337. AuthorName: "User Two",
  338. Message: "close user2/repo1#1",
  339. },
  340. }
  341. repo := AssertExistsAndLoadBean(t, &Repository{ID: 2}).(*Repository)
  342. commentBean := &Comment{
  343. Type: CommentTypeCommitRef,
  344. CommitSHA: "abcdef1",
  345. PosterID: user.ID,
  346. IssueID: 1,
  347. }
  348. issueBean := &Issue{RepoID: 1, Index: 1, ID: 1}
  349. AssertNotExistsBean(t, commentBean)
  350. AssertNotExistsBean(t, issueBean, "is_closed=1")
  351. assert.NoError(t, UpdateIssuesCommit(user, repo, pushCommits, repo.DefaultBranch))
  352. AssertExistsAndLoadBean(t, commentBean)
  353. AssertExistsAndLoadBean(t, issueBean, "is_closed=1")
  354. CheckConsistencyFor(t, &Action{})
  355. }
  356. func TestUpdateIssuesCommit_AnotherRepoNoPermission(t *testing.T) {
  357. assert.NoError(t, PrepareTestDatabase())
  358. user := AssertExistsAndLoadBean(t, &User{ID: 10}).(*User)
  359. // Test that a push with close reference *can not* close issue
  360. // If the commiter doesn't have push rights in that repo
  361. pushCommits := []*PushCommit{
  362. {
  363. Sha1: "abcdef3",
  364. CommitterEmail: "user10@example.com",
  365. CommitterName: "User Ten",
  366. AuthorEmail: "user10@example.com",
  367. AuthorName: "User Ten",
  368. Message: "close user3/repo3#1",
  369. },
  370. }
  371. repo := AssertExistsAndLoadBean(t, &Repository{ID: 6}).(*Repository)
  372. commentBean := &Comment{
  373. Type: CommentTypeCommitRef,
  374. CommitSHA: "abcdef3",
  375. PosterID: user.ID,
  376. IssueID: 6,
  377. }
  378. issueBean := &Issue{RepoID: 3, Index: 1, ID: 6}
  379. AssertNotExistsBean(t, commentBean)
  380. AssertNotExistsBean(t, issueBean, "is_closed=1")
  381. assert.NoError(t, UpdateIssuesCommit(user, repo, pushCommits, repo.DefaultBranch))
  382. AssertExistsAndLoadBean(t, commentBean)
  383. AssertNotExistsBean(t, issueBean, "is_closed=1")
  384. CheckConsistencyFor(t, &Action{})
  385. }
  386. func TestTransferRepoAction(t *testing.T) {
  387. assert.NoError(t, PrepareTestDatabase())
  388. user2 := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
  389. user4 := AssertExistsAndLoadBean(t, &User{ID: 4}).(*User)
  390. repo := AssertExistsAndLoadBean(t, &Repository{ID: 1, OwnerID: user2.ID}).(*Repository)
  391. repo.OwnerID = user4.ID
  392. repo.Owner = user4
  393. actionBean := &Action{
  394. OpType: ActionTransferRepo,
  395. ActUserID: user2.ID,
  396. ActUser: user2,
  397. RepoID: repo.ID,
  398. Repo: repo,
  399. IsPrivate: repo.IsPrivate,
  400. }
  401. AssertNotExistsBean(t, actionBean)
  402. assert.NoError(t, TransferRepoAction(user2, user2, repo))
  403. AssertExistsAndLoadBean(t, actionBean)
  404. _, err := x.ID(repo.ID).Cols("owner_id").Update(repo)
  405. assert.NoError(t, err)
  406. CheckConsistencyFor(t, &Action{})
  407. }
  408. func TestMergePullRequestAction(t *testing.T) {
  409. assert.NoError(t, PrepareTestDatabase())
  410. user := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
  411. repo := AssertExistsAndLoadBean(t, &Repository{ID: 1, OwnerID: user.ID}).(*Repository)
  412. repo.Owner = user
  413. issue := AssertExistsAndLoadBean(t, &Issue{ID: 3, RepoID: repo.ID}).(*Issue)
  414. actionBean := &Action{
  415. OpType: ActionMergePullRequest,
  416. ActUserID: user.ID,
  417. ActUser: user,
  418. RepoID: repo.ID,
  419. Repo: repo,
  420. IsPrivate: repo.IsPrivate,
  421. }
  422. AssertNotExistsBean(t, actionBean)
  423. assert.NoError(t, MergePullRequestAction(user, repo, issue))
  424. AssertExistsAndLoadBean(t, actionBean)
  425. CheckConsistencyFor(t, &Action{})
  426. }
  427. func TestGetFeeds(t *testing.T) {
  428. // test with an individual user
  429. assert.NoError(t, PrepareTestDatabase())
  430. user := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
  431. actions, err := GetFeeds(GetFeedsOptions{
  432. RequestedUser: user,
  433. RequestingUserID: user.ID,
  434. IncludePrivate: true,
  435. OnlyPerformedBy: false,
  436. IncludeDeleted: true,
  437. })
  438. assert.NoError(t, err)
  439. if assert.Len(t, actions, 1) {
  440. assert.EqualValues(t, 1, actions[0].ID)
  441. assert.EqualValues(t, user.ID, actions[0].UserID)
  442. }
  443. actions, err = GetFeeds(GetFeedsOptions{
  444. RequestedUser: user,
  445. RequestingUserID: user.ID,
  446. IncludePrivate: false,
  447. OnlyPerformedBy: false,
  448. })
  449. assert.NoError(t, err)
  450. assert.Len(t, actions, 0)
  451. }
  452. func TestGetFeeds2(t *testing.T) {
  453. // test with an organization user
  454. assert.NoError(t, PrepareTestDatabase())
  455. org := AssertExistsAndLoadBean(t, &User{ID: 3}).(*User)
  456. const userID = 2 // user2 is an owner of the organization
  457. actions, err := GetFeeds(GetFeedsOptions{
  458. RequestedUser: org,
  459. RequestingUserID: userID,
  460. IncludePrivate: true,
  461. OnlyPerformedBy: false,
  462. IncludeDeleted: true,
  463. })
  464. assert.NoError(t, err)
  465. assert.Len(t, actions, 1)
  466. if assert.Len(t, actions, 1) {
  467. assert.EqualValues(t, 2, actions[0].ID)
  468. assert.EqualValues(t, org.ID, actions[0].UserID)
  469. }
  470. actions, err = GetFeeds(GetFeedsOptions{
  471. RequestedUser: org,
  472. RequestingUserID: userID,
  473. IncludePrivate: false,
  474. OnlyPerformedBy: false,
  475. IncludeDeleted: true,
  476. })
  477. assert.NoError(t, err)
  478. assert.Len(t, actions, 0)
  479. }