@@ -34,6 +34,7 @@ import (
34
34
"k8s.io/apimachinery/pkg/labels"
35
35
"k8s.io/apimachinery/pkg/runtime"
36
36
"k8s.io/apimachinery/pkg/runtime/serializer"
37
+ "k8s.io/apimachinery/pkg/util/clock"
37
38
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
38
39
"k8s.io/apimachinery/pkg/util/sets"
39
40
"k8s.io/apimachinery/pkg/util/wait"
56
57
codecs = serializer .NewCodecFactory (scheme )
57
58
)
58
59
60
+ const (
61
+ // watchCacheDefaultCapacity syncs watch cache defaultLowerBoundCapacity.
62
+ watchCacheDefaultCapacity = 100
63
+ )
64
+
59
65
func init () {
60
66
metav1 .AddToGroupVersion (scheme , metav1 .SchemeGroupVersion )
61
67
utilruntime .Must (example .AddToScheme (scheme ))
@@ -100,6 +106,10 @@ func newEtcdTestStorage(t *testing.T, prefix string) (*etcd3testing.EtcdTestServ
100
106
}
101
107
102
108
func newTestCacher (s storage.Interface , cap int ) (* cacherstorage.Cacher , storage.Versioner , error ) {
109
+ return newTestCacherWithClock (s , cap , clock.RealClock {})
110
+ }
111
+
112
+ func newTestCacherWithClock (s storage.Interface , cap int , clock clock.Clock ) (* cacherstorage.Cacher , storage.Versioner , error ) {
103
113
prefix := "pods"
104
114
v := etcd3.APIObjectVersioner {}
105
115
config := cacherstorage.Config {
@@ -112,6 +122,7 @@ func newTestCacher(s storage.Interface, cap int) (*cacherstorage.Cacher, storage
112
122
NewFunc : func () runtime.Object { return & example.Pod {} },
113
123
NewListFunc : func () runtime.Object { return & example.PodList {} },
114
124
Codec : codecs .LegacyCodec (examplev1 .SchemeGroupVersion ),
125
+ Clock : clock ,
115
126
}
116
127
cacher , err := cacherstorage .NewCacherFromConfig (config )
117
128
return cacher , v , err
@@ -394,7 +405,8 @@ func TestWatch(t *testing.T) {
394
405
// Inject one list error to make sure we test the relist case.
395
406
etcdStorage = & injectListError {errors : 1 , Interface : etcdStorage }
396
407
defer server .Terminate (t )
397
- cacher , _ , err := newTestCacher (etcdStorage , 3 ) // small capacity to trigger "too old version" error
408
+ fakeClock := clock .NewFakeClock (time .Now ())
409
+ cacher , _ , err := newTestCacherWithClock (etcdStorage , watchCacheDefaultCapacity , fakeClock )
398
410
if err != nil {
399
411
t .Fatalf ("Couldn't create cacher: %v" , err )
400
412
}
@@ -437,15 +449,6 @@ func TestWatch(t *testing.T) {
437
449
verifyWatchEvent (t , watcher , watch .Added , podFoo )
438
450
verifyWatchEvent (t , watcher , watch .Modified , podFooPrime )
439
451
440
- // Check whether we get too-old error via the watch channel
441
- tooOldWatcher , err := cacher .Watch (context .TODO (), "pods/ns/foo" , storage.ListOptions {ResourceVersion : "1" , Predicate : storage .Everything })
442
- if err != nil {
443
- t .Fatalf ("Expected no direct error, got %v" , err )
444
- }
445
- defer tooOldWatcher .Stop ()
446
- // Events happens in eventFreshDuration, cache expand without event "Gone".
447
- verifyWatchEvent (t , tooOldWatcher , watch .Added , podFoo )
448
-
449
452
initialWatcher , err := cacher .Watch (context .TODO (), "pods/ns/foo" , storage.ListOptions {ResourceVersion : fooCreated .ResourceVersion , Predicate : storage .Everything })
450
453
if err != nil {
451
454
t .Fatalf ("Unexpected error: %v" , err )
@@ -466,6 +469,25 @@ func TestWatch(t *testing.T) {
466
469
_ = updatePod (t , etcdStorage , podFooBis , fooUpdated )
467
470
468
471
verifyWatchEvent (t , nowWatcher , watch .Modified , podFooBis )
472
+
473
+ // Add watchCacheDefaultCapacity events to make current watch cache full.
474
+ // Make start and last event duration exceed eventFreshDuration(current 75s) to ensure watch cache won't expand.
475
+ for i := 0 ; i < watchCacheDefaultCapacity ; i ++ {
476
+ fakeClock .SetTime (time .Now ().Add (time .Duration (i ) * time .Minute ))
477
+ podFoo := makeTestPod (fmt .Sprintf ("foo-%d" , i ))
478
+ updatePod (t , etcdStorage , podFoo , nil )
479
+ }
480
+
481
+ // Check whether we get too-old error via the watch channel
482
+ tooOldWatcher , err := cacher .Watch (context .TODO (), "pods/ns/foo" , storage.ListOptions {ResourceVersion : "1" , Predicate : storage .Everything })
483
+ if err != nil {
484
+ t .Fatalf ("Expected no direct error, got %v" , err )
485
+ }
486
+ defer tooOldWatcher .Stop ()
487
+
488
+ // Ensure we get a "Gone" error.
489
+ expectedResourceExpiredError := errors .NewResourceExpired ("" ).ErrStatus
490
+ verifyWatchEvent (t , tooOldWatcher , watch .Error , & expectedResourceExpiredError )
469
491
}
470
492
471
493
func TestWatcherTimeout (t * testing.T ) {
0 commit comments