2014-05-16 06:36:18 +04:00
|
|
|
package ledis
|
|
|
|
|
|
|
|
import (
|
2014-05-22 07:11:50 +04:00
|
|
|
"fmt"
|
2014-10-01 19:26:46 +04:00
|
|
|
"github.com/siddontang/ledisdb/store"
|
|
|
|
"reflect"
|
2014-05-16 06:36:18 +04:00
|
|
|
"testing"
|
|
|
|
)
|
|
|
|
|
2014-05-22 07:11:50 +04:00
|
|
|
const (
|
2014-05-22 08:52:09 +04:00
|
|
|
endPos int = -1
|
2014-05-22 07:11:50 +04:00
|
|
|
)
|
|
|
|
|
|
|
|
func bin(sz string) []byte {
|
|
|
|
return []byte(sz)
|
|
|
|
}
|
|
|
|
|
|
|
|
func pair(memb string, score int) ScorePair {
|
|
|
|
return ScorePair{int64(score), bin(memb)}
|
|
|
|
}
|
|
|
|
|
2014-05-20 04:41:24 +04:00
|
|
|
func TestZSetCodec(t *testing.T) {
|
|
|
|
db := getTestDB()
|
|
|
|
|
|
|
|
key := []byte("key")
|
|
|
|
member := []byte("member")
|
|
|
|
|
|
|
|
ek := db.zEncodeSizeKey(key)
|
|
|
|
if k, err := db.zDecodeSizeKey(ek); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
} else if string(k) != "key" {
|
|
|
|
t.Fatal(string(k))
|
|
|
|
}
|
|
|
|
|
|
|
|
ek = db.zEncodeSetKey(key, member)
|
|
|
|
if k, m, err := db.zDecodeSetKey(ek); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
} else if string(k) != "key" {
|
|
|
|
t.Fatal(string(k))
|
|
|
|
} else if string(m) != "member" {
|
|
|
|
t.Fatal(string(m))
|
|
|
|
}
|
|
|
|
|
|
|
|
ek = db.zEncodeScoreKey(key, member, 100)
|
|
|
|
if k, m, s, err := db.zDecodeScoreKey(ek); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
} else if string(k) != "key" {
|
|
|
|
t.Fatal(string(k))
|
|
|
|
} else if string(m) != "member" {
|
|
|
|
t.Fatal(string(m))
|
|
|
|
} else if s != 100 {
|
|
|
|
t.Fatal(s)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2014-05-16 06:36:18 +04:00
|
|
|
func TestDBZSet(t *testing.T) {
|
|
|
|
db := getTestDB()
|
|
|
|
|
2014-05-22 07:11:50 +04:00
|
|
|
key := bin("testdb_zset_a")
|
|
|
|
|
|
|
|
// {'a':0, 'b':1, 'c':2, 'd':3}
|
|
|
|
if n, err := db.ZAdd(key, pair("a", 0), pair("b", 1),
|
|
|
|
pair("c", 2), pair("d", 3)); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
} else if n != 4 {
|
|
|
|
t.Fatal(n)
|
|
|
|
}
|
|
|
|
|
|
|
|
if n, err := db.ZCount(key, 0, 0XFF); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
} else if n != 4 {
|
|
|
|
t.Fatal(n)
|
|
|
|
}
|
|
|
|
|
2014-06-04 14:32:23 +04:00
|
|
|
if s, err := db.ZScore(key, bin("d")); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
} else if s != 3 {
|
|
|
|
t.Fatal(s)
|
|
|
|
}
|
|
|
|
|
2014-06-05 07:49:12 +04:00
|
|
|
if s, err := db.ZScore(key, bin("zzz")); err != ErrScoreMiss || s != InvalidScore {
|
2014-06-04 14:32:23 +04:00
|
|
|
t.Fatal(fmt.Sprintf("s=[%d] err=[%s]", s, err))
|
|
|
|
}
|
|
|
|
|
2014-05-22 07:11:50 +04:00
|
|
|
// {c':2, 'd':3}
|
|
|
|
if n, err := db.ZRem(key, bin("a"), bin("b")); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
} else if n != 2 {
|
|
|
|
t.Fatal(n)
|
|
|
|
}
|
|
|
|
|
|
|
|
if n, err := db.ZRem(key, bin("a"), bin("b")); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
} else if n != 0 {
|
|
|
|
t.Fatal(n)
|
|
|
|
}
|
|
|
|
|
|
|
|
if n, err := db.ZCard(key); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
} else if n != 2 {
|
|
|
|
t.Fatal(n)
|
|
|
|
}
|
2014-05-16 06:36:18 +04:00
|
|
|
|
2014-05-22 07:11:50 +04:00
|
|
|
// {}
|
|
|
|
if n, err := db.ZClear(key); err != nil {
|
2014-05-16 06:36:18 +04:00
|
|
|
t.Fatal(err)
|
|
|
|
} else if n != 2 {
|
|
|
|
t.Fatal(n)
|
|
|
|
}
|
2014-05-22 07:11:50 +04:00
|
|
|
|
|
|
|
if n, err := db.ZCount(key, 0, 0XFF); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
} else if n != 0 {
|
|
|
|
t.Fatal(n)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestZSetOrder(t *testing.T) {
|
|
|
|
db := getTestDB()
|
|
|
|
|
|
|
|
key := bin("testdb_zset_order")
|
|
|
|
|
|
|
|
// {'a':0, 'b':1, 'c':2, 'd':3, 'e':4, 'f':5}
|
|
|
|
membs := [...]string{"a", "b", "c", "d", "e", "f"}
|
|
|
|
membCnt := len(membs)
|
|
|
|
|
|
|
|
for i := 0; i < membCnt; i++ {
|
|
|
|
db.ZAdd(key, pair(membs[i], i))
|
|
|
|
}
|
|
|
|
|
|
|
|
if n, _ := db.ZCount(key, 0, 0XFFFF); int(n) != membCnt {
|
|
|
|
t.Fatal(n)
|
|
|
|
}
|
|
|
|
|
|
|
|
for i := 0; i < membCnt; i++ {
|
|
|
|
if pos, err := db.ZRank(key, bin(membs[i])); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
} else if int(pos) != i {
|
|
|
|
t.Fatal(pos)
|
|
|
|
}
|
|
|
|
|
|
|
|
if pos, err := db.ZRevRank(key, bin(membs[i])); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
} else if int(pos) != membCnt-i-1 {
|
|
|
|
t.Fatal(pos)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-22 11:25:51 +04:00
|
|
|
if qMembs, err := db.ZRange(key, 0, endPos); err != nil {
|
2014-05-22 07:11:50 +04:00
|
|
|
t.Fatal(err)
|
|
|
|
} else if len(qMembs) != membCnt {
|
|
|
|
t.Fatal(fmt.Sprintf("%d vs %d", len(qMembs), membCnt))
|
|
|
|
} else {
|
|
|
|
for i := 0; i < membCnt; i++ {
|
2014-06-22 11:25:51 +04:00
|
|
|
if string(qMembs[i].Member) != membs[i] {
|
2014-05-22 07:11:50 +04:00
|
|
|
t.Fatal(fmt.Sprintf("[%s] vs [%s]", qMembs[i], membs[i]))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// {'a':0, 'b':1, 'c':2, 'd':999, 'e':4, 'f':5}
|
|
|
|
if n, err := db.ZAdd(key, pair("d", 999)); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
} else if n != 0 {
|
|
|
|
t.Fatal(n)
|
|
|
|
}
|
|
|
|
|
|
|
|
if pos, _ := db.ZRank(key, bin("d")); int(pos) != membCnt-1 {
|
|
|
|
t.Fatal(pos)
|
|
|
|
}
|
|
|
|
|
|
|
|
if pos, _ := db.ZRevRank(key, bin("d")); int(pos) != 0 {
|
|
|
|
t.Fatal(pos)
|
|
|
|
}
|
|
|
|
|
|
|
|
if pos, _ := db.ZRank(key, bin("e")); int(pos) != 3 {
|
|
|
|
t.Fatal(pos)
|
|
|
|
}
|
|
|
|
|
|
|
|
if pos, _ := db.ZRank(key, bin("f")); int(pos) != 4 {
|
|
|
|
t.Fatal(pos)
|
|
|
|
}
|
|
|
|
|
2014-06-22 11:25:51 +04:00
|
|
|
if qMembs, err := db.ZRangeByScore(key, 999, 0XFFFF, 0, membCnt); err != nil {
|
2014-05-22 07:11:50 +04:00
|
|
|
t.Fatal(err)
|
|
|
|
} else if len(qMembs) != 1 {
|
|
|
|
t.Fatal(len(qMembs))
|
|
|
|
}
|
|
|
|
|
|
|
|
// {'a':0, 'b':1, 'c':2, 'd':999, 'e':6, 'f':5}
|
2014-06-04 14:32:23 +04:00
|
|
|
if s, err := db.ZIncrBy(key, 2, bin("e")); err != nil {
|
2014-05-22 07:11:50 +04:00
|
|
|
t.Fatal(err)
|
2014-06-04 14:32:23 +04:00
|
|
|
} else if s != 6 {
|
|
|
|
t.Fatal(s)
|
2014-05-22 07:11:50 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if pos, _ := db.ZRank(key, bin("e")); int(pos) != 4 {
|
|
|
|
t.Fatal(pos)
|
|
|
|
}
|
|
|
|
|
|
|
|
if pos, _ := db.ZRevRank(key, bin("e")); int(pos) != 1 {
|
|
|
|
t.Fatal(pos)
|
|
|
|
}
|
2014-06-04 14:32:23 +04:00
|
|
|
|
2014-06-22 11:25:51 +04:00
|
|
|
if datas, _ := db.ZRange(key, 0, endPos); len(datas) != 6 {
|
2014-06-04 14:32:23 +04:00
|
|
|
t.Fatal(len(datas))
|
|
|
|
} else {
|
|
|
|
scores := []int64{0, 1, 2, 5, 6, 999}
|
2014-06-22 11:25:51 +04:00
|
|
|
for i := 0; i < len(datas); i++ {
|
|
|
|
if datas[i].Score != scores[i] {
|
2014-06-04 14:32:23 +04:00
|
|
|
t.Fatal(fmt.Sprintf("[%d]=%d", i, datas[i]))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
2014-05-16 06:36:18 +04:00
|
|
|
}
|
2014-05-26 05:21:17 +04:00
|
|
|
|
2014-06-23 07:12:20 +04:00
|
|
|
func TestZSetPersist(t *testing.T) {
|
|
|
|
db := getTestDB()
|
|
|
|
|
|
|
|
key := []byte("persist")
|
|
|
|
db.ZAdd(key, ScorePair{1, []byte("a")})
|
|
|
|
|
|
|
|
if n, err := db.ZPersist(key); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
} else if n != 0 {
|
|
|
|
t.Fatal(n)
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, err := db.ZExpire(key, 10); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if n, err := db.ZPersist(key); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
} else if n != 1 {
|
|
|
|
t.Fatal(n)
|
|
|
|
}
|
|
|
|
}
|
2014-08-12 14:06:02 +04:00
|
|
|
|
|
|
|
func TestZUnionStore(t *testing.T) {
|
|
|
|
db := getTestDB()
|
|
|
|
key1 := []byte("key1")
|
|
|
|
key2 := []byte("key2")
|
|
|
|
|
|
|
|
db.ZAdd(key1, ScorePair{1, []byte("one")})
|
|
|
|
db.ZAdd(key1, ScorePair{1, []byte("two")})
|
|
|
|
|
|
|
|
db.ZAdd(key2, ScorePair{2, []byte("two")})
|
|
|
|
db.ZAdd(key2, ScorePair{2, []byte("three")})
|
|
|
|
|
|
|
|
keys := [][]byte{key1, key2}
|
|
|
|
weights := []int64{1, 2}
|
|
|
|
|
|
|
|
out := []byte("out")
|
2014-08-16 09:43:21 +04:00
|
|
|
|
|
|
|
db.ZAdd(out, ScorePair{3, []byte("out")})
|
|
|
|
|
2014-08-12 14:06:02 +04:00
|
|
|
n, err := db.ZUnionStore(out, keys, weights, AggregateSum)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err.Error())
|
|
|
|
}
|
|
|
|
if n != 3 {
|
|
|
|
t.Fatal("invalid value ", n)
|
|
|
|
}
|
|
|
|
|
|
|
|
v, err := db.ZScore(out, []byte("two"))
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err.Error())
|
|
|
|
}
|
|
|
|
if v != 5 {
|
|
|
|
t.Fatal("invalid value ", v)
|
|
|
|
}
|
2014-08-13 05:57:13 +04:00
|
|
|
|
|
|
|
out = []byte("out")
|
|
|
|
n, err = db.ZUnionStore(out, keys, weights, AggregateMax)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err.Error())
|
|
|
|
}
|
|
|
|
if n != 3 {
|
|
|
|
t.Fatal("invalid value ", n)
|
|
|
|
}
|
|
|
|
|
|
|
|
v, err = db.ZScore(out, []byte("two"))
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err.Error())
|
|
|
|
}
|
|
|
|
if v != 4 {
|
|
|
|
t.Fatal("invalid value ", v)
|
|
|
|
}
|
2014-08-13 06:26:35 +04:00
|
|
|
|
|
|
|
n, err = db.ZCount(out, 0, 0XFFFE)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err.Error())
|
|
|
|
}
|
|
|
|
if n != 3 {
|
|
|
|
t.Fatal("invalid value ", v)
|
|
|
|
}
|
2014-08-16 09:43:21 +04:00
|
|
|
|
|
|
|
n, err = db.ZCard(out)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err.Error())
|
|
|
|
}
|
|
|
|
if n != 3 {
|
|
|
|
t.Fatal("invalid value ", n)
|
|
|
|
}
|
2014-08-13 05:57:13 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestZInterStore(t *testing.T) {
|
|
|
|
db := getTestDB()
|
|
|
|
|
|
|
|
key1 := []byte("key1")
|
|
|
|
key2 := []byte("key2")
|
|
|
|
|
|
|
|
db.ZAdd(key1, ScorePair{1, []byte("one")})
|
|
|
|
db.ZAdd(key1, ScorePair{1, []byte("two")})
|
|
|
|
|
|
|
|
db.ZAdd(key2, ScorePair{2, []byte("two")})
|
|
|
|
db.ZAdd(key2, ScorePair{2, []byte("three")})
|
|
|
|
|
|
|
|
keys := [][]byte{key1, key2}
|
2014-08-13 11:38:59 +04:00
|
|
|
weights := []int64{2, 3}
|
2014-08-13 05:57:13 +04:00
|
|
|
out := []byte("out")
|
|
|
|
|
2014-08-16 09:43:21 +04:00
|
|
|
db.ZAdd(out, ScorePair{3, []byte("out")})
|
|
|
|
|
2014-08-13 05:57:13 +04:00
|
|
|
n, err := db.ZInterStore(out, keys, weights, AggregateSum)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err.Error())
|
|
|
|
}
|
|
|
|
if n != 1 {
|
|
|
|
t.Fatal("invalid value ", n)
|
|
|
|
}
|
|
|
|
v, err := db.ZScore(out, []byte("two"))
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err.Error())
|
|
|
|
}
|
2014-08-13 11:38:59 +04:00
|
|
|
if v != 8 {
|
2014-08-13 05:57:13 +04:00
|
|
|
t.Fatal("invalid value ", v)
|
|
|
|
}
|
|
|
|
|
|
|
|
n, err = db.ZInterStore(out, keys, weights, AggregateMin)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err.Error())
|
|
|
|
}
|
|
|
|
if n != 1 {
|
|
|
|
t.Fatal("invalid value ", n)
|
|
|
|
}
|
|
|
|
|
|
|
|
v, err = db.ZScore(out, []byte("two"))
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err.Error())
|
|
|
|
}
|
2014-08-13 11:38:59 +04:00
|
|
|
if v != 2 {
|
2014-08-13 05:57:13 +04:00
|
|
|
t.Fatal("invalid value ", v)
|
|
|
|
}
|
|
|
|
|
2014-08-13 06:26:35 +04:00
|
|
|
n, err = db.ZCount(out, 0, 0XFFFF)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err.Error())
|
|
|
|
}
|
|
|
|
if n != 1 {
|
|
|
|
t.Fatal("invalid value ", n)
|
|
|
|
}
|
|
|
|
|
2014-08-16 09:43:21 +04:00
|
|
|
n, err = db.ZCard(out)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err.Error())
|
|
|
|
}
|
|
|
|
if n != 1 {
|
|
|
|
t.Fatal("invalid value ", n)
|
|
|
|
}
|
2014-08-12 14:06:02 +04:00
|
|
|
}
|
2014-08-25 18:25:10 +04:00
|
|
|
|
|
|
|
func TestZScan(t *testing.T) {
|
|
|
|
db := getTestDB()
|
|
|
|
db.FlushAll()
|
|
|
|
|
|
|
|
for i := 0; i < 2000; i++ {
|
|
|
|
key := fmt.Sprintf("%d", i)
|
|
|
|
if _, err := db.ZAdd([]byte(key), ScorePair{1, []byte("v")}); err != nil {
|
|
|
|
t.Fatal(err.Error())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if v, err := db.ZScan(nil, 3000, true, ""); err != nil {
|
|
|
|
t.Fatal(err.Error())
|
|
|
|
} else if len(v) != 2000 {
|
|
|
|
t.Fatal("invalid value ", len(v))
|
|
|
|
}
|
|
|
|
|
|
|
|
if n, err := db.zFlush(); err != nil {
|
|
|
|
t.Fatal(err.Error())
|
|
|
|
} else if n != 2000 {
|
|
|
|
t.Fatal("invalid value ", n)
|
|
|
|
}
|
|
|
|
|
|
|
|
if v, err := db.ZScan(nil, 3000, true, ""); err != nil {
|
|
|
|
t.Fatal(err.Error())
|
|
|
|
} else if len(v) != 0 {
|
|
|
|
t.Fatal("invalid value length ", len(v))
|
|
|
|
}
|
|
|
|
}
|
2014-10-01 19:26:46 +04:00
|
|
|
|
|
|
|
func TestZLex(t *testing.T) {
|
|
|
|
db := getTestDB()
|
|
|
|
if _, err := db.zFlush(); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
key := []byte("myzset")
|
|
|
|
if _, err := db.ZAdd(key, ScorePair{0, []byte("a")},
|
|
|
|
ScorePair{0, []byte("b")},
|
|
|
|
ScorePair{0, []byte("c")},
|
|
|
|
ScorePair{0, []byte("d")},
|
|
|
|
ScorePair{0, []byte("e")},
|
|
|
|
ScorePair{0, []byte("f")},
|
|
|
|
ScorePair{0, []byte("g")}); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if ay, err := db.ZRangeByLex(key, nil, []byte("c"), store.RangeClose, 0, -1); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
} else if !reflect.DeepEqual(ay, [][]byte{[]byte("a"), []byte("b"), []byte("c")}) {
|
|
|
|
t.Fatal("must equal a, b, c")
|
|
|
|
}
|
|
|
|
|
|
|
|
if ay, err := db.ZRangeByLex(key, nil, []byte("c"), store.RangeROpen, 0, -1); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
} else if !reflect.DeepEqual(ay, [][]byte{[]byte("a"), []byte("b")}) {
|
|
|
|
t.Fatal("must equal a, b")
|
|
|
|
}
|
|
|
|
|
|
|
|
if ay, err := db.ZRangeByLex(key, []byte("aaa"), []byte("g"), store.RangeROpen, 0, -1); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
} else if !reflect.DeepEqual(ay, [][]byte{[]byte("b"),
|
|
|
|
[]byte("c"), []byte("d"), []byte("e"), []byte("f")}) {
|
|
|
|
t.Fatal("must equal b, c, d, e, f", fmt.Sprintf("%q", ay))
|
|
|
|
}
|
|
|
|
|
|
|
|
if n, err := db.ZLexCount(key, nil, nil, store.RangeClose); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
} else if n != 7 {
|
|
|
|
t.Fatal(n)
|
|
|
|
}
|
|
|
|
|
|
|
|
if n, err := db.ZRemRangeByLex(key, []byte("aaa"), []byte("g"), store.RangeROpen); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
} else if n != 5 {
|
|
|
|
t.Fatal(n)
|
|
|
|
}
|
|
|
|
|
|
|
|
if n, err := db.ZLexCount(key, nil, nil, store.RangeClose); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
} else if n != 2 {
|
|
|
|
t.Fatal(n)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|