2026-09-29 17:58:15 +00:00
package configkit_test
import (
"bytes"
"os"
"path/filepath"
"reflect"
"strconv"
"strings"
"testing"
"testing/fstest"
2026-11-01 14:19:37 +00:00
configkit "go.maximumdirect.net/configkit"
2026-09-29 17:58:15 +00:00
)
type layeredFacadeConfig struct {
Settings map [ string ] string ` yaml:"settings" `
Count int ` yaml:"count" `
Enabled bool ` yaml:"enabled" `
List [ ] string ` yaml:"list" `
Optional * string ` yaml:"optional" `
Derived string ` yaml:"derived" `
}
func TestFacadeLayeredMixedSourcesAndInspection ( t * testing . T ) {
mainPath := filepath . Join ( t . TempDir ( ) , "main.yml" )
if err := os . WriteFile ( mainPath , [ ] byte ( "settings: {shared: main, secret: new-canary}\ncount: 0\nenabled: false\nlist: []\noptional: null\n" ) , 0 o600 ) ; err != nil {
t . Fatal ( err )
}
lower := configkit . NewFilesystem ( "bundle" , fstest . MapFS {
2026-11-02 00:44:04 +00:00
"main.yml" : & fstest . MapFile { Data : [ ] byte ( "config: {imports: [{path: defaults.yml}]}\nsettings: {shared: lower, native: retained, secret: old-canary}\nlist: [lower]\n" ) } ,
2026-09-29 17:58:15 +00:00
"defaults.yml" : & fstest . MapFile { Data : [ ] byte ( "settings: {imported: retained}\n" ) } ,
"overlays/testing.yml" : & fstest . MapFile { Data : [ ] byte ( "settings: {from_lower_namespace: retained}\n" ) } ,
} )
selected := configkit . NewFilesystem ( "bundle" , fstest . MapFS {
"overlays/testing.yml" : & fstest . MapFile { Data : [ ] byte ( "settings: {shared: overlay}\n" ) } ,
} )
checks := struct { defaults , resolution , validation int } { }
result , err := configkit . LoadLayered ( configkit . Input { Source : configkit . File ( mainPath ) } , configkit . LayeredOptions [ layeredFacadeConfig ] {
Underlays : [ ] configkit . Underlay {
{ Inputs : [ ] configkit . Input {
{ Source : lower . File ( "main.yml" ) , Imports : true } ,
{ Source : configkit . Mapping ( "programmatic-low" , map [ string ] any { "settings" : map [ string ] any { "mapping" : "retained" } , "count" : 7 , "enabled" : true } ) } ,
{ Source : lower . File ( "overlays/testing.yml" ) } ,
} } ,
{ Inputs : [ ] configkit . Input { { Source : configkit . Mapping ( "programmatic-high" , map [ string ] any {
"settings" : map [ string ] any { "shared" : "middle" , "second" : "retained" } , "list" : [ ] any { "middle" } ,
} ) } } } ,
} ,
Overlay : "testing" , OverlayFilesystem : & configkit . FilesystemContext { Root : "." , BaseDir : "." , FS : & selected } ,
Overrides : [ ] configkit . Override { { Path : configkit . Keys ( "settings" , "shared" ) , Value : "cli" , Flag : "--shared" } } ,
Definition : configkit . Definition [ layeredFacadeConfig ] {
Defaults : func ( ) layeredFacadeConfig { checks . defaults ++ ; return layeredFacadeConfig { } } ,
Resolve : func ( config * layeredFacadeConfig , resolution * configkit . Resolution ) error {
checks . resolution ++
if source , ok := resolution . Source ( "source-2" ) ; ! ok || source . Layer != configkit . LayerUnderlay || source . UnderlayIndex != 1 || source . Kind != configkit . SourceKindFilesystem {
t . Errorf ( "resolver source = %#v, %v" , source , ok )
}
configkit . Default ( resolution , configkit . Keys ( "derived" ) , & config . Derived , config . Settings [ "native" ] , "derive from native" , configkit . Keys ( "settings" , "native" ) )
return nil
} ,
2026-10-27 15:00:04 +00:00
Validate : func ( config * layeredFacadeConfig , validation * configkit . Validation ) { checks . validation ++ } ,
Sensitive : func ( path configkit . Path ) bool { return path . String ( ) == "/settings/secret" } ,
2026-09-29 17:58:15 +00:00
} ,
} )
if err != nil {
t . Fatalf ( "layered load: %v, diagnostics %#v" , err , err . ( * configkit . LoadError ) . Diagnostics ( ) )
}
wantSettings := map [ string ] string {
"shared" : "cli" , "secret" : "new-canary" , "native" : "retained" , "imported" : "retained" ,
"mapping" : "retained" , "from_lower_namespace" : "retained" , "second" : "retained" ,
}
if ! reflect . DeepEqual ( result . Config . Settings , wantSettings ) || result . Config . Count != 0 || result . Config . Enabled || result . Config . List == nil || len ( result . Config . List ) != 0 || result . Config . Optional != nil || result . Config . Derived != "retained" {
t . Fatalf ( "configuration = %#v" , result . Config )
}
if checks != ( struct { defaults , resolution , validation int } { 1 , 1 , 1 } ) {
t . Fatalf ( "lifecycle calls = %#v" , checks )
}
sources := result . Sources ( )
if len ( sources ) != 8 {
t . Fatalf ( "sources = %#v" , sources )
}
2026-10-27 15:15:39 +00:00
wantLayers := [ ] configkit . Layer { configkit . LayerMain , configkit . LayerUnderlay , configkit . LayerUnderlay , configkit . LayerUnderlay , configkit . LayerUnderlay , configkit . LayerUnderlay , configkit . LayerOverlay , configkit . LayerCLI }
2026-09-29 17:58:15 +00:00
wantIndexes := [ ] int { 0 , 1 , 1 , 1 , 1 , 2 , 0 , 0 }
wantKinds := [ ] configkit . SourceKind { configkit . SourceKindFile , configkit . SourceKindFilesystem , configkit . SourceKindFilesystem , configkit . SourceKindMapping , configkit . SourceKindFilesystem , configkit . SourceKindMapping , configkit . SourceKindFilesystem , configkit . SourceKindCLI }
for index , source := range sources {
if source . ID != "source-" + strconv . Itoa ( index + 1 ) || source . Layer != wantLayers [ index ] || source . UnderlayIndex != wantIndexes [ index ] || source . Kind != wantKinds [ index ] {
t . Errorf ( "source %d = %#v" , index , source )
}
}
if sources [ 4 ] . Path != sources [ 6 ] . Path || sources [ 4 ] . Label != sources [ 6 ] . Label {
t . Fatalf ( "namespace-collision fixture changed: %#v, %#v" , sources [ 4 ] , sources [ 6 ] )
}
sources [ 1 ] . Label = "changed"
if result . Sources ( ) [ 1 ] . Label != "bundle/main.yml" {
t . Fatal ( "source records alias retained metadata" )
}
for _ , test := range [ ] struct {
path string
want configkit . Layer
} {
{ "/settings/native" , configkit . LayerUnderlay } ,
{ "/settings/shared" , configkit . LayerCLI } ,
{ "/derived" , configkit . LayerResolution } ,
} {
path , err := configkit . ParsePath ( test . path )
if err != nil {
t . Fatal ( err )
}
info , ok := result . Metadata ( ) . Lookup ( path )
if ! ok || info . Origin . Layer != test . want {
t . Errorf ( "%s metadata = %#v, %v" , test . path , info , ok )
}
}
container , ok := result . Metadata ( ) . Lookup ( configkit . Keys ( "settings" ) )
if ! ok || len ( container . Origin . Locations ) < 4 {
t . Fatalf ( "composite mapping origin = %#v, %v" , container , ok )
}
explanation , ok := result . Explain ( configkit . Keys ( "settings" , "shared" ) )
if ! ok || len ( explanation . History ) < 5 || explanation . Origin . Layer != configkit . LayerCLI {
t . Fatalf ( "shared history = %#v, %v" , explanation , ok )
}
var effective , rendered bytes . Buffer
if err := result . WriteEffective ( & effective ) ; err != nil {
t . Fatal ( err )
}
if err := result . WriteExplanation ( & rendered , configkit . Keys ( "settings" , "secret" ) ) ; err != nil {
t . Fatal ( err )
}
if strings . Contains ( effective . String ( ) + rendered . String ( ) , "old-canary" ) || strings . Contains ( effective . String ( ) + rendered . String ( ) , "new-canary" ) || ! strings . Contains ( rendered . String ( ) , "redacted" ) {
t . Fatalf ( "secret rendering leaked: effective %q, explanation %q" , effective . String ( ) , rendered . String ( ) )
}
}
func TestFacadeLayeredDisplacedDescendantRemainsInspectable ( t * testing . T ) {
type config struct {
Choice string ` yaml:"choice" `
}
result , err := configkit . LoadLayered ( configkit . Input { Source : configkit . Mapping ( "main" , map [ string ] any { "choice" : "flat" } ) } , configkit . LayeredOptions [ config ] {
Underlays : [ ] configkit . Underlay { { Inputs : [ ] configkit . Input { { Source : configkit . Mapping ( "lower" , map [ string ] any {
"choice" : map [ string ] any { "nested" : "historical" } ,
} ) } } } } ,
} )
if err != nil || result . Config . Choice != "flat" {
t . Fatalf ( "replacement load = %#v, %v" , result , err )
}
path := configkit . Keys ( "choice" , "nested" )
explanation , ok := result . Explain ( path )
if ! ok || explanation . Effective . Present || len ( explanation . History ) == 0 || explanation . History [ 0 ] . Origin . Layer != configkit . LayerUnderlay {
t . Fatalf ( "deleted descendant = %#v, %v" , explanation , ok )
}
}
func TestFacadeLayeredZeroUnderlaysMatchesOrdinaryLoad ( t * testing . T ) {
filesystem := configkit . NewFilesystem ( "bundle" , fstest . MapFS {
"overlays/testing.yml" : & fstest . MapFile { Data : [ ] byte ( "value: selected\n" ) } ,
} )
context := & configkit . FilesystemContext { Root : "." , BaseDir : "." , FS : & filesystem }
source := configkit . Bytes ( "main" , [ ] byte ( "value: base\n" ) )
type config struct {
Value string ` yaml:"value" `
}
ordinary , err := configkit . Load ( source , configkit . Options [ config ] { Overlay : "testing" , Filesystem : context } )
if err != nil {
t . Fatal ( err )
}
layered , err := configkit . LoadLayered ( configkit . Input { Source : source } , configkit . LayeredOptions [ config ] { Overlay : "testing" , OverlayFilesystem : context } )
if err != nil {
t . Fatal ( err )
}
if ordinary . Config != layered . Config || ! reflect . DeepEqual ( ordinary . Sources ( ) , layered . Sources ( ) ) {
t . Fatalf ( "ordinary = %#v, %#v; layered = %#v, %#v" , ordinary . Config , ordinary . Sources ( ) , layered . Config , layered . Sources ( ) )
}
var first , second bytes . Buffer
if err := ordinary . WriteEffective ( & first ) ; err != nil {
t . Fatal ( err )
}
if err := layered . WriteEffective ( & second ) ; err != nil {
t . Fatal ( err )
}
if first . String ( ) != second . String ( ) {
t . Fatalf ( "effective ordinary %q, layered %q" , first . String ( ) , second . String ( ) )
}
if ordinaryExplanation , ok := ordinary . Explain ( configkit . Keys ( "value" ) ) ; ! ok {
t . Fatal ( "ordinary explanation missing" )
} else if layeredExplanation , ok := layered . Explain ( configkit . Keys ( "value" ) ) ; ! ok || ! reflect . DeepEqual ( ordinaryExplanation , layeredExplanation ) {
t . Fatalf ( "explanations differ: %#v, %#v" , ordinaryExplanation , layeredExplanation )
}
}
func TestFacadeLayeredOptionAndVersionFailures ( t * testing . T ) {
type config struct {
Version string ` yaml:"version" `
}
namespace := configkit . NewFilesystem ( "bundle" , fstest . MapFS {
"overlays/testing.yml" : & fstest . MapFile { Data : [ ] byte ( "{}\n" ) } ,
} )
for _ , test := range [ ] struct {
name string
main configkit . Input
options [ ] configkit . LayeredOptions [ config ]
want configkit . Code
} {
{ "zero source" , configkit . Input { } , nil , configkit . CodeSourceInvalid } ,
{ "multiple options" , configkit . Input { Source : configkit . NoSource ( ) } , [ ] configkit . LayeredOptions [ config ] { { } , { } } , configkit . CodeOptionsInvalid } ,
{ "missing overlay context" , configkit . Input { Source : configkit . NoSource ( ) } , [ ] configkit . LayeredOptions [ config ] { { Overlay : "testing" } } , configkit . CodeOptionsInvalid } ,
{ "selected file already acquired" , configkit . Input { Source : configkit . NoSource ( ) } , [ ] configkit . LayeredOptions [ config ] { {
Overlay : "testing" , OverlayFilesystem : & configkit . FilesystemContext { Root : "." , BaseDir : "." , FS : & namespace } ,
Underlays : [ ] configkit . Underlay { { Inputs : [ ] configkit . Input { { Source : namespace . File ( "overlays/testing.yml" ) } } } } ,
} } , configkit . CodeOverlayRepeated } ,
{ "underlay version" , configkit . Input { Source : configkit . NoSource ( ) } , [ ] configkit . LayeredOptions [ config ] { {
Definition : configkit . Definition [ config ] { Version : & configkit . VersionRule { Path : configkit . Keys ( "version" ) , Check : func ( configkit . Version , * configkit . Validation ) error { return nil } } } ,
Underlays : [ ] configkit . Underlay { { Inputs : [ ] configkit . Input { { Source : configkit . Mapping ( "lower" , map [ string ] any { "version" : "forbidden" } ) } } } } ,
} } , configkit . CodeUnderlayVersion } ,
} {
t . Run ( test . name , func ( t * testing . T ) {
_ , err := configkit . LoadLayered ( test . main , test . options ... )
loadError , ok := err . ( * configkit . LoadError )
if ! ok || len ( loadError . Diagnostics ( ) ) == 0 || loadError . Diagnostics ( ) [ 0 ] . Code != test . want {
t . Fatalf ( "error = %#v, want %s" , err , test . want )
}
} )
}
}
func TestFacadeLayeredExplicitHostOverlayWithoutMain ( t * testing . T ) {
root := t . TempDir ( )
if err := os . Mkdir ( filepath . Join ( root , "overlays" ) , 0 o700 ) ; err != nil {
t . Fatal ( err )
}
if err := os . WriteFile ( filepath . Join ( root , "overlays" , "testing.yml" ) , [ ] byte ( "value: selected\n" ) , 0 o600 ) ; err != nil {
t . Fatal ( err )
}
type config struct {
Value string ` yaml:"value" `
}
result , err := configkit . LoadLayered ( configkit . Input { Source : configkit . NoSource ( ) } , configkit . LayeredOptions [ config ] {
Overlay : "testing" , OverlayFilesystem : & configkit . FilesystemContext { Root : root , BaseDir : root } ,
} )
if err != nil || result . Config . Value != "selected" || len ( result . Sources ( ) ) != 1 || result . Sources ( ) [ 0 ] . Kind != configkit . SourceKindFile {
t . Fatalf ( "explicit host overlay = %#v, %v" , result , err )
}
}