Pass effective destinations through import traversal

This commit is contained in:
2026-10-14 17:21:07 +00:00
parent a8beb3e620
commit 49c0c6d908
7 changed files with 189 additions and 35 deletions

View File

@@ -71,6 +71,124 @@ first: one
}
}
func TestImportTraversalUsesPerDeclarationDestinations(t *testing.T) {
t.Parallel()
directory := t.TempDir()
mainPath := writeImportFile(t, directory, "main.yml", `configkit:
imports:
- path: parent.yml
- path: sibling.yml
- glob: fragments/*.yml
`)
parentPath := writeImportFile(t, directory, "parent.yml", `configkit:
imports:
- path: nested/child.yml
parent: true
`)
childPath := writeImportFile(t, directory, "nested/child.yml", "child: true\n")
siblingPath := writeImportFile(t, directory, "sibling.yml", "sibling: true\n")
alphaPath := writeImportFile(t, directory, "fragments/a.yml", "alpha: true\n")
betaPath := writeImportFile(t, directory, "fragments/b.yml", "beta: true\n")
main := parseImportMain(t, mainPath)
_, declarations, diagnostics := splitImportDirectives(main.document)
if len(diagnostics) != 0 {
t.Fatalf("main directive diagnostics = %#v", diagnostics)
}
declarations[0].destination = Keys("parent")
declarations[1].destination = Keys("sibling")
declarations[2].destination = Keys("collection")
access, err := openHostAccess(directory)
if err != nil {
t.Fatal(err)
}
defer func() { _ = access.close() }()
state := importTraversal{
access: access, accounting: &importAccounting{}, limits: defaultImportLimits(),
active: make(map[resourceIdentity]int), visited: make(map[resourceIdentity]importRoute),
}
if diagnostics := state.walkDeclarations(directory, declarations, 0, Keys("entry")); len(diagnostics) != 0 {
t.Fatalf("walk diagnostics = %#v", diagnostics)
}
wantSources := []struct {
path string
destination string
}{
{path: parentPath, destination: "/entry/parent"},
{path: childPath, destination: "/entry/parent"},
{path: siblingPath, destination: "/entry/sibling"},
{path: alphaPath, destination: "/entry/collection"},
{path: betaPath, destination: "/entry/collection"},
}
if len(state.sources) != len(wantSources) {
t.Fatalf("import sources = %#v, want %d", state.sources, len(wantSources))
}
for index, want := range wantSources {
got := state.sources[index]
if got.Path != canonicalTestPath(t, want.path) || got.Destination.String() != want.destination {
t.Errorf("source %d = (%q, %q), want (%q, %q)", index, got.Path, got.Destination.String(), canonicalTestPath(t, want.path), want.destination)
}
}
composed, diagnostics := composeDocuments(state.documents...)
if len(diagnostics) != 0 {
t.Fatalf("composition diagnostics = %#v", diagnostics)
}
for _, path := range []Path{
Keys("entry", "parent", "parent"), Keys("entry", "parent", "child"),
Keys("entry", "sibling", "sibling"), Keys("entry", "collection", "alpha"),
Keys("entry", "collection", "beta"),
} {
if _, present := documentAtPath(composed.root, path); !present {
t.Errorf("no composed value at %q", path.String())
}
}
}
func TestEntryDestinationSurvivesImportSetupAndParseFailures(t *testing.T) {
t.Parallel()
t.Run("import context failure", func(t *testing.T) {
directory := t.TempDir()
mainPath := writeImportFile(t, directory, "main.yml", "configkit: {imports: [{path: child.yml}]}\n")
input, diagnostics := assembleBaseInputTracked(
File(mainPath),
Options[map[string]any]{Imports: true, Filesystem: &FilesystemContext{Root: t.TempDir()}},
Keys("mounted"), &importAccounting{}, nil, nil,
)
if len(diagnostics) != 1 || diagnostics[0].Code != CodeImportOutsideRoot {
t.Fatalf("context diagnostics = %#v", diagnostics)
}
if len(input.sources) != 1 || input.sources[0].Destination.String() != "/mounted" {
t.Fatalf("entry source fallback = %#v", input.sources)
}
})
t.Run("imported parse failure", func(t *testing.T) {
directory := t.TempDir()
mainPath := writeImportFile(t, directory, "main.yml", "configkit: {imports: [{path: broken.yml}]}\n")
writeImportFile(t, directory, "broken.yml", "broken: [\n")
input, diagnostics := assembleBaseInputTracked(
File(mainPath), Options[map[string]any]{Imports: true},
Keys("mounted"), &importAccounting{}, nil, nil,
)
if len(diagnostics) != 1 || diagnostics[0].Code != CodeYAMLInvalid {
t.Fatalf("parse diagnostics = %#v", diagnostics)
}
if len(input.sources) != 2 {
t.Fatalf("parse-failure sources = %#v", input.sources)
}
for index, source := range input.sources {
if source.Destination.String() != "/mounted" {
t.Errorf("source %d destination = %q, want /mounted", index, source.Destination.String())
}
}
})
}
func TestLayeredNativeFilesystemImportsInheritInputDestination(t *testing.T) {
t.Parallel()