istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pkg/config/analysis/analyzers/schema/validation_test.go (about) 1 // Copyright Istio Authors 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 package schema 15 16 import ( 17 "fmt" 18 "testing" 19 20 "github.com/hashicorp/go-multierror" 21 . "github.com/onsi/gomega" 22 23 "istio.io/api/networking/v1alpha3" 24 "istio.io/istio/pkg/cluster" 25 "istio.io/istio/pkg/config" 26 "istio.io/istio/pkg/config/analysis/msg" 27 "istio.io/istio/pkg/config/analysis/testing/fixtures" 28 "istio.io/istio/pkg/config/resource" 29 "istio.io/istio/pkg/config/schema/collections" 30 "istio.io/istio/pkg/config/schema/gvk" 31 resource2 "istio.io/istio/pkg/config/schema/resource" 32 "istio.io/istio/pkg/config/validation" 33 ) 34 35 func TestCorrectArgs(t *testing.T) { 36 g := NewWithT(t) 37 38 m1 := &v1alpha3.VirtualService{} 39 40 testSchema := schemaWithValidateFn(func(cfg config.Config) (warnings validation.Warning, errs error) { 41 g.Expect(cfg.Name).To(Equal("name")) 42 g.Expect(cfg.Namespace).To(Equal("ns")) 43 g.Expect(cfg.Spec).To(Equal(m1)) 44 return nil, nil 45 }) 46 ctx := &fixtures.Context{ 47 Resources: []*resource.Instance{ 48 { 49 Message: &v1alpha3.VirtualService{}, 50 Metadata: resource.Metadata{ 51 FullName: resource.NewFullName("ns", "name"), 52 }, 53 Origin: fakeOrigin{}, 54 }, 55 }, 56 } 57 a := ValidationAnalyzer{s: testSchema} 58 a.Analyze(ctx) 59 } 60 61 func TestSchemaValidationWrapper(t *testing.T) { 62 testCol := gvk.VirtualService 63 64 m1 := &v1alpha3.VirtualService{} 65 m2 := &v1alpha3.VirtualService{} 66 m3 := &v1alpha3.VirtualService{} 67 68 testSchema := schemaWithValidateFn(func(cfg config.Config) (warnings validation.Warning, errs error) { 69 if cfg.Spec == m1 { 70 return nil, nil 71 } 72 if cfg.Spec == m2 { 73 return nil, fmt.Errorf("") 74 } 75 if cfg.Spec == m3 { 76 return nil, multierror.Append(fmt.Errorf(""), fmt.Errorf("")) 77 } 78 return nil, nil 79 }) 80 81 a := ValidationAnalyzer{s: testSchema} 82 83 t.Run("CheckMetadataInputs", func(t *testing.T) { 84 g := NewWithT(t) 85 g.Expect(a.Metadata().Inputs).To(ConsistOf(testCol)) 86 }) 87 88 t.Run("NoErrors", func(t *testing.T) { 89 g := NewWithT(t) 90 ctx := &fixtures.Context{ 91 Resources: []*resource.Instance{ 92 { 93 Message: m1, 94 }, 95 }, 96 } 97 a.Analyze(ctx) 98 g.Expect(ctx.Reports).To(BeEmpty()) 99 }) 100 101 t.Run("SingleError", func(t *testing.T) { 102 g := NewWithT(t) 103 104 ctx := &fixtures.Context{ 105 Resources: []*resource.Instance{ 106 { 107 Message: m2, 108 Origin: fakeOrigin{}, 109 }, 110 }, 111 } 112 a.Analyze(ctx) 113 g.Expect(ctx.Reports).To(HaveLen(1)) 114 g.Expect(ctx.Reports[0].Type).To(Equal(msg.SchemaValidationError)) 115 }) 116 117 t.Run("MultiError", func(t *testing.T) { 118 g := NewWithT(t) 119 ctx := &fixtures.Context{ 120 Resources: []*resource.Instance{ 121 { 122 Message: m3, 123 Origin: fakeOrigin{}, 124 }, 125 }, 126 } 127 a.Analyze(ctx) 128 g.Expect(ctx.Reports).To(HaveLen(2)) 129 g.Expect(ctx.Reports[0].Type).To(Equal(msg.SchemaValidationError)) 130 g.Expect(ctx.Reports[1].Type).To(Equal(msg.SchemaValidationError)) 131 }) 132 } 133 134 func BenchmarkMetadata(b *testing.B) { 135 a := ValidationAnalyzer{ 136 s: schemaWithValidateFn(validation.EmptyValidate), 137 } 138 139 b.ResetTimer() 140 for i := 0; i < b.N; i++ { 141 a.Metadata() 142 } 143 } 144 145 func schemaWithValidateFn(validateFn func(cfg config.Config) (validation.Warning, error)) resource2.Schema { 146 original := collections.VirtualService 147 return resource2.Builder{ 148 ClusterScoped: original.IsClusterScoped(), 149 Kind: original.Kind(), 150 Plural: original.Plural(), 151 Group: original.Group(), 152 Version: original.Version(), 153 Proto: original.Proto(), 154 ProtoPackage: original.ProtoPackage(), 155 ValidateProto: validateFn, 156 }.MustBuild() 157 } 158 159 type fakeOrigin struct{} 160 161 func (fakeOrigin) FriendlyName() string { return "myFriendlyName" } 162 func (fakeOrigin) Comparator() string { return "myFriendlyName" } 163 func (fakeOrigin) Namespace() resource.Namespace { return "myNamespace" } 164 func (fakeOrigin) Reference() resource.Reference { return fakeReference{} } 165 func (fakeOrigin) FieldMap() map[string]int { return make(map[string]int) } 166 func (fakeOrigin) ClusterName() cluster.ID { 167 return "cluster" 168 } 169 170 type fakeReference struct{} 171 172 func (fakeReference) String() string { return "" }