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) } }