74 lines
2.2 KiB
Go
74 lines
2.2 KiB
Go
package engine
|
|
|
|
import (
|
|
"errors"
|
|
"testing"
|
|
)
|
|
|
|
func capturePanic(call func()) (recovered any) {
|
|
defer func() { recovered = recover() }()
|
|
call()
|
|
return nil
|
|
}
|
|
|
|
func requirePanicValue(t *testing.T, want any, call func()) {
|
|
t.Helper()
|
|
if got := capturePanic(call); got != want {
|
|
t.Fatalf("panic = %#v, want %#v", got, want)
|
|
}
|
|
}
|
|
|
|
func TestCallbackContextsCloseWhenCallbacksPanic(t *testing.T) {
|
|
type config struct {
|
|
Value string `yaml:"value"`
|
|
Version string `yaml:"version"`
|
|
}
|
|
|
|
t.Run("resolution", func(t *testing.T) {
|
|
sentinel := errors.New("resolution panic sentinel")
|
|
var retained *Resolution
|
|
got := capturePanic(func() {
|
|
_, _ = testLoad[config](NoSource(), Options[config]{Definition: Definition[config]{Resolve: func(_ *config, resolution *Resolution) error {
|
|
retained = resolution
|
|
panic(sentinel)
|
|
}}})
|
|
})
|
|
if got != sentinel {
|
|
t.Fatalf("callback panic = %#v, want original sentinel", got)
|
|
}
|
|
requirePanicValue(t, closedCallbackContextMessage, func() { retained.IsExplicit(Keys("value")) })
|
|
})
|
|
|
|
t.Run("validation", func(t *testing.T) {
|
|
sentinel := errors.New("validation panic sentinel")
|
|
var retained *Validation
|
|
got := capturePanic(func() {
|
|
_, _ = testLoad[config](NoSource(), Options[config]{Definition: Definition[config]{Validate: func(_ *config, validation *Validation) {
|
|
retained = validation
|
|
panic(sentinel)
|
|
}}})
|
|
})
|
|
if got != sentinel {
|
|
t.Fatalf("callback panic = %#v, want original sentinel", got)
|
|
}
|
|
requirePanicValue(t, closedCallbackContextMessage, func() { retained.Error(Keys("value"), "too late") })
|
|
})
|
|
|
|
t.Run("version", func(t *testing.T) {
|
|
sentinel := errors.New("version panic sentinel")
|
|
var retained *Validation
|
|
got := capturePanic(func() {
|
|
_, _ = testLoad[config](Bytes("version.yml", []byte("version: v1\n")), Options[config]{Definition: Definition[config]{
|
|
Version: &VersionRule{Path: Keys("version"), Check: func(_ Version, validation *Validation) error {
|
|
retained = validation
|
|
panic(sentinel)
|
|
}},
|
|
}})
|
|
})
|
|
if got != sentinel {
|
|
t.Fatalf("callback panic = %#v, want original sentinel", got)
|
|
}
|
|
requirePanicValue(t, closedCallbackContextMessage, func() { retained.Warning(Keys("version"), "too late") })
|
|
})
|
|
}
|