diff --git a/modules/testlogger/testlogger.go b/modules/testlogger/testlogger.go index c5ca906220..7300b80667 100644 --- a/modules/testlogger/testlogger.go +++ b/modules/testlogger/testlogger.go @@ -43,9 +43,7 @@ func (w *testLoggerWriterCloser) pushT(t testing.TB) { } func (w *testLoggerWriterCloser) Log(level log.Level, msg string) { - if len(msg) > 0 && msg[len(msg)-1] == '\n' { - msg = msg[:len(msg)-1] - } + msg = strings.TrimSpace(msg) w.printMsg(msg) if level >= log.ERROR { @@ -111,6 +109,279 @@ var ignoredErrorMessageSuffixes = []string{ // TestRebuildCargo `RebuildCargoIndex() [E] RebuildIndex failed: GetRepositoryByOwnerAndName: repository does not exist [id: 0, uid: 0, owner_name: user2, name: _cargo-index]`, + + // TestCommitMail/Delete/Not_activated + `/context_response.go:87:HTML() [E] Render failed: failed to render template: repo/editor/edit, error: template error: builtin(static):repo/editor/edit:13:13 : executing "repo/editor/edit" at : error calling len: reflect: call of reflect.Value.Type on zero Value +---------------------------------------------------------------------- + {{$n := len .TreeNames}} + ^ +----------------------------------------------------------------------`, + // TestCommitMail/Delete/Not_belong_to_user + `/context_response.go:87:HTML() [E] Render failed: failed to render template: repo/editor/edit, error: template error: builtin(static):repo/editor/edit:13:13 : executing "repo/editor/edit" at : error calling len: reflect: call of reflect.Value.Type on zero Value +---------------------------------------------------------------------- + {{$n := len .TreeNames}} + ^ +----------------------------------------------------------------------`, + // TestCommitMail/Apply_patch/Not_activated + `/context_response.go:87:HTML() [E] Render failed: failed to render template: repo/editor/edit, error: template error: builtin(static):repo/editor/edit:13:13 : executing "repo/editor/edit" at : error calling len: reflect: call of reflect.Value.Type on zero Value +---------------------------------------------------------------------- + {{$n := len .TreeNames}} + ^ +----------------------------------------------------------------------`, + // TestCommitMail/Apply_patch/Not_belong_to_user + `/context_response.go:87:HTML() [E] Render failed: failed to render template: repo/editor/edit, error: template error: builtin(static):repo/editor/edit:13:13 : executing "repo/editor/edit" at : error calling len: reflect: call of reflect.Value.Type on zero Value +---------------------------------------------------------------------- + {{$n := len .TreeNames}} + ^ +----------------------------------------------------------------------`, + // TestCommitMail/Cherry_pick/Not_activated + `/context_response.go:87:HTML() [E] Render failed: failed to render template: repo/editor/edit, error: template error: builtin(static):repo/editor/edit:13:13 : executing "repo/editor/edit" at : error calling len: reflect: call of reflect.Value.Type on zero Value +---------------------------------------------------------------------- + {{$n := len .TreeNames}} + ^ +----------------------------------------------------------------------`, + // TestCommitMail/Cherry_pick/Not_belong_to_user + `/context_response.go:87:HTML() [E] Render failed: failed to render template: repo/editor/edit, error: template error: builtin(static):repo/editor/edit:13:13 : executing "repo/editor/edit" at : error calling len: reflect: call of reflect.Value.Type on zero Value +---------------------------------------------------------------------- + {{$n := len .TreeNames}} + ^ +----------------------------------------------------------------------`, + // TestDangerZoneConfirmation/Convert_fork/Fail + `/gitea-repositories/user20/big_test_public_fork_7.git Error: no such file or directory`, + // TestGitSmartHTTP + `/web/repo/githttp.go:384:sendFile() [E] request file path contains invalid path: objects/info/..\..\..\..\custom\conf\app.ini`, + // TestGit/HTTP/BranchProtectMerge + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Not allowed to push to protected branch protected. HookPreReceive(last) failed: internal API error response, status=403`, + // TestGit/HTTP/BranchProtectMerge + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Not allowed to push to protected branch protected. HookPreReceive(last) failed: internal API error response, status=403`, + // TestGit/HTTP/BranchProtectMerge + `/gitea-repositories/user2/repo-tmp-17.git'`, + // TestGit/HTTP/BranchProtectMerge + `s/private/ssh_log.go:26:SSHLog() [E] ssh: branch protected is protected from force push. HookPreReceive(last) failed: internal API error response, status=403`, + // TestGit/HTTP/MergeFork/CreatePRAndMerge + `s/web/repo/branch.go:108:DeleteBranchPost() [E] DeleteBranch: GetBranch: branch does not exist [repo_id: 1099 name: user2:master]`, // sqlite + "s/web/repo/branch.go:108:DeleteBranchPost() [E] DeleteBranch: GetBranch: branch does not exist [repo_id: 10000 name: user2:master]", // mysql + "s/web/repo/branch.go:108:DeleteBranchPost() [E] DeleteBranch: GetBranch: branch does not exist [repo_id: 1060 name: user2:master]", // pgsql + // TestGit/SSH/LFS/PushCommit/Little + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/LFS/PushCommit/Little + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/LFS/PushCommit/Big + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/LFS/PushCommit/Big + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/LFS/Locks + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/LFS/Locks + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/LFS/Locks + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/LFS/Locks + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/LFS/Locks + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/CreateAgitFlowPull/PushParams/NoParams + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/CreateAgitFlowPull/PushParams/NoParams + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/CreateAgitFlowPull/PushParams/TitleOverride + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/CreateAgitFlowPull/PushParams/TitleOverride + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/CreateAgitFlowPull/PushParams/DescriptionOverride + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/CreateAgitFlowPull/PushParams/DescriptionOverride + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/CreateAgitFlowPull/Force_push/Fails + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/CreateAgitFlowPull/Force_push/Fails + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/CreateAgitFlowPull/Force_push/Succeeds + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/CreateAgitFlowPull/Force_push/Succeeds + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/CreateAgitFlowPull/Force_push + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/CreateAgitFlowPull/Force_push + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/CreateAgitFlowPull/Branch_already_contains_commit + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/CreateAgitFlowPull/Branch_already_contains_commit + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/CreateAgitFlowPull + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/CreateAgitFlowPull + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/CreateAgitFlowPull + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/CreateAgitFlowPull + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/CreateAgitFlowPull + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/CreateAgitFlowPull + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/CreateAgitFlowPull + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/CreateAgitFlowPull + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/BranchProtectMerge + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/BranchProtectMerge + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/BranchProtectMerge + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/BranchProtectMerge + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/BranchProtectMerge + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Not allowed to push to protected branch protected. HookPreReceive(last) failed: internal API error response, status=403`, + // TestGit/SSH/BranchProtectMerge + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/BranchProtectMerge + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/BranchProtectMerge + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/BranchProtectMerge + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/BranchProtectMerge + `/gitea-repositories/user2/repo-tmp-18.git'`, + // TestGit/SSH/BranchProtectMerge + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/BranchProtectMerge + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/BranchProtectMerge + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/BranchProtectMerge + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/BranchProtectMerge + `s/private/ssh_log.go:26:SSHLog() [E] ssh: branch protected is protected from force push. HookPreReceive(last) failed: internal API error response, status=403`, + // TestGit/SSH/BranchProtectMerge + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/BranchProtectMerge + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`, + // TestGit/SSH/MergeFork/CreatePRAndMerge + `s/web/repo/branch.go:108:DeleteBranchPost() [E] DeleteBranch: GetBranch: branch does not exist [repo_id: 1102 name: user2:master]`, // sqlite + "s/web/repo/branch.go:108:DeleteBranchPost() [E] DeleteBranch: GetBranch: branch does not exist [repo_id: 10003 name: user2:master]", // mysql + "s/web/repo/branch.go:108:DeleteBranchPost() [E] DeleteBranch: GetBranch: branch does not exist [repo_id: 1063 name: user2:master]", // pgsql + // TestGit/SSH/PushCreate + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Push to create is not enabled for users. ServCommand failed: internal API error response, status=403`, + // TestGit/SSH/PushCreate + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Cannot find repository: user2/repo-tmp-push-create-ssh. ServCommand failed: internal API error response, status=404`, + // TestGit/SSH/PushCreate + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Invalid repo name. Invalid repo name: invalid/repo-tmp-push-create-ssh`, + // TestIssueReaction + `rs/web/repo/issue.go:3282:ChangeIssueReaction() [E] ChangeIssueReaction: '8ball' is not an allowed reaction`, + // TestIssuePinMove + `eb/repo/issue_pin.go:95:IssuePinMove() [E] Issue does not belong to this repository`, + // TestLinksLogin + `ervices/pull/pull.go:880:GetIssuesAllCommitStatus() [E] getAllCommitStatus: cant get commit statuses of pull [6]: object does not exist [id: refs/pull/2/head, rel_path: ]`, + // TestLinksLogin + `ervices/pull/pull.go:880:GetIssuesAllCommitStatus() [E] getAllCommitStatus: cant get commit statuses of pull [6]: object does not exist [id: refs/pull/2/head, rel_path: ]`, + // TestLinksLogin + `ervices/pull/pull.go:880:GetIssuesAllCommitStatus() [E] getAllCommitStatus: cant get commit statuses of pull [6]: object does not exist [id: refs/pull/2/head, rel_path: ]`, + // TestLinksLogin + `ervices/pull/pull.go:872:GetIssuesAllCommitStatus() [E] Cannot open git repository for issue #1[20]. Error: no such file or directory`, + // TestMigrate + `] for OwnerID[2] failed: error while listing issues: token does not have at least one of required scope(s): [read:issue]`, + // TestMigrate + `ervices/task/task.go:53:handler() [E] Run task failed: error while listing issues: token does not have at least one of required scope(s): [read:issue]`, + // TestMigrate + `] for OwnerID[2] failed: error while listing issues: token does not have at least one of required scope(s): [read:issue]`, + // TestMigrate + `ervices/task/task.go:53:handler() [E] Run task failed: error while listing issues: token does not have at least one of required scope(s): [read:issue]`, + // TestMirrorPush + `/web/repo/githttp.go:533:GetInfoRefs() [E] fork/exec /usr/bin/git: no such file or directory -`, + + // TestOrgMembers + `nization/org_user.go:122:loadOrganizationOwners() [E] Organization does not have owner team: 25`, + // TestOrgMembers + `nization/org_user.go:122:loadOrganizationOwners() [E] Organization does not have owner team: 25`, + // TestOrgMembers + `nization/org_user.go:122:loadOrganizationOwners() [E] Organization does not have owner team: 25`, + // TestRecentlyPushed/unrelated_branches_are_not_shown + `repository/branch.go:30:SyncRepoBranches() [E] OpenRepository[user30/repo50]: %!w(*errors.errorString=&{no such file or directory})`, + // TestRecentlyPushed/unrelated_branches_are_not_shown + `repository/branch.go:488:handlerBranchSync() [E] syncRepoBranches [50] failed: no such file or directory`, + // TestRecentlyPushed/unrelated_branches_are_not_shown + `repository/branch.go:30:SyncRepoBranches() [E] OpenRepository[user30/repo51]: %!w(*errors.errorString=&{no such file or directory})`, + // TestRecentlyPushed/unrelated_branches_are_not_shown + `repository/branch.go:488:handlerBranchSync() [E] syncRepoBranches [51] failed: no such file or directory`, + // TestRecentlyPushed/unrelated_branches_are_not_shown + `repository/branch.go:30:SyncRepoBranches() [E] OpenRepository[user2/scoped_label]: %!w(*errors.errorString=&{no such file or directory})`, + // TestRecentlyPushed/unrelated_branches_are_not_shown + `repository/branch.go:488:handlerBranchSync() [E] syncRepoBranches [55] failed: no such file or directory`, + // TestCantMergeConflict + "]user1/repo1#1[base...conflict]> Unable to merge tracking into base: Merge Conflict Error: exit status 1: \nAuto-merging README.md\nCONFLICT (content): Merge conflict in README.md\nAutomatic merge failed; fix conflicts and then commit the result.", + + // TestCantMergeUnrelated + `]user1/repo1#1[base...unrelated]> Unable to merge tracking into base: Merge UnrelatedHistories Error: exit status 128: fatal: refusing to merge unrelated histories`, + // TestCantFastForwardOnlyMergeDiverging + "]user1/repo1#1[master...diverging]> Unable to merge tracking into base: Merge DivergingFastForwardOnly Error: exit status 128: hint: Diverging branches can't be fast-forwarded, you need to either:\nhint: \nhint: \tgit merge --no-ff\nhint: \nhint: or:\nhint: \nhint: \tgit rebase\nhint: \nhint: Disable this message with \"git config advice.diverging false\"\nfatal: Not possible to fast-forward, aborting.", + // TestPullrequestReopen/Base_branch_deleted + `fatal: couldn't find remote ref base-branch`, + // TestPullrequestReopen/Head_branch_deleted + `]user2/reopen-base#1[base-branch...org26/reopen-head:head-branch]>]: branch does not exist [repo_id: 0 name: head-branch]`, + // TestDatabaseMissingABranch + `repository/branch.go:30:SyncRepoBranches() [E] OpenRepository[user30/repo50]: %!w(*errors.errorString=&{no such file or directory})`, + // TestDatabaseMissingABranch + `repository/branch.go:488:handlerBranchSync() [E] syncRepoBranches [50] failed: no such file or directory`, + // TestDatabaseMissingABranch + `repository/branch.go:30:SyncRepoBranches() [E] OpenRepository[user30/repo51]: %!w(*errors.errorString=&{no such file or directory})`, + // TestDatabaseMissingABranch + `repository/branch.go:488:handlerBranchSync() [E] syncRepoBranches [51] failed: no such file or directory`, + // TestDatabaseMissingABranch + `repository/branch.go:30:SyncRepoBranches() [E] OpenRepository[user2/scoped_label]: %!w(*errors.errorString=&{no such file or directory})`, + // TestDatabaseMissingABranch + `repository/branch.go:488:handlerBranchSync() [E] syncRepoBranches [55] failed: no such file or directory`, + // TestDatabaseMissingABranch + `repository/branch.go:100:LoadBranches() [E] loadOneBranch() on repo #1, branch 'will-be-missing' failed: CountDivergingCommits: exit status 128 - fatal: bad revision 'master...refs/heads/will-be-missing' + - fatal: bad revision 'master...refs/heads/will-be-missing'`, + // TestDatabaseMissingABranch + `repository/branch.go:30:SyncRepoBranches() [E] OpenRepository[user30/repo50]: %!w(*errors.errorString=&{no such file or directory})`, + // TestDatabaseMissingABranch + `repository/branch.go:488:handlerBranchSync() [E] syncRepoBranches [50] failed: no such file or directory`, + // TestDatabaseMissingABranch + `repository/branch.go:30:SyncRepoBranches() [E] OpenRepository[user30/repo51]: %!w(*errors.errorString=&{no such file or directory})`, + // TestDatabaseMissingABranch + `repository/branch.go:488:handlerBranchSync() [E] syncRepoBranches [51] failed: no such file or directory`, + // TestDatabaseMissingABranch + `repository/branch.go:30:SyncRepoBranches() [E] OpenRepository[user2/scoped_label]: %!w(*errors.errorString=&{no such file or directory})`, + // TestDatabaseMissingABranch + `repository/branch.go:488:handlerBranchSync() [E] syncRepoBranches [55] failed: no such file or directory`, + // TestDatabaseMissingABranch + "LoadBranches() [E] loadOneBranch() on repo #1, branch 'will-be-missing' failed: CountDivergingCommits: exit status 128 - fatal: bad revision 'master...refs/heads/will-be-missing'\n - fatal: bad revision 'master...refs/heads/will-be-missing'", + + // TestCreateNewTagProtected/Git + `s/private/ssh_log.go:26:SSHLog() [E] ssh: Tag v-2 is protected. HookPreReceive(last) failed: internal API error response, status=403`, + // TestMarkDownReadmeImage + `ers/web/repo/view.go:1167:checkOutdatedBranch() [E] GetBranch: branch does not exist [repo_id: 1 name: home-md-img-check]`, + // TestMarkDownReadmeImage + `ers/web/repo/view.go:1167:checkOutdatedBranch() [E] GetBranch: branch does not exist [repo_id: 1 name: home-md-img-check]`, + // TestMarkDownReadmeImageSubfolder + `ers/web/repo/view.go:1167:checkOutdatedBranch() [E] GetBranch: branch does not exist [repo_id: 1 name: sub-home-md-img-check]`, + // TestMarkDownReadmeImageSubfolder + `ers/web/repo/view.go:1167:checkOutdatedBranch() [E] GetBranch: branch does not exist [repo_id: 1 name: sub-home-md-img-check]`, + + // TestKeyOnlyOneType + `:ssh-key-test-repo-push is not authorized to write to user2/ssh-key-test-repo. ServCommand failed: internal API error response, status=401`, + + // TestPullRebase + "/gitea-repositories/user2/repo1.git' does not appear to be a git repository\nfatal: Could not read from remote repository.\n\nPlease make sure you have the correct access rights\nand the repository exists.", + + // TestPullRebaseMerge + "]user2/repo1#3[master...branch2]>]: branch does not exist [repo_id: 0 name: branch2]", + + // TestAuthorizeNoClientID + `TrString() [E] Missing translation "form.ResponseType"`, + + // TestWebhookForms + `TrString() [E] Missing translation "form.AuthorizationHeader"`, + `TrString() [E] Missing translation "form.Channel"`, + `TrString() [E] Missing translation "form.ContentType"`, + `TrString() [E] Missing translation "form.HTTPMethod"`, + `TrString() [E] Missing translation "form.PayloadURL"`, + + // TestRenameInvalidUsername + `TrString() [E] Missing translation "form.Name"`, } func (w *testLoggerWriterCloser) recordError(msg string) { @@ -128,6 +399,11 @@ func (w *testLoggerWriterCloser) recordError(msg string) { err = w.errs[len(w.errs)-1] } + if len(w.t) > 0 { + // format error message to easily add it to the ignore list + msg = fmt.Sprintf("// %s\n\t%q,", w.t[len(w.t)-1].Name(), msg) + } + err = errors.Join(err, errors.New(msg)) if len(w.errs) > 0 { diff --git a/tests/integration/cmd_forgejo_actions_test.go b/tests/integration/cmd_forgejo_actions_test.go index 44211007f5..e45526ac7a 100644 --- a/tests/integration/cmd_forgejo_actions_test.go +++ b/tests/integration/cmd_forgejo_actions_test.go @@ -4,8 +4,11 @@ package integration import ( gocontext "context" + "errors" + "io" "net/url" "os" + "os/exec" "strings" "testing" @@ -19,16 +22,18 @@ import ( func Test_CmdForgejo_Actions(t *testing.T) { onGiteaRun(t, func(*testing.T, *url.URL) { - token, err := cmdForgejoCaptureOutput(t, []string{"forgejo", "forgejo-cli", "actions", "generate-runner-token"}) + token, err := runMainApp("forgejo-cli", "actions", "generate-runner-token") assert.NoError(t, err) assert.EqualValues(t, 40, len(token)) - secret, err := cmdForgejoCaptureOutput(t, []string{"forgejo", "forgejo-cli", "actions", "generate-secret"}) + secret, err := runMainApp("forgejo-cli", "actions", "generate-secret") assert.NoError(t, err) assert.EqualValues(t, 40, len(secret)) - _, err = cmdForgejoCaptureOutput(t, []string{"forgejo", "forgejo-cli", "actions", "register"}) - assert.ErrorContains(t, err, "at least one of the --secret") + _, err = runMainApp("forgejo-cli", "actions", "register") + var exitErr *exec.ExitError + assert.True(t, errors.As(err, &exitErr)) + assert.Contains(t, string(exitErr.Stderr), "at least one of the --secret") for _, testCase := range []struct { testName string @@ -62,10 +67,12 @@ func Test_CmdForgejo_Actions(t *testing.T) { }, } { t.Run(testCase.testName, func(t *testing.T) { - cmd := []string{"forgejo", "forgejo-cli", "actions", "register", "--secret", testCase.secret, "--scope", testCase.scope} - output, err := cmdForgejoCaptureOutput(t, cmd) - assert.ErrorContains(t, err, testCase.errorMessage) + output, err := runMainApp("forgejo-cli", "actions", "register", "--secret", testCase.secret, "--scope", testCase.scope) assert.EqualValues(t, "", output) + + var exitErr *exec.ExitError + assert.True(t, errors.As(err, &exitErr)) + assert.Contains(t, string(exitErr.Stderr), testCase.errorMessage) }) } @@ -75,7 +82,7 @@ func Test_CmdForgejo_Actions(t *testing.T) { for _, testCase := range []struct { testName string secretOption func() string - stdin []string + stdin io.Reader }{ { testName: "secret from argument", @@ -88,7 +95,7 @@ func Test_CmdForgejo_Actions(t *testing.T) { secretOption: func() string { return "--secret-stdin" }, - stdin: []string{secret}, + stdin: strings.NewReader(secret), }, { testName: "secret from file", @@ -100,8 +107,7 @@ func Test_CmdForgejo_Actions(t *testing.T) { }, } { t.Run(testCase.testName, func(t *testing.T) { - cmd := []string{"forgejo", "forgejo-cli", "actions", "register", testCase.secretOption(), "--scope=org26"} - uuid, err := cmdForgejoCaptureOutput(t, cmd, testCase.stdin...) + uuid, err := runMainAppWithStdin(testCase.stdin, "forgejo-cli", "actions", "register", testCase.secretOption(), "--scope=org26") assert.NoError(t, err) assert.EqualValues(t, expecteduuid, uuid) }) @@ -161,7 +167,7 @@ func Test_CmdForgejo_Actions(t *testing.T) { } { t.Run(testCase.testName, func(t *testing.T) { cmd := []string{ - "forgejo", "forgejo-cli", "actions", "register", + "actions", "register", "--secret", testCase.secret, "--scope", testCase.scope, } if testCase.name != "" { @@ -177,7 +183,7 @@ func Test_CmdForgejo_Actions(t *testing.T) { // Run twice to verify it is idempotent // for i := 0; i < 2; i++ { - uuid, err := cmdForgejoCaptureOutput(t, cmd) + uuid, err := runMainApp("forgejo-cli", cmd...) assert.NoError(t, err) if assert.EqualValues(t, testCase.uuid, uuid) { ownerName, repoName, found := strings.Cut(testCase.scope, "/") diff --git a/tests/integration/cmd_forgejo_test.go b/tests/integration/cmd_forgejo_test.go deleted file mode 100644 index 76f5a6fc08..0000000000 --- a/tests/integration/cmd_forgejo_test.go +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: MIT - -package integration - -import ( - "bytes" - "context" - "strings" - "testing" - - "code.gitea.io/gitea/cmd/forgejo" - - "github.com/urfave/cli/v2" -) - -func cmdForgejoCaptureOutput(t *testing.T, args []string, stdin ...string) (string, error) { - buf := new(bytes.Buffer) - - app := cli.NewApp() - app.Writer = buf - app.ErrWriter = buf - ctx := context.Background() - ctx = forgejo.ContextSetNoInit(ctx, true) - ctx = forgejo.ContextSetNoExit(ctx, true) - ctx = forgejo.ContextSetStdout(ctx, buf) - ctx = forgejo.ContextSetStderr(ctx, buf) - if len(stdin) > 0 { - ctx = forgejo.ContextSetStdin(ctx, strings.NewReader(strings.Join(stdin, ""))) - } - app.Commands = []*cli.Command{ - forgejo.CmdForgejo(ctx), - } - err := app.Run(args) - - return buf.String(), err -} diff --git a/tests/integration/cmd_keys_test.go b/tests/integration/cmd_keys_test.go index 61f11c58b0..a3220c13ce 100644 --- a/tests/integration/cmd_keys_test.go +++ b/tests/integration/cmd_keys_test.go @@ -4,16 +4,15 @@ package integration import ( - "bytes" + "errors" "net/url" + "os/exec" "testing" - "code.gitea.io/gitea/cmd" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/util" "github.com/stretchr/testify/assert" - "github.com/urfave/cli/v2" ) func Test_CmdKeys(t *testing.T) { @@ -24,30 +23,30 @@ func Test_CmdKeys(t *testing.T) { wantErr bool expectedOutput string }{ - {"test_empty_1", []string{"keys", "--username=git", "--type=test", "--content=test"}, true, ""}, - {"test_empty_2", []string{"keys", "-e", "git", "-u", "git", "-t", "test", "-k", "test"}, true, ""}, + {"test_empty_1", []string{"--username=git", "--type=test", "--content=test"}, true, ""}, + {"test_empty_2", []string{"-e", "git", "-u", "git", "-t", "test", "-k", "test"}, true, ""}, { "with_key", - []string{"keys", "-e", "git", "-u", "git", "-t", "ssh-rsa", "-k", "AAAAB3NzaC1yc2EAAAADAQABAAABgQDWVj0fQ5N8wNc0LVNA41wDLYJ89ZIbejrPfg/avyj3u/ZohAKsQclxG4Ju0VirduBFF9EOiuxoiFBRr3xRpqzpsZtnMPkWVWb+akZwBFAx8p+jKdy4QXR/SZqbVobrGwip2UjSrri1CtBxpJikojRIZfCnDaMOyd9Jp6KkujvniFzUWdLmCPxUE9zhTaPu0JsEP7MW0m6yx7ZUhHyfss+NtqmFTaDO+QlMR7L2QkDliN2Jl3Xa3PhuWnKJfWhdAq1Cw4oraKUOmIgXLkuiuxVQ6mD3AiFupkmfqdHq6h+uHHmyQqv3gU+/sD8GbGAhf6ftqhTsXjnv1Aj4R8NoDf9BS6KRkzkeun5UisSzgtfQzjOMEiJtmrep2ZQrMGahrXa+q4VKr0aKJfm+KlLfwm/JztfsBcqQWNcTURiCFqz+fgZw0Ey/de0eyMzldYTdXXNRYCKjs9bvBK+6SSXRM7AhftfQ0ZuoW5+gtinPrnmoOaSCEJbAiEiTO/BzOHgowiM="}, + []string{"-e", "git", "-u", "git", "-t", "ssh-rsa", "-k", "AAAAB3NzaC1yc2EAAAADAQABAAABgQDWVj0fQ5N8wNc0LVNA41wDLYJ89ZIbejrPfg/avyj3u/ZohAKsQclxG4Ju0VirduBFF9EOiuxoiFBRr3xRpqzpsZtnMPkWVWb+akZwBFAx8p+jKdy4QXR/SZqbVobrGwip2UjSrri1CtBxpJikojRIZfCnDaMOyd9Jp6KkujvniFzUWdLmCPxUE9zhTaPu0JsEP7MW0m6yx7ZUhHyfss+NtqmFTaDO+QlMR7L2QkDliN2Jl3Xa3PhuWnKJfWhdAq1Cw4oraKUOmIgXLkuiuxVQ6mD3AiFupkmfqdHq6h+uHHmyQqv3gU+/sD8GbGAhf6ftqhTsXjnv1Aj4R8NoDf9BS6KRkzkeun5UisSzgtfQzjOMEiJtmrep2ZQrMGahrXa+q4VKr0aKJfm+KlLfwm/JztfsBcqQWNcTURiCFqz+fgZw0Ey/de0eyMzldYTdXXNRYCKjs9bvBK+6SSXRM7AhftfQ0ZuoW5+gtinPrnmoOaSCEJbAiEiTO/BzOHgowiM="}, false, "# gitea public key\ncommand=\"" + setting.AppPath + " --config=" + util.ShellEscape(setting.CustomConf) + " serv key-1\",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty,no-user-rc,restrict ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDWVj0fQ5N8wNc0LVNA41wDLYJ89ZIbejrPfg/avyj3u/ZohAKsQclxG4Ju0VirduBFF9EOiuxoiFBRr3xRpqzpsZtnMPkWVWb+akZwBFAx8p+jKdy4QXR/SZqbVobrGwip2UjSrri1CtBxpJikojRIZfCnDaMOyd9Jp6KkujvniFzUWdLmCPxUE9zhTaPu0JsEP7MW0m6yx7ZUhHyfss+NtqmFTaDO+QlMR7L2QkDliN2Jl3Xa3PhuWnKJfWhdAq1Cw4oraKUOmIgXLkuiuxVQ6mD3AiFupkmfqdHq6h+uHHmyQqv3gU+/sD8GbGAhf6ftqhTsXjnv1Aj4R8NoDf9BS6KRkzkeun5UisSzgtfQzjOMEiJtmrep2ZQrMGahrXa+q4VKr0aKJfm+KlLfwm/JztfsBcqQWNcTURiCFqz+fgZw0Ey/de0eyMzldYTdXXNRYCKjs9bvBK+6SSXRM7AhftfQ0ZuoW5+gtinPrnmoOaSCEJbAiEiTO/BzOHgowiM= user2@localhost\n", }, - {"invalid", []string{"keys", "--not-a-flag=git"}, true, "Incorrect Usage: flag provided but not defined: -not-a-flag\n\n"}, + {"invalid", []string{"--not-a-flag=git"}, true, "Incorrect Usage: flag provided but not defined: -not-a-flag\n\n"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - out := new(bytes.Buffer) - app := cli.NewApp() - app.Writer = out - app.Commands = []*cli.Command{cmd.CmdKeys} - cmd.CmdKeys.HideHelp = true - err := app.Run(append([]string{"prog"}, tt.args...)) + out, err := runMainApp("keys", tt.args...) + + var exitErr *exec.ExitError + if errors.As(err, &exitErr) { + t.Log(string(exitErr.Stderr)) + } if tt.wantErr { assert.Error(t, err) } else { assert.NoError(t, err) } - assert.Equal(t, tt.expectedOutput, out.String()) + assert.Equal(t, tt.expectedOutput, out) }) } }) diff --git a/tests/integration/integration_test.go b/tests/integration/integration_test.go index e8f28105c1..b087281ff4 100644 --- a/tests/integration/integration_test.go +++ b/tests/integration/integration_test.go @@ -17,6 +17,7 @@ import ( "net/http/httptest" "net/url" "os" + "os/exec" "path/filepath" "strconv" "strings" @@ -24,6 +25,7 @@ import ( "testing" "time" + "code.gitea.io/gitea/cmd" "code.gitea.io/gitea/models/auth" "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" @@ -93,7 +95,43 @@ func NewNilResponseHashSumRecorder() *NilResponseHashSumRecorder { } } +// runMainApp runs the subcommand and returns its standard output. Any returned error will usually be of type *ExitError. If c.Stderr was nil, Output populates ExitError.Stderr. +func runMainApp(subcommand string, args ...string) (string, error) { + return runMainAppWithStdin(nil, subcommand, args...) +} + +// runMainAppWithStdin runs the subcommand and returns its standard output. Any returned error will usually be of type *ExitError. If c.Stderr was nil, Output populates ExitError.Stderr. +func runMainAppWithStdin(stdin io.Reader, subcommand string, args ...string) (string, error) { + // running the main app directly will very likely mess with the testing setup (logger & co.) + // hence we run it as a subprocess and capture its output + args = append([]string{subcommand}, args...) + cmd := exec.Command(os.Args[0], args...) + cmd.Env = append(os.Environ(), + "GITEA_TEST_CLI=true", + "GITEA_CONF="+setting.CustomConf, + "GITEA_WORK_DIR="+setting.AppWorkPath) + cmd.Stdin = stdin + out, err := cmd.Output() + return string(out), err +} + func TestMain(m *testing.M) { + // GITEA_TEST_CLI is set by runMainAppWithStdin + // inspired by https://abhinavg.net/2022/05/15/hijack-testmain/ + if testCLI := os.Getenv("GITEA_TEST_CLI"); testCLI == "true" { + app := cmd.NewMainApp("test-version", "integration-test") + args := append([]string{ + "executable-name", // unused, but expected at position 1 + "--config", os.Getenv("GITEA_CONF"), + }, + os.Args[1:]..., // skip the executable name + ) + if err := cmd.RunMainApp(app, args...); err != nil { + panic(err) // should never happen since RunMainApp exits on error + } + return + } + defer log.GetManager().Close() managerCtx, cancel := context.WithCancel(context.Background()) diff --git a/tests/integration/pull_merge_test.go b/tests/integration/pull_merge_test.go index c9ecadca9a..e613538d05 100644 --- a/tests/integration/pull_merge_test.go +++ b/tests/integration/pull_merge_test.go @@ -26,11 +26,14 @@ import ( "code.gitea.io/gitea/models/webhook" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/gitrepo" + "code.gitea.io/gitea/modules/hostmatcher" + "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/test" "code.gitea.io/gitea/modules/translation" "code.gitea.io/gitea/services/pull" files_service "code.gitea.io/gitea/services/repository/files" + webhook_service "code.gitea.io/gitea/services/webhook" "github.com/stretchr/testify/assert" ) @@ -83,7 +86,19 @@ func testPullCleanUp(t *testing.T, session *TestSession, user, repo, pullnum str func retrieveHookTasks(t *testing.T, hookID int64, activateWebhook bool) []*webhook.HookTask { t.Helper() if activateWebhook { - updated, err := db.GetEngine(db.DefaultContext).ID(hookID).Cols("is_active").Update(webhook.Webhook{IsActive: true}) + s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNoContent) + })) + t.Cleanup(s.Close) + updated, err := db.GetEngine(db.DefaultContext).ID(hookID).Cols("is_active", "url").Update(webhook.Webhook{ + IsActive: true, + URL: s.URL, + }) + + // allow webhook deliveries on localhost + t.Cleanup(test.MockVariableValue(&setting.Webhook.AllowedHostList, hostmatcher.MatchBuiltinLoopback)) + webhook_service.Init() + assert.Equal(t, int64(1), updated) assert.NoError(t, err) }