jojo/services/migrations/gitea_downloader_test.go
Gusted d6f7e154a1 fix: Use mock server for TestBreakConditions (#9948)
- Follow up of forgejo/forgejo!9274
- The test does not call to Gitea for fetching comments, but when initializing the Gitea client it does check the API version and some settings. Mock these responses so this test can be run without a network connection.
- Resolves forgejo/forgejo#9928

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/9948
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: Gusted <postmaster@gusted.xyz>
Co-committed-by: Gusted <postmaster@gusted.xyz>
2025-11-03 09:33:51 +01:00

456 lines
14 KiB
Go

// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package migrations
import (
"os"
"sort"
"strconv"
"testing"
"time"
"forgejo.org/models/unittest"
base "forgejo.org/modules/migration"
gitea_sdk "code.gitea.io/sdk/gitea"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestGiteaDownloadRepo(t *testing.T) {
giteaToken := os.Getenv("GITEA_TOKEN")
fixturePath := "./testdata/gitea/full_download"
server := unittest.NewMockWebServer(t, "https://gitea.com", fixturePath, giteaToken != "")
defer server.Close()
giteaClient, err := gitea_sdk.NewClient(
server.URL,
gitea_sdk.SetToken(giteaToken),
gitea_sdk.SetBasicAuth("", ""),
gitea_sdk.SetContext(t.Context()),
gitea_sdk.SetHTTPClient(NewMigrationHTTPClient()),
)
require.NoError(t, err, "Clould not create Client")
downloader, err := NewGiteaDownloader(t.Context(), giteaClient, server.URL, "gitea/test_repo")
if downloader == nil {
t.Fatal("NewGitlabDownloader is nil")
}
require.NoError(t, err, "NewGitlabDownloader error occur")
repo, err := downloader.GetRepoInfo()
require.NoError(t, err)
assertRepositoryEqual(t, &base.Repository{
Name: "test_repo",
Owner: "gitea",
IsPrivate: false,
Description: "Test repository for testing migration from gitea to gitea",
CloneURL: server.URL + "/gitea/test_repo.git",
OriginalURL: server.URL + "/gitea/test_repo",
DefaultBranch: "master",
Website: "https://codeberg.org/forgejo/forgejo/",
}, repo)
topics, err := downloader.GetTopics()
require.NoError(t, err)
sort.Strings(topics)
assert.Equal(t, []string{"ci", "gitea", "migration", "test"}, topics)
labels, err := downloader.GetLabels()
require.NoError(t, err)
assertLabelsEqual(t, []*base.Label{
{
Name: "Bug",
Color: "e11d21",
},
{
Name: "Enhancement",
Color: "207de5",
},
{
Name: "Feature",
Color: "0052cc",
Description: "a feature request",
},
{
Name: "Invalid",
Color: "d4c5f9",
},
{
Name: "Question",
Color: "fbca04",
},
{
Name: "Valid",
Color: "53e917",
},
}, labels)
milestones, err := downloader.GetMilestones()
require.NoError(t, err)
assertMilestonesEqual(t, []*base.Milestone{
{
Title: "V2 Finalize",
Created: time.Unix(0, 0),
Deadline: timePtr(time.Unix(1599263999, 0)),
Updated: timePtr(time.Date(2022, 11, 13, 5, 29, 15, 0, time.UTC)),
State: "open",
},
{
Title: "V1",
Description: "Generate Content",
Created: time.Unix(0, 0),
Updated: timePtr(time.Unix(0, 0)),
Closed: timePtr(time.Unix(1598985406, 0)),
State: "closed",
},
}, milestones)
releases, err := downloader.GetReleases()
require.NoError(t, err)
assertReleasesEqual(t, []*base.Release{
{
Name: "Second Release",
TagName: "v2-rc1",
TargetCommitish: "master",
Body: "this repo has:\r\n* reactions\r\n* wiki\r\n* issues (open/closed)\r\n* pulls (open/closed/merged) (external/internal)\r\n* pull reviews\r\n* projects\r\n* milestones\r\n* labels\r\n* releases\r\n\r\nto test migration against",
Draft: false,
Prerelease: true,
Created: time.Date(2020, 9, 1, 18, 2, 43, 0, time.UTC),
Published: time.Date(2020, 9, 1, 18, 2, 43, 0, time.UTC),
PublisherID: 689,
PublisherName: "6543",
PublisherEmail: "6543@noreply.gitea.com",
},
{
Name: "First Release",
TagName: "V1",
TargetCommitish: "master",
Body: "as title",
Draft: false,
Prerelease: false,
Created: time.Date(2020, 9, 1, 17, 30, 32, 0, time.UTC),
Published: time.Date(2020, 9, 1, 17, 30, 32, 0, time.UTC),
PublisherID: 689,
PublisherName: "6543",
PublisherEmail: "6543@noreply.gitea.com",
},
}, releases)
issues, isEnd, err := downloader.GetIssues(1, 50)
require.NoError(t, err)
assert.True(t, isEnd)
assert.Len(t, issues, 7)
assert.Equal(t, "open", issues[0].State)
issues, isEnd, err = downloader.GetIssues(3, 2)
require.NoError(t, err)
assert.False(t, isEnd)
assertIssuesEqual(t, []*base.Issue{
{
Number: 4,
Title: "what is this repo about?",
Content: "",
Milestone: "V1",
PosterID: -1,
PosterName: "Ghost",
PosterEmail: "",
State: "closed",
IsLocked: true,
Created: time.Unix(1598975321, 0),
Updated: time.Unix(1598975400, 0),
Labels: []*base.Label{{
Name: "Question",
Color: "fbca04",
Description: "",
}},
Reactions: []*base.Reaction{
{
UserID: 689,
UserName: "6543",
Content: "gitea",
},
{
UserID: 689,
UserName: "6543",
Content: "laugh",
},
},
Closed: timePtr(time.Date(2020, 9, 1, 15, 49, 34, 0, time.UTC)),
},
{
Number: 2,
Title: "Spam",
Content: ":(",
Milestone: "",
PosterID: 689,
PosterName: "6543",
PosterEmail: "6543@obermui.de",
State: "closed",
IsLocked: false,
Created: time.Unix(1598919780, 0),
Updated: time.Unix(1598969497, 0),
Labels: []*base.Label{{
Name: "Invalid",
Color: "d4c5f9",
Description: "",
}},
Closed: timePtr(time.Unix(1598969497, 0)),
},
}, issues)
comments, _, err := downloader.GetComments(&base.Issue{Number: 4, ForeignIndex: 4})
require.NoError(t, err)
assertCommentsEqual(t, []*base.Comment{
{
IssueIndex: 4,
PosterID: 689,
PosterName: "6543",
PosterEmail: "6543@noreply.gitea.com",
Created: time.Unix(1598975370, 0),
Updated: time.Unix(1599070865, 0),
Content: "a really good question!\n\nIt is the used as TESTSET for gitea2gitea repo migration function",
},
{
IssueIndex: 4,
PosterID: -1,
PosterName: "Ghost",
PosterEmail: "ghost@noreply.gitea.com",
Created: time.Unix(1598975393, 0),
Updated: time.Unix(1598975393, 0),
Content: "Oh!",
},
}, comments)
prs, isEnd, err := downloader.GetPullRequests(1, 50)
require.NoError(t, err)
assert.True(t, isEnd)
assert.Len(t, prs, 6)
prs, isEnd, err = downloader.GetPullRequests(1, 3)
require.NoError(t, err)
assert.False(t, isEnd)
assert.Len(t, prs, 3)
assertPullRequestEqual(t, &base.PullRequest{
Number: 12,
PosterID: 689,
PosterName: "6543",
PosterEmail: "6543@obermui.de",
Title: "Dont Touch",
Content: "\r\nadd dont touch note",
Milestone: "V2 Finalize",
State: "closed",
IsLocked: false,
Created: time.Unix(1598982759, 0),
Updated: time.Unix(1599023425, 0),
Closed: timePtr(time.Date(2020, 9, 1, 17, 55, 33, 0, time.UTC)),
Assignees: []string{"techknowlogick"},
Base: base.PullRequestBranch{
CloneURL: "",
Ref: "master",
SHA: "827aa28a907853e5ddfa40c8f9bc52471a2685fd",
RepoName: "test_repo",
OwnerName: "gitea",
},
Head: base.PullRequestBranch{
CloneURL: server.URL + "/6543-forks/test_repo.git",
Ref: "refs/pull/12/head",
SHA: "b6ab5d9ae000b579a5fff03f92c486da4ddf48b6",
RepoName: "test_repo",
OwnerName: "6543-forks",
},
Merged: true,
MergedTime: timePtr(time.Unix(1598982934, 0)),
MergeCommitSHA: "827aa28a907853e5ddfa40c8f9bc52471a2685fd",
PatchURL: server.URL + "/gitea/test_repo/pulls/12.patch",
}, prs[1])
reviews, err := downloader.GetReviews(&base.Issue{Number: 7, ForeignIndex: 7})
require.NoError(t, err)
assertReviewsEqual(t, []*base.Review{
{
ID: 1770,
IssueIndex: 7,
ReviewerID: 689,
ReviewerName: "6543",
CommitID: "187ece0cb6631e2858a6872e5733433bb3ca3b03",
CreatedAt: time.Date(2020, 9, 1, 16, 12, 58, 0, time.UTC),
State: "COMMENT", // TODO
Comments: []*base.ReviewComment{
{
ID: 116561,
InReplyTo: 0,
Content: "is one `\\newline` to less?",
TreePath: "README.md",
DiffHunk: "@@ -2,3 +2,3 @@\n \n-Test repository for testing migration from gitea 2 gitea\n\\ No newline at end of file\n+Test repository for testing migration from gitea 2 gitea",
Position: 0,
Line: 4,
CommitID: "187ece0cb6631e2858a6872e5733433bb3ca3b03",
PosterID: 689,
Reactions: nil,
CreatedAt: time.Date(2020, 9, 1, 16, 12, 58, 0, time.UTC),
UpdatedAt: time.Date(2024, 6, 3, 1, 18, 36, 0, time.UTC),
},
},
},
{
ID: 1771,
IssueIndex: 7,
ReviewerID: 9,
ReviewerName: "techknowlogick",
CommitID: "187ece0cb6631e2858a6872e5733433bb3ca3b03",
CreatedAt: time.Date(2020, 9, 1, 17, 6, 47, 0, time.UTC),
State: "REQUEST_CHANGES", // TODO
Content: "I think this needs some changes",
},
{
ID: 1772,
IssueIndex: 7,
ReviewerID: 9,
ReviewerName: "techknowlogick",
CommitID: "187ece0cb6631e2858a6872e5733433bb3ca3b03",
CreatedAt: time.Date(2020, 9, 1, 17, 19, 51, 0, time.UTC),
State: base.ReviewStateApproved,
Official: true,
Content: "looks good",
},
}, reviews)
}
func TestForgejoDownloadRepo(t *testing.T) {
token := os.Getenv("CODE_FORGEJO_TOKEN")
fixturePath := "./testdata/code-forgejo-org/full_download"
server := unittest.NewMockWebServer(t, "https://code.forgejo.org", fixturePath, token != "")
defer server.Close()
giteaClient, err := gitea_sdk.NewClient(
server.URL,
gitea_sdk.SetToken(token),
gitea_sdk.SetBasicAuth("", ""),
gitea_sdk.SetContext(t.Context()),
gitea_sdk.SetHTTPClient(NewMigrationHTTPClient()),
)
require.NoError(t, err, "Clould not create Client")
downloader, err := NewGiteaDownloader(t.Context(), giteaClient, server.URL, "Gusted/agit-test")
require.NoError(t, err)
require.NotNil(t, downloader)
prs, _, err := downloader.GetPullRequests(1, 50)
require.NoError(t, err)
assert.Len(t, prs, 1)
assertPullRequestEqual(t, &base.PullRequest{
Number: 1,
PosterID: 63,
PosterName: "Gusted",
PosterEmail: "postmaster@gusted.xyz",
Title: "Add extra information",
State: "open",
Created: time.Date(2025, time.April, 1, 20, 28, 45, 0, time.UTC),
Updated: time.Date(2025, time.April, 1, 20, 28, 45, 0, time.UTC),
Base: base.PullRequestBranch{
CloneURL: "",
Ref: "main",
SHA: "79ebb873a6497c8847141ba9706b3f757196a1e6",
RepoName: "agit-test",
OwnerName: "Gusted",
},
Head: base.PullRequestBranch{
CloneURL: server.URL + "/Gusted/agit-test.git",
Ref: "refs/pull/1/head",
SHA: "667e9317ec37b977e6d3d7d43e3440636970563c",
RepoName: "agit-test",
OwnerName: "Gusted",
},
PatchURL: server.URL + "/Gusted/agit-test/pulls/1.patch",
Flow: 1,
}, prs[0])
}
func createGiteaIssueComments(number int) []*gitea_sdk.Comment {
giteaComments := make([]*gitea_sdk.Comment, 0, number)
giteaUser := &gitea_sdk.User{
ID: 1,
UserName: "rando",
}
for i := 1; i <= number; i++ {
giteaComment := gitea_sdk.Comment{
ID: 1,
Poster: giteaUser,
Created: time.Date(2025, time.August, 7, 13, i, 25, 0, time.UTC),
Updated: time.Date(2025, time.August, 7, 13, i+2, 25, 0, time.UTC),
Body: strconv.Itoa(i),
}
giteaComments = append(giteaComments, &giteaComment)
}
return giteaComments
}
func createForgejoIssueComments(comments []*gitea_sdk.Comment) []*base.Comment {
forgejoComments := make([]*base.Comment, 0, len(comments))
for _, comment := range comments {
forgejoComments = append(forgejoComments, &base.Comment{
IssueIndex: 1, // commentable.GetLocalIndex()
Index: comment.ID,
PosterID: comment.Poster.ID,
PosterName: comment.Poster.UserName,
PosterEmail: comment.Poster.Email,
Content: comment.Body,
Created: comment.Created,
Updated: comment.Updated,
Reactions: []*base.Reaction{},
})
}
return forgejoComments
}
func TestBreakConditions(t *testing.T) {
giteaToken := os.Getenv("GITEA_TOKEN")
fixturePath := "./testdata/gitea/breaking_conditions"
server := unittest.NewMockWebServer(t, "https://gitea.com", fixturePath, giteaToken != "")
defer server.Close()
// Client
giteaClient, err := gitea_sdk.NewClient(
server.URL,
gitea_sdk.SetToken(""),
gitea_sdk.SetBasicAuth("", ""),
gitea_sdk.SetContext(t.Context()),
gitea_sdk.SetHTTPClient(NewMigrationHTTPClient()),
)
require.NoError(t, err, "Clould not create Client")
// Downloader
downloader, err := NewGiteaDownloader(t.Context(), giteaClient, server.URL, "gitea/test_repo")
if downloader == nil {
t.Fatal("NewGiteaDownloader is nil")
}
require.NoError(t, err, "Could not create Gitea Downloader")
pageSize := 20
buggyPageSize := 25
smallerPageSize := 15
downloader.maxPerPage = pageSize
bugResponse := createGiteaIssueComments(buggyPageSize)
commentsWithBug := createForgejoIssueComments(bugResponse)
shorterListResponse := createGiteaIssueComments(smallerPageSize)
commentsShortList := createForgejoIssueComments(shorterListResponse)
fullListResponse := createGiteaIssueComments(pageSize)
differentFullListResponse := createGiteaIssueComments(pageSize)
differentFullListResponse[0].Body = "Different String"
differentFullListResponse[len(differentFullListResponse)-1].Body = "Different String"
commentsFullList := createForgejoIssueComments(fullListResponse)
assert.True(t, downloader.isSinglePage(commentsWithBug))
assert.True(t, downloader.isSinglePage(commentsShortList))
assert.True(t, downloader.isLastPage(commentsShortList, shorterListResponse))
assert.True(t, downloader.isLastPage(commentsWithBug, bugResponse))
assert.False(t, downloader.isSinglePage(commentsFullList))
assert.False(t, downloader.isLastPage(commentsFullList, differentFullListResponse))
}