143 lines
6.5 KiB
Go
143 lines
6.5 KiB
Go
package configkit_test
|
|
|
|
import (
|
|
"embed"
|
|
"io/fs"
|
|
"reflect"
|
|
"strconv"
|
|
"strings"
|
|
"testing"
|
|
"testing/fstest"
|
|
|
|
configkit "gitea.maximumdirect.net/eric/ConfigKit"
|
|
)
|
|
|
|
//go:embed testdata/filesystem
|
|
var filesystemFixtures embed.FS
|
|
|
|
type filesystemFacadeConfig struct {
|
|
Items map[string]string `yaml:"items"`
|
|
}
|
|
|
|
func TestFacadeFilesystemSourceImportsOverlayAndReuse(t *testing.T) {
|
|
fixture, err := fs.Sub(filesystemFixtures, "testdata/filesystem")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
namespace := configkit.NewFilesystem("embedded", fixture)
|
|
copyOfNamespace := namespace
|
|
source := namespace.File("config/main.yml")
|
|
for range 2 {
|
|
result, err := configkit.Load(source, configkit.Options[filesystemFacadeConfig]{
|
|
Imports: true, Overlay: "testing", Filesystem: &configkit.FilesystemContext{FS: ©OfNamespace},
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if want := (map[string]string{"main": "selected", "shared": "default"}); !reflect.DeepEqual(result.Config.Items, want) {
|
|
t.Fatalf("items = %#v, want %#v", result.Config.Items, want)
|
|
}
|
|
sources := result.Sources()
|
|
if len(sources) != 3 {
|
|
t.Fatalf("sources = %#v", sources)
|
|
}
|
|
for index, want := range []string{"config/main.yml", "shared.yml", "overlays/testing.yml"} {
|
|
if sources[index].ID != "source-"+strconv.Itoa(index+1) || sources[index].Path != want || sources[index].Kind != configkit.SourceKindFilesystem {
|
|
t.Errorf("source %d = %#v", index, sources[index])
|
|
}
|
|
if sources[index].Label != "embedded/"+want {
|
|
t.Errorf("source label = %q", sources[index].Label)
|
|
}
|
|
}
|
|
if sources[1].ImportedFrom == nil || sources[1].ImportedFrom.SourceID != sources[0].ID || sources[1].ImportedFrom.Line == 0 {
|
|
t.Fatalf("import location = %#v", sources[1].ImportedFrom)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFacadeFilesystemContextsAndIdentity(t *testing.T) {
|
|
first := configkit.NewFilesystem("same", fstest.MapFS{
|
|
"root/config/main.yml": &fstest.MapFile{Data: []byte("configkit: {imports: [{path: ../shared.yml}]}\n")},
|
|
"root/shared.yml": &fstest.MapFile{Data: []byte("items: {value: first}\n")},
|
|
"root/overlays/testing.yml": &fstest.MapFile{Data: []byte("items: {overlay: first}\n")},
|
|
})
|
|
second := configkit.NewFilesystem("same", fstest.MapFS{
|
|
"root/config/main.yml": &fstest.MapFile{Data: []byte("items: {value: second}\n")},
|
|
})
|
|
context := &configkit.FilesystemContext{Root: "root", FS: &first}
|
|
result, err := configkit.Load(first.File("root/config/main.yml"), configkit.Options[filesystemFacadeConfig]{Imports: true, Overlay: "testing", Filesystem: context})
|
|
if err != nil || result.Config.Items["value"] != "first" || result.Config.Items["overlay"] != "first" {
|
|
t.Fatalf("contained load = %#v, %v", result, err)
|
|
}
|
|
result, err = configkit.Load[filesystemFacadeConfig](second.File("root/config/main.yml"))
|
|
if err != nil || result.Config.Items["value"] != "second" {
|
|
t.Fatalf("same-label independent namespace = %#v, %v", result, err)
|
|
}
|
|
checkCode(t, second.File("root/config/main.yml"), configkit.Options[filesystemFacadeConfig]{Filesystem: context}, configkit.CodeOptionsInvalid)
|
|
checkCode(t, first.File("root/config/main.yml"), configkit.Options[filesystemFacadeConfig]{Filesystem: &configkit.FilesystemContext{Root: "root/config", FS: &first}, Imports: true}, configkit.CodeImportOutsideRoot)
|
|
checkCode(t, configkit.File("testdata/filesystem/config/main.yml"), configkit.Options[filesystemFacadeConfig]{Filesystem: context}, configkit.CodeOptionsInvalid)
|
|
|
|
for _, input := range []struct {
|
|
name string
|
|
source configkit.Source
|
|
kind configkit.SourceKind
|
|
}{
|
|
{"bytes", configkit.Bytes("memory", []byte("configkit: {imports: [{path: shared.yml}]}\n")), configkit.SourceKindBytes},
|
|
{"reader", configkit.Reader("stream", strings.NewReader("configkit: {imports: [{path: shared.yml}]}\n")), configkit.SourceKindReader},
|
|
} {
|
|
t.Run(input.name, func(t *testing.T) {
|
|
result, err := configkit.Load(input.source, configkit.Options[filesystemFacadeConfig]{Imports: true, Filesystem: &configkit.FilesystemContext{Root: "root", BaseDir: "root", FS: &first}})
|
|
if err != nil || result.Config.Items["value"] != "first" {
|
|
t.Fatalf("synthetic import = %#v, %v", result, err)
|
|
}
|
|
if got := result.Sources(); len(got) != 2 || got[0].Kind != input.kind || got[0].Path != "" || got[1].Kind != configkit.SourceKindFilesystem {
|
|
t.Fatalf("sources = %#v", got)
|
|
}
|
|
})
|
|
}
|
|
checkCode(t, configkit.Bytes("memory", []byte("items: {}\n")), configkit.Options[filesystemFacadeConfig]{Filesystem: &configkit.FilesystemContext{Root: "root", BaseDir: ".", FS: &first}}, configkit.CodeImportOutsideRoot)
|
|
result, err = configkit.Load(configkit.Bytes("memory", []byte("items: {value: main}\n")), configkit.Options[filesystemFacadeConfig]{
|
|
Overlay: "testing", Filesystem: &configkit.FilesystemContext{Root: "root", BaseDir: "root", FS: &first},
|
|
})
|
|
if err != nil || result.Config.Items["value"] != "main" || result.Config.Items["overlay"] != "first" {
|
|
t.Fatalf("synthetic selected overlay = %#v, %v", result, err)
|
|
}
|
|
}
|
|
|
|
func TestFacadeSourceKindsIncludeHostAndCLI(t *testing.T) {
|
|
result, err := configkit.Load(configkit.File("testdata/filesystem/shared.yml"), configkit.Options[filesystemFacadeConfig]{
|
|
Overrides: []configkit.Override{{Path: configkit.Keys("items", "shared"), Value: "changed", Flag: "--shared"}},
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
sources := result.Sources()
|
|
if len(sources) != 2 || sources[0].Kind != configkit.SourceKindFile || sources[0].Path == "" || sources[1].Kind != configkit.SourceKindCLI || sources[1].Path != "" {
|
|
t.Fatalf("host and CLI sources = %#v", sources)
|
|
}
|
|
}
|
|
|
|
func TestFacadeFilesystemConstructorDiagnostics(t *testing.T) {
|
|
var nilFilesystem fs.FS
|
|
var zero configkit.Filesystem
|
|
for _, source := range []configkit.Source{
|
|
zero.File("main.yml"),
|
|
configkit.NewFilesystem("", fstest.MapFS{}).File("main.yml"),
|
|
configkit.NewFilesystem("bad\nlabel", fstest.MapFS{}).File("main.yml"),
|
|
configkit.NewFilesystem("good", nilFilesystem).File("main.yml"),
|
|
configkit.NewFilesystem("good", fstest.MapFS{}).File("."),
|
|
configkit.NewFilesystem("good", fstest.MapFS{}).File("../outside.yml"),
|
|
} {
|
|
checkCode(t, source, configkit.Options[filesystemFacadeConfig]{}, configkit.CodeSourceInvalid)
|
|
}
|
|
}
|
|
|
|
func checkCode(t *testing.T, source configkit.Source, options configkit.Options[filesystemFacadeConfig], want configkit.Code) {
|
|
t.Helper()
|
|
_, err := configkit.Load(source, options)
|
|
loadError, ok := err.(*configkit.LoadError)
|
|
if !ok || len(loadError.Diagnostics()) == 0 || loadError.Diagnostics()[0].Code != want {
|
|
t.Fatalf("error = %#v, want %s", err, want)
|
|
}
|
|
}
|