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.

gitlab_test.go 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. // Copyright 2019 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package migrations
  5. import (
  6. "context"
  7. "fmt"
  8. "net/http"
  9. "net/http/httptest"
  10. "os"
  11. "strconv"
  12. "testing"
  13. "time"
  14. base "code.gitea.io/gitea/modules/migration"
  15. "github.com/stretchr/testify/assert"
  16. "github.com/xanzy/go-gitlab"
  17. )
  18. func TestGitlabDownloadRepo(t *testing.T) {
  19. // Skip tests if Gitlab token is not found
  20. gitlabPersonalAccessToken := os.Getenv("GITLAB_READ_TOKEN")
  21. if gitlabPersonalAccessToken == "" {
  22. t.Skip("skipped test because GITLAB_READ_TOKEN was not in the environment")
  23. }
  24. resp, err := http.Get("https://gitlab.com/gitea/test_repo")
  25. if err != nil || resp.StatusCode != http.StatusOK {
  26. t.Skipf("Can't access test repo, skipping %s", t.Name())
  27. }
  28. downloader, err := NewGitlabDownloader(context.Background(), "https://gitlab.com", "gitea/test_repo", "", "", gitlabPersonalAccessToken)
  29. if err != nil {
  30. t.Fatalf("NewGitlabDownloader is nil: %v", err)
  31. }
  32. repo, err := downloader.GetRepoInfo()
  33. assert.NoError(t, err)
  34. // Repo Owner is blank in Gitlab Group repos
  35. assertRepositoryEqual(t, &base.Repository{
  36. Name: "test_repo",
  37. Owner: "",
  38. Description: "Test repository for testing migration from gitlab to gitea",
  39. CloneURL: "https://gitlab.com/gitea/test_repo.git",
  40. OriginalURL: "https://gitlab.com/gitea/test_repo",
  41. DefaultBranch: "master",
  42. }, repo)
  43. topics, err := downloader.GetTopics()
  44. assert.NoError(t, err)
  45. assert.True(t, len(topics) == 2)
  46. assert.EqualValues(t, []string{"migration", "test"}, topics)
  47. milestones, err := downloader.GetMilestones()
  48. assert.NoError(t, err)
  49. assertMilestonesEqual(t, []*base.Milestone{
  50. {
  51. Title: "1.1.0",
  52. Created: time.Date(2019, 11, 28, 8, 42, 44, 575000000, time.UTC),
  53. Updated: timePtr(time.Date(2019, 11, 28, 8, 42, 44, 575000000, time.UTC)),
  54. State: "active",
  55. },
  56. {
  57. Title: "1.0.0",
  58. Created: time.Date(2019, 11, 28, 8, 42, 30, 301000000, time.UTC),
  59. Updated: timePtr(time.Date(2019, 11, 28, 15, 57, 52, 401000000, time.UTC)),
  60. Closed: timePtr(time.Date(2019, 11, 28, 15, 57, 52, 401000000, time.UTC)),
  61. State: "closed",
  62. },
  63. }, milestones)
  64. labels, err := downloader.GetLabels()
  65. assert.NoError(t, err)
  66. assertLabelsEqual(t, []*base.Label{
  67. {
  68. Name: "bug",
  69. Color: "d9534f",
  70. },
  71. {
  72. Name: "confirmed",
  73. Color: "d9534f",
  74. },
  75. {
  76. Name: "critical",
  77. Color: "d9534f",
  78. },
  79. {
  80. Name: "discussion",
  81. Color: "428bca",
  82. },
  83. {
  84. Name: "documentation",
  85. Color: "f0ad4e",
  86. },
  87. {
  88. Name: "duplicate",
  89. Color: "7f8c8d",
  90. },
  91. {
  92. Name: "enhancement",
  93. Color: "5cb85c",
  94. },
  95. {
  96. Name: "suggestion",
  97. Color: "428bca",
  98. },
  99. {
  100. Name: "support",
  101. Color: "f0ad4e",
  102. },
  103. }, labels)
  104. releases, err := downloader.GetReleases()
  105. assert.NoError(t, err)
  106. assertReleasesEqual(t, []*base.Release{
  107. {
  108. TagName: "v0.9.99",
  109. TargetCommitish: "0720a3ec57c1f843568298117b874319e7deee75",
  110. Name: "First Release",
  111. Body: "A test release",
  112. Created: time.Date(2019, 11, 28, 9, 9, 48, 840000000, time.UTC),
  113. PublisherID: 1241334,
  114. PublisherName: "lafriks",
  115. },
  116. }, releases)
  117. issues, isEnd, err := downloader.GetIssues(1, 2)
  118. assert.NoError(t, err)
  119. assert.False(t, isEnd)
  120. assertIssuesEqual(t, []*base.Issue{
  121. {
  122. Number: 1,
  123. Title: "Please add an animated gif icon to the merge button",
  124. Content: "I just want the merge button to hurt my eyes a little. :stuck_out_tongue_closed_eyes:",
  125. Milestone: "1.0.0",
  126. PosterID: 1241334,
  127. PosterName: "lafriks",
  128. State: "closed",
  129. Created: time.Date(2019, 11, 28, 8, 43, 35, 459000000, time.UTC),
  130. Updated: time.Date(2019, 11, 28, 8, 46, 23, 304000000, time.UTC),
  131. Labels: []*base.Label{
  132. {
  133. Name: "bug",
  134. },
  135. {
  136. Name: "discussion",
  137. },
  138. },
  139. Reactions: []*base.Reaction{
  140. {
  141. UserID: 1241334,
  142. UserName: "lafriks",
  143. Content: "thumbsup",
  144. },
  145. {
  146. UserID: 1241334,
  147. UserName: "lafriks",
  148. Content: "open_mouth",
  149. },
  150. },
  151. Closed: timePtr(time.Date(2019, 11, 28, 8, 46, 23, 275000000, time.UTC)),
  152. },
  153. {
  154. Number: 2,
  155. Title: "Test issue",
  156. Content: "This is test issue 2, do not touch!",
  157. Milestone: "1.1.0",
  158. PosterID: 1241334,
  159. PosterName: "lafriks",
  160. State: "closed",
  161. Created: time.Date(2019, 11, 28, 8, 44, 46, 277000000, time.UTC),
  162. Updated: time.Date(2019, 11, 28, 8, 45, 44, 987000000, time.UTC),
  163. Labels: []*base.Label{
  164. {
  165. Name: "duplicate",
  166. },
  167. },
  168. Reactions: []*base.Reaction{
  169. {
  170. UserID: 1241334,
  171. UserName: "lafriks",
  172. Content: "thumbsup",
  173. },
  174. {
  175. UserID: 1241334,
  176. UserName: "lafriks",
  177. Content: "thumbsdown",
  178. },
  179. {
  180. UserID: 1241334,
  181. UserName: "lafriks",
  182. Content: "laughing",
  183. },
  184. {
  185. UserID: 1241334,
  186. UserName: "lafriks",
  187. Content: "tada",
  188. },
  189. {
  190. UserID: 1241334,
  191. UserName: "lafriks",
  192. Content: "confused",
  193. },
  194. {
  195. UserID: 1241334,
  196. UserName: "lafriks",
  197. Content: "hearts",
  198. },
  199. },
  200. Closed: timePtr(time.Date(2019, 11, 28, 8, 45, 44, 959000000, time.UTC)),
  201. },
  202. }, issues)
  203. comments, _, err := downloader.GetComments(&base.Issue{
  204. Number: 2,
  205. ForeignIndex: 2,
  206. Context: gitlabIssueContext{IsMergeRequest: false},
  207. })
  208. assert.NoError(t, err)
  209. assertCommentsEqual(t, []*base.Comment{
  210. {
  211. IssueIndex: 2,
  212. PosterID: 1241334,
  213. PosterName: "lafriks",
  214. Created: time.Date(2019, 11, 28, 8, 44, 52, 501000000, time.UTC),
  215. Content: "This is a comment",
  216. Reactions: nil,
  217. },
  218. {
  219. IssueIndex: 2,
  220. PosterID: 1241334,
  221. PosterName: "lafriks",
  222. Created: time.Date(2019, 11, 28, 8, 45, 2, 329000000, time.UTC),
  223. Content: "changed milestone to %2",
  224. Reactions: nil,
  225. },
  226. {
  227. IssueIndex: 2,
  228. PosterID: 1241334,
  229. PosterName: "lafriks",
  230. Created: time.Date(2019, 11, 28, 8, 45, 45, 7000000, time.UTC),
  231. Content: "closed",
  232. Reactions: nil,
  233. },
  234. {
  235. IssueIndex: 2,
  236. PosterID: 1241334,
  237. PosterName: "lafriks",
  238. Created: time.Date(2019, 11, 28, 8, 45, 53, 501000000, time.UTC),
  239. Content: "A second comment",
  240. Reactions: nil,
  241. },
  242. }, comments)
  243. prs, _, err := downloader.GetPullRequests(1, 1)
  244. assert.NoError(t, err)
  245. assertPullRequestsEqual(t, []*base.PullRequest{
  246. {
  247. Number: 4,
  248. Title: "Test branch",
  249. Content: "do not merge this PR",
  250. Milestone: "1.0.0",
  251. PosterID: 1241334,
  252. PosterName: "lafriks",
  253. State: "opened",
  254. Created: time.Date(2019, 11, 28, 15, 56, 54, 104000000, time.UTC),
  255. Labels: []*base.Label{
  256. {
  257. Name: "bug",
  258. },
  259. },
  260. Reactions: []*base.Reaction{{
  261. UserID: 4575606,
  262. UserName: "real6543",
  263. Content: "thumbsup",
  264. }, {
  265. UserID: 4575606,
  266. UserName: "real6543",
  267. Content: "tada",
  268. }},
  269. PatchURL: "https://gitlab.com/gitea/test_repo/-/merge_requests/2.patch",
  270. Head: base.PullRequestBranch{
  271. Ref: "feat/test",
  272. CloneURL: "https://gitlab.com/gitea/test_repo/-/merge_requests/2",
  273. SHA: "9f733b96b98a4175276edf6a2e1231489c3bdd23",
  274. RepoName: "test_repo",
  275. OwnerName: "lafriks",
  276. },
  277. Base: base.PullRequestBranch{
  278. Ref: "master",
  279. SHA: "",
  280. OwnerName: "lafriks",
  281. RepoName: "test_repo",
  282. },
  283. Closed: nil,
  284. Merged: false,
  285. MergedTime: nil,
  286. MergeCommitSHA: "",
  287. ForeignIndex: 2,
  288. Context: gitlabIssueContext{IsMergeRequest: true},
  289. },
  290. }, prs)
  291. rvs, err := downloader.GetReviews(&base.PullRequest{Number: 1, ForeignIndex: 1})
  292. assert.NoError(t, err)
  293. assertReviewsEqual(t, []*base.Review{
  294. {
  295. IssueIndex: 1,
  296. ReviewerID: 4102996,
  297. ReviewerName: "zeripath",
  298. CreatedAt: time.Date(2019, 11, 28, 16, 2, 8, 377000000, time.UTC),
  299. State: "APPROVED",
  300. },
  301. {
  302. IssueIndex: 1,
  303. ReviewerID: 527793,
  304. ReviewerName: "axifive",
  305. CreatedAt: time.Date(2019, 11, 28, 16, 2, 8, 377000000, time.UTC),
  306. State: "APPROVED",
  307. },
  308. }, rvs)
  309. rvs, err = downloader.GetReviews(&base.PullRequest{Number: 2, ForeignIndex: 2})
  310. assert.NoError(t, err)
  311. assertReviewsEqual(t, []*base.Review{
  312. {
  313. IssueIndex: 2,
  314. ReviewerID: 4575606,
  315. ReviewerName: "real6543",
  316. CreatedAt: time.Date(2020, 4, 19, 19, 24, 21, 108000000, time.UTC),
  317. State: "APPROVED",
  318. },
  319. }, rvs)
  320. }
  321. func gitlabClientMockSetup(t *testing.T) (*http.ServeMux, *httptest.Server, *gitlab.Client) {
  322. // mux is the HTTP request multiplexer used with the test server.
  323. mux := http.NewServeMux()
  324. // server is a test HTTP server used to provide mock API responses.
  325. server := httptest.NewServer(mux)
  326. // client is the Gitlab client being tested.
  327. client, err := gitlab.NewClient("", gitlab.WithBaseURL(server.URL))
  328. if err != nil {
  329. server.Close()
  330. t.Fatalf("Failed to create client: %v", err)
  331. }
  332. return mux, server, client
  333. }
  334. func gitlabClientMockTeardown(server *httptest.Server) {
  335. server.Close()
  336. }
  337. type reviewTestCase struct {
  338. repoID, prID, reviewerID int
  339. reviewerName string
  340. createdAt, updatedAt *time.Time
  341. expectedCreatedAt time.Time
  342. }
  343. func convertTestCase(t reviewTestCase) (func(w http.ResponseWriter, r *http.Request), base.Review) {
  344. var updatedAtField string
  345. if t.updatedAt == nil {
  346. updatedAtField = ""
  347. } else {
  348. updatedAtField = `"updated_at": "` + t.updatedAt.Format(time.RFC3339) + `",`
  349. }
  350. var createdAtField string
  351. if t.createdAt == nil {
  352. createdAtField = ""
  353. } else {
  354. createdAtField = `"created_at": "` + t.createdAt.Format(time.RFC3339) + `",`
  355. }
  356. handler := func(w http.ResponseWriter, r *http.Request) {
  357. fmt.Fprint(w, `
  358. {
  359. "id": 5,
  360. "iid": `+strconv.Itoa(t.prID)+`,
  361. "project_id": `+strconv.Itoa(t.repoID)+`,
  362. "title": "Approvals API",
  363. "description": "Test",
  364. "state": "opened",
  365. `+createdAtField+`
  366. `+updatedAtField+`
  367. "merge_status": "cannot_be_merged",
  368. "approvals_required": 2,
  369. "approvals_left": 1,
  370. "approved_by": [
  371. {
  372. "user": {
  373. "name": "Administrator",
  374. "username": "`+t.reviewerName+`",
  375. "id": `+strconv.Itoa(t.reviewerID)+`,
  376. "state": "active",
  377. "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon",
  378. "web_url": "http://localhost:3000/root"
  379. }
  380. }
  381. ]
  382. }`)
  383. }
  384. review := base.Review{
  385. IssueIndex: int64(t.prID),
  386. ReviewerID: int64(t.reviewerID),
  387. ReviewerName: t.reviewerName,
  388. CreatedAt: t.expectedCreatedAt,
  389. State: "APPROVED",
  390. }
  391. return handler, review
  392. }
  393. func TestGitlabGetReviews(t *testing.T) {
  394. mux, server, client := gitlabClientMockSetup(t)
  395. defer gitlabClientMockTeardown(server)
  396. repoID := 1324
  397. downloader := &GitlabDownloader{
  398. ctx: context.Background(),
  399. client: client,
  400. repoID: repoID,
  401. }
  402. createdAt := time.Date(2020, 4, 19, 19, 24, 21, 0, time.UTC)
  403. for _, testCase := range []reviewTestCase{
  404. {
  405. repoID: repoID,
  406. prID: 1,
  407. reviewerID: 801,
  408. reviewerName: "someone1",
  409. createdAt: nil,
  410. updatedAt: &createdAt,
  411. expectedCreatedAt: createdAt,
  412. },
  413. {
  414. repoID: repoID,
  415. prID: 2,
  416. reviewerID: 802,
  417. reviewerName: "someone2",
  418. createdAt: &createdAt,
  419. updatedAt: nil,
  420. expectedCreatedAt: createdAt,
  421. },
  422. {
  423. repoID: repoID,
  424. prID: 3,
  425. reviewerID: 803,
  426. reviewerName: "someone3",
  427. createdAt: nil,
  428. updatedAt: nil,
  429. expectedCreatedAt: time.Now(),
  430. },
  431. } {
  432. mock, review := convertTestCase(testCase)
  433. mux.HandleFunc(fmt.Sprintf("/api/v4/projects/%d/merge_requests/%d/approvals", testCase.repoID, testCase.prID), mock)
  434. id := int64(testCase.prID)
  435. rvs, err := downloader.GetReviews(&base.Issue{Number: id, ForeignIndex: id})
  436. assert.NoError(t, err)
  437. assertReviewsEqual(t, []*base.Review{&review}, rvs)
  438. }
  439. }