up: add more unit tests

This commit is contained in:
inhere
2021-06-30 13:45:22 +08:00
parent 1af54fad12
commit 5e02b7557a
17 changed files with 240 additions and 57 deletions

View File

@@ -25,11 +25,14 @@ Generic cache use and cache manager for golang. Provide a unified usage API by p
- `gocache` https://github.com/patrickmn/go-cache
- `bigcache` https://github.com/allegro/bigcache
internal:
Internal:
- file internal driver [driver_file.go](driver_file.go)
- memory internal driver [driver_memory.go](driver_memory.go)
> Notice: The built-in implementation is relatively simple and is not recommended for production environments;
> the production environment recommends using the third-party drivers listed above.
## GoDoc
- [doc on gowalker](https://gowalker.org/github.com/gookit/cache)
@@ -53,8 +56,6 @@ type Cache interface {
// basic operation
Has(key string) bool
Get(key string) interface{}
// GetAs get cache value and unmarshal to an object ptr.
GetAs(key string, ptr interface{}) error
Set(key string, val interface{}, ttl time.Duration) (err error)
Del(key string) error
// multi operation

View File

@@ -26,11 +26,13 @@ Golang 通用的缓存管理使用库。
- `gocache` https://github.com/patrickmn/go-cache
- `bigcache` https://github.com/allegro/bigcache
internal:
Internal:
- file 简单的文件缓存(_当前包的内置实现_)
- memory 简单的内存缓存(_当前包的内置实现_)
> 注意:内置实现比较简单,不推荐生产环境使用;生产环境推荐使用上面列出的三方驱动。
## GoDoc
- [doc on gowalker](https://gowalker.org/github.com/gookit/cache)
@@ -53,8 +55,6 @@ type Cache interface {
// basic op
Has(key string) bool
Get(key string) interface{}
// GetAs get cache value and unmarshal to an object ptr.
GetAs(key string, ptr interface{}) error
Set(key string, val interface{}, ttl time.Duration) (err error)
Del(key string) error
// multi op

View File

@@ -8,6 +8,7 @@ import (
"go.etcd.io/bbolt"
)
// Name driver name
const Name = "boltDB"
// BoltDB definition

View File

@@ -10,6 +10,7 @@ import (
// Memory open a file that does not persist to disk.
const Memory = ":memory:"
// Name driver name
const Name = "buntDB"
// BuntDB definition.

View File

@@ -88,13 +88,13 @@ func Register(name string, driver Cache) *Manager {
}
// Unregister an cache driver
func Unregister(name string) {
std.Unregister(name)
func Unregister(name string) int {
return std.Unregister(name)
}
// UnregisterAll cache drivers
func UnregisterAll(fn ...func(cache Cache)) {
std.UnregisterAll(fn...)
func UnregisterAll(fn ...func(cache Cache)) int {
return std.UnregisterAll(fn...)
}
// SetDefName set default driver name.
@@ -124,6 +124,11 @@ func Driver(driverName string) Cache {
return std.Driver(driverName)
}
// Std get default cache manager instance
func Std() *Manager {
return std
}
// DefManager get default cache manager instance
func DefManager() *Manager {
return std
@@ -139,6 +144,11 @@ func Close() error {
return std.Close()
}
// ClearAll all drivers caches
func ClearAll() error {
return std.ClearAll()
}
/*************************************************************
* quick use by default cache driver
*************************************************************/

View File

@@ -49,15 +49,9 @@ func NewFileCache(dir string, pfxAndKey ...string) *FileCache {
return c
}
// Has cache key.
// TODO decode value, and check expire time
// Has cache key. will check expire time
func (c *FileCache) Has(key string) bool {
if c.MemoryCache.Has(key) {
return true
}
path := c.GetFilename(key)
return fileExists(path)
return c.get(key) != nil
}
// Get value by key
@@ -87,17 +81,16 @@ func (c *FileCache) get(key string) interface{} {
return nil
}
// check expire time
if item.Exp == 0 || item.Exp > time.Now().Unix() {
c.caches[key] = item // save to memory.
return item.Val
}
// has been expired. delete it.
// check expired
if item.Expired() {
c.SetLastErr(c.del(key))
return nil
}
c.caches[key] = item // save to memory.
return item.Val
}
// Set value by key
func (c *FileCache) Set(key string, val interface{}, ttl time.Duration) (err error) {
c.lock.Lock()
@@ -107,8 +100,8 @@ func (c *FileCache) Set(key string, val interface{}, ttl time.Duration) (err err
}
func (c *FileCache) set(key string, val interface{}, ttl time.Duration) (err error) {
if err = c.MemoryCache.set(key, val, ttl); err != nil {
c.SetLastErr(err)
err = c.MemoryCache.set(key, val, ttl)
if err != nil {
return
}
@@ -132,10 +125,7 @@ func (c *FileCache) set(key string, val interface{}, ttl time.Duration) (err err
}
defer f.Close()
if _, err = f.Write(bs); err != nil {
return err
}
_, err = f.Write(bs)
return
}
@@ -165,12 +155,12 @@ func (c *FileCache) GetMulti(keys []string) map[string]interface{} {
c.lock.RLock()
defer c.lock.RUnlock()
values := make(map[string]interface{}, len(keys))
data := make(map[string]interface{}, len(keys))
for _, key := range keys {
values[key] = c.get(key)
data[key] = c.get(key)
}
return values
return data
}
// SetMulti values by multi key

View File

@@ -5,16 +5,6 @@ import (
"time"
)
// MemoryCache definition.
type MemoryCache struct {
// locker
lock sync.RWMutex
// cache data in memory. or use sync.Map
caches map[string]*Item
// TODO set max cache number
MaxCacheNum int
}
// Item for memory cache
type Item struct {
// Exp expire time
@@ -23,9 +13,19 @@ type Item struct {
Val interface{}
}
// Invalid check whether expired
func (item Item) Invalid() bool {
return item.Exp != 0 && item.Exp < time.Now().Unix()
// Expired check whether expired
func (item Item) Expired() bool {
return item.Exp > 1 && item.Exp < time.Now().Unix()
}
// MemoryCache definition.
type MemoryCache struct {
// locker
lock sync.RWMutex
// cache data in memory. or use sync.Map
caches map[string]*Item
// CacheSize TODO set max cache size
CacheSize int
}
// NewMemoryCache create a memory cache instance
@@ -53,9 +53,8 @@ func (c *MemoryCache) Get(key string) interface{} {
func (c *MemoryCache) get(key string) interface{} {
if item, ok := c.caches[key]; ok {
// check expire time
// if has been expired, remove it.
if item.Invalid() {
// check expire time. if has been expired, remove it.
if item.Expired() {
_ = c.del(key)
}

View File

@@ -122,3 +122,33 @@ func TestFileCache_object(t *testing.T) {
// val2 := c.GetAs()
// dump.P("cache get:", val)
}
func TestDefManager(t *testing.T) {
is := assert.New(t)
num := cache.UnregisterAll()
is.Equal(0, num)
is.Equal(0, cache.Unregister("not_exist"))
cache.Register(cache.DvrMemory, cache.NewMemoryCache())
is.Equal(cache.DvrMemory, cache.Std().DefName())
key := "name"
// set
err := cache.Set(key, "cache value", cache.TwoMinutes)
is.NoError(err)
is.True(cache.Has(key))
// get
val := cache.Get(key)
is.Equal("cache value", val)
// del
is.NoError(cache.Del(key))
is.False(cache.Has(key))
is.NoError(cache.Clear())
num = cache.UnregisterAll()
is.GreaterOrEqual(1, num)
}

View File

@@ -17,7 +17,7 @@ func Example() {
cache.Register(goredis.Name, goredis.Connect("127.0.0.1:6379", "", 0))
// setting default driver name
cache.DefaultUse(cache.DvrRedis)
cache.DefaultUse(goredis.Name)
// quick use.(it is default driver)
//

View File

@@ -7,6 +7,9 @@ import (
"github.com/bluele/gcache"
)
// Name driver name
const Name = "gcache"
// GCache driver definition
type GCache struct {
// cache.BaseDriver

122
gcache/gcache_test.go Normal file
View File

@@ -0,0 +1,122 @@
package gcache_test
import (
"fmt"
"testing"
"time"
"github.com/gookit/cache"
"github.com/gookit/cache/gcache"
"github.com/gookit/goutil/dump"
"github.com/gookit/goutil/strutil"
"github.com/stretchr/testify/assert"
)
func Example() {
c := gcache.New(12)
key := "name"
// set
c.Set(key, "cache value", cache.Seconds2)
fmt.Println(c.Has(key))
// get
val := c.Get(key)
fmt.Println(val)
time.Sleep(2 * time.Second)
// get expired
val2 := c.Get(key)
fmt.Println(val2)
// del
c.Del(key)
fmt.Println(c.Has(key))
// Output:
// true
// cache value
// <nil>
// false
}
func ExampleGCache_in_cachePkg() {
cache.Register(gcache.Name, gcache.New(12))
defer cache.UnregisterAll()
key := "name1"
// set
cache.Set(key, "cache value", cache.Seconds2)
fmt.Println(cache.Has(key))
// get
val := cache.Get(key)
fmt.Println(val)
time.Sleep(2 * time.Second)
// get expired
val2 := cache.Get(key)
fmt.Println(val2)
// del
cache.Del(key)
fmt.Println(cache.Has(key))
// Output:
// true
// cache value
// <nil>
// false
}
func TestGCache_usage(t *testing.T) {
is := assert.New(t)
c := gcache.New(12)
defer c.Clear()
key := strutil.RandomCharsV2(12)
is.False(c.Has(key))
err := c.Set(key, "value", cache.Seconds3)
is.NoError(err)
is.True(c.Has(key))
val := c.Get(key)
is.Equal("value", val)
// del
err = c.Del(key)
is.NoError(err)
is.False(c.Has(key))
}
type user struct {
Age int
Name string
}
func TestGCache_object(t *testing.T) {
is := assert.New(t)
c := gcache.New(12)
defer c.Clear()
b1 := user {
Age: 1,
Name: "inhere",
}
key := strutil.RandomCharsV2(12)
dump.P("cache key: " + key)
is.False(c.Has(key))
err := c.Set(key, b1, cache.Seconds3)
is.NoError(err)
is.True(c.Has(key))
b2 := c.Get(key).(user)
dump.P(b2)
is.Equal("inhere", b2.Name)
}

View File

@@ -12,7 +12,7 @@ import (
"github.com/stretchr/testify/assert"
)
func ExampleGoCache() {
func Example() {
c := gocache.New()
key := "name"
@@ -41,7 +41,7 @@ func ExampleGoCache() {
// false
}
func ExampleNewGoCache_cachePkg() {
func ExampleGoCache_in_cachePkg() {
c1 := gocache.NewGoCache(cache.OneDay, cache.FiveMinutes)
cache.Register(gocache.Name, c1)
defer cache.UnregisterAll()

View File

@@ -7,6 +7,9 @@ import (
"github.com/syndtr/goleveldb/leveldb"
)
// Name driver name
const Name = "leveldb"
// LevelDB definition
type LevelDB struct {
// cache.BaseDriver

View File

@@ -43,13 +43,18 @@ func (m *Manager) Register(name string, driver Cache) *Manager {
}
// Unregister an cache driver
func (m *Manager) Unregister(name string) {
func (m *Manager) Unregister(name string) int {
if _, ok := m.drivers[name]; !ok {
return 0
}
delete(m.drivers, name)
// reset default driver name.
if m.defName == name {
m.defName = ""
}
return 1
}
// SetDefName set default driver name. alias of DefaultUse()
@@ -106,10 +111,20 @@ func (m *Manager) Close() (err error) {
return err
}
// UnregisterAll cache drivers
func (m *Manager) UnregisterAll(fn ...func(cache Cache)) {
m.defName = ""
// ClearAll all drivers caches
func (m *Manager) ClearAll() (err error) {
for _, cache := range m.drivers {
err = cache.Clear()
}
return err
}
// UnregisterAll cache drivers
func (m *Manager) UnregisterAll(fn ...func(cache Cache)) int {
num := len(m.drivers)
// unregister
m.defName = ""
for name, driver := range m.drivers {
if len(fn) > 0 {
fn[0](driver)
@@ -117,6 +132,7 @@ func (m *Manager) UnregisterAll(fn ...func(cache Cache)) {
delete(m.drivers, name)
}
return num
}
/*************************************************************

View File

@@ -8,6 +8,9 @@ import (
"github.com/gookit/cache"
)
// Name driver name
const Name = "memCached"
// MemCached definition
type MemCached struct {
cache.BaseDriver

View File

@@ -5,6 +5,9 @@ import (
"time"
)
// Name driver name
const Name = "nutsdb"
// NutsDB definition TODO
type NutsDB struct {
// cache.BaseDriver

View File

@@ -11,6 +11,7 @@ import (
"github.com/gookit/cache"
)
// Name driver name
const Name = "redigo"
// RedisCache fallback alias