Files
ConfigKit/internal/engine/dynamic_descriptor_transaction_test.go

96 lines
3.6 KiB
Go

package engine
import (
"errors"
"reflect"
"testing"
)
type unsupportedDynamicRoot struct {
Child unsupportedDynamicChild `yaml:"child"`
Invalid chan int `yaml:"invalid"`
}
type unsupportedDynamicChild struct {
Parent *unsupportedDynamicRoot `yaml:"parent"`
}
type secretDynamicRoot struct {
Nested secretDynamicNested `yaml:"nested"`
}
type secretDynamicNested struct {
Token Secret `yaml:"token"`
}
type dynamicTransactionConfig struct {
First any `yaml:"first"`
Second any `yaml:"second"`
Good any `yaml:"good"`
}
func TestDynamicDescriptorFailuresRollBackProvisionalTypes(t *testing.T) {
called := false
result, err := testLoad[dynamicTransactionConfig](NoSource(), Options[dynamicTransactionConfig]{Definition: Definition[dynamicTransactionConfig]{
Resolve: func(config *dynamicTransactionConfig, resolution *Resolution) error {
called = true
Normalize(resolution, Keys("first"), &config.First, any((*unsupportedDynamicRoot)(nil)), "try typed nil")
Normalize(resolution, Keys("second"), &config.Second, any(&unsupportedDynamicRoot{}), "try non-nil")
Normalize(resolution, Keys("good"), &config.Good, any(map[string]string{"valid": "value"}), "continue with supported value")
return nil
},
}})
var loadErr *LoadError
if !called || result != nil || !errors.As(err, &loadErr) {
t.Fatalf("result = %#v, called=%v, error=%v", result, called, err)
}
paths := make(map[string]Code)
for _, diagnostic := range loadErr.Diagnostics() {
paths[diagnostic.Path.String()] = diagnostic.Code
}
for _, path := range []string{"/first", "/second"} {
if paths[path] != CodeResolveInvalidValue {
t.Errorf("diagnostic at %s = %q, want safe invalid-value failure", path, paths[path])
}
}
schema := mustSchemaFor[dynamicTransactionConfig](t)
operation := valueOperation{schema: schema}
prior, issue := operation.dynamicDescriptor(reflect.TypeFor[map[string]string](), Keys("prior"))
if issue != nil {
t.Fatalf("prior valid dynamic descriptor issue = %#v", issue)
}
if _, issue := operation.dynamicDescriptor(reflect.TypeFor[unsupportedDynamicRoot](), Keys("failure")); issue == nil || issue.code != CodeSchemaDynamicType {
t.Fatalf("unsupported dynamic descriptor issue = %#v", issue)
}
if schema.types[reflect.TypeFor[map[string]string]()] != prior {
t.Fatal("failed build removed a previously completed descriptor")
}
for _, current := range []reflect.Type{
reflect.TypeFor[unsupportedDynamicRoot](),
reflect.TypeFor[unsupportedDynamicChild](),
reflect.TypeFor[*unsupportedDynamicRoot](),
} {
if _, exists := schema.types[current]; exists {
t.Errorf("failed build retained provisional descriptor for %v", current)
}
}
if _, issue := operation.dynamicDescriptor(reflect.TypeFor[unsupportedDynamicRoot](), Keys("again")); issue == nil || issue.path.String() != "/again" {
t.Fatalf("repeated failure issue = %#v", issue)
}
secretSchema, schemaIssue := buildSchema(reflect.TypeFor[dynamicTransactionConfig](), testSecretBinding())
if schemaIssue != nil {
t.Fatalf("secret schema issue = %#v", schemaIssue)
}
secretOperation := valueOperation{schema: secretSchema}
if _, issue := secretOperation.dynamicDescriptor(reflect.TypeFor[secretDynamicRoot](), Keys("secret")); issue == nil || issue.code != CodeSchemaDynamicType {
t.Fatalf("dynamic secret eligibility issue = %#v", issue)
}
for _, current := range []reflect.Type{reflect.TypeFor[secretDynamicRoot](), reflect.TypeFor[secretDynamicNested](), reflect.TypeFor[Secret]()} {
if _, exists := secretSchema.types[current]; exists {
t.Errorf("secret eligibility failure retained provisional descriptor for %v", current)
}
}
}