k8s.io/kube-openapi@v0.0.0-20240228011516-70dd3763d340/pkg/validation/spec/schema_test.go (about) 1 // Copyright 2015 go-swagger maintainers 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package spec 16 17 import ( 18 "encoding/json" 19 "testing" 20 21 "github.com/stretchr/testify/assert" 22 "github.com/stretchr/testify/require" 23 jsontesting "k8s.io/kube-openapi/pkg/util/jsontesting" 24 ) 25 26 var schema = Schema{ 27 VendorExtensible: VendorExtensible{Extensions: map[string]interface{}{"x-framework": "go-swagger"}}, 28 SchemaProps: SchemaProps{ 29 Ref: MustCreateRef("Cat"), 30 Schema: "schemaURL", 31 Type: []string{"string"}, 32 Format: "date", 33 Description: "the description of this schema", 34 Title: "the title", 35 Default: "blah", 36 Maximum: float64Ptr(100), 37 ExclusiveMaximum: true, 38 ExclusiveMinimum: true, 39 Minimum: float64Ptr(5), 40 MaxLength: int64Ptr(100), 41 MinLength: int64Ptr(5), 42 Pattern: "\\w{1,5}\\w+", 43 MaxItems: int64Ptr(100), 44 MinItems: int64Ptr(5), 45 UniqueItems: true, 46 MultipleOf: float64Ptr(5), 47 Enum: []interface{}{"hello", "world"}, 48 MaxProperties: int64Ptr(5), 49 MinProperties: int64Ptr(1), 50 Required: []string{"id", "name"}, 51 Items: &SchemaOrArray{Schema: &Schema{SchemaProps: SchemaProps{Type: []string{"string"}}}}, 52 AllOf: []Schema{{SchemaProps: SchemaProps{Type: []string{"string"}}}}, 53 Properties: map[string]Schema{ 54 "id": {SchemaProps: SchemaProps{Type: []string{"integer"}, Format: "int64"}}, 55 "name": {SchemaProps: SchemaProps{Type: []string{"string"}}}, 56 }, 57 AdditionalProperties: &SchemaOrBool{Allows: true, Schema: &Schema{SchemaProps: SchemaProps{ 58 Type: []string{"integer"}, 59 Format: "int32", 60 }}}, 61 }, 62 SwaggerSchemaProps: SwaggerSchemaProps{ 63 Discriminator: "not this", 64 ReadOnly: true, 65 ExternalDocs: &ExternalDocumentation{ 66 Description: "the documentation etc", 67 URL: "http://readthedocs.org/swagger", 68 }, 69 Example: []interface{}{ 70 map[string]interface{}{ 71 "id": 1, 72 "name": "a book", 73 }, 74 map[string]interface{}{ 75 "id": 2, 76 "name": "the thing", 77 }, 78 }, 79 }, 80 } 81 82 var schemaJSON = `{ 83 "x-framework": "go-swagger", 84 "$ref": "Cat", 85 "$schema": "schemaURL", 86 "description": "the description of this schema", 87 "maximum": 100, 88 "minimum": 5, 89 "exclusiveMaximum": true, 90 "exclusiveMinimum": true, 91 "maxLength": 100, 92 "minLength": 5, 93 "pattern": "\\w{1,5}\\w+", 94 "maxItems": 100, 95 "minItems": 5, 96 "uniqueItems": true, 97 "multipleOf": 5, 98 "enum": ["hello", "world"], 99 "type": "string", 100 "format": "date", 101 "title": "the title", 102 "default": "blah", 103 "maxProperties": 5, 104 "minProperties": 1, 105 "required": ["id", "name"], 106 "items": { 107 "type": "string" 108 }, 109 "allOf": [ 110 { 111 "type": "string" 112 } 113 ], 114 "properties": { 115 "id": { 116 "type": "integer", 117 "format": "int64" 118 }, 119 "name": { 120 "type": "string" 121 } 122 }, 123 "discriminator": "not this", 124 "readOnly": true, 125 "externalDocs": { 126 "description": "the documentation etc", 127 "url": "http://readthedocs.org/swagger" 128 }, 129 "example": [ 130 { 131 "id": 1, 132 "name": "a book" 133 }, 134 { 135 "id": 2, 136 "name": "the thing" 137 } 138 ], 139 "additionalProperties": { 140 "type": "integer", 141 "format": "int32" 142 } 143 } 144 ` 145 146 func TestSchema(t *testing.T) { 147 148 expected := map[string]interface{}{} 149 _ = json.Unmarshal([]byte(schemaJSON), &expected) 150 b, err := json.Marshal(schema) 151 if assert.NoError(t, err) { 152 var actual map[string]interface{} 153 _ = json.Unmarshal(b, &actual) 154 assert.Equal(t, expected, actual) 155 } 156 157 actual2 := Schema{} 158 if assert.NoError(t, json.Unmarshal([]byte(schemaJSON), &actual2)) { 159 assert.Equal(t, schema.Ref, actual2.Ref) 160 assert.Equal(t, schema.Schema, actual2.Schema) 161 assert.Equal(t, schema.Description, actual2.Description) 162 assert.Equal(t, schema.Maximum, actual2.Maximum) 163 assert.Equal(t, schema.Minimum, actual2.Minimum) 164 assert.Equal(t, schema.ExclusiveMinimum, actual2.ExclusiveMinimum) 165 assert.Equal(t, schema.ExclusiveMaximum, actual2.ExclusiveMaximum) 166 assert.Equal(t, schema.MaxLength, actual2.MaxLength) 167 assert.Equal(t, schema.MinLength, actual2.MinLength) 168 assert.Equal(t, schema.Pattern, actual2.Pattern) 169 assert.Equal(t, schema.MaxItems, actual2.MaxItems) 170 assert.Equal(t, schema.MinItems, actual2.MinItems) 171 assert.True(t, actual2.UniqueItems) 172 assert.Equal(t, schema.MultipleOf, actual2.MultipleOf) 173 assert.Equal(t, schema.Enum, actual2.Enum) 174 assert.Equal(t, schema.Type, actual2.Type) 175 assert.Equal(t, schema.Format, actual2.Format) 176 assert.Equal(t, schema.Title, actual2.Title) 177 assert.Equal(t, schema.MaxProperties, actual2.MaxProperties) 178 assert.Equal(t, schema.MinProperties, actual2.MinProperties) 179 assert.Equal(t, schema.Required, actual2.Required) 180 assert.Equal(t, schema.Items, actual2.Items) 181 assert.Equal(t, schema.AllOf, actual2.AllOf) 182 assert.Equal(t, schema.Properties, actual2.Properties) 183 assert.Equal(t, schema.Discriminator, actual2.Discriminator) 184 assert.Equal(t, schema.ReadOnly, actual2.ReadOnly) 185 assert.Equal(t, schema.ExternalDocs, actual2.ExternalDocs) 186 assert.Equal(t, schema.AdditionalProperties, actual2.AdditionalProperties) 187 assert.Equal(t, schema.Extensions, actual2.Extensions) 188 examples := actual2.Example.([]interface{}) 189 expEx := schema.Example.([]interface{}) 190 ex1 := examples[0].(map[string]interface{}) 191 ex2 := examples[1].(map[string]interface{}) 192 exp1 := expEx[0].(map[string]interface{}) 193 exp2 := expEx[1].(map[string]interface{}) 194 195 assert.EqualValues(t, exp1["id"], ex1["id"]) 196 assert.Equal(t, exp1["name"], ex1["name"]) 197 assert.EqualValues(t, exp2["id"], ex2["id"]) 198 assert.Equal(t, exp2["name"], ex2["name"]) 199 } 200 201 } 202 203 func TestSchemaRoundtrip(t *testing.T) { 204 cases := []jsontesting.RoundTripTestCase{ 205 { 206 // Show at least one field from each embededd struct sitll allows 207 // roundtrips successfully 208 Name: "UnmarshalEmbedded", 209 Object: &Schema{ 210 VendorExtensible{Extensions: Extensions{ 211 "x-framework": "go-swagger", 212 }}, 213 SchemaProps{ 214 Description: "this is a description", 215 }, 216 SwaggerSchemaProps{ 217 Example: "this is an example", 218 }, 219 map[string]interface{}{ 220 "unknown/prop": "test prop", 221 }, 222 }, 223 }, 224 // Can't add this case due to map[string]interface{} unmarshaling 225 // numbers unconditionally into float. But schema uses ints 226 // { 227 // Name: "BasicCase", 228 // JSON: schemaJSON, 229 // Object: &schema, 230 // }, 231 } 232 233 for _, tcase := range cases { 234 t.Run(tcase.Name, func(t *testing.T) { 235 require.NoError(t, tcase.RoundTripTest(&Schema{})) 236 }) 237 } 238 } 239 240 func BenchmarkSchemaUnmarshal(b *testing.B) { 241 for i := 0; i < b.N; i++ { 242 sch := &Schema{} 243 _ = sch.UnmarshalJSON([]byte(schemaJSON)) 244 } 245 }