istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pkg/kube/kclient/crdwatcher_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 15 package kclient_test 16 17 import ( 18 "testing" 19 20 "go.uber.org/atomic" 21 "sigs.k8s.io/gateway-api/pkg/consts" 22 23 "istio.io/istio/pkg/config/schema/gvr" 24 "istio.io/istio/pkg/kube" 25 "istio.io/istio/pkg/kube/kclient/clienttest" 26 "istio.io/istio/pkg/test" 27 "istio.io/istio/pkg/test/util/assert" 28 ) 29 30 // TestCRDWatcherRace tests for a previous bug where callbacks may be skipped if added during a handler 31 func TestCRDWatcherRace(t *testing.T) { 32 stop := test.NewStop(t) 33 c := kube.NewFakeClient() 34 ctl := c.CrdWatcher() 35 vsCalls := atomic.NewInt32(0) 36 37 // Race callback and CRD creation 38 go func() { 39 if ctl.KnownOrCallback(gvr.VirtualService, func(s <-chan struct{}) { 40 assert.Equal(t, s, stop) 41 // Happened async 42 vsCalls.Inc() 43 }) { 44 // Happened sync 45 vsCalls.Inc() 46 } 47 }() 48 clienttest.MakeCRD(t, c, gvr.VirtualService) 49 c.RunAndWait(stop) 50 assert.EventuallyEqual(t, vsCalls.Load, 1) 51 } 52 53 func TestCRDWatcher(t *testing.T) { 54 stop := test.NewStop(t) 55 c := kube.NewFakeClient() 56 57 clienttest.MakeCRD(t, c, gvr.VirtualService) 58 vsCalls := atomic.NewInt32(0) 59 60 clienttest.MakeCRD(t, c, gvr.GatewayClass) 61 62 ctl := c.CrdWatcher() 63 // Created before informer runs 64 assert.Equal(t, ctl.KnownOrCallback(gvr.VirtualService, func(s <-chan struct{}) { 65 assert.Equal(t, s, stop) 66 vsCalls.Inc() 67 }), false) 68 69 c.RunAndWait(stop) 70 assert.EventuallyEqual(t, vsCalls.Load, 1) 71 72 // created once running 73 assert.Equal(t, ctl.KnownOrCallback(gvr.GatewayClass, func(s <-chan struct{}) { 74 t.Fatalf("callback should not be called") 75 }), true) 76 77 // Create CRD later 78 saCalls := atomic.NewInt32(0) 79 // When should return false 80 assert.Equal(t, ctl.KnownOrCallback(gvr.ServiceAccount, func(s <-chan struct{}) { 81 assert.Equal(t, s, stop) 82 saCalls.Inc() 83 }), false) 84 clienttest.MakeCRD(t, c, gvr.ServiceAccount) 85 // And call the callback when the CRD is created 86 assert.EventuallyEqual(t, saCalls.Load, 1) 87 } 88 89 func TestCRDWatcherMinimumVersion(t *testing.T) { 90 stop := test.NewStop(t) 91 c := kube.NewFakeClient() 92 93 clienttest.MakeCRDWithAnnotations(t, c, gvr.GRPCRoute, map[string]string{ 94 consts.BundleVersionAnnotation: "v1.0.0", 95 }) 96 calls := atomic.NewInt32(0) 97 98 ctl := c.CrdWatcher() 99 // Created before informer runs: not ready yet 100 assert.Equal(t, ctl.KnownOrCallback(gvr.GRPCRoute, func(s <-chan struct{}) { 101 assert.Equal(t, s, stop) 102 calls.Inc() 103 }), false) 104 105 c.RunAndWait(stop) 106 107 // Still not ready 108 assert.Equal(t, calls.Load(), 0) 109 110 // Upgrade it to v1.1, which is allowed 111 clienttest.MakeCRDWithAnnotations(t, c, gvr.GRPCRoute, map[string]string{ 112 consts.BundleVersionAnnotation: "v1.1.0", 113 }) 114 assert.EventuallyEqual(t, calls.Load, 1) 115 }