mirror of
https://github.com/hanzoai/tasks.git
synced 2026-10-04 02:04:03 +00:00
## What changed? Adds a new package `testing/testcontext` for creating and managing test `context.Context`s. No behavior change expected/intended. ## Why? tl;dr encapsulating the test context behavior and decouple from TestEnv Bigger picture: Right now the test context behavior is coupled to TestEnv; and legacy suites use `testcore.NewContext()`. That served us well so far, but it's suboptimal. A test context should be available outside of TestEnv and `tests/` package; ie unit and integration tests can also benefit it. ## How did you test it? - [ ] built - [ ] run locally and tested manually - [ ] covered by existing tests - [x] added new unit test(s) - [ ] added new functional test(s)
127 lines
3.0 KiB
Go
127 lines
3.0 KiB
Go
package testcontext
|
|
|
|
import (
|
|
"context"
|
|
"sync/atomic"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestWithTimeout(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
ctx := New(t, WithTimeout(time.Second))
|
|
deadline, ok := ctx.Deadline()
|
|
require.True(t, ok)
|
|
require.WithinDuration(t, time.Now().Add(time.Second), deadline, 50*time.Millisecond)
|
|
}
|
|
|
|
func TestContextDecorators(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
t.Run("applied once across calls", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
type key struct{}
|
|
|
|
var calls atomic.Int32
|
|
decorator := func(ctx context.Context) context.Context {
|
|
calls.Add(1)
|
|
return context.WithValue(ctx, key{}, "decorated")
|
|
}
|
|
|
|
ctx := New(t, WithContextDecorator(key{}, decorator))
|
|
require.Equal(t, "decorated", ctx.Value(key{}))
|
|
|
|
ctx = New(t, WithContextDecorator(key{}, decorator))
|
|
require.Equal(t, "decorated", ctx.Value(key{}))
|
|
require.Equal(t, int32(1), calls.Load(), "decorator should only be applied once")
|
|
})
|
|
|
|
t.Run("applied once in single call", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
type key struct{}
|
|
|
|
var calls atomic.Int32
|
|
decorator := func(ctx context.Context) context.Context {
|
|
calls.Add(1)
|
|
return context.WithValue(ctx, key{}, "decorated")
|
|
}
|
|
|
|
ctx := New(t,
|
|
WithContextDecorator(key{}, decorator),
|
|
WithContextDecorator(key{}, decorator),
|
|
)
|
|
|
|
require.Equal(t, "decorated", ctx.Value(key{}))
|
|
require.Equal(t, int32(1), calls.Load(), "decorator should only be applied once")
|
|
})
|
|
|
|
t.Run("multiple decorators", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
type key1 struct{}
|
|
type key2 struct{}
|
|
|
|
ctx := New(t,
|
|
WithContextDecorator(key1{}, func(ctx context.Context) context.Context {
|
|
return context.WithValue(ctx, key1{}, "one")
|
|
}),
|
|
WithContextDecorator(key2{}, func(ctx context.Context) context.Context {
|
|
return context.WithValue(ctx, key2{}, "two")
|
|
}),
|
|
)
|
|
|
|
require.Equal(t, "one", ctx.Value(key1{}))
|
|
require.Equal(t, "two", ctx.Value(key2{}))
|
|
})
|
|
|
|
t.Run("later call decorates cached context", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
type key struct{}
|
|
|
|
ctx := New(t)
|
|
require.Nil(t, ctx.Value(key{}))
|
|
|
|
ctx = New(t, WithContextDecorator(key{}, func(ctx context.Context) context.Context {
|
|
return context.WithValue(ctx, key{}, "decorated")
|
|
}))
|
|
require.Equal(t, "decorated", ctx.Value(key{}))
|
|
})
|
|
}
|
|
|
|
func TestCleanupCancelsContext(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
var ctx context.Context
|
|
t.Run("subtest", func(t *testing.T) {
|
|
ctx = New(t)
|
|
require.NoError(t, ctx.Err())
|
|
})
|
|
require.ErrorIs(t, ctx.Err(), context.Canceled)
|
|
}
|
|
|
|
func TestEnvTimeout(t *testing.T) {
|
|
t.Run("from env", func(t *testing.T) {
|
|
t.Setenv("TEMPORAL_TEST_TIMEOUT", "10s")
|
|
|
|
ctx := New(t)
|
|
deadline, ok := ctx.Deadline()
|
|
require.True(t, ok)
|
|
require.WithinDuration(t, time.Now().Add(10*time.Second), deadline, 50*time.Millisecond)
|
|
})
|
|
|
|
t.Run("custom overrides env", func(t *testing.T) {
|
|
t.Setenv("TEMPORAL_TEST_TIMEOUT", "10s")
|
|
|
|
ctx := New(t, WithTimeout(time.Second))
|
|
deadline, ok := ctx.Deadline()
|
|
require.True(t, ok)
|
|
require.WithinDuration(t, time.Now().Add(time.Second), deadline, 50*time.Millisecond)
|
|
})
|
|
}
|