Files
promptkit/sources_contract_test.go

125 lines
5.0 KiB
Go

package promptkit_test
import (
"bytes"
"context"
"encoding/json"
"errors"
"strings"
"testing"
"go.maximumdirect.net/configkit"
"go.maximumdirect.net/promptkit"
)
func TestProgrammaticSourcesPreserveOrderAndRejectDuplicates(t *testing.T) {
endpoint := "https://example.invalid/v1"
params := map[string]any{"visible": "original"}
backendSource := promptkit.BackendSource("backends", []promptkit.BackendConfig{
{ID: "zeta", Endpoint: &endpoint, ExtraParams: params}, {ID: "alpha", Endpoint: &endpoint},
})
profileSource := promptkit.ProfileSource("profiles", []promptkit.ProfileConfig{
{ID: "zeta", ExtraParams: params}, {ID: "alpha"},
})
params["visible"] = "changed"
engine, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{
Underlays: []configkit.Underlay{{Inputs: []configkit.Input{{Source: backendSource}, {Source: profileSource}}}},
}}, promptkit.WithBundledOpenRouter(false))
if err != nil {
t.Fatal(err)
}
view, err := engine.InspectConfiguration()
if err != nil {
t.Fatal(err)
}
var report bytes.Buffer
if err := view.WriteEffective(&report); err != nil {
t.Fatal(err)
}
contents := report.String()
if strings.Count(contents, "original") != 2 || strings.Contains(contents, "changed") {
t.Fatalf("source ownership was lost: %s", contents)
}
for _, kind := range []string{"backends", "profiles"} {
for index, id := range []string{"zeta", "alpha"} {
entry, found := view.Explain(configkit.Keys(kind).Index(index).Key("id"))
if !found || !strings.Contains(entry.Effective.YAML, id) {
t.Fatalf("%s entry %d = %+v, want %s", kind, index, entry, id)
}
}
}
for _, source := range []configkit.Source{
promptkit.BackendSource("duplicate backends", []promptkit.BackendConfig{{ID: "duplicate", Endpoint: &endpoint}, {ID: "duplicate", Endpoint: &endpoint}}),
promptkit.ProfileSource("duplicate profiles", []promptkit.ProfileConfig{{ID: "duplicate"}, {ID: "duplicate"}}),
} {
_, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{Main: &configkit.Input{Source: source}}})
if !errors.Is(err, promptkit.ErrInvalidConfig) {
t.Fatalf("duplicate source error = %v, want ErrInvalidConfig", err)
}
}
}
func TestProgrammaticProfileVariantInherits(t *testing.T) {
parent, endpoint, model, timeout := "base", "https://example.invalid/v1", "synthetic-model", 15
source := promptkit.ProfileSource("profiles", []promptkit.ProfileConfig{
{ID: parent, Endpoint: &endpoint, Model: &model},
{ID: "child", Extends: &parent, TimeoutSeconds: &timeout},
})
engine, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{Main: &configkit.Input{Source: source}}})
if err != nil {
t.Fatal(err)
}
profile, err := engine.InspectProfile(context.Background(), "child")
if err != nil || profile.EffectiveModelParams.Model != model || profile.EffectiveModelParams.Endpoint != endpoint || profile.EffectiveModelParams.TimeoutSeconds != timeout {
t.Fatalf("inherited profile = %+v, %v", profile, err)
}
}
func TestProgrammaticSourcesCaptureNestedValuesAndDeferInvalidValues(t *testing.T) {
endpoint := "https://example.invalid/v1"
type namedString string
cyclic := map[string]any{}
cyclic["self"] = cyclic
for _, kind := range []string{"backend", "profile"} {
makeSource := func(params map[string]any) configkit.Source {
if kind == "backend" {
return promptkit.BackendSource("backend", []promptkit.BackendConfig{{ID: "local", Endpoint: &endpoint, ExtraParams: params}})
}
return promptkit.ProfileSource("profile", []promptkit.ProfileConfig{{ID: "local", ExtraParams: params}})
}
load := func(source configkit.Source) (*promptkit.Engine, error) {
return promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{Main: &configkit.Input{Source: source}}}, promptkit.WithBundledOpenRouter(false))
}
t.Run(kind+"/capture", func(t *testing.T) {
values := map[string]any{"nested": map[string]any{"items": []any{"original", int64(42), true, nil}}}
source := makeSource(values)
values["nested"].(map[string]any)["items"].([]any)[0] = "mutated"
engine, err := load(source)
if err != nil {
t.Fatal(err)
}
view, err := engine.InspectConfiguration()
if err != nil {
t.Fatal(err)
}
var output bytes.Buffer
if err := view.WriteEffective(&output); err != nil {
t.Fatal(err)
}
if !strings.Contains(output.String(), "original") || strings.Contains(output.String(), "mutated") {
t.Fatalf("captured configuration = %s", output.String())
}
})
for name, value := range map[string]any{"number": json.Number("1.25"), "typed slice": []string{"value"}, "named scalar": namedString("value"), "pointer": &endpoint, "cycle": cyclic} {
t.Run(kind+"/"+name, func(t *testing.T) {
source := makeSource(map[string]any{"value": value})
_, err := load(source)
var loadErr *configkit.LoadError
if !errors.As(err, &loadErr) || len(loadErr.Diagnostics()) == 0 {
t.Fatalf("source error = %v", err)
}
})
}
}
}