Preserve defaults-only input absence
This commit is contained in:
@@ -191,7 +191,12 @@ named `version`.
|
|||||||
|
|
||||||
## 6. Preserve absence for ordinary defaults-only loads — P2
|
## 6. Preserve absence for ordinary defaults-only loads — P2
|
||||||
|
|
||||||
- [ ] Addressed and regression-tested.
|
- [x] Addressed and regression-tested.
|
||||||
|
|
||||||
|
Completion: absent ordinary input stays absent until an existing explicit layer
|
||||||
|
needs assembly. Public parity tests cover values, root presence/origin, optional
|
||||||
|
registrations/defaults, and real empty mappings. Existing defaults-only override
|
||||||
|
coverage and the everyday check passed.
|
||||||
|
|
||||||
**Owner:** `executeLoadRequest` in
|
**Owner:** `executeLoadRequest` in
|
||||||
[load.go](../../internal/engine/load.go), lines 210–216, and
|
[load.go](../../internal/engine/load.go), lines 210–216, and
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"testing/fstest"
|
"testing/fstest"
|
||||||
@@ -11,6 +12,45 @@ import (
|
|||||||
configkit "gitea.maximumdirect.net/eric/ConfigKit"
|
configkit "gitea.maximumdirect.net/eric/ConfigKit"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestFacadeNoSourcePreservesAbsenceWithSequencePolicy(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
for _, defaults := range []bool{false, true} {
|
||||||
|
for _, registered := range []bool{false, true} {
|
||||||
|
definition := configkit.Definition[map[string]any]{}
|
||||||
|
if defaults {
|
||||||
|
definition.Defaults = func() map[string]any { return map[string]any{"fallback": true} }
|
||||||
|
}
|
||||||
|
if registered {
|
||||||
|
definition.SequenceCompositions = []configkit.SequenceComposition{{Path: configkit.Keys("records"), IdentityField: "id"}}
|
||||||
|
}
|
||||||
|
ordinary, err := configkit.Load(configkit.NoSource(), configkit.Options[map[string]any]{Definition: definition})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
layered, err := configkit.LoadLayered[map[string]any](configkit.Input{Source: configkit.NoSource()}, configkit.LayeredOptions[map[string]any]{Definition: definition})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(ordinary.Config, layered.Config) {
|
||||||
|
t.Fatal("NoSource values differ between entry points")
|
||||||
|
}
|
||||||
|
for _, result := range []*configkit.Result[map[string]any]{ordinary, layered} {
|
||||||
|
if len(result.Sources()) != 0 || result.Metadata().IsExplicit(configkit.Keys()) {
|
||||||
|
t.Fatal("NoSource contributed an explicit root")
|
||||||
|
}
|
||||||
|
info, ok := result.Metadata().Lookup(configkit.Keys())
|
||||||
|
if !ok || info.Origin.Layer != configkit.LayerDefault {
|
||||||
|
t.Fatalf("NoSource root origin = %#v, %t", info, ok)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
empty, err := configkit.Load(configkit.Mapping("empty", map[string]any{}), configkit.Options[map[string]any]{Definition: definition})
|
||||||
|
if err != nil || !empty.Metadata().IsExplicit(configkit.Keys()) {
|
||||||
|
t.Fatal("real empty mapping lost its presence")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestFacadeItemHelperHistoryPreservesTraversalOrder(t *testing.T) {
|
func TestFacadeItemHelperHistoryPreservesTraversalOrder(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
filesystem := configkit.NewFilesystem("history", fstest.MapFS{
|
filesystem := configkit.NewFilesystem("history", fstest.MapFS{
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ func executeLoadRequest[T any](request loadRequest[T], secrets SecretBinding, lo
|
|||||||
return nil, accumulator.loadError()
|
return nil, accumulator.loadError()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if request.ordinary {
|
if request.ordinary && input.document != nil {
|
||||||
input.composition, diagnostics = compositionForInputWithPolicy(input, request.sequencePolicy)
|
input.composition, diagnostics = compositionForInputWithPolicy(input, request.sequencePolicy)
|
||||||
if len(diagnostics) != 0 {
|
if len(diagnostics) != 0 {
|
||||||
accumulator.add(diagnostics...)
|
accumulator.add(diagnostics...)
|
||||||
|
|||||||
Reference in New Issue
Block a user