125 lines
3.6 KiB
Go
125 lines
3.6 KiB
Go
package llm
|
|
|
|
import (
|
|
"encoding/json"
|
|
"sort"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestLookupResponseSchemaSucceedsForRegisteredSchemas(t *testing.T) {
|
|
tests := []ResponseSchemaKey{
|
|
TestArtifactSchemaKey,
|
|
TestValidatorDecisionSchemaKey,
|
|
}
|
|
|
|
for _, key := range tests {
|
|
t.Run(string(key), func(t *testing.T) {
|
|
schema, ok := LookupResponseSchema(key)
|
|
if !ok {
|
|
t.Fatalf("expected schema for key %q", key)
|
|
}
|
|
if schema.Key != key {
|
|
t.Fatalf("unexpected key: got %q want %q", schema.Key, key)
|
|
}
|
|
if schema.ID == "" || schema.Version == "" || schema.Name == "" {
|
|
t.Fatalf("expected schema metadata, got %+v", schema)
|
|
}
|
|
if !strings.HasPrefix(schema.SHA256, "sha256:") {
|
|
t.Fatalf("expected prefixed hash, got %q", schema.SHA256)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestLookupResponseSchemaUnknownReturnsFalse(t *testing.T) {
|
|
if schema, ok := LookupResponseSchema("unknown"); ok {
|
|
t.Fatalf("expected unknown schema lookup to fail, got %+v", schema)
|
|
}
|
|
}
|
|
|
|
func TestLookupResponseSchemaDNDSpellsLLMIsNotFrameworkRegistered(t *testing.T) {
|
|
if schema, ok := LookupResponseSchema("dnd_spells_llm"); ok {
|
|
t.Fatalf("expected D&D spells schema lookup to fail in framework registry, got %+v", schema)
|
|
}
|
|
}
|
|
|
|
func TestMustLookupResponseSchemaPanicsForUnknownKey(t *testing.T) {
|
|
defer func() {
|
|
if recover() == nil {
|
|
t.Fatalf("expected panic")
|
|
}
|
|
}()
|
|
|
|
_ = MustLookupResponseSchema("unknown")
|
|
}
|
|
|
|
func TestRegisteredResponseSchemasSortedByKey(t *testing.T) {
|
|
schemas := RegisteredResponseSchemas()
|
|
keys := make([]string, len(schemas))
|
|
seen := make(map[ResponseSchemaKey]bool, len(schemas))
|
|
for i, schema := range schemas {
|
|
keys[i] = string(schema.Key)
|
|
seen[schema.Key] = true
|
|
}
|
|
if !sort.StringsAreSorted(keys) {
|
|
t.Fatalf("expected sorted keys, got %v", keys)
|
|
}
|
|
if !seen[TestArtifactSchemaKey] || !seen[TestValidatorDecisionSchemaKey] {
|
|
t.Fatalf("registered schemas = %v, want test schemas", keys)
|
|
}
|
|
}
|
|
|
|
func TestResponseSchemaContentIsValidJSON(t *testing.T) {
|
|
for _, schema := range RegisteredResponseSchemas() {
|
|
if !json.Valid(schema.JSONSchema) {
|
|
t.Fatalf("schema %q has invalid JSON: %s", schema.Key, schema.JSONSchema)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestResponseSchemaJSONIsMutationSafe(t *testing.T) {
|
|
for _, key := range []ResponseSchemaKey{TestArtifactSchemaKey, TestValidatorDecisionSchemaKey} {
|
|
t.Run(string(key), func(t *testing.T) {
|
|
first := MustLookupResponseSchema(key)
|
|
first.JSONSchema[0] = '['
|
|
|
|
second := MustLookupResponseSchema(key)
|
|
if !json.Valid(second.JSONSchema) {
|
|
t.Fatalf("schema JSON was mutated: %s", second.JSONSchema)
|
|
}
|
|
if len(second.JSONSchema) > 0 && second.JSONSchema[0] == '[' {
|
|
t.Fatalf("schema JSON did not use defensive copy")
|
|
}
|
|
|
|
registered := RegisteredResponseSchemas()
|
|
for i := range registered {
|
|
if registered[i].Key == key {
|
|
registered[i].JSONSchema[0] = '['
|
|
}
|
|
}
|
|
again := MustLookupResponseSchema(key)
|
|
if !json.Valid(again.JSONSchema) || again.JSONSchema[0] == '[' {
|
|
t.Fatalf("registered schema JSON did not use defensive copy")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestResponseSchemaDiagnosticsMapOmitsRawSchemaContent(t *testing.T) {
|
|
schema := MustLookupResponseSchema(TestValidatorDecisionSchemaKey)
|
|
diagnostics := schema.DiagnosticsMap()
|
|
|
|
for _, key := range []string{"id", "version", "name", "sha256"} {
|
|
if diagnostics[key] == "" {
|
|
t.Fatalf("expected diagnostics key %q, got %#v", key, diagnostics)
|
|
}
|
|
}
|
|
if _, ok := diagnostics["json_schema"]; ok {
|
|
t.Fatalf("diagnostics should omit raw schema content: %#v", diagnostics)
|
|
}
|
|
if _, ok := diagnostics["JSONSchema"]; ok {
|
|
t.Fatalf("diagnostics should omit raw schema content: %#v", diagnostics)
|
|
}
|
|
}
|