forked from NYANDEV/forgejo
8f9c9c63fb
Fix gitlab migration unit test
Closes #1837.
The differences in dates can be explained by commit e19b9653ea
, which
changed the order in which "created_date" and "updated_date" are
considered.
(cherry picked from commit b0bba20aa44e30ef0296b89f336d426224d73a16)
Mock HTTP requests in GitLab migration test
This introduces a new utility which can be added to other tests
making HTTP calls to a live service, to cache the responses of this
service in the repository.
(cherry picked from commit 52053b138948bd74c7eb88c0796c2e18f4247f3c)
Enable mocked HTTP responses for GitLab migration test
(cherry picked from commit 19cefc4de24b935a6a5c92be8360301f196f3aa5)
Simplify HTTP mocking utility in unit tests
Follow-up to https://codeberg.org/forgejo/forgejo/pulls/1841
(cherry picked from commit ca517c8bb4bf97f061b8b19fd3303d734f46660c)
(cherry picked from commit b227e0dd6bdf2dc3e8679443fc538fbce4b3bcf5)
(cherry picked from commit 6cc9d06556cda6c952a0542284fbe504114971ce)
(cherry picked from commit f0746e648dc30510d655b8a3b821199b2638800f)
(cherry picked from commit 414193341b8493723c16694789cbc08dc80b9ce5)
(cherry picked from commit 6e93df3bbb6c589502afc9dc74a7ae1a7c0f7da8)
(cherry picked from commit db0dbab5527c9f1783fd0eddb057c2d91cbb67e4)
533 lines
13 KiB
Go
533 lines
13 KiB
Go
// Copyright 2019 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package migrations
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"os"
|
|
"strconv"
|
|
"testing"
|
|
"time"
|
|
|
|
"code.gitea.io/gitea/models/unittest"
|
|
"code.gitea.io/gitea/modules/json"
|
|
base "code.gitea.io/gitea/modules/migration"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/xanzy/go-gitlab"
|
|
)
|
|
|
|
func TestGitlabDownloadRepo(t *testing.T) {
|
|
// If a GitLab access token is provided, this test will make HTTP requests to the live gitlab.com instance.
|
|
// When doing so, the responses from gitlab.com will be saved as test data files.
|
|
// If no access token is available, those cached responses will be used instead.
|
|
gitlabPersonalAccessToken := os.Getenv("GITLAB_READ_TOKEN")
|
|
fixturePath := "./testdata/gitlab/full_download"
|
|
server := unittest.NewMockWebServer(t, "https://gitlab.com", fixturePath, gitlabPersonalAccessToken != "")
|
|
defer server.Close()
|
|
|
|
downloader, err := NewGitlabDownloader(context.Background(), server.URL, "gitea/test_repo", "", "", gitlabPersonalAccessToken)
|
|
if err != nil {
|
|
t.Fatalf("NewGitlabDownloader is nil: %v", err)
|
|
}
|
|
repo, err := downloader.GetRepoInfo()
|
|
assert.NoError(t, err)
|
|
// Repo Owner is blank in Gitlab Group repos
|
|
assertRepositoryEqual(t, &base.Repository{
|
|
Name: "test_repo",
|
|
Owner: "",
|
|
Description: "Test repository for testing migration from gitlab to gitea",
|
|
CloneURL: server.URL + "/gitea/test_repo.git",
|
|
OriginalURL: server.URL + "/gitea/test_repo",
|
|
DefaultBranch: "master",
|
|
}, repo)
|
|
|
|
topics, err := downloader.GetTopics()
|
|
assert.NoError(t, err)
|
|
assert.True(t, len(topics) == 2)
|
|
assert.EqualValues(t, []string{"migration", "test"}, topics)
|
|
|
|
milestones, err := downloader.GetMilestones()
|
|
assert.NoError(t, err)
|
|
assertMilestonesEqual(t, []*base.Milestone{
|
|
{
|
|
Title: "1.1.0",
|
|
Created: time.Date(2019, 11, 28, 8, 42, 44, 575000000, time.UTC),
|
|
Updated: timePtr(time.Date(2019, 11, 28, 8, 42, 44, 575000000, time.UTC)),
|
|
State: "active",
|
|
},
|
|
{
|
|
Title: "1.0.0",
|
|
Created: time.Date(2019, 11, 28, 8, 42, 30, 301000000, time.UTC),
|
|
Updated: timePtr(time.Date(2019, 11, 28, 15, 57, 52, 401000000, time.UTC)),
|
|
Closed: timePtr(time.Date(2019, 11, 28, 15, 57, 52, 401000000, time.UTC)),
|
|
State: "closed",
|
|
},
|
|
}, milestones)
|
|
|
|
labels, err := downloader.GetLabels()
|
|
assert.NoError(t, err)
|
|
assertLabelsEqual(t, []*base.Label{
|
|
{
|
|
Name: "bug",
|
|
Color: "d9534f",
|
|
},
|
|
{
|
|
Name: "confirmed",
|
|
Color: "d9534f",
|
|
},
|
|
{
|
|
Name: "critical",
|
|
Color: "d9534f",
|
|
},
|
|
{
|
|
Name: "discussion",
|
|
Color: "428bca",
|
|
},
|
|
{
|
|
Name: "documentation",
|
|
Color: "f0ad4e",
|
|
},
|
|
{
|
|
Name: "duplicate",
|
|
Color: "7f8c8d",
|
|
},
|
|
{
|
|
Name: "enhancement",
|
|
Color: "5cb85c",
|
|
},
|
|
{
|
|
Name: "suggestion",
|
|
Color: "428bca",
|
|
},
|
|
{
|
|
Name: "support",
|
|
Color: "f0ad4e",
|
|
},
|
|
}, labels)
|
|
|
|
releases, err := downloader.GetReleases()
|
|
assert.NoError(t, err)
|
|
assertReleasesEqual(t, []*base.Release{
|
|
{
|
|
TagName: "v0.9.99",
|
|
TargetCommitish: "0720a3ec57c1f843568298117b874319e7deee75",
|
|
Name: "First Release",
|
|
Body: "A test release",
|
|
Created: time.Date(2019, 11, 28, 9, 9, 48, 840000000, time.UTC),
|
|
PublisherID: 1241334,
|
|
PublisherName: "lafriks",
|
|
},
|
|
}, releases)
|
|
|
|
issues, isEnd, err := downloader.GetIssues(1, 2)
|
|
assert.NoError(t, err)
|
|
assert.False(t, isEnd)
|
|
|
|
assertIssuesEqual(t, []*base.Issue{
|
|
{
|
|
Number: 1,
|
|
Title: "Please add an animated gif icon to the merge button",
|
|
Content: "I just want the merge button to hurt my eyes a little. :stuck_out_tongue_closed_eyes:",
|
|
Milestone: "1.0.0",
|
|
PosterID: 1241334,
|
|
PosterName: "lafriks",
|
|
State: "closed",
|
|
Created: time.Date(2019, 11, 28, 8, 43, 35, 459000000, time.UTC),
|
|
Updated: time.Date(2019, 11, 28, 8, 46, 23, 304000000, time.UTC),
|
|
Labels: []*base.Label{
|
|
{
|
|
Name: "bug",
|
|
},
|
|
{
|
|
Name: "discussion",
|
|
},
|
|
},
|
|
Reactions: []*base.Reaction{
|
|
{
|
|
UserID: 1241334,
|
|
UserName: "lafriks",
|
|
Content: "thumbsup",
|
|
},
|
|
{
|
|
UserID: 1241334,
|
|
UserName: "lafriks",
|
|
Content: "open_mouth",
|
|
},
|
|
},
|
|
Closed: timePtr(time.Date(2019, 11, 28, 8, 46, 23, 275000000, time.UTC)),
|
|
},
|
|
{
|
|
Number: 2,
|
|
Title: "Test issue",
|
|
Content: "This is test issue 2, do not touch!",
|
|
Milestone: "1.1.0",
|
|
PosterID: 1241334,
|
|
PosterName: "lafriks",
|
|
State: "closed",
|
|
Created: time.Date(2019, 11, 28, 8, 44, 46, 277000000, time.UTC),
|
|
Updated: time.Date(2019, 11, 28, 8, 45, 44, 987000000, time.UTC),
|
|
Labels: []*base.Label{
|
|
{
|
|
Name: "duplicate",
|
|
},
|
|
},
|
|
Reactions: []*base.Reaction{
|
|
{
|
|
UserID: 1241334,
|
|
UserName: "lafriks",
|
|
Content: "thumbsup",
|
|
},
|
|
{
|
|
UserID: 1241334,
|
|
UserName: "lafriks",
|
|
Content: "thumbsdown",
|
|
},
|
|
{
|
|
UserID: 1241334,
|
|
UserName: "lafriks",
|
|
Content: "laughing",
|
|
},
|
|
{
|
|
UserID: 1241334,
|
|
UserName: "lafriks",
|
|
Content: "tada",
|
|
},
|
|
{
|
|
UserID: 1241334,
|
|
UserName: "lafriks",
|
|
Content: "confused",
|
|
},
|
|
{
|
|
UserID: 1241334,
|
|
UserName: "lafriks",
|
|
Content: "hearts",
|
|
},
|
|
},
|
|
Closed: timePtr(time.Date(2019, 11, 28, 8, 45, 44, 959000000, time.UTC)),
|
|
},
|
|
}, issues)
|
|
|
|
comments, _, err := downloader.GetComments(&base.Issue{
|
|
Number: 2,
|
|
ForeignIndex: 2,
|
|
Context: gitlabIssueContext{IsMergeRequest: false},
|
|
})
|
|
assert.NoError(t, err)
|
|
assertCommentsEqual(t, []*base.Comment{
|
|
{
|
|
IssueIndex: 2,
|
|
PosterID: 1241334,
|
|
PosterName: "lafriks",
|
|
Created: time.Date(2019, 11, 28, 8, 44, 52, 501000000, time.UTC),
|
|
Content: "This is a comment",
|
|
Reactions: nil,
|
|
},
|
|
{
|
|
IssueIndex: 2,
|
|
PosterID: 1241334,
|
|
PosterName: "lafriks",
|
|
Created: time.Date(2019, 11, 28, 8, 45, 2, 329000000, time.UTC),
|
|
Content: "changed milestone to %2",
|
|
Reactions: nil,
|
|
},
|
|
{
|
|
IssueIndex: 2,
|
|
PosterID: 1241334,
|
|
PosterName: "lafriks",
|
|
Created: time.Date(2019, 11, 28, 8, 45, 45, 7000000, time.UTC),
|
|
Content: "closed",
|
|
Reactions: nil,
|
|
},
|
|
{
|
|
IssueIndex: 2,
|
|
PosterID: 1241334,
|
|
PosterName: "lafriks",
|
|
Created: time.Date(2019, 11, 28, 8, 45, 53, 501000000, time.UTC),
|
|
Content: "A second comment",
|
|
Reactions: nil,
|
|
},
|
|
}, comments)
|
|
|
|
prs, _, err := downloader.GetPullRequests(1, 1)
|
|
assert.NoError(t, err)
|
|
assertPullRequestsEqual(t, []*base.PullRequest{
|
|
{
|
|
Number: 4,
|
|
Title: "Test branch",
|
|
Content: "do not merge this PR",
|
|
Milestone: "1.0.0",
|
|
PosterID: 1241334,
|
|
PosterName: "lafriks",
|
|
State: "opened",
|
|
Created: time.Date(2019, 11, 28, 15, 56, 54, 104000000, time.UTC),
|
|
Labels: []*base.Label{
|
|
{
|
|
Name: "bug",
|
|
},
|
|
},
|
|
Reactions: []*base.Reaction{{
|
|
UserID: 4575606,
|
|
UserName: "real6543",
|
|
Content: "thumbsup",
|
|
}, {
|
|
UserID: 4575606,
|
|
UserName: "real6543",
|
|
Content: "tada",
|
|
}},
|
|
PatchURL: server.URL + "/gitea/test_repo/-/merge_requests/2.patch",
|
|
Head: base.PullRequestBranch{
|
|
Ref: "feat/test",
|
|
CloneURL: server.URL + "/gitea/test_repo/-/merge_requests/2",
|
|
SHA: "9f733b96b98a4175276edf6a2e1231489c3bdd23",
|
|
RepoName: "test_repo",
|
|
OwnerName: "lafriks",
|
|
},
|
|
Base: base.PullRequestBranch{
|
|
Ref: "master",
|
|
SHA: "c59c9b451acca9d106cc19d61d87afe3fbbb8b83",
|
|
OwnerName: "lafriks",
|
|
RepoName: "test_repo",
|
|
},
|
|
Closed: nil,
|
|
Merged: false,
|
|
MergedTime: nil,
|
|
MergeCommitSHA: "",
|
|
ForeignIndex: 2,
|
|
Context: gitlabIssueContext{IsMergeRequest: true},
|
|
},
|
|
}, prs)
|
|
|
|
rvs, err := downloader.GetReviews(&base.PullRequest{Number: 1, ForeignIndex: 1})
|
|
assert.NoError(t, err)
|
|
assertReviewsEqual(t, []*base.Review{
|
|
{
|
|
IssueIndex: 1,
|
|
ReviewerID: 527793,
|
|
ReviewerName: "axifive",
|
|
CreatedAt: time.Date(2019, 11, 28, 8, 54, 41, 34000000, time.UTC),
|
|
State: "APPROVED",
|
|
},
|
|
{
|
|
IssueIndex: 1,
|
|
ReviewerID: 4102996,
|
|
ReviewerName: "zeripath",
|
|
CreatedAt: time.Date(2019, 11, 28, 8, 54, 41, 34000000, time.UTC),
|
|
State: "APPROVED",
|
|
},
|
|
}, rvs)
|
|
|
|
rvs, err = downloader.GetReviews(&base.PullRequest{Number: 2, ForeignIndex: 2})
|
|
assert.NoError(t, err)
|
|
assertReviewsEqual(t, []*base.Review{
|
|
{
|
|
IssueIndex: 2,
|
|
ReviewerID: 4575606,
|
|
ReviewerName: "real6543",
|
|
CreatedAt: time.Date(2019, 11, 28, 15, 56, 54, 108000000, time.UTC),
|
|
State: "APPROVED",
|
|
},
|
|
}, rvs)
|
|
}
|
|
|
|
func gitlabClientMockSetup(t *testing.T) (*http.ServeMux, *httptest.Server, *gitlab.Client) {
|
|
// mux is the HTTP request multiplexer used with the test server.
|
|
mux := http.NewServeMux()
|
|
|
|
// server is a test HTTP server used to provide mock API responses.
|
|
server := httptest.NewServer(mux)
|
|
|
|
// client is the Gitlab client being tested.
|
|
client, err := gitlab.NewClient("", gitlab.WithBaseURL(server.URL))
|
|
if err != nil {
|
|
server.Close()
|
|
t.Fatalf("Failed to create client: %v", err)
|
|
}
|
|
|
|
return mux, server, client
|
|
}
|
|
|
|
func gitlabClientMockTeardown(server *httptest.Server) {
|
|
server.Close()
|
|
}
|
|
|
|
type reviewTestCase struct {
|
|
repoID, prID, reviewerID int
|
|
reviewerName string
|
|
createdAt, updatedAt *time.Time
|
|
expectedCreatedAt time.Time
|
|
}
|
|
|
|
func convertTestCase(t reviewTestCase) (func(w http.ResponseWriter, r *http.Request), base.Review) {
|
|
var updatedAtField string
|
|
if t.updatedAt == nil {
|
|
updatedAtField = ""
|
|
} else {
|
|
updatedAtField = `"updated_at": "` + t.updatedAt.Format(time.RFC3339) + `",`
|
|
}
|
|
|
|
var createdAtField string
|
|
if t.createdAt == nil {
|
|
createdAtField = ""
|
|
} else {
|
|
createdAtField = `"created_at": "` + t.createdAt.Format(time.RFC3339) + `",`
|
|
}
|
|
|
|
handler := func(w http.ResponseWriter, r *http.Request) {
|
|
fmt.Fprint(w, `
|
|
{
|
|
"id": 5,
|
|
"iid": `+strconv.Itoa(t.prID)+`,
|
|
"project_id": `+strconv.Itoa(t.repoID)+`,
|
|
"title": "Approvals API",
|
|
"description": "Test",
|
|
"state": "opened",
|
|
`+createdAtField+`
|
|
`+updatedAtField+`
|
|
"merge_status": "cannot_be_merged",
|
|
"approvals_required": 2,
|
|
"approvals_left": 1,
|
|
"approved_by": [
|
|
{
|
|
"user": {
|
|
"name": "Administrator",
|
|
"username": "`+t.reviewerName+`",
|
|
"id": `+strconv.Itoa(t.reviewerID)+`,
|
|
"state": "active",
|
|
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon",
|
|
"web_url": "http://localhost:3000/root"
|
|
}
|
|
}
|
|
]
|
|
}`)
|
|
}
|
|
review := base.Review{
|
|
IssueIndex: int64(t.prID),
|
|
ReviewerID: int64(t.reviewerID),
|
|
ReviewerName: t.reviewerName,
|
|
CreatedAt: t.expectedCreatedAt,
|
|
State: "APPROVED",
|
|
}
|
|
|
|
return handler, review
|
|
}
|
|
|
|
func TestGitlabGetReviews(t *testing.T) {
|
|
mux, server, client := gitlabClientMockSetup(t)
|
|
defer gitlabClientMockTeardown(server)
|
|
|
|
repoID := 1324
|
|
|
|
downloader := &GitlabDownloader{
|
|
ctx: context.Background(),
|
|
client: client,
|
|
repoID: repoID,
|
|
}
|
|
|
|
createdAt := time.Date(2020, 4, 19, 19, 24, 21, 0, time.UTC)
|
|
|
|
for _, testCase := range []reviewTestCase{
|
|
{
|
|
repoID: repoID,
|
|
prID: 1,
|
|
reviewerID: 801,
|
|
reviewerName: "someone1",
|
|
createdAt: nil,
|
|
updatedAt: &createdAt,
|
|
expectedCreatedAt: createdAt,
|
|
},
|
|
{
|
|
repoID: repoID,
|
|
prID: 2,
|
|
reviewerID: 802,
|
|
reviewerName: "someone2",
|
|
createdAt: &createdAt,
|
|
updatedAt: nil,
|
|
expectedCreatedAt: createdAt,
|
|
},
|
|
{
|
|
repoID: repoID,
|
|
prID: 3,
|
|
reviewerID: 803,
|
|
reviewerName: "someone3",
|
|
createdAt: nil,
|
|
updatedAt: nil,
|
|
expectedCreatedAt: time.Now(),
|
|
},
|
|
} {
|
|
mock, review := convertTestCase(testCase)
|
|
mux.HandleFunc(fmt.Sprintf("/api/v4/projects/%d/merge_requests/%d/approvals", testCase.repoID, testCase.prID), mock)
|
|
|
|
id := int64(testCase.prID)
|
|
rvs, err := downloader.GetReviews(&base.Issue{Number: id, ForeignIndex: id})
|
|
assert.NoError(t, err)
|
|
assertReviewsEqual(t, []*base.Review{&review}, rvs)
|
|
}
|
|
}
|
|
|
|
func TestAwardsToReactions(t *testing.T) {
|
|
downloader := &GitlabDownloader{}
|
|
// yes gitlab can have duplicated reactions (https://gitlab.com/jaywink/socialhome/-/issues/24)
|
|
testResponse := `
|
|
[
|
|
{
|
|
"name": "thumbsup",
|
|
"user": {
|
|
"id": 1241334,
|
|
"username": "lafriks"
|
|
}
|
|
},
|
|
{
|
|
"name": "thumbsup",
|
|
"user": {
|
|
"id": 1241334,
|
|
"username": "lafriks"
|
|
}
|
|
},
|
|
{
|
|
"name": "thumbsup",
|
|
"user": {
|
|
"id": 4575606,
|
|
"username": "real6543"
|
|
}
|
|
}
|
|
]
|
|
`
|
|
var awards []*gitlab.AwardEmoji
|
|
assert.NoError(t, json.Unmarshal([]byte(testResponse), &awards))
|
|
|
|
reactions := downloader.awardsToReactions(awards)
|
|
assert.EqualValues(t, []*base.Reaction{
|
|
{
|
|
UserName: "lafriks",
|
|
UserID: 1241334,
|
|
Content: "thumbsup",
|
|
},
|
|
{
|
|
UserName: "real6543",
|
|
UserID: 4575606,
|
|
Content: "thumbsup",
|
|
},
|
|
}, reactions)
|
|
}
|
|
|
|
func TestGitlabIIDResolver(t *testing.T) {
|
|
r := gitlabIIDResolver{}
|
|
r.recordIssueIID(1)
|
|
r.recordIssueIID(2)
|
|
r.recordIssueIID(3)
|
|
r.recordIssueIID(2)
|
|
assert.EqualValues(t, 4, r.generatePullRequestNumber(1))
|
|
assert.EqualValues(t, 13, r.generatePullRequestNumber(10))
|
|
|
|
assert.Panics(t, func() {
|
|
r := gitlabIIDResolver{}
|
|
r.recordIssueIID(1)
|
|
assert.EqualValues(t, 2, r.generatePullRequestNumber(1))
|
|
r.recordIssueIID(3) // the generation procedure has been started, it shouldn't accept any new issue IID, so it panics
|
|
})
|
|
}
|