github.com/bhojpur/cache@v0.0.4/pkg/engine/ristretto/policy_test.go (about) 1 package ristretto 2 3 // Copyright (c) 2018 Bhojpur Consulting Private Limited, India. All rights reserved. 4 5 // Permission is hereby granted, free of charge, to any person obtaining a copy 6 // of this software and associated documentation files (the "Software"), to deal 7 // in the Software without restriction, including without limitation the rights 8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 // copies of the Software, and to permit persons to whom the Software is 10 // furnished to do so, subject to the following conditions: 11 12 // The above copyright notice and this permission notice shall be included in 13 // all copies or substantial portions of the Software. 14 15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 // THE SOFTWARE. 22 23 import ( 24 "testing" 25 "time" 26 27 "github.com/stretchr/testify/require" 28 ) 29 30 func TestPolicy(t *testing.T) { 31 defer func() { 32 require.Nil(t, recover()) 33 }() 34 newPolicy(100, 10) 35 } 36 37 func TestPolicyMetrics(t *testing.T) { 38 p := newDefaultPolicy(100, 10) 39 p.CollectMetrics(newMetrics()) 40 require.NotNil(t, p.metrics) 41 require.NotNil(t, p.evict.metrics) 42 } 43 44 func TestPolicyProcessItems(t *testing.T) { 45 p := newDefaultPolicy(100, 10) 46 p.itemsCh <- []uint64{1, 2, 2} 47 time.Sleep(wait) 48 p.Lock() 49 require.Equal(t, int64(2), p.admit.Estimate(2)) 50 require.Equal(t, int64(1), p.admit.Estimate(1)) 51 p.Unlock() 52 53 p.stop <- struct{}{} 54 p.itemsCh <- []uint64{3, 3, 3} 55 time.Sleep(wait) 56 p.Lock() 57 require.Equal(t, int64(0), p.admit.Estimate(3)) 58 p.Unlock() 59 } 60 61 func TestPolicyPush(t *testing.T) { 62 p := newDefaultPolicy(100, 10) 63 require.True(t, p.Push([]uint64{})) 64 65 keepCount := 0 66 for i := 0; i < 10; i++ { 67 if p.Push([]uint64{1, 2, 3, 4, 5}) { 68 keepCount++ 69 } 70 } 71 require.NotEqual(t, 0, keepCount) 72 } 73 74 func TestPolicyAdd(t *testing.T) { 75 p := newDefaultPolicy(1000, 100) 76 if victims, added := p.Add(1, 101); victims != nil || added { 77 t.Fatal("can't add an item bigger than entire cache") 78 } 79 p.Lock() 80 p.evict.add(1, 1) 81 p.admit.Increment(1) 82 p.admit.Increment(2) 83 p.admit.Increment(3) 84 p.Unlock() 85 86 victims, added := p.Add(1, 1) 87 require.Nil(t, victims) 88 require.False(t, added) 89 90 victims, added = p.Add(2, 20) 91 require.Nil(t, victims) 92 require.True(t, added) 93 94 victims, added = p.Add(3, 90) 95 require.NotNil(t, victims) 96 require.True(t, added) 97 98 victims, added = p.Add(4, 20) 99 require.NotNil(t, victims) 100 require.False(t, added) 101 } 102 103 func TestPolicyHas(t *testing.T) { 104 p := newDefaultPolicy(100, 10) 105 p.Add(1, 1) 106 require.True(t, p.Has(1)) 107 require.False(t, p.Has(2)) 108 } 109 110 func TestPolicyDel(t *testing.T) { 111 p := newDefaultPolicy(100, 10) 112 p.Add(1, 1) 113 p.Del(1) 114 p.Del(2) 115 require.False(t, p.Has(1)) 116 require.False(t, p.Has(2)) 117 } 118 119 func TestPolicyCap(t *testing.T) { 120 p := newDefaultPolicy(100, 10) 121 p.Add(1, 1) 122 require.Equal(t, int64(9), p.MaxCost()-p.Used()) 123 } 124 125 func TestPolicyUpdate(t *testing.T) { 126 p := newDefaultPolicy(100, 10) 127 p.Add(1, 1) 128 p.Update(1, 2) 129 p.Lock() 130 require.Equal(t, int64(2), p.evict.keyCosts[1]) 131 p.Unlock() 132 } 133 134 func TestPolicyCost(t *testing.T) { 135 p := newDefaultPolicy(100, 10) 136 p.Add(1, 2) 137 require.Equal(t, int64(2), p.Cost(1)) 138 require.Equal(t, int64(-1), p.Cost(2)) 139 } 140 141 func TestPolicyClear(t *testing.T) { 142 p := newDefaultPolicy(100, 10) 143 p.Add(1, 1) 144 p.Add(2, 2) 145 p.Add(3, 3) 146 p.Clear() 147 require.Equal(t, int64(10), p.MaxCost()-p.Used()) 148 require.False(t, p.Has(1)) 149 require.False(t, p.Has(2)) 150 require.False(t, p.Has(3)) 151 } 152 153 func TestPolicyClose(t *testing.T) { 154 defer func() { 155 require.NotNil(t, recover()) 156 }() 157 158 p := newDefaultPolicy(100, 10) 159 p.Add(1, 1) 160 p.Close() 161 p.itemsCh <- []uint64{1} 162 } 163 164 func TestPushAfterClose(t *testing.T) { 165 p := newDefaultPolicy(100, 10) 166 p.Close() 167 require.False(t, p.Push([]uint64{1, 2})) 168 } 169 170 func TestAddAfterClose(t *testing.T) { 171 p := newDefaultPolicy(100, 10) 172 p.Close() 173 p.Add(1, 1) 174 } 175 176 func TestSampledLFUAdd(t *testing.T) { 177 e := newSampledLFU(4) 178 e.add(1, 1) 179 e.add(2, 2) 180 e.add(3, 1) 181 require.Equal(t, int64(4), e.used) 182 require.Equal(t, int64(2), e.keyCosts[2]) 183 } 184 185 func TestSampledLFUDel(t *testing.T) { 186 e := newSampledLFU(4) 187 e.add(1, 1) 188 e.add(2, 2) 189 e.del(2) 190 require.Equal(t, int64(1), e.used) 191 _, ok := e.keyCosts[2] 192 require.False(t, ok) 193 e.del(4) 194 } 195 196 func TestSampledLFUUpdate(t *testing.T) { 197 e := newSampledLFU(4) 198 e.add(1, 1) 199 require.True(t, e.updateIfHas(1, 2)) 200 require.Equal(t, int64(2), e.used) 201 require.False(t, e.updateIfHas(2, 2)) 202 } 203 204 func TestSampledLFUClear(t *testing.T) { 205 e := newSampledLFU(4) 206 e.add(1, 1) 207 e.add(2, 2) 208 e.add(3, 1) 209 e.clear() 210 require.Equal(t, 0, len(e.keyCosts)) 211 require.Equal(t, int64(0), e.used) 212 } 213 214 func TestSampledLFURoom(t *testing.T) { 215 e := newSampledLFU(16) 216 e.add(1, 1) 217 e.add(2, 2) 218 e.add(3, 3) 219 require.Equal(t, int64(6), e.roomLeft(4)) 220 } 221 222 func TestSampledLFUSample(t *testing.T) { 223 e := newSampledLFU(16) 224 e.add(4, 4) 225 e.add(5, 5) 226 sample := e.fillSample([]*policyPair{ 227 {1, 1}, 228 {2, 2}, 229 {3, 3}, 230 }) 231 k := sample[len(sample)-1].key 232 require.Equal(t, 5, len(sample)) 233 require.NotEqual(t, 1, k) 234 require.NotEqual(t, 2, k) 235 require.NotEqual(t, 3, k) 236 require.Equal(t, len(sample), len(e.fillSample(sample))) 237 e.del(5) 238 sample = e.fillSample(sample[:len(sample)-2]) 239 require.Equal(t, 4, len(sample)) 240 } 241 242 func TestTinyLFUIncrement(t *testing.T) { 243 a := newTinyLFU(4) 244 a.Increment(1) 245 a.Increment(1) 246 a.Increment(1) 247 require.True(t, a.door.Has(1)) 248 require.Equal(t, int64(2), a.freq.Estimate(1)) 249 250 a.Increment(1) 251 require.False(t, a.door.Has(1)) 252 require.Equal(t, int64(1), a.freq.Estimate(1)) 253 } 254 255 func TestTinyLFUEstimate(t *testing.T) { 256 a := newTinyLFU(8) 257 a.Increment(1) 258 a.Increment(1) 259 a.Increment(1) 260 require.Equal(t, int64(3), a.Estimate(1)) 261 require.Equal(t, int64(0), a.Estimate(2)) 262 } 263 264 func TestTinyLFUPush(t *testing.T) { 265 a := newTinyLFU(16) 266 a.Push([]uint64{1, 2, 2, 3, 3, 3}) 267 require.Equal(t, int64(1), a.Estimate(1)) 268 require.Equal(t, int64(2), a.Estimate(2)) 269 require.Equal(t, int64(3), a.Estimate(3)) 270 require.Equal(t, int64(6), a.incrs) 271 } 272 273 func TestTinyLFUClear(t *testing.T) { 274 a := newTinyLFU(16) 275 a.Push([]uint64{1, 3, 3, 3}) 276 a.clear() 277 require.Equal(t, int64(0), a.incrs) 278 require.Equal(t, int64(0), a.Estimate(3)) 279 }