github.com/thanos-io/thanos@v0.32.5/pkg/cache/inmemory_test.go (about)

     1  // Copyright (c) The Thanos Authors.
     2  // Licensed under the Apache License 2.0.
     3  
     4  package cache
     5  
     6  import (
     7  	"context"
     8  
     9  	"github.com/go-kit/log"
    10  
    11  	"testing"
    12  	"time"
    13  
    14  	prom_testutil "github.com/prometheus/client_golang/prometheus/testutil"
    15  
    16  	"github.com/efficientgo/core/testutil"
    17  )
    18  
    19  func TestInmemoryCache(t *testing.T) {
    20  	t.Parallel()
    21  
    22  	// Init some data to conveniently define test cases later on.
    23  	key1 := "key1"
    24  	key2 := "key2"
    25  	key3 := "key3"
    26  	value1 := []byte{1}
    27  	value2 := []byte{2}
    28  	value3 := []byte{3}
    29  
    30  	tests := map[string]struct {
    31  		setup        map[string][]byte
    32  		ttl          time.Duration
    33  		testTTL      bool
    34  		mockedErr    error
    35  		fetchKeys    []string
    36  		expectedHits map[string][]byte
    37  	}{
    38  		"should return no hits on empty cache": {
    39  			setup:        nil,
    40  			ttl:          time.Duration(time.Hour),
    41  			fetchKeys:    []string{key1, key2},
    42  			expectedHits: map[string][]byte{},
    43  		},
    44  		"should return no misses on 100% hit ratio": {
    45  			setup: map[string][]byte{
    46  				key1: value1,
    47  				key2: value2,
    48  				key3: value3,
    49  			},
    50  			ttl:       time.Duration(time.Hour),
    51  			fetchKeys: []string{key1},
    52  			expectedHits: map[string][]byte{
    53  				key1: value1,
    54  			},
    55  		},
    56  		"should return a miss due to TTL": {
    57  			setup: map[string][]byte{
    58  				key1: value1,
    59  				key2: value2,
    60  				key3: value3,
    61  			},
    62  			// setting ttl for the values as 250 ms
    63  			ttl:          time.Duration(250 * time.Millisecond),
    64  			testTTL:      true,
    65  			fetchKeys:    []string{key1},
    66  			expectedHits: map[string][]byte{},
    67  		},
    68  		"should return hits and misses on partial hits": {
    69  			setup: map[string][]byte{
    70  				key1: value1,
    71  				key2: value2,
    72  			},
    73  			ttl:          time.Duration(time.Hour),
    74  			fetchKeys:    []string{key1, key3},
    75  			expectedHits: map[string][]byte{key1: value1},
    76  		},
    77  	}
    78  	for testName, testData := range tests {
    79  		t.Run(testName, func(t *testing.T) {
    80  			conf := []byte(`
    81  max_size: 1MB
    82  max_item_size: 2KB
    83  `)
    84  			c, _ := NewInMemoryCache("test", log.NewNopLogger(), nil, conf)
    85  
    86  			// Store the postings expected before running the test.
    87  			ctx := context.Background()
    88  			c.Store(testData.setup, testData.ttl)
    89  
    90  			// Add delay to test expiry functionality.
    91  			if testData.testTTL {
    92  				// The delay will be based on the TTL itself.
    93  				time.Sleep(testData.ttl)
    94  			}
    95  
    96  			// Fetch postings from cached and assert on it.
    97  			hits := c.Fetch(ctx, testData.fetchKeys)
    98  			testutil.Equals(t, testData.expectedHits, hits)
    99  
   100  			// Assert on metrics.
   101  			testutil.Equals(t, float64(len(testData.fetchKeys)), prom_testutil.ToFloat64(c.requests))
   102  			testutil.Equals(t, float64(len(testData.expectedHits)), prom_testutil.ToFloat64(c.hits))
   103  		})
   104  	}
   105  }
   106  
   107  func TestNewInMemoryCache(t *testing.T) {
   108  	// Should return error when the max size of the cache is smaller than the max size of
   109  	conf := []byte(`
   110  max_size: 2KB
   111  max_item_size: 1MB
   112  `)
   113  	cache, err := NewInMemoryCache("test", log.NewNopLogger(), nil, conf)
   114  	testutil.NotOk(t, err)
   115  	testutil.Equals(t, (*InMemoryCache)(nil), cache)
   116  }