github.com/maypok86/otter@v1.2.1/internal/stats/stats_test.go (about) 1 // Copyright (c) 2023 Alexey Mayshev. All rights reserved. 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 stats 16 17 import ( 18 "math/rand" 19 "testing" 20 "time" 21 ) 22 23 const ( 24 maxCount = 10_000 25 ) 26 27 func generateCount(t *testing.T) int64 { 28 t.Helper() 29 30 r := rand.NewSource(time.Now().UnixNano()) 31 count := r.Int63() % maxCount 32 if count == 0 { 33 return 1 34 } 35 36 return count 37 } 38 39 func TestStats_Nil(t *testing.T) { 40 var s *Stats 41 expected := int64(0) 42 for _, inc := range []func(){ 43 s.IncHits, 44 s.IncMisses, 45 s.IncRejectedSets, 46 s.IncEvictedCount, 47 func() { 48 s.AddEvictedCost(1) 49 }, 50 s.IncHits, 51 s.IncMisses, 52 } { 53 inc() 54 } 55 for _, f := range []func() int64{ 56 s.Hits, 57 s.Misses, 58 s.RejectedSets, 59 s.EvictedCount, 60 s.EvictedCost, 61 } { 62 if expected != f() { 63 t.Fatalf("hits and misses for nil stats should always be %d", expected) 64 } 65 } 66 s.Clear() 67 } 68 69 func TestStats_Hits(t *testing.T) { 70 expected := generateCount(t) 71 72 s := New() 73 for i := int64(0); i < expected; i++ { 74 s.IncHits() 75 } 76 77 hits := s.Hits() 78 if expected != hits { 79 t.Fatalf("number of hits should be %d, but got %d", expected, hits) 80 } 81 } 82 83 func TestStats_Misses(t *testing.T) { 84 expected := generateCount(t) 85 86 s := New() 87 for i := int64(0); i < expected; i++ { 88 s.IncMisses() 89 } 90 91 misses := s.Misses() 92 if expected != misses { 93 t.Fatalf("number of misses should be %d, but got %d", expected, misses) 94 } 95 } 96 97 func TestStats_RejectedSets(t *testing.T) { 98 expected := generateCount(t) 99 100 s := New() 101 for i := int64(0); i < expected; i++ { 102 s.IncRejectedSets() 103 } 104 105 rejectedSets := s.RejectedSets() 106 if expected != rejectedSets { 107 t.Fatalf("number of rejected sets should be %d, but got %d", expected, rejectedSets) 108 } 109 } 110 111 func TestStats_EvictedCount(t *testing.T) { 112 expected := generateCount(t) 113 114 s := New() 115 for i := int64(0); i < expected; i++ { 116 s.IncEvictedCount() 117 } 118 119 evictedCount := s.EvictedCount() 120 if expected != evictedCount { 121 t.Fatalf("number of evicted entries should be %d, but got %d", expected, evictedCount) 122 } 123 } 124 125 func TestStats_EvictedCost(t *testing.T) { 126 expected := generateCount(t) 127 128 s := New() 129 k := int64(0) 130 for k < expected { 131 add := 2 132 if expected-k < 2 { 133 add = 1 134 } 135 k += int64(add) 136 s.AddEvictedCost(uint32(add)) 137 } 138 139 evictedCost := s.EvictedCost() 140 if expected != evictedCost { 141 t.Fatalf("sum of costs of evicted entries should be %d, but got %d", expected, evictedCost) 142 } 143 } 144 145 func TestStats_Clear(t *testing.T) { 146 s := New() 147 148 count := generateCount(t) 149 for i := int64(0); i < count; i++ { 150 s.IncHits() 151 } 152 for i := int64(0); i < count; i++ { 153 s.IncMisses() 154 } 155 156 misses := s.Misses() 157 if count != misses { 158 t.Fatalf("number of misses should be %d, but got %d", count, misses) 159 } 160 hits := s.Hits() 161 if count != hits { 162 t.Fatalf("number of hits should be %d, but got %d", count, hits) 163 } 164 165 s.Clear() 166 167 hits = s.Hits() 168 misses = s.Misses() 169 if hits != 0 || misses != 0 { 170 t.Fatalf("hits and misses after clear should be 0, but got hits: %d and misses: %d", hits, misses) 171 } 172 }