mirror of
				https://codeberg.org/forgejo/forgejo.git
				synced 2025-11-04 08:21:11 +00:00 
			
		
		
		
	More about codespell: https://github.com/codespell-project/codespell . I personally introduced it to dozens if not hundreds of projects already and so far only positive feedback. ``` ❯ grep lint-spell Makefile @echo " - lint-spell lint spelling" @echo " - lint-spell-fix lint spelling and fix issues" lint: lint-frontend lint-backend lint-spell lint-fix: lint-frontend-fix lint-backend-fix lint-spell-fix .PHONY: lint-spell lint-spell: lint-codespell .PHONY: lint-spell-fix lint-spell-fix: lint-codespell-fix ❯ git grep lint- -- .forgejo/ .forgejo/workflows/testing.yml: - run: make --always-make -j$(nproc) lint-backend checks-backend # ensure the "go-licenses" make target runs .forgejo/workflows/testing.yml: - run: make lint-frontend ``` so how would you like me to invoke `lint-codespell` on CI? (without that would be IMHO very suboptimal and let typos sneak in) Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3270 Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org> Co-authored-by: Yaroslav Halchenko <debian@onerussian.com> Co-committed-by: Yaroslav Halchenko <debian@onerussian.com>
		
			
				
	
	
		
			578 lines
		
	
	
	
		
			27 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			578 lines
		
	
	
	
		
			27 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright 2019 The Gitea Authors. All rights reserved.
 | 
						|
// SPDX-License-Identifier: MIT
 | 
						|
 | 
						|
package testlogger
 | 
						|
 | 
						|
import (
 | 
						|
	"bytes"
 | 
						|
	"context"
 | 
						|
	"errors"
 | 
						|
	"fmt"
 | 
						|
	"io"
 | 
						|
	"os"
 | 
						|
	"runtime"
 | 
						|
	"strings"
 | 
						|
	"sync"
 | 
						|
	"testing"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"code.gitea.io/gitea/modules/log"
 | 
						|
	"code.gitea.io/gitea/modules/queue"
 | 
						|
)
 | 
						|
 | 
						|
var (
 | 
						|
	prefix    string
 | 
						|
	SlowTest  = 10 * time.Second
 | 
						|
	SlowFlush = 5 * time.Second
 | 
						|
)
 | 
						|
 | 
						|
var WriterCloser = &testLoggerWriterCloser{}
 | 
						|
 | 
						|
type testLoggerWriterCloser struct {
 | 
						|
	sync.RWMutex
 | 
						|
	t    []testing.TB
 | 
						|
	errs []error // stack of error, parallel to the stack of testing.TB
 | 
						|
	err  error   // fallback if the stack is empty
 | 
						|
}
 | 
						|
 | 
						|
func (w *testLoggerWriterCloser) pushT(t testing.TB) {
 | 
						|
	w.Lock()
 | 
						|
	w.t = append(w.t, t)
 | 
						|
	w.errs = append(w.errs, nil)
 | 
						|
	w.Unlock()
 | 
						|
}
 | 
						|
 | 
						|
func (w *testLoggerWriterCloser) Log(level log.Level, msg string) {
 | 
						|
	msg = strings.TrimSpace(msg)
 | 
						|
 | 
						|
	w.printMsg(msg)
 | 
						|
	if level >= log.ERROR {
 | 
						|
		w.recordError(msg)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// list of error message which will not fail the test
 | 
						|
// ideally this list should be empty, however ensuring that it does not grow
 | 
						|
// is already a good first step.
 | 
						|
var ignoredErrorMessage = []string{
 | 
						|
	// only seen on mysql tests https://codeberg.org/forgejo/forgejo/pulls/2657#issuecomment-1693055
 | 
						|
	`table columns using inconsistent collation, they should use "utf8mb4_0900_ai_ci". Please go to admin panel Self Check page`,
 | 
						|
 | 
						|
	// TestPullWIPConvertSidebar
 | 
						|
	`:PullRequestPushCommits() [E] comment.LoadIssue: issue does not exist [id:`,
 | 
						|
 | 
						|
	// TestAPIDeleteReleaseByTagName
 | 
						|
	// action notification were a commit cannot be computed (because the commit got deleted)
 | 
						|
	`Notify() [E] an error occurred while executing the DeleteRelease actions method: gitRepo.GetCommit: object does not exist [id: refs/tags/release-tag, rel_path: ]`,
 | 
						|
	`Notify() [E] an error occurred while executing the PushCommits actions method: gitRepo.GetCommit: object does not exist [id: refs/tags/release-tag, rel_path: ]`,
 | 
						|
 | 
						|
	// TestAPIRepoTags
 | 
						|
	`Notify() [E] an error occurred while executing the DeleteRelease actions method: gitRepo.GetCommit: object does not exist [id: refs/tags/gitea/22, rel_path: ]`,
 | 
						|
	`Notify() [E] an error occurred while executing the PushCommits actions method: gitRepo.GetCommit: object does not exist [id: refs/tags/gitea/22, rel_path: ]`,
 | 
						|
 | 
						|
	// TestAPIDeleteTagByName
 | 
						|
	`Notify() [E] an error occurred while executing the DeleteRelease actions method: gitRepo.GetCommit: object does not exist [id: refs/tags/delete-tag, rel_path: ]`,
 | 
						|
	`Notify() [E] an error occurred while executing the PushCommits actions method: gitRepo.GetCommit: object does not exist [id: refs/tags/delete-tag, rel_path: ]`,
 | 
						|
 | 
						|
	// TestAPIGenerateRepo
 | 
						|
	`Notify() [E] an error occurred while executing the CreateRepository actions method: gitRepo.GetCommit: object does not exist [id: , rel_path: ]`,
 | 
						|
 | 
						|
	// TestAPIPullUpdateByRebase
 | 
						|
	`:testPR() [E] Unable to GetPullRequestByID[`,
 | 
						|
	`:PullRequestSynchronized() [E] LoadAttributes: getRepositoryByID `,
 | 
						|
	`:PullRequestSynchronized() [E] pr.Issue.LoadRepo: getRepositoryByID [`,
 | 
						|
	`:handler() [E] Was unable to create issue notification: issue does not exist [`,
 | 
						|
	`:func1() [E] PullRequestList.LoadAttributes: issues and prs may be not in sync: cannot find issue`,
 | 
						|
	`:func1() [E] checkForInvalidation: GetRepositoryByIDCtx: repository does not exist `,
 | 
						|
 | 
						|
	// TestAPIPullReview
 | 
						|
	`PullRequestReview() [E] Unsupported review webhook type`,
 | 
						|
 | 
						|
	// TestAPIPullReviewRequest
 | 
						|
	`ToAPIPullRequest() [E] unable to resolve PR head ref`,
 | 
						|
 | 
						|
	// TestAPILFSUpload
 | 
						|
	`Put() [E] Whilst putting LFS OID[ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb]: Failed to copy to tmpPath: ca/97/8112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb Error: content size does not match`,
 | 
						|
	`[E] Error putting LFS MetaObject [ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb] into content store. Error: content size does not match`,
 | 
						|
	`UploadHandler() [E] Upload does not match LFS MetaObject [ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb]. Error: content size does not match`,
 | 
						|
	`Put() [E] Whilst putting LFS OID[2581dd7bbc1fe44726de4b7dd806a087a978b9c5aec0a60481259e34be09b06a]: Failed to copy to tmpPath: 25/81/dd7bbc1fe44726de4b7dd806a087a978b9c5aec0a60481259e34be09b06a Error: content hash does not match OID`,
 | 
						|
	`[E] Error putting LFS MetaObject [2581dd7bbc1fe44726de4b7dd806a087a978b9c5aec0a60481259e34be09b06a] into content store. Error: content hash does not match OID`,
 | 
						|
	`UploadHandler() [E] Upload does not match LFS MetaObject [2581dd7bbc1fe44726de4b7dd806a087a978b9c5aec0a60481259e34be09b06a]. Error: content hash does not match OID`,
 | 
						|
	`UploadHandler() [E] Upload does not match LFS MetaObject [83de2e488b89a0aa1c97496b888120a28b0c1e15463a4adb8405578c540f36d4]. Error: content size does not match`,
 | 
						|
 | 
						|
	// TestAPILFSVerify
 | 
						|
	`getAuthenticatedMeta() [E] Unable to get LFS OID[fb8f7d8435968c4f82a726a92395be4d16f2f63116caf36c8ad35c60831ab042] Error: LFS Meta object does not exist`,
 | 
						|
 | 
						|
	// TestAPIUpdateOrgAvatar
 | 
						|
	`UpdateAvatar() [E] UploadAvatar: image.DecodeConfig: image: unknown format`,
 | 
						|
 | 
						|
	// TestGetAttachment
 | 
						|
	`/data/attachments/a/0/a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a18: no such file or directory`,
 | 
						|
 | 
						|
	// TestBlockUser
 | 
						|
	`BlockedUsersUnblock() [E] IsOrganization: org3 is an organization not a user`,
 | 
						|
	`BlockedUsersBlock() [E] IsOrganization: org3 is an organization not a user`,
 | 
						|
	`Action() [E] Cannot perform this action on an organization "unblock"`,
 | 
						|
	`Action() [E] Cannot perform this action on an organization "block"`,
 | 
						|
 | 
						|
	// TestBlockActions
 | 
						|
	`/gitea-repositories/user10/repo7.git Error: no such file or directory`,
 | 
						|
 | 
						|
	// TestRebuildCargo
 | 
						|
	`RebuildCargoIndex() [E] RebuildIndex failed: GetRepositoryByOwnerAndName: repository does not exist [id: 0, uid: 0, owner_name: user2, name: _cargo-index]`,
 | 
						|
 | 
						|
	// TestDangerZoneConfirmation/Convert_fork/Fail
 | 
						|
	`/gitea-repositories/user20/big_test_public_fork_7.git Error: no such file or directory`,
 | 
						|
	// TestGitSmartHTTP
 | 
						|
	`:sendFile() [E] request file path contains invalid path: objects/info/..\..\..\..\custom\conf\app.ini`,
 | 
						|
	// TestGit/HTTP/BranchProtectMerge
 | 
						|
	`:SSHLog() [E] ssh: Not allowed to push to protected branch protected. HookPreReceive(last) failed: internal API error response, status=403`,
 | 
						|
	// TestGit/HTTP/BranchProtectMerge
 | 
						|
	`:SSHLog() [E] ssh: Not allowed to push to protected branch protected. HookPreReceive(last) failed: internal API error response, status=403`,
 | 
						|
	// TestGit/HTTP/BranchProtectMerge
 | 
						|
	`:SSHLog() [E] ssh: branch protected is protected from force push. HookPreReceive(last) failed: internal API error response, status=403`,
 | 
						|
	// TestGit/HTTP/MergeFork/CreatePRAndMerge
 | 
						|
	`: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/HTTP/BranchProtectMerge
 | 
						|
	`:func1() [E] PushToBaseRepo: PushRejected Error: exit status 1 - remote: error: cannot lock ref`,
 | 
						|
	// TestGit/SSH/BranchProtectMerge
 | 
						|
	`:func1() [E] PushToBaseRepo: PushRejected Error: exit status 1 - remote: error: cannot lock ref`,
 | 
						|
	// TestGit/SSH/LFS/PushCommit/Little
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/LFS/PushCommit/Little
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/LFS/PushCommit/Big
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/LFS/PushCommit/Big
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/LFS/Locks
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/LFS/Locks
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/LFS/Locks
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/LFS/Locks
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/LFS/Locks
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/CreateAgitFlowPull/PushParams/NoParams
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/CreateAgitFlowPull/PushParams/NoParams
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/CreateAgitFlowPull/PushParams/TitleOverride
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/CreateAgitFlowPull/PushParams/TitleOverride
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/CreateAgitFlowPull/PushParams/DescriptionOverride
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/CreateAgitFlowPull/PushParams/DescriptionOverride
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/CreateAgitFlowPull/Force_push/Fails
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/CreateAgitFlowPull/Force_push/Fails
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/CreateAgitFlowPull/Force_push/Succeeds
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/CreateAgitFlowPull/Force_push/Succeeds
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/CreateAgitFlowPull/Force_push
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/CreateAgitFlowPull/Force_push
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/CreateAgitFlowPull/Branch_already_contains_commit
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/CreateAgitFlowPull/Branch_already_contains_commit
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/CreateAgitFlowPull
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/CreateAgitFlowPull
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/CreateAgitFlowPull
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/CreateAgitFlowPull
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/CreateAgitFlowPull
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/CreateAgitFlowPull
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/CreateAgitFlowPull
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/CreateAgitFlowPull
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/BranchProtectMerge
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/BranchProtectMerge
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/BranchProtectMerge
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/BranchProtectMerge
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/BranchProtectMerge
 | 
						|
	`:SSHLog() [E] ssh: Not allowed to push to protected branch protected. HookPreReceive(last) failed: internal API error response, status=403`,
 | 
						|
	// TestGit/SSH/BranchProtectMerge
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/BranchProtectMerge
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/BranchProtectMerge
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/BranchProtectMerge
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/BranchProtectMerge
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/BranchProtectMerge
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/BranchProtectMerge
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/BranchProtectMerge
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/BranchProtectMerge
 | 
						|
	`:SSHLog() [E] ssh: branch protected is protected from force push. HookPreReceive(last) failed: internal API error response, status=403`,
 | 
						|
	// TestGit/SSH/BranchProtectMerge
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/BranchProtectMerge
 | 
						|
	`:SSHLog() [E] ssh: Unknown git command. Unknown git command git-lfs-transfer`,
 | 
						|
	// TestGit/SSH/MergeFork/CreatePRAndMerge
 | 
						|
	`: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
 | 
						|
	`:SSHLog() [E] ssh: Push to create is not enabled for users. ServCommand failed: internal API error response, status=403`,
 | 
						|
	// TestGit/SSH/PushCreate
 | 
						|
	`:SSHLog() [E] ssh: Cannot find repository: user2/repo-tmp-push-create-ssh. ServCommand failed: internal API error response, status=404`,
 | 
						|
	// TestGit/SSH/PushCreate
 | 
						|
	`:SSHLog() [E] ssh: Invalid repo name. Invalid repo name: invalid/repo-tmp-push-create-ssh`,
 | 
						|
	// TestIssueReaction
 | 
						|
	`:ChangeIssueReaction() [E] ChangeIssueReaction: '8ball' is not an allowed reaction`,
 | 
						|
	// TestIssuePinMove
 | 
						|
	`:IssuePinMove() [E] Issue does not belong to this repository`,
 | 
						|
	// TestLinksLogin
 | 
						|
	`:GetIssuesAllCommitStatus() [E] getAllCommitStatus: can't get commit statuses of pull [6]: object does not exist [id: refs/pull/2/head, rel_path: ]`,
 | 
						|
	// TestLinksLogin
 | 
						|
	`:GetIssuesAllCommitStatus() [E] getAllCommitStatus: can't get commit statuses of pull [6]: object does not exist [id: refs/pull/2/head, rel_path: ]`,
 | 
						|
	// TestLinksLogin
 | 
						|
	`:GetIssuesAllCommitStatus() [E] getAllCommitStatus: can't get commit statuses of pull [6]: object does not exist [id: refs/pull/2/head, rel_path: ]`,
 | 
						|
	// TestLinksLogin
 | 
						|
	`:GetIssuesAllCommitStatus() [E] Cannot open git repository <Repository 23:org17/big_test_public_4> 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
 | 
						|
	`: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
 | 
						|
	`:handler() [E] Run task failed: error while listing issues: token does not have at least one of required scope(s): [read:issue]`,
 | 
						|
	// TestMirrorPush
 | 
						|
	`:GetInfoRefs() [E] fork/exec /usr/bin/git: no such file or directory -`,
 | 
						|
 | 
						|
	// TestOrgMembers
 | 
						|
	`:loadOrganizationOwners() [E] Organization does not have owner team: 25`,
 | 
						|
	// TestOrgMembers
 | 
						|
	`:loadOrganizationOwners() [E] Organization does not have owner team: 25`,
 | 
						|
	// TestOrgMembers
 | 
						|
	`:loadOrganizationOwners() [E] Organization does not have owner team: 25`,
 | 
						|
	// TestRecentlyPushed/unrelated_branches_are_not_shown
 | 
						|
	`:SyncRepoBranches() [E] OpenRepository[user30/repo50]: %!w(*errors.errorString=&{no such file or directory})`,
 | 
						|
	// TestRecentlyPushed/unrelated_branches_are_not_shown
 | 
						|
	`:handlerBranchSync() [E] syncRepoBranches [50] failed: no such file or directory`,
 | 
						|
	// TestRecentlyPushed/unrelated_branches_are_not_shown
 | 
						|
	`:SyncRepoBranches() [E] OpenRepository[user30/repo51]: %!w(*errors.errorString=&{no such file or directory})`,
 | 
						|
	// TestRecentlyPushed/unrelated_branches_are_not_shown
 | 
						|
	`:handlerBranchSync() [E] syncRepoBranches [51] failed: no such file or directory`,
 | 
						|
	// TestRecentlyPushed/unrelated_branches_are_not_shown
 | 
						|
	`:SyncRepoBranches() [E] OpenRepository[user2/scoped_label]: %!w(*errors.errorString=&{no such file or directory})`,
 | 
						|
	// TestRecentlyPushed/unrelated_branches_are_not_shown
 | 
						|
	`: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
 | 
						|
	`:SyncRepoBranches() [E] OpenRepository[user30/repo50]: %!w(*errors.errorString=&{no such file or directory})`,
 | 
						|
	// TestDatabaseMissingABranch
 | 
						|
	`:handlerBranchSync() [E] syncRepoBranches [50] failed: no such file or directory`,
 | 
						|
	// TestDatabaseMissingABranch
 | 
						|
	`:SyncRepoBranches() [E] OpenRepository[user30/repo51]: %!w(*errors.errorString=&{no such file or directory})`,
 | 
						|
	// TestDatabaseMissingABranch
 | 
						|
	`:handlerBranchSync() [E] syncRepoBranches [51] failed: no such file or directory`,
 | 
						|
	// TestDatabaseMissingABranch
 | 
						|
	`:SyncRepoBranches() [E] OpenRepository[user2/scoped_label]: %!w(*errors.errorString=&{no such file or directory})`,
 | 
						|
	// TestDatabaseMissingABranch
 | 
						|
	`: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'
 | 
						|
		- fatal: bad revision 'master...refs/heads/will-be-missing'`,
 | 
						|
	// TestDatabaseMissingABranch
 | 
						|
	`:SyncRepoBranches() [E] OpenRepository[user30/repo50]: %!w(*errors.errorString=&{no such file or directory})`,
 | 
						|
	// TestDatabaseMissingABranch
 | 
						|
	`:handlerBranchSync() [E] syncRepoBranches [50] failed: no such file or directory`,
 | 
						|
	// TestDatabaseMissingABranch
 | 
						|
	`:SyncRepoBranches() [E] OpenRepository[user30/repo51]: %!w(*errors.errorString=&{no such file or directory})`,
 | 
						|
	// TestDatabaseMissingABranch
 | 
						|
	`:handlerBranchSync() [E] syncRepoBranches [51] failed: no such file or directory`,
 | 
						|
	// TestDatabaseMissingABranch
 | 
						|
	`:SyncRepoBranches() [E] OpenRepository[user2/scoped_label]: %!w(*errors.errorString=&{no such file or directory})`,
 | 
						|
	// TestDatabaseMissingABranch
 | 
						|
	`: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
 | 
						|
	`:SSHLog() [E] ssh: Tag v-2 is protected. HookPreReceive(last) failed: internal API error response, status=403`,
 | 
						|
	// TestMarkDownReadmeImage
 | 
						|
	`:checkOutdatedBranch() [E] GetBranch: branch does not exist [repo_id: 1 name: home-md-img-check]`,
 | 
						|
	// TestMarkDownReadmeImage
 | 
						|
	`:checkOutdatedBranch() [E] GetBranch: branch does not exist [repo_id: 1 name: home-md-img-check]`,
 | 
						|
	// TestMarkDownReadmeImageSubfolder
 | 
						|
	`:checkOutdatedBranch() [E] GetBranch: branch does not exist [repo_id: 1 name: sub-home-md-img-check]`,
 | 
						|
	// TestMarkDownReadmeImageSubfolder
 | 
						|
	`: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"`,
 | 
						|
 | 
						|
	// TestDatabaseCollation
 | 
						|
	`[E] [Error SQL Query] INSERT INTO test_collation_tbl (txt) VALUES ('main') []`,
 | 
						|
}
 | 
						|
 | 
						|
func (w *testLoggerWriterCloser) recordError(msg string) {
 | 
						|
	for _, s := range ignoredErrorMessage {
 | 
						|
		if strings.Contains(msg, s) {
 | 
						|
			return
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	w.Lock()
 | 
						|
	defer w.Unlock()
 | 
						|
 | 
						|
	err := w.err
 | 
						|
	if len(w.errs) > 0 {
 | 
						|
		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 {
 | 
						|
		w.errs[len(w.errs)-1] = err
 | 
						|
	} else {
 | 
						|
		w.err = err
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (w *testLoggerWriterCloser) printMsg(msg string) {
 | 
						|
	// There was a data race problem: the logger system could still try to output logs after the runner is finished.
 | 
						|
	// So we must ensure that the "t" in stack is still valid.
 | 
						|
	w.RLock()
 | 
						|
	defer w.RUnlock()
 | 
						|
 | 
						|
	if len(w.t) > 0 {
 | 
						|
		t := w.t[len(w.t)-1]
 | 
						|
		t.Log(msg)
 | 
						|
	} else {
 | 
						|
		// if there is no running test, the log message should be outputted to console, to avoid losing important information.
 | 
						|
		// the "???" prefix is used to match the "===" and "+++" in PrintCurrentTest
 | 
						|
		fmt.Fprintln(os.Stdout, "??? [TestLogger]", msg)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (w *testLoggerWriterCloser) popT() error {
 | 
						|
	w.Lock()
 | 
						|
	defer w.Unlock()
 | 
						|
 | 
						|
	if len(w.t) > 0 {
 | 
						|
		w.t = w.t[:len(w.t)-1]
 | 
						|
		err := w.errs[len(w.errs)-1]
 | 
						|
		w.errs = w.errs[:len(w.errs)-1]
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	return w.err
 | 
						|
}
 | 
						|
 | 
						|
func (w *testLoggerWriterCloser) Reset() error {
 | 
						|
	w.Lock()
 | 
						|
	if len(w.t) > 0 {
 | 
						|
		for _, t := range w.t {
 | 
						|
			if t == nil {
 | 
						|
				continue
 | 
						|
			}
 | 
						|
			_, _ = fmt.Fprintf(os.Stdout, "Unclosed logger writer in test: %s", t.Name())
 | 
						|
			t.Errorf("Unclosed logger writer in test: %s", t.Name())
 | 
						|
		}
 | 
						|
		w.t = nil
 | 
						|
		w.errs = nil
 | 
						|
	}
 | 
						|
	err := w.err
 | 
						|
	w.err = nil
 | 
						|
	w.Unlock()
 | 
						|
	return err
 | 
						|
}
 | 
						|
 | 
						|
// PrintCurrentTest prints the current test to os.Stdout
 | 
						|
func PrintCurrentTest(t testing.TB, skip ...int) func() {
 | 
						|
	t.Helper()
 | 
						|
	start := time.Now()
 | 
						|
	actualSkip := 1
 | 
						|
	if len(skip) > 0 {
 | 
						|
		actualSkip = skip[0] + 1
 | 
						|
	}
 | 
						|
	_, filename, line, _ := runtime.Caller(actualSkip)
 | 
						|
 | 
						|
	if log.CanColorStdout {
 | 
						|
		_, _ = fmt.Fprintf(os.Stdout, "=== %s (%s:%d)\n", fmt.Formatter(log.NewColoredValue(t.Name())), strings.TrimPrefix(filename, prefix), line)
 | 
						|
	} else {
 | 
						|
		_, _ = fmt.Fprintf(os.Stdout, "=== %s (%s:%d)\n", t.Name(), strings.TrimPrefix(filename, prefix), line)
 | 
						|
	}
 | 
						|
	WriterCloser.pushT(t)
 | 
						|
	return func() {
 | 
						|
		took := time.Since(start)
 | 
						|
		if took > SlowTest {
 | 
						|
			if log.CanColorStdout {
 | 
						|
				_, _ = fmt.Fprintf(os.Stdout, "+++ %s is a slow test (took %v)\n", fmt.Formatter(log.NewColoredValue(t.Name(), log.Bold, log.FgYellow)), fmt.Formatter(log.NewColoredValue(took, log.Bold, log.FgYellow)))
 | 
						|
			} else {
 | 
						|
				_, _ = fmt.Fprintf(os.Stdout, "+++ %s is a slow test (took %v)\n", t.Name(), took)
 | 
						|
			}
 | 
						|
		}
 | 
						|
		timer := time.AfterFunc(SlowFlush, func() {
 | 
						|
			if log.CanColorStdout {
 | 
						|
				_, _ = fmt.Fprintf(os.Stdout, "+++ %s ... still flushing after %v ...\n", fmt.Formatter(log.NewColoredValue(t.Name(), log.Bold, log.FgRed)), SlowFlush)
 | 
						|
			} else {
 | 
						|
				_, _ = fmt.Fprintf(os.Stdout, "+++ %s ... still flushing after %v ...\n", t.Name(), SlowFlush)
 | 
						|
			}
 | 
						|
		})
 | 
						|
		if err := queue.GetManager().FlushAll(context.Background(), time.Minute); err != nil {
 | 
						|
			t.Errorf("Flushing queues failed with error %v", err)
 | 
						|
		}
 | 
						|
		timer.Stop()
 | 
						|
		flushTook := time.Since(start) - took
 | 
						|
		if flushTook > SlowFlush {
 | 
						|
			if log.CanColorStdout {
 | 
						|
				_, _ = fmt.Fprintf(os.Stdout, "+++ %s had a slow clean-up flush (took %v)\n", fmt.Formatter(log.NewColoredValue(t.Name(), log.Bold, log.FgRed)), fmt.Formatter(log.NewColoredValue(flushTook, log.Bold, log.FgRed)))
 | 
						|
			} else {
 | 
						|
				_, _ = fmt.Fprintf(os.Stdout, "+++ %s had a slow clean-up flush (took %v)\n", t.Name(), flushTook)
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		if err := WriterCloser.popT(); err != nil {
 | 
						|
			// disable test failure for now (too flacky)
 | 
						|
			_, _ = fmt.Fprintf(os.Stdout, "testlogger.go:recordError() FATAL ERROR: log.Error has been called: %v", err)
 | 
						|
			// t.Errorf("testlogger.go:recordError() FATAL ERROR: log.Error has been called: %v", err)
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// Printf takes a format and args and prints the string to os.Stdout
 | 
						|
func Printf(format string, args ...any) {
 | 
						|
	if log.CanColorStdout {
 | 
						|
		for i := 0; i < len(args); i++ {
 | 
						|
			args[i] = log.NewColoredValue(args[i])
 | 
						|
		}
 | 
						|
	}
 | 
						|
	_, _ = fmt.Fprintf(os.Stdout, "\t"+format, args...)
 | 
						|
}
 | 
						|
 | 
						|
// NewTestLoggerWriter creates a TestLogEventWriter as a log.LoggerProvider
 | 
						|
func NewTestLoggerWriter(name string, mode log.WriterMode) log.EventWriter {
 | 
						|
	w := &TestLogEventWriter{}
 | 
						|
	w.base = log.NewEventWriterBase(name, "test-log-writer", mode)
 | 
						|
	w.writer = WriterCloser
 | 
						|
	return w
 | 
						|
}
 | 
						|
 | 
						|
// TestLogEventWriter is a logger which will write to the testing log
 | 
						|
type TestLogEventWriter struct {
 | 
						|
	base   *log.EventWriterBaseImpl
 | 
						|
	writer *testLoggerWriterCloser
 | 
						|
}
 | 
						|
 | 
						|
// Base implements log.EventWriter.
 | 
						|
func (t *TestLogEventWriter) Base() *log.EventWriterBaseImpl {
 | 
						|
	return t.base
 | 
						|
}
 | 
						|
 | 
						|
// GetLevel implements log.EventWriter.
 | 
						|
func (t *TestLogEventWriter) GetLevel() log.Level {
 | 
						|
	return t.base.GetLevel()
 | 
						|
}
 | 
						|
 | 
						|
// GetWriterName implements log.EventWriter.
 | 
						|
func (t *TestLogEventWriter) GetWriterName() string {
 | 
						|
	return t.base.GetWriterName()
 | 
						|
}
 | 
						|
 | 
						|
// GetWriterType implements log.EventWriter.
 | 
						|
func (t *TestLogEventWriter) GetWriterType() string {
 | 
						|
	return t.base.GetWriterType()
 | 
						|
}
 | 
						|
 | 
						|
// Run implements log.EventWriter.
 | 
						|
func (t *TestLogEventWriter) Run(ctx context.Context) {
 | 
						|
	for {
 | 
						|
		select {
 | 
						|
		case <-ctx.Done():
 | 
						|
			return
 | 
						|
		case event, ok := <-t.base.Queue:
 | 
						|
			if !ok {
 | 
						|
				return
 | 
						|
			}
 | 
						|
 | 
						|
			var errorMsg string
 | 
						|
 | 
						|
			switch msg := event.Msg.(type) {
 | 
						|
			case string:
 | 
						|
				errorMsg = msg
 | 
						|
			case []byte:
 | 
						|
				errorMsg = string(msg)
 | 
						|
			case io.WriterTo:
 | 
						|
				var buf bytes.Buffer
 | 
						|
				if _, err := msg.WriteTo(&buf); err != nil {
 | 
						|
					panic(err)
 | 
						|
				}
 | 
						|
				errorMsg = buf.String()
 | 
						|
			default:
 | 
						|
				errorMsg = fmt.Sprint(msg)
 | 
						|
			}
 | 
						|
			t.writer.Log(event.Origin.Level, errorMsg)
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func init() {
 | 
						|
	const relFilePath = "modules/testlogger/testlogger.go"
 | 
						|
	_, filename, _, _ := runtime.Caller(0)
 | 
						|
	if !strings.HasSuffix(filename, relFilePath) {
 | 
						|
		panic("source code file path doesn't match expected: " + relFilePath)
 | 
						|
	}
 | 
						|
	prefix = strings.TrimSuffix(filename, relFilePath)
 | 
						|
}
 |