198 lines
4.8 KiB
Go
198 lines
4.8 KiB
Go
package config
|
|
|
|
import (
|
|
"errors"
|
|
"testing"
|
|
|
|
configkit "gitea.maximumdirect.net/eric/ConfigKit"
|
|
)
|
|
|
|
func TestDocumentPipelineNormalizesCanonicalIdentifiers(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
loaded, err := loadDocumentSource(configkit.Bytes("document.yml", []byte(`version: 5
|
|
pipelines:
|
|
" session ":
|
|
llm_profile: " local "
|
|
input:
|
|
module: " seriatim "
|
|
artifacts:
|
|
" spells ":
|
|
extract:
|
|
module: " dnd/spells "
|
|
structured_output_repair_attempts: 0
|
|
validators: []
|
|
merge:
|
|
module: dnd/merge
|
|
references:
|
|
previous:
|
|
artifact:
|
|
step: " default "
|
|
lane: " spells "
|
|
`)), LoadOptions{})
|
|
if err != nil {
|
|
var loadError *configkit.LoadError
|
|
if errors.As(err, &loadError) {
|
|
t.Fatalf("loadDocumentSource() diagnostics = %#v", loadError.Diagnostics())
|
|
}
|
|
t.Fatalf("loadDocumentSource() error = %v", err)
|
|
}
|
|
profile, ok := loaded.Config.Pipelines["session"]
|
|
if !ok || profile.Input.Module != "seriatim" || profile.LLMProfile == nil || *profile.LLMProfile != "local" {
|
|
t.Fatalf("normalized pipeline = %#v", loaded.Config.Pipelines)
|
|
}
|
|
lane, ok := profile.Artifacts["spells"]
|
|
if !ok || lane.Extract.StructuredOutputRepairAttempts == nil || *lane.Extract.StructuredOutputRepairAttempts != 0 || lane.Extract.Validators == nil || len(lane.Extract.Validators) != 0 {
|
|
t.Fatalf("normalized lane = %#v", profile.Artifacts)
|
|
}
|
|
selector := lane.Merge.References["previous"].Artifact
|
|
if selector == nil || selector.Step != "default" || selector.Lane != "spells" {
|
|
t.Fatalf("artifact selector = %#v", selector)
|
|
}
|
|
}
|
|
|
|
func TestDocumentPipelineRejectsInvalidShapes(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
name string
|
|
source string
|
|
path string
|
|
}{
|
|
{
|
|
name: "both pipeline forms",
|
|
source: `version: 5
|
|
pipelines:
|
|
session:
|
|
input: {module: seriatim}
|
|
artifacts: {}
|
|
steps:
|
|
- id: first
|
|
artifacts: {}
|
|
`,
|
|
path: "/pipelines/session/steps",
|
|
},
|
|
{
|
|
name: "empty ordered steps",
|
|
source: `version: 5
|
|
pipelines:
|
|
session:
|
|
input: {module: seriatim}
|
|
steps: []
|
|
`,
|
|
path: "/pipelines/session/steps",
|
|
},
|
|
{
|
|
name: "normalized pipeline collision",
|
|
source: `version: 5
|
|
pipelines:
|
|
session: {input: {module: seriatim}}
|
|
" session ": {input: {module: seriatim}}
|
|
`,
|
|
path: "/pipelines/session",
|
|
},
|
|
{
|
|
name: "duplicate lane across ordered steps",
|
|
source: `version: 5
|
|
pipelines:
|
|
session:
|
|
input: {module: seriatim}
|
|
steps:
|
|
- id: first
|
|
artifacts: {summary: {extract: {module: dnd/summary}}}
|
|
- id: second
|
|
artifacts: {summary: {extract: {module: dnd/summary}}}
|
|
`,
|
|
path: "/pipelines/session/steps/1/artifacts/summary",
|
|
},
|
|
{
|
|
name: "invalid reference union",
|
|
source: `version: 5
|
|
pipelines:
|
|
session:
|
|
input: {module: seriatim}
|
|
references:
|
|
party: {path: ./party.txt, artifact: {step: one, lane: summary}}
|
|
`,
|
|
path: "/pipelines/session/references/party",
|
|
},
|
|
}
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
_, err := loadDocumentSource(configkit.Bytes("document.yml", []byte(test.source)), LoadOptions{})
|
|
assertDocumentDiagnosticAt(t, err, test.path)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDocumentPipelineRejectsInvalidBindingPlacementAndPresence(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
name string
|
|
source string
|
|
path string
|
|
}{
|
|
{
|
|
name: "input validators",
|
|
source: `version: 5
|
|
pipelines:
|
|
session:
|
|
input:
|
|
module: seriatim
|
|
validators: [{module: generic/valid_json}]
|
|
`,
|
|
path: "/pipelines/session/input/validators",
|
|
},
|
|
{
|
|
name: "blank selected profile",
|
|
source: `version: 5
|
|
pipelines:
|
|
session:
|
|
llm_profile: " "
|
|
input: {module: seriatim}
|
|
`,
|
|
path: "/pipelines/session/llm_profile",
|
|
},
|
|
{
|
|
name: "null validators",
|
|
source: `version: 5
|
|
pipelines:
|
|
session:
|
|
input: {module: seriatim}
|
|
chunk: {module: generic/chunk, validators: null}
|
|
`,
|
|
path: "/pipelines/session/chunk/validators",
|
|
},
|
|
{
|
|
name: "negative retry budget",
|
|
source: `version: 5
|
|
pipelines:
|
|
session:
|
|
input: {module: seriatim, retries: -1}
|
|
`,
|
|
path: "/pipelines/session/input/retries",
|
|
},
|
|
}
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
_, err := loadDocumentSource(configkit.Bytes("document.yml", []byte(test.source)), LoadOptions{})
|
|
assertDocumentDiagnosticAt(t, err, test.path)
|
|
})
|
|
}
|
|
}
|
|
|
|
func assertDocumentDiagnosticAt(t *testing.T, err error, path string) {
|
|
t.Helper()
|
|
var loadError *configkit.LoadError
|
|
if !errors.As(err, &loadError) {
|
|
t.Fatalf("error = %v, want ConfigKit load error", err)
|
|
}
|
|
for _, diagnostic := range loadError.Diagnostics() {
|
|
if diagnostic.Path.String() == path {
|
|
return
|
|
}
|
|
}
|
|
t.Fatalf("diagnostics = %#v, want a diagnostic at %s", loadError.Diagnostics(), path)
|
|
}
|