github.com/rajeev159/opa@v0.45.0/ast/schema_test.go (about) 1 package ast 2 3 import ( 4 "errors" 5 "fmt" 6 "io/ioutil" 7 "net/http" 8 "net/http/httptest" 9 "strings" 10 "testing" 11 12 "github.com/open-policy-agent/opa/types" 13 "github.com/open-policy-agent/opa/util" 14 ) 15 16 func testParseSchema(t *testing.T, schema string, expectedType types.Type, expectedError error) { 17 t.Helper() 18 19 var sch interface{} 20 err := util.Unmarshal([]byte(schema), &sch) 21 if err != nil { 22 t.Fatalf("unexpected error: %s", err) 23 } 24 newtype, err := loadSchema(sch, nil) 25 if err != nil && errors.Is(err, expectedError) { 26 t.Fatalf("unexpected error: %v", err) 27 } 28 if newtype == nil && expectedType != nil { 29 t.Fatalf("parseSchema returned nil type") 30 } 31 if newtype != nil && expectedType == nil { 32 t.Fatalf("expected nil but parseSchema returned a not nil type") 33 } 34 if types.Compare(newtype, expectedType) != 0 { 35 t.Fatalf("parseSchema returned an incorrect type: %s, expected: %s", newtype.String(), expectedType.String()) 36 } 37 } 38 39 func TestParseSchemaObject(t *testing.T) { 40 innerObjectStaticProps := []*types.StaticProperty{} 41 innerObjectStaticProps = append(innerObjectStaticProps, &types.StaticProperty{Key: "a", Value: types.N}) 42 innerObjectStaticProps = append(innerObjectStaticProps, &types.StaticProperty{Key: "b", Value: types.NewArray(nil, types.N)}) 43 innerObjectStaticProps = append(innerObjectStaticProps, &types.StaticProperty{Key: "c", Value: types.A}) 44 innerObjectType := types.NewObject(innerObjectStaticProps, nil) 45 46 staticProps := []*types.StaticProperty{} 47 staticProps = append(staticProps, &types.StaticProperty{Key: "b", Value: types.NewArray(nil, innerObjectType)}) 48 staticProps = append(staticProps, &types.StaticProperty{Key: "foo", Value: types.S}) 49 50 expectedType := types.NewObject(staticProps, nil) 51 testParseSchema(t, objectSchema, expectedType, nil) 52 } 53 54 func TestSetTypesWithSchemaRef(t *testing.T) { 55 var sch interface{} 56 57 ts := kubeSchemaServer(t) 58 t.Cleanup(ts.Close) 59 refSchemaReplaced := strings.ReplaceAll(refSchema, "https://kubernetesjsonschema.dev/v1.14.0/", ts.URL+"/") 60 err := util.Unmarshal([]byte(refSchemaReplaced), &sch) 61 if err != nil { 62 t.Fatalf("unexpected error: %s", err) 63 } 64 65 t.Run("remote refs disabled", func(t *testing.T) { 66 _, err := loadSchema(sch, []string{}) 67 if err == nil { 68 t.Fatal("expected error, got nil") 69 } 70 expErr := fmt.Sprintf("unable to compile the schema: remote reference loading disabled: %s/_definitions.json", ts.URL) 71 if exp, act := expErr, err.Error(); act != exp { 72 t.Errorf("expected message %q, got %q", exp, act) 73 } 74 }) 75 76 t.Run("all remote refs enabled", func(t *testing.T) { 77 newtype, err := loadSchema(sch, nil) 78 if err != nil { 79 t.Fatalf("unexpected error: %v", err) 80 } 81 if newtype == nil { 82 t.Fatalf("parseSchema returned nil type") 83 } 84 if newtype.String() != "object<apiVersion: string, kind: string, metadata: object<annotations: object[any: any], clusterName: string, creationTimestamp: string, deletionGracePeriodSeconds: number, deletionTimestamp: string, finalizers: array[string], generateName: string, generation: number, initializers: object<pending: array[object<name: string>], result: object<apiVersion: string, code: number, details: object<causes: array[object<field: string, message: string, reason: string>], group: string, kind: string, name: string, retryAfterSeconds: number, uid: string>, kind: string, message: string, metadata: object<continue: string, resourceVersion: string, selfLink: string>, reason: string, status: string>>, labels: object[any: any], managedFields: array[object<apiVersion: string, fields: object[any: any], manager: string, operation: string, time: string>], name: string, namespace: string, ownerReferences: array[object<apiVersion: string, blockOwnerDeletion: boolean, controller: boolean, kind: string, name: string, uid: string>], resourceVersion: string, selfLink: string, uid: string>>" { 85 t.Fatalf("parseSchema returned an incorrect type: %s", newtype.String()) 86 } 87 }) 88 89 t.Run("desired remote ref selectively enabled", func(t *testing.T) { 90 newtype, err := loadSchema(sch, []string{"127.0.0.1"}) 91 if err != nil { 92 t.Fatalf("unexpected error: %v", err) 93 } 94 if newtype == nil { 95 t.Fatalf("parseSchema returned nil type") 96 } 97 if newtype.String() != "object<apiVersion: string, kind: string, metadata: object<annotations: object[any: any], clusterName: string, creationTimestamp: string, deletionGracePeriodSeconds: number, deletionTimestamp: string, finalizers: array[string], generateName: string, generation: number, initializers: object<pending: array[object<name: string>], result: object<apiVersion: string, code: number, details: object<causes: array[object<field: string, message: string, reason: string>], group: string, kind: string, name: string, retryAfterSeconds: number, uid: string>, kind: string, message: string, metadata: object<continue: string, resourceVersion: string, selfLink: string>, reason: string, status: string>>, labels: object[any: any], managedFields: array[object<apiVersion: string, fields: object[any: any], manager: string, operation: string, time: string>], name: string, namespace: string, ownerReferences: array[object<apiVersion: string, blockOwnerDeletion: boolean, controller: boolean, kind: string, name: string, uid: string>], resourceVersion: string, selfLink: string, uid: string>>" { 98 t.Fatalf("parseSchema returned an incorrect type: %s", newtype.String()) 99 } 100 }) 101 102 t.Run("different remote ref selectively enabled", func(t *testing.T) { 103 _, err := loadSchema(sch, []string{"foo"}) 104 if err == nil { 105 t.Fatal("expected error, got nil") 106 } 107 expErr := fmt.Sprintf("unable to compile the schema: remote reference loading disabled: %s/_definitions.json", ts.URL) 108 if exp, act := expErr, err.Error(); act != exp { 109 t.Errorf("expected message %q, got %q", exp, act) 110 } 111 }) 112 } 113 114 func TestSetTypesWithPodSchema(t *testing.T) { 115 var sch interface{} 116 117 ts := kubeSchemaServer(t) 118 t.Cleanup(ts.Close) 119 120 podSchemaReplaced := strings.ReplaceAll(podSchema, "https://kubernetesjsonschema.dev/v1.14.0/", ts.URL+"/") 121 err := util.Unmarshal([]byte(podSchemaReplaced), &sch) 122 if err != nil { 123 t.Fatalf("unexpected error: %s", err) 124 } 125 newtype, err := loadSchema(sch, nil) 126 if err != nil { 127 t.Fatalf("unexpected error: %s", err) 128 } 129 if newtype == nil { 130 t.Fatalf("parseSchema returned nil type") 131 } 132 if newtype.String() == "object<apiVersion: string, kind: string, metadata: any, spec: any, status: any>" { 133 t.Fatalf("parseSchema returned an incorrect type: %s", newtype.String()) 134 } 135 136 } 137 138 func TestAllOfSchemas(t *testing.T) { 139 //Test 1: object schema 140 objectSchemaStaticProps := []*types.StaticProperty{} 141 objectSchemaStaticProps = append(objectSchemaStaticProps, &types.StaticProperty{Key: "AddressLine1", Value: types.S}) 142 objectSchemaStaticProps = append(objectSchemaStaticProps, &types.StaticProperty{Key: "AddressLine2", Value: types.S}) 143 objectSchemaStaticProps = append(objectSchemaStaticProps, &types.StaticProperty{Key: "City", Value: types.S}) 144 objectSchemaStaticProps = append(objectSchemaStaticProps, &types.StaticProperty{Key: "State", Value: types.S}) 145 objectSchemaStaticProps = append(objectSchemaStaticProps, &types.StaticProperty{Key: "ZipCode", Value: types.S}) 146 objectSchemaStaticProps = append(objectSchemaStaticProps, &types.StaticProperty{Key: "County", Value: types.S}) 147 objectSchemaStaticProps = append(objectSchemaStaticProps, &types.StaticProperty{Key: "PostCode", Value: types.S}) 148 objectSchemaExpectedType := types.NewObject(objectSchemaStaticProps, nil) 149 150 //Test 2: array schema 151 arrayExpectedType := types.NewArray(nil, types.N) 152 153 //Test 3: parent variation 154 parentVariationStaticProps := []*types.StaticProperty{} 155 parentVariationStaticProps = append(parentVariationStaticProps, &types.StaticProperty{Key: "State", Value: types.S}) 156 parentVariationStaticProps = append(parentVariationStaticProps, &types.StaticProperty{Key: "ZipCode", Value: types.S}) 157 parentVariationStaticProps = append(parentVariationStaticProps, &types.StaticProperty{Key: "County", Value: types.S}) 158 parentVariationStaticProps = append(parentVariationStaticProps, &types.StaticProperty{Key: "PostCode", Value: types.S}) 159 parentVariationExpectedType := types.NewObject(parentVariationStaticProps, nil) 160 161 //Test 4: empty schema with allOf 162 emptyExpectedType := types.A 163 164 //Tests 5 & 6: schema with array of arrays, object and array as siblings 165 expectedError := fmt.Errorf("unable to merge these schemas") 166 167 //Test 7: array of objects 168 arrayOfObjectsStaticProps := []*types.StaticProperty{} 169 arrayOfObjectsStaticProps = append(arrayOfObjectsStaticProps, &types.StaticProperty{Key: "State", Value: types.S}) 170 arrayOfObjectsStaticProps = append(arrayOfObjectsStaticProps, &types.StaticProperty{Key: "ZipCode", Value: types.S}) 171 arrayOfObjectsStaticProps = append(arrayOfObjectsStaticProps, &types.StaticProperty{Key: "County", Value: types.S}) 172 arrayOfObjectsStaticProps = append(arrayOfObjectsStaticProps, &types.StaticProperty{Key: "PostCode", Value: types.S}) 173 arrayOfObjectsStaticProps = append(arrayOfObjectsStaticProps, &types.StaticProperty{Key: "Street", Value: types.S}) 174 arrayOfObjectsStaticProps = append(arrayOfObjectsStaticProps, &types.StaticProperty{Key: "House", Value: types.S}) 175 innerType := types.NewObject(arrayOfObjectsStaticProps, nil) 176 arrayOfObjectsExpectedType := types.NewArray(nil, innerType) 177 178 //Tests 8 & 9: allOf schema with type not specified 179 objectMissingStaticProps := []*types.StaticProperty{} 180 objectMissingStaticProps = append(objectMissingStaticProps, &types.StaticProperty{Key: "AddressLine", Value: types.S}) 181 objectMissingStaticProps = append(objectMissingStaticProps, &types.StaticProperty{Key: "State", Value: types.S}) 182 objectMissingStaticProps = append(objectMissingStaticProps, &types.StaticProperty{Key: "ZipCode", Value: types.S}) 183 objectMissingStaticProps = append(objectMissingStaticProps, &types.StaticProperty{Key: "County", Value: types.S}) 184 objectMissingStaticProps = append(objectMissingStaticProps, &types.StaticProperty{Key: "PostCode", Value: types.N}) 185 objectMissingExpectedType := types.NewObject(objectMissingStaticProps, nil) 186 arrayMissingExpectedType := types.NewArray([]types.Type{types.N, types.N}, nil) 187 188 //Tests 10 & 11: allOf schema with array that contains different types (with and without error) 189 arrayDifTypesExpectedType := types.NewArray([]types.Type{types.S, types.N}, nil) 190 191 //Test 12: array inside of object 192 arrayInObjectstaticProps := []*types.StaticProperty{} 193 arrayInObjectstaticProps = append(arrayInObjectstaticProps, &types.StaticProperty{Key: "age", Value: types.N}) 194 arrayInObjectstaticProps = append(arrayInObjectstaticProps, &types.StaticProperty{Key: "name", Value: types.S}) 195 arrayInObjectstaticProps = append(arrayInObjectstaticProps, &types.StaticProperty{Key: "personality", Value: types.S}) 196 arrayInObjectstaticProps = append(arrayInObjectstaticProps, &types.StaticProperty{Key: "nickname", Value: types.S}) 197 innerObjectsType := types.NewObject(arrayInObjectstaticProps, nil) 198 arrayInObjectInnerType := types.NewArray(nil, innerObjectsType) 199 arrayInObjectExpectedType := types.NewObject([]*types.StaticProperty{ 200 types.NewStaticProperty("familyMembers", arrayInObjectInnerType)}, nil) 201 202 //Test 13: allOf inside core schema 203 coreStaticProps := []*types.StaticProperty{} 204 coreStaticProps = append(coreStaticProps, &types.StaticProperty{Key: "accessMe", Value: types.S}) 205 coreStaticProps = append(coreStaticProps, &types.StaticProperty{Key: "accessYou", Value: types.S}) 206 insideType := types.NewObject(coreStaticProps, nil) 207 outerType := []*types.StaticProperty{} 208 outerType = append(outerType, &types.StaticProperty{Key: "RandomInfo", Value: insideType}) 209 outerType = append(outerType, &types.StaticProperty{Key: "AddressLine", Value: types.S}) 210 coreSchemaExpectedType := types.NewObject(outerType, nil) 211 212 //Tests 14-17: other types besides array and object 213 expectedStringType := types.NewString() 214 expectedIntegerType := types.NewNumber() 215 expectedBooleanType := types.NewBoolean() 216 217 //Test 18: array with uneven numbers of items children to merge 218 expectedUnevenArrayType := types.NewArray([]types.Type{types.N, types.N, types.S}, nil) 219 220 tests := []struct { 221 note string 222 schema string 223 expectedType types.Type 224 expectedError error 225 }{ 226 { 227 note: "allOf with mergeable Object types in schema", 228 schema: allOfObjectSchema, 229 expectedType: objectSchemaExpectedType, 230 expectedError: nil, 231 }, 232 { 233 note: "allOf with mergeable Array types in schema", 234 schema: allOfArraySchema, 235 expectedType: arrayExpectedType, 236 expectedError: nil, 237 }, 238 { 239 note: "allOf without a parent schema", 240 schema: allOfSchemaParentVariation, 241 expectedType: parentVariationExpectedType, 242 expectedError: nil, 243 }, 244 { 245 note: "allOf with empty schema", 246 schema: emptySchema, 247 expectedType: emptyExpectedType, 248 expectedError: nil, 249 }, 250 { 251 note: "allOf schema with unmergeable Array of Arrays", 252 schema: allOfArrayOfArrays, 253 expectedType: nil, 254 expectedError: expectedError, 255 }, 256 { 257 note: "allOf with mergeable Array of Object types in schema", 258 schema: allOfArrayOfObjects, 259 expectedType: arrayOfObjectsExpectedType, 260 expectedError: nil, 261 }, 262 { 263 note: "allOf schema with Array and Object types as siblings", 264 schema: allOfObjectAndArray, 265 expectedType: nil, 266 expectedError: expectedError, 267 }, 268 { 269 note: "allOf with mergeable Object types in schema with type declaration missing", 270 schema: allOfObjectMissing, 271 expectedType: objectMissingExpectedType, 272 expectedError: nil, 273 }, 274 { 275 note: "allOf with mergeable Array types in schema with type declaration missing", 276 schema: allOfArrayMissing, 277 expectedType: arrayMissingExpectedType, 278 expectedError: nil, 279 }, 280 { 281 note: "allOf schema with an Array that contains different mergeable types", 282 schema: allOfArrayDifTypes, 283 expectedType: arrayDifTypesExpectedType, 284 expectedError: nil, 285 }, 286 { 287 note: "allOf schema with Array type that contains different unmergeable types", 288 schema: allOfArrayDifTypesWithError, 289 expectedType: nil, 290 expectedError: expectedError, 291 }, 292 { 293 note: "allOf with mergeable Object containing Array types in schema", 294 schema: allOfArrayInsideObject, 295 expectedType: arrayInObjectExpectedType, 296 expectedError: nil, 297 }, 298 { 299 note: "allOf with mergeable types inside of core schema", 300 schema: allOfInsideCoreSchema, 301 expectedType: coreSchemaExpectedType, 302 expectedError: nil, 303 }, 304 { 305 note: "allOf with mergeable String types in schema", 306 schema: allOfStringSchema, 307 expectedType: expectedStringType, 308 expectedError: nil, 309 }, 310 { 311 note: "allOf with mergeable Integer types in schema", 312 schema: allOfIntegerSchema, 313 expectedType: expectedIntegerType, 314 expectedError: nil, 315 }, 316 { 317 note: "allOf with mergeable Boolean types in schema", 318 schema: allOfBooleanSchema, 319 expectedType: expectedBooleanType, 320 expectedError: nil, 321 }, 322 { 323 note: "allOf schema with different unmergeable types", 324 schema: allOfTypeErrorSchema, 325 expectedType: nil, 326 expectedError: expectedError, 327 }, 328 { 329 note: "allOf schema with unmergeable types String and Boolean", 330 schema: allOfStringSchemaWithError, 331 expectedType: nil, 332 expectedError: expectedError, 333 }, 334 { 335 note: "allOf unmergeable schema with different parent and items types", 336 schema: allOfSchemaWithParentError, 337 expectedType: nil, 338 expectedError: expectedError, 339 }, 340 { 341 note: "allOf schema of Array type with uneven numbers of items to merge", 342 schema: allOfSchemaWithUnevenArray, 343 expectedType: expectedUnevenArrayType, 344 expectedError: nil, 345 }, 346 } 347 348 for _, tc := range tests { 349 t.Run(tc.note, func(t *testing.T) { 350 testParseSchema(t, tc.schema, tc.expectedType, tc.expectedError) 351 }) 352 } 353 } 354 355 func TestParseSchemaUntypedField(t *testing.T) { 356 //Expected type is: object<foo: any> 357 staticProps := []*types.StaticProperty{} 358 staticProps = append(staticProps, &types.StaticProperty{Key: "foo", Value: types.A}) 359 expectedType := types.NewObject(staticProps, nil) 360 testParseSchema(t, untypedFieldObjectSchema, expectedType, nil) 361 } 362 363 func TestParseSchemaNoChildren(t *testing.T) { 364 //Expected type is: object[any: any] 365 expectedType := types.NewObject(nil, &types.DynamicProperty{Key: types.A, Value: types.A}) 366 testParseSchema(t, noChildrenObjectSchema, expectedType, nil) 367 } 368 369 func TestParseSchemaArrayNoItems(t *testing.T) { 370 //Expected type is: object<b: array[any]> 371 staticProps := []*types.StaticProperty{} 372 staticProps = append(staticProps, &types.StaticProperty{Key: "b", Value: types.NewArray(nil, types.A)}) 373 expectedType := types.NewObject(staticProps, nil) 374 testParseSchema(t, arrayNoItemsSchema, expectedType, nil) 375 } 376 377 func TestParseSchemaBooleanField(t *testing.T) { 378 //Expected type is: object<a: boolean> 379 staticProps := []*types.StaticProperty{} 380 staticProps = append(staticProps, &types.StaticProperty{Key: "a", Value: types.B}) 381 expectedType := types.NewObject(staticProps, nil) 382 testParseSchema(t, booleanSchema, expectedType, nil) 383 } 384 385 func TestParseSchemaBasics(t *testing.T) { 386 tests := []struct { 387 note string 388 schema string 389 exp types.Type 390 }{ 391 { 392 note: "number", 393 schema: `{"type": "number"}`, 394 exp: types.N, 395 }, 396 { 397 note: "array of objects", 398 schema: `{ 399 "type": "array", 400 "items": { 401 "type": "object", 402 "properties": { 403 "id": {"type": "string"}, 404 "value": {"type": "number"} 405 } 406 } 407 }`, 408 exp: types.NewArray(nil, types.NewObject([]*types.StaticProperty{ 409 types.NewStaticProperty("id", types.S), 410 types.NewStaticProperty("value", types.N), 411 }, nil)), 412 }, 413 { 414 note: "static array items", 415 schema: `{ 416 "type": "array", 417 "items": [ 418 {"type": "string"}, 419 {"type": "number"} 420 ] 421 }`, 422 exp: types.NewArray([]types.Type{ 423 types.S, 424 types.N, 425 }, nil), 426 }, 427 } 428 429 for _, tc := range tests { 430 t.Run(tc.note, func(t *testing.T) { 431 testParseSchema(t, tc.schema, tc.exp, nil) 432 }) 433 } 434 } 435 436 func TestCompileSchemaEmptySchema(t *testing.T) { 437 schema := "" 438 var sch interface{} 439 err := util.Unmarshal([]byte(schema), &sch) 440 if err != nil { 441 t.Fatalf("unexpected error: %s", err) 442 } 443 jsonSchema, _ := compileSchema(sch, []string{}) 444 if jsonSchema != nil { 445 t.Fatalf("Incorrect return from parseSchema with an empty schema") 446 } 447 } 448 449 func TestParseSchemaWithSchemaBadSchema(t *testing.T) { 450 var sch interface{} 451 err := util.Unmarshal([]byte(objectSchema), &sch) 452 if err != nil { 453 t.Fatalf("unexpected error: %s", err) 454 } 455 jsonSchema, err := compileSchema(sch, []string{}) 456 if err != nil { 457 t.Fatalf("Unable to compile schema: %v", err) 458 } 459 newtype, err := parseSchema(jsonSchema) // Did not pass the subschema 460 if err == nil { 461 t.Fatalf("Expected parseSchema() = error, got nil") 462 } 463 if newtype != nil { 464 t.Fatalf("Incorrect return from parseSchema with a bad schema") 465 } 466 } 467 468 func TestAnyOfSchema(t *testing.T) { 469 470 // Test 1 & 3: anyOf extends the core schema 471 extendCoreStaticPropsExp1 := []*types.StaticProperty{types.NewStaticProperty("AddressLine", types.S)} 472 extendCoreStaticPropsExp2 := []*types.StaticProperty{ 473 types.NewStaticProperty("State", types.S), 474 types.NewStaticProperty("ZipCode", types.S)} 475 extendCoreStaticPropsExp3 := []*types.StaticProperty{ 476 types.NewStaticProperty("County", types.S), 477 types.NewStaticProperty("PostCode", types.N)} 478 extendCoreSchemaTypeExp := types.Or(types.NewObject(extendCoreStaticPropsExp3, nil), 479 types.Or( 480 types.NewObject(extendCoreStaticPropsExp1, nil), 481 types.NewObject(extendCoreStaticPropsExp2, nil))) 482 483 // Test 2: anyOf is inside the core schema 484 insideCoreObjType := types.NewObject([]*types.StaticProperty{ 485 types.NewStaticProperty("accessMe", types.S)}, nil) 486 insideCoreAnyType := types.Or(insideCoreObjType, types.N) 487 insideCoreStaticProps := []*types.StaticProperty{ 488 types.NewStaticProperty("AddressLine", types.S), 489 types.NewStaticProperty("RandomInfo", insideCoreAnyType)} 490 insideCoreTypeExp := types.NewObject(insideCoreStaticProps, nil) 491 492 // Test 4: anyOf in an array 493 arrayObjType1 := types.NewObject([]*types.StaticProperty{ 494 types.NewStaticProperty("age", types.N), 495 types.NewStaticProperty("name", types.S)}, nil) 496 arrayObjType2 := types.NewObject([]*types.StaticProperty{ 497 types.NewStaticProperty("personality", types.S), 498 types.NewStaticProperty("nickname", types.S)}, nil) 499 arrayOrType := types.Or(arrayObjType1, arrayObjType2) 500 arrayArrayType := types.NewArray(nil, arrayOrType) 501 arrayObjtype := types.NewObject([]*types.StaticProperty{ 502 types.NewStaticProperty("familyMembers", arrayArrayType)}, nil) 503 504 // Test 5: anyOf array has items but not specified 505 arrayMissing1 := types.NewArray([]types.Type{ 506 types.N, types.S}, nil) 507 arrayMissing2 := types.NewArray([]types.Type{types.N}, nil) 508 arrayMissingType := types.Or(arrayMissing1, arrayMissing2) 509 510 // Test 6: anyOf Parent variation schema 511 anyOfParentVar1 := types.NewObject([]*types.StaticProperty{ 512 types.NewStaticProperty("State", types.S), 513 types.NewStaticProperty("ZipCode", types.S)}, nil) 514 anyOfParentVar2 := types.NewObject([]*types.StaticProperty{ 515 types.NewStaticProperty("County", types.S), 516 types.NewStaticProperty("PostCode", types.S)}, nil) 517 anyOfParentVarType := types.Or(anyOfParentVar1, anyOfParentVar2) 518 519 tests := []struct { 520 note string 521 schema string 522 expected types.Type 523 }{ 524 { 525 note: "anyOf extend core schema", 526 schema: anyOfExtendCoreSchema, 527 expected: extendCoreSchemaTypeExp, 528 }, 529 { 530 note: "anyOf inside core schema", 531 schema: anyOfInsideCoreSchema, 532 expected: insideCoreTypeExp, 533 }, 534 { 535 note: "anyOf object missing type", 536 schema: anyOfObjectMissing, 537 expected: extendCoreSchemaTypeExp, 538 }, 539 { 540 note: "anyOf of an array", 541 schema: anyOfArraySchema, 542 expected: arrayObjtype, 543 }, 544 { 545 note: "anyOf array missing type", 546 schema: anyOfArrayMissing, 547 expected: arrayMissingType, 548 }, 549 { 550 note: "anyOf as parent", 551 schema: anyOfSchemaParentVariation, 552 expected: anyOfParentVarType, 553 }, 554 } 555 556 for _, tc := range tests { 557 t.Run(tc.note, func(t *testing.T) { 558 testParseSchema(t, tc.schema, tc.expected, nil) 559 }) 560 } 561 } 562 563 func kubeSchemaServer(t *testing.T) *httptest.Server { 564 t.Helper() 565 bs, err := ioutil.ReadFile("testdata/_definitions.json") 566 if err != nil { 567 t.Fatal(err) 568 } 569 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { 570 _, err := w.Write(bs) 571 if err != nil { 572 panic(err) 573 } 574 })) 575 return ts 576 }