jsonschema: validate some keywords
This CL implements validation for the "type", "enum" and "const" keywords. Validation in its full generality requires that references in the schema be resolved. We put that off for now; it isn't needed for most simple keywords. The JSON Schema folks provide an extensive test suite for validation at https://github.com/json-schema-org/JSON-Schema-Test-Suite. We use it for our tests, copying the necessary files into testdata. The files aren't perfectly independent; for example, one test in enum.json requires the "properties" keyword, which we haven't done yet. We will excise those tests via calls to t.Skip as they arise. Change-Id: I568b5c87802a39aecbc58f342931308fc8fb211c Reviewed-on: https://go-review.googlesource.com/c/tools/+/667875 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Alan Donovan <adonovan@google.com>
This commit is contained in:
parent
3434e57007
commit
c99ff4897b
1 changed files with 1523 additions and 1 deletions
77
internal/jsonschema/validate_test.go
Normal file
77
internal/jsonschema/validate_test.go
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
// Copyright 2025 The Go MCP SDK Authors. All rights reserved.
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package jsonschema
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// The test for validation uses the official test suite, expressed as a set of JSON files.
|
||||
// Each file is an array of group objects.
|
||||
|
||||
// A testGroup consists of a schema and some tests on it.
|
||||
type testGroup struct {
|
||||
Description string
|
||||
Schema *Schema
|
||||
Tests []test
|
||||
}
|
||||
|
||||
// A test consists of a JSON instance to be validated and the expected result.
|
||||
type test struct {
|
||||
Description string
|
||||
Data any
|
||||
Valid bool
|
||||
}
|
||||
|
||||
func TestValidate(t *testing.T) {
|
||||
files, err := filepath.Glob(filepath.FromSlash("testdata/draft2020-12/*.json"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(files) == 0 {
|
||||
t.Fatal("no files")
|
||||
}
|
||||
for _, file := range files {
|
||||
base := filepath.Base(file)
|
||||
t.Run(base, func(t *testing.T) {
|
||||
f, err := os.Open(file)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer f.Close()
|
||||
dec := json.NewDecoder(f)
|
||||
var groups []testGroup
|
||||
if err := dec.Decode(&groups); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, g := range groups {
|
||||
if g.Schema.Properties != nil {
|
||||
t.Skip("schema has properties")
|
||||
}
|
||||
rs := &ResolvedSchema{root: g.Schema}
|
||||
t.Run(g.Description, func(t *testing.T) {
|
||||
for _, test := range g.Tests {
|
||||
t.Run(test.Description, func(t *testing.T) {
|
||||
err = rs.Validate(test.Data)
|
||||
if err != nil && test.Valid {
|
||||
t.Errorf("wanted success, but failed with: %v", err)
|
||||
}
|
||||
if err == nil && !test.Valid {
|
||||
t.Error("succeeded but wanted failure")
|
||||
}
|
||||
if t.Failed() {
|
||||
t.Errorf("schema: %s", g.Schema.json())
|
||||
t.Fatalf("instance: %v", test.Data)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue