Files
ConfigKit/internal/engine/selected_overlay_test.go

612 lines
24 KiB
Go

package engine
import (
"errors"
"io/fs"
"os"
"path"
"path/filepath"
"reflect"
"runtime"
"testing"
"testing/fstest"
)
type overlayTestConfig struct {
Settings struct {
Kept string `yaml:"kept"`
Changed string `yaml:"changed"`
Added string `yaml:"added"`
} `yaml:"settings"`
Values []string `yaml:"values"`
Nullable *string `yaml:"nullable"`
Value any `yaml:"value"`
Schema map[string]string `yaml:"schema"`
}
func TestNoSourceSelectedOverlayUsesRootedHostContext(t *testing.T) {
t.Parallel()
type config struct {
Resource string `yaml:"resource"`
}
root := t.TempDir()
overlayPath := writeImportFile(t, root, "overlays/testing.yml", "resource: asset.txt\n")
writeImportFile(t, root, "overlays/asset.txt", "host asset\n")
loaded, err := testLoad[config](NoSource(), Options[config]{
Overlay: "testing", Filesystem: &FilesystemContext{Root: root},
})
if err != nil {
t.Fatal(err)
}
sources := loaded.Sources()
if len(sources) != 1 || sources[0].ID != "source-1" || sources[0].Path != canonicalTestPath(t, overlayPath) || sources[0].Layer != LayerOverlay || sources[0].Kind != SourceKindFile {
t.Fatalf("NoSource overlay sources = %#v", sources)
}
context, ok := loaded.Inspection.SourceContext("source-1")
if !ok || context.BaseDir != "overlays" {
t.Fatalf("overlay resource context = %#v, %v", context, ok)
}
data, err := fs.ReadFile(context.FS, path.Join(context.BaseDir, loaded.Config.Resource))
if err != nil || string(data) != "host asset\n" {
t.Fatalf("overlay resource = %q, %v", data, err)
}
}
func TestNoSourceSelectedOverlayRequiresContextAndSelection(t *testing.T) {
t.Parallel()
requireLoadCode(t, NoSource(), Options[importTestConfig]{Overlay: "testing"}, CodeOptionsInvalid)
root := t.TempDir()
requireLoadCode(t, NoSource(), Options[importTestConfig]{
Overlay: "testing", Filesystem: &FilesystemContext{Root: root},
}, CodeOverlayMissing)
outside := t.TempDir()
requireLoadCode(t, NoSource(), Options[importTestConfig]{
Overlay: "testing", Filesystem: &FilesystemContext{Root: root, BaseDir: outside},
}, CodeImportOutsideRoot)
}
func TestNoSourceSelectedOverlayUsesCompleteNativeContext(t *testing.T) {
t.Parallel()
type config struct {
Resource string `yaml:"resource"`
}
filesystem := NewFilesystem("embedded", fstest.MapFS{
"overlays/testing.yml": &fstest.MapFile{Data: []byte("resource: asset.txt\n")},
"overlays/asset.txt": &fstest.MapFile{Data: []byte("native asset\n")},
})
loaded, err := testLoad[config](NoSource(), Options[config]{
Overlay: "testing", Filesystem: &FilesystemContext{FS: &filesystem, BaseDir: ".", Root: "."},
})
if err != nil {
t.Fatal(err)
}
sources := loaded.Sources()
if len(sources) != 1 || sources[0].ID != "source-1" || sources[0].Path != "overlays/testing.yml" || sources[0].Layer != LayerOverlay || sources[0].Kind != SourceKindFilesystem {
t.Fatalf("native NoSource overlay sources = %#v", sources)
}
context, ok := loaded.Inspection.SourceContext("source-1")
if !ok || context.BaseDir != "overlays" {
t.Fatalf("native overlay resource context = %#v, %v", context, ok)
}
data, err := fs.ReadFile(context.FS, path.Join(context.BaseDir, loaded.Config.Resource))
if err != nil || string(data) != "native asset\n" {
t.Fatalf("native overlay resource = %q, %v", data, err)
}
}
func TestLoadAppliesSelectedOverlayAfterBaseAndBeforeDefaults(t *testing.T) {
directory := t.TempDir()
mainPath := writeImportFile(t, directory, "main.yml", `configkit:
imports: [{path: base.yml}]
settings:
kept: main
changed: base
values: [base, stale]
nullable: base
value: {child: base}
`)
basePath := writeImportFile(t, directory, "base.yml", "settings: {added: imported}\n")
overlayPath := writeImportFile(t, directory, "overlays/testing.yml", `settings:
changed: overlay
values: [overlay]
nullable: null
value: scalar
`)
result, err := testLoad[overlayTestConfig](File(mainPath), Options[overlayTestConfig]{
Imports: true,
Overlay: "testing",
Definition: Definition[overlayTestConfig]{Defaults: func() overlayTestConfig {
defaultValue := "default"
return overlayTestConfig{
Values: []string{"default"}, Nullable: &defaultValue,
Settings: struct {
Kept string `yaml:"kept"`
Changed string `yaml:"changed"`
Added string `yaml:"added"`
}{Kept: "default", Changed: "default", Added: "default"},
}
}},
})
if err != nil {
t.Fatal(err)
}
if result.Config.Settings.Kept != "main" || result.Config.Settings.Changed != "overlay" || result.Config.Settings.Added != "imported" {
t.Fatalf("settings = %#v", result.Config.Settings)
}
if !reflect.DeepEqual(result.Config.Values, []string{"overlay"}) || result.Config.Nullable != nil || result.Config.Value != "scalar" {
t.Fatalf("overlay values = values %#v nullable %#v value %#v", result.Config.Values, result.Config.Nullable, result.Config.Value)
}
sources := result.Sources()
wantPaths := []string{canonicalTestPath(t, mainPath), canonicalTestPath(t, basePath), canonicalTestPath(t, overlayPath)}
gotPaths := make([]string, len(sources))
for index, source := range sources {
gotPaths[index] = source.Path
}
if !reflect.DeepEqual(gotPaths, wantPaths) || sources[2].Layer != LayerOverlay {
t.Fatalf("sources = %#v", sources)
}
changed, _ := result.Metadata().Lookup(Keys("settings", "changed"))
kept, _ := result.Metadata().Lookup(Keys("settings", "kept"))
if changed.Origin.Layer != LayerOverlay || changed.Origin.Locations[0].SourceID != "source-3" || kept.Origin.Layer != LayerBase {
t.Fatalf("origins = changed %#v kept %#v", changed, kept)
}
if _, ok := result.Metadata().Lookup(Keys("value", "child")); ok {
t.Fatal("removed child remains effective")
}
childHistory := result.Metadata().History(Keys("value", "child"))
if len(childHistory) < 2 || childHistory[len(childHistory)-1].Path.String() != "/value" || childHistory[len(childHistory)-1].Origin.Layer != LayerOverlay {
t.Fatalf("removed child history = %#v", childHistory)
}
if _, ok := result.Metadata().Lookup(Keys("values").Index(1)); ok {
t.Fatal("removed sequence index remains effective")
}
indexHistory := result.Metadata().History(Keys("values").Index(1))
if len(indexHistory) < 2 || indexHistory[len(indexHistory)-1].Path.String() != "/values" {
t.Fatalf("removed sequence history = %#v", indexHistory)
}
}
func TestLoadSelectedOverlayAppliesCollectionOperationsAndEvidence(t *testing.T) {
t.Parallel()
type item struct {
ID string `yaml:"id"`
Value string `yaml:"value"`
Children []item `yaml:"children"`
}
type config struct {
Items []item `yaml:"items"`
}
tests := []struct {
name string
mode string
overlay string
want []item
}{
{
name: "append",
mode: "append",
overlay: `configkit:
sequences:
- destination: [items]
key: id
mode: append
items: [{id: c, value: added}]
`,
want: []item{{ID: "a", Value: "old"}, {ID: "b", Value: "kept"}, {ID: "c", Value: "added"}},
},
{
name: "upsert replaces complete records at retained positions",
mode: "upsert",
overlay: `configkit:
sequences:
- destination: [items]
key: id
mode: upsert
items: [{id: a, value: new}]
`,
want: []item{{ID: "a", Value: "new"}, {ID: "b", Value: "kept"}},
},
{
name: "replace",
mode: "replace",
overlay: `configkit:
sequences:
- destination: [items]
key: id
mode: replace
items: [{id: c, value: replacement}]
`,
want: []item{{ID: "c", Value: "replacement"}},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
directory := t.TempDir()
mainPath := writeImportFile(t, directory, "main.yml", "items: [{id: a, value: old, children: [{id: child}]}, {id: b, value: kept}]\n")
writeImportFile(t, directory, "overlays/testing.yml", test.overlay)
result, err := testLoad[config](File(mainPath), Options[config]{Overlay: "testing"})
if err != nil {
t.Fatal(err)
}
if len(result.Config.Items) != len(test.want) {
t.Fatalf("items = %#v, want %#v", result.Config.Items, test.want)
}
for index, want := range test.want {
if result.Config.Items[index].ID != want.ID || result.Config.Items[index].Value != want.Value {
t.Fatalf("items[%d] = %#v, want id %q value %q", index, result.Config.Items[index], want.ID, want.Value)
}
}
if _, found := result.Metadata().Lookup(Keys("configkit")); found {
t.Fatal("overlay collection controls reached application metadata")
}
if test.mode == "append" {
base, _ := result.Metadata().Lookup(Keys("items").Index(0).Key("value"))
added, _ := result.Metadata().Lookup(Keys("items").Index(2).Key("value"))
if base.Origin.Layer != LayerBase || added.Origin.Layer != LayerOverlay {
t.Fatalf("append origins = base %#v added %#v", base.Origin, added.Origin)
}
history := result.Metadata().History(Keys("items").Index(2).Key("value"))
if len(history) == 0 || history[len(history)-1].Origin.Layer != LayerOverlay {
t.Fatalf("append history = %#v", history)
}
}
if test.mode == "upsert" {
if _, found := result.Metadata().Lookup(Keys("items").Index(0).Key("children").Index(0)); found {
t.Fatal("upsert retained a discarded child")
}
history := result.Metadata().History(Keys("items").Index(0).Key("children").Index(0))
if len(history) < 2 {
t.Fatalf("discarded child history = %#v", history)
}
}
})
}
}
func TestLoadSelectedOverlayReconcilesPendingAndRetainedCollectionPolicy(t *testing.T) {
t.Parallel()
requireCode := func(t *testing.T, main, overlay string, code Code) {
t.Helper()
directory := t.TempDir()
mainPath := writeImportFile(t, directory, "main.yml", main)
writeImportFile(t, directory, "overlays/testing.yml", overlay)
_, err := testLoad[ordinarySequenceConfig](File(mainPath), Options[ordinarySequenceConfig]{Overlay: "testing"})
var loadError *LoadError
if !errors.As(err, &loadError) || len(loadError.Diagnostics()) == 0 || loadError.Diagnostics()[0].Code != code {
t.Fatalf("load error = %#v, want %s", err, code)
}
}
t.Run("key only validates retained records", func(t *testing.T) {
requireCode(t, "items: [{id: duplicate}, {id: duplicate}]\n", `configkit:
sequences:
- destination: [items]
key: id
`, CodeSequenceConflict)
})
t.Run("mode only retains lower identity", func(t *testing.T) {
directory := t.TempDir()
mainPath := writeImportFile(t, directory, "main.yml", `configkit:
sequences:
- destination: [items]
key: id
mode: append
items: [{id: base}]
`)
writeImportFile(t, directory, "overlays/testing.yml", `configkit:
sequences:
- destination: [items]
mode: append
items: [{id: overlay}]
`)
result, err := testLoad[ordinarySequenceConfig](File(mainPath), Options[ordinarySequenceConfig]{Overlay: "testing"})
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(result.Config.Items, []ordinarySequenceItem{{ID: "base"}, {ID: "overlay"}}) {
t.Fatalf("items = %#v", result.Config.Items)
}
})
t.Run("lower explicit mode remains active when overlay omits it", func(t *testing.T) {
directory := t.TempDir()
mainPath := writeImportFile(t, directory, "main.yml", `configkit:
sequences:
- destination: [items]
key: id
mode: append
items: [{id: base}]
`)
writeImportFile(t, directory, "overlays/testing.yml", "items: [{id: overlay}]\n")
result, err := testLoad[ordinarySequenceConfig](File(mainPath), Options[ordinarySequenceConfig]{Overlay: "testing"})
if err != nil || !reflect.DeepEqual(result.Config.Items, []ordinarySequenceItem{{ID: "base"}, {ID: "overlay"}}) {
t.Fatalf("retained operation = %#v, %v", result, err)
}
})
t.Run("overlay identity must agree with retained identity", func(t *testing.T) {
requireCode(t, `configkit:
sequences:
- destination: [items]
key: id
items: [{id: base}]
`, `configkit:
sequences:
- destination: [items]
key: slug
items: [{id: overlay}]
`, CodeSequenceConflict)
})
t.Run("replace accepts null and append rejects it", func(t *testing.T) {
for _, test := range []struct {
mode string
want Code
}{
{mode: "replace"},
{mode: "append", want: CodeSequenceInvalid},
} {
overlay := "configkit:\n sequences:\n - destination: [items]\n key: id\n mode: " + test.mode + "\nitems: null\n"
if test.want != "" {
requireCode(t, "items: [{id: base}]\n", overlay, test.want)
continue
}
directory := t.TempDir()
mainPath := writeImportFile(t, directory, "main.yml", "items: [{id: base}]\n")
writeImportFile(t, directory, "overlays/testing.yml", overlay)
result, err := testLoad[ordinarySequenceConfig](File(mainPath), Options[ordinarySequenceConfig]{Overlay: "testing"})
if err != nil || result.Config.Items != nil {
t.Fatalf("replace null = %#v, %v", result, err)
}
}
})
t.Run("empty contributions and kind mismatches", func(t *testing.T) {
for _, test := range []struct {
name, mode, value string
want int
wantCode Code
}{
{name: "append empty", mode: "append", value: "[]", want: 1},
{name: "upsert empty", mode: "upsert", value: "[]", want: 1},
{name: "replace empty", mode: "replace", value: "[]", want: 0},
{name: "append mapping", mode: "append", value: "{id: overlay}", wantCode: CodeSequenceInvalid},
} {
t.Run(test.name, func(t *testing.T) {
overlay := "configkit:\n sequences:\n - destination: [items]\n key: id\n mode: " + test.mode + "\nitems: " + test.value + "\n"
if test.wantCode != "" {
requireCode(t, "items: [{id: base}]\n", overlay, test.wantCode)
return
}
directory := t.TempDir()
mainPath := writeImportFile(t, directory, "main.yml", "items: [{id: base}]\n")
writeImportFile(t, directory, "overlays/testing.yml", overlay)
result, err := testLoad[ordinarySequenceConfig](File(mainPath), Options[ordinarySequenceConfig]{Overlay: "testing"})
if err != nil || len(result.Config.Items) != test.want {
t.Fatalf("%s result = %#v, %v", test.name, result, err)
}
})
}
})
}
func TestLoadSelectedOverlayKeepsCollectionPoliciesIndependent(t *testing.T) {
t.Parallel()
directory := t.TempDir()
mainPath := writeImportFile(t, directory, "main.yml", `configkit:
sequences:
- destination: [items]
key: id
mode: append
- destination: [catalog, items]
key: id
mode: append
items: [{id: base}]
catalog: {items: [{id: catalog-base}]}
`)
writeImportFile(t, directory, "overlays/testing.yml", `configkit:
sequences:
- destination: [items]
mode: upsert
- destination: [catalog, items]
mode: append
items: [{id: base}]
catalog: {items: [{id: catalog-overlay}]}
`)
result, err := testLoad[ordinarySequenceConfig](File(mainPath), Options[ordinarySequenceConfig]{Overlay: "testing"})
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(result.Config.Items, []ordinarySequenceItem{{ID: "base"}}) ||
!reflect.DeepEqual(result.Config.Catalog.Items, []ordinarySequenceItem{{ID: "catalog-base"}, {ID: "catalog-overlay"}}) {
t.Fatalf("independent overlay policies = items %#v, catalog %#v", result.Config.Items, result.Config.Catalog.Items)
}
}
func TestLoadOverlaySelectionUsesOneFixedYAMLFile(t *testing.T) {
directory := t.TempDir()
mainPath := writeImportFile(t, directory, "main.yml", "settings: {kept: base}\n")
writeImportFile(t, directory, "overlays/testing.yml", "settings: {changed: selected}\n")
writeImportFile(t, directory, "profiles/testing.yml", "settings: {changed: legacy}\n")
writeImportFile(t, directory, "overlays/default.yml", "settings: {changed: forbidden}\n")
for _, name := range []string{"", "default"} {
result, err := testLoad[overlayTestConfig](File(mainPath), Options[overlayTestConfig]{Overlay: name})
if err != nil || result.Config.Settings.Changed != "" || len(result.Sources()) != 1 {
t.Fatalf("inactive overlay %q = %#v, %v", name, result, err)
}
}
selected, err := testLoad[overlayTestConfig](File(mainPath), Options[overlayTestConfig]{Overlay: "testing"})
if err != nil || selected.Config.Settings.Changed != "selected" || len(selected.Sources()) != 2 ||
selected.Sources()[1].Label != "overlays/testing.yml" || selected.Sources()[1].Layer != LayerOverlay {
t.Fatalf("selected overlay = %#v, %v", selected, err)
}
t.Run("legacy directory is not selected", func(t *testing.T) {
legacyDirectory := t.TempDir()
legacyMain := writeImportFile(t, legacyDirectory, "main.yml", "settings: {kept: base}\n")
writeImportFile(t, legacyDirectory, "profiles/testing.yml", "settings: {changed: legacy}\n")
requireOverlayLoadCode(t, File(legacyMain), Options[overlayTestConfig]{Overlay: "testing"}, CodeOverlayMissing)
})
for _, name := range []string{"../testing", "testing.yml", "one,two", "with space", "é", "bad\x00name"} {
t.Run(name, func(t *testing.T) {
requireOverlayLoadCode(t, File(mainPath), Options[overlayTestConfig]{Overlay: name}, CodeOptionsInvalid)
})
}
requireOverlayLoadCode(t, File(mainPath), Options[overlayTestConfig]{Overlay: "missing"}, CodeOverlayMissing)
writeImportFile(t, directory, "overlays/fallback.yaml", "settings: {changed: fallback}\n")
requireOverlayLoadCode(t, File(mainPath), Options[overlayTestConfig]{Overlay: "fallback"}, CodeOverlayMissing)
}
func TestLoadOverlayRejectsDirectivesVersionsAndBaseAliases(t *testing.T) {
versionRule := &VersionRule{Path: Keys("schema", "version"), Check: func(version Version, _ *Validation) error {
if !version.Present || version.Text != "4" {
return errors.New("unexpected version")
}
return nil
}}
for _, test := range []struct {
name string
overlay string
code Code
}{
{name: "root directive", overlay: "configkit: {}\n", code: CodeOverlayDirective},
{name: "nested directive", overlay: "settings: {configkit: {}}\n", code: CodeOverlayDirective},
{name: "equal integer version", overlay: "schema: {version: 4}\n", code: CodeOverlayVersion},
{name: "ancestor scalar", overlay: "schema: null\n", code: CodeOverlayVersion},
} {
t.Run(test.name, func(t *testing.T) {
directory := t.TempDir()
mainPath := writeImportFile(t, directory, "main.yml", "schema: {version: 4}\n")
writeImportFile(t, directory, "overlays/testing.yml", test.overlay)
requireOverlayLoadCode(t, File(mainPath), Options[overlayTestConfig]{Overlay: "testing", Definition: Definition[overlayTestConfig]{Version: versionRule}}, test.code)
})
}
t.Run("mapping sibling is allowed", func(t *testing.T) {
directory := t.TempDir()
mainPath := writeImportFile(t, directory, "main.yml", "schema: {version: 4}\n")
writeImportFile(t, directory, "overlays/testing.yml", "schema: {other: allowed}\n")
result, err := testLoad[overlayTestConfig](File(mainPath), Options[overlayTestConfig]{Overlay: "testing", Definition: Definition[overlayTestConfig]{Version: versionRule}})
if err != nil || result.Config.Schema["other"] != "allowed" {
t.Fatalf("mapping sibling = %#v, %v", result, err)
}
})
t.Run("overlay aliases imported base", func(t *testing.T) {
directory := t.TempDir()
mainPath := writeImportFile(t, directory, "main.yml", "configkit: {imports: [{path: overlays/testing.yml}]}\n")
writeImportFile(t, directory, "overlays/testing.yml", "settings: {changed: value}\n")
requireOverlayLoadCode(t, File(mainPath), Options[overlayTestConfig]{Imports: true, Overlay: "testing"}, CodeOverlayRepeated)
})
}
func TestLoadOverlayKeepsBaseFailuresAndFilesystemContainment(t *testing.T) {
t.Run("base parse precedes overlay", func(t *testing.T) {
directory := t.TempDir()
mainPath := writeImportFile(t, directory, "main.yml", "settings: [\n")
writeImportFile(t, directory, "overlays/testing.yml", "settings: {changed: overlay}\n")
requireOverlayLoadCode(t, File(mainPath), Options[overlayTestConfig]{Overlay: "testing"}, CodeYAMLInvalid)
})
t.Run("overlay parse", func(t *testing.T) {
directory := t.TempDir()
mainPath := writeImportFile(t, directory, "main.yml", "{}\n")
writeImportFile(t, directory, "overlays/testing.yml", "settings: [\n")
loadError := requireOverlayLoadCode(t, File(mainPath), Options[overlayTestConfig]{Overlay: "testing"}, CodeYAMLInvalid)
if loadError.Diagnostics()[0].Primary.SourceID != "source-2" || len(loadError.Sources()) != 2 {
t.Fatalf("overlay parse attribution = %#v / %#v", loadError.Diagnostics(), loadError.Sources())
}
})
if runtime.GOOS == "linux" || runtime.GOOS == "darwin" {
t.Run("symlink escape", func(t *testing.T) {
root := t.TempDir()
outside := t.TempDir()
outsideOverlay := writeImportFile(t, outside, "testing.yml", "settings: {changed: outside}\n")
if err := os.Mkdir(filepath.Join(root, "overlays"), 0o755); err != nil {
t.Fatal(err)
}
if err := os.Symlink(outsideOverlay, filepath.Join(root, "overlays/testing.yml")); err != nil {
t.Skipf("symlinks unavailable: %v", err)
}
mainPath := writeImportFile(t, root, "main.yml", "{}\n")
requireOverlayLoadCode(t, File(mainPath), Options[overlayTestConfig]{Overlay: "testing"}, CodeOverlayOutsideRoot)
})
}
t.Run("byte source context", func(t *testing.T) {
directory := t.TempDir()
writeImportFile(t, directory, "overlays/testing.yml", "settings: {changed: selected}\n")
result, err := testLoad[overlayTestConfig](Bytes("s3://bucket/main.yml", []byte("{}\n")), Options[overlayTestConfig]{
Overlay: "testing", Filesystem: &FilesystemContext{BaseDir: directory, Root: directory},
})
if err != nil || result.Config.Settings.Changed != "selected" {
t.Fatalf("byte overlay = %#v, %v", result, err)
}
requireOverlayLoadCode(t, Bytes("memory.yml", []byte("{}\n")), Options[overlayTestConfig]{Overlay: "testing"}, CodeOptionsInvalid)
})
}
func TestLoadOverlayCountsAgainstAggregateBudgets(t *testing.T) {
for _, test := range []struct {
name string
limits func(parsedSource, int) importLimits
}{
{name: "source count", limits: func(_ parsedSource, _ int) importLimits {
return importLimits{sources: 1, bytes: maxTotalBytes, nodes: maxDocumentNodes}
}},
{name: "aggregate bytes", limits: func(main parsedSource, overlayBytes int) importLimits {
return importLimits{sources: 2, bytes: main.bytes + int64(overlayBytes) - 1, nodes: maxDocumentNodes}
}},
{name: "aggregate nodes", limits: func(main parsedSource, _ int) importLimits {
return importLimits{sources: 2, bytes: maxTotalBytes, nodes: countInputNodes(main.document) + 1}
}},
} {
t.Run(test.name, func(t *testing.T) {
directory := t.TempDir()
mainPath := writeImportFile(t, directory, "main.yml", "{}\n")
overlayData := "settings: {changed: selected}\n"
writeImportFile(t, directory, "overlays/testing.yml", overlayData)
main, diagnostics := parseSource(File(mainPath), "source-1", defaultParseLimits())
if len(diagnostics) != 0 {
t.Fatal(diagnostics)
}
base, diagnostics := composeDocuments(main.document)
if len(diagnostics) != 0 {
t.Fatal(diagnostics)
}
base.inputBytes = main.bytes
base.inputNodes = countInputNodes(main.document)
_, _, diagnostics = loadSelectedOverlayDocument(File(mainPath), nil, main, base, sourceInfos(main.source), "testing", nil, test.limits(main, len(overlayData)))
if len(diagnostics) == 0 || diagnostics[0].Code != CodeOverlayLimitExceeded {
t.Fatalf("diagnostics = %#v", diagnostics)
}
})
}
}
func requireOverlayLoadCode(t *testing.T, source Source, options Options[overlayTestConfig], code Code) *LoadError {
t.Helper()
result, err := testLoad[overlayTestConfig](source, options)
if result != nil || err == nil {
t.Fatalf("result, error = %#v, %v", result, err)
}
var loadError *LoadError
if !errors.As(err, &loadError) {
t.Fatalf("error type = %T", err)
}
diagnostics := loadError.Diagnostics()
if len(diagnostics) == 0 || diagnostics[0].Code != code {
t.Fatalf("diagnostics = %#v, want %s", diagnostics, code)
}
return loadError
}