84 lines
3.0 KiB
Go
84 lines
3.0 KiB
Go
package promptkit_test
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"sync/atomic"
|
|
"testing"
|
|
|
|
"gitea.maximumdirect.net/eric/promptkit"
|
|
)
|
|
|
|
func TestValidateRequestMatchesPrepareContract(t *testing.T) {
|
|
var modelCalls atomic.Int64
|
|
profiles := map[string]any{
|
|
"offline": map[string]any{"endpoint": "http://example.test/v1", "model": "offline-model"},
|
|
}
|
|
newEngine := func(t *testing.T, definition map[string]any) *promptkit.Engine {
|
|
t.Helper()
|
|
return requirementsEngine(t, oneVersionPrompt("synthetic", "v1", definition), profiles,
|
|
promptkit.WithLLMClient(countingLLMClient{calls: &modelCalls}))
|
|
}
|
|
testParity := func(t *testing.T, engine *promptkit.Engine, request promptkit.RunRequest, want error) {
|
|
t.Helper()
|
|
prepared, prepareErr := engine.Prepare(context.Background(), request)
|
|
validateErr := engine.ValidateRequest(context.Background(), request)
|
|
if want == nil {
|
|
if prepareErr != nil || prepared == nil {
|
|
t.Fatalf("Prepare() = (%+v, %v), want a prepared result", prepared, prepareErr)
|
|
}
|
|
if validateErr != nil {
|
|
t.Fatalf("ValidateRequest() error = %v, want nil", validateErr)
|
|
}
|
|
return
|
|
}
|
|
if prepared != nil || !errors.Is(prepareErr, want) {
|
|
t.Fatalf("Prepare() = (%+v, %v), want error matching %v", prepared, prepareErr, want)
|
|
}
|
|
if !errors.Is(validateErr, want) {
|
|
t.Fatalf("ValidateRequest() error = %v, want error matching %v", validateErr, want)
|
|
}
|
|
}
|
|
|
|
t.Run("successful request", func(t *testing.T) {
|
|
engine := newEngine(t, contractPrompt("offline", "hello", nil, "", noValidationOutput))
|
|
testParity(t, engine, promptkit.RunRequest{PromptID: "synthetic"}, nil)
|
|
})
|
|
|
|
t.Run("nil engine", func(t *testing.T) {
|
|
var engine *promptkit.Engine
|
|
request := promptkit.RunRequest{PromptID: "synthetic"}
|
|
prepared, prepareErr := engine.Prepare(context.Background(), request)
|
|
validateErr := engine.ValidateRequest(context.Background(), request)
|
|
if prepared != nil || !errors.Is(prepareErr, promptkit.ErrInvalidConfig) {
|
|
t.Fatalf("Prepare() = (%+v, %v), want ErrInvalidConfig", prepared, prepareErr)
|
|
}
|
|
if !errors.Is(validateErr, promptkit.ErrInvalidConfig) {
|
|
t.Fatalf("ValidateRequest() error = %v, want ErrInvalidConfig", validateErr)
|
|
}
|
|
})
|
|
|
|
t.Run("invalid appended message", func(t *testing.T) {
|
|
engine := newEngine(t, contractPrompt("offline", "hello", nil, "", noValidationOutput))
|
|
request := promptkit.RunRequest{
|
|
PromptID: "synthetic",
|
|
AppendedMessages: []promptkit.RenderedMessage{{
|
|
Role: "unsupported-role", Content: "not sent to a model",
|
|
}},
|
|
}
|
|
testParity(t, engine, request, promptkit.ErrInvalidRequest)
|
|
})
|
|
|
|
t.Run("missing required input", func(t *testing.T) {
|
|
definition := contractPrompt("offline", `{{input "required"}}`, []any{
|
|
map[string]any{"name": "required", "required": true},
|
|
}, "", noValidationOutput)
|
|
engine := newEngine(t, definition)
|
|
testParity(t, engine, promptkit.RunRequest{PromptID: "synthetic"}, promptkit.ErrPromptRender)
|
|
})
|
|
|
|
if got := modelCalls.Load(); got != 0 {
|
|
t.Fatalf("preparation operations made %d model calls, want none", got)
|
|
}
|
|
}
|