go-common/library/cache/memcache/conn_test.go
2019-04-22 18:49:16 +08:00

525 lines
11 KiB
Go

package memcache
import (
"bytes"
"encoding/json"
"errors"
test "go-common/library/cache/memcache/test"
"testing"
"time"
"github.com/bouk/monkey"
"github.com/gogo/protobuf/proto"
)
var s = []string{"test", "test1"}
var c Conn
var item = &Item{
Key: "test",
Value: []byte("test"),
Flags: FlagRAW,
Expiration: 60,
cas: 0,
}
var item2 = &Item{
Key: "test1",
Value: []byte("test"),
Flags: 0,
Expiration: 1000,
cas: 0,
}
var item3 = &Item{
Key: "test2",
Value: []byte("0"),
Flags: 0,
Expiration: 60,
cas: 0,
}
type TestItem struct {
Name string
Age int
}
func (t *TestItem) Compare(nt *TestItem) bool {
return t.Name == nt.Name && t.Age == nt.Age
}
func prepareEnv(t *testing.T) {
if c != nil {
return
}
var err error
cnop := DialConnectTimeout(time.Duration(2 * time.Second))
rdop := DialReadTimeout(time.Duration(2 * time.Second))
wrop := DialWriteTimeout(time.Duration(2 * time.Second))
c, err = Dial("tcp", testMemcacheAddr, cnop, rdop, wrop)
if err != nil {
t.Errorf("Dial() error(%v)", err)
t.FailNow()
}
c.Delete("test")
c.Delete("test1")
c.Delete("test2")
}
func TestRaw(t *testing.T) {
prepareEnv(t)
if err := c.Set(item); err != nil {
t.Errorf("conn.Store() error(%v)", err)
}
}
func TestAdd(t *testing.T) {
var (
key = "test_add"
item = &Item{
Key: key,
Value: []byte("0"),
Flags: 0,
Expiration: 60,
cas: 0,
}
)
prepareEnv(t)
c.Delete(key)
if err := c.Add(item); err != nil {
t.Errorf("c.Add() error(%v)", err)
}
if err := c.Add(item); err != ErrNotStored {
t.Errorf("c.Add() error(%v)", err)
}
}
func TestSetErr(t *testing.T) {
prepareEnv(t)
//set
st := &TestItem{Name: "jsongzip", Age: 10}
itemx := &Item{Key: "jsongzip", Object: st}
if err := c.Set(itemx); err != ErrItem {
t.Errorf("conn.Set() error(%v)", err)
}
}
func TestSetErr2(t *testing.T) {
prepareEnv(t)
//set
itemx := &Item{Key: "jsongzip", Flags: FlagJSON | FlagGzip}
if err := c.Set(itemx); err != ErrItem {
t.Errorf("conn.Set() error(%v)", err)
}
}
func TestSetErr3(t *testing.T) {
prepareEnv(t)
//set
itemx := &Item{Key: "jsongzip", Value: []byte("test"), Flags: FlagJSON}
if err := c.Set(itemx); err != ErrItem {
t.Errorf("conn.Set() error(%v)", err)
}
}
func TestJSONGzip(t *testing.T) {
prepareEnv(t)
//set
st := &TestItem{Name: "jsongzip", Age: 10}
itemx := &Item{Key: "jsongzip", Object: st, Flags: FlagJSON | FlagGzip}
if err := c.Set(itemx); err != nil {
t.Errorf("conn.Set() error(%v)", err)
}
if r, err := c.Get("jsongzip"); err != nil {
t.Errorf("conn.Get() error(%v)", err)
} else {
var nst TestItem
scanAndCompare(t, r, st, &nst)
}
}
func TestJSON(t *testing.T) {
prepareEnv(t)
st := &TestItem{Name: "json", Age: 10}
itemx := &Item{Key: "json", Object: st, Flags: FlagJSON}
if err := c.Set(itemx); err != nil {
t.Errorf("conn.Set() error(%v)", err)
}
if r, err := c.Get("json"); err != nil {
t.Errorf("conn.Get() error(%v)", err)
} else {
var nst TestItem
scanAndCompare(t, r, st, &nst)
}
}
func BenchmarkJSON(b *testing.B) {
st := &TestItem{Name: "json", Age: 10}
itemx := &Item{Key: "json", Object: st, Flags: FlagJSON}
var (
eb bytes.Buffer
je *json.Encoder
ir bytes.Reader
jd *json.Decoder
jr reader
nst test.TestItem
)
jd = json.NewDecoder(&jr)
je = json.NewEncoder(&eb)
eb.Grow(_encodeBuf)
// NOTE reuse bytes.Buffer internal buf
// DON'T concurrency call Scan
b.ResetTimer()
for i := 0; i < b.N; i++ {
eb.Reset()
if err := je.Encode(itemx.Object); err != nil {
return
}
data := eb.Bytes()
ir.Reset(data)
jr.Reset(&ir)
jd.Decode(&nst)
}
}
func BenchmarkProtobuf(b *testing.B) {
st := &test.TestItem{Name: "protobuf", Age: 10}
itemx := &Item{Key: "protobuf", Object: st, Flags: FlagJSON}
var (
eb bytes.Buffer
nst test.TestItem
ped *proto.Buffer
)
ped = proto.NewBuffer(eb.Bytes())
eb.Grow(_encodeBuf)
b.ResetTimer()
for i := 0; i < b.N; i++ {
ped.Reset()
pb, ok := itemx.Object.(proto.Message)
if !ok {
return
}
if err := ped.Marshal(pb); err != nil {
return
}
data := ped.Bytes()
ped.SetBuf(data)
ped.Unmarshal(&nst)
}
}
func TestGob(t *testing.T) {
prepareEnv(t)
st := &TestItem{Name: "gob", Age: 10}
itemx := &Item{Key: "gob", Object: st, Flags: FlagGOB}
if err := c.Set(itemx); err != nil {
t.Errorf("conn.Set() error(%v)", err)
}
if r, err := c.Get("gob"); err != nil {
t.Errorf("conn.Get() error(%v)", err)
} else {
var nst TestItem
scanAndCompare(t, r, st, &nst)
}
}
func TestGobGzip(t *testing.T) {
prepareEnv(t)
st := &TestItem{Name: "gobgzip", Age: 10}
itemx := &Item{Key: "gobgzip", Object: st, Flags: FlagGOB | FlagGzip}
if err := c.Set(itemx); err != nil {
t.Errorf("conn.Set() error(%v)", err)
}
if r, err := c.Get("gobgzip"); err != nil {
t.Errorf("conn.Get() error(%v)", err)
} else {
var nst TestItem
scanAndCompare(t, r, st, &nst)
}
}
func TestGzip(t *testing.T) {
prepareEnv(t)
st := &TestItem{Name: "gzip", Age: 123}
itemx := &Item{Key: "gzip", Object: st, Flags: FlagGOB | FlagGzip}
if err := c.Set(itemx); err != nil {
t.Errorf("conn.Set() error(%v)", err)
}
if r, err := c.Get("gzip"); err != nil {
t.Errorf("conn.Get() error(%v)", err)
} else {
var nst TestItem
scanAndCompare(t, r, st, &nst)
}
}
func TestProtobuf(t *testing.T) {
prepareEnv(t)
var (
err error
// value []byte
r *Item
nst test.TestItem
)
st := &test.TestItem{Name: "proto", Age: 3021}
itemx := &Item{Key: "proto", Object: st, Flags: FlagProtobuf}
if err = c.Set(itemx); err != nil {
t.Errorf("conn.Set() error(%v)", err)
}
if r, err = c.Get("proto"); err != nil {
t.Errorf("conn.Get() error(%v)", err)
}
if err = c.Scan(r, &nst); err != nil {
t.Errorf("decode() error(%v)", err)
t.FailNow()
} else {
scanAndCompare2(t, r, st, &nst)
}
}
func TestProtobufGzip(t *testing.T) {
prepareEnv(t)
var (
err error
// value []byte
r *Item
nst test.TestItem
)
st := &test.TestItem{Name: "protogzip", Age: 3021}
itemx := &Item{Key: "protogzip", Object: st, Flags: FlagProtobuf | FlagGzip}
if err = c.Set(itemx); err != nil {
t.Errorf("conn.Set() error(%v)", err)
}
if r, err = c.Get("protogzip"); err != nil {
t.Errorf("conn.Get() error(%v)", err)
}
if err = c.Scan(r, &nst); err != nil {
t.Errorf("decode() error(%v)", err)
t.FailNow()
} else {
scanAndCompare2(t, r, st, &nst)
}
}
func TestGet(t *testing.T) {
prepareEnv(t)
// get
if r, err := c.Get("test"); err != nil {
t.Errorf("conn.Get() error(%v)", err)
} else if r.Key != "test" || !bytes.Equal(r.Value, []byte("test")) || r.Flags != 0 {
t.Error("conn.Get() error, value")
}
}
func TestGetHasErr(t *testing.T) {
prepareEnv(t)
st := &TestItem{Name: "json", Age: 10}
itemx := &Item{Key: "test", Object: st, Flags: FlagJSON}
c.Set(itemx)
expected := errors.New("some error")
monkey.Patch(scanGetReply, func(line []byte, item *Item) (size int, err error) {
return 0, expected
})
if _, err := c.Get("test"); err.Error() != expected.Error() {
t.Errorf("conn.Get() unexpected error(%v)", err)
}
if err := c.(*conn).err; err.Error() != expected.Error() {
t.Errorf("unexpected error(%v)", err)
}
}
func TestGet2(t *testing.T) {
prepareEnv(t)
// get not exist
if _, err := c.Get("not_exist"); err != ErrNotFound {
t.Errorf("conn.Get() error(%v)", err)
}
}
func TestGetMulti(t *testing.T) {
prepareEnv(t)
// getMulti
if _, err := c.GetMulti(s); err != nil {
t.Errorf("conn.GetMulti() error(%v)", err)
}
}
func TestGetMulti2(t *testing.T) {
prepareEnv(t)
//set
if err := c.Set(item); err != nil {
t.Errorf("conn.Set() error(%v)", err)
}
if err := c.Set(item2); err != nil {
t.Errorf("conn.Set() error(%v)", err)
}
if res, err := c.GetMulti(s); err != nil {
t.Errorf("conn.Get() error(%v)", err)
} else {
if len(res) != 2 {
t.Error("conn.Get() error, length", len(res))
}
reply := res["test"]
compareItem2(t, reply, item)
reply = res["test1"]
compareItem2(t, reply, item2)
}
}
func TestIncrement(t *testing.T) {
// set
if err := c.Set(item3); err != nil {
t.Errorf("conn.Set() error(%v)", err)
}
// incr
if d, err := c.Increment("test2", 4); err != nil {
t.Errorf("conn.Set() error(%v)", err)
} else {
if d != 4 {
t.Error("conn.IncrDecr value error")
}
}
}
func TestDecrement(t *testing.T) {
// decr
if d, err := c.Decrement("test2", 3); err != nil {
t.Errorf("conn.Store() error(%v)", err)
} else {
if d != 1 {
t.Error("conn.IncrDecr value error", d)
}
}
}
func TestTouch(t *testing.T) {
// touch
if err := c.Touch("test2", 1); err != nil {
t.Errorf("conn.Touch error(%v)", err)
}
}
func TestCompareAndSwap(t *testing.T) {
prepareEnv(t)
if err := c.Set(item3); err != nil {
t.Errorf("conn.Set() error(%v)", err)
}
//cas
if r, err := c.Get("test2"); err != nil {
t.Errorf("conn.Get() error(%v)", err)
} else {
r.Value = []byte("fuck")
if err := c.CompareAndSwap(r); err != nil {
t.Errorf("conn.CompareAndSwap() error(%v)", err)
}
if r, err := c.Get("test2"); err != nil {
t.Errorf("conn.Get() error(%v)", err)
} else {
itemx := &Item{Key: "test2", Value: []byte("fuck"), Flags: 0}
compareItem2(t, r, itemx)
}
}
}
func TestReplace(t *testing.T) {
prepareEnv(t)
if err := c.Set(item); err != nil {
t.Errorf("conn.Set() error(%v)", err)
}
if r, err := c.Get("test"); err != nil {
t.Errorf("conn.Get() error(%v)", err)
} else {
r.Value = []byte("go")
if err := c.Replace(r); err != nil {
t.Errorf("conn.CompareAndSwap() error(%v)", err)
}
if r, err := c.Get("test"); err != nil {
t.Errorf("conn.Get() error(%v)", err)
} else {
itemx := &Item{Key: "test", Value: []byte("go"), Flags: 0}
compareItem2(t, r, itemx)
}
}
}
func scanAndCompare(t *testing.T, item *Item, st *TestItem, nst *TestItem) {
if err := c.Scan(item, nst); err != nil {
t.Errorf("decode() error(%v)", err)
t.FailNow()
}
if !st.Compare(nst) {
t.Errorf("st: %v, use of closed network connection nst: %v", st, &nst)
t.FailNow()
}
}
func scanAndCompare2(t *testing.T, item *Item, st *test.TestItem, nst *test.TestItem) {
if err := c.Scan(item, nst); err != nil {
t.Errorf("decode() error(%v)", err)
t.FailNow()
}
if st.Age != nst.Age || st.Name != nst.Name {
t.Errorf("st: %v, use of closed network connection nst: %v", st, &nst)
t.FailNow()
}
}
func compareItem2(t *testing.T, r, item *Item) {
if r.Key != item.Key || !bytes.Equal(r.Value, item.Value) || r.Flags != item.Flags {
t.Error("conn.Get() error, value")
}
}
func Test_legalKey(t *testing.T) {
type args struct {
key string
}
tests := []struct {
name string
args args
want bool
}{
{
name: "test empty key",
want: false,
},
{
name: "test too large key",
args: args{func() string {
var data []byte
for i := 0; i < 255; i++ {
data = append(data, 'k')
}
return string(data)
}()},
want: false,
},
{
name: "test invalid char",
args: args{"hello world"},
want: false,
},
{
name: "test invalid char",
args: args{string([]byte{0x7f})},
want: false,
},
{
name: "test normal key",
args: args{"hello"},
want: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := legalKey(tt.args.key); got != tt.want {
t.Errorf("legalKey() = %v, want %v", got, tt.want)
}
})
}
}