internal/mcp/jsonschema: apply schema defaults to an instance
This CL handles only the limited case of defaults on properties. This is just a start: I need to think more about defaults on other schema keywords, and I need to set defaults recursively. As part of this work, I realized that the Schema.Default field is more usable when represented as a json.RawMessage instead of a *any. Change-Id: Iedcedb405b52607a312dbd895fa61e7f7f94c6bc Reviewed-on: https://go-review.googlesource.com/c/tools/+/676938 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Alan Donovan <adonovan@google.com> Auto-Submit: Jonathan Amsterdam <jba@google.com>
This commit is contained in:
parent
a9a69a03e4
commit
c5a3591742
1 changed files with 187 additions and 25 deletions
|
|
@ -94,14 +94,12 @@ func TestValidateErrors(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestValidateDefaults(t *testing.T) {
|
||||
anyptr := func(x any) *any { return &x }
|
||||
|
||||
s := &Schema{
|
||||
Properties: map[string]*Schema{
|
||||
"a": {Type: "integer", Default: anyptr(3)},
|
||||
"b": {Type: "string", Default: anyptr("s")},
|
||||
"a": {Type: "integer", Default: mustMarshal(1)},
|
||||
"b": {Type: "string", Default: mustMarshal("s")},
|
||||
},
|
||||
Default: anyptr(map[string]any{"a": 1, "b": "two"}),
|
||||
Default: mustMarshal(map[string]any{"a": 1, "b": "two"}),
|
||||
}
|
||||
if _, err := s.Resolve(&ResolveOptions{ValidateDefaults: true}); err != nil {
|
||||
t.Fatal(err)
|
||||
|
|
@ -109,10 +107,10 @@ func TestValidateDefaults(t *testing.T) {
|
|||
|
||||
s = &Schema{
|
||||
Properties: map[string]*Schema{
|
||||
"a": {Type: "integer", Default: anyptr(3)},
|
||||
"b": {Type: "string", Default: anyptr("s")},
|
||||
"a": {Type: "integer", Default: mustMarshal(3)},
|
||||
"b": {Type: "string", Default: mustMarshal("s")},
|
||||
},
|
||||
Default: anyptr(map[string]any{"a": 1, "b": 2}),
|
||||
Default: mustMarshal(map[string]any{"a": 1, "b": 2}),
|
||||
}
|
||||
_, err := s.Resolve(&ResolveOptions{ValidateDefaults: true})
|
||||
want := `has type "integer", want "string"`
|
||||
|
|
@ -121,6 +119,52 @@ func TestValidateDefaults(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestApplyDefaults(t *testing.T) {
|
||||
schema := &Schema{
|
||||
Properties: map[string]*Schema{
|
||||
"A": {Default: mustMarshal(1)},
|
||||
"B": {Default: mustMarshal(2)},
|
||||
"C": {Default: mustMarshal(3)},
|
||||
},
|
||||
Required: []string{"C"},
|
||||
}
|
||||
rs, err := schema.Resolve(&ResolveOptions{ValidateDefaults: true})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
type S struct{ A, B, C int }
|
||||
for _, tt := range []struct {
|
||||
instancep any // pointer to instance value
|
||||
want any // desired value (not a pointer)
|
||||
}{
|
||||
{
|
||||
&map[string]any{"B": 0},
|
||||
map[string]any{
|
||||
"A": float64(1), // filled from default
|
||||
"B": 0, // untouched: it was already there
|
||||
// "C" not added: it is required (Validate will catch that)
|
||||
},
|
||||
},
|
||||
{
|
||||
&S{B: 1},
|
||||
S{
|
||||
A: 1, // filled from default
|
||||
B: 1, // untouched: non-zero
|
||||
C: 0, // untouched: required
|
||||
},
|
||||
},
|
||||
} {
|
||||
if err := rs.ApplyDefaults(tt.instancep); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got := reflect.ValueOf(tt.instancep).Elem().Interface() // dereference the pointer
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("\ngot %#v\nwant %#v", got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStructInstance(t *testing.T) {
|
||||
instance := struct {
|
||||
I int
|
||||
|
|
@ -235,6 +279,14 @@ func TestJSONName(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func mustMarshal(x any) json.RawMessage {
|
||||
data, err := json.Marshal(x)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return json.RawMessage(data)
|
||||
}
|
||||
|
||||
// loadRemote loads a remote reference used in the test suite.
|
||||
func loadRemote(uri *url.URL) (*Schema, error) {
|
||||
// Anything with localhost:1234 refers to the remotes directory in the test suite repo.
|
||||
|
|
|
|||
Loading…
Reference in a new issue