k8s.io/kube-openapi@v0.0.0-20240826222958-65a50c78dec5/pkg/schemaconv/smd_test.go (about) 1 /* 2 Copyright 2017 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package schemaconv 18 19 import ( 20 "os" 21 "path/filepath" 22 "testing" 23 24 "github.com/google/go-cmp/cmp" 25 yaml "gopkg.in/yaml.v2" 26 27 "k8s.io/kube-openapi/pkg/util/proto" 28 prototesting "k8s.io/kube-openapi/pkg/util/proto/testing" 29 ) 30 31 func TestToSchema(t *testing.T) { 32 tests := []struct { 33 name string 34 openAPIFilename string 35 expectedSchemaFilename string 36 }{ 37 { 38 name: "kubernetes", 39 openAPIFilename: "swagger.json", 40 expectedSchemaFilename: "new-schema.yaml", 41 }, 42 { 43 name: "atomics", 44 openAPIFilename: "atomic-types.json", 45 expectedSchemaFilename: "atomic-types.yaml", 46 }, 47 { 48 name: "defaults", 49 openAPIFilename: "defaults.json", 50 expectedSchemaFilename: "defaults.yaml", 51 }, 52 { 53 name: "preserve-unknown", 54 openAPIFilename: "preserve-unknown.json", 55 expectedSchemaFilename: "preserve-unknown.yaml", 56 }, 57 } 58 for _, tc := range tests { 59 t.Run(tc.name, func(t *testing.T) { 60 openAPIPath := filepath.Join("testdata", tc.openAPIFilename) 61 expectedNewSchemaPath := filepath.Join("testdata", tc.expectedSchemaFilename) 62 testToSchema(t, openAPIPath, expectedNewSchemaPath) 63 }) 64 } 65 } 66 67 func testToSchema(t *testing.T, openAPIPath, expectedNewSchemaPath string) { 68 fakeSchema := prototesting.Fake{Path: openAPIPath} 69 s, err := fakeSchema.OpenAPISchema() 70 if err != nil { 71 t.Fatalf("failed to get schema for %s: %v", openAPIPath, err) 72 } 73 models, err := proto.NewOpenAPIData(s) 74 if err != nil { 75 t.Fatal(err) 76 } 77 78 ns, err := ToSchema(models) 79 if err != nil { 80 t.Fatal(err) 81 } 82 got, err := yaml.Marshal(ns) 83 if err != nil { 84 t.Fatal(err) 85 } 86 87 expect, err := os.ReadFile(expectedNewSchemaPath) 88 if err != nil { 89 t.Fatalf("Unable to read golden data file %q: %v", expectedNewSchemaPath, err) 90 } 91 92 if string(expect) != string(got) { 93 t.Errorf("Computed schema did not match %q.", expectedNewSchemaPath) 94 t.Logf("To recompute this file, run:\n\tgo run ./cmd/openapi2smd/openapi2smd.go < %q > %q", 95 filepath.Join("pkg", "schemaconv", openAPIPath), 96 filepath.Join("pkg", "schemaconv", expectedNewSchemaPath), 97 ) 98 t.Log("You can then use `git diff` to see the changes.") 99 t.Error(cmp.Diff(string(expect), string(got))) 100 } 101 } 102 103 func TestFieldLevelAnnotation(t *testing.T) { 104 openAPIPath := filepath.Join("testdata", "field-level-annotation.json") 105 fakeSchema := prototesting.Fake{Path: openAPIPath} 106 s, err := fakeSchema.OpenAPISchema() 107 if err != nil { 108 t.Fatalf("failed to get schema for %s: %v", openAPIPath, err) 109 } 110 models, err := proto.NewOpenAPIData(s) 111 if err != nil { 112 t.Fatal(err) 113 } 114 115 ns, err := ToSchema(models) 116 if err != nil { 117 t.Fatal(err) 118 } 119 120 _ = ns 121 122 // Test to make sure that MapElementRelationship is populated correctly 123 // after being converted from proto type 124 endpointAddress, ok := ns.FindNamedType("io.k8s.api.core.v1.EndpointAddress") 125 if !ok { 126 t.Fatalf("expected to find EndpointAddress") 127 } 128 129 targetRef, ok := endpointAddress.FindField("targetRef") 130 if !ok { 131 t.Fatalf("expected to find EndpointAddress field 'targetRef'") 132 } 133 134 if targetRef.Type.ElementRelationship == nil { 135 t.Fatalf("expected targetRef MapElementRelationship to be atomic") 136 } 137 138 // Test to make sure that schema.Resolve overrides the ElementRelationship 139 // when asked to resolve a reference 140 resolved, ok := ns.Resolve(targetRef.Type) 141 if !ok { 142 t.Fatalf("failed to resolve targetRef type") 143 } 144 145 if resolved.Map == nil { 146 t.Fatalf("expected to resolve to a Map") 147 } 148 149 if resolved.Map.ElementRelationship != *targetRef.Type.ElementRelationship { 150 t.Fatalf("resolved element relationship not converted") 151 } 152 153 // Make sure our test is actually testing something by ensuring the original 154 // relationship is different from what we are changing it to. 155 targetRefWithoutRelationship := targetRef 156 targetRefWithoutRelationship.Type.ElementRelationship = nil 157 158 originalResolved, ok := ns.Resolve(targetRefWithoutRelationship.Type) 159 if !ok { 160 t.Fatalf("failed to resolve targetRef type") 161 } 162 163 if originalResolved.Map.ElementRelationship == *targetRef.Type.ElementRelationship { 164 t.Fatalf("expected original element relationship to differ from field-level override for test") 165 } 166 }