Keep complete paths in missing version evidence

This commit is contained in:
2026-10-15 22:20:20 +00:00
parent 0a2246bdbe
commit e69ad0f32d
5 changed files with 105 additions and 7 deletions

View File

@@ -113,6 +113,63 @@ func TestFacadeSourceVersionModesPreserveImportOptIn(t *testing.T) {
}
}
func TestFacadeSourceVersionAbsenceKeepsCompleteEvidencePath(t *testing.T) {
t.Parallel()
for _, test := range []struct {
name, main, underlay string
path configkit.Path
}{
{"missing member", "meta: {version: main}\n", "{}\n", configkit.Keys("meta", "version")},
{"scalar obstruction", "meta: {version: main}\n", "meta: false\n", configkit.Keys("meta", "version")},
{"unavailable index", "meta: [null, null, null, {version: main}]\n", "meta: []\n", configkit.Keys("meta").Index(3).Key("version")},
} {
for _, mode := range []configkit.SourceVersionMode{configkit.SourceVersionModeIfPresent, configkit.SourceVersionModeRequired} {
var callbackEvidence *configkit.SourceVersionCheck
loaded, err := configkit.LoadLayered(configkit.Input{Source: configkit.Bytes("main", []byte(test.main))}, configkit.LayeredOptions[map[string]any]{
SourceVersionMode: mode,
Definition: configkit.Definition[map[string]any]{
Version: &configkit.VersionRule{Path: test.path, Check: func(configkit.Version, *configkit.Validation) error { return nil }},
Resolve: func(_ *map[string]any, resolution *configkit.Resolution) error {
source, found := resolution.Source("source-2")
if !found {
t.Fatal("missing callback source")
}
callbackEvidence = source.VersionCheck
return nil
},
},
Underlays: []configkit.Underlay{{Inputs: []configkit.Input{{
Source: configkit.Bytes("underlay", []byte(test.underlay)), Destination: configkit.Keys("under"),
}}}},
})
var evidence *configkit.SourceVersionCheck
if mode == configkit.SourceVersionModeRequired {
var failure *configkit.LoadError
if loaded != nil || !errors.As(err, &failure) {
t.Fatalf("%s: required omission did not fail", test.name)
}
diagnostics := failure.Diagnostics()
if len(diagnostics) != 1 || diagnostics[0].Code != configkit.CodeVersionError || diagnostics[0].Path.String() != test.path.String() {
t.Fatalf("%s: required diagnostics=%#v", test.name, diagnostics)
}
evidence = failure.Sources()[1].VersionCheck
} else {
if err != nil {
t.Fatalf("%s: %v", test.name, err)
}
evidence = loaded.Sources()[1].VersionCheck
if callbackEvidence == nil || callbackEvidence.Path.String() != test.path.String() {
t.Errorf("%s: callback path is incomplete", test.name)
}
}
if evidence == nil || evidence.Version.Present || evidence.Path.String() != test.path.String() ||
evidence.Location == nil || evidence.Location.SourceID != "source-2" || evidence.Location.Line != 1 {
t.Errorf("%s mode=%v: absence evidence=%#v", test.name, mode, evidence)
}
}
}
}
func (reader *sourceVersionModeReader) Read(data []byte) (int, error) {
reader.reads++
return reader.Reader.Read(data)