86 lines
2.1 KiB
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)
|
|
}
|
|
}
|
|
}
|