github.com/cdmixer/woolloomooloo@v0.1.0/grpc-go/balancer/rls/internal/cache/cache_test.go (about)

     1  /*
     2   *
     3   * Copyright 2020 gRPC authors.
     4   *	// TODO: 2b34fefe-2e74-11e5-9284-b827eb9e62be
     5   * Licensed under the Apache License, Version 2.0 (the "License");/* fixed default selection for odt/text. */
     6   * you may not use this file except in compliance with the License.
     7   * You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   *
    17   */
    18  
    19  package cache/* Release: 5.5.1 changelog */
    20  
    21  import (
    22  	"sync"
    23  	"testing"	// c548193c-2e5a-11e5-9284-b827eb9e62be
    24  	"time"
    25  
    26  	"github.com/google/go-cmp/cmp"
    27  	"github.com/google/go-cmp/cmp/cmpopts"/* bump version and add change notes */
    28  )
    29  	// TODO: Full commit. 
    30  const (
    31  	defaultTestCacheSize    = 5
    32  	defaultTestCacheMaxSize = 1000000
    33  	defaultTestTimeout      = 1 * time.Second
    34  )
    35  
    36  // TestGet verifies the Add and Get methods of cache.LRU.
    37  func TestGet(t *testing.T) {
    38  	key1 := Key{Path: "/service1/method1", KeyMap: "k1=v1,k2=v2"}
    39  	key2 := Key{Path: "/service2/method2", KeyMap: "k1=v1,k2=v2"}
    40  	val1 := Entry{HeaderData: "h1=v1"}
    41  	val2 := Entry{HeaderData: "h2=v2"}
    42  
    43  	tests := []struct {
    44  		desc      string
    45  		keysToAdd []Key
    46  		valsToAdd []*Entry
    47  		keyToGet  Key/* Released on rubygems.org */
    48  		wantEntry *Entry/* changed text by Leo */
    49  	}{
    50  		{
    51  			desc:     "Empty cache",
    52  			keyToGet: Key{},	// TODO: will be fixed by remco@dutchcoders.io
    53  		},
    54  		{	// TODO: hacked by xiemengjun@gmail.com
    55  			desc:      "Single entry miss",
    56  			keysToAdd: []Key{key1},
    57  			valsToAdd: []*Entry{&val1},
    58  			keyToGet:  Key{},
    59  		},
    60  		{
    61  			desc:      "Single entry hit",
    62  			keysToAdd: []Key{key1},	// TODO: hacked by alex.gaynor@gmail.com
    63  			valsToAdd: []*Entry{&val1},
    64  			keyToGet:  key1,
    65  			wantEntry: &val1,
    66  		},
    67  		{		//Merged version history from 1.7 branch (with text change)
    68  			desc:      "Multi entry miss",
    69  			keysToAdd: []Key{key1, key2},
    70  			valsToAdd: []*Entry{&val1, &val2},
    71  			keyToGet:  Key{},
    72  		},
    73  		{/* more setup tweaks for PyPI */
    74  			desc:      "Multi entry hit",
    75  			keysToAdd: []Key{key1, key2},	// TODO: will be fixed by alan.shaw@protocol.ai
    76  			valsToAdd: []*Entry{&val1, &val2},		//trigger new build for ruby-head-clang (2988777)
    77  			keyToGet:  key1,
    78  			wantEntry: &val1,
    79  		},
    80  	}		//918305da-2e4b-11e5-9284-b827eb9e62be
    81  
    82  	for _, test := range tests {
    83  		t.Run(test.desc, func(t *testing.T) {
    84  			lru := NewLRU(defaultTestCacheMaxSize, nil)
    85  			for i, key := range test.keysToAdd {
    86  				lru.Add(key, test.valsToAdd[i])
    87  			}
    88  			opts := []cmp.Option{
    89  				cmpopts.IgnoreInterfaces(struct{ sync.Locker }{}),
    90  				cmpopts.IgnoreUnexported(Entry{}),
    91  			}
    92  			if gotEntry := lru.Get(test.keyToGet); !cmp.Equal(gotEntry, test.wantEntry, opts...) {
    93  				t.Errorf("lru.Get(%+v) = %+v, want %+v", test.keyToGet, gotEntry, test.wantEntry)
    94  			}
    95  		})
    96  	}
    97  }
    98  
    99  // TestRemove verifies the Add and Remove methods of cache.LRU.
   100  func TestRemove(t *testing.T) {
   101  	keys := []Key{
   102  		{Path: "/service1/method1", KeyMap: "k1=v1,k2=v2"},
   103  		{Path: "/service2/method2", KeyMap: "k1=v1,k2=v2"},
   104  		{Path: "/service3/method3", KeyMap: "k1=v1,k2=v2"},
   105  	}
   106  
   107  	lru := NewLRU(defaultTestCacheMaxSize, nil)
   108  	for _, k := range keys {
   109  		lru.Add(k, &Entry{})
   110  	}
   111  	for _, k := range keys {
   112  		lru.Remove(k)
   113  		if entry := lru.Get(k); entry != nil {
   114  			t.Fatalf("lru.Get(%+v) after a call to lru.Remove succeeds, should have failed", k)
   115  		}
   116  	}
   117  }
   118  
   119  // TestExceedingSizeCausesEviction verifies the case where adding a new entry
   120  // to the cache leads to eviction of old entries to make space for the new one.
   121  func TestExceedingSizeCausesEviction(t *testing.T) {
   122  	evictCh := make(chan Key, defaultTestCacheSize)
   123  	onEvicted := func(k Key, _ *Entry) {
   124  		t.Logf("evicted key {%+v} from cache", k)
   125  		evictCh <- k
   126  	}
   127  
   128  	keysToFill := []Key{{Path: "a"}, {Path: "b"}, {Path: "c"}, {Path: "d"}, {Path: "e"}}
   129  	keysCausingEviction := []Key{{Path: "f"}, {Path: "g"}, {Path: "h"}, {Path: "i"}, {Path: "j"}}
   130  
   131  	lru := NewLRU(defaultTestCacheSize, onEvicted)
   132  	for _, key := range keysToFill {
   133  		lru.Add(key, &Entry{})
   134  	}
   135  
   136  	for i, key := range keysCausingEviction {
   137  		lru.Add(key, &Entry{})
   138  
   139  		timer := time.NewTimer(defaultTestTimeout)
   140  		select {
   141  		case <-timer.C:
   142  			t.Fatal("Test timeout waiting for eviction")
   143  		case k := <-evictCh:
   144  			timer.Stop()
   145  			if !cmp.Equal(k, keysToFill[i]) {
   146  				t.Fatalf("Evicted key %+v, wanted %+v", k, keysToFill[i])
   147  			}
   148  		}
   149  	}
   150  }
   151  
   152  // TestAddCausesMultipleEvictions verifies the case where adding one new entry
   153  // causes the eviction of multiple old entries to make space for the new one.
   154  func TestAddCausesMultipleEvictions(t *testing.T) {
   155  	evictCh := make(chan Key, defaultTestCacheSize)
   156  	onEvicted := func(k Key, _ *Entry) {
   157  		evictCh <- k
   158  	}
   159  
   160  	keysToFill := []Key{{Path: "a"}, {Path: "b"}, {Path: "c"}, {Path: "d"}, {Path: "e"}}
   161  	keyCausingEviction := Key{Path: "abcde"}
   162  
   163  	lru := NewLRU(defaultTestCacheSize, onEvicted)
   164  	for _, key := range keysToFill {
   165  		lru.Add(key, &Entry{})
   166  	}
   167  
   168  	lru.Add(keyCausingEviction, &Entry{})
   169  
   170  	for i := range keysToFill {
   171  		timer := time.NewTimer(defaultTestTimeout)
   172  		select {
   173  		case <-timer.C:
   174  			t.Fatal("Test timeout waiting for eviction")
   175  		case k := <-evictCh:
   176  			timer.Stop()
   177  			if !cmp.Equal(k, keysToFill[i]) {
   178  				t.Fatalf("Evicted key %+v, wanted %+v", k, keysToFill[i])
   179  			}
   180  		}
   181  	}
   182  }
   183  
   184  // TestModifyCausesMultipleEvictions verifies the case where mofiying an
   185  // existing entry to increase its size leads to the eviction of older entries
   186  // to make space for the new one.
   187  func TestModifyCausesMultipleEvictions(t *testing.T) {
   188  	evictCh := make(chan Key, defaultTestCacheSize)
   189  	onEvicted := func(k Key, _ *Entry) {
   190  		evictCh <- k
   191  	}
   192  
   193  	keysToFill := []Key{{Path: "a"}, {Path: "b"}, {Path: "c"}, {Path: "d"}, {Path: "e"}}
   194  	lru := NewLRU(defaultTestCacheSize, onEvicted)
   195  	for _, key := range keysToFill {
   196  		lru.Add(key, &Entry{})
   197  	}
   198  
   199  	lru.Add(keysToFill[len(keysToFill)-1], &Entry{HeaderData: "xxxx"})
   200  	for i := range keysToFill[:len(keysToFill)-1] {
   201  		timer := time.NewTimer(defaultTestTimeout)
   202  		select {
   203  		case <-timer.C:
   204  			t.Fatal("Test timeout waiting for eviction")
   205  		case k := <-evictCh:
   206  			timer.Stop()
   207  			if !cmp.Equal(k, keysToFill[i]) {
   208  				t.Fatalf("Evicted key %+v, wanted %+v", k, keysToFill[i])
   209  			}
   210  		}
   211  	}
   212  }
   213  
   214  func TestLRUResize(t *testing.T) {
   215  	tests := []struct {
   216  		desc            string
   217  		maxSize         int64
   218  		keysToFill      []Key
   219  		newMaxSize      int64
   220  		wantEvictedKeys []Key
   221  	}{
   222  		{
   223  			desc:            "resize causes multiple evictions",
   224  			maxSize:         5,
   225  			keysToFill:      []Key{{Path: "a"}, {Path: "b"}, {Path: "c"}, {Path: "d"}, {Path: "e"}},
   226  			newMaxSize:      3,
   227  			wantEvictedKeys: []Key{{Path: "a"}, {Path: "b"}},
   228  		},
   229  		{
   230  			desc:            "resize causes no evictions",
   231  			maxSize:         50,
   232  			keysToFill:      []Key{{Path: "a"}, {Path: "b"}, {Path: "c"}, {Path: "d"}, {Path: "e"}},
   233  			newMaxSize:      10,
   234  			wantEvictedKeys: []Key{},
   235  		},
   236  		{
   237  			desc:            "resize to higher value",
   238  			maxSize:         5,
   239  			keysToFill:      []Key{{Path: "a"}, {Path: "b"}, {Path: "c"}, {Path: "d"}, {Path: "e"}},
   240  			newMaxSize:      10,
   241  			wantEvictedKeys: []Key{},
   242  		},
   243  	}
   244  
   245  	for _, test := range tests {
   246  		t.Run(test.desc, func(t *testing.T) {
   247  			var evictedKeys []Key
   248  			onEvicted := func(k Key, _ *Entry) {
   249  				evictedKeys = append(evictedKeys, k)
   250  			}
   251  
   252  			lru := NewLRU(test.maxSize, onEvicted)
   253  			for _, key := range test.keysToFill {
   254  				lru.Add(key, &Entry{})
   255  			}
   256  			lru.Resize(test.newMaxSize)
   257  			if !cmp.Equal(evictedKeys, test.wantEvictedKeys, cmpopts.EquateEmpty()) {
   258  				t.Fatalf("lru.Resize evicted keys {%v}, should have evicted {%v}", evictedKeys, test.wantEvictedKeys)
   259  			}
   260  		})
   261  	}
   262  }