96 lines
3.2 KiB
Go
96 lines
3.2 KiB
Go
package configkit_test
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"strings"
|
|
"testing"
|
|
"testing/fstest"
|
|
|
|
configkit "go.maximumdirect.net/configkit"
|
|
)
|
|
|
|
func TestFacadeCompositionConflictKeepsClaimantOrder(t *testing.T) {
|
|
filesystem := configkit.NewFilesystem("bundle", fstest.MapFS{
|
|
"a.yml": &fstest.MapFile{Data: []byte(`configkit:
|
|
imports:
|
|
- path: z.yml
|
|
`)},
|
|
"b.yml": &fstest.MapFile{Data: []byte("x: b\n")},
|
|
"c.yml": &fstest.MapFile{Data: []byte("x: c\n")},
|
|
"z.yml": &fstest.MapFile{Data: []byte("x: z\n")},
|
|
})
|
|
main := configkit.Mapping("main", map[string]any{
|
|
"configkit": map[string]any{"imports": []any{
|
|
map[string]any{"path": "a.yml"},
|
|
map[string]any{"path": "b.yml"},
|
|
map[string]any{"path": "c.yml"},
|
|
}},
|
|
})
|
|
_, err := configkit.Load[map[string]any](main, configkit.Options[map[string]any]{
|
|
Imports: true,
|
|
Filesystem: &configkit.FilesystemContext{
|
|
FS: &filesystem, Root: ".", BaseDir: ".",
|
|
},
|
|
})
|
|
var loadError *configkit.LoadError
|
|
if !errors.As(err, &loadError) {
|
|
t.Fatalf("Load error = %v, want composition LoadError", err)
|
|
}
|
|
diagnostics := loadError.Diagnostics()
|
|
if len(diagnostics) != 1 {
|
|
t.Fatalf("diagnostics = %#v, want one composition conflict", diagnostics)
|
|
}
|
|
diagnostic := diagnostics[0]
|
|
if diagnostic.Code != configkit.CodeComposeConflict || diagnostic.Path.String() != "/x" || diagnostic.Primary == nil {
|
|
t.Fatalf("composition diagnostic = %#v", diagnostic)
|
|
}
|
|
|
|
pathsByID := make(map[string]string)
|
|
var acquisitionOrder []string
|
|
for _, source := range loadError.Sources() {
|
|
pathsByID[source.ID] = source.Path
|
|
for _, name := range []string{"z.yml", "b.yml", "c.yml"} {
|
|
if source.Path == name || strings.HasSuffix(source.Path, "/"+name) {
|
|
acquisitionOrder = append(acquisitionOrder, strings.TrimSuffix(name, ".yml"))
|
|
break
|
|
}
|
|
}
|
|
}
|
|
if strings.Join(acquisitionOrder, ",") != "z,b,c" {
|
|
t.Fatalf("claimant acquisition order = %v, want z,b,c", acquisitionOrder)
|
|
}
|
|
claimant := func(location configkit.Location) string {
|
|
for _, name := range []string{"b.yml", "c.yml", "z.yml"} {
|
|
if pathsByID[location.SourceID] == name || strings.HasSuffix(pathsByID[location.SourceID], "/"+name) {
|
|
return strings.TrimSuffix(name, ".yml")
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
if got := claimant(*diagnostic.Primary); got != "b" {
|
|
t.Fatalf("primary claimant = %q, want b (sources: %#v)", got, pathsByID)
|
|
}
|
|
if len(diagnostic.Related) != 2 || claimant(diagnostic.Related[0]) != "c" || claimant(diagnostic.Related[1]) != "z" {
|
|
t.Fatalf("related claimants = %#v, want c then z", diagnostic.Related)
|
|
}
|
|
|
|
var output bytes.Buffer
|
|
if err := configkit.WriteDiagnostics(&output, diagnostics); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
positions := []int{
|
|
strings.Index(output.String(), diagnostic.Primary.SourceID),
|
|
strings.Index(output.String(), diagnostic.Related[0].SourceID),
|
|
strings.Index(output.String(), diagnostic.Related[1].SourceID),
|
|
}
|
|
if positions[0] < 0 || positions[1] <= positions[0] || positions[2] <= positions[1] {
|
|
t.Fatalf("rendered claimant order = %v in %q", positions, output.String())
|
|
}
|
|
|
|
diagnostics[0].Related[0].SourceID = "mutated"
|
|
if got := claimant(loadError.Diagnostics()[0].Related[0]); got != "c" {
|
|
t.Fatalf("LoadError.Diagnostics retained caller mutation; first claimant = %q", got)
|
|
}
|
|
}
|