You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
570 lines
10 KiB
570 lines
10 KiB
6 years ago
|
package memcache
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"strconv"
|
||
|
"strings"
|
||
|
|
||
|
"testing"
|
||
|
)
|
||
|
|
||
|
func TestASCIIConnAdd(t *testing.T) {
|
||
|
tests := []struct {
|
||
|
name string
|
||
|
a *Item
|
||
|
e error
|
||
|
}{
|
||
|
{
|
||
|
"Add",
|
||
|
&Item{
|
||
|
Key: "test_add",
|
||
|
Value: []byte("0"),
|
||
|
Flags: 0,
|
||
|
Expiration: 60,
|
||
|
},
|
||
|
nil,
|
||
|
},
|
||
|
{
|
||
|
"Add_Large",
|
||
|
&Item{
|
||
|
Key: "test_add_large",
|
||
|
Value: bytes.Repeat(space, _largeValue+1),
|
||
|
Flags: 0,
|
||
|
Expiration: 60,
|
||
|
},
|
||
|
nil,
|
||
|
},
|
||
|
{
|
||
|
"Add_Exist",
|
||
|
&Item{
|
||
|
Key: "test_add",
|
||
|
Value: []byte("0"),
|
||
|
Flags: 0,
|
||
|
Expiration: 60,
|
||
|
},
|
||
|
ErrNotStored,
|
||
|
},
|
||
|
}
|
||
|
for _, test := range tests {
|
||
|
t.Run(test.name, func(t *testing.T) {
|
||
|
if err := testConnASCII.Add(test.a); err != test.e {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
if b, err := testConnASCII.Get(test.a.Key); err != nil {
|
||
|
t.Fatal(err)
|
||
|
} else {
|
||
|
compareItem(t, test.a, b)
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestASCIIConnGet(t *testing.T) {
|
||
|
tests := []struct {
|
||
|
name string
|
||
|
a *Item
|
||
|
k string
|
||
|
e error
|
||
|
}{
|
||
|
{
|
||
|
"Get",
|
||
|
&Item{
|
||
|
Key: "test_get",
|
||
|
Value: []byte("0"),
|
||
|
Flags: 0,
|
||
|
Expiration: 60,
|
||
|
},
|
||
|
"test_get",
|
||
|
nil,
|
||
|
},
|
||
|
{
|
||
|
"Get_NotExist",
|
||
|
&Item{
|
||
|
Key: "test_get_not_exist",
|
||
|
Value: []byte("0"),
|
||
|
Flags: 0,
|
||
|
Expiration: 60,
|
||
|
},
|
||
|
"test_get_not_exist!",
|
||
|
ErrNotFound,
|
||
|
},
|
||
|
}
|
||
|
for _, test := range tests {
|
||
|
t.Run(test.name, func(t *testing.T) {
|
||
|
if err := testConnASCII.Add(test.a); err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
if b, err := testConnASCII.Get(test.a.Key); err != nil {
|
||
|
t.Fatal(err)
|
||
|
} else {
|
||
|
compareItem(t, test.a, b)
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//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.(*asciiConn).err; err.Error() != expected.Error() {
|
||
|
// t.Errorf("unexpected error(%v)", err)
|
||
|
// }
|
||
|
//}
|
||
|
|
||
|
func TestASCIIConnGetMulti(t *testing.T) {
|
||
|
tests := []struct {
|
||
|
name string
|
||
|
a []*Item
|
||
|
k []string
|
||
|
e error
|
||
|
}{
|
||
|
{"getMulti_Add",
|
||
|
[]*Item{
|
||
|
{
|
||
|
Key: "get_multi_1",
|
||
|
Value: []byte("test"),
|
||
|
Flags: FlagRAW,
|
||
|
Expiration: 60,
|
||
|
cas: 0,
|
||
|
},
|
||
|
{
|
||
|
Key: "get_multi_2",
|
||
|
Value: []byte("test2"),
|
||
|
Flags: FlagRAW,
|
||
|
Expiration: 60,
|
||
|
cas: 0,
|
||
|
},
|
||
|
},
|
||
|
[]string{"get_multi_1", "get_multi_2"},
|
||
|
nil,
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for _, test := range tests {
|
||
|
t.Run(test.name, func(t *testing.T) {
|
||
|
for _, i := range test.a {
|
||
|
if err := testConnASCII.Set(i); err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
}
|
||
|
if r, err := testConnASCII.GetMulti(test.k); err != nil {
|
||
|
t.Fatal(err)
|
||
|
} else {
|
||
|
reply := r["get_multi_1"]
|
||
|
compareItem(t, reply, test.a[0])
|
||
|
reply = r["get_multi_2"]
|
||
|
compareItem(t, reply, test.a[1])
|
||
|
}
|
||
|
|
||
|
})
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
func TestASCIIConnSet(t *testing.T) {
|
||
|
tests := []struct {
|
||
|
name string
|
||
|
a *Item
|
||
|
e error
|
||
|
}{
|
||
|
{
|
||
|
"SetLowerBound",
|
||
|
&Item{
|
||
|
Key: strings.Repeat("a", 1),
|
||
|
Value: []byte("4"),
|
||
|
Flags: 0,
|
||
|
Expiration: 60,
|
||
|
},
|
||
|
nil,
|
||
|
},
|
||
|
{
|
||
|
"SetUpperBound",
|
||
|
&Item{
|
||
|
Key: strings.Repeat("a", 250),
|
||
|
Value: []byte("3"),
|
||
|
Flags: 0,
|
||
|
Expiration: 60,
|
||
|
},
|
||
|
nil,
|
||
|
},
|
||
|
{
|
||
|
"SetIllegalKeyZeroLength",
|
||
|
&Item{
|
||
|
Key: "",
|
||
|
Value: []byte("2"),
|
||
|
Flags: 0,
|
||
|
Expiration: 60,
|
||
|
},
|
||
|
ErrMalformedKey,
|
||
|
},
|
||
|
{
|
||
|
"SetIllegalKeyLengthExceededLimit",
|
||
|
&Item{
|
||
|
Key: " ",
|
||
|
Value: []byte("1"),
|
||
|
Flags: 0,
|
||
|
Expiration: 60,
|
||
|
},
|
||
|
ErrMalformedKey,
|
||
|
},
|
||
|
{
|
||
|
"SeJsonItem",
|
||
|
&Item{
|
||
|
Key: "set_obj",
|
||
|
Object: &struct {
|
||
|
Name string
|
||
|
Age int
|
||
|
}{"json", 10},
|
||
|
Expiration: 60,
|
||
|
Flags: FlagJSON,
|
||
|
},
|
||
|
nil,
|
||
|
},
|
||
|
{
|
||
|
"SeErrItemJSONGzip",
|
||
|
&Item{
|
||
|
Key: "set_err_item",
|
||
|
Expiration: 60,
|
||
|
Flags: FlagJSON | FlagGzip,
|
||
|
},
|
||
|
ErrItem,
|
||
|
},
|
||
|
{
|
||
|
"SeErrItemBytesValueWrongFlag",
|
||
|
&Item{
|
||
|
Key: "set_err_item",
|
||
|
Value: []byte("2"),
|
||
|
Expiration: 60,
|
||
|
Flags: FlagJSON,
|
||
|
},
|
||
|
ErrItem,
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for _, test := range tests {
|
||
|
t.Run(test.name, func(t *testing.T) {
|
||
|
if err := testConnASCII.Set(test.a); err != test.e {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestASCIIConnCompareAndSwap(t *testing.T) {
|
||
|
tests := []struct {
|
||
|
name string
|
||
|
a *Item
|
||
|
b *Item
|
||
|
c *Item
|
||
|
k string
|
||
|
e error
|
||
|
}{
|
||
|
{
|
||
|
"CompareAndSwap",
|
||
|
&Item{
|
||
|
Key: "test_cas",
|
||
|
Value: []byte("2"),
|
||
|
Flags: 0,
|
||
|
Expiration: 60,
|
||
|
},
|
||
|
nil,
|
||
|
&Item{
|
||
|
Key: "test_cas",
|
||
|
Value: []byte("3"),
|
||
|
Flags: 0,
|
||
|
Expiration: 60,
|
||
|
},
|
||
|
"test_cas",
|
||
|
nil,
|
||
|
},
|
||
|
{
|
||
|
"CompareAndSwapErrCASConflict",
|
||
|
&Item{
|
||
|
Key: "test_cas_conflict",
|
||
|
Value: []byte("2"),
|
||
|
Flags: 0,
|
||
|
Expiration: 60,
|
||
|
},
|
||
|
&Item{
|
||
|
Key: "test_cas_conflict",
|
||
|
Value: []byte("1"),
|
||
|
Flags: 0,
|
||
|
Expiration: 60,
|
||
|
},
|
||
|
&Item{
|
||
|
Key: "test_cas_conflict",
|
||
|
Value: []byte("3"),
|
||
|
Flags: 0,
|
||
|
Expiration: 60,
|
||
|
},
|
||
|
"test_cas_conflict",
|
||
|
ErrCASConflict,
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for _, test := range tests {
|
||
|
t.Run(test.name, func(t *testing.T) {
|
||
|
if err := testConnASCII.Set(test.a); err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
r, err := testConnASCII.Get(test.k)
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
|
||
|
if test.b != nil {
|
||
|
if err := testConnASCII.Set(test.b); err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
r.Value = test.c.Value
|
||
|
if err := testConnASCII.CompareAndSwap(r); err != nil {
|
||
|
if err != test.e {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
} else {
|
||
|
if fr, err := testConnASCII.Get(test.k); err != nil {
|
||
|
t.Fatal(err)
|
||
|
} else {
|
||
|
compareItem(t, fr, test.c)
|
||
|
}
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
|
||
|
t.Run("TestCompareAndSwapErrNotFound", func(t *testing.T) {
|
||
|
ti := &Item{
|
||
|
Key: "test_cas_notfound",
|
||
|
Value: []byte("2"),
|
||
|
Flags: 0,
|
||
|
Expiration: 60,
|
||
|
}
|
||
|
if err := testConnASCII.Set(ti); err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
r, err := testConnASCII.Get(ti.Key)
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
|
||
|
r.Key = "test_cas_notfound_boom"
|
||
|
r.Value = []byte("3")
|
||
|
if err := testConnASCII.CompareAndSwap(r); err != nil {
|
||
|
if err != ErrNotFound {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func TestASCIIConnReplace(t *testing.T) {
|
||
|
tests := []struct {
|
||
|
name string
|
||
|
a *Item
|
||
|
b *Item
|
||
|
e error
|
||
|
}{
|
||
|
{
|
||
|
"TestReplace",
|
||
|
&Item{
|
||
|
Key: "test_replace",
|
||
|
Value: []byte("2"),
|
||
|
Flags: 0,
|
||
|
Expiration: 60,
|
||
|
},
|
||
|
&Item{
|
||
|
Key: "test_replace",
|
||
|
Value: []byte("3"),
|
||
|
Flags: 0,
|
||
|
Expiration: 60,
|
||
|
},
|
||
|
nil,
|
||
|
},
|
||
|
{
|
||
|
"TestReplaceErrNotStored",
|
||
|
&Item{
|
||
|
Key: "test_replace_not_stored",
|
||
|
Value: []byte("2"),
|
||
|
Flags: 0,
|
||
|
Expiration: 60,
|
||
|
},
|
||
|
&Item{
|
||
|
Key: "test_replace_not_stored_boom",
|
||
|
Value: []byte("3"),
|
||
|
Flags: 0,
|
||
|
Expiration: 60,
|
||
|
},
|
||
|
ErrNotStored,
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for _, test := range tests {
|
||
|
t.Run(test.name, func(t *testing.T) {
|
||
|
if err := testConnASCII.Set(test.a); err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
if err := testConnASCII.Replace(test.b); err != nil {
|
||
|
if err == test.e {
|
||
|
return
|
||
|
}
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
if r, err := testConnASCII.Get(test.b.Key); err != nil {
|
||
|
t.Fatal(err)
|
||
|
} else {
|
||
|
compareItem(t, r, test.b)
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestASCIIConnIncrDecr(t *testing.T) {
|
||
|
tests := []struct {
|
||
|
fn func(key string, delta uint64) (uint64, error)
|
||
|
name string
|
||
|
k string
|
||
|
v uint64
|
||
|
w uint64
|
||
|
}{
|
||
|
{
|
||
|
testConnASCII.Increment,
|
||
|
"Incr_10",
|
||
|
"test_incr",
|
||
|
10,
|
||
|
10,
|
||
|
},
|
||
|
{
|
||
|
testConnASCII.Increment,
|
||
|
"Incr_10(2)",
|
||
|
"test_incr",
|
||
|
10,
|
||
|
20,
|
||
|
},
|
||
|
{
|
||
|
testConnASCII.Decrement,
|
||
|
"Decr_10",
|
||
|
"test_incr",
|
||
|
10,
|
||
|
10,
|
||
|
},
|
||
|
}
|
||
|
if err := testConnASCII.Add(&Item{
|
||
|
Key: "test_incr",
|
||
|
Value: []byte("0"),
|
||
|
}); err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
for _, test := range tests {
|
||
|
t.Run(test.name, func(t *testing.T) {
|
||
|
if a, err := test.fn(test.k, test.v); err != nil {
|
||
|
t.Fatal(err)
|
||
|
} else {
|
||
|
if a != test.w {
|
||
|
t.Fatalf("want %d, got %d", test.w, a)
|
||
|
}
|
||
|
}
|
||
|
if b, err := testConnASCII.Get(test.k); err != nil {
|
||
|
t.Fatal(err)
|
||
|
} else {
|
||
|
if string(b.Value) != strconv.FormatUint(test.w, 10) {
|
||
|
t.Fatalf("want %s, got %d", b.Value, test.w)
|
||
|
}
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestASCIIConnTouch(t *testing.T) {
|
||
|
tests := []struct {
|
||
|
name string
|
||
|
k string
|
||
|
a *Item
|
||
|
e error
|
||
|
}{
|
||
|
{
|
||
|
"Touch",
|
||
|
"test_touch",
|
||
|
&Item{
|
||
|
Key: "test_touch",
|
||
|
Value: []byte("0"),
|
||
|
Expiration: 60,
|
||
|
},
|
||
|
nil,
|
||
|
},
|
||
|
{
|
||
|
"Touch_NotExist",
|
||
|
"test_touch_not_exist",
|
||
|
nil,
|
||
|
ErrNotFound,
|
||
|
},
|
||
|
}
|
||
|
for _, test := range tests {
|
||
|
if test.a != nil {
|
||
|
if err := testConnASCII.Add(test.a); err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
if err := testConnASCII.Touch(test.k, 1); err != test.e {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestASCIIConnDelete(t *testing.T) {
|
||
|
tests := []struct {
|
||
|
name string
|
||
|
k string
|
||
|
a *Item
|
||
|
e error
|
||
|
}{
|
||
|
{
|
||
|
"Delete",
|
||
|
"test_delete",
|
||
|
&Item{
|
||
|
Key: "test_delete",
|
||
|
Value: []byte("0"),
|
||
|
Expiration: 60,
|
||
|
},
|
||
|
nil,
|
||
|
},
|
||
|
{
|
||
|
"Delete_NotExist",
|
||
|
"test_delete_not_exist",
|
||
|
nil,
|
||
|
ErrNotFound,
|
||
|
},
|
||
|
}
|
||
|
for _, test := range tests {
|
||
|
if test.a != nil {
|
||
|
if err := testConnASCII.Add(test.a); err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
if err := testConnASCII.Delete(test.k); err != test.e {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
if _, err := testConnASCII.Get(test.k); err != ErrNotFound {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func compareItem(t *testing.T, a, b *Item) {
|
||
|
if a.Key != b.Key || !bytes.Equal(a.Value, b.Value) || a.Flags != b.Flags {
|
||
|
t.Fatalf("compareItem: a(%s, %d, %d) : b(%s, %d, %d)", a.Key, len(a.Value), a.Flags, b.Key, len(b.Value), b.Flags)
|
||
|
}
|
||
|
}
|