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

     1  // Copyright (c) The Thanos Authors.
     2  // Licensed under the Apache License 2.0.
     3  
     4  package storecache
     5  
     6  import (
     7  	"encoding/base64"
     8  	"fmt"
     9  	"math"
    10  	"strings"
    11  	"testing"
    12  
    13  	"github.com/oklog/ulid"
    14  	"github.com/prometheus/prometheus/model/labels"
    15  	"golang.org/x/crypto/blake2b"
    16  
    17  	"github.com/efficientgo/core/testutil"
    18  	"github.com/thanos-io/thanos/pkg/testutil/custom"
    19  )
    20  
    21  func TestMain(m *testing.M) {
    22  	custom.TolerantVerifyLeakMain(m)
    23  }
    24  
    25  func TestCacheKey_string(t *testing.T) {
    26  	t.Parallel()
    27  
    28  	uid := ulid.MustNew(1, nil)
    29  	ulidString := uid.String()
    30  	matcher := labels.MustNewMatcher(labels.MatchRegexp, "aaa", "bbb")
    31  	matcher2 := labels.MustNewMatcher(labels.MatchNotEqual, "foo", "bar")
    32  
    33  	tests := map[string]struct {
    34  		key      cacheKey
    35  		expected string
    36  	}{
    37  		"should stringify postings cache key": {
    38  			key: cacheKey{ulidString, cacheKeyPostings(labels.Label{Name: "foo", Value: "bar"}), ""},
    39  			expected: func() string {
    40  				hash := blake2b.Sum256([]byte("foo:bar"))
    41  				encodedHash := base64.RawURLEncoding.EncodeToString(hash[0:])
    42  
    43  				return fmt.Sprintf("P:%s:%s", uid.String(), encodedHash)
    44  			}(),
    45  		},
    46  		"postings cache key includes compression scheme": {
    47  			key: cacheKey{ulidString, cacheKeyPostings(labels.Label{Name: "foo", Value: "bar"}), compressionSchemeStreamedSnappy},
    48  			expected: func() string {
    49  				hash := blake2b.Sum256([]byte("foo:bar"))
    50  				encodedHash := base64.RawURLEncoding.EncodeToString(hash[0:])
    51  
    52  				return fmt.Sprintf("P:%s:%s:%s", uid.String(), encodedHash, compressionSchemeStreamedSnappy)
    53  			}(),
    54  		},
    55  		"should stringify series cache key": {
    56  			key:      cacheKey{ulidString, cacheKeySeries(12345), ""},
    57  			expected: fmt.Sprintf("S:%s:12345", uid.String()),
    58  		},
    59  		"should stringify expanded postings cache key": {
    60  			key: cacheKey{ulidString, cacheKeyExpandedPostings(labelMatchersToString([]*labels.Matcher{matcher})), ""},
    61  			expected: func() string {
    62  				hash := blake2b.Sum256([]byte(matcher.String()))
    63  				encodedHash := base64.RawURLEncoding.EncodeToString(hash[0:])
    64  
    65  				return fmt.Sprintf("EP:%s:%s", uid.String(), encodedHash)
    66  			}(),
    67  		},
    68  		"should stringify expanded postings cache key when multiple matchers": {
    69  			key: cacheKey{ulidString, cacheKeyExpandedPostings(labelMatchersToString([]*labels.Matcher{matcher, matcher2})), ""},
    70  			expected: func() string {
    71  				hash := blake2b.Sum256([]byte(fmt.Sprintf("%s;%s", matcher.String(), matcher2.String())))
    72  				encodedHash := base64.RawURLEncoding.EncodeToString(hash[0:])
    73  
    74  				return fmt.Sprintf("EP:%s:%s", uid.String(), encodedHash)
    75  			}(),
    76  		},
    77  		"expanded postings cache key includes compression scheme": {
    78  			key: cacheKey{ulidString, cacheKeyExpandedPostings(labelMatchersToString([]*labels.Matcher{matcher})), compressionSchemeStreamedSnappy},
    79  			expected: func() string {
    80  				hash := blake2b.Sum256([]byte(matcher.String()))
    81  				encodedHash := base64.RawURLEncoding.EncodeToString(hash[0:])
    82  
    83  				return fmt.Sprintf("EP:%s:%s:%s", uid.String(), encodedHash, compressionSchemeStreamedSnappy)
    84  			}(),
    85  		},
    86  	}
    87  
    88  	for testName, testData := range tests {
    89  		t.Run(testName, func(t *testing.T) {
    90  			actual := testData.key.string()
    91  			testutil.Equals(t, testData.expected, actual)
    92  		})
    93  	}
    94  }
    95  
    96  func TestCacheKey_string_ShouldGuaranteeReasonablyShortKeyLength(t *testing.T) {
    97  	t.Parallel()
    98  
    99  	uid := ulid.MustNew(1, nil)
   100  	ulidString := uid.String()
   101  
   102  	tests := map[string]struct {
   103  		keys        []cacheKey
   104  		expectedLen int
   105  	}{
   106  		"should guarantee reasonably short key length for postings": {
   107  			expectedLen: 72,
   108  			keys: []cacheKey{
   109  				{ulidString, cacheKeyPostings(labels.Label{Name: "a", Value: "b"}), ""},
   110  				{ulidString, cacheKeyPostings(labels.Label{Name: strings.Repeat("a", 100), Value: strings.Repeat("a", 1000)}), ""},
   111  			},
   112  		},
   113  		"should guarantee reasonably short key length for series": {
   114  			expectedLen: 49,
   115  			keys: []cacheKey{
   116  				{ulidString, cacheKeySeries(math.MaxUint64), ""},
   117  			},
   118  		},
   119  		"should guarantee reasonably short key length for expanded postings": {
   120  			expectedLen: 73,
   121  			keys: []cacheKey{
   122  				{ulidString, func() interface{} {
   123  					matchers := make([]*labels.Matcher, 0, 100)
   124  					name := strings.Repeat("a", 100)
   125  					value := strings.Repeat("a", 1000)
   126  					for i := 0; i < 100; i++ {
   127  						t := labels.MatchType(i % 4)
   128  						matchers = append(matchers, labels.MustNewMatcher(t, name, value))
   129  					}
   130  					return cacheKeyExpandedPostings(labelMatchersToString(matchers))
   131  				}(), ""},
   132  			},
   133  		},
   134  	}
   135  
   136  	for testName, testData := range tests {
   137  		t.Run(testName, func(t *testing.T) {
   138  			for _, key := range testData.keys {
   139  				testutil.Equals(t, testData.expectedLen, len(key.string()))
   140  			}
   141  		})
   142  	}
   143  }
   144  
   145  func BenchmarkCacheKey_string_Postings(b *testing.B) {
   146  	uid := ulid.MustNew(1, nil)
   147  	key := cacheKey{uid.String(), cacheKeyPostings(labels.Label{Name: strings.Repeat("a", 100), Value: strings.Repeat("a", 1000)}), ""}
   148  
   149  	b.ResetTimer()
   150  	for i := 0; i < b.N; i++ {
   151  		key.string()
   152  	}
   153  }
   154  
   155  func BenchmarkCacheKey_string_Series(b *testing.B) {
   156  	uid := ulid.MustNew(1, nil)
   157  	key := cacheKey{uid.String(), cacheKeySeries(math.MaxUint64), ""}
   158  
   159  	b.ResetTimer()
   160  	for i := 0; i < b.N; i++ {
   161  		key.string()
   162  	}
   163  }