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.

585 lines
17 KiB

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