github.com/mdaxf/iac@v0.0.0-20240519030858-58a061660378/framework/cache/memcache/memcache_test.go (about) 1 // The package is migrated from beego, you can get from following link: 2 // import( 3 // "github.com/beego/beego/v2/client/cache" 4 // ) 5 // Copyright 2023. All Rights Reserved. 6 // 7 // Licensed under the Apache License, Version 2.0 (the "License"); 8 // you may not use this file except in compliance with the License. 9 // You may obtain a copy of the License at 10 // 11 // http://www.apache.org/licenses/LICENSE-2.0 12 // 13 // Unless required by applicable law or agreed to in writing, software 14 // distributed under the License is distributed on an "AS IS" BASIS, 15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 // See the License for the specific language governing permissions and 17 // limitations under the License. 18 19 package memcache 20 21 import ( 22 "context" 23 "errors" 24 "fmt" 25 "os" 26 "strconv" 27 "strings" 28 "testing" 29 "time" 30 31 _ "github.com/bradfitz/gomemcache/memcache" 32 "github.com/stretchr/testify/assert" 33 34 "github.com/mdaxf/iac/framework/berror" 35 "github.com/mdaxf/iac/framework/cache" 36 ) 37 38 func TestMemcacheCache(t *testing.T) { 39 addr := os.Getenv("MEMCACHE_ADDR") 40 if addr == "" { 41 addr = "127.0.0.1:11211" 42 } 43 44 bm, err := cache.NewCache("memcache", fmt.Sprintf(`{"conn": "%s"}`, addr)) 45 assert.Nil(t, err) 46 47 timeoutDuration := 10 * time.Second 48 49 assert.Nil(t, bm.Put(context.Background(), "astaxie", "1", timeoutDuration)) 50 res, _ := bm.IsExist(context.Background(), "astaxie") 51 assert.True(t, res) 52 53 time.Sleep(11 * time.Second) 54 55 res, _ = bm.IsExist(context.Background(), "astaxie") 56 assert.False(t, res) 57 58 assert.Nil(t, bm.Put(context.Background(), "astaxie", "1", timeoutDuration)) 59 60 val, _ := bm.Get(context.Background(), "astaxie") 61 v, err := strconv.Atoi(string(val.([]byte))) 62 assert.Nil(t, err) 63 assert.Equal(t, 1, v) 64 65 assert.Nil(t, bm.Incr(context.Background(), "astaxie")) 66 67 val, _ = bm.Get(context.Background(), "astaxie") 68 v, err = strconv.Atoi(string(val.([]byte))) 69 assert.Nil(t, err) 70 assert.Equal(t, 2, v) 71 72 assert.Nil(t, bm.Decr(context.Background(), "astaxie")) 73 74 val, _ = bm.Get(context.Background(), "astaxie") 75 v, err = strconv.Atoi(string(val.([]byte))) 76 assert.Nil(t, err) 77 assert.Equal(t, 1, v) 78 assert.Nil(t, bm.Delete(context.Background(), "astaxie")) 79 80 res, _ = bm.IsExist(context.Background(), "astaxie") 81 assert.False(t, res) 82 83 assert.Nil(t, bm.Put(context.Background(), "astaxie", "author", timeoutDuration)) 84 // test string 85 res, _ = bm.IsExist(context.Background(), "astaxie") 86 assert.True(t, res) 87 88 val, _ = bm.Get(context.Background(), "astaxie") 89 vs := val.([]byte) 90 assert.Equal(t, "author", string(vs)) 91 92 // test GetMulti 93 assert.Nil(t, bm.Put(context.Background(), "astaxie1", "author1", timeoutDuration)) 94 95 res, _ = bm.IsExist(context.Background(), "astaxie1") 96 assert.True(t, res) 97 98 vv, _ := bm.GetMulti(context.Background(), []string{"astaxie", "astaxie1"}) 99 assert.Equal(t, 2, len(vv)) 100 101 if string(vv[0].([]byte)) != "author" && string(vv[0].([]byte)) != "author1" { 102 t.Error("GetMulti ERROR") 103 } 104 if string(vv[1].([]byte)) != "author1" && string(vv[1].([]byte)) != "author" { 105 t.Error("GetMulti ERROR") 106 } 107 108 vv, err = bm.GetMulti(context.Background(), []string{"astaxie0", "astaxie1"}) 109 assert.Equal(t, 2, len(vv)) 110 assert.Nil(t, vv[0]) 111 112 assert.Equal(t, "author1", string(vv[1].([]byte))) 113 114 assert.NotNil(t, err) 115 assert.True(t, strings.Contains(err.Error(), "key not exist")) 116 117 assert.Nil(t, bm.ClearAll(context.Background())) 118 // test clear all 119 } 120 121 func TestReadThroughCache_Memcache_Get(t *testing.T) { 122 bm, err := cache.NewCache("memcache", fmt.Sprintf(`{"conn": "%s"}`, "127.0.0.1:11211")) 123 assert.Nil(t, err) 124 125 testReadThroughCacheGet(t, bm) 126 } 127 128 func testReadThroughCacheGet(t *testing.T, bm cache.Cache) { 129 testCases := []struct { 130 name string 131 key string 132 value string 133 cache cache.Cache 134 wantErr error 135 }{ 136 { 137 name: "Get load err", 138 key: "key0", 139 cache: func() cache.Cache { 140 kvs := map[string]any{"key0": "value0"} 141 db := &MockOrm{kvs: kvs} 142 loadfunc := func(ctx context.Context, key string) (any, error) { 143 v, er := db.Load(key) 144 if er != nil { 145 return nil, er 146 } 147 val := []byte(v.(string)) 148 return val, nil 149 } 150 c, err := cache.NewReadThroughCache(bm, 3*time.Second, loadfunc) 151 assert.Nil(t, err) 152 return c 153 }(), 154 wantErr: func() error { 155 err := errors.New("the key not exist") 156 return berror.Wrap( 157 err, cache.LoadFuncFailed, "cache unable to load data") 158 }(), 159 }, 160 { 161 name: "Get cache exist", 162 key: "key1", 163 value: "value1", 164 cache: func() cache.Cache { 165 keysMap := map[string]int{"key1": 1} 166 kvs := map[string]any{"key1": "value1"} 167 db := &MockOrm{keysMap: keysMap, kvs: kvs} 168 loadfunc := func(ctx context.Context, key string) (any, error) { 169 v, er := db.Load(key) 170 if er != nil { 171 return nil, er 172 } 173 val := []byte(v.(string)) 174 return val, nil 175 } 176 c, err := cache.NewReadThroughCache(bm, 3*time.Second, loadfunc) 177 assert.Nil(t, err) 178 err = c.Put(context.Background(), "key1", "value1", 3*time.Second) 179 assert.Nil(t, err) 180 return c 181 }(), 182 }, 183 { 184 name: "Get loadFunc exist", 185 key: "key2", 186 value: "value2", 187 cache: func() cache.Cache { 188 keysMap := map[string]int{"key2": 1} 189 kvs := map[string]any{"key2": "value2"} 190 db := &MockOrm{keysMap: keysMap, kvs: kvs} 191 loadfunc := func(ctx context.Context, key string) (any, error) { 192 v, er := db.Load(key) 193 if er != nil { 194 return nil, er 195 } 196 val := []byte(v.(string)) 197 return val, nil 198 } 199 c, err := cache.NewReadThroughCache(bm, 3*time.Second, loadfunc) 200 assert.Nil(t, err) 201 return c 202 }(), 203 }, 204 } 205 _, err := cache.NewReadThroughCache(bm, 3*time.Second, nil) 206 assert.Equal(t, berror.Error(cache.InvalidLoadFunc, "loadFunc cannot be nil"), err) 207 for _, tc := range testCases { 208 t.Run(tc.name, func(t *testing.T) { 209 bs := []byte(tc.value) 210 c := tc.cache 211 val, err := c.Get(context.Background(), tc.key) 212 if err != nil { 213 assert.EqualError(t, tc.wantErr, err.Error()) 214 return 215 } 216 assert.Equal(t, bs, val) 217 }) 218 } 219 } 220 221 type MockOrm struct { 222 keysMap map[string]int 223 kvs map[string]any 224 } 225 226 func (m *MockOrm) Load(key string) (any, error) { 227 _, ok := m.keysMap[key] 228 if !ok { 229 return nil, errors.New("the key not exist") 230 } 231 return m.kvs[key], nil 232 }