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 }