2026-09-06 20:03:22 +00:00
package configkit
import (
"errors"
"os"
"path/filepath"
"reflect"
"strings"
"sync/atomic"
"testing"
)
func TestLoadSingleSourceKindsAndDefaultsOnly ( t * testing . T ) {
t . Parallel ( )
type config struct {
Name string ` yaml:"name" `
}
input := [ ] byte ( "name: configured\n" )
temporary := t . TempDir ( )
filename := filepath . Join ( temporary , "config.yml" )
if err := os . WriteFile ( filename , input , 0 o600 ) ; err != nil {
t . Fatal ( err )
}
tests := [ ] struct {
name string
source func ( ) Source
want string
wantSources int
} {
{ name : "file" , source : func ( ) Source { return File ( filename ) } , want : "configured" , wantSources : 1 } ,
{ name : "bytes" , source : func ( ) Source { return Bytes ( "memory.yml" , input ) } , want : "configured" , wantSources : 1 } ,
{ name : "reader" , source : func ( ) Source { return Reader ( "reader.yml" , strings . NewReader ( string ( input ) ) ) } , want : "configured" , wantSources : 1 } ,
{ name : "no source" , source : NoSource , want : "default" , wantSources : 0 } ,
}
for _ , test := range tests {
t . Run ( test . name , func ( t * testing . T ) {
var defaultsCalls atomic . Int32
result , err := Load ( test . source ( ) , Options [ config ] { Definition : Definition [ config ] {
Defaults : func ( ) config {
defaultsCalls . Add ( 1 )
return config { Name : "default" }
} ,
} } )
if err != nil {
t . Fatal ( err )
}
if result . Config . Name != test . want || defaultsCalls . Load ( ) != 1 || len ( result . Sources ( ) ) != test . wantSources {
t . Fatalf ( "result = %#v, calls = %d, sources = %#v" , result . Config , defaultsCalls . Load ( ) , result . Sources ( ) )
}
} )
}
}
func TestLoadVersionStatesWarningsAndSafeFailures ( t * testing . T ) {
t . Parallel ( )
type config struct {
SchemaVersion * string ` yaml:"schema_version" `
}
versionPath := Keys ( "schema_version" )
tests := [ ] struct {
name string
source Source
want Version
wantLine int
wantErr Code
returnOnly bool
} {
{ name : "absent" , source : Bytes ( "absent.yml" , [ ] byte ( "{}\n" ) ) , want : Version { } , wantLine : 1 } ,
{ name : "no source absent" , source : NoSource ( ) , want : Version { } } ,
{ name : "null" , source : Bytes ( "null.yml" , [ ] byte ( "schema_version: null\n" ) ) , want : Version { Present : true , Null : true } , wantLine : 1 } ,
{ name : "string" , source : Bytes ( "string.yml" , [ ] byte ( "schema_version: app.v1\n" ) ) , want : Version { Present : true , Text : "app.v1" } , wantLine : 1 } ,
{ name : "integer" , source : Bytes ( "integer.yml" , [ ] byte ( "schema_version: 1\n" ) ) , wantErr : CodeVersionType } ,
{ name : "returned error" , source : Bytes ( "return.yml" , [ ] byte ( "{}\n" ) ) , wantErr : CodeVersionHookFailed , returnOnly : true } ,
}
for _ , test := range tests {
t . Run ( test . name , func ( t * testing . T ) {
called := false
rule := & VersionRule { Path : versionPath , Check : func ( version Version , validation * Validation ) error {
called = true
if test . returnOnly {
return errors . New ( "CANARY_VERSION_ERROR" )
}
if version != test . want {
t . Errorf ( "version = %#v, want %#v" , version , test . want )
}
validation . Warning ( versionPath , "review schema compatibility" , Keys ( "missing_related" ) )
return nil
} }
result , err := Load ( test . source , Options [ config ] { Definition : Definition [ config ] { Version : rule } } )
if test . wantErr != "" {
if result != nil || err == nil {
t . Fatalf ( "result, err = %#v, %v" , result , err )
}
var loadError * LoadError
if ! errors . As ( err , & loadError ) {
t . Fatalf ( "error type = %T" , err )
}
diagnostics := loadError . Diagnostics ( )
if len ( diagnostics ) != 1 || diagnostics [ 0 ] . Code != test . wantErr || strings . Contains ( diagnostics [ 0 ] . Message , "CANARY" ) {
t . Fatalf ( "diagnostics = %#v" , diagnostics )
}
if test . wantErr == CodeVersionType && called {
t . Fatal ( "checker ran for a non-string version" )
}
return
}
if err != nil {
t . Fatal ( err )
}
diagnostics := result . Diagnostics ( )
if len ( diagnostics ) != 1 || diagnostics [ 0 ] . Code != CodeVersionWarning || diagnostics [ 0 ] . Severity != SeverityWarning {
t . Fatalf ( "diagnostics = %#v" , diagnostics )
}
if test . wantLine == 0 && ( diagnostics [ 0 ] . Primary != nil || len ( diagnostics [ 0 ] . Related ) != 0 ) {
t . Fatalf ( "synthetic diagnostic locations = %#v" , diagnostics [ 0 ] )
}
if test . wantLine != 0 && ( diagnostics [ 0 ] . Primary == nil || diagnostics [ 0 ] . Primary . Line != test . wantLine || len ( diagnostics [ 0 ] . Related ) != 1 ) {
t . Fatalf ( "diagnostic locations = %#v" , diagnostics [ 0 ] )
}
} )
}
}
func TestLoadVersionReportSuppressesReturnedErrorTextAndDefaults ( t * testing . T ) {
t . Parallel ( )
type config struct {
Name string ` yaml:"name" `
}
var defaultsCalls atomic . Int32
result , err := Load ( Bytes ( "version.yml" , [ ] byte ( "name: value\n" ) ) , Options [ config ] { Definition : Definition [ config ] {
Defaults : func ( ) config {
defaultsCalls . Add ( 1 )
return config { Name : "default" }
} ,
Version : & VersionRule { Path : Keys ( "schema_version" ) , Check : func ( _ Version , validation * Validation ) error {
validation . Error ( Keys ( "schema_version" ) , "schema_version is required" )
return errors . New ( "CANARY_RETURNED_ERROR" )
} } ,
} } )
if result != nil || err == nil || defaultsCalls . Load ( ) != 0 {
t . Fatalf ( "result = %#v, err = %v, calls = %d" , result , err , defaultsCalls . Load ( ) )
}
var loadError * LoadError
if ! errors . As ( err , & loadError ) {
t . Fatalf ( "error type = %T" , err )
}
diagnostics := loadError . Diagnostics ( )
if len ( diagnostics ) != 1 || diagnostics [ 0 ] . Code != CodeVersionError || strings . Contains ( diagnostics [ 0 ] . Message , "CANARY" ) {
t . Fatalf ( "diagnostics = %#v" , diagnostics )
}
}
func TestLoadMetadataReflectsDefaultsInputAndDetachedRecords ( t * testing . T ) {
t . Parallel ( )
type nested struct {
Kept string ` yaml:"kept" `
Set string ` yaml:"set" `
}
type config struct {
Nested nested ` yaml:"nested" `
Nullable map [ string ] string ` yaml:"nullable" `
}
result , err := Load ( Bytes ( "metadata.yml" , [ ] byte ( "nested: {set: configured}\nnullable: null\n" ) ) , Options [ config ] { Definition : Definition [ config ] {
Defaults : func ( ) config {
return config { Nested : nested { Kept : "default" , Set : "default" } , Nullable : map [ string ] string { "key" : "value" } }
} ,
} } )
if err != nil {
t . Fatal ( err )
}
metadata := result . Metadata ( )
kept , ok := metadata . Lookup ( Keys ( "nested" , "kept" ) )
if ! ok || kept . Explicit || kept . Origin . Layer != LayerDefault {
t . Fatalf ( "kept = %#v, %v" , kept , ok )
}
set , ok := metadata . Lookup ( Keys ( "nested" , "set" ) )
if ! ok || ! set . Explicit || set . Origin . Layer != LayerBase || len ( set . Origin . Locations ) != 1 {
t . Fatalf ( "set = %#v, %v" , set , ok )
}
nullable , ok := metadata . Lookup ( Keys ( "nullable" ) )
if ! ok || ! nullable . Explicit || ! nullable . Null || nullable . Origin . Layer != LayerBase {
t . Fatalf ( "nullable = %#v, %v" , nullable , ok )
}
if metadata . IsExplicit ( Keys ( "nested" , "kept" ) ) || ! metadata . IsExplicit ( Keys ( "nested" , "set" ) ) {
t . Fatal ( "explicit presence disagrees with lookup" )
}
if history := metadata . History ( Keys ( "nested" , "set" ) ) ; len ( history ) != 2 || history [ 0 ] . Origin . Layer != LayerDefault || history [ 1 ] . Origin . Layer != LayerBase || len ( history [ 1 ] . Previous ) != 1 {
t . Fatalf ( "history = %#v" , history )
}
set . Origin . Locations [ 0 ] . Line = 99
history := metadata . History ( Keys ( "nested" , "set" ) )
history [ 1 ] . Origin . Locations [ 0 ] . Line = 99
sources := result . Sources ( )
sources [ 0 ] . Label = "changed"
diagnostics := result . Diagnostics ( )
if diagnostics != nil {
diagnostics [ 0 ] . Message = "changed"
}
fresh , _ := result . Metadata ( ) . Lookup ( Keys ( "nested" , "set" ) )
if fresh . Origin . Locations [ 0 ] . Line == 99 || result . Sources ( ) [ 0 ] . Label != "metadata.yml" || result . Diagnostics ( ) != nil {
t . Fatal ( "result inspection aliases internal records" )
}
}
func TestLoadRejectsUnavailableOptionsAndDisabledDirectives ( t * testing . T ) {
t . Parallel ( )
type config struct {
Name string ` yaml:"name" `
}
validSource := func ( ) Source { return Bytes ( "options.yml" , [ ] byte ( "name: value\n" ) ) }
tests := [ ] struct {
name string
source Source
options [ ] Options [ config ]
code Code
} {
{ name : "multiple options" , source : validSource ( ) , options : [ ] Options [ config ] { { } , { } } , code : CodeOptionsInvalid } ,
2026-09-06 20:41:40 +00:00
{ name : "imports without filesystem context" , source : validSource ( ) , options : [ ] Options [ config ] { { Imports : true } } , code : CodeOptionsInvalid } ,
2026-09-06 20:51:21 +00:00
{ name : "incomplete filesystem" , source : validSource ( ) , options : [ ] Options [ config ] { { Filesystem : & FilesystemContext { } } } , code : CodeOptionsInvalid } ,
2026-09-06 20:03:22 +00:00
{ name : "missing version checker" , source : validSource ( ) , options : [ ] Options [ config ] { { Definition : Definition [ config ] { Version : & VersionRule { Path : Keys ( "version" ) } } } } , code : CodeOptionsInvalid } ,
{ name : "no-source filesystem" , source : NoSource ( ) , options : [ ] Options [ config ] { { Filesystem : & FilesystemContext { } } } , code : CodeOptionsInvalid } ,
}
for _ , test := range tests {
t . Run ( test . name , func ( t * testing . T ) {
result , err := Load ( test . source , test . options ... )
if result != nil || err == nil {
t . Fatalf ( "result, err = %#v, %v" , result , err )
}
var loadError * LoadError
if ! errors . As ( err , & loadError ) || len ( loadError . Diagnostics ( ) ) == 0 || loadError . Diagnostics ( ) [ 0 ] . Code != test . code {
t . Fatalf ( "error = %#v" , err )
}
} )
}
result , err := Load [ config ] ( Bytes ( "directive.yml" , [ ] byte ( "nested:\n _configkit: {}\n" ) ) )
if result != nil || err == nil {
t . Fatalf ( "result, err = %#v, %v" , result , err )
}
var loadError * LoadError
if ! errors . As ( err , & loadError ) {
t . Fatal ( err )
}
diagnostic := loadError . Diagnostics ( ) [ 0 ]
if diagnostic . Code != CodeImportDisabled || diagnostic . Path . String ( ) != "/nested/_configkit" || diagnostic . Primary == nil || diagnostic . Primary . Line != 2 {
t . Fatalf ( "diagnostic = %#v" , diagnostic )
}
}
func TestLoadReturnsNilForSourceSchemaAndDecodeFailures ( t * testing . T ) {
t . Parallel ( )
type invalidSchema struct {
Channel chan int ` yaml:"channel" `
}
type validConfig struct {
Known int ` yaml:"known" `
}
tests := [ ] struct {
name string
run func ( ) ( any , error )
code Code
} {
{ name : "source" , run : func ( ) ( any , error ) { return Load [ validConfig ] ( File ( filepath . Join ( t . TempDir ( ) , "missing.yml" ) ) ) } , code : CodeSourceMissing } ,
{ name : "schema" , run : func ( ) ( any , error ) { return Load [ invalidSchema ] ( Bytes ( "schema.yml" , [ ] byte ( "{}\n" ) ) ) } , code : CodeSchemaUnsupportedType } ,
{ name : "decode" , run : func ( ) ( any , error ) { return Load [ validConfig ] ( Bytes ( "decode.yml" , [ ] byte ( "unknown: 1\n" ) ) ) } , code : CodeDecodeUnknownField } ,
}
for _ , test := range tests {
t . Run ( test . name , func ( t * testing . T ) {
result , err := test . run ( )
if ! isNilInterface ( result ) || err == nil {
t . Fatalf ( "result, err = %#v, %v" , result , err )
}
var loadError * LoadError
if ! errors . As ( err , & loadError ) || len ( loadError . Diagnostics ( ) ) != 1 || loadError . Diagnostics ( ) [ 0 ] . Code != test . code {
t . Fatalf ( "error = %#v" , err )
}
} )
}
}
func isNilInterface ( value any ) bool {
if value == nil {
return true
}
reflected := reflect . ValueOf ( value )
return reflected . Kind ( ) == reflect . Pointer && reflected . IsNil ( )
}