k8s.io/client-go@v0.22.2/tools/cache/expiration_cache_test.go (about)

     1  /*
     2  Copyright 2014 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 cache
    18  
    19  import (
    20  	"reflect"
    21  	"testing"
    22  	"time"
    23  
    24  	"k8s.io/apimachinery/pkg/util/clock"
    25  	"k8s.io/apimachinery/pkg/util/sets"
    26  	"k8s.io/apimachinery/pkg/util/wait"
    27  )
    28  
    29  func TestTTLExpirationBasic(t *testing.T) {
    30  	testObj := testStoreObject{id: "foo", val: "bar"}
    31  	deleteChan := make(chan string, 1)
    32  	ttlStore := NewFakeExpirationStore(
    33  		testStoreKeyFunc, deleteChan,
    34  		&FakeExpirationPolicy{
    35  			NeverExpire: sets.NewString(),
    36  			RetrieveKeyFunc: func(obj interface{}) (string, error) {
    37  				return obj.(*TimestampedEntry).Obj.(testStoreObject).id, nil
    38  			},
    39  		},
    40  		clock.RealClock{},
    41  	)
    42  	err := ttlStore.Add(testObj)
    43  	if err != nil {
    44  		t.Errorf("Unable to add obj %#v", testObj)
    45  	}
    46  	item, exists, err := ttlStore.Get(testObj)
    47  	if err != nil {
    48  		t.Errorf("Failed to get from store, %v", err)
    49  	}
    50  	if exists || item != nil {
    51  		t.Errorf("Got unexpected item %#v", item)
    52  	}
    53  	key, _ := testStoreKeyFunc(testObj)
    54  	select {
    55  	case delKey := <-deleteChan:
    56  		if delKey != key {
    57  			t.Errorf("Unexpected delete for key %s", key)
    58  		}
    59  	case <-time.After(wait.ForeverTestTimeout):
    60  		t.Errorf("Unexpected timeout waiting on delete")
    61  	}
    62  	close(deleteChan)
    63  }
    64  
    65  func TestReAddExpiredItem(t *testing.T) {
    66  	deleteChan := make(chan string, 1)
    67  	exp := &FakeExpirationPolicy{
    68  		NeverExpire: sets.NewString(),
    69  		RetrieveKeyFunc: func(obj interface{}) (string, error) {
    70  			return obj.(*TimestampedEntry).Obj.(testStoreObject).id, nil
    71  		},
    72  	}
    73  	ttlStore := NewFakeExpirationStore(
    74  		testStoreKeyFunc, deleteChan, exp, clock.RealClock{})
    75  	testKey := "foo"
    76  	testObj := testStoreObject{id: testKey, val: "bar"}
    77  	err := ttlStore.Add(testObj)
    78  	if err != nil {
    79  		t.Errorf("Unable to add obj %#v", testObj)
    80  	}
    81  
    82  	// This get will expire the item.
    83  	item, exists, err := ttlStore.Get(testObj)
    84  	if err != nil {
    85  		t.Errorf("Failed to get from store, %v", err)
    86  	}
    87  	if exists || item != nil {
    88  		t.Errorf("Got unexpected item %#v", item)
    89  	}
    90  
    91  	key, _ := testStoreKeyFunc(testObj)
    92  	differentValue := "different_bar"
    93  	err = ttlStore.Add(
    94  		testStoreObject{id: testKey, val: differentValue})
    95  	if err != nil {
    96  		t.Errorf("Failed to add second value")
    97  	}
    98  
    99  	select {
   100  	case delKey := <-deleteChan:
   101  		if delKey != key {
   102  			t.Errorf("Unexpected delete for key %s", key)
   103  		}
   104  	case <-time.After(wait.ForeverTestTimeout):
   105  		t.Errorf("Unexpected timeout waiting on delete")
   106  	}
   107  	exp.NeverExpire = sets.NewString(testKey)
   108  	item, exists, err = ttlStore.GetByKey(testKey)
   109  	if err != nil {
   110  		t.Errorf("Failed to get from store, %v", err)
   111  	}
   112  	if !exists || item == nil || item.(testStoreObject).val != differentValue {
   113  		t.Errorf("Got unexpected item %#v", item)
   114  	}
   115  	close(deleteChan)
   116  }
   117  
   118  func TestTTLList(t *testing.T) {
   119  	testObjs := []testStoreObject{
   120  		{id: "foo", val: "bar"},
   121  		{id: "foo1", val: "bar1"},
   122  		{id: "foo2", val: "bar2"},
   123  	}
   124  	expireKeys := sets.NewString(testObjs[0].id, testObjs[2].id)
   125  	deleteChan := make(chan string, len(testObjs))
   126  	defer close(deleteChan)
   127  
   128  	ttlStore := NewFakeExpirationStore(
   129  		testStoreKeyFunc, deleteChan,
   130  		&FakeExpirationPolicy{
   131  			NeverExpire: sets.NewString(testObjs[1].id),
   132  			RetrieveKeyFunc: func(obj interface{}) (string, error) {
   133  				return obj.(*TimestampedEntry).Obj.(testStoreObject).id, nil
   134  			},
   135  		},
   136  		clock.RealClock{},
   137  	)
   138  	for _, obj := range testObjs {
   139  		err := ttlStore.Add(obj)
   140  		if err != nil {
   141  			t.Errorf("Unable to add obj %#v", obj)
   142  		}
   143  	}
   144  	listObjs := ttlStore.List()
   145  	if len(listObjs) != 1 || !reflect.DeepEqual(listObjs[0], testObjs[1]) {
   146  		t.Errorf("List returned unexpected results %#v", listObjs)
   147  	}
   148  
   149  	// Make sure all our deletes come through in an acceptable rate (1/100ms)
   150  	for expireKeys.Len() != 0 {
   151  		select {
   152  		case delKey := <-deleteChan:
   153  			if !expireKeys.Has(delKey) {
   154  				t.Errorf("Unexpected delete for key %s", delKey)
   155  			}
   156  			expireKeys.Delete(delKey)
   157  		case <-time.After(wait.ForeverTestTimeout):
   158  			t.Errorf("Unexpected timeout waiting on delete")
   159  			return
   160  		}
   161  	}
   162  }
   163  
   164  func TestTTLPolicy(t *testing.T) {
   165  	fakeTime := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
   166  	ttl := 30 * time.Second
   167  	exactlyOnTTL := fakeTime.Add(-ttl)
   168  	expiredTime := fakeTime.Add(-(ttl + 1))
   169  
   170  	policy := TTLPolicy{ttl, clock.NewFakeClock(fakeTime)}
   171  	item := testStoreObject{id: "foo", val: "bar"}
   172  	itemkey, _ := testStoreKeyFunc(item)
   173  	fakeTimestampedEntry := &TimestampedEntry{Obj: item, Timestamp: exactlyOnTTL, key: itemkey}
   174  	if policy.IsExpired(fakeTimestampedEntry) {
   175  		t.Errorf("TTL cache should not expire entries exactly on ttl")
   176  	}
   177  	fakeTimestampedEntry.Timestamp = fakeTime
   178  	if policy.IsExpired(fakeTimestampedEntry) {
   179  		t.Errorf("TTL Cache should not expire entries before ttl")
   180  	}
   181  	fakeTimestampedEntry.Timestamp = expiredTime
   182  	if !policy.IsExpired(fakeTimestampedEntry) {
   183  		t.Errorf("TTL Cache should expire entries older than ttl")
   184  	}
   185  	for _, ttl = range []time.Duration{0, -1} {
   186  		policy.TTL = ttl
   187  		if policy.IsExpired(fakeTimestampedEntry) {
   188  			t.Errorf("TTL policy should only expire entries when initialized with a ttl > 0")
   189  		}
   190  	}
   191  }