Files
notarius/internal/modules/dnd/register/schema_compatibility_test.go

86 lines
2.1 KiB
Go

package register
import (
"encoding/json"
"io/fs"
"sort"
"strconv"
"strings"
"testing"
"gitea.maximumdirect.net/eric/notarius/internal/framework/llm"
)
func TestRegisteredResponseSchemasRequireEveryObjectProperty(t *testing.T) {
assets := llm.NewAssetRegistry()
if err := Register(completeRegistries(), assets); err != nil {
t.Fatal(err)
}
schemaFS, err := assets.SchemaFS()
if err != nil {
t.Fatal(err)
}
count := 0
err = fs.WalkDir(schemaFS, ".", func(path string, entry fs.DirEntry, walkErr error) error {
if walkErr != nil {
return walkErr
}
if entry.IsDir() || !strings.HasSuffix(path, ".json") {
return nil
}
content, err := fs.ReadFile(schemaFS, path)
if err != nil {
return err
}
var schema any
if err := json.Unmarshal(content, &schema); err != nil {
t.Errorf("decode response schema %q: %v", path, err)
return nil
}
count++
assertRequiredObjectProperties(t, path, "$", schema)
return nil
})
if err != nil {
t.Fatal(err)
}
if count == 0 {
t.Fatal("no registered response schemas found")
}
}
func assertRequiredObjectProperties(t *testing.T, schemaPath, nodePath string, value any) {
t.Helper()
switch node := value.(type) {
case map[string]any:
if properties, ok := node["properties"].(map[string]any); ok {
required := make(map[string]struct{})
if values, ok := node["required"].([]any); ok {
for _, value := range values {
if name, ok := value.(string); ok {
required[name] = struct{}{}
}
}
}
propertyNames := make([]string, 0, len(properties))
for name := range properties {
propertyNames = append(propertyNames, name)
}
sort.Strings(propertyNames)
for _, name := range propertyNames {
if _, ok := required[name]; !ok {
t.Errorf("response schema %q object %s declares property %q without requiring it", schemaPath, nodePath, name)
}
}
}
for name, child := range node {
assertRequiredObjectProperties(t, schemaPath, nodePath+"."+name, child)
}
case []any:
for index, child := range node {
assertRequiredObjectProperties(t, schemaPath, nodePath+"["+strconv.Itoa(index)+"]", child)
}
}
}