Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitaly.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavlo Strokov <pstrokov@gitlab.com>2021-10-07 11:31:25 +0300
committerPavlo Strokov <pstrokov@gitlab.com>2021-10-07 11:31:25 +0300
commit043bb6e66fa839296d76d5105756a005b2613808 (patch)
treec090b62ec8f4e2b1b1ae1b53f43975b24fb79093
parentefb14ad0a5a0b23ebd96d3216c07c135258fd24e (diff)
parent9ef46dc05bbe2ef39838ec973a2e8cf01252d919 (diff)
Merge branch 'pks-testhelper-goroutine-leakage' into 'master'
testhelper: Enable Goroutine leak checks by default Closes #3790 See merge request gitlab-org/gitaly!3909
-rw-r--r--STYLE.md20
-rw-r--r--client/client_test.go10
-rw-r--r--cmd/gitaly-backup/create.go6
-rw-r--r--cmd/gitaly-backup/restore.go6
-rw-r--r--cmd/gitaly-backup/testhelper_test.go12
-rw-r--r--cmd/gitaly-git2go/conflicts/conflicts_test.go10
-rw-r--r--cmd/gitaly-git2go/main_test.go10
-rw-r--r--cmd/gitaly-hooks/hooks_test.go9
-rw-r--r--cmd/gitaly-lfs-smudge/lfs_smudge_test.go10
-rw-r--r--cmd/gitaly-ssh/testhelper_test.go12
-rw-r--r--cmd/praefect/main.go3
-rw-r--r--cmd/praefect/main_test.go10
-rw-r--r--cmd/praefect/subcmd_track_repository_test.go1
-rw-r--r--internal/backup/backup.go4
-rw-r--r--internal/backup/backup_test.go10
-rw-r--r--internal/backup/testhelper_test.go14
-rw-r--r--internal/bootstrap/bootstrap.go2
-rw-r--r--internal/bootstrap/bootstrap_test.go43
-rw-r--r--internal/bootstrap/testhelper_test.go9
-rw-r--r--internal/cache/diskcache.go5
-rw-r--r--internal/cache/testhelper_test.go10
-rw-r--r--internal/cache/walker.go28
-rw-r--r--internal/cache/walker_test.go2
-rw-r--r--internal/cgroups/cgroups_linux_test.go12
-rw-r--r--internal/command/command.go24
-rw-r--r--internal/command/command_test.go55
-rw-r--r--internal/command/commandcounter/counter.go25
-rw-r--r--internal/command/stats_test.go12
-rw-r--r--internal/dontpanic/retry.go56
-rw-r--r--internal/dontpanic/retry_test.go4
-rw-r--r--internal/dontpanic/testhelper_test.go10
-rw-r--r--internal/git/catfile/testhelper_test.go14
-rw-r--r--internal/git/gitpipe/testhelper_test.go12
-rw-r--r--internal/git/gittest/commit_test.go2
-rw-r--r--internal/git/gittest/testhelper_test.go9
-rw-r--r--internal/git/helper_test.go10
-rw-r--r--internal/git/housekeeping/testhelper_test.go9
-rw-r--r--internal/git/localrepo/config_test.go5
-rw-r--r--internal/git/localrepo/objects_test.go4
-rw-r--r--internal/git/localrepo/refs_test.go5
-rw-r--r--internal/git/localrepo/remote_test.go5
-rw-r--r--internal/git/localrepo/repo.go4
-rw-r--r--internal/git/localrepo/repo_test.go16
-rw-r--r--internal/git/localrepo/testhelper_test.go10
-rw-r--r--internal/git/objectpool/clone_test.go5
-rw-r--r--internal/git/objectpool/testhelper_test.go14
-rw-r--r--internal/git/packfile/packfile_test.go10
-rw-r--r--internal/git/quarantine/testhelper_test.go12
-rw-r--r--internal/git/remoterepo/helper_test.go10
-rw-r--r--internal/git/remoterepo/repository_test.go1
-rw-r--r--internal/git/stats/testhelper_test.go10
-rw-r--r--internal/git/updateref/updateref_test.go14
-rw-r--r--internal/git2go/commit_test.go10
-rw-r--r--internal/gitaly/config/testhelper_test.go10
-rw-r--r--internal/gitaly/hook/testhelper_test.go10
-rw-r--r--internal/gitaly/linguist/linguist_test.go10
-rw-r--r--internal/gitaly/maintenance/main_test.go10
-rw-r--r--internal/gitaly/maintenance/optimize_test.go14
-rw-r--r--internal/gitaly/rubyserver/testhelper_test.go12
-rw-r--r--internal/gitaly/server/auth_test.go12
-rw-r--r--internal/gitaly/server/server_factory_test.go4
-rw-r--r--internal/gitaly/service/blob/testhelper_test.go12
-rw-r--r--internal/gitaly/service/cleanup/testhelper_test.go10
-rw-r--r--internal/gitaly/service/commit/testhelper_test.go10
-rw-r--r--internal/gitaly/service/conflicts/server.go18
-rw-r--r--internal/gitaly/service/conflicts/testhelper_test.go33
-rw-r--r--internal/gitaly/service/diff/testhelper_test.go10
-rw-r--r--internal/gitaly/service/hook/testhelper_test.go10
-rw-r--r--internal/gitaly/service/internalgitaly/testhelper_test.go10
-rw-r--r--internal/gitaly/service/namespace/namespace_test.go11
-rw-r--r--internal/gitaly/service/objectpool/fetch_into_object_pool_test.go5
-rw-r--r--internal/gitaly/service/objectpool/testhelper_test.go13
-rw-r--r--internal/gitaly/service/operations/apply_patch_test.go5
-rw-r--r--internal/gitaly/service/operations/testhelper_test.go18
-rw-r--r--internal/gitaly/service/ref/find_all_tags_test.go7
-rw-r--r--internal/gitaly/service/ref/refs_test.go2
-rw-r--r--internal/gitaly/service/ref/testhelper_test.go21
-rw-r--r--internal/gitaly/service/remote/server.go6
-rw-r--r--internal/gitaly/service/remote/testhelper_test.go13
-rw-r--r--internal/gitaly/service/remote/update_remote_mirror_test.go6
-rw-r--r--internal/gitaly/service/repository/apply_gitattributes_test.go1
-rw-r--r--internal/gitaly/service/repository/cleanup_test.go5
-rw-r--r--internal/gitaly/service/repository/clone_from_pool_internal_test.go4
-rw-r--r--internal/gitaly/service/repository/clone_from_pool_test.go3
-rw-r--r--internal/gitaly/service/repository/fetch_bundle_test.go1
-rw-r--r--internal/gitaly/service/repository/fetch_remote_test.go1
-rw-r--r--internal/gitaly/service/repository/fork_test.go12
-rw-r--r--internal/gitaly/service/repository/search_files_test.go17
-rw-r--r--internal/gitaly/service/repository/server.go16
-rw-r--r--internal/gitaly/service/repository/snapshot_test.go1
-rw-r--r--internal/gitaly/service/repository/testhelper_test.go13
-rw-r--r--internal/gitaly/service/server/server_test.go10
-rw-r--r--internal/gitaly/service/setup/register.go3
-rw-r--r--internal/gitaly/service/smarthttp/inforefs_test.go3
-rw-r--r--internal/gitaly/service/smarthttp/testhelper_test.go12
-rw-r--r--internal/gitaly/service/ssh/testhelper_test.go12
-rw-r--r--internal/gitaly/service/wiki/testhelper_test.go29
-rw-r--r--internal/gitaly/transaction/testhelper_test.go12
-rw-r--r--internal/gitalyssh/testhelper_test.go10
-rw-r--r--internal/gitlab/testhelper_test.go6
-rw-r--r--internal/helper/chunk/chunker_test.go10
-rw-r--r--internal/helper/repo_test.go10
-rw-r--r--internal/middleware/commandstatshandler/commandstatshandler_test.go11
-rw-r--r--internal/middleware/limithandler/limithandler_test.go10
-rw-r--r--internal/praefect/auth_test.go1
-rw-r--r--internal/praefect/coordinator_test.go6
-rw-r--r--internal/praefect/datastore/glsql/postgres.go1
-rw-r--r--internal/praefect/grpc-proxy/proxy/handler_ext_test.go14
-rw-r--r--internal/praefect/helper_test.go1
-rw-r--r--internal/praefect/info_service_test.go2
-rw-r--r--internal/praefect/middleware/errorhandler_test.go2
-rw-r--r--internal/praefect/middleware/helper_test.go10
-rw-r--r--internal/praefect/nodes/disabled_elector.go3
-rw-r--r--internal/praefect/nodes/init_test.go10
-rw-r--r--internal/praefect/nodes/local_elector.go13
-rw-r--r--internal/praefect/nodes/local_elector_test.go1
-rw-r--r--internal/praefect/nodes/manager.go14
-rw-r--r--internal/praefect/nodes/manager_test.go7
-rw-r--r--internal/praefect/nodes/sql_elector.go12
-rw-r--r--internal/praefect/nodes/sql_elector_test.go5
-rw-r--r--internal/praefect/replicator_pg_test.go1
-rw-r--r--internal/praefect/replicator_test.go16
-rw-r--r--internal/praefect/repocleaner/init_test.go10
-rw-r--r--internal/praefect/repository_exists_test.go1
-rw-r--r--internal/praefect/server_factory_test.go1
-rw-r--r--internal/praefect/server_test.go5
-rw-r--r--internal/safe/main_test.go10
-rw-r--r--internal/streamcache/cache.go15
-rw-r--r--internal/streamcache/cache_test.go39
-rw-r--r--internal/streamcache/filestore.go15
-rw-r--r--internal/streamcache/filestore_test.go8
-rw-r--r--internal/streamcache/testhelper_test.go8
-rw-r--r--internal/supervisor/monitor.go6
-rw-r--r--internal/supervisor/supervisor_test.go54
-rw-r--r--internal/tempdir/testhelper_test.go11
-rw-r--r--internal/testhelper/configure.go88
-rw-r--r--internal/testhelper/leakage.go99
-rw-r--r--internal/testhelper/testhelper.go67
-rw-r--r--internal/testhelper/testserver/gitaly.go1
-rw-r--r--internal/transaction/voting/testhelper_test.go12
140 files changed, 752 insertions, 966 deletions
diff --git a/STYLE.md b/STYLE.md
index a67515d6a..e663c397a 100644
--- a/STYLE.md
+++ b/STYLE.md
@@ -238,22 +238,10 @@ importantly, this includes any calls to `log.Fatal()` and related functions.
### Common setup
-When all tests require a common setup, we use the `TestMain()` function for
-this. `TestMain()` must call `os.Exit()` to indicate whether any tests failed.
-As this will cause deferred function calls to not be processed, we use the
-following pattern:
-
-```
-func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
-}
-```
+The `TestMain()` function shouldn't do any package-specific setup. Instead, all
+tests are supposed to set up required state as part of the tests themselves. All
+`TestMain()` functions must call `testhelper.Run()` though, which performs the
+setup of global state required for tests.
## Black box and white box testing
diff --git a/client/client_test.go b/client/client_test.go
index 6414626c1..e8083a74e 100644
--- a/client/client_test.go
+++ b/client/client_test.go
@@ -1,19 +1,11 @@
package client
import (
- "os"
"testing"
"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper"
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
diff --git a/cmd/gitaly-backup/create.go b/cmd/gitaly-backup/create.go
index 9dae3d4a5..0ceac7d8e 100644
--- a/cmd/gitaly-backup/create.go
+++ b/cmd/gitaly-backup/create.go
@@ -9,6 +9,7 @@ import (
"runtime"
log "github.com/sirupsen/logrus"
+ "gitlab.com/gitlab-org/gitaly/v14/client"
"gitlab.com/gitlab-org/gitaly/v14/internal/backup"
"gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/storage"
"gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb"
@@ -46,7 +47,10 @@ func (cmd *createSubcommand) Run(ctx context.Context, stdin io.Reader, stdout io
return fmt.Errorf("create: resolve locator: %w", err)
}
- manager := backup.NewManager(sink, locator)
+ pool := client.NewPool()
+ defer pool.Close()
+
+ manager := backup.NewManager(sink, locator, pool)
var pipeline backup.Pipeline
pipeline = backup.NewLoggingPipeline(log.StandardLogger())
diff --git a/cmd/gitaly-backup/restore.go b/cmd/gitaly-backup/restore.go
index 695e98cfb..6e119ba92 100644
--- a/cmd/gitaly-backup/restore.go
+++ b/cmd/gitaly-backup/restore.go
@@ -10,6 +10,7 @@ import (
"runtime"
log "github.com/sirupsen/logrus"
+ "gitlab.com/gitlab-org/gitaly/v14/client"
"gitlab.com/gitlab-org/gitaly/v14/internal/backup"
"gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/storage"
"gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb"
@@ -48,7 +49,10 @@ func (cmd *restoreSubcommand) Run(ctx context.Context, stdin io.Reader, stdout i
return fmt.Errorf("restore: resolve locator: %w", err)
}
- manager := backup.NewManager(sink, locator)
+ pool := client.NewPool()
+ defer pool.Close()
+
+ manager := backup.NewManager(sink, locator, pool)
var pipeline backup.Pipeline
pipeline = backup.NewLoggingPipeline(log.StandardLogger())
diff --git a/cmd/gitaly-backup/testhelper_test.go b/cmd/gitaly-backup/testhelper_test.go
index 7fd4db4d4..64d8edae5 100644
--- a/cmd/gitaly-backup/testhelper_test.go
+++ b/cmd/gitaly-backup/testhelper_test.go
@@ -1,21 +1,11 @@
package main
import (
- "os"
"testing"
"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper"
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
-
- cleanup := testhelper.Configure()
- defer cleanup()
-
- return m.Run()
+ testhelper.Run(m)
}
diff --git a/cmd/gitaly-git2go/conflicts/conflicts_test.go b/cmd/gitaly-git2go/conflicts/conflicts_test.go
index 34b28bdf7..13a981365 100644
--- a/cmd/gitaly-git2go/conflicts/conflicts_test.go
+++ b/cmd/gitaly-git2go/conflicts/conflicts_test.go
@@ -4,7 +4,6 @@
package conflicts
import (
- "os"
"testing"
git "github.com/libgit2/git2go/v31"
@@ -17,14 +16,7 @@ import (
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
func TestConflicts(t *testing.T) {
diff --git a/cmd/gitaly-git2go/main_test.go b/cmd/gitaly-git2go/main_test.go
index 75cfb525c..2113b2335 100644
--- a/cmd/gitaly-git2go/main_test.go
+++ b/cmd/gitaly-git2go/main_test.go
@@ -4,19 +4,11 @@
package main
import (
- "os"
"testing"
"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper"
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
diff --git a/cmd/gitaly-hooks/hooks_test.go b/cmd/gitaly-hooks/hooks_test.go
index 93d980bdd..811c6f6d8 100644
--- a/cmd/gitaly-hooks/hooks_test.go
+++ b/cmd/gitaly-hooks/hooks_test.go
@@ -96,14 +96,7 @@ func envForHooks(t testing.TB, ctx context.Context, cfg config.Cfg, repo *gitaly
}
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
func TestHooksPrePostWithSymlinkedStoragePath(t *testing.T) {
diff --git a/cmd/gitaly-lfs-smudge/lfs_smudge_test.go b/cmd/gitaly-lfs-smudge/lfs_smudge_test.go
index 5136587d9..88f4c661f 100644
--- a/cmd/gitaly-lfs-smudge/lfs_smudge_test.go
+++ b/cmd/gitaly-lfs-smudge/lfs_smudge_test.go
@@ -4,7 +4,6 @@ import (
"bytes"
"encoding/json"
"net/http"
- "os"
"path/filepath"
"strings"
"testing"
@@ -52,14 +51,7 @@ type mapConfig struct {
}
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
func (m *mapConfig) Get(key string) string {
diff --git a/cmd/gitaly-ssh/testhelper_test.go b/cmd/gitaly-ssh/testhelper_test.go
index 7fd4db4d4..64d8edae5 100644
--- a/cmd/gitaly-ssh/testhelper_test.go
+++ b/cmd/gitaly-ssh/testhelper_test.go
@@ -1,21 +1,11 @@
package main
import (
- "os"
"testing"
"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper"
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
-
- cleanup := testhelper.Configure()
- defer cleanup()
-
- return m.Run()
+ testhelper.Run(m)
}
diff --git a/cmd/praefect/main.go b/cmd/praefect/main.go
index 8b56cab28..44a0981f0 100644
--- a/cmd/praefect/main.go
+++ b/cmd/praefect/main.go
@@ -340,6 +340,7 @@ func run(cfgs []starter.Config, conf config.Config) error {
nodeManager = nodeMgr
nodeMgr.Start(conf.Failover.BootstrapInterval.Duration(), conf.Failover.MonitorInterval.Duration())
+ defer nodeMgr.Stop()
}
logger.Infof("election strategy: %q", conf.Failover.ElectionStrategy)
@@ -401,6 +402,8 @@ func run(cfgs []starter.Config, conf config.Config) error {
if err != nil {
return fmt.Errorf("create gRPC server: %w", err)
}
+ defer srv.Stop()
+
b.RegisterStarter(starter.New(cfg, srv))
}
diff --git a/cmd/praefect/main_test.go b/cmd/praefect/main_test.go
index 5fb0619e4..9a4e8949f 100644
--- a/cmd/praefect/main_test.go
+++ b/cmd/praefect/main_test.go
@@ -2,7 +2,6 @@ package main
import (
"errors"
- "os"
"testing"
"github.com/stretchr/testify/assert"
@@ -13,14 +12,7 @@ import (
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
func TestNoConfigFlag(t *testing.T) {
diff --git a/cmd/praefect/subcmd_track_repository_test.go b/cmd/praefect/subcmd_track_repository_test.go
index bdf29ce68..c03329eb1 100644
--- a/cmd/praefect/subcmd_track_repository_test.go
+++ b/cmd/praefect/subcmd_track_repository_test.go
@@ -154,6 +154,7 @@ func TestAddRepository_Exec(t *testing.T) {
nodeMgr, err := nodes.NewManager(testhelper.DiscardTestEntry(t), addCmdConf, db.DB, nil, promtest.NewMockHistogramVec(), protoregistry.GitalyProtoPreregistered, nil, nil, nil)
require.NoError(t, err)
nodeMgr.Start(0, time.Hour)
+ defer nodeMgr.Stop()
relativePath := fmt.Sprintf("path/to/test/repo_%s", tn)
repoDS := datastore.NewPostgresRepositoryStore(db, conf.StorageNames())
diff --git a/internal/backup/backup.go b/internal/backup/backup.go
index c59591b59..9543a4483 100644
--- a/internal/backup/backup.go
+++ b/internal/backup/backup.go
@@ -122,10 +122,10 @@ type Manager struct {
}
// NewManager creates and returns initialized *Manager instance.
-func NewManager(sink Sink, locator Locator) *Manager {
+func NewManager(sink Sink, locator Locator, pool *client.Pool) *Manager {
return &Manager{
sink: sink,
- conns: client.NewPool(),
+ conns: pool,
locator: locator,
backupID: time.Now().UTC().Format("20060102150405"),
}
diff --git a/internal/backup/backup_test.go b/internal/backup/backup_test.go
index ab8304965..059f9267c 100644
--- a/internal/backup/backup_test.go
+++ b/internal/backup/backup_test.go
@@ -89,7 +89,10 @@ func TestManager_Create(t *testing.T) {
ctx, cancel := testhelper.Context()
defer cancel()
- fsBackup := NewManager(NewFilesystemSink(path), LegacyLocator{})
+ pool := client.NewPool()
+ defer testhelper.MustClose(t, pool)
+
+ fsBackup := NewManager(NewFilesystemSink(path), LegacyLocator{}, pool)
err := fsBackup.Create(ctx, &CreateRequest{
Server: storage.ServerInfo{Address: gitalyAddr, Token: cfg.Auth.Token},
Repository: tc.repo,
@@ -351,11 +354,14 @@ func testManagerRestore(t *testing.T, cfg config.Cfg, gitalyAddr string) {
repo, bundles := tc.setup(t)
repoPath := filepath.Join(cfg.Storages[0].Path, repo.RelativePath)
+ pool := client.NewPool()
+ defer testhelper.MustClose(t, pool)
+
sink := NewFilesystemSink(path)
locator, err := ResolveLocator(locatorName, sink)
require.NoError(t, err)
- fsBackup := NewManager(sink, locator)
+ fsBackup := NewManager(sink, locator, pool)
err = fsBackup.Restore(ctx, &RestoreRequest{
Server: storage.ServerInfo{Address: gitalyAddr, Token: cfg.Auth.Token},
Repository: repo,
diff --git a/internal/backup/testhelper_test.go b/internal/backup/testhelper_test.go
index 83b1e76cd..b900cb5d5 100644
--- a/internal/backup/testhelper_test.go
+++ b/internal/backup/testhelper_test.go
@@ -1,21 +1,13 @@
package backup
import (
- "os"
"testing"
"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper"
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
-
- cleanup := testhelper.Configure()
- defer cleanup()
-
- return m.Run()
+ // gocloud.dev/blob leaks the HTTP connection even if we make sure to close all buckets.
+ //nolint:staticcheck
+ testhelper.Run(m, testhelper.WithDisabledGoroutineChecker())
}
diff --git a/internal/bootstrap/bootstrap.go b/internal/bootstrap/bootstrap.go
index ef414184d..95e43aa10 100644
--- a/internal/bootstrap/bootstrap.go
+++ b/internal/bootstrap/bootstrap.go
@@ -38,6 +38,7 @@ type upgrader interface {
HasParent() bool
Ready() error
Upgrade() error
+ Stop()
}
// New performs tableflip initialization
@@ -172,6 +173,7 @@ func (b *Bootstrap) Wait(gracefulTimeout time.Duration) error {
err = fmt.Errorf("graceful upgrade: %v", waitError)
case s := <-immediateShutdown:
err = fmt.Errorf("received signal %q", s)
+ b.upgrader.Stop()
case err = <-b.errChan:
}
diff --git a/internal/bootstrap/bootstrap_test.go b/internal/bootstrap/bootstrap_test.go
index 8b870395c..1fb6c3485 100644
--- a/internal/bootstrap/bootstrap_test.go
+++ b/internal/bootstrap/bootstrap_test.go
@@ -26,6 +26,8 @@ func (m *mockUpgrader) Exit() <-chan struct{} {
return m.exit
}
+func (m *mockUpgrader) Stop() {}
+
func (m *mockUpgrader) HasParent() bool {
return m.hasParent
}
@@ -104,7 +106,10 @@ func waitWithTimeout(t *testing.T, waitCh <-chan error, timeout time.Duration) e
}
func TestImmediateTerminationOnSocketError(t *testing.T) {
- b, server := makeBootstrap(t)
+ ctx, cancel := testhelper.Context()
+ defer cancel()
+
+ b, server := makeBootstrap(t, ctx)
waitCh := make(chan error)
go func() { waitCh <- b.Wait(2 * time.Second) }()
@@ -119,7 +124,10 @@ func TestImmediateTerminationOnSocketError(t *testing.T) {
func TestImmediateTerminationOnSignal(t *testing.T) {
for _, sig := range []syscall.Signal{syscall.SIGTERM, syscall.SIGINT} {
t.Run(sig.String(), func(t *testing.T) {
- b, server := makeBootstrap(t)
+ ctx, cancel := testhelper.Context()
+ defer cancel()
+
+ b, server := makeBootstrap(t, ctx)
done := server.slowRequest(3 * time.Minute)
@@ -146,7 +154,10 @@ func TestImmediateTerminationOnSignal(t *testing.T) {
}
func TestGracefulTerminationStuck(t *testing.T) {
- b, server := makeBootstrap(t)
+ ctx, cancel := testhelper.Context()
+ defer cancel()
+
+ b, server := makeBootstrap(t, ctx)
err := testGracefulUpdate(t, server, b, 3*time.Second, 2*time.Second, nil)
require.Contains(t, err.Error(), "grace period expired")
@@ -158,7 +169,9 @@ func TestGracefulTerminationWithSignals(t *testing.T) {
for _, sig := range []syscall.Signal{syscall.SIGTERM, syscall.SIGINT} {
t.Run(sig.String(), func(t *testing.T) {
- b, server := makeBootstrap(t)
+ ctx, cancel := testhelper.Context()
+ defer cancel()
+ b, server := makeBootstrap(t, ctx)
err := testGracefulUpdate(t, server, b, 1*time.Second, 2*time.Second, func() {
require.NoError(t, self.Signal(sig))
@@ -169,7 +182,9 @@ func TestGracefulTerminationWithSignals(t *testing.T) {
}
func TestGracefulTerminationServerErrors(t *testing.T) {
- b, server := makeBootstrap(t)
+ ctx, cancel := testhelper.Context()
+ defer cancel()
+ b, server := makeBootstrap(t, ctx)
done := make(chan error, 1)
// This is a simulation of receiving a listener error during waitGracePeriod
@@ -192,7 +207,9 @@ func TestGracefulTerminationServerErrors(t *testing.T) {
}
func TestGracefulTermination(t *testing.T) {
- b, server := makeBootstrap(t)
+ ctx, cancel := testhelper.Context()
+ defer cancel()
+ b, server := makeBootstrap(t, ctx)
// Using server.Close we bypass the graceful shutdown faking a completed shutdown
b.StopAction = func() { server.server.Close() }
@@ -202,21 +219,21 @@ func TestGracefulTermination(t *testing.T) {
}
func TestPortReuse(t *testing.T) {
- var addr string
-
b, err := New()
require.NoError(t, err)
l, err := b.listen("tcp", "localhost:")
require.NoError(t, err, "failed to bind")
- addr = l.Addr().String()
+ addr := l.Addr().String()
_, port, err := net.SplitHostPort(addr)
require.NoError(t, err)
l, err = b.listen("tcp", "localhost:"+port)
require.NoError(t, err, "failed to bind")
require.NoError(t, l.Close())
+
+ b.upgrader.Stop()
}
func testGracefulUpdate(t *testing.T, server *testServer, b *Bootstrap, waitTimeout, gracefulWait time.Duration, duringGracePeriodCallback func()) error {
@@ -251,7 +268,7 @@ func testGracefulUpdate(t *testing.T, server *testServer, b *Bootstrap, waitTime
return waitErr
}
-func makeBootstrap(t *testing.T) (*Bootstrap, *testServer) {
+func makeBootstrap(t *testing.T, ctx context.Context) (*Bootstrap, *testServer) {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(200)
@@ -260,12 +277,16 @@ func makeBootstrap(t *testing.T) (*Bootstrap, *testServer) {
sec, err := strconv.Atoi(r.URL.Query().Get("seconds"))
require.NoError(t, err)
- time.Sleep(time.Duration(sec) * time.Second)
+ select {
+ case <-ctx.Done():
+ case <-time.After(time.Duration(sec) * time.Second):
+ }
w.WriteHeader(200)
})
s := http.Server{Handler: mux}
+ t.Cleanup(func() { testhelper.MustClose(t, &s) })
u := &mockUpgrader{exit: make(chan struct{})}
b, err := _new(u, net.Listen, false)
diff --git a/internal/bootstrap/testhelper_test.go b/internal/bootstrap/testhelper_test.go
index baed8d01f..514236bd7 100644
--- a/internal/bootstrap/testhelper_test.go
+++ b/internal/bootstrap/testhelper_test.go
@@ -1,18 +1,11 @@
package bootstrap
import (
- "os"
"testing"
"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper"
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
diff --git a/internal/cache/diskcache.go b/internal/cache/diskcache.go
index 3fb5bf4bb..dffc38ca5 100644
--- a/internal/cache/diskcache.go
+++ b/internal/cache/diskcache.go
@@ -10,6 +10,7 @@ import (
"github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/ctxlogrus"
"github.com/prometheus/client_golang/prometheus"
+ "gitlab.com/gitlab-org/gitaly/v14/internal/dontpanic"
"gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/config"
"gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/storage"
"gitlab.com/gitlab-org/gitaly/v14/internal/safe"
@@ -79,6 +80,9 @@ type DiskCache struct {
af activeFiles
cacheConfig cacheConfig
+ walkersDone chan struct{}
+ walkerLoops []*dontpanic.Forever
+
requestTotals prometheus.Counter
missTotals prometheus.Counter
bytesStoredtotals prometheus.Counter
@@ -107,6 +111,7 @@ func New(cfg config.Cfg, locator storage.Locator, opts ...Option) *DiskCache {
m: map[string]int{},
},
cacheConfig: cacheConfig,
+ walkersDone: make(chan struct{}),
requestTotals: prometheus.NewCounter(
prometheus.CounterOpts{
diff --git a/internal/cache/testhelper_test.go b/internal/cache/testhelper_test.go
index ed9467aae..687ad7d6e 100644
--- a/internal/cache/testhelper_test.go
+++ b/internal/cache/testhelper_test.go
@@ -1,19 +1,11 @@
package cache
import (
- "os"
"testing"
"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper"
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
diff --git a/internal/cache/walker.go b/internal/cache/walker.go
index bfd5fba01..00d990c17 100644
--- a/internal/cache/walker.go
+++ b/internal/cache/walker.go
@@ -98,12 +98,27 @@ func (c *DiskCache) walkLoop(walkPath string) {
logger.Infof("Starting file walker for %s", walkPath)
walkTick := time.NewTicker(cleanWalkFrequency)
- dontpanic.GoForever(time.Minute, func() {
+
+ forever := dontpanic.NewForever(time.Minute)
+ forever.Go(func() {
+ select {
+ case <-c.walkersDone:
+ return
+ default:
+ }
+
if err := c.cleanWalk(walkPath); err != nil {
logger.Error(err)
}
- <-walkTick.C
+
+ select {
+ case <-c.walkersDone:
+ return
+ case <-walkTick.C:
+ }
})
+
+ c.walkerLoops = append(c.walkerLoops, forever)
}
func (c *DiskCache) startCleanWalker(cacheDir, stateDir string) {
@@ -199,3 +214,12 @@ func (c *DiskCache) StartWalkers() error {
return nil
}
+
+// StopWalkers stops all walkers started by StartWalkers.
+func (c *DiskCache) StopWalkers() {
+ close(c.walkersDone)
+ for _, walkerLoop := range c.walkerLoops {
+ walkerLoop.Cancel()
+ }
+ c.walkerLoops = nil
+}
diff --git a/internal/cache/walker_test.go b/internal/cache/walker_test.go
index 87e02d8fa..727e93d04 100644
--- a/internal/cache/walker_test.go
+++ b/internal/cache/walker_test.go
@@ -53,6 +53,7 @@ func TestDiskCacheObjectWalker(t *testing.T) {
cache := New(cfg, locator, withDisabledMoveAndClear())
require.NoError(t, cache.StartWalkers())
+ defer cache.StopWalkers()
pollCountersUntil(t, cache, 4)
@@ -78,6 +79,7 @@ func TestDiskCacheInitialClear(t *testing.T) {
cache := New(cfg, locator, withDisabledWalker())
require.NoError(t, cache.StartWalkers())
+ defer cache.StopWalkers()
require.NoFileExists(t, canary)
}
diff --git a/internal/cgroups/cgroups_linux_test.go b/internal/cgroups/cgroups_linux_test.go
index 7045a8484..9d8267bff 100644
--- a/internal/cgroups/cgroups_linux_test.go
+++ b/internal/cgroups/cgroups_linux_test.go
@@ -1,7 +1,6 @@
package cgroups
import (
- "os"
"testing"
"github.com/stretchr/testify/require"
@@ -10,16 +9,7 @@ import (
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
-
- cleanup := testhelper.Configure()
- defer cleanup()
-
- return m.Run()
+ testhelper.Run(m)
}
func TestNewManager(t *testing.T) {
diff --git a/internal/command/command.go b/internal/command/command.go
index 858c72642..2960487d6 100644
--- a/internal/command/command.go
+++ b/internal/command/command.go
@@ -15,6 +15,7 @@ import (
"github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/ctxlogrus"
"github.com/opentracing/opentracing-go"
"github.com/sirupsen/logrus"
+ "gitlab.com/gitlab-org/gitaly/v14/internal/command/commandcounter"
"gitlab.com/gitlab-org/labkit/tracing"
)
@@ -118,15 +119,6 @@ func (c *Command) Wait() error {
return c.waitError
}
-var wg = &sync.WaitGroup{}
-
-// WaitAllDone waits for all commands started by the command package to
-// finish. This can only be called once in the lifecycle of the current
-// Go process.
-func WaitAllDone() {
- wg.Wait()
-}
-
type contextWithoutDonePanic string
// New creates a Command from an exec.Cmd. On success, the Command
@@ -225,7 +217,7 @@ func New(ctx context.Context, cmd *exec.Cmd, stdin io.Reader, stdout, stderr io.
// The goroutine below is responsible for terminating and reaping the
// process when ctx is canceled.
- wg.Add(1)
+ commandcounter.Increment()
go func() {
<-ctx.Done()
@@ -277,14 +269,14 @@ func (c *Command) wait() {
c.logProcessComplete()
- // This is a bit out-of-place here given that the `wg.Add()` call is in `New()`.
- // But in `New()`, we have to resort waiting on the context being finished until we
+ // This is a bit out-of-place here given that the `commandcounter.Increment()` call is in
+ // `New()`. But in `New()`, we have to resort waiting on the context being finished until we
// would be able to decrement the number of in-flight commands. Given that in some
// cases we detach processes from their initial context such that they run in the
- // background, this would cause us to take longer than necessary to decrease the
- // wait group counter again. So we instead do it here to accelerate the process,
- // even though it's less idiomatic.
- wg.Done()
+ // background, this would cause us to take longer than necessary to decrease the wait group
+ // counter again. So we instead do it here to accelerate the process, even though it's less
+ // idiomatic.
+ commandcounter.Decrement()
}
// ExitStatus will return the exit-code from an error returned by Wait().
diff --git a/internal/command/command_test.go b/internal/command/command_test.go
index c29fba8ed..8f563f4c1 100644
--- a/internal/command/command_test.go
+++ b/internal/command/command_test.go
@@ -5,7 +5,6 @@ import (
"context"
"fmt"
"io"
- "os"
"os/exec"
"regexp"
"strings"
@@ -16,15 +15,15 @@ import (
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "go.uber.org/goleak"
+ "gitlab.com/gitlab-org/gitaly/v14/internal/testhelper"
)
func TestMain(m *testing.M) {
- goleak.VerifyTestMain(m, goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"))
+ testhelper.Run(m)
}
func TestNewCommandExtraEnv(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
+ ctx, cancel := testhelper.Context()
defer cancel()
extraVar := "FOOBAR=123456"
@@ -38,7 +37,7 @@ func TestNewCommandExtraEnv(t *testing.T) {
}
func TestNewCommandExportedEnv(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
+ ctx, cancel := testhelper.Context()
defer cancel()
testCases := []struct {
@@ -113,15 +112,8 @@ func TestNewCommandExportedEnv(t *testing.T) {
for _, tc := range testCases {
t.Run(tc.key, func(t *testing.T) {
- oldValue, exists := os.LookupEnv(tc.key)
- defer func() {
- if !exists {
- require.NoError(t, os.Unsetenv(tc.key))
- return
- }
- require.NoError(t, os.Setenv(tc.key, oldValue))
- }()
- require.NoError(t, os.Setenv(tc.key, tc.value))
+ cleanup := testhelper.ModifyEnvironment(t, tc.key, tc.value)
+ defer cleanup()
buff := &bytes.Buffer{}
cmd, err := New(ctx, exec.Command("/usr/bin/env"), nil, buff, nil)
@@ -135,21 +127,12 @@ func TestNewCommandExportedEnv(t *testing.T) {
}
func TestNewCommandUnexportedEnv(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
+ ctx, cancel := testhelper.Context()
defer cancel()
unexportedEnvKey, unexportedEnvVal := "GITALY_UNEXPORTED_ENV", "foobar"
-
- oldValue, exists := os.LookupEnv(unexportedEnvKey)
- defer func() {
- if !exists {
- require.NoError(t, os.Unsetenv(unexportedEnvKey))
- return
- }
- require.NoError(t, os.Setenv(unexportedEnvKey, oldValue))
- }()
-
- require.NoError(t, os.Setenv(unexportedEnvKey, unexportedEnvVal))
+ cleanup := testhelper.ModifyEnvironment(t, unexportedEnvKey, unexportedEnvVal)
+ defer cleanup()
buff := &bytes.Buffer{}
cmd, err := New(ctx, exec.Command("/usr/bin/env"), nil, buff, nil)
@@ -178,7 +161,7 @@ func TestRejectEmptyContextDone(t *testing.T) {
}
func TestNewCommandTimeout(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
+ ctx, cancel := testhelper.Context()
defer cancel()
defer func(ch chan struct{}, t time.Duration) {
@@ -222,7 +205,7 @@ wait:
}
func TestCommand_Wait_interrupts_after_context_timeout(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
+ ctx, cancel := testhelper.Context()
defer cancel()
ctx, timeout := context.WithTimeout(ctx, time.Second)
@@ -246,7 +229,7 @@ func TestCommand_Wait_interrupts_after_context_timeout(t *testing.T) {
}
func TestNewCommandWithSetupStdin(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
+ ctx, cancel := testhelper.Context()
defer cancel()
value := "Test value"
@@ -267,7 +250,7 @@ func TestNewCommandWithSetupStdin(t *testing.T) {
}
func TestNewCommandNullInArg(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
+ ctx, cancel := testhelper.Context()
defer cancel()
_, err := New(ctx, exec.Command("sh", "-c", "hello\x00world"), nil, nil, nil)
@@ -276,7 +259,7 @@ func TestNewCommandNullInArg(t *testing.T) {
}
func TestNewNonExistent(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
+ ctx, cancel := testhelper.Context()
defer cancel()
cmd, err := New(ctx, exec.Command("command-non-existent"), nil, nil, nil)
@@ -285,7 +268,7 @@ func TestNewNonExistent(t *testing.T) {
}
func TestCommandStdErr(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
+ ctx, cancel := testhelper.Context()
defer cancel()
var stdout, stderr bytes.Buffer
@@ -305,7 +288,7 @@ func TestCommandStdErr(t *testing.T) {
}
func TestCommandStdErrLargeOutput(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
+ ctx, cancel := testhelper.Context()
defer cancel()
var stdout, stderr bytes.Buffer
@@ -325,7 +308,7 @@ func TestCommandStdErrLargeOutput(t *testing.T) {
}
func TestCommandStdErrBinaryNullBytes(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
+ ctx, cancel := testhelper.Context()
defer cancel()
var stdout, stderr bytes.Buffer
@@ -345,7 +328,7 @@ func TestCommandStdErrBinaryNullBytes(t *testing.T) {
}
func TestCommandStdErrLongLine(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
+ ctx, cancel := testhelper.Context()
defer cancel()
var stdout, stderr bytes.Buffer
@@ -364,7 +347,7 @@ func TestCommandStdErrLongLine(t *testing.T) {
}
func TestCommandStdErrMaxBytes(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
+ ctx, cancel := testhelper.Context()
defer cancel()
var stdout, stderr bytes.Buffer
diff --git a/internal/command/commandcounter/counter.go b/internal/command/commandcounter/counter.go
new file mode 100644
index 000000000..f2eb7935d
--- /dev/null
+++ b/internal/command/commandcounter/counter.go
@@ -0,0 +1,25 @@
+package commandcounter
+
+import "sync"
+
+// inFlightCommands tracks the number of in-flight commands. This is hosted outside of the command
+// package to avoid a cyclic dependency with the testhelper package.
+var inFlightCommands = &sync.WaitGroup{}
+
+// Increment will add another process to the command counter. This may only be called by the
+// command package.
+func Increment() {
+ inFlightCommands.Add(1)
+}
+
+// Decrement removes one process from the command counter. This may only be called by the command
+// package.
+func Decrement() {
+ inFlightCommands.Done()
+}
+
+// WaitAllDone waits for all commands started by the command package to finish. This can only be
+// called once in the lifecycle of the current Go process.
+func WaitAllDone() {
+ inFlightCommands.Wait()
+}
diff --git a/internal/command/stats_test.go b/internal/command/stats_test.go
index 98af29a51..12b29505c 100644
--- a/internal/command/stats_test.go
+++ b/internal/command/stats_test.go
@@ -1,15 +1,15 @@
package command
import (
- "context"
"testing"
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/require"
+ "gitlab.com/gitlab-org/gitaly/v14/internal/testhelper"
)
func TestStatsFromContext_BackgroundContext(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
+ ctx, cancel := testhelper.Context()
defer cancel()
stats := StatsFromContext(ctx)
@@ -17,7 +17,7 @@ func TestStatsFromContext_BackgroundContext(t *testing.T) {
}
func TestStatsFromContext_InitContext(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
+ ctx, cancel := testhelper.Context()
defer cancel()
ctx = InitContextStats(ctx)
@@ -29,7 +29,7 @@ func TestStatsFromContext_InitContext(t *testing.T) {
}
func TestStatsFromContext_RecordSum(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
+ ctx, cancel := testhelper.Context()
defer cancel()
ctx = InitContextStats(ctx)
@@ -44,7 +44,7 @@ func TestStatsFromContext_RecordSum(t *testing.T) {
}
func TestStatsFromContext_RecordSumByRef(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
+ ctx, cancel := testhelper.Context()
defer cancel()
ctx = InitContextStats(ctx)
@@ -61,7 +61,7 @@ func TestStatsFromContext_RecordSumByRef(t *testing.T) {
}
func TestStatsFromContext_RecordMax(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
+ ctx, cancel := testhelper.Context()
defer cancel()
ctx = InitContextStats(ctx)
diff --git a/internal/dontpanic/retry.go b/internal/dontpanic/retry.go
index bb8fa93bb..83eb007f5 100644
--- a/internal/dontpanic/retry.go
+++ b/internal/dontpanic/retry.go
@@ -8,6 +8,7 @@
package dontpanic
import (
+ "sync"
"time"
sentry "github.com/getsentry/sentry-go"
@@ -56,24 +57,63 @@ func catchAndLog(fn func()) bool {
return normal
}
-// GoForever will keep retrying a function fn in a goroutine forever in the
-// background (until the process exits) while recovering from panics. Each
-// time a closure panics, the recovered value will be sent to Sentry and
-// logged at level error. The provided backoff will delay retries to enable
+// Forever encapsulates logic to run a function forever.
+type Forever struct {
+ backoff time.Duration
+
+ cancelOnce sync.Once
+ cancelCh chan struct{}
+ doneCh chan struct{}
+}
+
+// NewForever creates a new Forever struct. The given duration controls how long retry of a
+// function should be delayed if the function were to thrown an error.
+func NewForever(backoff time.Duration) *Forever {
+ return &Forever{
+ backoff: backoff,
+ cancelCh: make(chan struct{}),
+ doneCh: make(chan struct{}),
+ }
+}
+
+// Go will keep retrying a function fn in a goroutine forever in the background (until the process
+// exits) while recovering from panics. Each time a closure panics, the recovered value will be
+// sent to Sentry and logged at level error. The provided backoff will delay retries to enable
// "breathing" room to prevent potentially worsening the situation.
-func GoForever(backoff time.Duration, fn func()) {
+func (f *Forever) Go(fn func()) {
go func() {
+ defer close(f.doneCh)
+
for {
+ select {
+ case <-f.cancelCh:
+ return
+ default:
+ }
+
if Try(fn) {
continue
}
- if backoff <= 0 {
+ if f.backoff <= 0 {
continue
}
- logger.Infof("dontpanic: backing off %s before retrying", backoff)
- time.Sleep(backoff)
+ logger.Infof("dontpanic: backing off %s before retrying", f.backoff)
+
+ select {
+ case <-f.cancelCh:
+ return
+ case <-time.After(f.backoff):
+ }
}
}()
}
+
+// Cancel cancels the walking loop.
+func (f *Forever) Cancel() {
+ f.cancelOnce.Do(func() {
+ close(f.cancelCh)
+ <-f.doneCh
+ })
+}
diff --git a/internal/dontpanic/retry_test.go b/internal/dontpanic/retry_test.go
index d94ce3801..dcb683161 100644
--- a/internal/dontpanic/retry_test.go
+++ b/internal/dontpanic/retry_test.go
@@ -49,11 +49,13 @@ func TestGoForever(t *testing.T) {
panic("don't panic")
}
- dontpanic.GoForever(time.Microsecond, fn)
+ forever := dontpanic.NewForever(time.Microsecond)
+ forever.Go(fn)
var actualPanics int
for range recoveredQ {
actualPanics++
}
require.Equal(t, expectPanics, actualPanics)
+ forever.Cancel()
}
diff --git a/internal/dontpanic/testhelper_test.go b/internal/dontpanic/testhelper_test.go
index d4d8f7402..dd438042b 100644
--- a/internal/dontpanic/testhelper_test.go
+++ b/internal/dontpanic/testhelper_test.go
@@ -1,19 +1,11 @@
package dontpanic
import (
- "os"
"testing"
"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper"
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
diff --git a/internal/git/catfile/testhelper_test.go b/internal/git/catfile/testhelper_test.go
index 4479adb85..fa977e099 100644
--- a/internal/git/catfile/testhelper_test.go
+++ b/internal/git/catfile/testhelper_test.go
@@ -2,7 +2,6 @@ package catfile
import (
"context"
- "os"
"testing"
"gitlab.com/gitlab-org/gitaly/v14/internal/command"
@@ -13,18 +12,7 @@ import (
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer func() {
- testhelper.MustHaveNoChildProcess()
- testhelper.MustHaveNoGoroutines()
- }()
-
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
type repoExecutor struct {
diff --git a/internal/git/gitpipe/testhelper_test.go b/internal/git/gitpipe/testhelper_test.go
index b3683135f..8b2532840 100644
--- a/internal/git/gitpipe/testhelper_test.go
+++ b/internal/git/gitpipe/testhelper_test.go
@@ -1,21 +1,11 @@
package gitpipe
import (
- "os"
"testing"
"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper"
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
-
- cleanup := testhelper.Configure()
- defer cleanup()
-
- return m.Run()
+ testhelper.Run(m)
}
diff --git a/internal/git/gittest/commit_test.go b/internal/git/gittest/commit_test.go
index e96520a14..c3ad815ce 100644
--- a/internal/git/gittest/commit_test.go
+++ b/internal/git/gittest/commit_test.go
@@ -19,6 +19,8 @@ func TestWriteCommit(t *testing.T) {
defer cancel()
batchCache := catfile.NewCache(cfg)
+ defer batchCache.Stop()
+
batch, err := batchCache.BatchProcess(ctx, repo)
require.NoError(t, err)
diff --git a/internal/git/gittest/testhelper_test.go b/internal/git/gittest/testhelper_test.go
index 89d810164..a16e984f6 100644
--- a/internal/git/gittest/testhelper_test.go
+++ b/internal/git/gittest/testhelper_test.go
@@ -12,14 +12,7 @@ import (
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
// setup sets up a test configuration and repository. Ideally we'd use our central test helpers to
diff --git a/internal/git/helper_test.go b/internal/git/helper_test.go
index eb7e925fd..f76065121 100644
--- a/internal/git/helper_test.go
+++ b/internal/git/helper_test.go
@@ -1,7 +1,6 @@
package git
import (
- "os"
"testing"
"github.com/stretchr/testify/require"
@@ -9,14 +8,7 @@ import (
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
func TestValidateRevision(t *testing.T) {
diff --git a/internal/git/housekeeping/testhelper_test.go b/internal/git/housekeeping/testhelper_test.go
index 05d4da7f7..f0afe0397 100644
--- a/internal/git/housekeeping/testhelper_test.go
+++ b/internal/git/housekeeping/testhelper_test.go
@@ -1,18 +1,11 @@
package housekeeping
import (
- "os"
"testing"
"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper"
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
diff --git a/internal/git/localrepo/config_test.go b/internal/git/localrepo/config_test.go
index 15c440524..7abc7be08 100644
--- a/internal/git/localrepo/config_test.go
+++ b/internal/git/localrepo/config_test.go
@@ -31,7 +31,10 @@ func setupRepoConfig(t *testing.T) (Config, string) {
repoProto, repoPath := gittest.InitRepo(t, cfg, cfg.Storages[0])
gitCmdFactory := git.NewExecCommandFactory(cfg)
- repo := New(gitCmdFactory, catfile.NewCache(cfg), repoProto, cfg)
+ catfileCache := catfile.NewCache(cfg)
+ t.Cleanup(catfileCache.Stop)
+
+ repo := New(gitCmdFactory, catfileCache, repoProto, cfg)
return repo.Config(), repoPath
}
diff --git a/internal/git/localrepo/objects_test.go b/internal/git/localrepo/objects_test.go
index d1d797955..53c420d6b 100644
--- a/internal/git/localrepo/objects_test.go
+++ b/internal/git/localrepo/objects_test.go
@@ -35,7 +35,9 @@ func setupRepo(t *testing.T, bare bool) (*Repo, string) {
}
gitCmdFactory := git.NewExecCommandFactory(cfg)
- return New(gitCmdFactory, catfile.NewCache(cfg), repoProto, cfg), repoPath
+ catfileCache := catfile.NewCache(cfg)
+ t.Cleanup(catfileCache.Stop)
+ return New(gitCmdFactory, catfileCache, repoProto, cfg), repoPath
}
type ReaderFunc func([]byte) (int, error)
diff --git a/internal/git/localrepo/refs_test.go b/internal/git/localrepo/refs_test.go
index 3d3fdcd32..6bdc9a7e1 100644
--- a/internal/git/localrepo/refs_test.go
+++ b/internal/git/localrepo/refs_test.go
@@ -242,9 +242,12 @@ func TestRepo_GetRemoteReferences(t *testing.T) {
annotatedTagOID := text.ChompBytes(gittest.Exec(t, cfg, "-C", repoPath, "rev-parse", "annotated-tag"))
gitCmdFactory := git.NewExecCommandFactory(cfg)
+ catfileCache := catfile.NewCache(cfg)
+ defer catfileCache.Stop()
+
repo := New(
gitCmdFactory,
- catfile.NewCache(cfg),
+ catfileCache,
&gitalypb.Repository{StorageName: "default", RelativePath: filepath.Join(relativePath, ".git")},
cfg,
)
diff --git a/internal/git/localrepo/remote_test.go b/internal/git/localrepo/remote_test.go
index 6b165f0c9..547f0cf90 100644
--- a/internal/git/localrepo/remote_test.go
+++ b/internal/git/localrepo/remote_test.go
@@ -37,7 +37,10 @@ func setupRepoRemote(t *testing.T, bare bool) (Remote, string) {
}
gitCmdFactory := git.NewExecCommandFactory(cfg)
- return New(gitCmdFactory, catfile.NewCache(cfg), repoProto, cfg).Remote(), repoPath
+ catfileCache := catfile.NewCache(cfg)
+ t.Cleanup(catfileCache.Stop)
+
+ return New(gitCmdFactory, catfileCache, repoProto, cfg).Remote(), repoPath
}
func TestRepo_Remote(t *testing.T) {
diff --git a/internal/git/localrepo/repo.go b/internal/git/localrepo/repo.go
index 08c996b18..af869a6bb 100644
--- a/internal/git/localrepo/repo.go
+++ b/internal/git/localrepo/repo.go
@@ -37,7 +37,9 @@ func New(gitCmdFactory git.CommandFactory, catfileCache catfile.Cache, repo repo
// dependencies ad-hoc from the given config.
func NewTestRepo(t testing.TB, cfg config.Cfg, repo repository.GitRepo) *Repo {
gitCmdFactory := git.NewExecCommandFactory(cfg)
- return New(gitCmdFactory, catfile.NewCache(cfg), repo, cfg)
+ catfileCache := catfile.NewCache(cfg)
+ t.Cleanup(catfileCache.Stop)
+ return New(gitCmdFactory, catfileCache, repo, cfg)
}
// Path returns the on-disk path of the repository.
diff --git a/internal/git/localrepo/repo_test.go b/internal/git/localrepo/repo_test.go
index 8993471e0..c456e21b3 100644
--- a/internal/git/localrepo/repo_test.go
+++ b/internal/git/localrepo/repo_test.go
@@ -20,7 +20,9 @@ func TestRepo(t *testing.T) {
gittest.TestRepository(t, cfg, func(t testing.TB, pbRepo *gitalypb.Repository) git.Repository {
t.Helper()
gitCmdFactory := git.NewExecCommandFactory(cfg)
- return New(gitCmdFactory, catfile.NewCache(cfg), pbRepo, cfg)
+ catfileCache := catfile.NewCache(cfg)
+ t.Cleanup(catfileCache.Stop)
+ return New(gitCmdFactory, catfileCache, pbRepo, cfg)
})
}
@@ -28,7 +30,9 @@ func TestRepo_Path(t *testing.T) {
t.Run("valid repository", func(t *testing.T) {
cfg, repoProto, repoPath := testcfg.BuildWithRepo(t)
gitCmdFactory := git.NewExecCommandFactory(cfg)
- repo := New(gitCmdFactory, catfile.NewCache(cfg), repoProto, cfg)
+ catfileCache := catfile.NewCache(cfg)
+ t.Cleanup(catfileCache.Stop)
+ repo := New(gitCmdFactory, catfileCache, repoProto, cfg)
path, err := repo.Path()
require.NoError(t, err)
@@ -38,7 +42,9 @@ func TestRepo_Path(t *testing.T) {
t.Run("deleted repository", func(t *testing.T) {
cfg, repoProto, repoPath := testcfg.BuildWithRepo(t)
gitCmdFactory := git.NewExecCommandFactory(cfg)
- repo := New(gitCmdFactory, catfile.NewCache(cfg), repoProto, cfg)
+ catfileCache := catfile.NewCache(cfg)
+ t.Cleanup(catfileCache.Stop)
+ repo := New(gitCmdFactory, catfileCache, repoProto, cfg)
require.NoError(t, os.RemoveAll(repoPath))
@@ -49,7 +55,9 @@ func TestRepo_Path(t *testing.T) {
t.Run("non-git repository", func(t *testing.T) {
cfg, repoProto, repoPath := testcfg.BuildWithRepo(t)
gitCmdFactory := git.NewExecCommandFactory(cfg)
- repo := New(gitCmdFactory, catfile.NewCache(cfg), repoProto, cfg)
+ catfileCache := catfile.NewCache(cfg)
+ t.Cleanup(catfileCache.Stop)
+ repo := New(gitCmdFactory, catfileCache, repoProto, cfg)
// Recreate the repository as a simple empty directory to simulate
// that the repository is in a partially-created state.
diff --git a/internal/git/localrepo/testhelper_test.go b/internal/git/localrepo/testhelper_test.go
index 224d1566b..38486d705 100644
--- a/internal/git/localrepo/testhelper_test.go
+++ b/internal/git/localrepo/testhelper_test.go
@@ -1,19 +1,11 @@
package localrepo
import (
- "os"
"testing"
"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper"
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
diff --git a/internal/git/objectpool/clone_test.go b/internal/git/objectpool/clone_test.go
index 0720170a0..f3689ef24 100644
--- a/internal/git/objectpool/clone_test.go
+++ b/internal/git/objectpool/clone_test.go
@@ -23,11 +23,14 @@ func setupObjectPool(t *testing.T) (*ObjectPool, *gitalypb.Repository) {
cfg, repo, _ := testcfg.BuildWithRepo(t)
gitCommandFactory := git.NewExecCommandFactory(cfg)
+ catfileCache := catfile.NewCache(cfg)
+ t.Cleanup(catfileCache.Stop)
+
pool, err := NewObjectPool(
cfg,
config.NewLocator(cfg),
gitCommandFactory,
- catfile.NewCache(cfg),
+ catfileCache,
transaction.NewManager(cfg, backchannel.NewRegistry()),
repo.GetStorageName(),
gittest.NewObjectPoolName(t),
diff --git a/internal/git/objectpool/testhelper_test.go b/internal/git/objectpool/testhelper_test.go
index b252b37c1..bf79617d8 100644
--- a/internal/git/objectpool/testhelper_test.go
+++ b/internal/git/objectpool/testhelper_test.go
@@ -1,7 +1,6 @@
package objectpool
import (
- "os"
"testing"
"gitlab.com/gitlab-org/gitaly/v14/internal/git/hooks"
@@ -9,13 +8,8 @@ import (
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- hooks.Override = "/"
- return m.Run()
+ testhelper.Run(m, testhelper.WithSetup(func() error {
+ hooks.Override = "/"
+ return nil
+ }))
}
diff --git a/internal/git/packfile/packfile_test.go b/internal/git/packfile/packfile_test.go
index c8d412827..ecf56563b 100644
--- a/internal/git/packfile/packfile_test.go
+++ b/internal/git/packfile/packfile_test.go
@@ -1,7 +1,6 @@
package packfile_test
import (
- "os"
"path/filepath"
"testing"
@@ -13,14 +12,7 @@ import (
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
func TestList(t *testing.T) {
diff --git a/internal/git/quarantine/testhelper_test.go b/internal/git/quarantine/testhelper_test.go
index 7ad131635..38d896d42 100644
--- a/internal/git/quarantine/testhelper_test.go
+++ b/internal/git/quarantine/testhelper_test.go
@@ -1,21 +1,11 @@
package quarantine
import (
- "os"
"testing"
"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper"
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
-
- cleanup := testhelper.Configure()
- defer cleanup()
-
- return m.Run()
+ testhelper.Run(m)
}
diff --git a/internal/git/remoterepo/helper_test.go b/internal/git/remoterepo/helper_test.go
index 555b5445d..619ff5b16 100644
--- a/internal/git/remoterepo/helper_test.go
+++ b/internal/git/remoterepo/helper_test.go
@@ -1,19 +1,11 @@
package remoterepo
import (
- "os"
"testing"
"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper"
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
diff --git a/internal/git/remoterepo/repository_test.go b/internal/git/remoterepo/repository_test.go
index ddc63fb11..5bb233fdc 100644
--- a/internal/git/remoterepo/repository_test.go
+++ b/internal/git/remoterepo/repository_test.go
@@ -32,6 +32,7 @@ func TestRepository(t *testing.T) {
deps.GetTxManager(),
deps.GetGitCmdFactory(),
deps.GetCatfileCache(),
+ deps.GetConnsPool(),
))
gitalypb.RegisterCommitServiceServer(srv, commit.NewServer(
deps.GetCfg(),
diff --git a/internal/git/stats/testhelper_test.go b/internal/git/stats/testhelper_test.go
index ce080ff27..b842dc949 100644
--- a/internal/git/stats/testhelper_test.go
+++ b/internal/git/stats/testhelper_test.go
@@ -1,19 +1,11 @@
package stats
import (
- "os"
"testing"
"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper"
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
diff --git a/internal/git/updateref/updateref_test.go b/internal/git/updateref/updateref_test.go
index c2cf6c0d6..17c87fd16 100644
--- a/internal/git/updateref/updateref_test.go
+++ b/internal/git/updateref/updateref_test.go
@@ -3,7 +3,6 @@ package updateref
import (
"context"
"fmt"
- "os"
"strings"
"testing"
@@ -17,15 +16,10 @@ import (
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- hooks.Override = "/"
- return m.Run()
+ testhelper.Run(m, testhelper.WithSetup(func() error {
+ hooks.Override = "/"
+ return nil
+ }))
}
func setupUpdater(t *testing.T, ctx context.Context) (config.Cfg, *localrepo.Repo, *Updater) {
diff --git a/internal/git2go/commit_test.go b/internal/git2go/commit_test.go
index 04eb5334e..0f45235e2 100644
--- a/internal/git2go/commit_test.go
+++ b/internal/git2go/commit_test.go
@@ -5,7 +5,6 @@ import (
"context"
"errors"
"fmt"
- "os"
"strconv"
"strings"
"testing"
@@ -21,14 +20,7 @@ import (
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
type commit struct {
diff --git a/internal/gitaly/config/testhelper_test.go b/internal/gitaly/config/testhelper_test.go
index 88f7044fa..de452320d 100644
--- a/internal/gitaly/config/testhelper_test.go
+++ b/internal/gitaly/config/testhelper_test.go
@@ -1,19 +1,11 @@
package config_test
import (
- "os"
"testing"
"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper"
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
diff --git a/internal/gitaly/hook/testhelper_test.go b/internal/gitaly/hook/testhelper_test.go
index 9ea5b4c4a..ed02a0c77 100644
--- a/internal/gitaly/hook/testhelper_test.go
+++ b/internal/gitaly/hook/testhelper_test.go
@@ -1,19 +1,11 @@
package hook
import (
- "os"
"testing"
"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper"
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
diff --git a/internal/gitaly/linguist/linguist_test.go b/internal/gitaly/linguist/linguist_test.go
index 3caea5606..ea662ef60 100644
--- a/internal/gitaly/linguist/linguist_test.go
+++ b/internal/gitaly/linguist/linguist_test.go
@@ -2,7 +2,6 @@ package linguist
import (
"encoding/json"
- "os"
"path/filepath"
"testing"
@@ -13,14 +12,7 @@ import (
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
func TestInstance_Stats_unmarshalJSONError(t *testing.T) {
diff --git a/internal/gitaly/maintenance/main_test.go b/internal/gitaly/maintenance/main_test.go
index f7b6eeaf1..2cf16c9b6 100644
--- a/internal/gitaly/maintenance/main_test.go
+++ b/internal/gitaly/maintenance/main_test.go
@@ -1,19 +1,11 @@
package maintenance
import (
- "os"
"testing"
"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper"
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
diff --git a/internal/gitaly/maintenance/optimize_test.go b/internal/gitaly/maintenance/optimize_test.go
index 19d6ee5ca..d764f59ee 100644
--- a/internal/gitaly/maintenance/optimize_test.go
+++ b/internal/gitaly/maintenance/optimize_test.go
@@ -8,6 +8,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ "gitlab.com/gitlab-org/gitaly/v14/client"
"gitlab.com/gitlab-org/gitaly/v14/internal/backchannel"
"gitlab.com/gitlab-org/gitaly/v14/internal/git"
"gitlab.com/gitlab-org/gitaly/v14/internal/git/catfile"
@@ -33,7 +34,18 @@ func (mo *mockOptimizer) OptimizeRepository(ctx context.Context, req *gitalypb.O
l := config.NewLocator(mo.cfg)
gitCmdFactory := git.NewExecCommandFactory(mo.cfg)
catfileCache := catfile.NewCache(mo.cfg)
- resp, err := repository.NewServer(mo.cfg, nil, l, transaction.NewManager(mo.cfg, backchannel.NewRegistry()), gitCmdFactory, catfileCache).OptimizeRepository(ctx, req)
+ mo.t.Cleanup(catfileCache.Stop)
+
+ connsPool := client.NewPool()
+ mo.t.Cleanup(func() { testhelper.MustClose(mo.t, connsPool) })
+
+ resp, err := repository.NewServer(mo.cfg, nil, l, transaction.NewManager(
+ mo.cfg,
+ backchannel.NewRegistry()),
+ gitCmdFactory,
+ catfileCache,
+ connsPool,
+ ).OptimizeRepository(ctx, req)
assert.NoError(mo.t, err)
return resp, err
}
diff --git a/internal/gitaly/rubyserver/testhelper_test.go b/internal/gitaly/rubyserver/testhelper_test.go
index 2d4c7deba..f304d96c2 100644
--- a/internal/gitaly/rubyserver/testhelper_test.go
+++ b/internal/gitaly/rubyserver/testhelper_test.go
@@ -1,21 +1,11 @@
package rubyserver
import (
- "os"
"testing"
"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper"
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
-
- cleanup := testhelper.Configure()
- defer cleanup()
-
- return m.Run()
+ testhelper.Run(m)
}
diff --git a/internal/gitaly/server/auth_test.go b/internal/gitaly/server/auth_test.go
index 2dbde3056..adf2d6300 100644
--- a/internal/gitaly/server/auth_test.go
+++ b/internal/gitaly/server/auth_test.go
@@ -7,7 +7,6 @@ import (
"fmt"
"io"
"net"
- "os"
"testing"
"time"
@@ -39,14 +38,7 @@ import (
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
func TestSanity(t *testing.T) {
@@ -202,6 +194,7 @@ func runServer(t *testing.T, cfg config.Cfg) string {
), cfg)
gitCmdFactory := git.NewExecCommandFactory(cfg)
catfileCache := catfile.NewCache(cfg)
+ t.Cleanup(catfileCache.Stop)
diskCache := cache.New(cfg, locator)
srv, err := New(false, cfg, testhelper.DiscardTestEntry(t), registry, diskCache)
@@ -255,6 +248,7 @@ func TestUnaryNoAuth(t *testing.T) {
path := runServer(t, cfg)
conn, err := grpc.Dial(path, grpc.WithInsecure())
require.NoError(t, err)
+ defer testhelper.MustClose(t, conn)
ctx, cancel := testhelper.Context()
defer cancel()
diff --git a/internal/gitaly/server/server_factory_test.go b/internal/gitaly/server/server_factory_test.go
index c851c32d7..369cf3775 100644
--- a/internal/gitaly/server/server_factory_test.go
+++ b/internal/gitaly/server/server_factory_test.go
@@ -239,8 +239,10 @@ func TestGitalyServerFactory_closeOrder(t *testing.T) {
go server.Serve(ln)
- *builder.conn, err = grpc.DialContext(ctx, ln.Addr().String(), grpc.WithInsecure())
+ conn, err := grpc.DialContext(ctx, ln.Addr().String(), grpc.WithInsecure())
require.NoError(t, err)
+ t.Cleanup(func() { testhelper.MustClose(t, conn) })
+ *builder.conn = conn
}
// both servers should be up and accepting RPCs
diff --git a/internal/gitaly/service/blob/testhelper_test.go b/internal/gitaly/service/blob/testhelper_test.go
index 5d760d761..6dfffa6a4 100644
--- a/internal/gitaly/service/blob/testhelper_test.go
+++ b/internal/gitaly/service/blob/testhelper_test.go
@@ -1,7 +1,6 @@
package blob
import (
- "os"
"testing"
"github.com/stretchr/testify/require"
@@ -16,16 +15,7 @@ import (
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
-
- cleanup := testhelper.Configure()
- defer cleanup()
-
- return m.Run()
+ testhelper.Run(m)
}
func setup(t *testing.T) (config.Cfg, *gitalypb.Repository, string, gitalypb.BlobServiceClient) {
diff --git a/internal/gitaly/service/cleanup/testhelper_test.go b/internal/gitaly/service/cleanup/testhelper_test.go
index 7cb00db68..220b46bc1 100644
--- a/internal/gitaly/service/cleanup/testhelper_test.go
+++ b/internal/gitaly/service/cleanup/testhelper_test.go
@@ -1,7 +1,6 @@
package cleanup
import (
- "os"
"testing"
"gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/config"
@@ -15,14 +14,7 @@ import (
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
func setupCleanupService(t *testing.T) (config.Cfg, *gitalypb.Repository, string, gitalypb.CleanupServiceClient) {
diff --git a/internal/gitaly/service/commit/testhelper_test.go b/internal/gitaly/service/commit/testhelper_test.go
index e6f2c31cf..ece194fb2 100644
--- a/internal/gitaly/service/commit/testhelper_test.go
+++ b/internal/gitaly/service/commit/testhelper_test.go
@@ -2,7 +2,6 @@ package commit
import (
"io"
- "os"
"testing"
"github.com/stretchr/testify/require"
@@ -18,14 +17,7 @@ import (
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
// setupCommitService makes a basic configuration and starts the service with the client.
diff --git a/internal/gitaly/service/conflicts/server.go b/internal/gitaly/service/conflicts/server.go
index 63f1279ee..0bd08481c 100644
--- a/internal/gitaly/service/conflicts/server.go
+++ b/internal/gitaly/service/conflicts/server.go
@@ -27,19 +27,23 @@ type server struct {
}
// NewServer creates a new instance of a grpc ConflictsServer
-func NewServer(cfg config.Cfg, hookManager hook.Manager, locator storage.Locator, gitCmdFactory git.CommandFactory, catfileCache catfile.Cache) gitalypb.ConflictsServiceServer {
+func NewServer(
+ cfg config.Cfg,
+ hookManager hook.Manager,
+ locator storage.Locator,
+ gitCmdFactory git.CommandFactory,
+ catfileCache catfile.Cache,
+ connsPool *client.Pool,
+) gitalypb.ConflictsServiceServer {
return &server{
cfg: cfg,
hookManager: hookManager,
locator: locator,
gitCmdFactory: gitCmdFactory,
catfileCache: catfileCache,
- pool: client.NewPoolWithOptions(
- client.WithDialer(client.HealthCheckDialer(client.DialContext)),
- client.WithDialOptions(client.FailOnNonTempDialError()...),
- ),
- updater: updateref.NewUpdaterWithHooks(cfg, hookManager, gitCmdFactory, catfileCache),
- git2go: git2go.NewExecutor(cfg, locator),
+ pool: connsPool,
+ updater: updateref.NewUpdaterWithHooks(cfg, hookManager, gitCmdFactory, catfileCache),
+ git2go: git2go.NewExecutor(cfg, locator),
}
}
diff --git a/internal/gitaly/service/conflicts/testhelper_test.go b/internal/gitaly/service/conflicts/testhelper_test.go
index f85a2adc1..31792b01c 100644
--- a/internal/gitaly/service/conflicts/testhelper_test.go
+++ b/internal/gitaly/service/conflicts/testhelper_test.go
@@ -1,11 +1,8 @@
package conflicts
import (
- "os"
- "path/filepath"
"testing"
- log "github.com/sirupsen/logrus"
"gitlab.com/gitlab-org/gitaly/v14/internal/git/gittest"
"gitlab.com/gitlab-org/gitaly/v14/internal/git/hooks"
"gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/config"
@@ -23,30 +20,10 @@ import (
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
-
- cleanup := testhelper.Configure()
- defer cleanup()
-
- tempDir, err := os.MkdirTemp("", "gitaly")
- if err != nil {
- log.Error(err)
- return 1
- }
- defer func() {
- if err := os.RemoveAll(tempDir); err != nil {
- log.Error(err)
- }
- }()
-
- defer func(old string) { hooks.Override = old }(hooks.Override)
- hooks.Override = filepath.Join(tempDir, "hooks")
-
- return m.Run()
+ testhelper.Run(m, testhelper.WithSetup(func() error {
+ hooks.Override = "/"
+ return nil
+ }))
}
func SetupConfigAndRepo(t testing.TB, bare bool) (config.Cfg, *gitalypb.Repository, string) {
@@ -87,6 +64,7 @@ func runConflictsServer(t testing.TB, cfg config.Cfg, hookManager hook.Manager)
deps.GetLocator(),
deps.GetGitCmdFactory(),
deps.GetCatfileCache(),
+ deps.GetConnsPool(),
))
gitalypb.RegisterRepositoryServiceServer(srv, repository.NewServer(
deps.GetCfg(),
@@ -95,6 +73,7 @@ func runConflictsServer(t testing.TB, cfg config.Cfg, hookManager hook.Manager)
deps.GetTxManager(),
deps.GetGitCmdFactory(),
deps.GetCatfileCache(),
+ deps.GetConnsPool(),
))
gitalypb.RegisterSSHServiceServer(srv, ssh.NewServer(
deps.GetCfg(),
diff --git a/internal/gitaly/service/diff/testhelper_test.go b/internal/gitaly/service/diff/testhelper_test.go
index 1029cd3ed..06c12df5f 100644
--- a/internal/gitaly/service/diff/testhelper_test.go
+++ b/internal/gitaly/service/diff/testhelper_test.go
@@ -1,7 +1,6 @@
package diff
import (
- "os"
"testing"
"github.com/stretchr/testify/require"
@@ -15,14 +14,7 @@ import (
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
func setupDiffService(t testing.TB, opt ...testserver.GitalyServerOpt) (config.Cfg, *gitalypb.Repository, string, gitalypb.DiffServiceClient) {
diff --git a/internal/gitaly/service/hook/testhelper_test.go b/internal/gitaly/service/hook/testhelper_test.go
index 35f7f416e..935a15d24 100644
--- a/internal/gitaly/service/hook/testhelper_test.go
+++ b/internal/gitaly/service/hook/testhelper_test.go
@@ -1,7 +1,6 @@
package hook
import (
- "os"
"testing"
"gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/config"
@@ -15,14 +14,7 @@ import (
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
func setupHookService(t testing.TB) (config.Cfg, *gitalypb.Repository, string, gitalypb.HookServiceClient) {
diff --git a/internal/gitaly/service/internalgitaly/testhelper_test.go b/internal/gitaly/service/internalgitaly/testhelper_test.go
index d768d2d80..b1ba1d050 100644
--- a/internal/gitaly/service/internalgitaly/testhelper_test.go
+++ b/internal/gitaly/service/internalgitaly/testhelper_test.go
@@ -1,7 +1,6 @@
package internalgitaly
import (
- "os"
"testing"
"github.com/stretchr/testify/require"
@@ -14,14 +13,7 @@ import (
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
func setupInternalGitalyService(t *testing.T, cfg config.Cfg, internalService gitalypb.InternalGitalyServer) gitalypb.InternalGitalyClient {
diff --git a/internal/gitaly/service/namespace/namespace_test.go b/internal/gitaly/service/namespace/namespace_test.go
index 8adab217a..7657e3b28 100644
--- a/internal/gitaly/service/namespace/namespace_test.go
+++ b/internal/gitaly/service/namespace/namespace_test.go
@@ -15,16 +15,7 @@ import (
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
-
- cleanup := testhelper.Configure()
- defer cleanup()
-
- return m.Run()
+ testhelper.Run(m)
}
func TestNamespaceExists(t *testing.T) {
diff --git a/internal/gitaly/service/objectpool/fetch_into_object_pool_test.go b/internal/gitaly/service/objectpool/fetch_into_object_pool_test.go
index 9b68557e1..ba48dd00c 100644
--- a/internal/gitaly/service/objectpool/fetch_into_object_pool_test.go
+++ b/internal/gitaly/service/objectpool/fetch_into_object_pool_test.go
@@ -162,11 +162,14 @@ func TestFetchIntoObjectPool_Failure(t *testing.T) {
locator := config.NewLocator(cfg)
gitCmdFactory := git.NewExecCommandFactory(cfg)
+ catfileCache := catfile.NewCache(cfg)
+ t.Cleanup(catfileCache.Stop)
+
server := NewServer(
cfg,
locator,
gitCmdFactory,
- catfile.NewCache(cfg),
+ catfileCache,
transaction.NewManager(cfg, backchannel.NewRegistry()),
)
diff --git a/internal/gitaly/service/objectpool/testhelper_test.go b/internal/gitaly/service/objectpool/testhelper_test.go
index 8cdf1d180..86b85adcc 100644
--- a/internal/gitaly/service/objectpool/testhelper_test.go
+++ b/internal/gitaly/service/objectpool/testhelper_test.go
@@ -25,14 +25,7 @@ import (
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
func setup(t *testing.T, opts ...testserver.GitalyServerOpt) (config.Cfg, *gitalypb.Repository, string, storage.Locator, gitalypb.ObjectPoolServiceClient) {
@@ -76,12 +69,14 @@ func initObjectPool(t testing.TB, cfg config.Cfg, storage config.Storage) *objec
relativePath := gittest.NewObjectPoolName(t)
gittest.InitRepoDir(t, storage.Path, relativePath)
+ catfileCache := catfile.NewCache(cfg)
+ t.Cleanup(catfileCache.Stop)
pool, err := objectpool.NewObjectPool(
cfg,
config.NewLocator(cfg),
git.NewExecCommandFactory(cfg),
- catfile.NewCache(cfg),
+ catfileCache,
transaction.NewManager(cfg, backchannel.NewRegistry()),
storage.Name,
relativePath,
diff --git a/internal/gitaly/service/operations/apply_patch_test.go b/internal/gitaly/service/operations/apply_patch_test.go
index bc128093c..ba6666b35 100644
--- a/internal/gitaly/service/operations/apply_patch_test.go
+++ b/internal/gitaly/service/operations/apply_patch_test.go
@@ -279,7 +279,10 @@ To restore the original branch and stop patching, run "git am --abort".
t.Run(tc.desc, func(t *testing.T) {
repoPb, repoPath := gittest.InitRepo(t, cfg, cfg.Storages[0])
- repo := localrepo.New(git.NewExecCommandFactory(cfg), catfile.NewCache(cfg), repoPb, cfg)
+ catfileCache := catfile.NewCache(cfg)
+ t.Cleanup(catfileCache.Stop)
+
+ repo := localrepo.New(git.NewExecCommandFactory(cfg), catfileCache, repoPb, cfg)
executor := git2go.NewExecutor(cfg, config.NewLocator(cfg))
diff --git a/internal/gitaly/service/operations/testhelper_test.go b/internal/gitaly/service/operations/testhelper_test.go
index b93c8b00e..3e8996740 100644
--- a/internal/gitaly/service/operations/testhelper_test.go
+++ b/internal/gitaly/service/operations/testhelper_test.go
@@ -2,7 +2,6 @@ package operations
import (
"context"
- "os"
"testing"
"github.com/stretchr/testify/require"
@@ -32,21 +31,9 @@ var (
GitlabHooks []string
)
-func init() {
- GitlabHooks = append(GitlabHooks, append(gitlabPreHooks, gitlabPostHooks...)...)
-}
-
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
-
- cleanup := testhelper.Configure()
- defer cleanup()
-
- return m.Run()
+ GitlabHooks = append(GitlabHooks, append(gitlabPreHooks, gitlabPostHooks...)...)
+ testhelper.Run(m)
}
func setupOperationsService(t testing.TB, ctx context.Context, options ...testserver.GitalyServerOpt) (context.Context, config.Cfg, *gitalypb.Repository, string, gitalypb.OperationServiceClient) {
@@ -103,6 +90,7 @@ func runOperationServiceServer(t testing.TB, cfg config.Cfg, rubySrv *rubyserver
deps.GetTxManager(),
deps.GetGitCmdFactory(),
deps.GetCatfileCache(),
+ deps.GetConnsPool(),
))
gitalypb.RegisterRefServiceServer(srv, ref.NewServer(
deps.GetCfg(),
diff --git a/internal/gitaly/service/ref/find_all_tags_test.go b/internal/gitaly/service/ref/find_all_tags_test.go
index 628edc948..86aebd495 100644
--- a/internal/gitaly/service/ref/find_all_tags_test.go
+++ b/internal/gitaly/service/ref/find_all_tags_test.go
@@ -399,6 +399,8 @@ func TestFindAllTags_nestedTags(t *testing.T) {
testhelper.MustRunCommand(t, tags, "xargs", cfg.Git.BinPath, "-C", repoPath, "tag", "-d")
catfileCache := catfile.NewCache(cfg)
+ defer catfileCache.Stop()
+
batch, err := catfileCache.BatchProcess(ctx, repo)
require.NoError(t, err)
@@ -506,7 +508,10 @@ func TestFindAllTags_sorted(t *testing.T) {
repoProto, _ := gittest.CloneRepo(t, cfg, cfg.Storages[0])
- repo := localrepo.New(git.NewExecCommandFactory(cfg), catfile.NewCache(cfg), repoProto, cfg)
+ catfileCache := catfile.NewCache(cfg)
+ defer catfileCache.Stop()
+
+ repo := localrepo.New(git.NewExecCommandFactory(cfg), catfileCache, repoProto, cfg)
headCommit, err := repo.ReadCommit(ctx, "HEAD")
require.NoError(t, err)
annotatedTagID, err := repo.WriteTag(ctx, git.ObjectID(headCommit.Id), "commit", []byte("annotated"), []byte("message"), gittest.TestUser, time.Now())
diff --git a/internal/gitaly/service/ref/refs_test.go b/internal/gitaly/service/ref/refs_test.go
index 381a368ec..d1540f1a0 100644
--- a/internal/gitaly/service/ref/refs_test.go
+++ b/internal/gitaly/service/ref/refs_test.go
@@ -1081,6 +1081,8 @@ func TestFindTagNestedTag(t *testing.T) {
testhelper.MustRunCommand(t, tags, "xargs", cfg.Git.BinPath, "-C", repoPath, "tag", "-d")
catfileCache := catfile.NewCache(cfg)
+ defer catfileCache.Stop()
+
batch, err := catfileCache.BatchProcess(ctx, repo)
require.NoError(t, err)
diff --git a/internal/gitaly/service/ref/testhelper_test.go b/internal/gitaly/service/ref/testhelper_test.go
index 89f71285e..f530ca28a 100644
--- a/internal/gitaly/service/ref/testhelper_test.go
+++ b/internal/gitaly/service/ref/testhelper_test.go
@@ -2,7 +2,6 @@ package ref
import (
"bytes"
- "os"
"testing"
"github.com/stretchr/testify/require"
@@ -26,20 +25,12 @@ var localBranches = map[string]*gitalypb.GitCommit{
}
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
-
- cleanup := testhelper.Configure()
- defer cleanup()
-
- // Force small messages to test that fragmenting the
- // ref list works correctly
- lines.ItemsPerMessage = 3
-
- return m.Run()
+ testhelper.Run(m, testhelper.WithSetup(func() error {
+ // Force small messages to test that fragmenting the
+ // ref list works correctly
+ lines.ItemsPerMessage = 3
+ return nil
+ }))
}
func setupRefService(t testing.TB) (config.Cfg, *gitalypb.Repository, string, gitalypb.RefServiceClient) {
diff --git a/internal/gitaly/service/remote/server.go b/internal/gitaly/service/remote/server.go
index d466af948..a44c96916 100644
--- a/internal/gitaly/service/remote/server.go
+++ b/internal/gitaly/service/remote/server.go
@@ -30,6 +30,7 @@ func NewServer(
gitCmdFactory git.CommandFactory,
catfileCache catfile.Cache,
txManager transaction.Manager,
+ connsPool *client.Pool,
) gitalypb.RemoteServiceServer {
return &server{
cfg: cfg,
@@ -37,10 +38,7 @@ func NewServer(
gitCmdFactory: gitCmdFactory,
catfileCache: catfileCache,
txManager: txManager,
- conns: client.NewPoolWithOptions(
- client.WithDialer(client.HealthCheckDialer(client.DialContext)),
- client.WithDialOptions(client.FailOnNonTempDialError()...),
- ),
+ conns: connsPool,
}
}
diff --git a/internal/gitaly/service/remote/testhelper_test.go b/internal/gitaly/service/remote/testhelper_test.go
index 35285044f..06eaa916e 100644
--- a/internal/gitaly/service/remote/testhelper_test.go
+++ b/internal/gitaly/service/remote/testhelper_test.go
@@ -1,7 +1,6 @@
package remote
import (
- "os"
"testing"
"gitlab.com/gitlab-org/gitaly/v14/internal/git/gittest"
@@ -15,16 +14,7 @@ import (
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
-
- cleanup := testhelper.Configure()
- defer cleanup()
-
- return m.Run()
+ testhelper.Run(m)
}
func setupRemoteService(t *testing.T, opts ...testserver.GitalyServerOpt) (config.Cfg, *gitalypb.Repository, string, gitalypb.RemoteServiceClient) {
@@ -41,6 +31,7 @@ func setupRemoteService(t *testing.T, opts ...testserver.GitalyServerOpt) (confi
deps.GetGitCmdFactory(),
deps.GetCatfileCache(),
deps.GetTxManager(),
+ deps.GetConnsPool(),
))
}, opts...)
cfg.SocketPath = addr
diff --git a/internal/gitaly/service/remote/update_remote_mirror_test.go b/internal/gitaly/service/remote/update_remote_mirror_test.go
index e56171609..7eeb8128f 100644
--- a/internal/gitaly/service/remote/update_remote_mirror_test.go
+++ b/internal/gitaly/service/remote/update_remote_mirror_test.go
@@ -564,6 +564,7 @@ func TestUpdateRemoteMirror(t *testing.T) {
cmdFactory,
deps.GetCatfileCache(),
deps.GetTxManager(),
+ deps.GetConnsPool(),
))
})
@@ -632,6 +633,7 @@ func TestSuccessfulUpdateRemoteMirrorRequest(t *testing.T) {
deps.GetGitCmdFactory(),
deps.GetCatfileCache(),
deps.GetTxManager(),
+ deps.GetConnsPool(),
))
})
@@ -734,6 +736,7 @@ func TestSuccessfulUpdateRemoteMirrorRequestWithWildcards(t *testing.T) {
deps.GetGitCmdFactory(),
deps.GetCatfileCache(),
deps.GetTxManager(),
+ deps.GetConnsPool(),
))
})
@@ -817,6 +820,7 @@ func TestUpdateRemoteMirrorInmemory(t *testing.T) {
deps.GetGitCmdFactory(),
deps.GetCatfileCache(),
deps.GetTxManager(),
+ deps.GetConnsPool(),
))
})
@@ -865,6 +869,7 @@ func TestSuccessfulUpdateRemoteMirrorRequestWithKeepDivergentRefs(t *testing.T)
deps.GetGitCmdFactory(),
deps.GetCatfileCache(),
deps.GetTxManager(),
+ deps.GetConnsPool(),
))
})
@@ -952,6 +957,7 @@ func TestFailedUpdateRemoteMirrorRequestDueToValidation(t *testing.T) {
deps.GetGitCmdFactory(),
deps.GetCatfileCache(),
deps.GetTxManager(),
+ deps.GetConnsPool(),
))
})
diff --git a/internal/gitaly/service/repository/apply_gitattributes_test.go b/internal/gitaly/service/repository/apply_gitattributes_test.go
index f85b6f456..c71b48b80 100644
--- a/internal/gitaly/service/repository/apply_gitattributes_test.go
+++ b/internal/gitaly/service/repository/apply_gitattributes_test.go
@@ -105,6 +105,7 @@ func TestApplyGitattributesWithTransaction(t *testing.T) {
deps.GetTxManager(),
deps.GetGitCmdFactory(),
deps.GetCatfileCache(),
+ deps.GetConnsPool(),
))
})
diff --git a/internal/gitaly/service/repository/cleanup_test.go b/internal/gitaly/service/repository/cleanup_test.go
index 3e8b2ce0b..c5d53b73f 100644
--- a/internal/gitaly/service/repository/cleanup_test.go
+++ b/internal/gitaly/service/repository/cleanup_test.go
@@ -153,7 +153,10 @@ func TestRemoveWorktree(t *testing.T) {
cfg, repoProto, repoPath := testcfg.BuildWithRepo(t)
gitCmdFactory := git.NewExecCommandFactory(cfg)
- repo := localrepo.New(gitCmdFactory, catfile.NewCache(cfg), repoProto, cfg)
+ catfileCache := catfile.NewCache(cfg)
+ defer catfileCache.Stop()
+
+ repo := localrepo.New(gitCmdFactory, catfileCache, repoProto, cfg)
existingWorktreePath := filepath.Join(repoPath, worktreePrefix, "existing")
gittest.AddWorktree(t, cfg, repoPath, existingWorktreePath)
diff --git a/internal/gitaly/service/repository/clone_from_pool_internal_test.go b/internal/gitaly/service/repository/clone_from_pool_internal_test.go
index 3a99242c7..72f17d230 100644
--- a/internal/gitaly/service/repository/clone_from_pool_internal_test.go
+++ b/internal/gitaly/service/repository/clone_from_pool_internal_test.go
@@ -26,12 +26,14 @@ func newTestObjectPool(t *testing.T, cfg config.Cfg) (*objectpool.ObjectPool, *g
repo := gittest.InitRepoDir(t, cfg.Storages[0].Path, relativePath)
gitCmdFactory := git.NewExecCommandFactory(cfg)
+ catfileCache := catfile.NewCache(cfg)
+ t.Cleanup(catfileCache.Stop)
pool, err := objectpool.NewObjectPool(
cfg,
config.NewLocator(cfg),
gitCmdFactory,
- catfile.NewCache(cfg),
+ catfileCache,
transaction.NewManager(cfg, backchannel.NewRegistry()),
repo.GetStorageName(),
relativePath,
diff --git a/internal/gitaly/service/repository/clone_from_pool_test.go b/internal/gitaly/service/repository/clone_from_pool_test.go
index 7a6623554..41de34186 100644
--- a/internal/gitaly/service/repository/clone_from_pool_test.go
+++ b/internal/gitaly/service/repository/clone_from_pool_test.go
@@ -37,7 +37,8 @@ func TestCloneFromPoolHTTP(t *testing.T) {
defer forkRepoCleanup()
authorizationHeader := "ABCefg0999182"
- _, remoteURL := gittest.RemoteUploadPackServer(ctx, t, cfg.Git.BinPath, "my-repo", authorizationHeader, repoPath)
+ server, remoteURL := gittest.RemoteUploadPackServer(ctx, t, cfg.Git.BinPath, "my-repo", authorizationHeader, repoPath)
+ defer server.Close()
req := &gitalypb.CloneFromPoolRequest{
Repository: forkedRepo,
diff --git a/internal/gitaly/service/repository/fetch_bundle_test.go b/internal/gitaly/service/repository/fetch_bundle_test.go
index a81889000..25b2d9961 100644
--- a/internal/gitaly/service/repository/fetch_bundle_test.go
+++ b/internal/gitaly/service/repository/fetch_bundle_test.go
@@ -83,6 +83,7 @@ func TestServer_FetchBundle_transaction(t *testing.T) {
deps.GetTxManager(),
deps.GetGitCmdFactory(),
deps.GetCatfileCache(),
+ deps.GetConnsPool(),
))
gitalypb.RegisterHookServiceServer(srv, hook.NewServer(
deps.GetCfg(),
diff --git a/internal/gitaly/service/repository/fetch_remote_test.go b/internal/gitaly/service/repository/fetch_remote_test.go
index a64a51d87..85bcc3254 100644
--- a/internal/gitaly/service/repository/fetch_remote_test.go
+++ b/internal/gitaly/service/repository/fetch_remote_test.go
@@ -209,6 +209,7 @@ func TestFetchRemote_transaction(t *testing.T) {
deps.GetTxManager(),
deps.GetGitCmdFactory(),
deps.GetCatfileCache(),
+ deps.GetConnsPool(),
))
}, testserver.WithTransactionManager(txManager))
diff --git a/internal/gitaly/service/repository/fork_test.go b/internal/gitaly/service/repository/fork_test.go
index dba63ffa2..092ec2e07 100644
--- a/internal/gitaly/service/repository/fork_test.go
+++ b/internal/gitaly/service/repository/fork_test.go
@@ -9,7 +9,7 @@ import (
"github.com/stretchr/testify/require"
gitalyauth "gitlab.com/gitlab-org/gitaly/v14/auth"
- gclient "gitlab.com/gitlab-org/gitaly/v14/client"
+ "gitlab.com/gitlab-org/gitaly/v14/client"
"gitlab.com/gitlab-org/gitaly/v14/internal/backchannel"
"gitlab.com/gitlab-org/gitaly/v14/internal/cache"
"gitlab.com/gitlab-org/gitaly/v14/internal/git"
@@ -129,7 +129,7 @@ func newSecureRepoClient(t testing.TB, addr, token string, pool *x509.CertPool)
grpc.WithPerRPCCredentials(gitalyauth.RPCCredentialsV2(token)),
}
- conn, err := gclient.Dial(addr, connOpts)
+ conn, err := client.Dial(addr, connOpts)
require.NoError(t, err)
return gitalypb.NewRepositoryServiceClient(conn), conn
@@ -226,10 +226,14 @@ func runSecureServer(t *testing.T, cfg config.Cfg, rubySrv *rubyserver.Server) s
), cfg)
gitCmdFactory := git.NewExecCommandFactory(cfg)
catfileCache := catfile.NewCache(cfg)
+ t.Cleanup(catfileCache.Stop)
- gitalypb.RegisterRepositoryServiceServer(server, NewServer(cfg, rubySrv, locator, txManager, gitCmdFactory, catfileCache))
+ connsPool := client.NewPool()
+ t.Cleanup(func() { testhelper.MustClose(t, connsPool) })
+
+ gitalypb.RegisterRepositoryServiceServer(server, NewServer(cfg, rubySrv, locator, txManager, gitCmdFactory, catfileCache, connsPool))
gitalypb.RegisterHookServiceServer(server, hookservice.NewServer(cfg, hookManager, gitCmdFactory, nil))
- gitalypb.RegisterRemoteServiceServer(server, remote.NewServer(cfg, locator, gitCmdFactory, catfileCache, txManager))
+ gitalypb.RegisterRemoteServiceServer(server, remote.NewServer(cfg, locator, gitCmdFactory, catfileCache, txManager, connsPool))
gitalypb.RegisterSSHServiceServer(server, ssh.NewServer(cfg, locator, gitCmdFactory, txManager))
gitalypb.RegisterRefServiceServer(server, ref.NewServer(cfg, locator, gitCmdFactory, txManager, catfileCache))
gitalypb.RegisterCommitServiceServer(server, commit.NewServer(cfg, locator, gitCmdFactory, nil, catfileCache))
diff --git a/internal/gitaly/service/repository/search_files_test.go b/internal/gitaly/service/repository/search_files_test.go
index 096485610..25bd6c17c 100644
--- a/internal/gitaly/service/repository/search_files_test.go
+++ b/internal/gitaly/service/repository/search_files_test.go
@@ -10,6 +10,7 @@ import (
"testing"
"github.com/stretchr/testify/require"
+ "gitlab.com/gitlab-org/gitaly/v14/client"
"gitlab.com/gitlab-org/gitaly/v14/internal/backchannel"
"gitlab.com/gitlab-org/gitaly/v14/internal/git"
"gitlab.com/gitlab-org/gitaly/v14/internal/git/catfile"
@@ -207,6 +208,11 @@ func TestSearchFilesByContentFailure(t *testing.T) {
t.Parallel()
cfg, repo, _ := testcfg.BuildWithRepo(t)
gitCommandFactory := git.NewExecCommandFactory(cfg)
+ catfileCache := catfile.NewCache(cfg)
+ t.Cleanup(catfileCache.Stop)
+
+ connsPool := client.NewPool()
+ defer testhelper.MustClose(t, connsPool)
server := NewServer(
cfg,
@@ -214,7 +220,8 @@ func TestSearchFilesByContentFailure(t *testing.T) {
config.NewLocator(cfg),
transaction.NewManager(cfg, backchannel.NewRegistry()),
gitCommandFactory,
- catfile.NewCache(cfg),
+ catfileCache,
+ connsPool,
)
testCases := []struct {
@@ -330,6 +337,11 @@ func TestSearchFilesByNameFailure(t *testing.T) {
t.Parallel()
cfg := testcfg.Build(t)
gitCommandFactory := git.NewExecCommandFactory(cfg)
+ catfileCache := catfile.NewCache(cfg)
+ t.Cleanup(catfileCache.Stop)
+
+ connsPool := client.NewPool()
+ defer testhelper.MustClose(t, connsPool)
server := NewServer(
cfg,
@@ -337,7 +349,8 @@ func TestSearchFilesByNameFailure(t *testing.T) {
config.NewLocator(cfg),
transaction.NewManager(cfg, backchannel.NewRegistry()),
gitCommandFactory,
- catfile.NewCache(cfg),
+ catfileCache,
+ connsPool,
)
testCases := []struct {
diff --git a/internal/gitaly/service/repository/server.go b/internal/gitaly/service/repository/server.go
index e248c70d7..d211325e5 100644
--- a/internal/gitaly/service/repository/server.go
+++ b/internal/gitaly/service/repository/server.go
@@ -36,21 +36,19 @@ func NewServer(
txManager transaction.Manager,
gitCmdFactory git.CommandFactory,
catfileCache catfile.Cache,
+ connsPool *client.Pool,
) gitalypb.RepositoryServiceServer {
return &server{
ruby: rs,
locator: locator,
txManager: txManager,
gitCmdFactory: gitCmdFactory,
- conns: client.NewPoolWithOptions(
- client.WithDialer(client.HealthCheckDialer(client.DialContext)),
- client.WithDialOptions(client.FailOnNonTempDialError()...),
- ),
- cfg: cfg,
- binDir: cfg.BinDir,
- loggingCfg: cfg.Logging,
- catfileCache: catfileCache,
- git2go: git2go.NewExecutor(cfg, locator),
+ conns: connsPool,
+ cfg: cfg,
+ binDir: cfg.BinDir,
+ loggingCfg: cfg.Logging,
+ catfileCache: catfileCache,
+ git2go: git2go.NewExecutor(cfg, locator),
}
}
diff --git a/internal/gitaly/service/repository/snapshot_test.go b/internal/gitaly/service/repository/snapshot_test.go
index 973eb93b6..a4727957a 100644
--- a/internal/gitaly/service/repository/snapshot_test.go
+++ b/internal/gitaly/service/repository/snapshot_test.go
@@ -133,6 +133,7 @@ func TestGetSnapshotWithDedupe(t *testing.T) {
locator := config.NewLocator(cfg)
catfileCache := catfile.NewCache(cfg)
+ defer catfileCache.Stop()
// ensure commit cannot be found in current repository
c, err := catfileCache.BatchProcess(ctx, repo)
diff --git a/internal/gitaly/service/repository/testhelper_test.go b/internal/gitaly/service/repository/testhelper_test.go
index a50e3a7da..1e33f5ff9 100644
--- a/internal/gitaly/service/repository/testhelper_test.go
+++ b/internal/gitaly/service/repository/testhelper_test.go
@@ -35,16 +35,7 @@ const testTimeString = "200601021504.05"
var testTime = time.Date(2006, 1, 2, 15, 4, 5, 0, time.UTC)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
-
- cleanup := testhelper.Configure()
- defer cleanup()
-
- return m.Run()
+ testhelper.Run(m)
}
func TestWithRubySidecar(t *testing.T) {
@@ -124,6 +115,7 @@ func runRepositoryServerWithConfig(t testing.TB, cfg config.Cfg, rubySrv *rubyse
deps.GetTxManager(),
deps.GetGitCmdFactory(),
deps.GetCatfileCache(),
+ deps.GetConnsPool(),
))
gitalypb.RegisterHookServiceServer(srv, hookservice.NewServer(cfg, deps.GetHookManager(), deps.GetGitCmdFactory(), deps.GetPackObjectsCache()))
gitalypb.RegisterRemoteServiceServer(srv, remote.NewServer(
@@ -132,6 +124,7 @@ func runRepositoryServerWithConfig(t testing.TB, cfg config.Cfg, rubySrv *rubyse
deps.GetGitCmdFactory(),
deps.GetCatfileCache(),
deps.GetTxManager(),
+ deps.GetConnsPool(),
))
gitalypb.RegisterSSHServiceServer(srv, ssh.NewServer(
cfg,
diff --git a/internal/gitaly/service/server/server_test.go b/internal/gitaly/service/server/server_test.go
index 95fca6a02..b2570c260 100644
--- a/internal/gitaly/service/server/server_test.go
+++ b/internal/gitaly/service/server/server_test.go
@@ -1,19 +1,11 @@
package server
import (
- "os"
"testing"
"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper"
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
diff --git a/internal/gitaly/service/setup/register.go b/internal/gitaly/service/setup/register.go
index 67286ffea..39010ff36 100644
--- a/internal/gitaly/service/setup/register.go
+++ b/internal/gitaly/service/setup/register.go
@@ -102,6 +102,7 @@ func RegisterAll(srv *grpc.Server, deps *service.Dependencies) {
deps.GetTxManager(),
deps.GetGitCmdFactory(),
deps.GetCatfileCache(),
+ deps.GetConnsPool(),
))
gitalypb.RegisterSSHServiceServer(srv, ssh.NewServer(
deps.GetCfg(),
@@ -124,6 +125,7 @@ func RegisterAll(srv *grpc.Server, deps *service.Dependencies) {
deps.GetLocator(),
deps.GetGitCmdFactory(),
deps.GetCatfileCache(),
+ deps.GetConnsPool(),
))
gitalypb.RegisterRemoteServiceServer(srv, remote.NewServer(
deps.GetCfg(),
@@ -131,6 +133,7 @@ func RegisterAll(srv *grpc.Server, deps *service.Dependencies) {
deps.GetGitCmdFactory(),
deps.GetCatfileCache(),
deps.GetTxManager(),
+ deps.GetConnsPool(),
))
gitalypb.RegisterServerServiceServer(srv, server.NewServer(deps.GetGitCmdFactory(), deps.GetCfg().Storages))
gitalypb.RegisterObjectPoolServiceServer(srv, objectpool.NewServer(
diff --git a/internal/gitaly/service/smarthttp/inforefs_test.go b/internal/gitaly/service/smarthttp/inforefs_test.go
index 1746aca5d..d2ccaeb37 100644
--- a/internal/gitaly/service/smarthttp/inforefs_test.go
+++ b/internal/gitaly/service/smarthttp/inforefs_test.go
@@ -121,7 +121,8 @@ func TestSuccessfulInfoRefsUploadPackWithGitProtocol(t *testing.T) {
GitProtocol: git.ProtocolV2,
}
- client, _ := newSmartHTTPClient(t, serverSocketPath, cfg.Auth.Token)
+ client, conn := newSmartHTTPClient(t, serverSocketPath, cfg.Auth.Token)
+ defer testhelper.MustClose(t, conn)
ctx, cancel := testhelper.Context()
defer cancel()
diff --git a/internal/gitaly/service/smarthttp/testhelper_test.go b/internal/gitaly/service/smarthttp/testhelper_test.go
index 3b4ef7cfc..3a6d1b70d 100644
--- a/internal/gitaly/service/smarthttp/testhelper_test.go
+++ b/internal/gitaly/service/smarthttp/testhelper_test.go
@@ -2,7 +2,6 @@ package smarthttp
import (
"context"
- "os"
"testing"
"github.com/stretchr/testify/require"
@@ -23,16 +22,7 @@ const (
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
-
- cleanup := testhelper.Configure()
- defer cleanup()
-
- return m.Run()
+ testhelper.Run(m)
}
func startSmartHTTPServer(t *testing.T, cfg config.Cfg, serverOpts ...ServerOpt) testserver.GitalyServer {
diff --git a/internal/gitaly/service/ssh/testhelper_test.go b/internal/gitaly/service/ssh/testhelper_test.go
index 7c5349c32..45ab030bf 100644
--- a/internal/gitaly/service/ssh/testhelper_test.go
+++ b/internal/gitaly/service/ssh/testhelper_test.go
@@ -1,7 +1,6 @@
package ssh
import (
- "os"
"testing"
"gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/config"
@@ -14,16 +13,7 @@ import (
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
-
- cleanup := testhelper.Configure()
- defer cleanup()
-
- return m.Run()
+ testhelper.Run(m)
}
func runSSHServer(t *testing.T, cfg config.Cfg, serverOpts ...testserver.GitalyServerOpt) string {
diff --git a/internal/gitaly/service/wiki/testhelper_test.go b/internal/gitaly/service/wiki/testhelper_test.go
index 9302d6b14..247fd9ac8 100644
--- a/internal/gitaly/service/wiki/testhelper_test.go
+++ b/internal/gitaly/service/wiki/testhelper_test.go
@@ -2,12 +2,10 @@ package wiki
import (
"bytes"
- "os"
"reflect"
"runtime"
"testing"
- log "github.com/sirupsen/logrus"
"github.com/stretchr/testify/require"
"gitlab.com/gitlab-org/gitaly/v14/internal/git"
"gitlab.com/gitlab-org/gitaly/v14/internal/git/gittest"
@@ -33,29 +31,10 @@ type createWikiPageOpts struct {
var mockPageContent = bytes.Repeat([]byte("Mock wiki page content"), 10000)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
-
- cleanup := testhelper.Configure()
- defer cleanup()
-
- tempDir, err := os.MkdirTemp("", "gitaly")
- if err != nil {
- log.Error(err)
- return 1
- }
- defer func() {
- if err := os.RemoveAll(tempDir); err != nil {
- log.Error(err)
- }
- }()
-
- hooks.Override = tempDir + "/hooks"
-
- return m.Run()
+ testhelper.Run(m, testhelper.WithSetup(func() error {
+ hooks.Override = "/"
+ return nil
+ }))
}
func TestWithRubySidecar(t *testing.T) {
diff --git a/internal/gitaly/transaction/testhelper_test.go b/internal/gitaly/transaction/testhelper_test.go
index 314059345..3e17bd91e 100644
--- a/internal/gitaly/transaction/testhelper_test.go
+++ b/internal/gitaly/transaction/testhelper_test.go
@@ -1,21 +1,11 @@
package transaction
import (
- "os"
"testing"
"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper"
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
-
- cleanup := testhelper.Configure()
- defer cleanup()
-
- return m.Run()
+ testhelper.Run(m)
}
diff --git a/internal/gitalyssh/testhelper_test.go b/internal/gitalyssh/testhelper_test.go
index 1f17e47a4..6af673482 100644
--- a/internal/gitalyssh/testhelper_test.go
+++ b/internal/gitalyssh/testhelper_test.go
@@ -1,19 +1,11 @@
package gitalyssh
import (
- "os"
"testing"
"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper"
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
diff --git a/internal/gitlab/testhelper_test.go b/internal/gitlab/testhelper_test.go
index f8a245a2d..69a859a86 100644
--- a/internal/gitlab/testhelper_test.go
+++ b/internal/gitlab/testhelper_test.go
@@ -1,15 +1,11 @@
package gitlab
import (
- "os"
"testing"
"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper"
)
func TestMain(m *testing.M) {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- os.Exit(m.Run())
+ testhelper.Run(m)
}
diff --git a/internal/helper/chunk/chunker_test.go b/internal/helper/chunk/chunker_test.go
index c7f91fd85..7f13050d8 100644
--- a/internal/helper/chunk/chunker_test.go
+++ b/internal/helper/chunk/chunker_test.go
@@ -3,7 +3,6 @@ package chunk
import (
"io"
"net"
- "os"
"testing"
"github.com/stretchr/testify/require"
@@ -15,14 +14,7 @@ import (
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
type testSender struct {
diff --git a/internal/helper/repo_test.go b/internal/helper/repo_test.go
index fb5961c52..c65665131 100644
--- a/internal/helper/repo_test.go
+++ b/internal/helper/repo_test.go
@@ -1,7 +1,6 @@
package helper
import (
- "os"
"testing"
"github.com/stretchr/testify/assert"
@@ -10,14 +9,7 @@ import (
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
func TestRepoPathEqual(t *testing.T) {
diff --git a/internal/middleware/commandstatshandler/commandstatshandler_test.go b/internal/middleware/commandstatshandler/commandstatshandler_test.go
index 2d923095e..d474744bd 100644
--- a/internal/middleware/commandstatshandler/commandstatshandler_test.go
+++ b/internal/middleware/commandstatshandler/commandstatshandler_test.go
@@ -25,6 +25,10 @@ import (
"google.golang.org/grpc/test/bufconn"
)
+func TestMain(m *testing.M) {
+ testhelper.Run(m)
+}
+
func createNewServer(t *testing.T, cfg config.Cfg) *grpc.Server {
logger := testhelper.NewTestLogger(t)
logrusEntry := logrus.NewEntry(logger).WithField("test", t.Name())
@@ -47,13 +51,15 @@ func createNewServer(t *testing.T, cfg config.Cfg) *grpc.Server {
server := grpc.NewServer(opts...)
gitCommandFactory := git.NewExecCommandFactory(cfg)
+ catfileCache := catfile.NewCache(cfg)
+ t.Cleanup(catfileCache.Stop)
gitalypb.RegisterRefServiceServer(server, ref.NewServer(
cfg,
config.NewLocator(cfg),
gitCommandFactory,
transaction.NewManager(cfg, backchannel.NewRegistry()),
- catfile.NewCache(cfg),
+ catfileCache,
))
return server
@@ -66,9 +72,6 @@ func getBufDialer(listener *bufconn.Listener) func(context.Context, string) (net
}
func TestInterceptor(t *testing.T) {
- cleanup := testhelper.Configure()
- defer cleanup()
-
cfg, repo, _ := testcfg.BuildWithRepo(t)
logBuffer := &bytes.Buffer{}
diff --git a/internal/middleware/limithandler/limithandler_test.go b/internal/middleware/limithandler/limithandler_test.go
index 743bb9d17..84df9f150 100644
--- a/internal/middleware/limithandler/limithandler_test.go
+++ b/internal/middleware/limithandler/limithandler_test.go
@@ -3,7 +3,6 @@ package limithandler_test
import (
"context"
"net"
- "os"
"sync"
"testing"
"time"
@@ -17,14 +16,7 @@ import (
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
func fixedLockKey(ctx context.Context) string {
diff --git a/internal/praefect/auth_test.go b/internal/praefect/auth_test.go
index bafa7bfda..29c8a989b 100644
--- a/internal/praefect/auth_test.go
+++ b/internal/praefect/auth_test.go
@@ -153,6 +153,7 @@ func runServer(t *testing.T, token string, required bool) (*grpc.Server, string,
nodeMgr, err := nodes.NewManager(logEntry, conf, nil, nil, promtest.NewMockHistogramVec(), protoregistry.GitalyProtoPreregistered, nil, nil, nil)
require.NoError(t, err)
+ defer nodeMgr.Stop()
txMgr := transactions.NewManager(conf)
diff --git a/internal/praefect/coordinator_test.go b/internal/praefect/coordinator_test.go
index adf4c6262..664428fb9 100644
--- a/internal/praefect/coordinator_test.go
+++ b/internal/praefect/coordinator_test.go
@@ -311,6 +311,7 @@ func TestStreamDirectorMutator_StopTransaction(t *testing.T) {
nodeMgr, err := nodes.NewManager(testhelper.DiscardTestEntry(t), conf, nil, nil, promtest.NewMockHistogramVec(), protoregistry.GitalyProtoPreregistered, nil, nil, nil)
require.NoError(t, err)
nodeMgr.Start(0, time.Hour)
+ defer nodeMgr.Stop()
ctx, cancel := testhelper.Context()
defer cancel()
@@ -442,6 +443,7 @@ func TestStreamDirectorAccessor(t *testing.T) {
nodeMgr, err := nodes.NewManager(entry, conf, nil, rs, promtest.NewMockHistogramVec(), protoregistry.GitalyProtoPreregistered, nil, nil, nil)
require.NoError(t, err)
nodeMgr.Start(0, time.Minute)
+ defer nodeMgr.Stop()
txMgr := transactions.NewManager(conf)
@@ -553,6 +555,7 @@ func TestCoordinatorStreamDirector_distributesReads(t *testing.T) {
nodeMgr, err := nodes.NewManager(entry, conf, nil, repoStore, promtest.NewMockHistogramVec(), protoregistry.GitalyProtoPreregistered, nil, nil, nil)
require.NoError(t, err)
nodeMgr.Start(0, time.Minute)
+ defer nodeMgr.Stop()
txMgr := transactions.NewManager(conf)
@@ -875,6 +878,7 @@ func TestStreamDirector_repo_creation(t *testing.T) {
nodeMgr, err := nodes.NewManager(testhelper.DiscardTestEntry(t), conf, nil, nil, promtest.NewMockHistogramVec(), protoregistry.GitalyProtoPreregistered, nil, nil, nil)
require.NoError(t, err)
nodeMgr.Start(0, time.Hour)
+ defer nodeMgr.Stop()
router = NewNodeManagerRouter(nodeMgr, rs)
for _, node := range nodeMgr.Nodes()["praefect"] {
@@ -1077,6 +1081,7 @@ func TestAbsentCorrelationID(t *testing.T) {
nodeMgr, err := nodes.NewManager(entry, conf, nil, nil, promtest.NewMockHistogramVec(), protoregistry.GitalyProtoPreregistered, nil, nil, nil)
require.NoError(t, err)
nodeMgr.Start(0, time.Hour)
+ defer nodeMgr.Stop()
txMgr := transactions.NewManager(conf)
rs := datastore.MockRepositoryStore{}
@@ -1211,6 +1216,7 @@ func TestStreamDirectorStorageScope(t *testing.T) {
nodeMgr, err := nodes.NewManager(testhelper.DiscardTestEntry(t), conf, nil, nil, promtest.NewMockHistogramVec(), protoregistry.GitalyProtoPreregistered, nil, nil, nil)
require.NoError(t, err)
nodeMgr.Start(0, time.Second)
+ defer nodeMgr.Stop()
coordinator := NewCoordinator(
nil,
rs,
diff --git a/internal/praefect/datastore/glsql/postgres.go b/internal/praefect/datastore/glsql/postgres.go
index aa814af5c..f9f3eb951 100644
--- a/internal/praefect/datastore/glsql/postgres.go
+++ b/internal/praefect/datastore/glsql/postgres.go
@@ -20,6 +20,7 @@ func OpenDB(conf config.DB) (*sql.DB, error) {
}
if err := db.Ping(); err != nil {
+ db.Close()
return nil, err
}
diff --git a/internal/praefect/grpc-proxy/proxy/handler_ext_test.go b/internal/praefect/grpc-proxy/proxy/handler_ext_test.go
index 0aaea9cfe..35a11f150 100644
--- a/internal/praefect/grpc-proxy/proxy/handler_ext_test.go
+++ b/internal/praefect/grpc-proxy/proxy/handler_ext_test.go
@@ -12,7 +12,6 @@ import (
"net/http"
"net/http/httptest"
"net/url"
- "os"
"path/filepath"
"testing"
"time"
@@ -49,18 +48,7 @@ const (
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer func() {
- testhelper.MustHaveNoChildProcess()
- testhelper.MustHaveNoGoroutines()
- }()
- cleanup := testhelper.Configure()
- defer cleanup()
-
- return m.Run()
+ testhelper.Run(m)
}
// asserting service is implemented on the server side and serves as a handler for stuff
diff --git a/internal/praefect/helper_test.go b/internal/praefect/helper_test.go
index 96e12c32b..597532f56 100644
--- a/internal/praefect/helper_test.go
+++ b/internal/praefect/helper_test.go
@@ -129,6 +129,7 @@ func defaultNodeMgr(t testing.TB, conf config.Config, rs datastore.RepositorySto
nodeMgr, err := nodes.NewManager(testhelper.DiscardTestEntry(t), conf, nil, rs, promtest.NewMockHistogramVec(), protoregistry.GitalyProtoPreregistered, nil, nil, nil)
require.NoError(t, err)
nodeMgr.Start(0, time.Hour)
+ t.Cleanup(nodeMgr.Stop)
return nodeMgr
}
diff --git a/internal/praefect/info_service_test.go b/internal/praefect/info_service_test.go
index 7d1710ffd..36ea0f286 100644
--- a/internal/praefect/info_service_test.go
+++ b/internal/praefect/info_service_test.go
@@ -40,6 +40,7 @@ func TestInfoService_RepositoryReplicas(t *testing.T) {
deps.GetTxManager(),
deps.GetGitCmdFactory(),
deps.GetCatfileCache(),
+ deps.GetConnsPool(),
))
}, testserver.WithDisablePraefect())
cfgNodes = append(cfgNodes, &config.Node{
@@ -63,6 +64,7 @@ func TestInfoService_RepositoryReplicas(t *testing.T) {
nodeManager, err := nodes.NewManager(testhelper.DiscardTestEntry(t), conf, nil, nil, promtest.NewMockHistogramVec(), protoregistry.GitalyProtoPreregistered, nil, nil, nil)
require.NoError(t, err)
nodeManager.Start(0, time.Hour)
+ defer nodeManager.Stop()
cc, _, cleanup := runPraefectServer(t, ctx, conf, buildOptions{
withPrimaryGetter: nodeManager,
withConnections: NodeSetFromNodeManager(nodeManager).Connections(),
diff --git a/internal/praefect/middleware/errorhandler_test.go b/internal/praefect/middleware/errorhandler_test.go
index fada40963..f85deea77 100644
--- a/internal/praefect/middleware/errorhandler_test.go
+++ b/internal/praefect/middleware/errorhandler_test.go
@@ -75,6 +75,7 @@ func TestStreamInterceptor(t *testing.T) {
grpc.WithStreamInterceptor(StreamErrorHandler(registry, errTracker, nodeName)),
)
require.NoError(t, err)
+ t.Cleanup(func() { testhelper.MustClose(t, cc) })
f, err := peeker.Peek()
require.NoError(t, err)
return proxy.NewStreamParameters(proxy.Destination{Conn: cc, Ctx: ctx, Msg: f}, nil, func() error { return nil }, nil), nil
@@ -90,6 +91,7 @@ func TestStreamInterceptor(t *testing.T) {
go praefectSrv.Serve(praefectLis)
praefectCC, err := grpc.Dial("unix://"+praefectSocket, grpc.WithInsecure())
+ defer testhelper.MustClose(t, praefectCC)
require.NoError(t, err)
simpleClient := mock.NewSimpleServiceClient(praefectCC)
diff --git a/internal/praefect/middleware/helper_test.go b/internal/praefect/middleware/helper_test.go
index e40f293dd..b733100c0 100644
--- a/internal/praefect/middleware/helper_test.go
+++ b/internal/praefect/middleware/helper_test.go
@@ -1,19 +1,11 @@
package middleware
import (
- "os"
"testing"
"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper"
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
diff --git a/internal/praefect/nodes/disabled_elector.go b/internal/praefect/nodes/disabled_elector.go
index 740632c47..047e41857 100644
--- a/internal/praefect/nodes/disabled_elector.go
+++ b/internal/praefect/nodes/disabled_elector.go
@@ -40,6 +40,9 @@ func (de *disabledElector) start(bootstrap, _ time.Duration) {
de.updateMetrics()
}
+func (de *disabledElector) stop() {
+}
+
func (de *disabledElector) updateMetrics() {
metrics.PrimaryGauge.WithLabelValues(de.virtualStorage, de.shard.Primary.GetStorage()).Set(1)
for _, n := range de.shard.Secondaries {
diff --git a/internal/praefect/nodes/init_test.go b/internal/praefect/nodes/init_test.go
index 678b275ea..1475680ed 100644
--- a/internal/praefect/nodes/init_test.go
+++ b/internal/praefect/nodes/init_test.go
@@ -1,19 +1,11 @@
package nodes
import (
- "os"
"testing"
"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper"
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) (code int) {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
diff --git a/internal/praefect/nodes/local_elector.go b/internal/praefect/nodes/local_elector.go
index 122ec5c16..bea1ef68b 100644
--- a/internal/praefect/nodes/local_elector.go
+++ b/internal/praefect/nodes/local_elector.go
@@ -19,6 +19,8 @@ type localElector struct {
nodes []Node
primaryNode Node
log logrus.FieldLogger
+
+ doneCh chan struct{}
}
func newLocalElector(name string, log logrus.FieldLogger, ns []*nodeStatus) *localElector {
@@ -31,6 +33,7 @@ func newLocalElector(name string, log logrus.FieldLogger, ns []*nodeStatus) *loc
log: log.WithField("virtual_storage", name),
nodes: nodes[:],
primaryNode: nodes[0],
+ doneCh: make(chan struct{}),
}
}
@@ -61,7 +64,11 @@ func (s *localElector) monitor(d time.Duration) {
ctx := context.Background()
for {
- <-ticker.C
+ select {
+ case <-s.doneCh:
+ return
+ case <-ticker.C:
+ }
err := s.checkNodes(ctx)
if err != nil {
@@ -70,6 +77,10 @@ func (s *localElector) monitor(d time.Duration) {
}
}
+func (s *localElector) stop() {
+ close(s.doneCh)
+}
+
// checkNodes issues a gRPC health check for each node managed by the
// shard.
func (s *localElector) checkNodes(ctx context.Context) error {
diff --git a/internal/praefect/nodes/local_elector_test.go b/internal/praefect/nodes/local_elector_test.go
index 778e85613..2976c32ee 100644
--- a/internal/praefect/nodes/local_elector_test.go
+++ b/internal/praefect/nodes/local_elector_test.go
@@ -20,6 +20,7 @@ func setupElector(t *testing.T) (*localElector, []*nodeStatus, *grpc.ClientConn)
"unix://"+socket,
grpc.WithInsecure(),
)
+ t.Cleanup(func() { testhelper.MustClose(t, cc) })
require.NoError(t, err)
diff --git a/internal/praefect/nodes/manager.go b/internal/praefect/nodes/manager.go
index 2bfd9fb54..e40bf161e 100644
--- a/internal/praefect/nodes/manager.go
+++ b/internal/praefect/nodes/manager.go
@@ -107,6 +107,7 @@ type Mgr struct {
// secondaries are managed.
type leaderElectionStrategy interface {
start(bootstrapInterval, monitorInterval time.Duration)
+ stop()
checkNodes(context.Context) error
GetShard(ctx context.Context) (Shard, error)
}
@@ -208,6 +209,19 @@ func (n *Mgr) Start(bootstrapInterval, monitorInterval time.Duration) {
}
}
+// Stop will stop all monitoring processes and closes connections. Must only be called once.
+func (n *Mgr) Stop() {
+ for _, strategy := range n.strategies {
+ strategy.stop()
+ }
+
+ for _, nodes := range n.nodes {
+ for _, node := range nodes {
+ _ = node.GetConnection().Close()
+ }
+ }
+}
+
// checkShards performs health checks on all the available shards. The
// election strategy is responsible for determining the criteria for
// when to elect a new primary and when a node is down.
diff --git a/internal/praefect/nodes/manager_test.go b/internal/praefect/nodes/manager_test.go
index 51e064ff5..2060c7fcc 100644
--- a/internal/praefect/nodes/manager_test.go
+++ b/internal/praefect/nodes/manager_test.go
@@ -63,6 +63,7 @@ func TestNodeStatus(t *testing.T) {
"unix://"+socket,
grpc.WithInsecure(),
)
+ defer testhelper.MustClose(t, cc)
require.NoError(t, err)
@@ -122,6 +123,7 @@ func TestManagerFailoverDisabledElectionStrategySQL(t *testing.T) {
require.NoError(t, err)
nm.Start(time.Millisecond, time.Millisecond)
+ defer nm.Stop()
ctx, cancel := testhelper.Context()
defer cancel()
@@ -170,6 +172,7 @@ func TestDialWithUnhealthyNode(t *testing.T) {
require.NoError(t, err)
mgr.Start(1*time.Millisecond, 1*time.Millisecond)
+ defer mgr.Stop()
ctx, cancel := testhelper.Context()
defer cancel()
@@ -222,7 +225,10 @@ func TestNodeManager(t *testing.T) {
// monitoring period set to 1 hour as we execute health checks by hands in this test
nm.Start(0, time.Hour)
+ defer nm.Stop()
+
nmWithoutFailover.Start(0, time.Hour)
+ defer nmWithoutFailover.Stop()
ctx, cancel := testhelper.Context()
defer cancel()
@@ -339,6 +345,7 @@ func TestMgr_GetSyncedNode(t *testing.T) {
healthSrvs[i].SetServingStatus("", grpc_health_v1.HealthCheckResponse_SERVING)
}
nm.Start(0, time.Hour)
+ t.Cleanup(nm.Stop)
return func(t *testing.T) { scenario(t, nm, rs) }
}
diff --git a/internal/praefect/nodes/sql_elector.go b/internal/praefect/nodes/sql_elector.go
index 6d8b7bfef..a0007c855 100644
--- a/internal/praefect/nodes/sql_elector.go
+++ b/internal/praefect/nodes/sql_elector.go
@@ -85,6 +85,7 @@ type sqlElector struct {
db *sql.DB
log logrus.FieldLogger
failoverTimeout time.Duration
+ doneCh chan struct{}
}
func newSQLElector(name string, c config.Config, db *sql.DB, log logrus.FieldLogger, ns []*nodeStatus) *sqlElector {
@@ -107,6 +108,7 @@ func newSQLElector(name string, c config.Config, db *sql.DB, log logrus.FieldLog
nodes: nodes,
primaryNode: nodes[0],
failoverTimeout: failoverTimeout,
+ doneCh: make(chan struct{}),
}
}
@@ -137,6 +139,10 @@ func (s *sqlElector) start(bootstrapInterval, monitorInterval time.Duration) {
go s.monitor(monitorInterval)
}
+func (s *sqlElector) stop() {
+ close(s.doneCh)
+}
+
func (s *sqlElector) bootstrap(d time.Duration) {
ctx := context.Background()
s.checkNodes(ctx)
@@ -149,7 +155,11 @@ func (s *sqlElector) monitor(d time.Duration) {
ctx := context.Background()
for {
- <-ticker.C
+ select {
+ case <-s.doneCh:
+ return
+ case <-ticker.C:
+ }
s.checkNodes(ctx)
}
}
diff --git a/internal/praefect/nodes/sql_elector_test.go b/internal/praefect/nodes/sql_elector_test.go
index f88369aa9..b86651e5b 100644
--- a/internal/praefect/nodes/sql_elector_test.go
+++ b/internal/praefect/nodes/sql_elector_test.go
@@ -47,6 +47,7 @@ func TestGetPrimaryAndSecondaries(t *testing.T) {
"unix://"+internalSocket0,
grpc.WithInsecure(),
)
+ defer testhelper.MustClose(t, cc0)
require.NoError(t, err)
storageName := "default"
@@ -85,6 +86,7 @@ func TestSqlElector_slow_execution(t *testing.T) {
"unix://"+gitalySocket,
grpc.WithInsecure(),
)
+ defer testhelper.MustClose(t, gitalyConn)
require.NoError(t, err)
gitalyNodeStatus := newConnectionStatus(config.Node{Storage: "gitaly", Address: "gitaly-address"}, gitalyConn, logger, promtest.NewMockHistogramVec(), nil)
@@ -128,6 +130,7 @@ func TestBasicFailover(t *testing.T) {
addr0,
grpc.WithInsecure(),
)
+ defer testhelper.MustClose(t, cc0)
require.NoError(t, err)
addr1 := "unix://" + internalSocket1
@@ -135,6 +138,7 @@ func TestBasicFailover(t *testing.T) {
addr1,
grpc.WithInsecure(),
)
+ defer testhelper.MustClose(t, cc1)
require.NoError(t, err)
@@ -483,6 +487,7 @@ func TestConnectionMultiplexing(t *testing.T) {
nil,
)
require.NoError(t, err)
+ defer mgr.Stop()
// check the shard to get the primary in a healthy state
mgr.checkShards()
diff --git a/internal/praefect/replicator_pg_test.go b/internal/praefect/replicator_pg_test.go
index d790a88c3..a1eccbed3 100644
--- a/internal/praefect/replicator_pg_test.go
+++ b/internal/praefect/replicator_pg_test.go
@@ -48,6 +48,7 @@ func TestReplicatorInvalidSourceRepository(t *testing.T) {
targetCC, err := client.Dial(ln.Addr().Network()+":"+ln.Addr().String(), nil)
require.NoError(t, err)
+ defer testhelper.MustClose(t, targetCC)
rs := datastore.NewPostgresRepositoryStore(glsql.NewDB(t), nil)
require.NoError(t, rs.SetGeneration(ctx, "virtual-storage-1", "relative-path-1", "gitaly-1", 0))
diff --git a/internal/praefect/replicator_test.go b/internal/praefect/replicator_test.go
index bf6abf37d..35646c33a 100644
--- a/internal/praefect/replicator_test.go
+++ b/internal/praefect/replicator_test.go
@@ -2,7 +2,6 @@ package praefect
import (
"context"
- "os"
"path/filepath"
"strings"
"sync"
@@ -46,16 +45,7 @@ import (
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
-
- cleanup := testhelper.Configure()
- defer cleanup()
-
- return m.Run()
+ testhelper.Run(m)
}
func TestReplMgr_ProcessBacklog(t *testing.T) {
@@ -127,6 +117,7 @@ func TestReplMgr_ProcessBacklog(t *testing.T) {
nodeMgr, err := nodes.NewManager(entry, conf, nil, nil, promtest.NewMockHistogramVec(), protoregistry.GitalyProtoPreregistered, nil, nil, nil)
require.NoError(t, err)
nodeMgr.Start(1*time.Millisecond, 5*time.Millisecond)
+ defer nodeMgr.Stop()
shard, err := nodeMgr.GetShard(ctx, conf.VirtualStorages[0].Name)
require.NoError(t, err)
@@ -331,6 +322,7 @@ func TestReplicator_PropagateReplicationJob(t *testing.T) {
nodeMgr, err := nodes.NewManager(logEntry, conf, nil, nil, promtest.NewMockHistogramVec(), protoregistry.GitalyProtoPreregistered, nil, nil, nil)
require.NoError(t, err)
nodeMgr.Start(0, time.Hour)
+ defer nodeMgr.Stop()
txMgr := transactions.NewManager(conf)
@@ -710,6 +702,7 @@ func TestProcessBacklog_FailedJobs(t *testing.T) {
nodeMgr, err := nodes.NewManager(logEntry, conf, nil, nil, promtest.NewMockHistogramVec(), protoregistry.GitalyProtoPreregistered, nil, nil, nil)
require.NoError(t, err)
nodeMgr.Start(0, time.Hour)
+ defer nodeMgr.Stop()
replMgr := NewReplMgr(
logEntry,
@@ -860,6 +853,7 @@ func TestProcessBacklog_Success(t *testing.T) {
nodeMgr, err := nodes.NewManager(logEntry, conf, nil, nil, promtest.NewMockHistogramVec(), protoregistry.GitalyProtoPreregistered, nil, nil, nil)
require.NoError(t, err)
nodeMgr.Start(0, time.Hour)
+ defer nodeMgr.Stop()
replMgr := NewReplMgr(
logEntry,
diff --git a/internal/praefect/repocleaner/init_test.go b/internal/praefect/repocleaner/init_test.go
index 011d4f2a4..7b5501eab 100644
--- a/internal/praefect/repocleaner/init_test.go
+++ b/internal/praefect/repocleaner/init_test.go
@@ -1,19 +1,11 @@
package repocleaner
import (
- "os"
"testing"
"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper"
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) (code int) {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
diff --git a/internal/praefect/repository_exists_test.go b/internal/praefect/repository_exists_test.go
index cf66210f2..39a25a71d 100644
--- a/internal/praefect/repository_exists_test.go
+++ b/internal/praefect/repository_exists_test.go
@@ -108,6 +108,7 @@ func TestRepositoryExistsHandler(t *testing.T) {
clientConn, err := grpc.DialContext(ctx, "unix://"+ln.Addr().String(), grpc.WithInsecure())
require.NoError(t, err)
+ defer testhelper.MustClose(t, clientConn)
client := gitalypb.NewRepositoryServiceClient(clientConn)
_, err = client.RepositorySize(ctx, &gitalypb.RepositorySizeRequest{Repository: tc.repository})
diff --git a/internal/praefect/server_factory_test.go b/internal/praefect/server_factory_test.go
index a6aea62a8..aba6ac118 100644
--- a/internal/praefect/server_factory_test.go
+++ b/internal/praefect/server_factory_test.go
@@ -80,6 +80,7 @@ func TestServerFactory(t *testing.T) {
nodeMgr, err := nodes.NewManager(logger, conf, nil, rs, &promtest.MockHistogramVec{}, protoregistry.GitalyProtoPreregistered, nil, clientHandshaker, sidechannelRegistry)
require.NoError(t, err)
nodeMgr.Start(0, time.Second)
+ defer nodeMgr.Stop()
registry := protoregistry.GitalyProtoPreregistered
coordinator := NewCoordinator(
diff --git a/internal/praefect/server_test.go b/internal/praefect/server_test.go
index 163c13d4f..20933e5fe 100644
--- a/internal/praefect/server_test.go
+++ b/internal/praefect/server_test.go
@@ -546,6 +546,7 @@ func TestRemoveRepository(t *testing.T) {
)
require.NoError(t, err)
nodeMgr.Start(0, time.Hour)
+ defer nodeMgr.Stop()
ctx, cancel := testhelper.Context()
defer cancel()
@@ -812,6 +813,7 @@ func TestProxyWrites(t *testing.T) {
nodeMgr, err := nodes.NewManager(entry, conf, nil, nil, promtest.NewMockHistogramVec(), protoregistry.GitalyProtoPreregistered, nil, nil, nil)
require.NoError(t, err)
nodeMgr.Start(0, time.Hour)
+ defer nodeMgr.Stop()
ctx, cancel := testhelper.Context()
defer cancel()
@@ -978,6 +980,7 @@ func TestErrorThreshold(t *testing.T) {
rs := datastore.MockRepositoryStore{}
nodeMgr, err := nodes.NewManager(entry, conf, nil, rs, promtest.NewMockHistogramVec(), registry, errorTracker, nil, nil)
require.NoError(t, err)
+ defer nodeMgr.Stop()
coordinator := NewCoordinator(
queue,
@@ -1002,6 +1005,7 @@ func TestErrorThreshold(t *testing.T) {
conn, err := dial("unix://"+socket, []grpc.DialOption{grpc.WithInsecure()})
require.NoError(t, err)
+ defer testhelper.MustClose(t, conn)
cli := mock.NewSimpleServiceClient(conn)
_, repo, _ := testcfg.BuildWithRepo(t)
@@ -1045,6 +1049,7 @@ func newSmartHTTPClient(t *testing.T, serverSocketPath string) (gitalypb.SmartHT
conn, err := grpc.Dial(serverSocketPath, grpc.WithInsecure())
require.NoError(t, err)
+ t.Cleanup(func() { testhelper.MustClose(t, conn) })
return gitalypb.NewSmartHTTPServiceClient(conn), conn
}
diff --git a/internal/safe/main_test.go b/internal/safe/main_test.go
index 3a903c513..7158dca83 100644
--- a/internal/safe/main_test.go
+++ b/internal/safe/main_test.go
@@ -1,19 +1,11 @@
package safe_test
import (
- "os"
"testing"
"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper"
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
- return m.Run()
+ testhelper.Run(m)
}
diff --git a/internal/streamcache/cache.go b/internal/streamcache/cache.go
index ffeca32ce..0ea6ca3f0 100644
--- a/internal/streamcache/cache.go
+++ b/internal/streamcache/cache.go
@@ -122,18 +122,19 @@ type cache struct {
stopOnce sync.Once
logger logrus.FieldLogger
dir string
+ sleepLoop *dontpanic.Forever
}
// New returns a new cache instance.
func New(cfg config.StreamCacheConfig, logger logrus.FieldLogger) Cache {
if cfg.Enabled {
- return newCacheWithSleep(cfg.Dir, cfg.MaxAge.Duration(), time.Sleep, logger)
+ return newCacheWithSleep(cfg.Dir, cfg.MaxAge.Duration(), time.After, logger)
}
return NullCache{}
}
-func newCacheWithSleep(dir string, maxAge time.Duration, sleep func(time.Duration), logger logrus.FieldLogger) Cache {
+func newCacheWithSleep(dir string, maxAge time.Duration, sleep func(time.Duration) <-chan time.Time, logger logrus.FieldLogger) Cache {
fs := newFilestore(dir, maxAge, sleep, logger)
c := &cache{
@@ -143,13 +144,15 @@ func newCacheWithSleep(dir string, maxAge time.Duration, sleep func(time.Duratio
stop: make(chan struct{}),
logger: logger,
dir: dir,
+ sleepLoop: dontpanic.NewForever(time.Minute),
}
- dontpanic.GoForever(1*time.Minute, func() {
+ c.sleepLoop.Go(func() {
sleepLoop(c.stop, c.maxAge, sleep, c.clean)
})
go func() {
<-c.stop
+ c.sleepLoop.Cancel()
fs.Stop()
}()
@@ -353,19 +356,17 @@ func (w *waiter) Wait(ctx context.Context) error {
}
}
-func sleepLoop(done chan struct{}, period time.Duration, sleep func(time.Duration), callback func()) {
+func sleepLoop(done chan struct{}, period time.Duration, sleep func(time.Duration) <-chan time.Time, callback func()) {
const maxPeriod = time.Minute
if period <= 0 || period >= maxPeriod {
period = maxPeriod
}
for {
- sleep(period)
-
select {
case <-done:
return
- default:
+ case <-sleep(period):
}
callback()
diff --git a/internal/streamcache/cache_test.go b/internal/streamcache/cache_test.go
index 708d09fd9..f562dad42 100644
--- a/internal/streamcache/cache_test.go
+++ b/internal/streamcache/cache_test.go
@@ -10,7 +10,6 @@ import (
"os"
"path/filepath"
"strings"
- "sync"
"testing"
"time"
@@ -221,35 +220,6 @@ func TestCache_scope(t *testing.T) {
}
}
-type clock struct {
- n int
- sync.Mutex
- *sync.Cond
-}
-
-func newClock() *clock {
- cl := &clock{}
- cl.Cond = sync.NewCond(cl)
- return cl
-}
-
-func (cl *clock) wait() {
- cl.Lock()
- defer cl.Unlock()
-
- for old := cl.n; old == cl.n; {
- cl.Cond.Wait()
- }
-}
-
-func (cl *clock) advance() {
- cl.Lock()
- defer cl.Unlock()
-
- cl.n++
- cl.Cond.Broadcast()
-}
-
func TestCache_diskCleanup(t *testing.T) {
tmp := testhelper.TempDir(t)
@@ -257,8 +227,11 @@ func TestCache_diskCleanup(t *testing.T) {
key = "test key"
)
- cl := newClock()
- c := newCacheWithSleep(tmp, 0, func(time.Duration) { cl.wait() }, log.Default())
+ timerCh := make(chan time.Time)
+
+ c := newCacheWithSleep(tmp, 0, func(time.Duration) <-chan time.Time {
+ return timerCh
+ }, log.Default())
defer c.Stop()
content := func(i int) string { return fmt.Sprintf("content %d", i) }
@@ -278,7 +251,7 @@ func TestCache_diskCleanup(t *testing.T) {
requireCacheEntries(t, c, 1)
// Unblock cleanup goroutines so they run exactly once
- cl.advance()
+ close(timerCh)
// Give them time to do their work
time.Sleep(10 * time.Millisecond)
diff --git a/internal/streamcache/filestore.go b/internal/streamcache/filestore.go
index 67337c95f..8933bc127 100644
--- a/internal/streamcache/filestore.go
+++ b/internal/streamcache/filestore.go
@@ -56,16 +56,19 @@ type filestore struct {
id []byte
counter uint64
stop chan struct{}
+
+ sleepLoop *dontpanic.Forever
}
-func newFilestore(dir string, maxAge time.Duration, sleep func(time.Duration), logger logrus.FieldLogger) *filestore {
+func newFilestore(dir string, maxAge time.Duration, sleep func(time.Duration) <-chan time.Time, logger logrus.FieldLogger) *filestore {
fs := &filestore{
- dir: dir,
- maxAge: maxAge,
- stop: make(chan struct{}),
+ dir: dir,
+ maxAge: maxAge,
+ stop: make(chan struct{}),
+ sleepLoop: dontpanic.NewForever(time.Minute),
}
- dontpanic.GoForever(1*time.Minute, func() {
+ fs.sleepLoop.Go(func() {
sleepLoop(fs.stop, fs.maxAge, sleep, func() {
diskUsageGauge.WithLabelValues(fs.dir).Set(fs.diskUsage())
@@ -146,6 +149,8 @@ func (fs *filestore) Stop() {
default:
close(fs.stop)
}
+
+ fs.sleepLoop.Cancel()
}
// cleanWalk removes files but not directories. This is to avoid races
diff --git a/internal/streamcache/filestore_test.go b/internal/streamcache/filestore_test.go
index b5c1f055e..cf8a29506 100644
--- a/internal/streamcache/filestore_test.go
+++ b/internal/streamcache/filestore_test.go
@@ -16,7 +16,7 @@ import (
func TestFilestoreCreate(t *testing.T) {
tmp := testhelper.TempDir(t)
- fs := newFilestore(tmp, 0, time.Sleep, log.Default())
+ fs := newFilestore(tmp, 0, time.After, log.Default())
defer fs.Stop()
f, err := fs.Create()
@@ -39,7 +39,7 @@ func TestFilestoreCreate(t *testing.T) {
func TestFilestoreCreate_concurrency(t *testing.T) {
tmp := testhelper.TempDir(t)
- fs := newFilestore(tmp, time.Hour, time.Sleep, log.Default())
+ fs := newFilestore(tmp, time.Hour, time.After, log.Default())
defer fs.Stop()
const N = 100
@@ -81,7 +81,7 @@ func TestFilestoreCreate_uniqueness(t *testing.T) {
filenames := make(map[string]struct{})
for j := 0; j < M; j++ {
- fs := newFilestore(tmp, time.Hour, time.Sleep, log.Default())
+ fs := newFilestore(tmp, time.Hour, time.After, log.Default())
defer fs.Stop()
for i := 0; i < N; i++ {
@@ -101,7 +101,7 @@ func TestFilestoreCreate_uniqueness(t *testing.T) {
func TestFilestoreCleanwalk(t *testing.T) {
tmp := testhelper.TempDir(t)
- fs := newFilestore(tmp, time.Hour, time.Sleep, log.Default())
+ fs := newFilestore(tmp, time.Hour, time.After, log.Default())
defer fs.Stop()
dir1 := filepath.Join(tmp, "dir1")
diff --git a/internal/streamcache/testhelper_test.go b/internal/streamcache/testhelper_test.go
index 1427567b4..03bcc2acf 100644
--- a/internal/streamcache/testhelper_test.go
+++ b/internal/streamcache/testhelper_test.go
@@ -1,15 +1,11 @@
package streamcache
import (
- "os"
"testing"
"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper"
)
-func TestMain(m *testing.M) { os.Exit(testMain(m)) }
-
-func testMain(m *testing.M) int {
- defer testhelper.Configure()()
- return m.Run()
+func TestMain(m *testing.M) {
+ testhelper.Run(m)
}
diff --git a/internal/supervisor/monitor.go b/internal/supervisor/monitor.go
index 08a112cd4..2e6a3dc71 100644
--- a/internal/supervisor/monitor.go
+++ b/internal/supervisor/monitor.go
@@ -93,6 +93,10 @@ func monitorHealth(f func() error, events chan<- Event, name string, shutdown <-
return
}
- time.Sleep(15 * time.Second)
+ select {
+ case <-shutdown:
+ return
+ case <-time.After(15 * time.Second):
+ }
}
}
diff --git a/internal/supervisor/supervisor_test.go b/internal/supervisor/supervisor_test.go
index 9e2642d57..ccd8c1a93 100644
--- a/internal/supervisor/supervisor_test.go
+++ b/internal/supervisor/supervisor_test.go
@@ -12,7 +12,6 @@ import (
"testing"
"time"
- log "github.com/sirupsen/logrus"
"github.com/stretchr/testify/require"
"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper"
)
@@ -24,45 +23,32 @@ var (
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
+ testhelper.Run(m, testhelper.WithSetup(func() error {
+ var err error
+ testDir, err = os.MkdirTemp("", "gitaly-supervisor-test")
+ if err != nil {
+ return err
+ }
- var err error
- testDir, err = os.MkdirTemp("", "gitaly-supervisor-test")
- if err != nil {
- log.Error(err)
- return 1
- }
- defer func() {
- if err := os.RemoveAll(testDir); err != nil {
- log.Error(err)
+ scriptPath, err := filepath.Abs("test-scripts/pid-server.go")
+ if err != nil {
+ return err
}
- }()
- scriptPath, err := filepath.Abs("test-scripts/pid-server.go")
- if err != nil {
- log.Error(err)
- return 1
- }
+ testExe = filepath.Join(testDir, "pid-server")
- testExe = filepath.Join(testDir, "pid-server")
- buildCmd := exec.Command("go", "build", "-o", testExe, scriptPath)
- buildCmd.Dir = filepath.Dir(scriptPath)
- buildCmd.Stderr = os.Stderr
- buildCmd.Stdout = os.Stdout
- if err := buildCmd.Run(); err != nil {
- log.Error(err)
- return 1
- }
+ buildCmd := exec.Command("go", "build", "-o", testExe, scriptPath)
+ buildCmd.Dir = filepath.Dir(scriptPath)
+ buildCmd.Stderr = os.Stderr
+ buildCmd.Stdout = os.Stdout
+ if err := buildCmd.Run(); err != nil {
+ return err
+ }
- socketPath = filepath.Join(testDir, "socket")
+ socketPath = filepath.Join(testDir, "socket")
- return m.Run()
+ return nil
+ }))
}
func TestRespawnAfterCrashWithoutCircuitBreaker(t *testing.T) {
diff --git a/internal/tempdir/testhelper_test.go b/internal/tempdir/testhelper_test.go
index 6c4397185..cdc9dc00e 100644
--- a/internal/tempdir/testhelper_test.go
+++ b/internal/tempdir/testhelper_test.go
@@ -1,20 +1,11 @@
package tempdir
import (
- "os"
"testing"
"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper"
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
- cleanup := testhelper.Configure()
- defer cleanup()
-
- return m.Run()
+ testhelper.Run(m)
}
diff --git a/internal/testhelper/configure.go b/internal/testhelper/configure.go
index ea993b678..f9319c42a 100644
--- a/internal/testhelper/configure.go
+++ b/internal/testhelper/configure.go
@@ -8,6 +8,7 @@ import (
"runtime"
"strings"
"sync"
+ "testing"
log "github.com/sirupsen/logrus"
"gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/config"
@@ -19,35 +20,102 @@ var (
testDirectory string
)
-// Configure sets up the global test configuration. On failure,
+// RunOption is an option that can be passed to Run.
+type RunOption func(*runConfig)
+
+type runConfig struct {
+ setup func() error
+ disableGoroutineChecks bool
+}
+
+// WithSetup allows the caller of Run to pass a setup function that will be called after global
+// test state has been configured.
+func WithSetup(setup func() error) RunOption {
+ return func(cfg *runConfig) {
+ cfg.setup = setup
+ }
+}
+
+// WithDisabledGoroutineChecker disables checking for leaked Goroutines after tests have run. This
+// should ideally only be used as a temporary measure until all Goroutine leaks have been fixed.
+//
+// Deprecated: This should not be used, but instead you should try to fix all Goroutine leakages.
+func WithDisabledGoroutineChecker() RunOption {
+ return func(cfg *runConfig) {
+ cfg.disableGoroutineChecks = true
+ }
+}
+
+// Run sets up required testing state and executes the given test suite. It can optionally receive a
+// variable number of RunOptions.
+func Run(m *testing.M, opts ...RunOption) {
+ // Run tests in a separate function such that we can use deferred statements and still
+ // (indirectly) call `os.Exit()` in case the test setup failed.
+ if err := func() error {
+ var cfg runConfig
+ for _, opt := range opts {
+ opt(&cfg)
+ }
+
+ defer mustHaveNoChildProcess()
+ if !cfg.disableGoroutineChecks {
+ defer mustHaveNoGoroutines()
+ }
+
+ cleanup, err := configure()
+ if err != nil {
+ return err
+ }
+ defer cleanup()
+
+ if cfg.setup != nil {
+ if err := cfg.setup(); err != nil {
+ return fmt.Errorf("error calling setup function: %w", err)
+ }
+ }
+
+ m.Run()
+
+ return nil
+ }(); err != nil {
+ log.Fatalf("%v", err)
+ }
+}
+
+// configure sets up the global test configuration. On failure,
// terminates the program.
-func Configure() func() {
+func configure() (func(), error) {
+ var returnedErr error
configureOnce.Do(func() {
gitalylog.Configure(gitalylog.Loggers, "json", "panic")
testDirectory = getTestTmpDir()
for _, f := range []func() error{
- ConfigureGit,
+ configureGit,
} {
- if err := f(); err != nil {
+ if returnedErr = f(); returnedErr != nil {
if err := os.RemoveAll(testDirectory); err != nil {
log.Error(err)
}
- log.Fatalf("error configuring tests: %v", err)
+
+ return
}
}
})
+ if returnedErr != nil {
+ return nil, returnedErr
+ }
return func() {
if err := os.RemoveAll(testDirectory); err != nil {
- log.Fatalf("error removing test directory: %v", err)
+ log.Errorf("error removing test directory: %v", err)
}
- }
+ }, nil
}
-// ConfigureGit configures git for test purpose
-func ConfigureGit() error {
+// configureGit configures git for test purpose
+func configureGit() error {
// We cannot use gittest here given that we ain't got no config yet. We thus need to
// manually resolve the git executable, which is either stored in below envvar if
// executed via our Makefile, or else just git as resolved via PATH.
@@ -108,7 +176,7 @@ func ConfigureRuby(cfg *config.Cfg) error {
}
if err := cfg.ConfigureRuby(); err != nil {
- log.Fatalf("validate ruby config: %v", err)
+ return fmt.Errorf("validate ruby config: %w", err)
}
return nil
diff --git a/internal/testhelper/leakage.go b/internal/testhelper/leakage.go
new file mode 100644
index 000000000..946b867d2
--- /dev/null
+++ b/internal/testhelper/leakage.go
@@ -0,0 +1,99 @@
+package testhelper
+
+import (
+ "fmt"
+ "os"
+ "os/exec"
+ "strings"
+ "syscall"
+ "time"
+
+ "gitlab.com/gitlab-org/gitaly/v14/internal/command/commandcounter"
+ "gitlab.com/gitlab-org/gitaly/v14/internal/helper/text"
+ "go.uber.org/goleak"
+)
+
+// mustHaveNoGoroutines panics if it finds any Goroutines running.
+func mustHaveNoGoroutines() {
+ if err := goleak.Find(
+ // opencensus has a "defaultWorker" which is started by the package's
+ // `init()` function. There is no way to stop this worker, so it will leak
+ // whenever we import the package.
+ goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"),
+ // The Ruby server's load balancer is registered in the `init()` function
+ // of our "rubyserver/balancer" package. Ideally we'd clean this up
+ // eventually, but the pragmatic approach is to just wait until we remove
+ // the Ruby sidecar altogether.
+ goleak.IgnoreTopFunction("google.golang.org/grpc.(*ccBalancerWrapper).watcher"),
+ goleak.IgnoreTopFunction("gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/rubyserver/balancer.(*builder).monitor"),
+ // labkit's logger spawns a Goroutine which cannot be closed when calling
+ // `Initialize()`.
+ goleak.IgnoreTopFunction("gitlab.com/gitlab-org/labkit/log.listenForSignalHangup"),
+ // The backchannel code is somehow stock on closing its connections. I have no clue
+ // why that is, but we should investigate.
+ goleak.IgnoreTopFunction("gitlab.com/gitlab-org/gitaly/v14/internal/backchannel.clientHandshake.serve.func4"),
+ ); err != nil {
+ panic(fmt.Errorf("goroutines running: %w", err))
+ }
+}
+
+// mustHaveNoChildProcess panics if it finds a running or finished child
+// process. It waits for 2 seconds for processes to be cleaned up by other
+// goroutines.
+func mustHaveNoChildProcess() {
+ waitDone := make(chan struct{})
+ go func() {
+ commandcounter.WaitAllDone()
+ close(waitDone)
+ }()
+
+ select {
+ case <-waitDone:
+ case <-time.After(2 * time.Second):
+ }
+
+ if err := mustFindNoFinishedChildProcess(); err != nil {
+ panic(err)
+ }
+
+ if err := mustFindNoRunningChildProcess(); err != nil {
+ panic(err)
+ }
+}
+
+func mustFindNoFinishedChildProcess() error {
+ // Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error)
+ //
+ // We use pid -1 to wait for any child. We don't care about wstatus or
+ // rusage. Use WNOHANG to return immediately if there is no child waiting
+ // to be reaped.
+ wpid, err := syscall.Wait4(-1, nil, syscall.WNOHANG, nil)
+ if err == nil && wpid > 0 {
+ return fmt.Errorf("wait4 found child process %d", wpid)
+ }
+
+ return nil
+}
+
+func mustFindNoRunningChildProcess() error {
+ pgrep := exec.Command("pgrep", "-P", fmt.Sprintf("%d", os.Getpid()))
+ desc := fmt.Sprintf("%q", strings.Join(pgrep.Args, " "))
+
+ out, err := pgrep.Output()
+ if err == nil {
+ pidsComma := strings.Replace(text.ChompBytes(out), "\n", ",", -1)
+ psOut, _ := exec.Command("ps", "-o", "pid,args", "-p", pidsComma).Output()
+ return fmt.Errorf("found running child processes %s:\n%s", pidsComma, psOut)
+ }
+
+ exitError, ok := err.(*exec.ExitError)
+ if !ok {
+ return fmt.Errorf("expected ExitError, got %T", err)
+ }
+
+ if exitError.ExitCode() == 1 {
+ return nil
+ }
+
+ return fmt.Errorf("%s: %w", desc, err)
+}
diff --git a/internal/testhelper/testhelper.go b/internal/testhelper/testhelper.go
index 30bd253ac..7a52ce3ee 100644
--- a/internal/testhelper/testhelper.go
+++ b/internal/testhelper/testhelper.go
@@ -16,8 +16,6 @@ import (
"os"
"os/exec"
"path/filepath"
- "strings"
- "syscall"
"testing"
"time"
@@ -25,12 +23,9 @@ import (
log "github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "gitlab.com/gitlab-org/gitaly/v14/internal/command"
"gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/config"
"gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/storage"
- "gitlab.com/gitlab-org/gitaly/v14/internal/helper/text"
"gitlab.com/gitlab-org/gitaly/v14/internal/metadata/featureflag"
- "go.uber.org/goleak"
"google.golang.org/grpc/metadata"
)
@@ -165,68 +160,6 @@ func GetLocalhostListener(t testing.TB) (net.Listener, string) {
return l, addr
}
-// MustHaveNoGoroutines panics if it finds any Goroutines running.
-func MustHaveNoGoroutines() {
- if err := goleak.Find(
- // opencensus has a "defaultWorker" which is started by the package's
- // `init()` function. There is no way to stop this worker, so it will leak
- // whenever we import the package.
- goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"),
- ); err != nil {
- panic(fmt.Errorf("goroutines running: %w", err))
- }
-}
-
-// MustHaveNoChildProcess panics if it finds a running or finished child
-// process. It waits for 2 seconds for processes to be cleaned up by other
-// goroutines.
-func MustHaveNoChildProcess() {
- waitDone := make(chan struct{})
- go func() {
- command.WaitAllDone()
- close(waitDone)
- }()
-
- select {
- case <-waitDone:
- case <-time.After(2 * time.Second):
- }
-
- mustFindNoFinishedChildProcess()
- mustFindNoRunningChildProcess()
-}
-
-func mustFindNoFinishedChildProcess() {
- // Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error)
- //
- // We use pid -1 to wait for any child. We don't care about wstatus or
- // rusage. Use WNOHANG to return immediately if there is no child waiting
- // to be reaped.
- wpid, err := syscall.Wait4(-1, nil, syscall.WNOHANG, nil)
- if err == nil && wpid > 0 {
- panic(fmt.Errorf("wait4 found child process %d", wpid))
- }
-}
-
-func mustFindNoRunningChildProcess() {
- pgrep := exec.Command("pgrep", "-P", fmt.Sprintf("%d", os.Getpid()))
- desc := fmt.Sprintf("%q", strings.Join(pgrep.Args, " "))
-
- out, err := pgrep.Output()
- if err == nil {
- pidsComma := strings.Replace(text.ChompBytes(out), "\n", ",", -1)
- psOut, _ := exec.Command("ps", "-o", "pid,args", "-p", pidsComma).Output()
- panic(fmt.Errorf("found running child processes %s:\n%s", pidsComma, psOut))
- }
-
- if status, ok := command.ExitStatus(err); ok && status == 1 {
- // Exit status 1 means no processes were found
- return
- }
-
- panic(fmt.Errorf("%s: %w", desc, err))
-}
-
// ContextOpt returns a new context instance with the new additions to it.
type ContextOpt func(context.Context) (context.Context, func())
diff --git a/internal/testhelper/testserver/gitaly.go b/internal/testhelper/testserver/gitaly.go
index 7dac962f3..cf7bf7b04 100644
--- a/internal/testhelper/testserver/gitaly.go
+++ b/internal/testhelper/testserver/gitaly.go
@@ -350,6 +350,7 @@ func (gsd *gitalyServerDeps) createDependencies(t testing.TB, cfg config.Cfg, ru
if gsd.packObjectsCache == nil {
gsd.packObjectsCache = streamcache.New(cfg.PackObjectsCache, gsd.logger)
+ t.Cleanup(gsd.packObjectsCache.Stop)
}
return &service.Dependencies{
diff --git a/internal/transaction/voting/testhelper_test.go b/internal/transaction/voting/testhelper_test.go
index 0c8359afd..59ee6c4a8 100644
--- a/internal/transaction/voting/testhelper_test.go
+++ b/internal/transaction/voting/testhelper_test.go
@@ -1,21 +1,11 @@
package voting
import (
- "os"
"testing"
"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper"
)
func TestMain(m *testing.M) {
- os.Exit(testMain(m))
-}
-
-func testMain(m *testing.M) int {
- defer testhelper.MustHaveNoChildProcess()
-
- cleanup := testhelper.Configure()
- defer cleanup()
-
- return m.Run()
+ testhelper.Run(m)
}