github.com/vicanso/lru-ttl@v1.5.1/l2cache_test.go (about) 1 // Copyright 2020 tree xie 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 package lruttl 15 16 import ( 17 "bytes" 18 "context" 19 "encoding/json" 20 "errors" 21 "testing" 22 "time" 23 24 "github.com/stretchr/testify/assert" 25 ) 26 27 type testSlowCache struct { 28 data map[string][]byte 29 } 30 31 const slowCacheTTL = 101 * time.Millisecond 32 33 var testSlowCacheNilErr = errors.New("not found") 34 35 func (sc *testSlowCache) Get(_ context.Context, key string) ([]byte, error) { 36 buf, ok := sc.data[key] 37 if !ok { 38 return nil, testSlowCacheNilErr 39 } 40 time.Sleep(time.Second) 41 return buf, nil 42 } 43 44 func (sc *testSlowCache) Set(_ context.Context, key string, value []byte, ttl time.Duration) error { 45 sc.data[key] = value 46 return nil 47 } 48 func (sc *testSlowCache) TTL(_ context.Context, key string) (time.Duration, error) { 49 return slowCacheTTL, nil 50 } 51 52 func (sc *testSlowCache) Del(_ context.Context, key string) (int64, error) { 53 delete(sc.data, key) 54 return 1, nil 55 } 56 57 type testData struct { 58 Name string `json:"name,omitempty"` 59 } 60 61 func TestL2Cache(t *testing.T) { 62 assert := assert.New(t) 63 ctx := context.Background() 64 65 sc := testSlowCache{ 66 data: make(map[string][]byte), 67 } 68 opts := []L2CacheOption{ 69 L2CacheMarshalOption(json.Marshal), 70 L2CacheUnmarshalOption(json.Unmarshal), 71 L2CachePrefixOption("prefix:"), 72 L2CacheNilErrOption(testSlowCacheNilErr), 73 } 74 l2 := NewL2Cache(&sc, 1, time.Second, opts...) 75 76 key, err := l2.getKey("1") 77 assert.Nil(err) 78 assert.Equal("prefix:1", key) 79 _, err = l2.getKey("") 80 assert.Equal(ErrKeyIsNil, err) 81 82 key = "abcd" 83 name := "test" 84 data := testData{} 85 86 err = l2.Get(ctx, key, &data) 87 assert.NotNil(err) 88 assert.Equal("not found", err.Error()) 89 90 err = l2.Set(ctx, key, &testData{ 91 Name: name, 92 }) 93 assert.Nil(err) 94 95 // 成功获取 96 err = l2.Get(ctx, key, &data) 97 assert.Nil(err) 98 assert.Equal(name, data.Name) 99 100 // 由于lru的大小令为1,因此会导致lru中清除了原有的key 101 err = l2.Set(ctx, "ab", &testData{}) 102 assert.Nil(err) 103 104 // 从slow cache中获取数据并更新lru缓存 105 err = l2.Get(ctx, key, &data) 106 assert.Nil(err) 107 assert.Equal(name, data.Name) 108 109 // 从lru获取缓存(时间较快) 110 start := time.Now() 111 err = l2.Get(ctx, key, &data) 112 assert.Nil(err) 113 assert.Equal(name, data.Name) 114 // 从lru获取耗时少于10ms 115 assert.True(time.Since(start) < 10*time.Millisecond) 116 117 err = l2.Set(ctx, key, &map[string]string{ 118 "name": "newName", 119 }) 120 assert.Nil(err) 121 m := make(map[string]string) 122 err = l2.Get(ctx, key, &m) 123 assert.Nil(err) 124 assert.Equal("newName", m["name"]) 125 126 err = l2.Get(ctx, "abc", &map[string]string{}) 127 assert.NotNil(err) 128 129 err = l2.GetIgnoreNilErr(ctx, "abc", &map[string]string{}) 130 assert.Nil(err) 131 } 132 133 func TestL2CacheTTL(t *testing.T) { 134 assert := assert.New(t) 135 sc := testSlowCache{ 136 data: make(map[string][]byte), 137 } 138 ctx := context.Background() 139 l2 := NewL2Cache(&sc, 10, 10*time.Second) 140 key := "test" 141 err := l2.Set(ctx, key, "value", 2*time.Second) 142 assert.Nil(err) 143 144 ttl, err := l2.TTL(ctx, key) 145 assert.Nil(err) 146 // 从lru中获取 147 assert.True(ttl > time.Second && ttl <= 2*time.Second) 148 149 l2.ttlCache.Remove(key) 150 151 ttl, err = l2.TTL(ctx, key) 152 assert.Nil(err) 153 // 从slow cache中获取,slow cache获取ttl为固定值 154 assert.Equal(slowCacheTTL, ttl) 155 } 156 157 func TestL2CacheDel(t *testing.T) { 158 assert := assert.New(t) 159 sc := testSlowCache{ 160 data: make(map[string][]byte), 161 } 162 ctx := context.Background() 163 l2 := NewL2Cache(&sc, 10, 10*time.Second) 164 key := "test" 165 value := "value" 166 err := l2.Set(ctx, key, value, 2*time.Second) 167 assert.Nil(err) 168 169 result := "" 170 err = l2.Get(ctx, key, &result) 171 assert.Nil(err) 172 assert.Equal(value, result) 173 174 count, err := l2.Del(ctx, key) 175 assert.Equal(int64(1), count) 176 assert.Nil(err) 177 178 // 删除后再获取失败 179 err = l2.Get(ctx, key, &result) 180 assert.Equal("not found", err.Error()) 181 } 182 183 func TestGetSetBytes(t *testing.T) { 184 assert := assert.New(t) 185 sc := testSlowCache{ 186 data: make(map[string][]byte), 187 } 188 ctx := context.Background() 189 l2 := NewL2Cache(&sc, 10, 10*time.Second) 190 191 key := "TestGetSetBytes" 192 err := l2.SetBytes(ctx, key, []byte("abc")) 193 assert.Nil(err) 194 195 buf, err := l2.GetBytes(ctx, key) 196 assert.Nil(err) 197 assert.Equal([]byte("abc"), buf) 198 } 199 200 func TestBufferMarshalUnmarshal(t *testing.T) { 201 assert := assert.New(t) 202 buf := bytes.NewBufferString("abc") 203 result, err := BufferMarshal(buf) 204 assert.Nil(err) 205 assert.Equal(buf.Bytes(), result) 206 207 newBuf := &bytes.Buffer{} 208 err = BufferUnmarshal(result, newBuf) 209 assert.Nil(err) 210 assert.Equal(buf, newBuf) 211 }