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  }