123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524 |
- 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)
- }
- })
- }
- }
|