返回 DeepSeek-Reasonix
schema_validate_test.go
根目录 / internal / provider / schema_validate_test.go
1 package provider
2
3 import (
4 "encoding/json"
5 "os"
6 "path/filepath"
7 "strings"
8 "testing"
9 )
10
11 func TestValidateToolSchemaAcceptsValidDrafts(t *testing.T) {
12 for _, raw := range []json.RawMessage{
13 json.RawMessage(`{"type":"object","properties":{"query":{"type":"string"}}}`),
14 json.RawMessage(`{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"values":{"type":"array","prefixItems":[{"type":"string"}]}}}`),
15 } {
16 if err := ValidateToolSchema(raw); err != nil {
17 t.Fatalf("ValidateToolSchema(%s): %v", raw, err)
18 }
19 }
20 }
21
22 func TestValidateToolSchemaRejectsMalformedNestedArrayItems(t *testing.T) {
23 raw := json.RawMessage(`{
24 "type":"object",
25 "properties":{
26 "options":{
27 "type":"array",
28 "items":{
29 "key":{"description":"option key","type":"string"},
30 "type":{"description":"option type","type":"string"},
31 "value":{"description":"option value","type":"string"}
32 }
33 }
34 }
35 }`)
36 err := ValidateToolSchema(raw)
37 if err == nil {
38 t.Fatal("malformed Yakit-style array item schema was accepted")
39 }
40 if msg := err.Error(); !strings.Contains(msg, "/properties/options/items/type") {
41 t.Fatalf("error does not identify the malformed nested type: %v", err)
42 }
43 }
44
45 func TestValidateToolSchemaRejectsNonObjectRootType(t *testing.T) {
46 for name, raw := range map[string]json.RawMessage{
47 "missing type": json.RawMessage(`{}`),
48 "string root": json.RawMessage(`{"type":"string"}`),
49 "nullable root": json.RawMessage(`{"type":["object","null"]}`),
50 } {
51 t.Run(name, func(t *testing.T) {
52 err := ValidateToolSchema(raw)
53 if err == nil {
54 t.Fatalf("ValidateToolSchema(%s) returned nil", raw)
55 }
56 if !strings.Contains(err.Error(), `"object"`) {
57 t.Fatalf("error does not name the object requirement: %v", err)
58 }
59 })
60 }
61 }
62
63 func TestValidateToolSchemaRejectsFileRefsEvenWhenResolvable(t *testing.T) {
64 // A resolvable local file proves rejection comes from the disabled loader,
65 // not from the file happening to be missing or malformed.
66 path := filepath.Join(t.TempDir(), "args.json")
67 if err := os.WriteFile(path, []byte(`{"type":"string"}`), 0o600); err != nil {
68 t.Fatalf("WriteFile: %v", err)
69 }
70 fileURL := "file:///" + strings.TrimPrefix(filepath.ToSlash(path), "/")
71 raw := json.RawMessage(`{"type":"object","properties":{"x":{"$ref":"` + fileURL + `"}}}`)
72 if err := ValidateToolSchema(raw); err == nil {
73 t.Fatalf("ValidateToolSchema resolved local file ref %s", fileURL)
74 }
75 }
76
77 func TestValidateToolSchemaRejectsNonObjectRootAndExternalRefs(t *testing.T) {
78 for name, raw := range map[string]json.RawMessage{
79 "array root": json.RawMessage(`[]`),
80 "external ref": json.RawMessage(`{"type":"object","properties":{"x":{"$ref":"https://example.com/schema.json"}}}`),
81 } {
82 t.Run(name, func(t *testing.T) {
83 if err := ValidateToolSchema(raw); err == nil {
84 t.Fatalf("ValidateToolSchema(%s) returned nil", raw)
85 }
86 })
87 }
88 }
89
89 lines GO