238 lines
6.6 KiB
Go
238 lines
6.6 KiB
Go
package ctxext
|
|
|
|
import (
|
|
"context"
|
|
"git.blackforestbytes.com/BlackForestBytes/goext/tst"
|
|
"testing"
|
|
)
|
|
|
|
type ctxKey string
|
|
|
|
const (
|
|
keyString ctxKey = "string-key"
|
|
keyInt ctxKey = "int-key"
|
|
keyStruct ctxKey = "struct-key"
|
|
keyPtr ctxKey = "ptr-key"
|
|
keyMissing ctxKey = "missing-key"
|
|
)
|
|
|
|
type sampleStruct struct {
|
|
Name string
|
|
N int
|
|
}
|
|
|
|
func TestValueStringPresent(t *testing.T) {
|
|
ctx := context.WithValue(context.Background(), keyString, "hello")
|
|
v, ok := Value[string](ctx, keyString)
|
|
tst.AssertEqual(t, ok, true)
|
|
tst.AssertEqual(t, v, "hello")
|
|
}
|
|
|
|
func TestValueIntPresent(t *testing.T) {
|
|
ctx := context.WithValue(context.Background(), keyInt, 42)
|
|
v, ok := Value[int](ctx, keyInt)
|
|
tst.AssertEqual(t, ok, true)
|
|
tst.AssertEqual(t, v, 42)
|
|
}
|
|
|
|
func TestValueStructPresent(t *testing.T) {
|
|
want := sampleStruct{Name: "abc", N: 7}
|
|
ctx := context.WithValue(context.Background(), keyStruct, want)
|
|
v, ok := Value[sampleStruct](ctx, keyStruct)
|
|
tst.AssertEqual(t, ok, true)
|
|
tst.AssertEqual(t, v.Name, "abc")
|
|
tst.AssertEqual(t, v.N, 7)
|
|
}
|
|
|
|
func TestValuePointerPresent(t *testing.T) {
|
|
want := &sampleStruct{Name: "ptr", N: 99}
|
|
ctx := context.WithValue(context.Background(), keyPtr, want)
|
|
v, ok := Value[*sampleStruct](ctx, keyPtr)
|
|
tst.AssertEqual(t, ok, true)
|
|
tst.AssertEqual(t, v == want, true)
|
|
tst.AssertEqual(t, v.Name, "ptr")
|
|
}
|
|
|
|
func TestValueMissing(t *testing.T) {
|
|
ctx := context.Background()
|
|
v, ok := Value[string](ctx, keyMissing)
|
|
tst.AssertEqual(t, ok, false)
|
|
tst.AssertEqual(t, v, "")
|
|
}
|
|
|
|
func TestValueMissingInt(t *testing.T) {
|
|
ctx := context.Background()
|
|
v, ok := Value[int](ctx, keyMissing)
|
|
tst.AssertEqual(t, ok, false)
|
|
tst.AssertEqual(t, v, 0)
|
|
}
|
|
|
|
func TestValueMissingStruct(t *testing.T) {
|
|
ctx := context.Background()
|
|
v, ok := Value[sampleStruct](ctx, keyMissing)
|
|
tst.AssertEqual(t, ok, false)
|
|
tst.AssertEqual(t, v.Name, "")
|
|
tst.AssertEqual(t, v.N, 0)
|
|
}
|
|
|
|
func TestValueMissingPointer(t *testing.T) {
|
|
ctx := context.Background()
|
|
v, ok := Value[*sampleStruct](ctx, keyMissing)
|
|
tst.AssertEqual(t, ok, false)
|
|
tst.AssertEqual(t, v == nil, true)
|
|
}
|
|
|
|
func TestValueWrongType(t *testing.T) {
|
|
ctx := context.WithValue(context.Background(), keyString, "hello")
|
|
v, ok := Value[int](ctx, keyString)
|
|
tst.AssertEqual(t, ok, false)
|
|
tst.AssertEqual(t, v, 0)
|
|
}
|
|
|
|
func TestValueWrongTypeStructToString(t *testing.T) {
|
|
ctx := context.WithValue(context.Background(), keyStruct, sampleStruct{Name: "x"})
|
|
v, ok := Value[string](ctx, keyStruct)
|
|
tst.AssertEqual(t, ok, false)
|
|
tst.AssertEqual(t, v, "")
|
|
}
|
|
|
|
func TestValueNilStoredAsInterface(t *testing.T) {
|
|
var stored *sampleStruct = nil
|
|
ctx := context.WithValue(context.Background(), keyPtr, stored)
|
|
v, ok := Value[*sampleStruct](ctx, keyPtr)
|
|
tst.AssertEqual(t, ok, true)
|
|
tst.AssertEqual(t, v == nil, true)
|
|
}
|
|
|
|
func TestValueEmptyString(t *testing.T) {
|
|
ctx := context.WithValue(context.Background(), keyString, "")
|
|
v, ok := Value[string](ctx, keyString)
|
|
tst.AssertEqual(t, ok, true)
|
|
tst.AssertEqual(t, v, "")
|
|
}
|
|
|
|
func TestValueZeroInt(t *testing.T) {
|
|
ctx := context.WithValue(context.Background(), keyInt, 0)
|
|
v, ok := Value[int](ctx, keyInt)
|
|
tst.AssertEqual(t, ok, true)
|
|
tst.AssertEqual(t, v, 0)
|
|
}
|
|
|
|
func TestValueWithStringKey(t *testing.T) {
|
|
type stringKey string
|
|
k := stringKey("my-key")
|
|
ctx := context.WithValue(context.Background(), k, "value")
|
|
v, ok := Value[string](ctx, k)
|
|
tst.AssertEqual(t, ok, true)
|
|
tst.AssertEqual(t, v, "value")
|
|
}
|
|
|
|
func TestValueOrDefaultPresent(t *testing.T) {
|
|
ctx := context.WithValue(context.Background(), keyString, "hello")
|
|
v := ValueOrDefault(ctx, keyString, "default")
|
|
tst.AssertEqual(t, v, "hello")
|
|
}
|
|
|
|
func TestValueOrDefaultIntPresent(t *testing.T) {
|
|
ctx := context.WithValue(context.Background(), keyInt, 42)
|
|
v := ValueOrDefault(ctx, keyInt, -1)
|
|
tst.AssertEqual(t, v, 42)
|
|
}
|
|
|
|
func TestValueOrDefaultMissing(t *testing.T) {
|
|
ctx := context.Background()
|
|
v := ValueOrDefault(ctx, keyMissing, "default")
|
|
tst.AssertEqual(t, v, "default")
|
|
}
|
|
|
|
func TestValueOrDefaultMissingInt(t *testing.T) {
|
|
ctx := context.Background()
|
|
v := ValueOrDefault(ctx, keyMissing, 99)
|
|
tst.AssertEqual(t, v, 99)
|
|
}
|
|
|
|
func TestValueOrDefaultMissingStruct(t *testing.T) {
|
|
ctx := context.Background()
|
|
def := sampleStruct{Name: "default", N: 1}
|
|
v := ValueOrDefault(ctx, keyMissing, def)
|
|
tst.AssertEqual(t, v.Name, "default")
|
|
tst.AssertEqual(t, v.N, 1)
|
|
}
|
|
|
|
func TestValueOrDefaultWrongType(t *testing.T) {
|
|
ctx := context.WithValue(context.Background(), keyString, "hello")
|
|
v := ValueOrDefault(ctx, keyString, 7)
|
|
tst.AssertEqual(t, v, 7)
|
|
}
|
|
|
|
func TestValueOrDefaultWrongTypeStruct(t *testing.T) {
|
|
ctx := context.WithValue(context.Background(), keyStruct, sampleStruct{Name: "x"})
|
|
def := "fallback"
|
|
v := ValueOrDefault(ctx, keyStruct, def)
|
|
tst.AssertEqual(t, v, "fallback")
|
|
}
|
|
|
|
func TestValueOrDefaultEmptyStringStored(t *testing.T) {
|
|
ctx := context.WithValue(context.Background(), keyString, "")
|
|
v := ValueOrDefault(ctx, keyString, "default")
|
|
tst.AssertEqual(t, v, "")
|
|
}
|
|
|
|
func TestValueOrDefaultZeroIntStored(t *testing.T) {
|
|
ctx := context.WithValue(context.Background(), keyInt, 0)
|
|
v := ValueOrDefault(ctx, keyInt, 99)
|
|
tst.AssertEqual(t, v, 0)
|
|
}
|
|
|
|
func TestValueOrDefaultPointerPresent(t *testing.T) {
|
|
want := &sampleStruct{Name: "p", N: 5}
|
|
ctx := context.WithValue(context.Background(), keyPtr, want)
|
|
def := &sampleStruct{Name: "def", N: 0}
|
|
v := ValueOrDefault(ctx, keyPtr, def)
|
|
tst.AssertEqual(t, v == want, true)
|
|
}
|
|
|
|
func TestValueOrDefaultPointerMissing(t *testing.T) {
|
|
ctx := context.Background()
|
|
def := &sampleStruct{Name: "def", N: 0}
|
|
v := ValueOrDefault(ctx, keyMissing, def)
|
|
tst.AssertEqual(t, v == def, true)
|
|
}
|
|
|
|
func TestValueOrDefaultNilPointerStored(t *testing.T) {
|
|
var stored *sampleStruct = nil
|
|
ctx := context.WithValue(context.Background(), keyPtr, stored)
|
|
def := &sampleStruct{Name: "def"}
|
|
v := ValueOrDefault(ctx, keyPtr, def)
|
|
tst.AssertEqual(t, v == nil, true)
|
|
}
|
|
|
|
func TestValueNestedContext(t *testing.T) {
|
|
ctx := context.WithValue(context.Background(), keyString, "outer")
|
|
ctx = context.WithValue(ctx, keyInt, 123)
|
|
ctx = context.WithValue(ctx, keyString, "inner")
|
|
|
|
vs, oks := Value[string](ctx, keyString)
|
|
tst.AssertEqual(t, oks, true)
|
|
tst.AssertEqual(t, vs, "inner")
|
|
|
|
vi, oki := Value[int](ctx, keyInt)
|
|
tst.AssertEqual(t, oki, true)
|
|
tst.AssertEqual(t, vi, 123)
|
|
}
|
|
|
|
func TestValueDifferentKeyTypesDoNotCollide(t *testing.T) {
|
|
type keyA string
|
|
type keyB string
|
|
ctx := context.WithValue(context.Background(), keyA("k"), "a-val")
|
|
ctx = context.WithValue(ctx, keyB("k"), "b-val")
|
|
|
|
va, oka := Value[string](ctx, keyA("k"))
|
|
tst.AssertEqual(t, oka, true)
|
|
tst.AssertEqual(t, va, "a-val")
|
|
|
|
vb, okb := Value[string](ctx, keyB("k"))
|
|
tst.AssertEqual(t, okb, true)
|
|
tst.AssertEqual(t, vb, "b-val")
|
|
}
|