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 "" }