Validate public JSON-like inputs
This commit is contained in:
133
engine_test.go
133
engine_test.go
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"math"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
@@ -1147,6 +1148,66 @@ func TestInMemoryProfileExtraParamsAreCopiedAcrossPublicBoundary(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithProfilesRejectsInvalidExtraParams(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
extraParams map[string]any
|
||||
}{
|
||||
{name: "function", extraParams: map[string]any{"bad": func() {}}},
|
||||
{name: "channel", extraParams: map[string]any{"bad": make(chan struct{})}},
|
||||
{name: "struct", extraParams: map[string]any{"bad": struct{ Name string }{Name: "bad"}}},
|
||||
{name: "non string map key", extraParams: map[string]any{"bad": map[int]string{1: "one"}}},
|
||||
{name: "nan", extraParams: map[string]any{"bad": math.NaN()}},
|
||||
{name: "positive infinity", extraParams: map[string]any{"bad": math.Inf(1)}},
|
||||
{name: "negative infinity", extraParams: map[string]any{"bad": math.Inf(-1)}},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
_, err := scriptorium.NewEngine(scriptorium.Config{PromptDir: "./examples/prompts"},
|
||||
scriptorium.WithProfiles(scriptorium.Profile{
|
||||
ID: "invalid-extra-params",
|
||||
Endpoint: "http://invalid/v1",
|
||||
Model: "invalid-model",
|
||||
ExtraParams: tc.extraParams,
|
||||
}),
|
||||
)
|
||||
if !errors.Is(err, scriptorium.ErrInvalidConfig) {
|
||||
t.Fatalf("expected ErrInvalidConfig, got %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithProfilesRejectsCyclicExtraParams(t *testing.T) {
|
||||
cyclicMap := map[string]any{}
|
||||
cyclicMap["self"] = cyclicMap
|
||||
cyclicSlice := []any{nil}
|
||||
cyclicSlice[0] = cyclicSlice
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
extraParams map[string]any
|
||||
}{
|
||||
{name: "map", extraParams: cyclicMap},
|
||||
{name: "slice", extraParams: map[string]any{"cycle": cyclicSlice}},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
_, err := scriptorium.NewEngine(scriptorium.Config{PromptDir: "./examples/prompts"},
|
||||
scriptorium.WithProfiles(scriptorium.Profile{
|
||||
ID: "cyclic-extra-params",
|
||||
Endpoint: "http://cyclic/v1",
|
||||
Model: "cyclic-model",
|
||||
ExtraParams: tc.extraParams,
|
||||
}),
|
||||
)
|
||||
if !errors.Is(err, scriptorium.ErrInvalidConfig) {
|
||||
t.Fatalf("expected ErrInvalidConfig, got %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunStructuredOutputWorksWithSchemaFS(t *testing.T) {
|
||||
fake := &fakeLLMClient{response: &scriptorium.GenerateResponse{Content: `{"events":[]}`}}
|
||||
engine, err := scriptorium.NewEngine(scriptorium.Config{
|
||||
@@ -1301,6 +1362,78 @@ func TestExtraParamsTypedNestedValuesAreCopiedAcrossPublicBoundary(t *testing.T)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunRejectsInvalidExtraParams(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
extraParams map[string]any
|
||||
}{
|
||||
{name: "function", extraParams: map[string]any{"bad": func() {}}},
|
||||
{name: "channel", extraParams: map[string]any{"bad": make(chan struct{})}},
|
||||
{name: "struct", extraParams: map[string]any{"bad": struct{ Name string }{Name: "bad"}}},
|
||||
{name: "non string map key", extraParams: map[string]any{"bad": map[int]string{1: "one"}}},
|
||||
{name: "nan", extraParams: map[string]any{"bad": math.NaN()}},
|
||||
{name: "positive infinity", extraParams: map[string]any{"bad": math.Inf(1)}},
|
||||
{name: "negative infinity", extraParams: map[string]any{"bad": math.Inf(-1)}},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
fake := &fakeLLMClient{response: &scriptorium.GenerateResponse{Content: "ok"}}
|
||||
engine := newExampleEngineWithOptions(t, "./examples/schemas", scriptorium.WithLLMClient(fake))
|
||||
|
||||
_, err := engine.Run(context.Background(), scriptorium.RunRequest{
|
||||
PromptID: "generic.markdown_summary",
|
||||
Inputs: map[string]scriptorium.ArtifactRef{
|
||||
"transcript": scriptorium.Inline("Rin opens the gate."),
|
||||
"glossary": scriptorium.Inline("gate: A guarded passage."),
|
||||
},
|
||||
Execution: &scriptorium.ExecutionTargetOverride{ExtraParams: tc.extraParams},
|
||||
})
|
||||
if !errors.Is(err, scriptorium.ErrInvalidRequest) {
|
||||
t.Fatalf("expected ErrInvalidRequest, got %v", err)
|
||||
}
|
||||
if len(fake.requests) != 0 {
|
||||
t.Fatalf("expected invalid request to fail before LLM call, got %d requests", len(fake.requests))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunRejectsCyclicExtraParams(t *testing.T) {
|
||||
cyclicMap := map[string]any{}
|
||||
cyclicMap["self"] = cyclicMap
|
||||
cyclicSlice := []any{nil}
|
||||
cyclicSlice[0] = cyclicSlice
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
extraParams map[string]any
|
||||
}{
|
||||
{name: "map", extraParams: cyclicMap},
|
||||
{name: "slice", extraParams: map[string]any{"cycle": cyclicSlice}},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
fake := &fakeLLMClient{response: &scriptorium.GenerateResponse{Content: "ok"}}
|
||||
engine := newExampleEngineWithOptions(t, "./examples/schemas", scriptorium.WithLLMClient(fake))
|
||||
|
||||
_, err := engine.Run(context.Background(), scriptorium.RunRequest{
|
||||
PromptID: "generic.markdown_summary",
|
||||
Inputs: map[string]scriptorium.ArtifactRef{
|
||||
"transcript": scriptorium.Inline("Rin opens the gate."),
|
||||
"glossary": scriptorium.Inline("gate: A guarded passage."),
|
||||
},
|
||||
Execution: &scriptorium.ExecutionTargetOverride{ExtraParams: tc.extraParams},
|
||||
})
|
||||
if !errors.Is(err, scriptorium.ErrInvalidRequest) {
|
||||
t.Fatalf("expected ErrInvalidRequest, got %v", err)
|
||||
}
|
||||
if len(fake.requests) != 0 {
|
||||
t.Fatalf("expected invalid request to fail before LLM call, got %d requests", len(fake.requests))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithLLMClientRejectsNilClient(t *testing.T) {
|
||||
_, err := scriptorium.NewEngine(exampleConfig("./examples/schemas"), scriptorium.WithLLMClient(nil))
|
||||
if !errors.Is(err, scriptorium.ErrInvalidConfig) {
|
||||
|
||||
Reference in New Issue
Block a user