test: use t.Context() instead of context.Background() (#1306)

The test context is cancelled when the test ends, so anything still holding it stops instead of leaking into the next test. Uses inside `t.Cleanup`, `defer` and `go func` blocks are left alone, as the context is already cancelled there.

Stacked on https://gitea.com/gitea/runner/pulls/1305.

Assisted-by: Codet
Co-authored-by: bircni <[email protected]>
Reviewed-on: https://gitea.com/gitea/runner/pulls/1306
Reviewed-by: bircni <[email protected]>
This commit is contained in:
Lunny Xiaoandbircni committed 2026-10-12 21:11:17 +00:00
1 parent 160e18e705
commit c3c647ef83
38 files changed
+288 -301

No files matched your search

+1 -2
View File
@@ -5,7 +5,6 @@
package container
import (
"context"
"fmt"
"os"
"os/exec"
@@ -42,7 +41,7 @@ func buildScratchImage(t *testing.T, platform string) string {
func TestImageExistsLocally(t *testing.T) {
requireDocker(t)
ctx := context.Background()
ctx := t.Context()
// a non-existent image is reported absent
missing, err := ImageExistsLocally(ctx, "library/alpine:this-random-tag-will-never-exist", "linux/amd64")
+4 -4
View File
@@ -19,7 +19,7 @@ import (
)
func TestIsolatedCacheContainer(t *testing.T) {
ctx := context.Background()
ctx := t.Context()
cache, lan := netip.MustParseAddr("172.18.0.3"), netip.MustParseAddr("192.168.1.20")
client := &mockDockerClient{}
client.On("ContainerList", ctx, mobyclient.ContainerListOptions{}).Return(mobyclient.ContainerListResult{Items: []container.Summary{{}, {
@@ -58,7 +58,7 @@ func TestIsAddressPoolExhausted(t *testing.T) {
}
func TestCreateDockerNetworkInheritsDaemonMTU(t *testing.T) {
ctx := context.Background()
ctx := t.Context()
for _, tc := range []struct {
bridgeOptions, want map[string]string
}{
@@ -87,7 +87,7 @@ func (m *mockDockerClient) NetworkDisconnect(ctx context.Context, id string, opt
}
func TestConnectAndDisconnectNetwork(t *testing.T) {
ctx := context.Background()
ctx := t.Context()
connect := func(answer error) error {
client := &mockDockerClient{}
client.On("NetworkConnect", ctx, "jobs", mobyclient.NetworkConnectOptions{
@@ -117,7 +117,7 @@ func TestConnectAndDisconnectNetwork(t *testing.T) {
// and old enough to predate any job now starting are the runner's to reclaim. An unexpected
// NetworkRemove fails the test on its own, since testify has no expectation to match it against.
func TestRemoveOrphanNetworks(t *testing.T) {
ctx := context.Background()
ctx := t.Context()
cutoff := time.Date(2026, time.April, 29, 20, 0, 0, 0, time.UTC)
client := &mockDockerClient{}
client.On("NetworkList", ctx, mobyclient.NetworkListOptions{
+2 -2
View File
@@ -285,7 +285,7 @@ func TestRemoveLabelledRemovesContainersNetworksAndVolumes(t *testing.T) {
containerFailure := errors.New("container removal failed")
listFailure := errors.New("listing failed")
volumeFailure := errors.New("volume removal failed")
ctx := context.Background()
ctx := t.Context()
filters := make(mobyclient.Filters).Add("label", jobLabel+"=job-1")
cli := &mockDockerClient{}
cli.On("ContainerList", ctx, mobyclient.ContainerListOptions{All: true, Filters: filters}).
@@ -312,7 +312,7 @@ func TestRemoveLabelledRemovesContainersNetworksAndVolumes(t *testing.T) {
func TestDockerProxyWithDaemon(t *testing.T) {
requireDocker(t)
ctx := context.Background()
ctx := t.Context()
require.NoError(t, NewDockerPullExecutor(NewDockerPullExecutorInput{Image: "alpine"})(ctx))
direct, err := GetDockerClient(ctx)
require.NoError(t, err)
+2 -3
View File
@@ -5,7 +5,6 @@
package container
import (
"context"
"io"
"strings"
"testing"
@@ -37,13 +36,13 @@ func TestCleanImage(t *testing.T) {
}
for _, table := range tables {
imageOut := cleanImage(context.Background(), table.imageIn)
imageOut := cleanImage(t.Context(), table.imageIn)
assert.Equal(t, table.imageOut, imageOut)
}
}
func TestGetImagePullOptions(t *testing.T) {
ctx := context.Background()
ctx := t.Context()
orig := config.Dir()
t.Cleanup(func() { config.SetDir(orig) })
+16 -16
View File
@@ -166,7 +166,7 @@ func (m *mockConn) Close() (err error) {
}
func TestDockerExecAbort(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
ctx, cancel := context.WithCancel(t.Context())
reader := &interruptReader{started: make(chan struct{}), interrupted: make(chan struct{}), stopped: make(chan struct{})}
conn := &mockConn{}
@@ -207,7 +207,7 @@ func TestDockerExecAbort(t *testing.T) {
}
func TestDockerExecFailure(t *testing.T) {
ctx := context.Background()
ctx := t.Context()
conn := &mockConn{}
@@ -254,7 +254,7 @@ func stdcopyFrame(stream stdcopy.StdType, payload string) []byte {
// attach() streaming goroutine has drained and flushed the container's output,
// so a final line without a trailing newline is not lost.
func TestDockerAttachFlushesTrailingLine(t *testing.T) {
ctx := context.Background()
ctx := t.Context()
framed := bytes.NewBuffer(stdcopyFrame(stdcopy.Stdout, "line one\nlast line without newline"))
@@ -303,7 +303,7 @@ func TestDockerAttachFlushesTrailingLine(t *testing.T) {
}
func TestDockerWaitFailure(t *testing.T) {
ctx := context.Background()
ctx := t.Context()
statusCh := make(chan container.WaitResponse, 1)
statusCh <- container.WaitResponse{StatusCode: 2}
@@ -355,7 +355,7 @@ func TestRemoveIgnoresAutoRemoveRace(t *testing.T) {
} {
t.Run(tc.name, func(t *testing.T) {
logger, hook := logtest.NewLogger()
ctx := common.WithLogger(context.Background(), logger)
ctx := common.WithLogger(t.Context(), logger)
client := &mockDockerClient{}
client.On("ContainerKill", ctx, "abc", killOpts).Return(mobyclient.ContainerKillResult{}, nil)
client.On("ContainerRemove", ctx, "abc", removeOpts).Return(mobyclient.ContainerRemoveResult{}, tc.err)
@@ -388,7 +388,7 @@ func TestRemoveIgnoresAutoRemoveRace(t *testing.T) {
// create() lost its reply, must still be removed rather than leaking with its network. It
// was never started here, so it is not worth a kill of its own.
func TestRemoveWithoutIDUsesName(t *testing.T) {
ctx := context.Background()
ctx := t.Context()
client := &mockDockerClient{}
client.On("ContainerRemove", ctx, "job-1", mobyclient.ContainerRemoveOptions{RemoveVolumes: true, Force: true}).
Return(mobyclient.ContainerRemoveResult{}, nil)
@@ -401,7 +401,7 @@ func TestRemoveWithoutIDUsesName(t *testing.T) {
// find() must drop a stale cached id so later Copy/Exec don't hit the
// daemon with a torn-down container.
func TestFindRevalidatesStaleID(t *testing.T) {
ctx := context.Background()
ctx := t.Context()
notFound := cerrdefs.ErrNotFound.WithMessage("No such container")
boom := errors.New("daemon unreachable")
newCR := func(id string) (*containerReference, *mockDockerClient) {
@@ -459,7 +459,7 @@ func TestFindRevalidatesStaleID(t *testing.T) {
// Every daemon entry point fails fast with a clear, container-named
// error when no live cr.id is known.
func TestRejectsMissingContainer(t *testing.T) {
ctx := context.Background()
ctx := t.Context()
client := &mockDockerClient{}
client.On("ContainerList", ctx, mobyclient.ContainerListOptions{All: true}).Return(mobyclient.ContainerListResult{}, nil)
cr := &containerReference{cli: client, input: &NewContainerInput{Name: "job-1"}}
@@ -616,7 +616,7 @@ func TestCheckVolumes(t *testing.T) {
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
logger, hook := logtest.NewLogger()
ctx := common.WithLogger(context.Background(), logger)
ctx := common.WithLogger(t.Context(), logger)
cr := &containerReference{
input: &NewContainerInput{
ValidVolumes: tc.validVolumes,
@@ -656,12 +656,12 @@ func TestMergeContainerConfigsKeepsTheRunnersFilesAndEnvToItself(t *testing.T) {
logger := logging.New(logtest.New())
cr := &containerReference{input: &NewContainerInput{NetworkMode: "bridge", WorkflowOptions: option}}
_, _, err := cr.mergeContainerConfigs(common.WithLogger(context.Background(), logger), &container.Config{}, &container.HostConfig{})
_, _, err := cr.mergeContainerConfigs(common.WithLogger(t.Context(), logger), &container.Config{}, &container.HostConfig{})
require.ErrorContains(t, err, "not allowed in a workflow")
// the runner reading its own files is what those options are for
cr = &containerReference{input: &NewContainerInput{NetworkMode: "bridge", RunnerOptions: option}}
_, _, err = cr.mergeContainerConfigs(common.WithLogger(context.Background(), logger), &container.Config{}, &container.HostConfig{})
_, _, err = cr.mergeContainerConfigs(common.WithLogger(t.Context(), logger), &container.Config{}, &container.HostConfig{})
require.NoError(t, err)
}
@@ -673,7 +673,7 @@ func TestMergeContainerConfigsKeepsTheRunnersFilesAndEnvToItself(t *testing.T) {
WorkflowOptions: "--env RUNNER_SECRET --env GIVEN=value",
}}
config, _, err := cr.mergeContainerConfigs(common.WithLogger(context.Background(), logger), &container.Config{}, &container.HostConfig{})
config, _, err := cr.mergeContainerConfigs(common.WithLogger(t.Context(), logger), &container.Config{}, &container.HostConfig{})
require.NoError(t, err)
assert.Equal(t, []string{"RUNNER_SECRET", "RUNNER_SECRET", "GIVEN=value"}, config.Env)
}
@@ -723,7 +723,7 @@ func mergeOptions(t *testing.T, runnerOptions, workflowOptions string, privilege
ValidVolumes: []string{"**"},
}}
_, hostConfig, err := cr.mergeContainerConfigs(common.WithLogger(context.Background(), logger), &container.Config{}, &container.HostConfig{
_, hostConfig, err := cr.mergeContainerConfigs(common.WithLogger(t.Context(), logger), &container.Config{}, &container.HostConfig{
Privileged: privileged,
UsernsMode: container.UsernsMode("private"),
NetworkMode: container.NetworkMode("bridge"),
@@ -767,7 +767,7 @@ func TestMergeContainerConfigsStripsDangerousOptionsWhenUnprivileged(t *testing.
func TestCheckVolumesRejectsEscapingHostPaths(t *testing.T) {
logger := logging.New(logtest.New())
ctx := common.WithLogger(context.Background(), logger)
ctx := common.WithLogger(t.Context(), logger)
base := t.TempDir()
allowed := filepath.Join(base, "allowed")
@@ -808,7 +808,7 @@ func TestSanitizeConfigKeepsTmpfsMounts(t *testing.T) {
for _, validVolumes := range [][]string{nil, {"data"}, {"**:ro"}} {
logger, hook := logtest.NewLogger()
_, sanitized := (&containerReference{input: &NewContainerInput{ValidVolumes: validVolumes}}).sanitizeConfig(common.WithLogger(context.Background(), logger), &container.Config{}, &container.HostConfig{Mounts: []mount.Mount{
_, sanitized := (&containerReference{input: &NewContainerInput{ValidVolumes: validVolumes}}).sanitizeConfig(common.WithLogger(t.Context(), logger), &container.Config{}, &container.HostConfig{Mounts: []mount.Mount{
hostConfig.Mounts[0],
{Type: mount.TypeVolume, Target: "/anonymous"},
{Type: mount.TypeTmpfs, Source: "/etc", Target: "/etc-copy"},
@@ -898,7 +898,7 @@ func TestContainerInfoFromInspect(t *testing.T) {
func TestMergeContainerConfigsVolumesReplaceRunnerMounts(t *testing.T) {
logger := logging.New(logtest.New())
ctx := common.WithLogger(context.Background(), logger)
ctx := common.WithLogger(t.Context(), logger)
cr := &containerReference{
input: &NewContainerInput{
NetworkMode: "bridge",
+1 -2
View File
@@ -4,7 +4,6 @@
package container
import (
"context"
"testing"
mobyclient "github.com/moby/moby/client"
@@ -15,7 +14,7 @@ import (
// so the daemon has to be pinged explicitly here to decide whether to skip.
func requireDocker(t *testing.T) {
t.Helper()
ctx := context.Background()
ctx := t.Context()
cli, err := GetDockerClient(ctx)
if err != nil {
t.Skipf("skipping: docker client unavailable: %v", err)
+8 -8
View File
@@ -62,7 +62,7 @@ func TestCopyDir(t *testing.T) {
func TestGetContainerArchive(t *testing.T) {
dir := t.TempDir()
ctx := context.Background()
ctx := t.Context()
e := &HostEnvironment{
Path: filepath.Join(dir, "path"),
TmpDir: filepath.Join(dir, "tmp"),
@@ -97,7 +97,7 @@ func TestHostEnvironmentExecExitCode(t *testing.T) {
t.Skip("uses POSIX shell")
}
dir := t.TempDir()
ctx := context.Background()
ctx := t.Context()
e := &HostEnvironment{
Path: filepath.Join(dir, "path"),
TmpDir: filepath.Join(dir, "tmp"),
@@ -148,7 +148,7 @@ func TestHostEnvironmentAllocatePTY(t *testing.T) {
err := e.Exec(
[]string{"sh", "-c", "[ -t 1 ] && printf TTY || printf NOTTY"},
map[string]string{"PATH": os.Getenv("PATH")}, "", "",
)(context.Background())
)(t.Context())
require.NoError(t, err)
got := strings.TrimSpace(strings.ReplaceAll(buf.String(), "\r", ""))
assert.Equal(t, tc.expect, got)
@@ -157,7 +157,7 @@ func TestHostEnvironmentAllocatePTY(t *testing.T) {
}
func TestHostEnvironmentRemovePreservesWorkdirByDefault(t *testing.T) {
ctx := common.WithLogger(context.Background(), logging.Default())
ctx := common.WithLogger(t.Context(), logging.Default())
base := t.TempDir()
miscRoot := filepath.Join(base, "misc")
path := filepath.Join(miscRoot, "hostexecutor")
@@ -179,7 +179,7 @@ func TestHostEnvironmentRemovePreservesWorkdirByDefault(t *testing.T) {
}
func TestHostEnvironmentRemoveCleansWorkdirWhenOwned(t *testing.T) {
ctx := common.WithLogger(context.Background(), logging.Default())
ctx := common.WithLogger(t.Context(), logging.Default())
base := t.TempDir()
miscRoot := filepath.Join(base, "misc")
path := filepath.Join(miscRoot, "hostexecutor")
@@ -220,7 +220,7 @@ func TestRemoveAllWithContextDoesNotHangOnStuckDelete(t *testing.T) {
removeAll = orig
})
ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
ctx, cancel := context.WithTimeout(t.Context(), 100*time.Millisecond)
defer cancel()
err := removeAllWithContext(ctx, t.TempDir())
@@ -237,7 +237,7 @@ func TestHostEnvironmentRemoveDoesNotHangOnStuckCleanUp(t *testing.T) {
hostCleanupTimeout = 100 * time.Millisecond
t.Cleanup(func() { hostCleanupTimeout = orig })
ctx := common.WithLogger(context.Background(), logging.Default())
ctx := common.WithLogger(t.Context(), logging.Default())
base := t.TempDir()
path := filepath.Join(base, "misc", "hostexecutor")
require.NoError(t, os.MkdirAll(path, 0o700))
@@ -290,7 +290,7 @@ func TestHostEnvironmentRemoveDoesNotHangOnStuckPathRemoval(t *testing.T) {
removeAll = origRemoveAll
})
ctx := common.WithLogger(context.Background(), logging.Default())
ctx := common.WithLogger(t.Context(), logging.Default())
base := t.TempDir()
path := filepath.Join(base, "misc", "hostexecutor")
require.NoError(t, os.MkdirAll(path, 0o700))
+10 -11
View File
@@ -5,7 +5,6 @@ package container
import (
"bufio"
"context"
"os"
"path/filepath"
"strings"
@@ -28,7 +27,7 @@ func TestParseEnvFileSingleLine(t *testing.T) {
require.NoError(t, os.WriteFile(envPath, []byte("FOO=bar\nBAZ=qux\n"), 0o600))
env := map[string]string{}
require.NoError(t, parseEnvFile(e, envPath, &env)(context.Background()))
require.NoError(t, parseEnvFile(e, envPath, &env)(t.Context()))
assert.Equal(t, "bar", env["FOO"])
assert.Equal(t, "qux", env["BAZ"])
}
@@ -39,7 +38,7 @@ func TestParseEnvFileMultiLine(t *testing.T) {
require.NoError(t, os.WriteFile(envPath, []byte(content), 0o600))
env := map[string]string{}
require.NoError(t, parseEnvFile(e, envPath, &env)(context.Background()))
require.NoError(t, parseEnvFile(e, envPath, &env)(t.Context()))
assert.Equal(t, "line1\nline2", env["FOO"])
}
@@ -50,7 +49,7 @@ func TestParseEnvFileLargeValueWithinLimit(t *testing.T) {
require.NoError(t, os.WriteFile(envPath, []byte(content), 0o600))
env := map[string]string{}
require.NoError(t, parseEnvFile(e, envPath, &env)(context.Background()))
require.NoError(t, parseEnvFile(e, envPath, &env)(t.Context()))
assert.Equal(t, big, env["FOO"])
}
@@ -61,7 +60,7 @@ func TestParseEnvFileLineExceedsBufferReportsScannerError(t *testing.T) {
require.NoError(t, os.WriteFile(envPath, []byte(content), 0o600))
env := map[string]string{}
err := parseEnvFile(e, envPath, &env)(context.Background())
err := parseEnvFile(e, envPath, &env)(t.Context())
require.ErrorIs(t, err, bufio.ErrTooLong)
assert.Contains(t, err.Error(), "reading env file")
}
@@ -73,7 +72,7 @@ func TestParseEnvFileBlankLines(t *testing.T) {
require.NoError(t, os.WriteFile(envPath, []byte("\nFOO=bar\n\n \nBAZ=qux\n\n"), 0o600))
env := map[string]string{}
require.NoError(t, parseEnvFile(e, envPath, &env)(context.Background()))
require.NoError(t, parseEnvFile(e, envPath, &env)(t.Context()))
assert.Equal(t, "bar", env["FOO"])
assert.Equal(t, "qux", env["BAZ"])
}
@@ -84,12 +83,12 @@ func TestParseEnvFileMultiLineKeepsBlankLines(t *testing.T) {
require.NoError(t, os.WriteFile(envPath, []byte("FOO<<EOF\nline1\n\nline2\nEOF\n"), 0o600))
env := map[string]string{}
require.NoError(t, parseEnvFile(e, envPath, &env)(context.Background()))
require.NoError(t, parseEnvFile(e, envPath, &env)(t.Context()))
assert.Equal(t, "line1\n\nline2", env["FOO"])
require.NoError(t, os.WriteFile(envPath, []byte("FOO<<EOF\n\nline2\nEOF\n"), 0o600))
env = map[string]string{}
require.NoError(t, parseEnvFile(e, envPath, &env)(context.Background()))
require.NoError(t, parseEnvFile(e, envPath, &env)(t.Context()))
assert.Equal(t, "\nline2", env["FOO"])
}
@@ -99,7 +98,7 @@ func TestParseEnvFileUTF8BOM(t *testing.T) {
require.NoError(t, os.WriteFile(envPath, content, 0o600))
env := map[string]string{}
require.NoError(t, parseEnvFile(e, envPath, &env)(context.Background()))
require.NoError(t, parseEnvFile(e, envPath, &env)(t.Context()))
assert.Equal(t, "bar", env["FOO"])
}
@@ -121,7 +120,7 @@ func TestParseEnvFileUTF16(t *testing.T) {
require.NoError(t, os.WriteFile(envPath, content, 0o600))
env := map[string]string{}
require.NoError(t, parseEnvFile(e, envPath, &env)(context.Background()))
require.NoError(t, parseEnvFile(e, envPath, &env)(t.Context()))
assert.Equal(t, "bar", env["FOO"])
assert.Equal(t, "line1", env["MULTI"])
})
@@ -133,7 +132,7 @@ func TestParseEnvFileMissingDelimiter(t *testing.T) {
require.NoError(t, os.WriteFile(envPath, []byte("FOO<<EOF\nline1\nline2\n"), 0o600))
env := map[string]string{}
err := parseEnvFile(e, envPath, &env)(context.Background())
err := parseEnvFile(e, envPath, &env)(t.Context())
require.Error(t, err)
assert.Contains(t, err.Error(), "delimiter")
}