This commit is contained in:
84
test/helpers.go
Normal file
84
test/helpers.go
Normal file
@@ -0,0 +1,84 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
gom "github.com/bradfitz/gomemcache/memcache"
|
||||
"github.com/cockroachdb/pebble"
|
||||
"github.com/dgraph-io/ristretto"
|
||||
redigo "github.com/gomodule/redigo/redis"
|
||||
"gitoa.ru/go-4devs/cache/provider/redis"
|
||||
)
|
||||
|
||||
// RedisClient created redis client.
|
||||
func RedisClient() func(ctx context.Context) (redis.Conn, error) {
|
||||
host, ok := os.LookupEnv("FDEVS_CACHE_REDIS_HOST")
|
||||
if !ok {
|
||||
host = ":6379"
|
||||
}
|
||||
|
||||
client := &redigo.Pool{
|
||||
DialContext: func(ctx context.Context) (redigo.Conn, error) {
|
||||
return redigo.DialContext(ctx, "tcp", host)
|
||||
},
|
||||
}
|
||||
|
||||
return redis.NewPool(client)
|
||||
}
|
||||
|
||||
// MemcacheClient created memcached client.
|
||||
func MemcacheClient() *gom.Client {
|
||||
host, ok := os.LookupEnv("FDEVS_CACHE_MEMCACHE_HOST")
|
||||
if !ok {
|
||||
host = "localhost:11211"
|
||||
}
|
||||
|
||||
return gom.New(host)
|
||||
}
|
||||
|
||||
// RistrettoClient creates ristretto client.
|
||||
func RistrettoClient() *ristretto.Cache {
|
||||
cache, _ := ristretto.NewCache(&ristretto.Config{
|
||||
NumCounters: 1e7, // number of keys to track frequency of (10M).
|
||||
MaxCost: 1 << 30, // maximum cost of cache (1GB).
|
||||
BufferItems: 64, // number of keys per Get buffer.
|
||||
})
|
||||
|
||||
return cache
|
||||
}
|
||||
|
||||
// PebbleDB creates pebble DB.
|
||||
func PebbleDB() (*pebble.DB, func()) {
|
||||
path := "demo.test"
|
||||
if _, filename, _, ok := runtime.Caller(0); ok {
|
||||
path = filepath.Dir(filename) + "/" + path
|
||||
}
|
||||
|
||||
db, _ := pebble.Open(path, &pebble.Options{})
|
||||
|
||||
return db, func() {
|
||||
os.RemoveAll(path)
|
||||
}
|
||||
}
|
||||
|
||||
// User tested user data.
|
||||
type User struct {
|
||||
ID int
|
||||
Name string
|
||||
UpdateAt time.Time
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
// NewUser create mocks data user.
|
||||
func NewUser(id int) User {
|
||||
return User{
|
||||
ID: id,
|
||||
Name: "andrey",
|
||||
UpdateAt: time.Date(2020, 2, 1, 1, 2, 3, 4, time.UTC),
|
||||
CreatedAt: time.Date(1999, 2, 1, 1, 2, 3, 4, time.UTC),
|
||||
}
|
||||
}
|
||||
57
test/provider.go
Normal file
57
test/provider.go
Normal file
@@ -0,0 +1,57 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"gitoa.ru/go-4devs/cache"
|
||||
)
|
||||
|
||||
var _ cache.Provider = NewProviderMock(&testing.T{})
|
||||
|
||||
// OptionMock configure mock.
|
||||
type OptionMock func(*ProviderMock)
|
||||
|
||||
// WithDelete sets delete method.
|
||||
func WithDelete(f func(t *testing.T) func(ctx context.Context, item *cache.Item) error) OptionMock {
|
||||
return func(pm *ProviderMock) { pm.operations[cache.OperationDelete] = f }
|
||||
}
|
||||
|
||||
// WithGet sets get method.
|
||||
func WithGet(f func(t *testing.T) func(ctx context.Context, item *cache.Item) error) OptionMock {
|
||||
return func(pm *ProviderMock) { pm.operations[cache.OperationGet] = f }
|
||||
}
|
||||
|
||||
// WithSet sets set method.
|
||||
func WithSet(f func(t *testing.T) func(ctx context.Context, item *cache.Item) error) OptionMock {
|
||||
return func(pm *ProviderMock) { pm.operations[cache.OperationSet] = f }
|
||||
}
|
||||
|
||||
// NewProviderMock create new mock provider.
|
||||
func NewProviderMock(t *testing.T, opts ...OptionMock) cache.Provider {
|
||||
t.Helper()
|
||||
|
||||
pm := &ProviderMock{
|
||||
t: t,
|
||||
operations: make(map[string]func(t *testing.T) func(ctx context.Context, item *cache.Item) error, 3),
|
||||
}
|
||||
|
||||
for _, o := range opts {
|
||||
o(pm)
|
||||
}
|
||||
|
||||
return func(ctx context.Context, operation string, item *cache.Item) error {
|
||||
if m, ok := pm.operations[operation]; ok {
|
||||
return m(pm.t)(ctx, item)
|
||||
}
|
||||
|
||||
return fmt.Errorf("%w: %s", cache.ErrOperationNotAllwed, operation)
|
||||
}
|
||||
}
|
||||
|
||||
// ProviderMock mock.
|
||||
type ProviderMock struct {
|
||||
t *testing.T
|
||||
operations map[string]func(t *testing.T) func(ctx context.Context, item *cache.Item) error
|
||||
}
|
||||
133
test/sute.go
Normal file
133
test/sute.go
Normal file
@@ -0,0 +1,133 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"gitoa.ru/go-4devs/cache"
|
||||
)
|
||||
|
||||
const (
|
||||
expire = time.Second
|
||||
waitExpire = expire * 2
|
||||
)
|
||||
|
||||
// Option configure sute.
|
||||
type Option func(*ProviderSuite)
|
||||
|
||||
// WithExpire sets expired errors.
|
||||
func WithExpire(err error) Option {
|
||||
return func(ps *ProviderSuite) { ps.expire = err }
|
||||
}
|
||||
|
||||
func WithWaitGet(f func()) Option {
|
||||
return func(ps *ProviderSuite) { ps.waitGet = f }
|
||||
}
|
||||
|
||||
// RunSute run test by provider.
|
||||
func RunSute(t *testing.T, provider cache.Provider, opts ...Option) {
|
||||
t.Helper()
|
||||
|
||||
cs := &ProviderSuite{
|
||||
provider: provider,
|
||||
expire: cache.ErrCacheExpired,
|
||||
waitGet: func() {},
|
||||
}
|
||||
|
||||
for _, o := range opts {
|
||||
o(cs)
|
||||
}
|
||||
|
||||
suite.Run(t, cs)
|
||||
}
|
||||
|
||||
// ProviderSuite for testing providers.
|
||||
type ProviderSuite struct {
|
||||
provider cache.Provider
|
||||
expire error
|
||||
waitGet func()
|
||||
suite.Suite
|
||||
}
|
||||
|
||||
// TestGet tested get.
|
||||
func (s *ProviderSuite) TestGet() {
|
||||
s.T().Parallel()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
var val string
|
||||
|
||||
require.Nil(s.T(), s.provider(ctx, cache.OperationSet, cache.NewItem("get", "some value")))
|
||||
s.waitGet()
|
||||
require.Nil(s.T(), s.provider(ctx, cache.OperationGet, cache.NewItem("get", &val)))
|
||||
require.Equal(s.T(), "some value", val)
|
||||
|
||||
var user User
|
||||
|
||||
cachedUser := NewUser(1)
|
||||
|
||||
require.Nil(s.T(), s.provider(ctx, cache.OperationSet, cache.NewItem("get_user", cachedUser)))
|
||||
s.waitGet()
|
||||
require.Nil(s.T(), s.provider(ctx, cache.OperationGet, cache.NewItem("get_user", &user)))
|
||||
require.Equal(s.T(), cachedUser, user)
|
||||
}
|
||||
|
||||
// TestCacheMiss tested cache miss error.
|
||||
func (s *ProviderSuite) TestCacheMiss() {
|
||||
s.T().Parallel()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
require.True(s.T(),
|
||||
errors.Is(s.provider(ctx, cache.OperationGet, cache.NewItem("cache_miss", nil)), cache.ErrCacheMiss),
|
||||
"failed expect errors",
|
||||
)
|
||||
}
|
||||
|
||||
// TestExpired tested error expired.
|
||||
func (s *ProviderSuite) TestExpired() {
|
||||
s.T().Parallel()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
var val string
|
||||
|
||||
require.Nil(s.T(), s.provider(ctx, cache.OperationSet, cache.NewItem("expired", "some value", cache.WithTTL(expire))))
|
||||
time.Sleep(waitExpire)
|
||||
|
||||
err := s.provider(ctx, cache.OperationGet, cache.NewItem("expired", nil))
|
||||
require.Truef(s.T(), errors.Is(err, s.expire), "failed expired error got:%s", err)
|
||||
require.Equal(s.T(), "", val)
|
||||
}
|
||||
|
||||
// TestTTL tested set ttl.
|
||||
func (s *ProviderSuite) TestTTL() {
|
||||
s.T().Parallel()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
var val string
|
||||
|
||||
require.Nil(s.T(), s.provider(ctx, cache.OperationSet, cache.NewItem("ttl", "some ttl value", cache.WithTTL(time.Hour))))
|
||||
s.waitGet()
|
||||
require.Nil(s.T(), s.provider(ctx, cache.OperationGet, cache.NewItem("ttl", &val)))
|
||||
require.Equal(s.T(), "some ttl value", val)
|
||||
}
|
||||
|
||||
// TestDelete tested delete method.
|
||||
func (s *ProviderSuite) TestDelete() {
|
||||
s.T().Parallel()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
require.Nil(s.T(), s.provider(ctx, cache.OperationSet, cache.NewItem("delete:key", "some delete value")))
|
||||
require.Nil(s.T(), s.provider(ctx, cache.OperationDelete, cache.NewItem("delete:key", nil)))
|
||||
require.True(s.T(),
|
||||
errors.Is(s.provider(ctx, cache.OperationGet, cache.NewItem("cache_miss", nil)), cache.ErrCacheMiss),
|
||||
"failed delete errors",
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user