From f6bca7816842e8cffc3d25bceac9cd4666327d13 Mon Sep 17 00:00:00 2001 From: Dimitrij Denissenko Date: Thu, 15 Jan 2015 15:51:22 +0000 Subject: [PATCH 01/11] Migrates tests to ginkgo/gomega --- .gitignore | 1 + .travis.yml | 3 +- Makefile | 4 +- command_test.go | 167 +++ commands_test.go | 2215 +++++++++++++++++++++++++++++++ example_test.go | 2 +- multi_test.go | 122 ++ pipeline_test.go | 152 +++ pool_test.go | 122 ++ pubsub_test.go | 202 +++ redis_test.go | 3305 ++-------------------------------------------- sentinel_test.go | 279 ++-- 12 files changed, 3203 insertions(+), 3371 deletions(-) create mode 100644 .gitignore create mode 100644 command_test.go create mode 100644 commands_test.go create mode 100644 multi_test.go create mode 100644 pipeline_test.go create mode 100644 pool_test.go create mode 100644 pubsub_test.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..58c2a9d6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.rdb diff --git a/.travis.yml b/.travis.yml index c3cf4b8a..00f40c6f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,8 @@ go: install: - go get gopkg.in/bufio.v1 - - go get gopkg.in/check.v1 + - go get onsi.github.io/ginkgo + - go get onsi.github.io/gomega - mkdir -p $HOME/gopath/src/gopkg.in - ln -s `pwd` $HOME/gopath/src/gopkg.in/redis.v2 diff --git a/Makefile b/Makefile index b250d9bf..d4290887 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,3 @@ all: - go test gopkg.in/redis.v2 -cpu=1,2,4 - go test gopkg.in/redis.v2 -short -race + go test ./... -cpu=1,2,4 + go test ./... -short -race diff --git a/command_test.go b/command_test.go new file mode 100644 index 00000000..1be2b945 --- /dev/null +++ b/command_test.go @@ -0,0 +1,167 @@ +package redis_test + +import ( + "bytes" + "strconv" + "sync" + "testing" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "gopkg.in/redis.v2" +) + +var _ = Describe("Command", func() { + var client *redis.Client + + BeforeEach(func() { + client = redis.NewTCPClient(&redis.Options{ + Addr: redisAddr, + }) + }) + + AfterEach(func() { + Expect(client.FlushDb().Err()).NotTo(HaveOccurred()) + Expect(client.Close()).NotTo(HaveOccurred()) + }) + + It("should have a plain string result", func() { + set := client.Set("foo", "bar") + Expect(set.String()).To(Equal("SET foo bar: OK")) + + get := client.Get("foo") + Expect(get.String()).To(Equal("GET foo: bar")) + }) + + It("should have correct val/err states", func() { + set := client.Set("key", "hello") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + get := client.Get("key") + Expect(get.Err()).NotTo(HaveOccurred()) + Expect(get.Val()).To(Equal("hello")) + + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + }) + + It("should escape special chars", func() { + set := client.Set("key", "hello1\r\nhello2\r\n") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + get := client.Get("key") + Expect(get.Err()).NotTo(HaveOccurred()) + Expect(get.Val()).To(Equal("hello1\r\nhello2\r\n")) + }) + + It("should handle big vals", func() { + val := string(bytes.Repeat([]byte{'*'}, 1<<16)) + set := client.Set("key", val) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + get := client.Get("key") + Expect(get.Err()).NotTo(HaveOccurred()) + Expect(get.Val()).To(Equal(val)) + }) + + It("should handle many keys #1", func() { + const n = 100000 + for i := 0; i < n; i++ { + client.Set("keys.key"+strconv.Itoa(i), "hello"+strconv.Itoa(i)) + } + keys := client.Keys("keys.*") + Expect(keys.Err()).NotTo(HaveOccurred()) + Expect(len(keys.Val())).To(Equal(n)) + }) + + It("should handle many keys #2", func() { + const n = 100000 + + keys := []string{"non-existent-key"} + for i := 0; i < n; i++ { + key := "keys.key" + strconv.Itoa(i) + client.Set(key, "hello"+strconv.Itoa(i)) + keys = append(keys, key) + } + keys = append(keys, "non-existent-key") + + mget := client.MGet(keys...) + Expect(mget.Err()).NotTo(HaveOccurred()) + Expect(len(mget.Val())).To(Equal(n + 2)) + vals := mget.Val() + for i := 0; i < n; i++ { + Expect(vals[i+1]).To(Equal("hello" + strconv.Itoa(i))) + } + Expect(vals[0]).To(BeNil()) + Expect(vals[n+1]).To(BeNil()) + }) + + It("should convert strings via helpers", func() { + set := client.Set("key", "10") + Expect(set.Err()).NotTo(HaveOccurred()) + + n, err := client.Get("key").Int64() + Expect(err).NotTo(HaveOccurred()) + Expect(n).To(Equal(int64(10))) + + un, err := client.Get("key").Uint64() + Expect(err).NotTo(HaveOccurred()) + Expect(un).To(Equal(uint64(10))) + + f, err := client.Get("key").Float64() + Expect(err).NotTo(HaveOccurred()) + Expect(f).To(Equal(float64(10))) + }) + + Describe("races", func() { + + It("should echo", func() { + var n = 10000 + if testing.Short() { + n = 1000 + } + + wg := &sync.WaitGroup{} + wg.Add(n) + for i := 0; i < n; i++ { + go func(i int) { + defer wg.Done() + + msg := "echo" + strconv.Itoa(i) + echo := client.Echo(msg) + Expect(echo.Err()).NotTo(HaveOccurred()) + Expect(echo.Val()).To(Equal(msg)) + }(i) + } + wg.Wait() + }) + + It("should incr", func() { + var n = 10000 + if testing.Short() { + n = 1000 + } + + key := "TestIncrFromGoroutines" + wg := &sync.WaitGroup{} + wg.Add(n) + for i := 0; i < n; i++ { + go func() { + defer wg.Done() + err := client.Incr(key).Err() + Expect(err).NotTo(HaveOccurred()) + }() + } + wg.Wait() + + val, err := client.Get(key).Int64() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal(int64(n))) + }) + + }) + +}) diff --git a/commands_test.go b/commands_test.go new file mode 100644 index 00000000..2eb43002 --- /dev/null +++ b/commands_test.go @@ -0,0 +1,2215 @@ +package redis_test + +import ( + "fmt" + "strconv" + "sync" + "testing" + "time" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "gopkg.in/redis.v2" +) + +var _ = Describe("Commands", func() { + var client *redis.Client + + BeforeEach(func() { + client = redis.NewTCPClient(&redis.Options{ + Addr: redisAddr, + }) + }) + + AfterEach(func() { + Expect(client.FlushDb().Err()).NotTo(HaveOccurred()) + Expect(client.Close()).NotTo(HaveOccurred()) + }) + + //------------------------------------------------------------------------------ + + Describe("server", func() { + + It("should Auth", func() { + auth := client.Auth("password") + Expect(auth.Err()).To(MatchError("ERR Client sent AUTH, but no password is set")) + Expect(auth.Val()).To(Equal("")) + }) + + It("should Echo", func() { + echo := client.Echo("hello") + Expect(echo.Err()).NotTo(HaveOccurred()) + Expect(echo.Val()).To(Equal("hello")) + }) + + It("should Ping", func() { + ping := client.Ping() + Expect(ping.Err()).NotTo(HaveOccurred()) + Expect(ping.Val()).To(Equal("PONG")) + }) + + It("should Select", func() { + sel := client.Select(1) + Expect(sel.Err()).NotTo(HaveOccurred()) + Expect(sel.Val()).To(Equal("OK")) + }) + + It("should BgRewriteAOF", func() { + r := client.BgRewriteAOF() + Expect(r.Err()).NotTo(HaveOccurred()) + Expect(r.Val()).To(ContainSubstring("Background append only file rewriting")) + }) + + It("should BgSave", func() { + // workaround for "ERR Can't BGSAVE while AOF log rewriting is in progress" + Eventually(func() string { + return client.BgSave().Val() + }).Should(Equal("Background saving started")) + }) + + It("should ClientKill", func() { + r := client.ClientKill("1.1.1.1:1111") + Expect(r.Err()).To(MatchError("ERR No such client")) + Expect(r.Val()).To(Equal("")) + }) + + It("should ConfigGet", func() { + r := client.ConfigGet("*") + Expect(r.Err()).NotTo(HaveOccurred()) + Expect(r.Val()).NotTo(BeEmpty()) + }) + + It("should ConfigResetStat", func() { + r := client.ConfigResetStat() + Expect(r.Err()).NotTo(HaveOccurred()) + Expect(r.Val()).To(Equal("OK")) + }) + + It("should ConfigSet", func() { + configGet := client.ConfigGet("maxmemory") + Expect(configGet.Err()).NotTo(HaveOccurred()) + Expect(configGet.Val()).To(HaveLen(2)) + Expect(configGet.Val()[0]).To(Equal("maxmemory")) + + configSet := client.ConfigSet("maxmemory", configGet.Val()[1].(string)) + Expect(configSet.Err()).NotTo(HaveOccurred()) + Expect(configSet.Val()).To(Equal("OK")) + }) + + It("should DbSize", func() { + dbSize := client.DbSize() + Expect(dbSize.Err()).NotTo(HaveOccurred()) + Expect(dbSize.Val()).To(Equal(int64(0))) + }) + + It("should Info", func() { + info := client.Info() + Expect(info.Err()).NotTo(HaveOccurred()) + Expect(info.Val()).NotTo(Equal("")) + }) + + It("should LastSave", func() { + lastSave := client.LastSave() + Expect(lastSave.Err()).NotTo(HaveOccurred()) + Expect(lastSave.Val()).NotTo(Equal(0)) + }) + + It("should Save", func() { + // workaround for "ERR Background save already in progress" + Eventually(func() string { + return client.Save().Val() + }).Should(Equal("OK")) + }) + + It("should SlaveOf", func() { + slaveOf := client.SlaveOf("localhost", "8888") + Expect(slaveOf.Err()).NotTo(HaveOccurred()) + Expect(slaveOf.Val()).To(Equal("OK")) + + slaveOf = client.SlaveOf("NO", "ONE") + Expect(slaveOf.Err()).NotTo(HaveOccurred()) + Expect(slaveOf.Val()).To(Equal("OK")) + }) + + It("should Time", func() { + time := client.Time() + Expect(time.Err()).NotTo(HaveOccurred()) + Expect(time.Val()).To(HaveLen(2)) + }) + + }) + + //------------------------------------------------------------------------------ + + Describe("debugging", func() { + + It("should DebugObject", func() { + debug := client.DebugObject("foo") + Expect(debug.Err()).To(HaveOccurred()) + Expect(debug.Err().Error()).To(Equal("ERR no such key")) + + client.Set("foo", "bar") + debug = client.DebugObject("foo") + Expect(debug.Err()).NotTo(HaveOccurred()) + Expect(debug.Val()).To(ContainSubstring(`serializedlength:4`)) + }) + + }) + + //------------------------------------------------------------------------------ + + Describe("keys", func() { + + It("should Del", func() { + set := client.Set("key1", "Hello") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + set = client.Set("key2", "World") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + del := client.Del("key1", "key2", "key3") + Expect(del.Err()).NotTo(HaveOccurred()) + Expect(del.Val()).To(Equal(int64(2))) + }) + + It("should Dump", func() { + set := client.Set("key", "hello") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + dump := client.Dump("key") + Expect(dump.Err()).NotTo(HaveOccurred()) + Expect(dump.Val()).To(Equal("\x00\x05hello\x06\x00\xf5\x9f\xb7\xf6\x90a\x1c\x99")) + }) + + It("should Exists", func() { + set := client.Set("key1", "Hello") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + exists := client.Exists("key1") + Expect(exists.Err()).NotTo(HaveOccurred()) + Expect(exists.Val()).To(Equal(true)) + + exists = client.Exists("key2") + Expect(exists.Err()).NotTo(HaveOccurred()) + Expect(exists.Val()).To(Equal(false)) + }) + + It("should Expire", func() { + set := client.Set("key", "Hello") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + expire := client.Expire("key", 10*time.Second) + Expect(expire.Err()).NotTo(HaveOccurred()) + Expect(expire.Val()).To(Equal(true)) + + ttl := client.TTL("key") + Expect(ttl.Err()).NotTo(HaveOccurred()) + Expect(ttl.Val()).To(Equal(10 * time.Second)) + + set = client.Set("key", "Hello World") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + ttl = client.TTL("key") + Expect(ttl.Err()).NotTo(HaveOccurred()) + Expect(ttl.Val() < 0).To(Equal(true)) + }) + + It("should ExpireAt", func() { + set := client.Set("key", "Hello") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + exists := client.Exists("key") + Expect(exists.Err()).NotTo(HaveOccurred()) + Expect(exists.Val()).To(Equal(true)) + + expireAt := client.ExpireAt("key", time.Now().Add(-time.Hour)) + Expect(expireAt.Err()).NotTo(HaveOccurred()) + Expect(expireAt.Val()).To(Equal(true)) + + exists = client.Exists("key") + Expect(exists.Err()).NotTo(HaveOccurred()) + Expect(exists.Val()).To(Equal(false)) + }) + + It("should Keys", func() { + mset := client.MSet("one", "1", "two", "2", "three", "3", "four", "4") + Expect(mset.Err()).NotTo(HaveOccurred()) + Expect(mset.Val()).To(Equal("OK")) + + keys := client.Keys("*o*") + Expect(keys.Err()).NotTo(HaveOccurred()) + Expect(sortStrings(keys.Val())).To(Equal([]string{"four", "one", "two"})) + + keys = client.Keys("t??") + Expect(keys.Err()).NotTo(HaveOccurred()) + Expect(keys.Val()).To(Equal([]string{"two"})) + + keys = client.Keys("*") + Expect(keys.Err()).NotTo(HaveOccurred()) + Expect(sortStrings(keys.Val())).To(Equal([]string{"four", "one", "three", "two"})) + }) + + It("should Migrate", func() { + migrate := client.Migrate("localhost", "6380", "key", 0, 0) + Expect(migrate.Err()).NotTo(HaveOccurred()) + Expect(migrate.Val()).To(Equal("NOKEY")) + + set := client.Set("key", "hello") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + migrate = client.Migrate("localhost", "6380", "key", 0, 0) + Expect(migrate.Err()).To(MatchError("IOERR error or timeout writing to target instance")) + Expect(migrate.Val()).To(Equal("")) + }) + + It("should Move", func() { + move := client.Move("key", 1) + Expect(move.Err()).NotTo(HaveOccurred()) + Expect(move.Val()).To(Equal(false)) + + set := client.Set("key", "hello") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + move = client.Move("key", 1) + Expect(move.Err()).NotTo(HaveOccurred()) + Expect(move.Val()).To(Equal(true)) + + get := client.Get("key") + Expect(get.Err()).To(Equal(redis.Nil)) + Expect(get.Val()).To(Equal("")) + + sel := client.Select(1) + Expect(sel.Err()).NotTo(HaveOccurred()) + Expect(sel.Val()).To(Equal("OK")) + + get = client.Get("key") + Expect(get.Err()).NotTo(HaveOccurred()) + Expect(get.Val()).To(Equal("hello")) + Expect(client.FlushDb().Err()).NotTo(HaveOccurred()) + Expect(client.Select(0).Err()).NotTo(HaveOccurred()) + }) + + It("should Object", func() { + set := client.Set("key", "hello") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + refCount := client.ObjectRefCount("key") + Expect(refCount.Err()).NotTo(HaveOccurred()) + Expect(refCount.Val()).To(Equal(int64(1))) + + enc := client.ObjectEncoding("key") + Expect(enc.Err()).NotTo(HaveOccurred()) + Expect(enc.Val()).To(Equal("raw")) + + idleTime := client.ObjectIdleTime("key") + Expect(idleTime.Err()).NotTo(HaveOccurred()) + Expect(idleTime.Val()).To(Equal(time.Duration(0))) + }) + + It("should Persist", func() { + set := client.Set("key", "Hello") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + expire := client.Expire("key", 10*time.Second) + Expect(expire.Err()).NotTo(HaveOccurred()) + Expect(expire.Val()).To(Equal(true)) + + ttl := client.TTL("key") + Expect(ttl.Err()).NotTo(HaveOccurred()) + Expect(ttl.Val()).To(Equal(10 * time.Second)) + + persist := client.Persist("key") + Expect(persist.Err()).NotTo(HaveOccurred()) + Expect(persist.Val()).To(Equal(true)) + + ttl = client.TTL("key") + Expect(ttl.Err()).NotTo(HaveOccurred()) + Expect(ttl.Val() < 0).To(Equal(true)) + }) + + It("should PExpire", func() { + set := client.Set("key", "Hello") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + expiration := 900 * time.Millisecond + pexpire := client.PExpire("key", expiration) + Expect(pexpire.Err()).NotTo(HaveOccurred()) + Expect(pexpire.Val()).To(Equal(true)) + + ttl := client.TTL("key") + Expect(ttl.Err()).NotTo(HaveOccurred()) + Expect(ttl.Val()).To(Equal(time.Second)) + + pttl := client.PTTL("key") + Expect(pttl.Err()).NotTo(HaveOccurred()) + Expect(pttl.Val() <= expiration).To(Equal(true)) + Expect(pttl.Val() >= expiration-time.Millisecond).To(Equal(true)) + }) + + It("should PExpireAt", func() { + set := client.Set("key", "Hello") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + expiration := 900 * time.Millisecond + pexpireat := client.PExpireAt("key", time.Now().Add(expiration)) + Expect(pexpireat.Err()).NotTo(HaveOccurred()) + Expect(pexpireat.Val()).To(Equal(true)) + + ttl := client.TTL("key") + Expect(ttl.Err()).NotTo(HaveOccurred()) + Expect(ttl.Val()).To(Equal(time.Second)) + + pttl := client.PTTL("key") + Expect(pttl.Err()).NotTo(HaveOccurred()) + Expect(pttl.Val() <= expiration).To(Equal(true)) + Expect(pttl.Val() >= expiration-time.Millisecond).To(Equal(true)) + }) + + It("should PTTL", func() { + set := client.Set("key", "Hello") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + expiration := time.Second + expire := client.Expire("key", expiration) + Expect(expire.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + pttl := client.PTTL("key") + Expect(pttl.Err()).NotTo(HaveOccurred()) + Expect(pttl.Val() <= expiration).To(Equal(true)) + Expect(pttl.Val() >= expiration-time.Millisecond).To(Equal(true)) + }) + + It("should RandomKey", func() { + randomKey := client.RandomKey() + Expect(randomKey.Err()).To(Equal(redis.Nil)) + Expect(randomKey.Val()).To(Equal("")) + + set := client.Set("key", "hello") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + randomKey = client.RandomKey() + Expect(randomKey.Err()).NotTo(HaveOccurred()) + Expect(randomKey.Val()).To(Equal("key")) + }) + + It("should Rename", func() { + set := client.Set("key", "hello") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + status := client.Rename("key", "key1") + Expect(status.Err()).NotTo(HaveOccurred()) + Expect(status.Val()).To(Equal("OK")) + + get := client.Get("key1") + Expect(get.Err()).NotTo(HaveOccurred()) + Expect(get.Val()).To(Equal("hello")) + }) + + It("should RenameNX", func() { + set := client.Set("key", "hello") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + renameNX := client.RenameNX("key", "key1") + Expect(renameNX.Err()).NotTo(HaveOccurred()) + Expect(renameNX.Val()).To(Equal(true)) + + get := client.Get("key1") + Expect(get.Err()).NotTo(HaveOccurred()) + Expect(get.Val()).To(Equal("hello")) + }) + + It("should Restore", func() { + set := client.Set("key", "hello") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + dump := client.Dump("key") + Expect(dump.Err()).NotTo(HaveOccurred()) + + del := client.Del("key") + Expect(del.Err()).NotTo(HaveOccurred()) + + restore := client.Restore("key", 0, dump.Val()) + Expect(restore.Err()).NotTo(HaveOccurred()) + Expect(restore.Val()).To(Equal("OK")) + + type_ := client.Type("key") + Expect(type_.Err()).NotTo(HaveOccurred()) + Expect(type_.Val()).To(Equal("string")) + + lRange := client.Get("key") + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal("hello")) + }) + + It("should Sort", func() { + lPush := client.LPush("list", "1") + Expect(lPush.Err()).NotTo(HaveOccurred()) + Expect(lPush.Val()).To(Equal(int64(1))) + lPush = client.LPush("list", "3") + Expect(lPush.Err()).NotTo(HaveOccurred()) + Expect(lPush.Val()).To(Equal(int64(2))) + lPush = client.LPush("list", "2") + Expect(lPush.Err()).NotTo(HaveOccurred()) + Expect(lPush.Val()).To(Equal(int64(3))) + + sort := client.Sort("list", redis.Sort{Offset: 0, Count: 2, Order: "ASC"}) + Expect(sort.Err()).NotTo(HaveOccurred()) + Expect(sort.Val()).To(Equal([]string{"1", "2"})) + }) + + It("should TTL", func() { + ttl := client.TTL("key") + Expect(ttl.Err()).NotTo(HaveOccurred()) + Expect(ttl.Val() < 0).To(Equal(true)) + + set := client.Set("key", "hello") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + expire := client.Expire("key", 60*time.Second) + Expect(expire.Err()).NotTo(HaveOccurred()) + Expect(expire.Val()).To(Equal(true)) + + ttl = client.TTL("key") + Expect(ttl.Err()).NotTo(HaveOccurred()) + Expect(ttl.Val()).To(Equal(60 * time.Second)) + }) + + It("should Type", func() { + set := client.Set("key", "hello") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + type_ := client.Type("key") + Expect(type_.Err()).NotTo(HaveOccurred()) + Expect(type_.Val()).To(Equal("string")) + }) + + }) + + //------------------------------------------------------------------------------ + + Describe("scanning", func() { + + It("should Scan", func() { + for i := 0; i < 1000; i++ { + set := client.Set(fmt.Sprintf("key%d", i), "hello") + Expect(set.Err()).NotTo(HaveOccurred()) + } + + cursor, keys, err := client.Scan(0, "", 0).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(cursor > 0).To(Equal(true)) + Expect(len(keys) > 0).To(Equal(true)) + }) + + It("should SScan", func() { + for i := 0; i < 1000; i++ { + sadd := client.SAdd("myset", fmt.Sprintf("member%d", i)) + Expect(sadd.Err()).NotTo(HaveOccurred()) + } + + cursor, keys, err := client.SScan("myset", 0, "", 0).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(cursor > 0).To(Equal(true)) + Expect(len(keys) > 0).To(Equal(true)) + }) + + It("should HScan", func() { + for i := 0; i < 1000; i++ { + sadd := client.HSet("myhash", fmt.Sprintf("key%d", i), "hello") + Expect(sadd.Err()).NotTo(HaveOccurred()) + } + + cursor, keys, err := client.HScan("myhash", 0, "", 0).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(cursor > 0).To(Equal(true)) + Expect(len(keys) > 0).To(Equal(true)) + }) + + It("should ZScan", func() { + for i := 0; i < 1000; i++ { + sadd := client.ZAdd("myset", redis.Z{float64(i), fmt.Sprintf("member%d", i)}) + Expect(sadd.Err()).NotTo(HaveOccurred()) + } + + cursor, keys, err := client.ZScan("myset", 0, "", 0).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(cursor > 0).To(Equal(true)) + Expect(len(keys) > 0).To(Equal(true)) + }) + + }) + + //------------------------------------------------------------------------------ + + Describe("strings", func() { + + It("should Append", func() { + exists := client.Exists("key") + Expect(exists.Err()).NotTo(HaveOccurred()) + Expect(exists.Val()).To(Equal(false)) + + append := client.Append("key", "Hello") + Expect(append.Err()).NotTo(HaveOccurred()) + Expect(append.Val()).To(Equal(int64(5))) + + append = client.Append("key", " World") + Expect(append.Err()).NotTo(HaveOccurred()) + Expect(append.Val()).To(Equal(int64(11))) + + get := client.Get("key") + Expect(get.Err()).NotTo(HaveOccurred()) + Expect(get.Val()).To(Equal("Hello World")) + }) + + It("should BitCount", func() { + set := client.Set("key", "foobar") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + bitCount := client.BitCount("key", nil) + Expect(bitCount.Err()).NotTo(HaveOccurred()) + Expect(bitCount.Val()).To(Equal(int64(26))) + + bitCount = client.BitCount("key", &redis.BitCount{0, 0}) + Expect(bitCount.Err()).NotTo(HaveOccurred()) + Expect(bitCount.Val()).To(Equal(int64(4))) + + bitCount = client.BitCount("key", &redis.BitCount{1, 1}) + Expect(bitCount.Err()).NotTo(HaveOccurred()) + Expect(bitCount.Val()).To(Equal(int64(6))) + }) + + It("should BitOpAnd", func() { + set := client.Set("key1", "1") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + set = client.Set("key2", "0") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + bitOpAnd := client.BitOpAnd("dest", "key1", "key2") + Expect(bitOpAnd.Err()).NotTo(HaveOccurred()) + Expect(bitOpAnd.Val()).To(Equal(int64(1))) + + get := client.Get("dest") + Expect(get.Err()).NotTo(HaveOccurred()) + Expect(get.Val()).To(Equal("0")) + }) + + It("should BitOpOr", func() { + set := client.Set("key1", "1") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + set = client.Set("key2", "0") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + bitOpOr := client.BitOpOr("dest", "key1", "key2") + Expect(bitOpOr.Err()).NotTo(HaveOccurred()) + Expect(bitOpOr.Val()).To(Equal(int64(1))) + + get := client.Get("dest") + Expect(get.Err()).NotTo(HaveOccurred()) + Expect(get.Val()).To(Equal("1")) + }) + + It("should BitOpXor", func() { + set := client.Set("key1", "\xff") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + set = client.Set("key2", "\x0f") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + bitOpXor := client.BitOpXor("dest", "key1", "key2") + Expect(bitOpXor.Err()).NotTo(HaveOccurred()) + Expect(bitOpXor.Val()).To(Equal(int64(1))) + + get := client.Get("dest") + Expect(get.Err()).NotTo(HaveOccurred()) + Expect(get.Val()).To(Equal("\xf0")) + }) + + It("should BitOpNot", func() { + set := client.Set("key1", "\x00") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + bitOpNot := client.BitOpNot("dest", "key1") + Expect(bitOpNot.Err()).NotTo(HaveOccurred()) + Expect(bitOpNot.Val()).To(Equal(int64(1))) + + get := client.Get("dest") + Expect(get.Err()).NotTo(HaveOccurred()) + Expect(get.Val()).To(Equal("\xff")) + }) + + It("should Decr", func() { + set := client.Set("key", "10") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + decr := client.Decr("key") + Expect(decr.Err()).NotTo(HaveOccurred()) + Expect(decr.Val()).To(Equal(int64(9))) + + set = client.Set("key", "234293482390480948029348230948") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + decr = client.Decr("key") + Expect(decr.Err()).To(MatchError("ERR value is not an integer or out of range")) + Expect(decr.Val()).To(Equal(int64(0))) + }) + + It("should DecrBy", func() { + set := client.Set("key", "10") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + decrBy := client.DecrBy("key", 5) + Expect(decrBy.Err()).NotTo(HaveOccurred()) + Expect(decrBy.Val()).To(Equal(int64(5))) + }) + + It("should Get", func() { + get := client.Get("_") + Expect(get.Err()).To(Equal(redis.Nil)) + Expect(get.Val()).To(Equal("")) + + set := client.Set("key", "hello") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + get = client.Get("key") + Expect(get.Err()).NotTo(HaveOccurred()) + Expect(get.Val()).To(Equal("hello")) + }) + + It("should GetBit", func() { + setBit := client.SetBit("key", 7, 1) + Expect(setBit.Err()).NotTo(HaveOccurred()) + Expect(setBit.Val()).To(Equal(int64(0))) + + getBit := client.GetBit("key", 0) + Expect(getBit.Err()).NotTo(HaveOccurred()) + Expect(getBit.Val()).To(Equal(int64(0))) + + getBit = client.GetBit("key", 7) + Expect(getBit.Err()).NotTo(HaveOccurred()) + Expect(getBit.Val()).To(Equal(int64(1))) + + getBit = client.GetBit("key", 100) + Expect(getBit.Err()).NotTo(HaveOccurred()) + Expect(getBit.Val()).To(Equal(int64(0))) + }) + + It("should GetRange", func() { + set := client.Set("key", "This is a string") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + getRange := client.GetRange("key", 0, 3) + Expect(getRange.Err()).NotTo(HaveOccurred()) + Expect(getRange.Val()).To(Equal("This")) + + getRange = client.GetRange("key", -3, -1) + Expect(getRange.Err()).NotTo(HaveOccurred()) + Expect(getRange.Val()).To(Equal("ing")) + + getRange = client.GetRange("key", 0, -1) + Expect(getRange.Err()).NotTo(HaveOccurred()) + Expect(getRange.Val()).To(Equal("This is a string")) + + getRange = client.GetRange("key", 10, 100) + Expect(getRange.Err()).NotTo(HaveOccurred()) + Expect(getRange.Val()).To(Equal("string")) + }) + + It("should GetSet", func() { + incr := client.Incr("key") + Expect(incr.Err()).NotTo(HaveOccurred()) + Expect(incr.Val()).To(Equal(int64(1))) + + getSet := client.GetSet("key", "0") + Expect(getSet.Err()).NotTo(HaveOccurred()) + Expect(getSet.Val()).To(Equal("1")) + + get := client.Get("key") + Expect(get.Err()).NotTo(HaveOccurred()) + Expect(get.Val()).To(Equal("0")) + }) + + It("should Incr", func() { + set := client.Set("key", "10") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + incr := client.Incr("key") + Expect(incr.Err()).NotTo(HaveOccurred()) + Expect(incr.Val()).To(Equal(int64(11))) + + get := client.Get("key") + Expect(get.Err()).NotTo(HaveOccurred()) + Expect(get.Val()).To(Equal("11")) + }) + + It("should IncrBy", func() { + set := client.Set("key", "10") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + incrBy := client.IncrBy("key", 5) + Expect(incrBy.Err()).NotTo(HaveOccurred()) + Expect(incrBy.Val()).To(Equal(int64(15))) + }) + + It("should IncrByFloat", func() { + set := client.Set("key", "10.50") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + incrByFloat := client.IncrByFloat("key", 0.1) + Expect(incrByFloat.Err()).NotTo(HaveOccurred()) + Expect(incrByFloat.Val()).To(Equal(10.6)) + + set = client.Set("key", "5.0e3") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + incrByFloat = client.IncrByFloat("key", 2.0e2) + Expect(incrByFloat.Err()).NotTo(HaveOccurred()) + Expect(incrByFloat.Val()).To(Equal(float64(5200))) + }) + + It("should IncrByFloatOverflow", func() { + incrByFloat := client.IncrByFloat("key", 996945661) + Expect(incrByFloat.Err()).NotTo(HaveOccurred()) + Expect(incrByFloat.Val()).To(Equal(float64(996945661))) + }) + + It("should MSetMGet", func() { + mSet := client.MSet("key1", "hello1", "key2", "hello2") + Expect(mSet.Err()).NotTo(HaveOccurred()) + Expect(mSet.Val()).To(Equal("OK")) + + mGet := client.MGet("key1", "key2", "_") + Expect(mGet.Err()).NotTo(HaveOccurred()) + Expect(mGet.Val()).To(Equal([]interface{}{"hello1", "hello2", nil})) + }) + + It("should MSetNX", func() { + mSetNX := client.MSetNX("key1", "hello1", "key2", "hello2") + Expect(mSetNX.Err()).NotTo(HaveOccurred()) + Expect(mSetNX.Val()).To(Equal(true)) + + mSetNX = client.MSetNX("key2", "hello1", "key3", "hello2") + Expect(mSetNX.Err()).NotTo(HaveOccurred()) + Expect(mSetNX.Val()).To(Equal(false)) + }) + + It("should PSetEx", func() { + expiration := 50 * time.Millisecond + psetex := client.PSetEx("key", expiration, "hello") + Expect(psetex.Err()).NotTo(HaveOccurred()) + Expect(psetex.Val()).To(Equal("OK")) + + pttl := client.PTTL("key") + Expect(pttl.Err()).NotTo(HaveOccurred()) + Expect(pttl.Val() <= expiration).To(Equal(true)) + Expect(pttl.Val() >= expiration-time.Millisecond).To(Equal(true)) + + get := client.Get("key") + Expect(get.Err()).NotTo(HaveOccurred()) + Expect(get.Val()).To(Equal("hello")) + }) + + It("should SetGet", func() { + set := client.Set("key", "hello") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + get := client.Get("key") + Expect(get.Err()).NotTo(HaveOccurred()) + Expect(get.Val()).To(Equal("hello")) + }) + + It("should SetEx", func() { + setEx := client.SetEx("key", 10*time.Second, "hello") + Expect(setEx.Err()).NotTo(HaveOccurred()) + Expect(setEx.Val()).To(Equal("OK")) + + ttl := client.TTL("key") + Expect(ttl.Err()).NotTo(HaveOccurred()) + Expect(ttl.Val()).To(Equal(10 * time.Second)) + }) + + It("should SetNX", func() { + setNX := client.SetNX("key", "hello") + Expect(setNX.Err()).NotTo(HaveOccurred()) + Expect(setNX.Val()).To(Equal(true)) + + setNX = client.SetNX("key", "hello2") + Expect(setNX.Err()).NotTo(HaveOccurred()) + Expect(setNX.Val()).To(Equal(false)) + + get := client.Get("key") + Expect(get.Err()).NotTo(HaveOccurred()) + Expect(get.Val()).To(Equal("hello")) + }) + + It("should SetRange", func() { + set := client.Set("key", "Hello World") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + range_ := client.SetRange("key", 6, "Redis") + Expect(range_.Err()).NotTo(HaveOccurred()) + Expect(range_.Val()).To(Equal(int64(11))) + + get := client.Get("key") + Expect(get.Err()).NotTo(HaveOccurred()) + Expect(get.Val()).To(Equal("Hello Redis")) + }) + + It("should StrLen", func() { + set := client.Set("key", "hello") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + strLen := client.StrLen("key") + Expect(strLen.Err()).NotTo(HaveOccurred()) + Expect(strLen.Val()).To(Equal(int64(5))) + + strLen = client.StrLen("_") + Expect(strLen.Err()).NotTo(HaveOccurred()) + Expect(strLen.Val()).To(Equal(int64(0))) + }) + + }) + + //------------------------------------------------------------------------------ + + Describe("hashes", func() { + + It("should HDel", func() { + hSet := client.HSet("hash", "key", "hello") + Expect(hSet.Err()).NotTo(HaveOccurred()) + + hDel := client.HDel("hash", "key") + Expect(hDel.Err()).NotTo(HaveOccurred()) + Expect(hDel.Val()).To(Equal(int64(1))) + + hDel = client.HDel("hash", "key") + Expect(hDel.Err()).NotTo(HaveOccurred()) + Expect(hDel.Val()).To(Equal(int64(0))) + }) + + It("should HExists", func() { + hSet := client.HSet("hash", "key", "hello") + Expect(hSet.Err()).NotTo(HaveOccurred()) + + hExists := client.HExists("hash", "key") + Expect(hExists.Err()).NotTo(HaveOccurred()) + Expect(hExists.Val()).To(Equal(true)) + + hExists = client.HExists("hash", "key1") + Expect(hExists.Err()).NotTo(HaveOccurred()) + Expect(hExists.Val()).To(Equal(false)) + }) + + It("should HGet", func() { + hSet := client.HSet("hash", "key", "hello") + Expect(hSet.Err()).NotTo(HaveOccurred()) + + hGet := client.HGet("hash", "key") + Expect(hGet.Err()).NotTo(HaveOccurred()) + Expect(hGet.Val()).To(Equal("hello")) + + hGet = client.HGet("hash", "key1") + Expect(hGet.Err()).To(Equal(redis.Nil)) + Expect(hGet.Val()).To(Equal("")) + }) + + It("should HGetAll", func() { + hSet := client.HSet("hash", "key1", "hello1") + Expect(hSet.Err()).NotTo(HaveOccurred()) + hSet = client.HSet("hash", "key2", "hello2") + Expect(hSet.Err()).NotTo(HaveOccurred()) + + hGetAll := client.HGetAll("hash") + Expect(hGetAll.Err()).NotTo(HaveOccurred()) + Expect(hGetAll.Val()).To(Equal([]string{"key1", "hello1", "key2", "hello2"})) + }) + + It("should HGetAllMap", func() { + hSet := client.HSet("hash", "key1", "hello1") + Expect(hSet.Err()).NotTo(HaveOccurred()) + hSet = client.HSet("hash", "key2", "hello2") + Expect(hSet.Err()).NotTo(HaveOccurred()) + + hGetAll := client.HGetAllMap("hash") + Expect(hGetAll.Err()).NotTo(HaveOccurred()) + Expect(hGetAll.Val()).To(Equal(map[string]string{"key1": "hello1", "key2": "hello2"})) + }) + + It("should HIncrBy", func() { + hSet := client.HSet("hash", "key", "5") + Expect(hSet.Err()).NotTo(HaveOccurred()) + + hIncrBy := client.HIncrBy("hash", "key", 1) + Expect(hIncrBy.Err()).NotTo(HaveOccurred()) + Expect(hIncrBy.Val()).To(Equal(int64(6))) + + hIncrBy = client.HIncrBy("hash", "key", -1) + Expect(hIncrBy.Err()).NotTo(HaveOccurred()) + Expect(hIncrBy.Val()).To(Equal(int64(5))) + + hIncrBy = client.HIncrBy("hash", "key", -10) + Expect(hIncrBy.Err()).NotTo(HaveOccurred()) + Expect(hIncrBy.Val()).To(Equal(int64(-5))) + }) + + It("should HIncrByFloat", func() { + hSet := client.HSet("hash", "field", "10.50") + Expect(hSet.Err()).NotTo(HaveOccurred()) + Expect(hSet.Val()).To(Equal(true)) + + hIncrByFloat := client.HIncrByFloat("hash", "field", 0.1) + Expect(hIncrByFloat.Err()).NotTo(HaveOccurred()) + Expect(hIncrByFloat.Val()).To(Equal(10.6)) + + hSet = client.HSet("hash", "field", "5.0e3") + Expect(hSet.Err()).NotTo(HaveOccurred()) + Expect(hSet.Val()).To(Equal(false)) + + hIncrByFloat = client.HIncrByFloat("hash", "field", 2.0e2) + Expect(hIncrByFloat.Err()).NotTo(HaveOccurred()) + Expect(hIncrByFloat.Val()).To(Equal(float64(5200))) + }) + + It("should HKeys", func() { + hkeys := client.HKeys("hash") + Expect(hkeys.Err()).NotTo(HaveOccurred()) + Expect(hkeys.Val()).To(Equal([]string{})) + + hset := client.HSet("hash", "key1", "hello1") + Expect(hset.Err()).NotTo(HaveOccurred()) + hset = client.HSet("hash", "key2", "hello2") + Expect(hset.Err()).NotTo(HaveOccurred()) + + hkeys = client.HKeys("hash") + Expect(hkeys.Err()).NotTo(HaveOccurred()) + Expect(hkeys.Val()).To(Equal([]string{"key1", "key2"})) + }) + + It("should HLen", func() { + hSet := client.HSet("hash", "key1", "hello1") + Expect(hSet.Err()).NotTo(HaveOccurred()) + hSet = client.HSet("hash", "key2", "hello2") + Expect(hSet.Err()).NotTo(HaveOccurred()) + + hLen := client.HLen("hash") + Expect(hLen.Err()).NotTo(HaveOccurred()) + Expect(hLen.Val()).To(Equal(int64(2))) + }) + + It("should HMGet", func() { + hSet := client.HSet("hash", "key1", "hello1") + Expect(hSet.Err()).NotTo(HaveOccurred()) + hSet = client.HSet("hash", "key2", "hello2") + Expect(hSet.Err()).NotTo(HaveOccurred()) + + hMGet := client.HMGet("hash", "key1", "key2", "_") + Expect(hMGet.Err()).NotTo(HaveOccurred()) + Expect(hMGet.Val()).To(Equal([]interface{}{"hello1", "hello2", nil})) + }) + + It("should HMSet", func() { + hMSet := client.HMSet("hash", "key1", "hello1", "key2", "hello2") + Expect(hMSet.Err()).NotTo(HaveOccurred()) + Expect(hMSet.Val()).To(Equal("OK")) + + hGet := client.HGet("hash", "key1") + Expect(hGet.Err()).NotTo(HaveOccurred()) + Expect(hGet.Val()).To(Equal("hello1")) + + hGet = client.HGet("hash", "key2") + Expect(hGet.Err()).NotTo(HaveOccurred()) + Expect(hGet.Val()).To(Equal("hello2")) + }) + + It("should HSet", func() { + hSet := client.HSet("hash", "key", "hello") + Expect(hSet.Err()).NotTo(HaveOccurred()) + Expect(hSet.Val()).To(Equal(true)) + + hGet := client.HGet("hash", "key") + Expect(hGet.Err()).NotTo(HaveOccurred()) + Expect(hGet.Val()).To(Equal("hello")) + }) + + It("should HSetNX", func() { + hSetNX := client.HSetNX("hash", "key", "hello") + Expect(hSetNX.Err()).NotTo(HaveOccurred()) + Expect(hSetNX.Val()).To(Equal(true)) + + hSetNX = client.HSetNX("hash", "key", "hello") + Expect(hSetNX.Err()).NotTo(HaveOccurred()) + Expect(hSetNX.Val()).To(Equal(false)) + + hGet := client.HGet("hash", "key") + Expect(hGet.Err()).NotTo(HaveOccurred()) + Expect(hGet.Val()).To(Equal("hello")) + }) + + It("should HVals", func() { + hSet := client.HSet("hash", "key1", "hello1") + Expect(hSet.Err()).NotTo(HaveOccurred()) + hSet = client.HSet("hash", "key2", "hello2") + Expect(hSet.Err()).NotTo(HaveOccurred()) + + hVals := client.HVals("hash") + Expect(hVals.Err()).NotTo(HaveOccurred()) + Expect(hVals.Val()).To(Equal([]string{"hello1", "hello2"})) + }) + + }) + + //------------------------------------------------------------------------------ + + Describe("lists", func() { + + It("should BLPop", func() { + rPush := client.RPush("list1", "a", "b", "c") + Expect(rPush.Err()).NotTo(HaveOccurred()) + + bLPop := client.BLPop(0, "list1", "list2") + Expect(bLPop.Err()).NotTo(HaveOccurred()) + Expect(bLPop.Val()).To(Equal([]string{"list1", "a"})) + }) + + It("should BLPopBlocks", func() { + started := make(chan bool) + done := make(chan bool) + go func() { + started <- true + bLPop := client.BLPop(0, "list") + Expect(bLPop.Err()).NotTo(HaveOccurred()) + Expect(bLPop.Val()).To(Equal([]string{"list", "a"})) + done <- true + }() + <-started + + select { + case <-done: + Fail("BLPop is not blocked") + case <-time.After(time.Second): + // ok + } + + rPush := client.RPush("list", "a") + Expect(rPush.Err()).NotTo(HaveOccurred()) + + select { + case <-done: + // ok + case <-time.After(time.Second): + Fail("BLPop is still blocked") + } + }) + + It("should BLPop timeout", func() { + bLPop := client.BLPop(1, "list1") + Expect(bLPop.Val()).To(BeNil()) + Expect(bLPop.Err()).To(Equal(redis.Nil)) + }) + + It("should BRPop", func() { + rPush := client.RPush("list1", "a", "b", "c") + Expect(rPush.Err()).NotTo(HaveOccurred()) + + bRPop := client.BRPop(0, "list1", "list2") + Expect(bRPop.Err()).NotTo(HaveOccurred()) + Expect(bRPop.Val()).To(Equal([]string{"list1", "c"})) + }) + + It("should BRPopBlocks", func() { + started := make(chan bool) + done := make(chan bool) + go func() { + started <- true + brpop := client.BRPop(0, "list") + Expect(brpop.Err()).NotTo(HaveOccurred()) + Expect(brpop.Val()).To(Equal([]string{"list", "a"})) + done <- true + }() + <-started + + select { + case <-done: + Fail("BRPop is not blocked") + case <-time.After(time.Second): + // ok + } + + rPush := client.RPush("list", "a") + Expect(rPush.Err()).NotTo(HaveOccurred()) + + select { + case <-done: + // ok + case <-time.After(time.Second): + Fail("BRPop is still blocked") + // ok + } + }) + + It("should BRPopLPush", func() { + rPush := client.RPush("list1", "a", "b", "c") + Expect(rPush.Err()).NotTo(HaveOccurred()) + + bRPopLPush := client.BRPopLPush("list1", "list2", 0) + Expect(bRPopLPush.Err()).NotTo(HaveOccurred()) + Expect(bRPopLPush.Val()).To(Equal("c")) + }) + + It("should LIndex", func() { + lPush := client.LPush("list", "World") + Expect(lPush.Err()).NotTo(HaveOccurred()) + lPush = client.LPush("list", "Hello") + Expect(lPush.Err()).NotTo(HaveOccurred()) + + lIndex := client.LIndex("list", 0) + Expect(lIndex.Err()).NotTo(HaveOccurred()) + Expect(lIndex.Val()).To(Equal("Hello")) + + lIndex = client.LIndex("list", -1) + Expect(lIndex.Err()).NotTo(HaveOccurred()) + Expect(lIndex.Val()).To(Equal("World")) + + lIndex = client.LIndex("list", 3) + Expect(lIndex.Err()).To(Equal(redis.Nil)) + Expect(lIndex.Val()).To(Equal("")) + }) + + It("should LInsert", func() { + rPush := client.RPush("list", "Hello") + Expect(rPush.Err()).NotTo(HaveOccurred()) + rPush = client.RPush("list", "World") + Expect(rPush.Err()).NotTo(HaveOccurred()) + + lInsert := client.LInsert("list", "BEFORE", "World", "There") + Expect(lInsert.Err()).NotTo(HaveOccurred()) + Expect(lInsert.Val()).To(Equal(int64(3))) + + lRange := client.LRange("list", 0, -1) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{"Hello", "There", "World"})) + }) + + It("should LLen", func() { + lPush := client.LPush("list", "World") + Expect(lPush.Err()).NotTo(HaveOccurred()) + lPush = client.LPush("list", "Hello") + Expect(lPush.Err()).NotTo(HaveOccurred()) + + lLen := client.LLen("list") + Expect(lLen.Err()).NotTo(HaveOccurred()) + Expect(lLen.Val()).To(Equal(int64(2))) + }) + + It("should LPop", func() { + rPush := client.RPush("list", "one") + Expect(rPush.Err()).NotTo(HaveOccurred()) + rPush = client.RPush("list", "two") + Expect(rPush.Err()).NotTo(HaveOccurred()) + rPush = client.RPush("list", "three") + Expect(rPush.Err()).NotTo(HaveOccurred()) + + lPop := client.LPop("list") + Expect(lPop.Err()).NotTo(HaveOccurred()) + Expect(lPop.Val()).To(Equal("one")) + + lRange := client.LRange("list", 0, -1) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{"two", "three"})) + }) + + It("should LPush", func() { + lPush := client.LPush("list", "World") + Expect(lPush.Err()).NotTo(HaveOccurred()) + lPush = client.LPush("list", "Hello") + Expect(lPush.Err()).NotTo(HaveOccurred()) + + lRange := client.LRange("list", 0, -1) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{"Hello", "World"})) + }) + + It("should LPushX", func() { + lPush := client.LPush("list", "World") + Expect(lPush.Err()).NotTo(HaveOccurred()) + + lPushX := client.LPushX("list", "Hello") + Expect(lPushX.Err()).NotTo(HaveOccurred()) + Expect(lPushX.Val()).To(Equal(int64(2))) + + lPushX = client.LPushX("list2", "Hello") + Expect(lPushX.Err()).NotTo(HaveOccurred()) + Expect(lPushX.Val()).To(Equal(int64(0))) + + lRange := client.LRange("list", 0, -1) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{"Hello", "World"})) + + lRange = client.LRange("list2", 0, -1) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{})) + }) + + It("should LRange", func() { + rPush := client.RPush("list", "one") + Expect(rPush.Err()).NotTo(HaveOccurred()) + rPush = client.RPush("list", "two") + Expect(rPush.Err()).NotTo(HaveOccurred()) + rPush = client.RPush("list", "three") + Expect(rPush.Err()).NotTo(HaveOccurred()) + + lRange := client.LRange("list", 0, 0) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{"one"})) + + lRange = client.LRange("list", -3, 2) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{"one", "two", "three"})) + + lRange = client.LRange("list", -100, 100) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{"one", "two", "three"})) + + lRange = client.LRange("list", 5, 10) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{})) + }) + + It("should LRem", func() { + rPush := client.RPush("list", "hello") + Expect(rPush.Err()).NotTo(HaveOccurred()) + rPush = client.RPush("list", "hello") + Expect(rPush.Err()).NotTo(HaveOccurred()) + rPush = client.RPush("list", "key") + Expect(rPush.Err()).NotTo(HaveOccurred()) + rPush = client.RPush("list", "hello") + Expect(rPush.Err()).NotTo(HaveOccurred()) + + lRem := client.LRem("list", -2, "hello") + Expect(lRem.Err()).NotTo(HaveOccurred()) + Expect(lRem.Val()).To(Equal(int64(2))) + + lRange := client.LRange("list", 0, -1) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{"hello", "key"})) + }) + + It("should LSet", func() { + rPush := client.RPush("list", "one") + Expect(rPush.Err()).NotTo(HaveOccurred()) + rPush = client.RPush("list", "two") + Expect(rPush.Err()).NotTo(HaveOccurred()) + rPush = client.RPush("list", "three") + Expect(rPush.Err()).NotTo(HaveOccurred()) + + lSet := client.LSet("list", 0, "four") + Expect(lSet.Err()).NotTo(HaveOccurred()) + Expect(lSet.Val()).To(Equal("OK")) + + lSet = client.LSet("list", -2, "five") + Expect(lSet.Err()).NotTo(HaveOccurred()) + Expect(lSet.Val()).To(Equal("OK")) + + lRange := client.LRange("list", 0, -1) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{"four", "five", "three"})) + }) + + It("should LTrim", func() { + rPush := client.RPush("list", "one") + Expect(rPush.Err()).NotTo(HaveOccurred()) + rPush = client.RPush("list", "two") + Expect(rPush.Err()).NotTo(HaveOccurred()) + rPush = client.RPush("list", "three") + Expect(rPush.Err()).NotTo(HaveOccurred()) + + lTrim := client.LTrim("list", 1, -1) + Expect(lTrim.Err()).NotTo(HaveOccurred()) + Expect(lTrim.Val()).To(Equal("OK")) + + lRange := client.LRange("list", 0, -1) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{"two", "three"})) + }) + + It("should RPop", func() { + rPush := client.RPush("list", "one") + Expect(rPush.Err()).NotTo(HaveOccurred()) + rPush = client.RPush("list", "two") + Expect(rPush.Err()).NotTo(HaveOccurred()) + rPush = client.RPush("list", "three") + Expect(rPush.Err()).NotTo(HaveOccurred()) + + rPop := client.RPop("list") + Expect(rPop.Err()).NotTo(HaveOccurred()) + Expect(rPop.Val()).To(Equal("three")) + + lRange := client.LRange("list", 0, -1) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{"one", "two"})) + }) + + It("should RPopLPush", func() { + rPush := client.RPush("list", "one") + Expect(rPush.Err()).NotTo(HaveOccurred()) + rPush = client.RPush("list", "two") + Expect(rPush.Err()).NotTo(HaveOccurred()) + rPush = client.RPush("list", "three") + Expect(rPush.Err()).NotTo(HaveOccurred()) + + rPopLPush := client.RPopLPush("list", "list2") + Expect(rPopLPush.Err()).NotTo(HaveOccurred()) + Expect(rPopLPush.Val()).To(Equal("three")) + + lRange := client.LRange("list", 0, -1) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{"one", "two"})) + + lRange = client.LRange("list2", 0, -1) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{"three"})) + }) + + It("should RPush", func() { + rPush := client.RPush("list", "Hello") + Expect(rPush.Err()).NotTo(HaveOccurred()) + Expect(rPush.Val()).To(Equal(int64(1))) + + rPush = client.RPush("list", "World") + Expect(rPush.Err()).NotTo(HaveOccurred()) + Expect(rPush.Val()).To(Equal(int64(2))) + + lRange := client.LRange("list", 0, -1) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{"Hello", "World"})) + }) + + It("should RPushX", func() { + rPush := client.RPush("list", "Hello") + Expect(rPush.Err()).NotTo(HaveOccurred()) + Expect(rPush.Val()).To(Equal(int64(1))) + + rPushX := client.RPushX("list", "World") + Expect(rPushX.Err()).NotTo(HaveOccurred()) + Expect(rPushX.Val()).To(Equal(int64(2))) + + rPushX = client.RPushX("list2", "World") + Expect(rPushX.Err()).NotTo(HaveOccurred()) + Expect(rPushX.Val()).To(Equal(int64(0))) + + lRange := client.LRange("list", 0, -1) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{"Hello", "World"})) + + lRange = client.LRange("list2", 0, -1) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{})) + }) + + }) + + //------------------------------------------------------------------------------ + + Describe("sets", func() { + + It("should SAdd", func() { + sAdd := client.SAdd("set", "Hello") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + Expect(sAdd.Val()).To(Equal(int64(1))) + + sAdd = client.SAdd("set", "World") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + Expect(sAdd.Val()).To(Equal(int64(1))) + + sAdd = client.SAdd("set", "World") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + Expect(sAdd.Val()).To(Equal(int64(0))) + + sMembers := client.SMembers("set") + Expect(sMembers.Err()).NotTo(HaveOccurred()) + Expect(sortStrings(sMembers.Val())).To(Equal([]string{"Hello", "World"})) + }) + + It("should SCard", func() { + sAdd := client.SAdd("set", "Hello") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + Expect(sAdd.Val()).To(Equal(int64(1))) + + sAdd = client.SAdd("set", "World") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + Expect(sAdd.Val()).To(Equal(int64(1))) + + sCard := client.SCard("set") + Expect(sCard.Err()).NotTo(HaveOccurred()) + Expect(sCard.Val()).To(Equal(int64(2))) + }) + + It("should SDiff", func() { + sAdd := client.SAdd("set1", "a") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd("set1", "b") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd("set1", "c") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sAdd = client.SAdd("set2", "c") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd("set2", "d") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd("set2", "e") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sDiff := client.SDiff("set1", "set2") + Expect(sDiff.Err()).NotTo(HaveOccurred()) + Expect(sortStrings(sDiff.Val())).To(Equal([]string{"a", "b"})) + }) + + It("should SDiffStore", func() { + sAdd := client.SAdd("set1", "a") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd("set1", "b") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd("set1", "c") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sAdd = client.SAdd("set2", "c") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd("set2", "d") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd("set2", "e") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sDiffStore := client.SDiffStore("set", "set1", "set2") + Expect(sDiffStore.Err()).NotTo(HaveOccurred()) + Expect(sDiffStore.Val()).To(Equal(int64(2))) + + sMembers := client.SMembers("set") + Expect(sMembers.Err()).NotTo(HaveOccurred()) + Expect(sortStrings(sMembers.Val())).To(Equal([]string{"a", "b"})) + }) + + It("should SInter", func() { + sAdd := client.SAdd("set1", "a") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd("set1", "b") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd("set1", "c") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sAdd = client.SAdd("set2", "c") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd("set2", "d") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd("set2", "e") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sInter := client.SInter("set1", "set2") + Expect(sInter.Err()).NotTo(HaveOccurred()) + Expect(sInter.Val()).To(Equal([]string{"c"})) + }) + + It("should SInterStore", func() { + sAdd := client.SAdd("set1", "a") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd("set1", "b") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd("set1", "c") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sAdd = client.SAdd("set2", "c") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd("set2", "d") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd("set2", "e") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sInterStore := client.SInterStore("set", "set1", "set2") + Expect(sInterStore.Err()).NotTo(HaveOccurred()) + Expect(sInterStore.Val()).To(Equal(int64(1))) + + sMembers := client.SMembers("set") + Expect(sMembers.Err()).NotTo(HaveOccurred()) + Expect(sMembers.Val()).To(Equal([]string{"c"})) + }) + + It("should IsMember", func() { + sAdd := client.SAdd("set", "one") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sIsMember := client.SIsMember("set", "one") + Expect(sIsMember.Err()).NotTo(HaveOccurred()) + Expect(sIsMember.Val()).To(Equal(true)) + + sIsMember = client.SIsMember("set", "two") + Expect(sIsMember.Err()).NotTo(HaveOccurred()) + Expect(sIsMember.Val()).To(Equal(false)) + }) + + It("should SMembers", func() { + sAdd := client.SAdd("set", "Hello") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd("set", "World") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sMembers := client.SMembers("set") + Expect(sMembers.Err()).NotTo(HaveOccurred()) + Expect(sortStrings(sMembers.Val())).To(Equal([]string{"Hello", "World"})) + }) + + It("should SMove", func() { + sAdd := client.SAdd("set1", "one") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd("set1", "two") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sAdd = client.SAdd("set2", "three") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sMove := client.SMove("set1", "set2", "two") + Expect(sMove.Err()).NotTo(HaveOccurred()) + Expect(sMove.Val()).To(Equal(true)) + + sMembers := client.SMembers("set1") + Expect(sMembers.Err()).NotTo(HaveOccurred()) + Expect(sMembers.Val()).To(Equal([]string{"one"})) + + sMembers = client.SMembers("set2") + Expect(sMembers.Err()).NotTo(HaveOccurred()) + Expect(sortStrings(sMembers.Val())).To(Equal([]string{"three", "two"})) + }) + + It("should SPop", func() { + sAdd := client.SAdd("set", "one") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd("set", "two") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd("set", "three") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sPop := client.SPop("set") + Expect(sPop.Err()).NotTo(HaveOccurred()) + Expect(sPop.Val()).NotTo(Equal("")) + + sMembers := client.SMembers("set") + Expect(sMembers.Err()).NotTo(HaveOccurred()) + Expect(sMembers.Val()).To(HaveLen(2)) + }) + + It("should SRandMember", func() { + sAdd := client.SAdd("set", "one") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd("set", "two") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd("set", "three") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sRandMember := client.SRandMember("set") + Expect(sRandMember.Err()).NotTo(HaveOccurred()) + Expect(sRandMember.Val()).NotTo(Equal("")) + + sMembers := client.SMembers("set") + Expect(sMembers.Err()).NotTo(HaveOccurred()) + Expect(sMembers.Val()).To(HaveLen(3)) + }) + + It("should SRem", func() { + sAdd := client.SAdd("set", "one") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd("set", "two") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd("set", "three") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sRem := client.SRem("set", "one") + Expect(sRem.Err()).NotTo(HaveOccurred()) + Expect(sRem.Val()).To(Equal(int64(1))) + + sRem = client.SRem("set", "four") + Expect(sRem.Err()).NotTo(HaveOccurred()) + Expect(sRem.Val()).To(Equal(int64(0))) + + sMembers := client.SMembers("set") + Expect(sMembers.Err()).NotTo(HaveOccurred()) + Expect(sortStrings(sMembers.Val())).To(ConsistOf([]string{"three", "two"})) + }) + + It("should SUnion", func() { + sAdd := client.SAdd("set1", "a") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd("set1", "b") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd("set1", "c") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sAdd = client.SAdd("set2", "c") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd("set2", "d") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd("set2", "e") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sUnion := client.SUnion("set1", "set2") + Expect(sUnion.Err()).NotTo(HaveOccurred()) + Expect(sUnion.Val()).To(HaveLen(5)) + }) + + It("should SUnionStore", func() { + sAdd := client.SAdd("set1", "a") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd("set1", "b") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd("set1", "c") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sAdd = client.SAdd("set2", "c") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd("set2", "d") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd("set2", "e") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sUnionStore := client.SUnionStore("set", "set1", "set2") + Expect(sUnionStore.Err()).NotTo(HaveOccurred()) + Expect(sUnionStore.Val()).To(Equal(int64(5))) + + sMembers := client.SMembers("set") + Expect(sMembers.Err()).NotTo(HaveOccurred()) + Expect(sMembers.Val()).To(HaveLen(5)) + }) + + }) + + //------------------------------------------------------------------------------ + + Describe("sorted sets", func() { + + It("should ZAdd", func() { + zAdd := client.ZAdd("zset", redis.Z{1, "one"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + Expect(zAdd.Val()).To(Equal(int64(1))) + + zAdd = client.ZAdd("zset", redis.Z{1, "uno"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + Expect(zAdd.Val()).To(Equal(int64(1))) + + zAdd = client.ZAdd("zset", redis.Z{2, "two"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + Expect(zAdd.Val()).To(Equal(int64(1))) + + zAdd = client.ZAdd("zset", redis.Z{3, "two"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + Expect(zAdd.Val()).To(Equal(int64(0))) + + val, err := client.ZRangeWithScores("zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]redis.Z{{1, "one"}, {1, "uno"}, {3, "two"}})) + }) + + It("should ZCard", func() { + zAdd := client.ZAdd("zset", redis.Z{1, "one"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + zAdd = client.ZAdd("zset", redis.Z{2, "two"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + + zCard := client.ZCard("zset") + Expect(zCard.Err()).NotTo(HaveOccurred()) + Expect(zCard.Val()).To(Equal(int64(2))) + }) + + It("should ZCount", func() { + zAdd := client.ZAdd("zset", redis.Z{1, "one"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + zAdd = client.ZAdd("zset", redis.Z{2, "two"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + zAdd = client.ZAdd("zset", redis.Z{3, "three"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + + zCount := client.ZCount("zset", "-inf", "+inf") + Expect(zCount.Err()).NotTo(HaveOccurred()) + Expect(zCount.Val()).To(Equal(int64(3))) + + zCount = client.ZCount("zset", "(1", "3") + Expect(zCount.Err()).NotTo(HaveOccurred()) + Expect(zCount.Val()).To(Equal(int64(2))) + }) + + It("should ZIncrBy", func() { + zAdd := client.ZAdd("zset", redis.Z{1, "one"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + zAdd = client.ZAdd("zset", redis.Z{2, "two"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + + zIncrBy := client.ZIncrBy("zset", 2, "one") + Expect(zIncrBy.Err()).NotTo(HaveOccurred()) + Expect(zIncrBy.Val()).To(Equal(float64(3))) + + val, err := client.ZRangeWithScores("zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]redis.Z{{2, "two"}, {3, "one"}})) + }) + + It("should ZInterStore", func() { + zAdd := client.ZAdd("zset1", redis.Z{1, "one"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + zAdd = client.ZAdd("zset1", redis.Z{2, "two"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + + zAdd = client.ZAdd("zset2", redis.Z{1, "one"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + zAdd = client.ZAdd("zset2", redis.Z{2, "two"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + zAdd = client.ZAdd("zset3", redis.Z{3, "two"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + + zInterStore := client.ZInterStore( + "out", redis.ZStore{Weights: []int64{2, 3}}, "zset1", "zset2") + Expect(zInterStore.Err()).NotTo(HaveOccurred()) + Expect(zInterStore.Val()).To(Equal(int64(2))) + + val, err := client.ZRangeWithScores("out", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]redis.Z{{5, "one"}, {10, "two"}})) + }) + + It("should ZRange", func() { + zAdd := client.ZAdd("zset", redis.Z{1, "one"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + zAdd = client.ZAdd("zset", redis.Z{2, "two"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + zAdd = client.ZAdd("zset", redis.Z{3, "three"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + + zRange := client.ZRange("zset", 0, -1) + Expect(zRange.Err()).NotTo(HaveOccurred()) + Expect(zRange.Val()).To(Equal([]string{"one", "two", "three"})) + + zRange = client.ZRange("zset", 2, 3) + Expect(zRange.Err()).NotTo(HaveOccurred()) + Expect(zRange.Val()).To(Equal([]string{"three"})) + + zRange = client.ZRange("zset", -2, -1) + Expect(zRange.Err()).NotTo(HaveOccurred()) + Expect(zRange.Val()).To(Equal([]string{"two", "three"})) + }) + + It("should ZRangeWithScores", func() { + zAdd := client.ZAdd("zset", redis.Z{1, "one"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + zAdd = client.ZAdd("zset", redis.Z{2, "two"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + zAdd = client.ZAdd("zset", redis.Z{3, "three"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + + val, err := client.ZRangeWithScores("zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]redis.Z{{1, "one"}, {2, "two"}, {3, "three"}})) + + val, err = client.ZRangeWithScores("zset", 2, 3).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]redis.Z{{3, "three"}})) + + val, err = client.ZRangeWithScores("zset", -2, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]redis.Z{{2, "two"}, {3, "three"}})) + }) + + It("should ZRangeByScore", func() { + zAdd := client.ZAdd("zset", redis.Z{1, "one"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + zAdd = client.ZAdd("zset", redis.Z{2, "two"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + zAdd = client.ZAdd("zset", redis.Z{3, "three"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + + zRangeByScore := client.ZRangeByScore("zset", redis.ZRangeByScore{ + Min: "-inf", + Max: "+inf", + }) + Expect(zRangeByScore.Err()).NotTo(HaveOccurred()) + Expect(zRangeByScore.Val()).To(Equal([]string{"one", "two", "three"})) + + zRangeByScore = client.ZRangeByScore("zset", redis.ZRangeByScore{ + Min: "1", + Max: "2", + }) + Expect(zRangeByScore.Err()).NotTo(HaveOccurred()) + Expect(zRangeByScore.Val()).To(Equal([]string{"one", "two"})) + + zRangeByScore = client.ZRangeByScore("zset", redis.ZRangeByScore{ + Min: "(1", + Max: "2", + }) + Expect(zRangeByScore.Err()).NotTo(HaveOccurred()) + Expect(zRangeByScore.Val()).To(Equal([]string{"two"})) + + zRangeByScore = client.ZRangeByScore("zset", redis.ZRangeByScore{ + Min: "(1", + Max: "(2", + }) + Expect(zRangeByScore.Err()).NotTo(HaveOccurred()) + Expect(zRangeByScore.Val()).To(Equal([]string{})) + }) + + It("should ZRangeByScoreWithScoresMap", func() { + zAdd := client.ZAdd("zset", redis.Z{1, "one"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + zAdd = client.ZAdd("zset", redis.Z{2, "two"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + zAdd = client.ZAdd("zset", redis.Z{3, "three"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + + val, err := client.ZRangeByScoreWithScores("zset", redis.ZRangeByScore{ + Min: "-inf", + Max: "+inf", + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]redis.Z{{1, "one"}, {2, "two"}, {3, "three"}})) + + val, err = client.ZRangeByScoreWithScores("zset", redis.ZRangeByScore{ + Min: "1", + Max: "2", + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]redis.Z{{1, "one"}, {2, "two"}})) + + val, err = client.ZRangeByScoreWithScores("zset", redis.ZRangeByScore{ + Min: "(1", + Max: "2", + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]redis.Z{{2, "two"}})) + + val, err = client.ZRangeByScoreWithScores("zset", redis.ZRangeByScore{ + Min: "(1", + Max: "(2", + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]redis.Z{})) + }) + + It("should ZRank", func() { + zAdd := client.ZAdd("zset", redis.Z{1, "one"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + zAdd = client.ZAdd("zset", redis.Z{2, "two"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + zAdd = client.ZAdd("zset", redis.Z{3, "three"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + + zRank := client.ZRank("zset", "three") + Expect(zRank.Err()).NotTo(HaveOccurred()) + Expect(zRank.Val()).To(Equal(int64(2))) + + zRank = client.ZRank("zset", "four") + Expect(zRank.Err()).To(Equal(redis.Nil)) + Expect(zRank.Val()).To(Equal(int64(0))) + }) + + It("should ZRem", func() { + zAdd := client.ZAdd("zset", redis.Z{1, "one"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + zAdd = client.ZAdd("zset", redis.Z{2, "two"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + zAdd = client.ZAdd("zset", redis.Z{3, "three"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + + zRem := client.ZRem("zset", "two") + Expect(zRem.Err()).NotTo(HaveOccurred()) + Expect(zRem.Val()).To(Equal(int64(1))) + + val, err := client.ZRangeWithScores("zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]redis.Z{{1, "one"}, {3, "three"}})) + }) + + It("should ZRemRangeByRank", func() { + zAdd := client.ZAdd("zset", redis.Z{1, "one"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + zAdd = client.ZAdd("zset", redis.Z{2, "two"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + zAdd = client.ZAdd("zset", redis.Z{3, "three"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + + zRemRangeByRank := client.ZRemRangeByRank("zset", 0, 1) + Expect(zRemRangeByRank.Err()).NotTo(HaveOccurred()) + Expect(zRemRangeByRank.Val()).To(Equal(int64(2))) + + val, err := client.ZRangeWithScores("zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]redis.Z{{3, "three"}})) + }) + + It("should ZRemRangeByScore", func() { + zAdd := client.ZAdd("zset", redis.Z{1, "one"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + zAdd = client.ZAdd("zset", redis.Z{2, "two"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + zAdd = client.ZAdd("zset", redis.Z{3, "three"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + + zRemRangeByScore := client.ZRemRangeByScore("zset", "-inf", "(2") + Expect(zRemRangeByScore.Err()).NotTo(HaveOccurred()) + Expect(zRemRangeByScore.Val()).To(Equal(int64(1))) + + val, err := client.ZRangeWithScores("zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]redis.Z{{2, "two"}, {3, "three"}})) + }) + + It("should ZRevRange", func() { + zAdd := client.ZAdd("zset", redis.Z{1, "one"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + zAdd = client.ZAdd("zset", redis.Z{2, "two"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + zAdd = client.ZAdd("zset", redis.Z{3, "three"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + + zRevRange := client.ZRevRange("zset", "0", "-1") + Expect(zRevRange.Err()).NotTo(HaveOccurred()) + Expect(zRevRange.Val()).To(Equal([]string{"three", "two", "one"})) + + zRevRange = client.ZRevRange("zset", "2", "3") + Expect(zRevRange.Err()).NotTo(HaveOccurred()) + Expect(zRevRange.Val()).To(Equal([]string{"one"})) + + zRevRange = client.ZRevRange("zset", "-2", "-1") + Expect(zRevRange.Err()).NotTo(HaveOccurred()) + Expect(zRevRange.Val()).To(Equal([]string{"two", "one"})) + }) + + It("should ZRevRangeWithScoresMap", func() { + zAdd := client.ZAdd("zset", redis.Z{1, "one"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + zAdd = client.ZAdd("zset", redis.Z{2, "two"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + zAdd = client.ZAdd("zset", redis.Z{3, "three"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + + val, err := client.ZRevRangeWithScores("zset", "0", "-1").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]redis.Z{{3, "three"}, {2, "two"}, {1, "one"}})) + + val, err = client.ZRevRangeWithScores("zset", "2", "3").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]redis.Z{{1, "one"}})) + + val, err = client.ZRevRangeWithScores("zset", "-2", "-1").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]redis.Z{{2, "two"}, {1, "one"}})) + }) + + It("should ZRevRangeByScore", func() { + zadd := client.ZAdd("zset", redis.Z{1, "one"}) + Expect(zadd.Err()).NotTo(HaveOccurred()) + zadd = client.ZAdd("zset", redis.Z{2, "two"}) + Expect(zadd.Err()).NotTo(HaveOccurred()) + zadd = client.ZAdd("zset", redis.Z{3, "three"}) + Expect(zadd.Err()).NotTo(HaveOccurred()) + + vals, err := client.ZRevRangeByScore( + "zset", redis.ZRangeByScore{Max: "+inf", Min: "-inf"}).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]string{"three", "two", "one"})) + + vals, err = client.ZRevRangeByScore( + "zset", redis.ZRangeByScore{Max: "2", Min: "(1"}).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]string{"two"})) + + vals, err = client.ZRevRangeByScore( + "zset", redis.ZRangeByScore{Max: "(2", Min: "(1"}).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]string{})) + }) + + It("should ZRevRangeByScoreWithScores", func() { + zadd := client.ZAdd("zset", redis.Z{1, "one"}) + Expect(zadd.Err()).NotTo(HaveOccurred()) + zadd = client.ZAdd("zset", redis.Z{2, "two"}) + Expect(zadd.Err()).NotTo(HaveOccurred()) + zadd = client.ZAdd("zset", redis.Z{3, "three"}) + Expect(zadd.Err()).NotTo(HaveOccurred()) + + vals, err := client.ZRevRangeByScoreWithScores( + "zset", redis.ZRangeByScore{Max: "+inf", Min: "-inf"}).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{3, "three"}, {2, "two"}, {1, "one"}})) + }) + + It("should ZRevRangeByScoreWithScoresMap", func() { + zAdd := client.ZAdd("zset", redis.Z{1, "one"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + zAdd = client.ZAdd("zset", redis.Z{2, "two"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + zAdd = client.ZAdd("zset", redis.Z{3, "three"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + + val, err := client.ZRevRangeByScoreWithScores( + "zset", redis.ZRangeByScore{Max: "+inf", Min: "-inf"}).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]redis.Z{{3, "three"}, {2, "two"}, {1, "one"}})) + + val, err = client.ZRevRangeByScoreWithScores( + "zset", redis.ZRangeByScore{Max: "2", Min: "(1"}).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]redis.Z{{2, "two"}})) + + val, err = client.ZRevRangeByScoreWithScores( + "zset", redis.ZRangeByScore{Max: "(2", Min: "(1"}).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]redis.Z{})) + }) + + It("should ZRevRank", func() { + zAdd := client.ZAdd("zset", redis.Z{1, "one"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + zAdd = client.ZAdd("zset", redis.Z{2, "two"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + zAdd = client.ZAdd("zset", redis.Z{3, "three"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + + zRevRank := client.ZRevRank("zset", "one") + Expect(zRevRank.Err()).NotTo(HaveOccurred()) + Expect(zRevRank.Val()).To(Equal(int64(2))) + + zRevRank = client.ZRevRank("zset", "four") + Expect(zRevRank.Err()).To(Equal(redis.Nil)) + Expect(zRevRank.Val()).To(Equal(int64(0))) + }) + + It("should ZScore", func() { + zAdd := client.ZAdd("zset", redis.Z{1.001, "one"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + + zScore := client.ZScore("zset", "one") + Expect(zScore.Err()).NotTo(HaveOccurred()) + Expect(zScore.Val()).To(Equal(float64(1.001))) + }) + + It("should ZUnionStore", func() { + zAdd := client.ZAdd("zset1", redis.Z{1, "one"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + zAdd = client.ZAdd("zset1", redis.Z{2, "two"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + + zAdd = client.ZAdd("zset2", redis.Z{1, "one"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + zAdd = client.ZAdd("zset2", redis.Z{2, "two"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + zAdd = client.ZAdd("zset2", redis.Z{3, "three"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + + zUnionStore := client.ZUnionStore( + "out", redis.ZStore{Weights: []int64{2, 3}}, "zset1", "zset2") + Expect(zUnionStore.Err()).NotTo(HaveOccurred()) + Expect(zUnionStore.Val()).To(Equal(int64(3))) + + val, err := client.ZRangeWithScores("out", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]redis.Z{{5, "one"}, {9, "three"}, {10, "two"}})) + }) + + }) + + //------------------------------------------------------------------------------ + + Describe("watch/unwatch", func() { + + var safeIncr = func() ([]redis.Cmder, error) { + multi := client.Multi() + defer multi.Close() + + watch := multi.Watch("key") + Expect(watch.Err()).NotTo(HaveOccurred()) + Expect(watch.Val()).To(Equal("OK")) + + get := multi.Get("key") + Expect(get.Err()).NotTo(HaveOccurred()) + Expect(get.Val()).NotTo(Equal(redis.Nil)) + + v, err := strconv.ParseInt(get.Val(), 10, 64) + Expect(err).NotTo(HaveOccurred()) + + return multi.Exec(func() error { + multi.Set("key", strconv.FormatInt(v+1, 10)) + return nil + }) + } + + It("should WatchUnwatch", func() { + var n = 10000 + if testing.Short() { + n = 1000 + } + + err := client.Set("key", "0").Err() + Expect(err).NotTo(HaveOccurred()) + + wg := &sync.WaitGroup{} + for i := 0; i < n; i++ { + wg.Add(1) + + go func() { + defer wg.Done() + for { + cmds, err := safeIncr() + if err == redis.TxFailedErr { + continue + } + Expect(err).NotTo(HaveOccurred()) + Expect(cmds).To(HaveLen(1)) + Expect(cmds[0].Err()).NotTo(HaveOccurred()) + break + } + }() + } + wg.Wait() + + val, err := client.Get("key").Int64() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal(int64(n))) + }) + + }) + +}) diff --git a/example_test.go b/example_test.go index dbc95131..8e9e5122 100644 --- a/example_test.go +++ b/example_test.go @@ -30,7 +30,7 @@ func ExampleNewTCPClient() { func ExampleNewFailoverClient() { client := redis.NewFailoverClient(&redis.FailoverOptions{ - MasterName: "master", + MasterName: "mymaster", SentinelAddrs: []string{":26379"}, }) diff --git a/multi_test.go b/multi_test.go new file mode 100644 index 00000000..801bb19a --- /dev/null +++ b/multi_test.go @@ -0,0 +1,122 @@ +package redis_test + +import ( + "gopkg.in/redis.v2" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("Multi", func() { + var client *redis.Client + + BeforeEach(func() { + client = redis.NewTCPClient(&redis.Options{ + Addr: redisAddr, + }) + }) + + AfterEach(func() { + Expect(client.FlushDb().Err()).NotTo(HaveOccurred()) + Expect(client.Close()).NotTo(HaveOccurred()) + }) + + It("should exec", func() { + multi := client.Multi() + defer func() { + Expect(multi.Close()).NotTo(HaveOccurred()) + }() + + var ( + set *redis.StatusCmd + get *redis.StringCmd + ) + cmds, err := multi.Exec(func() error { + set = multi.Set("key", "hello") + get = multi.Get("key") + return nil + }) + Expect(err).NotTo(HaveOccurred()) + Expect(cmds).To(HaveLen(2)) + + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + Expect(get.Err()).NotTo(HaveOccurred()) + Expect(get.Val()).To(Equal("hello")) + }) + + It("should discard", func() { + multi := client.Multi() + defer func() { + Expect(multi.Close()).NotTo(HaveOccurred()) + }() + + cmds, err := multi.Exec(func() error { + multi.Set("key1", "hello1") + multi.Discard() + multi.Set("key2", "hello2") + return nil + }) + Expect(err).NotTo(HaveOccurred()) + Expect(cmds).To(HaveLen(1)) + + get := client.Get("key1") + Expect(get.Err()).To(Equal(redis.Nil)) + Expect(get.Val()).To(Equal("")) + + get = client.Get("key2") + Expect(get.Err()).NotTo(HaveOccurred()) + Expect(get.Val()).To(Equal("hello2")) + }) + + It("should exec empty", func() { + multi := client.Multi() + defer func() { + Expect(multi.Close()).NotTo(HaveOccurred()) + }() + + cmds, err := multi.Exec(func() error { return nil }) + Expect(err).NotTo(HaveOccurred()) + Expect(cmds).To(HaveLen(0)) + + ping := multi.Ping() + Expect(ping.Err()).NotTo(HaveOccurred()) + Expect(ping.Val()).To(Equal("PONG")) + }) + + It("should exec empty queue", func() { + multi := client.Multi() + defer func() { + Expect(multi.Close()).NotTo(HaveOccurred()) + }() + + cmds, err := multi.Exec(func() error { return nil }) + Expect(err).NotTo(HaveOccurred()) + Expect(cmds).To(HaveLen(0)) + }) + + It("should exec bulks", func() { + multi := client.Multi() + defer func() { + Expect(multi.Close()).NotTo(HaveOccurred()) + }() + + cmds, err := multi.Exec(func() error { + for i := int64(0); i < 20000; i++ { + multi.Incr("key") + } + return nil + }) + Expect(err).NotTo(HaveOccurred()) + Expect(len(cmds)).To(Equal(20000)) + for _, cmd := range cmds { + Expect(cmd.Err()).NotTo(HaveOccurred()) + } + + get := client.Get("key") + Expect(get.Err()).NotTo(HaveOccurred()) + Expect(get.Val()).To(Equal("20000")) + }) + +}) diff --git a/pipeline_test.go b/pipeline_test.go new file mode 100644 index 00000000..c55f99dc --- /dev/null +++ b/pipeline_test.go @@ -0,0 +1,152 @@ +package redis_test + +import ( + "strconv" + "sync" + + "gopkg.in/redis.v2" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("Pipelining", func() { + var client *redis.Client + + BeforeEach(func() { + client = redis.NewTCPClient(&redis.Options{ + Addr: redisAddr, + }) + }) + + AfterEach(func() { + Expect(client.FlushDb().Err()).NotTo(HaveOccurred()) + Expect(client.Close()).NotTo(HaveOccurred()) + }) + + It("should pipeline", func() { + set := client.Set("key2", "hello2") + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + pipeline := client.Pipeline() + set = pipeline.Set("key1", "hello1") + get := pipeline.Get("key2") + incr := pipeline.Incr("key3") + getNil := pipeline.Get("key4") + + cmds, err := pipeline.Exec() + Expect(err).To(Equal(redis.Nil)) + Expect(cmds).To(HaveLen(4)) + Expect(pipeline.Close()).NotTo(HaveOccurred()) + + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + Expect(get.Err()).NotTo(HaveOccurred()) + Expect(get.Val()).To(Equal("hello2")) + + Expect(incr.Err()).NotTo(HaveOccurred()) + Expect(incr.Val()).To(Equal(int64(1))) + + Expect(getNil.Err()).To(Equal(redis.Nil)) + Expect(getNil.Val()).To(Equal("")) + }) + + It("should discard", func() { + pipeline := client.Pipeline() + + pipeline.Get("key") + pipeline.Discard() + cmds, err := pipeline.Exec() + Expect(err).NotTo(HaveOccurred()) + Expect(cmds).To(HaveLen(0)) + Expect(pipeline.Close()).NotTo(HaveOccurred()) + }) + + It("should support block style", func() { + var get *redis.StringCmd + cmds, err := client.Pipelined(func(pipe *redis.Pipeline) error { + get = pipe.Get("foo") + return nil + }) + Expect(err).To(Equal(redis.Nil)) + Expect(cmds).To(HaveLen(1)) + Expect(cmds[0]).To(Equal(get)) + Expect(get.Err()).To(Equal(redis.Nil)) + Expect(get.Val()).To(Equal("")) + }) + + It("should handle vals/err", func() { + pipeline := client.Pipeline() + + get := pipeline.Get("key") + Expect(get.Err()).NotTo(HaveOccurred()) + Expect(get.Val()).To(Equal("")) + Expect(pipeline.Close()).NotTo(HaveOccurred()) + }) + + It("should pipeline with empty queue", func() { + pipeline := client.Pipeline() + cmds, err := pipeline.Exec() + Expect(err).NotTo(HaveOccurred()) + Expect(cmds).To(HaveLen(0)) + Expect(pipeline.Close()).NotTo(HaveOccurred()) + }) + + It("should increment correctly", func() { + const N = 20000 + key := "TestPipelineIncr" + pipeline := client.Pipeline() + for i := 0; i < N; i++ { + pipeline.Incr(key) + } + + cmds, err := pipeline.Exec() + Expect(err).NotTo(HaveOccurred()) + Expect(pipeline.Close()).NotTo(HaveOccurred()) + + Expect(len(cmds)).To(Equal(20000)) + for _, cmd := range cmds { + Expect(cmd.Err()).NotTo(HaveOccurred()) + } + + get := client.Get(key) + Expect(get.Err()).NotTo(HaveOccurred()) + Expect(get.Val()).To(Equal(strconv.Itoa(N))) + }) + + It("should PipelineEcho", func() { + const N = 1000 + + wg := &sync.WaitGroup{} + wg.Add(N) + for i := 0; i < N; i++ { + go func(i int) { + pipeline := client.Pipeline() + + msg1 := "echo" + strconv.Itoa(i) + msg2 := "echo" + strconv.Itoa(i+1) + + echo1 := pipeline.Echo(msg1) + echo2 := pipeline.Echo(msg2) + + cmds, err := pipeline.Exec() + Expect(err).NotTo(HaveOccurred()) + Expect(cmds).To(HaveLen(2)) + + Expect(echo1.Err()).NotTo(HaveOccurred()) + Expect(echo1.Val()).To(Equal(msg1)) + + Expect(echo2.Err()).NotTo(HaveOccurred()) + Expect(echo2.Val()).To(Equal(msg2)) + + Expect(pipeline.Close()).NotTo(HaveOccurred()) + + wg.Done() + }(i) + } + wg.Wait() + }) + +}) diff --git a/pool_test.go b/pool_test.go new file mode 100644 index 00000000..d2569f15 --- /dev/null +++ b/pool_test.go @@ -0,0 +1,122 @@ +package redis_test + +import ( + "sync" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "gopkg.in/redis.v2" +) + +var _ = Describe("Pool", func() { + var client *redis.Client + var perform = func(n int, cb func()) { + wg := &sync.WaitGroup{} + for i := 0; i < n; i++ { + wg.Add(1) + go func() { + defer wg.Done() + cb() + }() + } + wg.Wait() + } + + BeforeEach(func() { + client = redis.NewTCPClient(&redis.Options{ + Addr: redisAddr, + }) + }) + + AfterEach(func() { + client.FlushDb() + Expect(client.Close()).NotTo(HaveOccurred()) + }) + + It("should respect max size", func() { + perform(1000, func() { + val, err := client.Ping().Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal("PONG")) + }) + Expect(client.Pool().Size()).To(Equal(10)) + Expect(client.Pool().Len()).To(Equal(10)) + }) + + It("should respect max on multi", func() { + perform(1000, func() { + var ping *redis.StatusCmd + + multi := client.Multi() + cmds, err := multi.Exec(func() error { + ping = multi.Ping() + return nil + }) + Expect(err).NotTo(HaveOccurred()) + Expect(cmds).To(HaveLen(1)) + Expect(ping.Err()).NotTo(HaveOccurred()) + Expect(ping.Val()).To(Equal("PONG")) + Expect(multi.Close()).NotTo(HaveOccurred()) + }) + + Expect(client.Pool().Size()).To(Equal(10)) + Expect(client.Pool().Len()).To(Equal(10)) + }) + + It("should respect max on pipelines", func() { + perform(1000, func() { + pipe := client.Pipeline() + ping := pipe.Ping() + cmds, err := pipe.Exec() + Expect(err).NotTo(HaveOccurred()) + Expect(cmds).To(HaveLen(1)) + Expect(ping.Err()).NotTo(HaveOccurred()) + Expect(ping.Val()).To(Equal("PONG")) + Expect(pipe.Close()).NotTo(HaveOccurred()) + }) + + Expect(client.Pool().Size()).To(Equal(10)) + Expect(client.Pool().Len()).To(Equal(10)) + }) + + It("should respect max on pubsub", func() { + perform(10, func() { + pubsub := client.PubSub() + Expect(pubsub.Subscribe()).NotTo(HaveOccurred()) + Expect(pubsub.Close()).NotTo(HaveOccurred()) + }) + + Expect(client.Pool().Size()).To(Equal(0)) + Expect(client.Pool().Len()).To(Equal(0)) + }) + + It("should remove broken connections", func() { + cn, _, err := client.Pool().Get() + Expect(err).NotTo(HaveOccurred()) + Expect(cn.Close()).NotTo(HaveOccurred()) + Expect(client.Pool().Put(cn)).NotTo(HaveOccurred()) + + err = client.Ping().Err() + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(Equal("use of closed network connection")) + + val, err := client.Ping().Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal("PONG")) + + Expect(client.Pool().Size()).To(Equal(1)) + Expect(client.Pool().Len()).To(Equal(1)) + }) + + It("should reuse connections", func() { + for i := 0; i < 100; i++ { + val, err := client.Ping().Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal("PONG")) + } + + Expect(client.Pool().Size()).To(Equal(1)) + Expect(client.Pool().Len()).To(Equal(1)) + }) + +}) diff --git a/pubsub_test.go b/pubsub_test.go new file mode 100644 index 00000000..76e3fa97 --- /dev/null +++ b/pubsub_test.go @@ -0,0 +1,202 @@ +package redis_test + +import ( + "net" + "time" + + "gopkg.in/redis.v2" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("PubSub", func() { + var client *redis.Client + + BeforeEach(func() { + client = redis.NewTCPClient(&redis.Options{ + Addr: redisAddr, + }) + }) + + AfterEach(func() { + Expect(client.FlushDb().Err()).NotTo(HaveOccurred()) + Expect(client.Close()).NotTo(HaveOccurred()) + }) + + It("should support pattern matching", func() { + pubsub := client.PubSub() + defer func() { + Expect(pubsub.Close()).NotTo(HaveOccurred()) + }() + + Expect(pubsub.PSubscribe("mychannel*")).NotTo(HaveOccurred()) + + pub := client.Publish("mychannel1", "hello") + Expect(pub.Err()).NotTo(HaveOccurred()) + Expect(pub.Val()).To(Equal(int64(1))) + + Expect(pubsub.PUnsubscribe("mychannel*")).NotTo(HaveOccurred()) + + { + msgi, err := pubsub.ReceiveTimeout(time.Second) + Expect(err).NotTo(HaveOccurred()) + subscr := msgi.(*redis.Subscription) + Expect(subscr.Kind).To(Equal("psubscribe")) + Expect(subscr.Channel).To(Equal("mychannel*")) + Expect(subscr.Count).To(Equal(1)) + } + + { + msgi, err := pubsub.ReceiveTimeout(time.Second) + Expect(err).NotTo(HaveOccurred()) + subscr := msgi.(*redis.PMessage) + Expect(subscr.Channel).To(Equal("mychannel1")) + Expect(subscr.Pattern).To(Equal("mychannel*")) + Expect(subscr.Payload).To(Equal("hello")) + } + + { + msgi, err := pubsub.ReceiveTimeout(time.Second) + Expect(err).NotTo(HaveOccurred()) + subscr := msgi.(*redis.Subscription) + Expect(subscr.Kind).To(Equal("punsubscribe")) + Expect(subscr.Channel).To(Equal("mychannel*")) + Expect(subscr.Count).To(Equal(0)) + } + + { + msgi, err := pubsub.ReceiveTimeout(time.Second) + Expect(err.(net.Error).Timeout()).To(Equal(true)) + Expect(msgi).NotTo(HaveOccurred()) + } + }) + + It("should pub/sub channels", func() { + channels, err := client.PubSubChannels("mychannel*").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(channels).To(BeEmpty()) + + pubsub := client.PubSub() + defer pubsub.Close() + Expect(pubsub.Subscribe("mychannel", "mychannel2")).NotTo(HaveOccurred()) + + channels, err = client.PubSubChannels("mychannel*").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(channels).To(ConsistOf([]string{"mychannel", "mychannel2"})) + + channels, err = client.PubSubChannels("").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(channels).To(BeEmpty()) + + channels, err = client.PubSubChannels("*").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(len(channels)).To(BeNumerically(">=", 2)) + }) + + It("should return the numbers of subscribers", func() { + pubsub := client.PubSub() + defer pubsub.Close() + Expect(pubsub.Subscribe("mychannel", "mychannel2")).NotTo(HaveOccurred()) + + channels, err := client.PubSubNumSub("mychannel", "mychannel2", "mychannel3").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(channels).To(Equal([]interface{}{ + "mychannel", int64(1), + "mychannel2", int64(1), + "mychannel3", int64(0), + })) + }) + + It("should return the numbers of subscribers by pattern", func() { + num, err := client.PubSubNumPat().Result() + Expect(err).NotTo(HaveOccurred()) + Expect(num).To(Equal(int64(0))) + + pubsub := client.PubSub() + defer pubsub.Close() + Expect(pubsub.PSubscribe("*")).NotTo(HaveOccurred()) + + num, err = client.PubSubNumPat().Result() + Expect(err).NotTo(HaveOccurred()) + Expect(num).To(Equal(int64(1))) + }) + + It("should pub/sub", func() { + pubsub := client.PubSub() + defer func() { + Expect(pubsub.Close()).NotTo(HaveOccurred()) + }() + + Expect(pubsub.Subscribe("mychannel", "mychannel2")).NotTo(HaveOccurred()) + + pub := client.Publish("mychannel", "hello") + Expect(pub.Err()).NotTo(HaveOccurred()) + Expect(pub.Val()).To(Equal(int64(1))) + + pub = client.Publish("mychannel2", "hello2") + Expect(pub.Err()).NotTo(HaveOccurred()) + Expect(pub.Val()).To(Equal(int64(1))) + + Expect(pubsub.Unsubscribe("mychannel", "mychannel2")).NotTo(HaveOccurred()) + + { + msgi, err := pubsub.ReceiveTimeout(time.Second) + Expect(err).NotTo(HaveOccurred()) + subscr := msgi.(*redis.Subscription) + Expect(subscr.Kind).To(Equal("subscribe")) + Expect(subscr.Channel).To(Equal("mychannel")) + Expect(subscr.Count).To(Equal(1)) + } + + { + msgi, err := pubsub.ReceiveTimeout(time.Second) + Expect(err).NotTo(HaveOccurred()) + subscr := msgi.(*redis.Subscription) + Expect(subscr.Kind).To(Equal("subscribe")) + Expect(subscr.Channel).To(Equal("mychannel2")) + Expect(subscr.Count).To(Equal(2)) + } + + { + msgi, err := pubsub.ReceiveTimeout(time.Second) + Expect(err).NotTo(HaveOccurred()) + subscr := msgi.(*redis.Message) + Expect(subscr.Channel).To(Equal("mychannel")) + Expect(subscr.Payload).To(Equal("hello")) + } + + { + msgi, err := pubsub.ReceiveTimeout(time.Second) + Expect(err).NotTo(HaveOccurred()) + msg := msgi.(*redis.Message) + Expect(msg.Channel).To(Equal("mychannel2")) + Expect(msg.Payload).To(Equal("hello2")) + } + + { + msgi, err := pubsub.ReceiveTimeout(time.Second) + Expect(err).NotTo(HaveOccurred()) + subscr := msgi.(*redis.Subscription) + Expect(subscr.Kind).To(Equal("unsubscribe")) + Expect(subscr.Channel).To(Equal("mychannel")) + Expect(subscr.Count).To(Equal(1)) + } + + { + msgi, err := pubsub.ReceiveTimeout(time.Second) + Expect(err).NotTo(HaveOccurred()) + subscr := msgi.(*redis.Subscription) + Expect(subscr.Kind).To(Equal("unsubscribe")) + Expect(subscr.Channel).To(Equal("mychannel2")) + Expect(subscr.Count).To(Equal(0)) + } + + { + msgi, err := pubsub.ReceiveTimeout(time.Second) + Expect(err.(net.Error).Timeout()).To(Equal(true)) + Expect(msgi).NotTo(HaveOccurred()) + } + }) + +}) diff --git a/redis_test.go b/redis_test.go index 49f84d0e..8649241b 100644 --- a/redis_test.go +++ b/redis_test.go @@ -1,25 +1,128 @@ package redis_test import ( - "bytes" - "fmt" - "io" "net" "sort" - "strconv" - "sync" "testing" "time" "gopkg.in/redis.v2" - . "gopkg.in/check.v1" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" ) const redisAddr = ":6379" +var _ = Describe("Client", func() { + var client *redis.Client + + BeforeEach(func() { + client = redis.NewTCPClient(&redis.Options{ + Addr: redisAddr, + }) + }) + + AfterEach(func() { + Expect(client.Close()).NotTo(HaveOccurred()) + }) + + It("should ping", func() { + val, err := client.Ping().Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal("PONG")) + }) + + It("should support custom dialers", func() { + custom := redis.NewClient(&redis.Options{ + Dialer: func() (net.Conn, error) { + return net.Dial("tcp", redisAddr) + }, + }) + + val, err := custom.Ping().Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal("PONG")) + Expect(custom.Close()).NotTo(HaveOccurred()) + }) + + It("should close", func() { + Expect(client.Close()).NotTo(HaveOccurred()) + err := client.Ping().Err() + Expect(err).To(HaveOccurred()) + Expect(err).To(MatchError("redis: client is closed")) + }) + + It("should close pubsub without closing the connection", func() { + pubsub := client.PubSub() + Expect(pubsub.Close()).NotTo(HaveOccurred()) + + _, err := pubsub.Receive() + Expect(err).To(HaveOccurred()) + Expect(err).To(MatchError("redis: client is closed")) + Expect(client.Ping().Err()).NotTo(HaveOccurred()) + }) + + It("should close multi without closing the connection", func() { + multi := client.Multi() + Expect(multi.Close()).NotTo(HaveOccurred()) + + _, err := multi.Exec(func() error { + multi.Ping() + return nil + }) + Expect(err).To(HaveOccurred()) + Expect(err).To(MatchError("redis: client is closed")) + Expect(client.Ping().Err()).NotTo(HaveOccurred()) + }) + + It("should close pipeline without closing the connection", func() { + pipeline := client.Pipeline() + Expect(pipeline.Close()).NotTo(HaveOccurred()) + + pipeline.Ping() + _, err := pipeline.Exec() + Expect(err).To(HaveOccurred()) + Expect(err).To(MatchError("redis: client is closed")) + Expect(client.Ping().Err()).NotTo(HaveOccurred()) + }) + + It("should support idle-timeouts", func() { + idle := redis.NewTCPClient(&redis.Options{ + Addr: redisAddr, + IdleTimeout: time.Nanosecond, + }) + defer idle.Close() + + Expect(idle.Ping().Err()).NotTo(HaveOccurred()) + time.Sleep(time.Millisecond) + Expect(idle.Ping().Err()).NotTo(HaveOccurred()) + }) + + It("should support DB selection", func() { + db1 := redis.NewTCPClient(&redis.Options{ + Addr: redisAddr, + DB: 1, + }) + defer db1.Close() + + Expect(db1.Get("key").Err()).To(Equal(redis.Nil)) + Expect(db1.Set("key", "value").Err()).NotTo(HaveOccurred()) + + Expect(client.Get("key").Err()).To(Equal(redis.Nil)) + Expect(db1.Get("key").Val()).To(Equal("value")) + Expect(db1.FlushDb().Err()).NotTo(HaveOccurred()) + }) + +}) + //------------------------------------------------------------------------------ +func TestGinkgoSuite(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "gopkg.in/redis.v2") +} + func sortStrings(slice []string) []string { sort.Strings(slice) return slice @@ -27,3196 +130,6 @@ func sortStrings(slice []string) []string { //------------------------------------------------------------------------------ -type RedisConnectorTest struct{} - -var _ = Suite(&RedisConnectorTest{}) - -func (t *RedisConnectorTest) TestShutdown(c *C) { - c.Skip("shutdowns server") - - client := redis.NewTCPClient(&redis.Options{ - Addr: redisAddr, - }) - - shutdown := client.Shutdown() - c.Check(shutdown.Err(), Equals, io.EOF) - c.Check(shutdown.Val(), Equals, "") - - ping := client.Ping() - c.Check(ping.Err(), ErrorMatches, "dial tcp :[0-9]+: connection refused") - c.Check(ping.Val(), Equals, "") -} - -func (t *RedisConnectorTest) TestNewTCPClient(c *C) { - client := redis.NewTCPClient(&redis.Options{ - Addr: redisAddr, - }) - ping := client.Ping() - c.Check(ping.Err(), IsNil) - c.Check(ping.Val(), Equals, "PONG") - c.Assert(client.Close(), IsNil) -} - -func (t *RedisConnectorTest) TestNewUnixClient(c *C) { - c.Skip("not available on Travis CI") - - client := redis.NewUnixClient(&redis.Options{ - Addr: "/tmp/redis.sock", - }) - ping := client.Ping() - c.Check(ping.Err(), IsNil) - c.Check(ping.Val(), Equals, "PONG") - c.Assert(client.Close(), IsNil) -} - -func (t *RedisConnectorTest) TestDialer(c *C) { - client := redis.NewClient(&redis.Options{ - Dialer: func() (net.Conn, error) { - return net.Dial("tcp", redisAddr) - }, - }) - ping := client.Ping() - c.Check(ping.Err(), IsNil) - c.Check(ping.Val(), Equals, "PONG") - c.Assert(client.Close(), IsNil) -} - -func (t *RedisConnectorTest) TestClose(c *C) { - client := redis.NewTCPClient(&redis.Options{ - Addr: redisAddr, - }) - c.Assert(client.Close(), IsNil) - - ping := client.Ping() - c.Assert(ping.Err(), Not(IsNil)) - c.Assert(ping.Err().Error(), Equals, "redis: client is closed") - - c.Assert(client.Close(), IsNil) -} - -func (t *RedisConnectorTest) TestPubSubClose(c *C) { - client := redis.NewTCPClient(&redis.Options{ - Addr: redisAddr, - }) - - pubsub := client.PubSub() - c.Assert(pubsub.Close(), IsNil) - - _, err := pubsub.Receive() - c.Assert(err, Not(IsNil)) - c.Assert(err.Error(), Equals, "redis: client is closed") - - ping := client.Ping() - c.Assert(ping.Err(), IsNil) - - c.Assert(client.Close(), IsNil) -} - -func (t *RedisConnectorTest) TestMultiClose(c *C) { - client := redis.NewTCPClient(&redis.Options{ - Addr: redisAddr, - }) - - multi := client.Multi() - c.Assert(multi.Close(), IsNil) - - _, err := multi.Exec(func() error { - multi.Ping() - return nil - }) - c.Assert(err, Not(IsNil)) - c.Assert(err.Error(), Equals, "redis: client is closed") - - ping := client.Ping() - c.Assert(ping.Err(), IsNil) - - c.Assert(client.Close(), IsNil) -} - -func (t *RedisConnectorTest) TestPipelineClose(c *C) { - client := redis.NewTCPClient(&redis.Options{ - Addr: redisAddr, - }) - - _, err := client.Pipelined(func(pipeline *redis.Pipeline) error { - c.Assert(pipeline.Close(), IsNil) - pipeline.Ping() - return nil - }) - c.Assert(err, Not(IsNil)) - c.Assert(err.Error(), Equals, "redis: client is closed") - - ping := client.Ping() - c.Assert(ping.Err(), IsNil) - - c.Assert(client.Close(), IsNil) -} - -func (t *RedisConnectorTest) TestIdleTimeout(c *C) { - client := redis.NewTCPClient(&redis.Options{ - Addr: redisAddr, - IdleTimeout: time.Nanosecond, - }) - for i := 0; i < 10; i++ { - c.Assert(client.Ping().Err(), IsNil) - } -} - -func (t *RedisConnectorTest) TestSelectDb(c *C) { - client1 := redis.NewTCPClient(&redis.Options{ - Addr: redisAddr, - DB: 1, - }) - c.Assert(client1.Set("key", "db1").Err(), IsNil) - - client2 := redis.NewTCPClient(&redis.Options{ - Addr: redisAddr, - DB: 2, - }) - c.Assert(client2.Get("key").Err(), Equals, redis.Nil) -} - -//------------------------------------------------------------------------------ - -type RedisConnPoolTest struct { - client *redis.Client -} - -var _ = Suite(&RedisConnPoolTest{}) - -func (t *RedisConnPoolTest) SetUpTest(c *C) { - t.client = redis.NewTCPClient(&redis.Options{ - Addr: redisAddr, - }) -} - -func (t *RedisConnPoolTest) TearDownTest(c *C) { - c.Assert(t.client.FlushDb().Err(), IsNil) - c.Assert(t.client.Close(), IsNil) -} - -func (t *RedisConnPoolTest) TestConnPoolMaxSize(c *C) { - wg := &sync.WaitGroup{} - for i := 0; i < 1000; i++ { - wg.Add(1) - go func() { - ping := t.client.Ping() - c.Assert(ping.Err(), IsNil) - c.Assert(ping.Val(), Equals, "PONG") - wg.Done() - }() - } - wg.Wait() - - c.Assert(t.client.Pool().Size(), Equals, 10) - c.Assert(t.client.Pool().Len(), Equals, 10) -} - -func (t *RedisConnPoolTest) TestConnPoolMaxSizeOnPipelineClient(c *C) { - const N = 1000 - - wg := &sync.WaitGroup{} - wg.Add(N) - for i := 0; i < N; i++ { - go func() { - pipeline := t.client.Pipeline() - ping := pipeline.Ping() - cmds, err := pipeline.Exec() - c.Assert(err, IsNil) - c.Assert(cmds, HasLen, 1) - c.Assert(ping.Err(), IsNil) - c.Assert(ping.Val(), Equals, "PONG") - - c.Assert(pipeline.Close(), IsNil) - - wg.Done() - }() - } - wg.Wait() - - c.Assert(t.client.Pool().Size(), Equals, 10) - c.Assert(t.client.Pool().Len(), Equals, 10) -} - -func (t *RedisConnPoolTest) TestConnPoolMaxSizeOnMultiClient(c *C) { - const N = 1000 - - wg := &sync.WaitGroup{} - wg.Add(N) - for i := 0; i < N; i++ { - go func() { - multi := t.client.Multi() - var ping *redis.StatusCmd - cmds, err := multi.Exec(func() error { - ping = multi.Ping() - return nil - }) - c.Assert(err, IsNil) - c.Assert(cmds, HasLen, 1) - c.Assert(ping.Err(), IsNil) - c.Assert(ping.Val(), Equals, "PONG") - - c.Assert(multi.Close(), IsNil) - - wg.Done() - }() - } - wg.Wait() - - c.Assert(t.client.Pool().Size(), Equals, 10) - c.Assert(t.client.Pool().Len(), Equals, 10) -} - -func (t *RedisConnPoolTest) TestConnPoolMaxSizeOnPubSub(c *C) { - const N = 10 - - wg := &sync.WaitGroup{} - wg.Add(N) - for i := 0; i < N; i++ { - go func() { - defer wg.Done() - pubsub := t.client.PubSub() - c.Assert(pubsub.Subscribe(), IsNil) - c.Assert(pubsub.Close(), IsNil) - }() - } - wg.Wait() - - c.Assert(t.client.Pool().Size(), Equals, 0) - c.Assert(t.client.Pool().Len(), Equals, 0) -} - -func (t *RedisConnPoolTest) TestConnPoolRemovesBrokenConn(c *C) { - cn, _, err := t.client.Pool().Get() - c.Assert(err, IsNil) - c.Assert(cn.Close(), IsNil) - c.Assert(t.client.Pool().Put(cn), IsNil) - - ping := t.client.Ping() - c.Assert(ping.Err().Error(), Equals, "use of closed network connection") - c.Assert(ping.Val(), Equals, "") - - ping = t.client.Ping() - c.Assert(ping.Err(), IsNil) - c.Assert(ping.Val(), Equals, "PONG") - - c.Assert(t.client.Pool().Size(), Equals, 1) - c.Assert(t.client.Pool().Len(), Equals, 1) -} - -func (t *RedisConnPoolTest) TestConnPoolReusesConn(c *C) { - for i := 0; i < 1000; i++ { - ping := t.client.Ping() - c.Assert(ping.Err(), IsNil) - c.Assert(ping.Val(), Equals, "PONG") - } - - c.Assert(t.client.Pool().Size(), Equals, 1) - c.Assert(t.client.Pool().Len(), Equals, 1) -} - -//------------------------------------------------------------------------------ - -type RedisTest struct { - client *redis.Client -} - -var _ = Suite(&RedisTest{}) - -func Test(t *testing.T) { TestingT(t) } - -func (t *RedisTest) SetUpTest(c *C) { - t.client = redis.NewTCPClient(&redis.Options{ - Addr: ":6379", - }) - - // This is much faster than Flushall. - c.Assert(t.client.Select(1).Err(), IsNil) - c.Assert(t.client.FlushDb().Err(), IsNil) - c.Assert(t.client.Select(0).Err(), IsNil) - c.Assert(t.client.FlushDb().Err(), IsNil) -} - -func (t *RedisTest) TearDownTest(c *C) { - c.Assert(t.client.Close(), IsNil) -} - -//------------------------------------------------------------------------------ - -func (t *RedisTest) TestCmdStringMethod(c *C) { - set := t.client.Set("foo", "bar") - c.Assert(set.String(), Equals, "SET foo bar: OK") - - get := t.client.Get("foo") - c.Assert(get.String(), Equals, "GET foo: bar") -} - -func (t *RedisTest) TestCmdStringMethodError(c *C) { - get2 := t.client.Get("key_does_not_exists") - c.Assert(get2.String(), Equals, "GET key_does_not_exists: redis: nil") -} - -func (t *RedisTest) TestRunWithouthCheckingErrVal(c *C) { - set := t.client.Set("key", "hello") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - get := t.client.Get("key") - c.Assert(get.Err(), IsNil) - c.Assert(get.Val(), Equals, "hello") - - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") -} - -func (t *RedisTest) TestGetSpecChars(c *C) { - set := t.client.Set("key", "hello1\r\nhello2\r\n") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - get := t.client.Get("key") - c.Assert(get.Err(), IsNil) - c.Assert(get.Val(), Equals, "hello1\r\nhello2\r\n") -} - -func (t *RedisTest) TestGetBigVal(c *C) { - val := string(bytes.Repeat([]byte{'*'}, 1<<16)) - - set := t.client.Set("key", val) - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - get := t.client.Get("key") - c.Assert(get.Err(), IsNil) - c.Assert(get.Val(), Equals, val) -} - -func (t *RedisTest) TestManyKeys(c *C) { - var n = 100000 - - for i := 0; i < n; i++ { - t.client.Set("keys.key"+strconv.Itoa(i), "hello"+strconv.Itoa(i)) - } - keys := t.client.Keys("keys.*") - c.Assert(keys.Err(), IsNil) - c.Assert(len(keys.Val()), Equals, n) -} - -func (t *RedisTest) TestManyKeys2(c *C) { - var n = 100000 - - keys := []string{"non-existent-key"} - for i := 0; i < n; i++ { - key := "keys.key" + strconv.Itoa(i) - t.client.Set(key, "hello"+strconv.Itoa(i)) - keys = append(keys, key) - } - keys = append(keys, "non-existent-key") - - mget := t.client.MGet(keys...) - c.Assert(mget.Err(), IsNil) - c.Assert(len(mget.Val()), Equals, n+2) - vals := mget.Val() - for i := 0; i < n; i++ { - c.Assert(vals[i+1], Equals, "hello"+strconv.Itoa(i)) - } - c.Assert(vals[0], Equals, nil) - c.Assert(vals[n+1], Equals, nil) -} - -func (t *RedisTest) TestStringCmdHelpers(c *C) { - set := t.client.Set("key", "10") - c.Assert(set.Err(), IsNil) - - n, err := t.client.Get("key").Int64() - c.Assert(err, IsNil) - c.Assert(n, Equals, int64(10)) - - un, err := t.client.Get("key").Uint64() - c.Assert(err, IsNil) - c.Assert(un, Equals, uint64(10)) - - f, err := t.client.Get("key").Float64() - c.Assert(err, IsNil) - c.Assert(f, Equals, float64(10)) -} - -//------------------------------------------------------------------------------ - -func (t *RedisTest) TestAuth(c *C) { - auth := t.client.Auth("password") - c.Assert(auth.Err(), ErrorMatches, "ERR Client sent AUTH, but no password is set") - c.Assert(auth.Val(), Equals, "") -} - -func (t *RedisTest) TestEcho(c *C) { - echo := t.client.Echo("hello") - c.Assert(echo.Err(), IsNil) - c.Assert(echo.Val(), Equals, "hello") -} - -func (t *RedisTest) TestPing(c *C) { - ping := t.client.Ping() - c.Assert(ping.Err(), IsNil) - c.Assert(ping.Val(), Equals, "PONG") -} - -func (t *RedisTest) TestSelect(c *C) { - sel := t.client.Select(1) - c.Assert(sel.Err(), IsNil) - c.Assert(sel.Val(), Equals, "OK") -} - -//------------------------------------------------------------------------------ - -func (t *RedisTest) TestCmdKeysDel(c *C) { - set := t.client.Set("key1", "Hello") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - set = t.client.Set("key2", "World") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - del := t.client.Del("key1", "key2", "key3") - c.Assert(del.Err(), IsNil) - c.Assert(del.Val(), Equals, int64(2)) -} - -func (t *RedisTest) TestCmdKeysDump(c *C) { - set := t.client.Set("key", "hello") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - dump := t.client.Dump("key") - c.Assert(dump.Err(), IsNil) - c.Assert(dump.Val(), Equals, "\x00\x05hello\x06\x00\xf5\x9f\xb7\xf6\x90a\x1c\x99") -} - -func (t *RedisTest) TestCmdKeysExists(c *C) { - set := t.client.Set("key1", "Hello") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - exists := t.client.Exists("key1") - c.Assert(exists.Err(), IsNil) - c.Assert(exists.Val(), Equals, true) - - exists = t.client.Exists("key2") - c.Assert(exists.Err(), IsNil) - c.Assert(exists.Val(), Equals, false) -} - -func (t *RedisTest) TestCmdKeysExpire(c *C) { - set := t.client.Set("key", "Hello") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - expire := t.client.Expire("key", 10*time.Second) - c.Assert(expire.Err(), IsNil) - c.Assert(expire.Val(), Equals, true) - - ttl := t.client.TTL("key") - c.Assert(ttl.Err(), IsNil) - c.Assert(ttl.Val(), Equals, 10*time.Second) - - set = t.client.Set("key", "Hello World") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - ttl = t.client.TTL("key") - c.Assert(ttl.Err(), IsNil) - c.Assert(ttl.Val() < 0, Equals, true) -} - -func (t *RedisTest) TestCmdKeysExpireAt(c *C) { - set := t.client.Set("key", "Hello") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - exists := t.client.Exists("key") - c.Assert(exists.Err(), IsNil) - c.Assert(exists.Val(), Equals, true) - - expireAt := t.client.ExpireAt("key", time.Now().Add(-time.Hour)) - c.Assert(expireAt.Err(), IsNil) - c.Assert(expireAt.Val(), Equals, true) - - exists = t.client.Exists("key") - c.Assert(exists.Err(), IsNil) - c.Assert(exists.Val(), Equals, false) -} - -func (t *RedisTest) TestCmdKeysKeys(c *C) { - mset := t.client.MSet("one", "1", "two", "2", "three", "3", "four", "4") - c.Assert(mset.Err(), IsNil) - c.Assert(mset.Val(), Equals, "OK") - - keys := t.client.Keys("*o*") - c.Assert(keys.Err(), IsNil) - c.Assert(sortStrings(keys.Val()), DeepEquals, []string{"four", "one", "two"}) - - keys = t.client.Keys("t??") - c.Assert(keys.Err(), IsNil) - c.Assert(keys.Val(), DeepEquals, []string{"two"}) - - keys = t.client.Keys("*") - c.Assert(keys.Err(), IsNil) - c.Assert( - sortStrings(keys.Val()), - DeepEquals, - []string{"four", "one", "three", "two"}, - ) -} - -func (t *RedisTest) TestCmdKeysMigrate(c *C) { - migrate := t.client.Migrate("localhost", "6380", "key", 0, 0) - c.Assert(migrate.Err(), IsNil) - c.Assert(migrate.Val(), Equals, "NOKEY") - - set := t.client.Set("key", "hello") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - migrate = t.client.Migrate("localhost", "6380", "key", 0, 0) - c.Assert(migrate.Err(), ErrorMatches, "IOERR error or timeout writing to target instance") - c.Assert(migrate.Val(), Equals, "") -} - -func (t *RedisTest) TestCmdKeysMove(c *C) { - move := t.client.Move("key", 1) - c.Assert(move.Err(), IsNil) - c.Assert(move.Val(), Equals, false) - - set := t.client.Set("key", "hello") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - move = t.client.Move("key", 1) - c.Assert(move.Err(), IsNil) - c.Assert(move.Val(), Equals, true) - - get := t.client.Get("key") - c.Assert(get.Err(), Equals, redis.Nil) - c.Assert(get.Val(), Equals, "") - - sel := t.client.Select(1) - c.Assert(sel.Err(), IsNil) - c.Assert(sel.Val(), Equals, "OK") - - get = t.client.Get("key") - c.Assert(get.Err(), IsNil) - c.Assert(get.Val(), Equals, "hello") -} - -func (t *RedisTest) TestCmdKeysObject(c *C) { - set := t.client.Set("key", "hello") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - refCount := t.client.ObjectRefCount("key") - c.Assert(refCount.Err(), IsNil) - c.Assert(refCount.Val(), Equals, int64(1)) - - enc := t.client.ObjectEncoding("key") - c.Assert(enc.Err(), IsNil) - c.Assert(enc.Val(), Equals, "raw") - - idleTime := t.client.ObjectIdleTime("key") - c.Assert(idleTime.Err(), IsNil) - c.Assert(idleTime.Val(), Equals, time.Duration(0)) -} - -func (t *RedisTest) TestCmdKeysPersist(c *C) { - set := t.client.Set("key", "Hello") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - expire := t.client.Expire("key", 10*time.Second) - c.Assert(expire.Err(), IsNil) - c.Assert(expire.Val(), Equals, true) - - ttl := t.client.TTL("key") - c.Assert(ttl.Err(), IsNil) - c.Assert(ttl.Val(), Equals, 10*time.Second) - - persist := t.client.Persist("key") - c.Assert(persist.Err(), IsNil) - c.Assert(persist.Val(), Equals, true) - - ttl = t.client.TTL("key") - c.Assert(ttl.Err(), IsNil) - c.Assert(ttl.Val() < 0, Equals, true) -} - -func (t *RedisTest) TestCmdKeysPExpire(c *C) { - set := t.client.Set("key", "Hello") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - expiration := 900 * time.Millisecond - pexpire := t.client.PExpire("key", expiration) - c.Assert(pexpire.Err(), IsNil) - c.Assert(pexpire.Val(), Equals, true) - - ttl := t.client.TTL("key") - c.Assert(ttl.Err(), IsNil) - c.Assert(ttl.Val(), Equals, time.Second) - - pttl := t.client.PTTL("key") - c.Assert(pttl.Err(), IsNil) - c.Assert(pttl.Val() <= expiration, Equals, true) - c.Assert(pttl.Val() >= expiration-time.Millisecond, Equals, true) -} - -func (t *RedisTest) TestCmdKeysPExpireAt(c *C) { - set := t.client.Set("key", "Hello") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - expiration := 900 * time.Millisecond - pexpireat := t.client.PExpireAt("key", time.Now().Add(expiration)) - c.Assert(pexpireat.Err(), IsNil) - c.Assert(pexpireat.Val(), Equals, true) - - ttl := t.client.TTL("key") - c.Assert(ttl.Err(), IsNil) - c.Assert(ttl.Val(), Equals, time.Second) - - pttl := t.client.PTTL("key") - c.Assert(pttl.Err(), IsNil) - c.Assert(pttl.Val() <= expiration, Equals, true) - c.Assert(pttl.Val() >= expiration-time.Millisecond, Equals, true) -} - -func (t *RedisTest) TestCmdKeysPTTL(c *C) { - set := t.client.Set("key", "Hello") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - expiration := time.Second - expire := t.client.Expire("key", expiration) - c.Assert(expire.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - pttl := t.client.PTTL("key") - c.Assert(pttl.Err(), IsNil) - c.Assert(pttl.Val() <= expiration, Equals, true) - c.Assert(pttl.Val() >= expiration-time.Millisecond, Equals, true) -} - -func (t *RedisTest) TestCmdKeysRandomKey(c *C) { - randomKey := t.client.RandomKey() - c.Assert(randomKey.Err(), Equals, redis.Nil) - c.Assert(randomKey.Val(), Equals, "") - - set := t.client.Set("key", "hello") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - randomKey = t.client.RandomKey() - c.Assert(randomKey.Err(), IsNil) - c.Assert(randomKey.Val(), Equals, "key") -} - -func (t *RedisTest) TestCmdKeysRename(c *C) { - set := t.client.Set("key", "hello") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - status := t.client.Rename("key", "key1") - c.Assert(status.Err(), IsNil) - c.Assert(status.Val(), Equals, "OK") - - get := t.client.Get("key1") - c.Assert(get.Err(), IsNil) - c.Assert(get.Val(), Equals, "hello") -} - -func (t *RedisTest) TestCmdKeysRenameNX(c *C) { - set := t.client.Set("key", "hello") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - renameNX := t.client.RenameNX("key", "key1") - c.Assert(renameNX.Err(), IsNil) - c.Assert(renameNX.Val(), Equals, true) - - get := t.client.Get("key1") - c.Assert(get.Err(), IsNil) - c.Assert(get.Val(), Equals, "hello") -} - -func (t *RedisTest) TestCmdKeysRestore(c *C) { - set := t.client.Set("key", "hello") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - dump := t.client.Dump("key") - c.Assert(dump.Err(), IsNil) - - del := t.client.Del("key") - c.Assert(del.Err(), IsNil) - - restore := t.client.Restore("key", 0, dump.Val()) - c.Assert(restore.Err(), IsNil) - c.Assert(restore.Val(), Equals, "OK") - - type_ := t.client.Type("key") - c.Assert(type_.Err(), IsNil) - c.Assert(type_.Val(), Equals, "string") - - lRange := t.client.Get("key") - c.Assert(lRange.Err(), IsNil) - c.Assert(lRange.Val(), Equals, "hello") -} - -func (t *RedisTest) TestCmdKeysSort(c *C) { - lPush := t.client.LPush("list", "1") - c.Assert(lPush.Err(), IsNil) - c.Assert(lPush.Val(), Equals, int64(1)) - lPush = t.client.LPush("list", "3") - c.Assert(lPush.Err(), IsNil) - c.Assert(lPush.Val(), Equals, int64(2)) - lPush = t.client.LPush("list", "2") - c.Assert(lPush.Err(), IsNil) - c.Assert(lPush.Val(), Equals, int64(3)) - - sort := t.client.Sort("list", redis.Sort{Offset: 0, Count: 2, Order: "ASC"}) - c.Assert(sort.Err(), IsNil) - c.Assert(sort.Val(), DeepEquals, []string{"1", "2"}) -} - -func (t *RedisTest) TestCmdKeysSortBy(c *C) { - lPush := t.client.LPush("list", "1") - c.Assert(lPush.Err(), IsNil) - c.Assert(lPush.Val(), Equals, int64(1)) - lPush = t.client.LPush("list", "3") - c.Assert(lPush.Err(), IsNil) - c.Assert(lPush.Val(), Equals, int64(2)) - lPush = t.client.LPush("list", "2") - c.Assert(lPush.Err(), IsNil) - c.Assert(lPush.Val(), Equals, int64(3)) - - set := t.client.Set("weight_1", "5") - c.Assert(set.Err(), IsNil) - set = t.client.Set("weight_2", "2") - c.Assert(set.Err(), IsNil) - set = t.client.Set("weight_3", "8") - c.Assert(set.Err(), IsNil) - - sort := t.client.Sort("list", redis.Sort{Offset: 0, Count: 2, Order: "ASC", By: "weight_*"}) - c.Assert(sort.Err(), IsNil) - c.Assert(sort.Val(), DeepEquals, []string{"2", "1"}) -} - -func (t *RedisTest) TestCmdKeysTTL(c *C) { - ttl := t.client.TTL("key") - c.Assert(ttl.Err(), IsNil) - c.Assert(ttl.Val() < 0, Equals, true) - - set := t.client.Set("key", "hello") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - expire := t.client.Expire("key", 60*time.Second) - c.Assert(expire.Err(), IsNil) - c.Assert(expire.Val(), Equals, true) - - ttl = t.client.TTL("key") - c.Assert(ttl.Err(), IsNil) - c.Assert(ttl.Val(), Equals, 60*time.Second) -} - -func (t *RedisTest) TestCmdKeysType(c *C) { - set := t.client.Set("key", "hello") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - type_ := t.client.Type("key") - c.Assert(type_.Err(), IsNil) - c.Assert(type_.Val(), Equals, "string") -} - -func (t *RedisTest) TestCmdScan(c *C) { - for i := 0; i < 1000; i++ { - set := t.client.Set(fmt.Sprintf("key%d", i), "hello") - c.Assert(set.Err(), IsNil) - } - - cursor, keys, err := t.client.Scan(0, "", 0).Result() - c.Assert(err, IsNil) - c.Assert(cursor > 0, Equals, true) - c.Assert(len(keys) > 0, Equals, true) -} - -func (t *RedisTest) TestCmdSScan(c *C) { - for i := 0; i < 1000; i++ { - sadd := t.client.SAdd("myset", fmt.Sprintf("member%d", i)) - c.Assert(sadd.Err(), IsNil) - } - - cursor, keys, err := t.client.SScan("myset", 0, "", 0).Result() - c.Assert(err, IsNil) - c.Assert(cursor > 0, Equals, true) - c.Assert(len(keys) > 0, Equals, true) -} - -func (t *RedisTest) TestCmdHScan(c *C) { - for i := 0; i < 1000; i++ { - sadd := t.client.HSet("myhash", fmt.Sprintf("key%d", i), "hello") - c.Assert(sadd.Err(), IsNil) - } - - cursor, keys, err := t.client.HScan("myhash", 0, "", 0).Result() - c.Assert(err, IsNil) - c.Assert(cursor > 0, Equals, true) - c.Assert(len(keys) > 0, Equals, true) -} - -func (t *RedisTest) TestCmdZScan(c *C) { - for i := 0; i < 1000; i++ { - sadd := t.client.ZAdd("myset", redis.Z{float64(i), fmt.Sprintf("member%d", i)}) - c.Assert(sadd.Err(), IsNil) - } - - cursor, keys, err := t.client.ZScan("myset", 0, "", 0).Result() - c.Assert(err, IsNil) - c.Assert(cursor > 0, Equals, true) - c.Assert(len(keys) > 0, Equals, true) -} - -//------------------------------------------------------------------------------ - -func (t *RedisTest) TestStringsAppend(c *C) { - exists := t.client.Exists("key") - c.Assert(exists.Err(), IsNil) - c.Assert(exists.Val(), Equals, false) - - append := t.client.Append("key", "Hello") - c.Assert(append.Err(), IsNil) - c.Assert(append.Val(), Equals, int64(5)) - - append = t.client.Append("key", " World") - c.Assert(append.Err(), IsNil) - c.Assert(append.Val(), Equals, int64(11)) - - get := t.client.Get("key") - c.Assert(get.Err(), IsNil) - c.Assert(get.Val(), Equals, "Hello World") -} - -func (t *RedisTest) TestStringsBitCount(c *C) { - set := t.client.Set("key", "foobar") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - bitCount := t.client.BitCount("key", nil) - c.Assert(bitCount.Err(), IsNil) - c.Assert(bitCount.Val(), Equals, int64(26)) - - bitCount = t.client.BitCount("key", &redis.BitCount{0, 0}) - c.Assert(bitCount.Err(), IsNil) - c.Assert(bitCount.Val(), Equals, int64(4)) - - bitCount = t.client.BitCount("key", &redis.BitCount{1, 1}) - c.Assert(bitCount.Err(), IsNil) - c.Assert(bitCount.Val(), Equals, int64(6)) -} - -func (t *RedisTest) TestStringsBitOpAnd(c *C) { - set := t.client.Set("key1", "1") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - set = t.client.Set("key2", "0") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - bitOpAnd := t.client.BitOpAnd("dest", "key1", "key2") - c.Assert(bitOpAnd.Err(), IsNil) - c.Assert(bitOpAnd.Val(), Equals, int64(1)) - - get := t.client.Get("dest") - c.Assert(get.Err(), IsNil) - c.Assert(get.Val(), Equals, "0") -} - -func (t *RedisTest) TestStringsBitOpOr(c *C) { - set := t.client.Set("key1", "1") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - set = t.client.Set("key2", "0") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - bitOpOr := t.client.BitOpOr("dest", "key1", "key2") - c.Assert(bitOpOr.Err(), IsNil) - c.Assert(bitOpOr.Val(), Equals, int64(1)) - - get := t.client.Get("dest") - c.Assert(get.Err(), IsNil) - c.Assert(get.Val(), Equals, "1") -} - -func (t *RedisTest) TestStringsBitOpXor(c *C) { - set := t.client.Set("key1", "\xff") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - set = t.client.Set("key2", "\x0f") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - bitOpXor := t.client.BitOpXor("dest", "key1", "key2") - c.Assert(bitOpXor.Err(), IsNil) - c.Assert(bitOpXor.Val(), Equals, int64(1)) - - get := t.client.Get("dest") - c.Assert(get.Err(), IsNil) - c.Assert(get.Val(), Equals, "\xf0") -} - -func (t *RedisTest) TestStringsBitOpNot(c *C) { - set := t.client.Set("key1", "\x00") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - bitOpNot := t.client.BitOpNot("dest", "key1") - c.Assert(bitOpNot.Err(), IsNil) - c.Assert(bitOpNot.Val(), Equals, int64(1)) - - get := t.client.Get("dest") - c.Assert(get.Err(), IsNil) - c.Assert(get.Val(), Equals, "\xff") -} - -func (t *RedisTest) TestStringsDecr(c *C) { - set := t.client.Set("key", "10") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - decr := t.client.Decr("key") - c.Assert(decr.Err(), IsNil) - c.Assert(decr.Val(), Equals, int64(9)) - - set = t.client.Set("key", "234293482390480948029348230948") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - decr = t.client.Decr("key") - c.Assert(decr.Err(), ErrorMatches, "ERR value is not an integer or out of range") - c.Assert(decr.Val(), Equals, int64(0)) -} - -func (t *RedisTest) TestStringsDecrBy(c *C) { - set := t.client.Set("key", "10") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - decrBy := t.client.DecrBy("key", 5) - c.Assert(decrBy.Err(), IsNil) - c.Assert(decrBy.Val(), Equals, int64(5)) -} - -func (t *RedisTest) TestStringsGet(c *C) { - get := t.client.Get("_") - c.Assert(get.Err(), Equals, redis.Nil) - c.Assert(get.Val(), Equals, "") - - set := t.client.Set("key", "hello") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - get = t.client.Get("key") - c.Assert(get.Err(), IsNil) - c.Assert(get.Val(), Equals, "hello") -} - -func (t *RedisTest) TestStringsGetBit(c *C) { - setBit := t.client.SetBit("key", 7, 1) - c.Assert(setBit.Err(), IsNil) - c.Assert(setBit.Val(), Equals, int64(0)) - - getBit := t.client.GetBit("key", 0) - c.Assert(getBit.Err(), IsNil) - c.Assert(getBit.Val(), Equals, int64(0)) - - getBit = t.client.GetBit("key", 7) - c.Assert(getBit.Err(), IsNil) - c.Assert(getBit.Val(), Equals, int64(1)) - - getBit = t.client.GetBit("key", 100) - c.Assert(getBit.Err(), IsNil) - c.Assert(getBit.Val(), Equals, int64(0)) -} - -func (t *RedisTest) TestStringsGetRange(c *C) { - set := t.client.Set("key", "This is a string") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - getRange := t.client.GetRange("key", 0, 3) - c.Assert(getRange.Err(), IsNil) - c.Assert(getRange.Val(), Equals, "This") - - getRange = t.client.GetRange("key", -3, -1) - c.Assert(getRange.Err(), IsNil) - c.Assert(getRange.Val(), Equals, "ing") - - getRange = t.client.GetRange("key", 0, -1) - c.Assert(getRange.Err(), IsNil) - c.Assert(getRange.Val(), Equals, "This is a string") - - getRange = t.client.GetRange("key", 10, 100) - c.Assert(getRange.Err(), IsNil) - c.Assert(getRange.Val(), Equals, "string") -} - -func (t *RedisTest) TestStringsGetSet(c *C) { - incr := t.client.Incr("key") - c.Assert(incr.Err(), IsNil) - c.Assert(incr.Val(), Equals, int64(1)) - - getSet := t.client.GetSet("key", "0") - c.Assert(getSet.Err(), IsNil) - c.Assert(getSet.Val(), Equals, "1") - - get := t.client.Get("key") - c.Assert(get.Err(), IsNil) - c.Assert(get.Val(), Equals, "0") -} - -func (t *RedisTest) TestStringsIncr(c *C) { - set := t.client.Set("key", "10") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - incr := t.client.Incr("key") - c.Assert(incr.Err(), IsNil) - c.Assert(incr.Val(), Equals, int64(11)) - - get := t.client.Get("key") - c.Assert(get.Err(), IsNil) - c.Assert(get.Val(), Equals, "11") -} - -func (t *RedisTest) TestStringsIncrBy(c *C) { - set := t.client.Set("key", "10") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - incrBy := t.client.IncrBy("key", 5) - c.Assert(incrBy.Err(), IsNil) - c.Assert(incrBy.Val(), Equals, int64(15)) -} - -func (t *RedisTest) TestIncrByFloat(c *C) { - set := t.client.Set("key", "10.50") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - incrByFloat := t.client.IncrByFloat("key", 0.1) - c.Assert(incrByFloat.Err(), IsNil) - c.Assert(incrByFloat.Val(), Equals, 10.6) - - set = t.client.Set("key", "5.0e3") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - incrByFloat = t.client.IncrByFloat("key", 2.0e2) - c.Assert(incrByFloat.Err(), IsNil) - c.Assert(incrByFloat.Val(), Equals, float64(5200)) -} - -func (t *RedisTest) TestIncrByFloatOverflow(c *C) { - incrByFloat := t.client.IncrByFloat("key", 996945661) - c.Assert(incrByFloat.Err(), IsNil) - c.Assert(incrByFloat.Val(), Equals, float64(996945661)) -} - -func (t *RedisTest) TestStringsMSetMGet(c *C) { - mSet := t.client.MSet("key1", "hello1", "key2", "hello2") - c.Assert(mSet.Err(), IsNil) - c.Assert(mSet.Val(), Equals, "OK") - - mGet := t.client.MGet("key1", "key2", "_") - c.Assert(mGet.Err(), IsNil) - c.Assert(mGet.Val(), DeepEquals, []interface{}{"hello1", "hello2", nil}) -} - -func (t *RedisTest) TestStringsMSetNX(c *C) { - mSetNX := t.client.MSetNX("key1", "hello1", "key2", "hello2") - c.Assert(mSetNX.Err(), IsNil) - c.Assert(mSetNX.Val(), Equals, true) - - mSetNX = t.client.MSetNX("key2", "hello1", "key3", "hello2") - c.Assert(mSetNX.Err(), IsNil) - c.Assert(mSetNX.Val(), Equals, false) -} - -func (t *RedisTest) TestStringsPSetEx(c *C) { - expiration := 50 * time.Millisecond - psetex := t.client.PSetEx("key", expiration, "hello") - c.Assert(psetex.Err(), IsNil) - c.Assert(psetex.Val(), Equals, "OK") - - pttl := t.client.PTTL("key") - c.Assert(pttl.Err(), IsNil) - c.Assert(pttl.Val() <= expiration, Equals, true) - c.Assert(pttl.Val() >= expiration-time.Millisecond, Equals, true) - - get := t.client.Get("key") - c.Assert(get.Err(), IsNil) - c.Assert(get.Val(), Equals, "hello") -} - -func (t *RedisTest) TestStringsSetGet(c *C) { - set := t.client.Set("key", "hello") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - get := t.client.Get("key") - c.Assert(get.Err(), IsNil) - c.Assert(get.Val(), Equals, "hello") -} - -func (t *RedisTest) TestStringsSetEx(c *C) { - setEx := t.client.SetEx("key", 10*time.Second, "hello") - c.Assert(setEx.Err(), IsNil) - c.Assert(setEx.Val(), Equals, "OK") - - ttl := t.client.TTL("key") - c.Assert(ttl.Err(), IsNil) - c.Assert(ttl.Val(), Equals, 10*time.Second) -} - -func (t *RedisTest) TestStringsSetNX(c *C) { - setNX := t.client.SetNX("key", "hello") - c.Assert(setNX.Err(), IsNil) - c.Assert(setNX.Val(), Equals, true) - - setNX = t.client.SetNX("key", "hello2") - c.Assert(setNX.Err(), IsNil) - c.Assert(setNX.Val(), Equals, false) - - get := t.client.Get("key") - c.Assert(get.Err(), IsNil) - c.Assert(get.Val(), Equals, "hello") -} - -func (t *RedisTest) TestStringsSetRange(c *C) { - set := t.client.Set("key", "Hello World") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - range_ := t.client.SetRange("key", 6, "Redis") - c.Assert(range_.Err(), IsNil) - c.Assert(range_.Val(), Equals, int64(11)) - - get := t.client.Get("key") - c.Assert(get.Err(), IsNil) - c.Assert(get.Val(), Equals, "Hello Redis") -} - -func (t *RedisTest) TestStringsStrLen(c *C) { - set := t.client.Set("key", "hello") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - strLen := t.client.StrLen("key") - c.Assert(strLen.Err(), IsNil) - c.Assert(strLen.Val(), Equals, int64(5)) - - strLen = t.client.StrLen("_") - c.Assert(strLen.Err(), IsNil) - c.Assert(strLen.Val(), Equals, int64(0)) -} - -//------------------------------------------------------------------------------ - -func (t *RedisTest) TestCmdHDel(c *C) { - hSet := t.client.HSet("hash", "key", "hello") - c.Assert(hSet.Err(), IsNil) - - hDel := t.client.HDel("hash", "key") - c.Assert(hDel.Err(), IsNil) - c.Assert(hDel.Val(), Equals, int64(1)) - - hDel = t.client.HDel("hash", "key") - c.Assert(hDel.Err(), IsNil) - c.Assert(hDel.Val(), Equals, int64(0)) -} - -func (t *RedisTest) TestCmdHExists(c *C) { - hSet := t.client.HSet("hash", "key", "hello") - c.Assert(hSet.Err(), IsNil) - - hExists := t.client.HExists("hash", "key") - c.Assert(hExists.Err(), IsNil) - c.Assert(hExists.Val(), Equals, true) - - hExists = t.client.HExists("hash", "key1") - c.Assert(hExists.Err(), IsNil) - c.Assert(hExists.Val(), Equals, false) -} - -func (t *RedisTest) TestCmdHGet(c *C) { - hSet := t.client.HSet("hash", "key", "hello") - c.Assert(hSet.Err(), IsNil) - - hGet := t.client.HGet("hash", "key") - c.Assert(hGet.Err(), IsNil) - c.Assert(hGet.Val(), Equals, "hello") - - hGet = t.client.HGet("hash", "key1") - c.Assert(hGet.Err(), Equals, redis.Nil) - c.Assert(hGet.Val(), Equals, "") -} - -func (t *RedisTest) TestCmdHGetAll(c *C) { - hSet := t.client.HSet("hash", "key1", "hello1") - c.Assert(hSet.Err(), IsNil) - hSet = t.client.HSet("hash", "key2", "hello2") - c.Assert(hSet.Err(), IsNil) - - hGetAll := t.client.HGetAll("hash") - c.Assert(hGetAll.Err(), IsNil) - c.Assert(hGetAll.Val(), DeepEquals, []string{"key1", "hello1", "key2", "hello2"}) -} - -func (t *RedisTest) TestCmdHGetAllMap(c *C) { - hSet := t.client.HSet("hash", "key1", "hello1") - c.Assert(hSet.Err(), IsNil) - hSet = t.client.HSet("hash", "key2", "hello2") - c.Assert(hSet.Err(), IsNil) - - hGetAll := t.client.HGetAllMap("hash") - c.Assert(hGetAll.Err(), IsNil) - c.Assert(hGetAll.Val(), DeepEquals, map[string]string{"key1": "hello1", "key2": "hello2"}) -} - -func (t *RedisTest) TestCmdHIncrBy(c *C) { - hSet := t.client.HSet("hash", "key", "5") - c.Assert(hSet.Err(), IsNil) - - hIncrBy := t.client.HIncrBy("hash", "key", 1) - c.Assert(hIncrBy.Err(), IsNil) - c.Assert(hIncrBy.Val(), Equals, int64(6)) - - hIncrBy = t.client.HIncrBy("hash", "key", -1) - c.Assert(hIncrBy.Err(), IsNil) - c.Assert(hIncrBy.Val(), Equals, int64(5)) - - hIncrBy = t.client.HIncrBy("hash", "key", -10) - c.Assert(hIncrBy.Err(), IsNil) - c.Assert(hIncrBy.Val(), Equals, int64(-5)) -} - -func (t *RedisTest) TestCmdHIncrByFloat(c *C) { - hSet := t.client.HSet("hash", "field", "10.50") - c.Assert(hSet.Err(), IsNil) - c.Assert(hSet.Val(), Equals, true) - - hIncrByFloat := t.client.HIncrByFloat("hash", "field", 0.1) - c.Assert(hIncrByFloat.Err(), IsNil) - c.Assert(hIncrByFloat.Val(), Equals, 10.6) - - hSet = t.client.HSet("hash", "field", "5.0e3") - c.Assert(hSet.Err(), IsNil) - c.Assert(hSet.Val(), Equals, false) - - hIncrByFloat = t.client.HIncrByFloat("hash", "field", 2.0e2) - c.Assert(hIncrByFloat.Err(), IsNil) - c.Assert(hIncrByFloat.Val(), Equals, float64(5200)) -} - -func (t *RedisTest) TestCmdHKeys(c *C) { - hkeys := t.client.HKeys("hash") - c.Assert(hkeys.Err(), IsNil) - c.Assert(hkeys.Val(), DeepEquals, []string{}) - - hset := t.client.HSet("hash", "key1", "hello1") - c.Assert(hset.Err(), IsNil) - hset = t.client.HSet("hash", "key2", "hello2") - c.Assert(hset.Err(), IsNil) - - hkeys = t.client.HKeys("hash") - c.Assert(hkeys.Err(), IsNil) - c.Assert(hkeys.Val(), DeepEquals, []string{"key1", "key2"}) -} - -func (t *RedisTest) TestCmdHLen(c *C) { - hSet := t.client.HSet("hash", "key1", "hello1") - c.Assert(hSet.Err(), IsNil) - hSet = t.client.HSet("hash", "key2", "hello2") - c.Assert(hSet.Err(), IsNil) - - hLen := t.client.HLen("hash") - c.Assert(hLen.Err(), IsNil) - c.Assert(hLen.Val(), Equals, int64(2)) -} - -func (t *RedisTest) TestCmdHMGet(c *C) { - hSet := t.client.HSet("hash", "key1", "hello1") - c.Assert(hSet.Err(), IsNil) - hSet = t.client.HSet("hash", "key2", "hello2") - c.Assert(hSet.Err(), IsNil) - - hMGet := t.client.HMGet("hash", "key1", "key2", "_") - c.Assert(hMGet.Err(), IsNil) - c.Assert(hMGet.Val(), DeepEquals, []interface{}{"hello1", "hello2", nil}) -} - -func (t *RedisTest) TestCmdHMSet(c *C) { - hMSet := t.client.HMSet("hash", "key1", "hello1", "key2", "hello2") - c.Assert(hMSet.Err(), IsNil) - c.Assert(hMSet.Val(), Equals, "OK") - - hGet := t.client.HGet("hash", "key1") - c.Assert(hGet.Err(), IsNil) - c.Assert(hGet.Val(), Equals, "hello1") - - hGet = t.client.HGet("hash", "key2") - c.Assert(hGet.Err(), IsNil) - c.Assert(hGet.Val(), Equals, "hello2") -} - -func (t *RedisTest) TestCmdHSet(c *C) { - hSet := t.client.HSet("hash", "key", "hello") - c.Assert(hSet.Err(), IsNil) - c.Assert(hSet.Val(), Equals, true) - - hGet := t.client.HGet("hash", "key") - c.Assert(hGet.Err(), IsNil) - c.Assert(hGet.Val(), Equals, "hello") -} - -func (t *RedisTest) TestCmdHSetNX(c *C) { - hSetNX := t.client.HSetNX("hash", "key", "hello") - c.Assert(hSetNX.Err(), IsNil) - c.Assert(hSetNX.Val(), Equals, true) - - hSetNX = t.client.HSetNX("hash", "key", "hello") - c.Assert(hSetNX.Err(), IsNil) - c.Assert(hSetNX.Val(), Equals, false) - - hGet := t.client.HGet("hash", "key") - c.Assert(hGet.Err(), IsNil) - c.Assert(hGet.Val(), Equals, "hello") -} - -func (t *RedisTest) TestCmdHVals(c *C) { - hSet := t.client.HSet("hash", "key1", "hello1") - c.Assert(hSet.Err(), IsNil) - hSet = t.client.HSet("hash", "key2", "hello2") - c.Assert(hSet.Err(), IsNil) - - hVals := t.client.HVals("hash") - c.Assert(hVals.Err(), IsNil) - c.Assert(hVals.Val(), DeepEquals, []string{"hello1", "hello2"}) -} - -//------------------------------------------------------------------------------ - -func (t *RedisTest) TestCmdListsBLPop(c *C) { - rPush := t.client.RPush("list1", "a", "b", "c") - c.Assert(rPush.Err(), IsNil) - - bLPop := t.client.BLPop(0, "list1", "list2") - c.Assert(bLPop.Err(), IsNil) - c.Assert(bLPop.Val(), DeepEquals, []string{"list1", "a"}) -} - -func (t *RedisTest) TestCmdListsBLPopBlocks(c *C) { - started := make(chan bool) - done := make(chan bool) - go func() { - started <- true - bLPop := t.client.BLPop(0, "list") - c.Assert(bLPop.Err(), IsNil) - c.Assert(bLPop.Val(), DeepEquals, []string{"list", "a"}) - done <- true - }() - <-started - - select { - case <-done: - c.Error("BLPop is not blocked") - case <-time.After(time.Second): - // ok - } - - rPush := t.client.RPush("list", "a") - c.Assert(rPush.Err(), IsNil) - - select { - case <-done: - // ok - case <-time.After(time.Second): - c.Error("BLPop is still blocked") - // ok - } -} - -func (t *RedisTest) TestCmdListsBLPopTimeout(c *C) { - bLPop := t.client.BLPop(1, "list1") - c.Assert(bLPop.Err(), Equals, redis.Nil) - c.Assert(bLPop.Val(), IsNil) -} - -func (t *RedisTest) TestCmdListsBRPop(c *C) { - rPush := t.client.RPush("list1", "a", "b", "c") - c.Assert(rPush.Err(), IsNil) - - bRPop := t.client.BRPop(0, "list1", "list2") - c.Assert(bRPop.Err(), IsNil) - c.Assert(bRPop.Val(), DeepEquals, []string{"list1", "c"}) -} - -func (t *RedisTest) TestCmdListsBRPopBlocks(c *C) { - started := make(chan bool) - done := make(chan bool) - go func() { - started <- true - brpop := t.client.BRPop(0, "list") - c.Assert(brpop.Err(), IsNil) - c.Assert(brpop.Val(), DeepEquals, []string{"list", "a"}) - done <- true - }() - <-started - - select { - case <-done: - c.Error("BRPop is not blocked") - case <-time.After(time.Second): - // ok - } - - rPush := t.client.RPush("list", "a") - c.Assert(rPush.Err(), IsNil) - - select { - case <-done: - // ok - case <-time.After(time.Second): - c.Error("BRPop is still blocked") - // ok - } -} - -func (t *RedisTest) TestCmdListsBRPopLPush(c *C) { - rPush := t.client.RPush("list1", "a", "b", "c") - c.Assert(rPush.Err(), IsNil) - - bRPopLPush := t.client.BRPopLPush("list1", "list2", 0) - c.Assert(bRPopLPush.Err(), IsNil) - c.Assert(bRPopLPush.Val(), Equals, "c") -} - -func (t *RedisTest) TestCmdListsLIndex(c *C) { - lPush := t.client.LPush("list", "World") - c.Assert(lPush.Err(), IsNil) - lPush = t.client.LPush("list", "Hello") - c.Assert(lPush.Err(), IsNil) - - lIndex := t.client.LIndex("list", 0) - c.Assert(lIndex.Err(), IsNil) - c.Assert(lIndex.Val(), Equals, "Hello") - - lIndex = t.client.LIndex("list", -1) - c.Assert(lIndex.Err(), IsNil) - c.Assert(lIndex.Val(), Equals, "World") - - lIndex = t.client.LIndex("list", 3) - c.Assert(lIndex.Err(), Equals, redis.Nil) - c.Assert(lIndex.Val(), Equals, "") -} - -func (t *RedisTest) TestCmdListsLInsert(c *C) { - rPush := t.client.RPush("list", "Hello") - c.Assert(rPush.Err(), IsNil) - rPush = t.client.RPush("list", "World") - c.Assert(rPush.Err(), IsNil) - - lInsert := t.client.LInsert("list", "BEFORE", "World", "There") - c.Assert(lInsert.Err(), IsNil) - c.Assert(lInsert.Val(), Equals, int64(3)) - - lRange := t.client.LRange("list", 0, -1) - c.Assert(lRange.Err(), IsNil) - c.Assert(lRange.Val(), DeepEquals, []string{"Hello", "There", "World"}) -} - -func (t *RedisTest) TestCmdListsLLen(c *C) { - lPush := t.client.LPush("list", "World") - c.Assert(lPush.Err(), IsNil) - lPush = t.client.LPush("list", "Hello") - c.Assert(lPush.Err(), IsNil) - - lLen := t.client.LLen("list") - c.Assert(lLen.Err(), IsNil) - c.Assert(lLen.Val(), Equals, int64(2)) -} - -func (t *RedisTest) TestCmdListsLPop(c *C) { - rPush := t.client.RPush("list", "one") - c.Assert(rPush.Err(), IsNil) - rPush = t.client.RPush("list", "two") - c.Assert(rPush.Err(), IsNil) - rPush = t.client.RPush("list", "three") - c.Assert(rPush.Err(), IsNil) - - lPop := t.client.LPop("list") - c.Assert(lPop.Err(), IsNil) - c.Assert(lPop.Val(), Equals, "one") - - lRange := t.client.LRange("list", 0, -1) - c.Assert(lRange.Err(), IsNil) - c.Assert(lRange.Val(), DeepEquals, []string{"two", "three"}) -} - -func (t *RedisTest) TestCmdListsLPush(c *C) { - lPush := t.client.LPush("list", "World") - c.Assert(lPush.Err(), IsNil) - lPush = t.client.LPush("list", "Hello") - c.Assert(lPush.Err(), IsNil) - - lRange := t.client.LRange("list", 0, -1) - c.Assert(lRange.Err(), IsNil) - c.Assert(lRange.Val(), DeepEquals, []string{"Hello", "World"}) -} - -func (t *RedisTest) TestCmdListsLPushX(c *C) { - lPush := t.client.LPush("list", "World") - c.Assert(lPush.Err(), IsNil) - - lPushX := t.client.LPushX("list", "Hello") - c.Assert(lPushX.Err(), IsNil) - c.Assert(lPushX.Val(), Equals, int64(2)) - - lPushX = t.client.LPushX("list2", "Hello") - c.Assert(lPushX.Err(), IsNil) - c.Assert(lPushX.Val(), Equals, int64(0)) - - lRange := t.client.LRange("list", 0, -1) - c.Assert(lRange.Err(), IsNil) - c.Assert(lRange.Val(), DeepEquals, []string{"Hello", "World"}) - - lRange = t.client.LRange("list2", 0, -1) - c.Assert(lRange.Err(), IsNil) - c.Assert(lRange.Val(), DeepEquals, []string{}) -} - -func (t *RedisTest) TestCmdListsLRange(c *C) { - rPush := t.client.RPush("list", "one") - c.Assert(rPush.Err(), IsNil) - rPush = t.client.RPush("list", "two") - c.Assert(rPush.Err(), IsNil) - rPush = t.client.RPush("list", "three") - c.Assert(rPush.Err(), IsNil) - - lRange := t.client.LRange("list", 0, 0) - c.Assert(lRange.Err(), IsNil) - c.Assert(lRange.Val(), DeepEquals, []string{"one"}) - - lRange = t.client.LRange("list", -3, 2) - c.Assert(lRange.Err(), IsNil) - c.Assert(lRange.Val(), DeepEquals, []string{"one", "two", "three"}) - - lRange = t.client.LRange("list", -100, 100) - c.Assert(lRange.Err(), IsNil) - c.Assert(lRange.Val(), DeepEquals, []string{"one", "two", "three"}) - - lRange = t.client.LRange("list", 5, 10) - c.Assert(lRange.Err(), IsNil) - c.Assert(lRange.Val(), DeepEquals, []string{}) -} - -func (t *RedisTest) TestCmdListsLRem(c *C) { - rPush := t.client.RPush("list", "hello") - c.Assert(rPush.Err(), IsNil) - rPush = t.client.RPush("list", "hello") - c.Assert(rPush.Err(), IsNil) - rPush = t.client.RPush("list", "key") - c.Assert(rPush.Err(), IsNil) - rPush = t.client.RPush("list", "hello") - c.Assert(rPush.Err(), IsNil) - - lRem := t.client.LRem("list", -2, "hello") - c.Assert(lRem.Err(), IsNil) - c.Assert(lRem.Val(), Equals, int64(2)) - - lRange := t.client.LRange("list", 0, -1) - c.Assert(lRange.Err(), IsNil) - c.Assert(lRange.Val(), DeepEquals, []string{"hello", "key"}) -} - -func (t *RedisTest) TestCmdListsLSet(c *C) { - rPush := t.client.RPush("list", "one") - c.Assert(rPush.Err(), IsNil) - rPush = t.client.RPush("list", "two") - c.Assert(rPush.Err(), IsNil) - rPush = t.client.RPush("list", "three") - c.Assert(rPush.Err(), IsNil) - - lSet := t.client.LSet("list", 0, "four") - c.Assert(lSet.Err(), IsNil) - c.Assert(lSet.Val(), Equals, "OK") - - lSet = t.client.LSet("list", -2, "five") - c.Assert(lSet.Err(), IsNil) - c.Assert(lSet.Val(), Equals, "OK") - - lRange := t.client.LRange("list", 0, -1) - c.Assert(lRange.Err(), IsNil) - c.Assert(lRange.Val(), DeepEquals, []string{"four", "five", "three"}) -} - -func (t *RedisTest) TestCmdListsLTrim(c *C) { - rPush := t.client.RPush("list", "one") - c.Assert(rPush.Err(), IsNil) - rPush = t.client.RPush("list", "two") - c.Assert(rPush.Err(), IsNil) - rPush = t.client.RPush("list", "three") - c.Assert(rPush.Err(), IsNil) - - lTrim := t.client.LTrim("list", 1, -1) - c.Assert(lTrim.Err(), IsNil) - c.Assert(lTrim.Val(), Equals, "OK") - - lRange := t.client.LRange("list", 0, -1) - c.Assert(lRange.Err(), IsNil) - c.Assert(lRange.Val(), DeepEquals, []string{"two", "three"}) -} - -func (t *RedisTest) TestCmdListsRPop(c *C) { - rPush := t.client.RPush("list", "one") - c.Assert(rPush.Err(), IsNil) - rPush = t.client.RPush("list", "two") - c.Assert(rPush.Err(), IsNil) - rPush = t.client.RPush("list", "three") - c.Assert(rPush.Err(), IsNil) - - rPop := t.client.RPop("list") - c.Assert(rPop.Err(), IsNil) - c.Assert(rPop.Val(), Equals, "three") - - lRange := t.client.LRange("list", 0, -1) - c.Assert(lRange.Err(), IsNil) - c.Assert(lRange.Val(), DeepEquals, []string{"one", "two"}) -} - -func (t *RedisTest) TestCmdListsRPopLPush(c *C) { - rPush := t.client.RPush("list", "one") - c.Assert(rPush.Err(), IsNil) - rPush = t.client.RPush("list", "two") - c.Assert(rPush.Err(), IsNil) - rPush = t.client.RPush("list", "three") - c.Assert(rPush.Err(), IsNil) - - rPopLPush := t.client.RPopLPush("list", "list2") - c.Assert(rPopLPush.Err(), IsNil) - c.Assert(rPopLPush.Val(), Equals, "three") - - lRange := t.client.LRange("list", 0, -1) - c.Assert(lRange.Err(), IsNil) - c.Assert(lRange.Val(), DeepEquals, []string{"one", "two"}) - - lRange = t.client.LRange("list2", 0, -1) - c.Assert(lRange.Err(), IsNil) - c.Assert(lRange.Val(), DeepEquals, []string{"three"}) -} - -func (t *RedisTest) TestCmdListsRPush(c *C) { - rPush := t.client.RPush("list", "Hello") - c.Assert(rPush.Err(), IsNil) - c.Assert(rPush.Val(), Equals, int64(1)) - - rPush = t.client.RPush("list", "World") - c.Assert(rPush.Err(), IsNil) - c.Assert(rPush.Val(), Equals, int64(2)) - - lRange := t.client.LRange("list", 0, -1) - c.Assert(lRange.Err(), IsNil) - c.Assert(lRange.Val(), DeepEquals, []string{"Hello", "World"}) -} - -func (t *RedisTest) TestCmdListsRPushX(c *C) { - rPush := t.client.RPush("list", "Hello") - c.Assert(rPush.Err(), IsNil) - c.Assert(rPush.Val(), Equals, int64(1)) - - rPushX := t.client.RPushX("list", "World") - c.Assert(rPushX.Err(), IsNil) - c.Assert(rPushX.Val(), Equals, int64(2)) - - rPushX = t.client.RPushX("list2", "World") - c.Assert(rPushX.Err(), IsNil) - c.Assert(rPushX.Val(), Equals, int64(0)) - - lRange := t.client.LRange("list", 0, -1) - c.Assert(lRange.Err(), IsNil) - c.Assert(lRange.Val(), DeepEquals, []string{"Hello", "World"}) - - lRange = t.client.LRange("list2", 0, -1) - c.Assert(lRange.Err(), IsNil) - c.Assert(lRange.Val(), DeepEquals, []string{}) -} - -//------------------------------------------------------------------------------ - -func (t *RedisTest) TestSAdd(c *C) { - sAdd := t.client.SAdd("set", "Hello") - c.Assert(sAdd.Err(), IsNil) - c.Assert(sAdd.Val(), Equals, int64(1)) - - sAdd = t.client.SAdd("set", "World") - c.Assert(sAdd.Err(), IsNil) - c.Assert(sAdd.Val(), Equals, int64(1)) - - sAdd = t.client.SAdd("set", "World") - c.Assert(sAdd.Err(), IsNil) - c.Assert(sAdd.Val(), Equals, int64(0)) - - sMembers := t.client.SMembers("set") - c.Assert(sMembers.Err(), IsNil) - c.Assert(sortStrings(sMembers.Val()), DeepEquals, []string{"Hello", "World"}) -} - -func (t *RedisTest) TestSCard(c *C) { - sAdd := t.client.SAdd("set", "Hello") - c.Assert(sAdd.Err(), IsNil) - c.Assert(sAdd.Val(), Equals, int64(1)) - - sAdd = t.client.SAdd("set", "World") - c.Assert(sAdd.Err(), IsNil) - c.Assert(sAdd.Val(), Equals, int64(1)) - - sCard := t.client.SCard("set") - c.Assert(sCard.Err(), IsNil) - c.Assert(sCard.Val(), Equals, int64(2)) -} - -func (t *RedisTest) TestSDiff(c *C) { - sAdd := t.client.SAdd("set1", "a") - c.Assert(sAdd.Err(), IsNil) - sAdd = t.client.SAdd("set1", "b") - c.Assert(sAdd.Err(), IsNil) - sAdd = t.client.SAdd("set1", "c") - c.Assert(sAdd.Err(), IsNil) - - sAdd = t.client.SAdd("set2", "c") - c.Assert(sAdd.Err(), IsNil) - sAdd = t.client.SAdd("set2", "d") - c.Assert(sAdd.Err(), IsNil) - sAdd = t.client.SAdd("set2", "e") - c.Assert(sAdd.Err(), IsNil) - - sDiff := t.client.SDiff("set1", "set2") - c.Assert(sDiff.Err(), IsNil) - c.Assert(sortStrings(sDiff.Val()), DeepEquals, []string{"a", "b"}) -} - -func (t *RedisTest) TestSDiffStore(c *C) { - sAdd := t.client.SAdd("set1", "a") - c.Assert(sAdd.Err(), IsNil) - sAdd = t.client.SAdd("set1", "b") - c.Assert(sAdd.Err(), IsNil) - sAdd = t.client.SAdd("set1", "c") - c.Assert(sAdd.Err(), IsNil) - - sAdd = t.client.SAdd("set2", "c") - c.Assert(sAdd.Err(), IsNil) - sAdd = t.client.SAdd("set2", "d") - c.Assert(sAdd.Err(), IsNil) - sAdd = t.client.SAdd("set2", "e") - c.Assert(sAdd.Err(), IsNil) - - sDiffStore := t.client.SDiffStore("set", "set1", "set2") - c.Assert(sDiffStore.Err(), IsNil) - c.Assert(sDiffStore.Val(), Equals, int64(2)) - - sMembers := t.client.SMembers("set") - c.Assert(sMembers.Err(), IsNil) - c.Assert(sortStrings(sMembers.Val()), DeepEquals, []string{"a", "b"}) -} - -func (t *RedisTest) TestSInter(c *C) { - sAdd := t.client.SAdd("set1", "a") - c.Assert(sAdd.Err(), IsNil) - sAdd = t.client.SAdd("set1", "b") - c.Assert(sAdd.Err(), IsNil) - sAdd = t.client.SAdd("set1", "c") - c.Assert(sAdd.Err(), IsNil) - - sAdd = t.client.SAdd("set2", "c") - c.Assert(sAdd.Err(), IsNil) - sAdd = t.client.SAdd("set2", "d") - c.Assert(sAdd.Err(), IsNil) - sAdd = t.client.SAdd("set2", "e") - c.Assert(sAdd.Err(), IsNil) - - sInter := t.client.SInter("set1", "set2") - c.Assert(sInter.Err(), IsNil) - c.Assert(sInter.Val(), DeepEquals, []string{"c"}) -} - -func (t *RedisTest) TestSInterStore(c *C) { - sAdd := t.client.SAdd("set1", "a") - c.Assert(sAdd.Err(), IsNil) - sAdd = t.client.SAdd("set1", "b") - c.Assert(sAdd.Err(), IsNil) - sAdd = t.client.SAdd("set1", "c") - c.Assert(sAdd.Err(), IsNil) - - sAdd = t.client.SAdd("set2", "c") - c.Assert(sAdd.Err(), IsNil) - sAdd = t.client.SAdd("set2", "d") - c.Assert(sAdd.Err(), IsNil) - sAdd = t.client.SAdd("set2", "e") - c.Assert(sAdd.Err(), IsNil) - - sInterStore := t.client.SInterStore("set", "set1", "set2") - c.Assert(sInterStore.Err(), IsNil) - c.Assert(sInterStore.Val(), Equals, int64(1)) - - sMembers := t.client.SMembers("set") - c.Assert(sMembers.Err(), IsNil) - c.Assert(sMembers.Val(), DeepEquals, []string{"c"}) -} - -func (t *RedisTest) TestIsMember(c *C) { - sAdd := t.client.SAdd("set", "one") - c.Assert(sAdd.Err(), IsNil) - - sIsMember := t.client.SIsMember("set", "one") - c.Assert(sIsMember.Err(), IsNil) - c.Assert(sIsMember.Val(), Equals, true) - - sIsMember = t.client.SIsMember("set", "two") - c.Assert(sIsMember.Err(), IsNil) - c.Assert(sIsMember.Val(), Equals, false) -} - -func (t *RedisTest) TestSMembers(c *C) { - sAdd := t.client.SAdd("set", "Hello") - c.Assert(sAdd.Err(), IsNil) - sAdd = t.client.SAdd("set", "World") - c.Assert(sAdd.Err(), IsNil) - - sMembers := t.client.SMembers("set") - c.Assert(sMembers.Err(), IsNil) - c.Assert(sortStrings(sMembers.Val()), DeepEquals, []string{"Hello", "World"}) -} - -func (t *RedisTest) TestSMove(c *C) { - sAdd := t.client.SAdd("set1", "one") - c.Assert(sAdd.Err(), IsNil) - sAdd = t.client.SAdd("set1", "two") - c.Assert(sAdd.Err(), IsNil) - - sAdd = t.client.SAdd("set2", "three") - c.Assert(sAdd.Err(), IsNil) - - sMove := t.client.SMove("set1", "set2", "two") - c.Assert(sMove.Err(), IsNil) - c.Assert(sMove.Val(), Equals, true) - - sMembers := t.client.SMembers("set1") - c.Assert(sMembers.Err(), IsNil) - c.Assert(sMembers.Val(), DeepEquals, []string{"one"}) - - sMembers = t.client.SMembers("set2") - c.Assert(sMembers.Err(), IsNil) - c.Assert(sortStrings(sMembers.Val()), DeepEquals, []string{"three", "two"}) -} - -func (t *RedisTest) TestSPop(c *C) { - sAdd := t.client.SAdd("set", "one") - c.Assert(sAdd.Err(), IsNil) - sAdd = t.client.SAdd("set", "two") - c.Assert(sAdd.Err(), IsNil) - sAdd = t.client.SAdd("set", "three") - c.Assert(sAdd.Err(), IsNil) - - sPop := t.client.SPop("set") - c.Assert(sPop.Err(), IsNil) - c.Assert(sPop.Val(), Not(Equals), "") - - sMembers := t.client.SMembers("set") - c.Assert(sMembers.Err(), IsNil) - c.Assert(sMembers.Val(), HasLen, 2) -} - -func (t *RedisTest) TestSRandMember(c *C) { - sAdd := t.client.SAdd("set", "one") - c.Assert(sAdd.Err(), IsNil) - sAdd = t.client.SAdd("set", "two") - c.Assert(sAdd.Err(), IsNil) - sAdd = t.client.SAdd("set", "three") - c.Assert(sAdd.Err(), IsNil) - - sRandMember := t.client.SRandMember("set") - c.Assert(sRandMember.Err(), IsNil) - c.Assert(sRandMember.Val(), Not(Equals), "") - - sMembers := t.client.SMembers("set") - c.Assert(sMembers.Err(), IsNil) - c.Assert(sMembers.Val(), HasLen, 3) -} - -func (t *RedisTest) TestSRem(c *C) { - sAdd := t.client.SAdd("set", "one") - c.Assert(sAdd.Err(), IsNil) - sAdd = t.client.SAdd("set", "two") - c.Assert(sAdd.Err(), IsNil) - sAdd = t.client.SAdd("set", "three") - c.Assert(sAdd.Err(), IsNil) - - sRem := t.client.SRem("set", "one") - c.Assert(sRem.Err(), IsNil) - c.Assert(sRem.Val(), Equals, int64(1)) - - sRem = t.client.SRem("set", "four") - c.Assert(sRem.Err(), IsNil) - c.Assert(sRem.Val(), Equals, int64(0)) - - sMembers := t.client.SMembers("set") - c.Assert(sMembers.Err(), IsNil) - c.Assert( - sortStrings(sMembers.Val()), - DeepEquals, - []string{"three", "two"}, - ) -} - -func (t *RedisTest) TestSUnion(c *C) { - sAdd := t.client.SAdd("set1", "a") - c.Assert(sAdd.Err(), IsNil) - sAdd = t.client.SAdd("set1", "b") - c.Assert(sAdd.Err(), IsNil) - sAdd = t.client.SAdd("set1", "c") - c.Assert(sAdd.Err(), IsNil) - - sAdd = t.client.SAdd("set2", "c") - c.Assert(sAdd.Err(), IsNil) - sAdd = t.client.SAdd("set2", "d") - c.Assert(sAdd.Err(), IsNil) - sAdd = t.client.SAdd("set2", "e") - c.Assert(sAdd.Err(), IsNil) - - sUnion := t.client.SUnion("set1", "set2") - c.Assert(sUnion.Err(), IsNil) - c.Assert(sUnion.Val(), HasLen, 5) -} - -func (t *RedisTest) TestSUnionStore(c *C) { - sAdd := t.client.SAdd("set1", "a") - c.Assert(sAdd.Err(), IsNil) - sAdd = t.client.SAdd("set1", "b") - c.Assert(sAdd.Err(), IsNil) - sAdd = t.client.SAdd("set1", "c") - c.Assert(sAdd.Err(), IsNil) - - sAdd = t.client.SAdd("set2", "c") - c.Assert(sAdd.Err(), IsNil) - sAdd = t.client.SAdd("set2", "d") - c.Assert(sAdd.Err(), IsNil) - sAdd = t.client.SAdd("set2", "e") - c.Assert(sAdd.Err(), IsNil) - - sUnionStore := t.client.SUnionStore("set", "set1", "set2") - c.Assert(sUnionStore.Err(), IsNil) - c.Assert(sUnionStore.Val(), Equals, int64(5)) - - sMembers := t.client.SMembers("set") - c.Assert(sMembers.Err(), IsNil) - c.Assert(sMembers.Val(), HasLen, 5) -} - -//------------------------------------------------------------------------------ - -func (t *RedisTest) TestZAdd(c *C) { - zAdd := t.client.ZAdd("zset", redis.Z{1, "one"}) - c.Assert(zAdd.Err(), IsNil) - c.Assert(zAdd.Val(), Equals, int64(1)) - - zAdd = t.client.ZAdd("zset", redis.Z{1, "uno"}) - c.Assert(zAdd.Err(), IsNil) - c.Assert(zAdd.Val(), Equals, int64(1)) - - zAdd = t.client.ZAdd("zset", redis.Z{2, "two"}) - c.Assert(zAdd.Err(), IsNil) - c.Assert(zAdd.Val(), Equals, int64(1)) - - zAdd = t.client.ZAdd("zset", redis.Z{3, "two"}) - c.Assert(zAdd.Err(), IsNil) - c.Assert(zAdd.Val(), Equals, int64(0)) - - val, err := t.client.ZRangeWithScores("zset", 0, -1).Result() - c.Assert(err, IsNil) - c.Assert(val, DeepEquals, []redis.Z{{1, "one"}, {1, "uno"}, {3, "two"}}) -} - -func (t *RedisTest) TestZCard(c *C) { - zAdd := t.client.ZAdd("zset", redis.Z{1, "one"}) - c.Assert(zAdd.Err(), IsNil) - zAdd = t.client.ZAdd("zset", redis.Z{2, "two"}) - c.Assert(zAdd.Err(), IsNil) - - zCard := t.client.ZCard("zset") - c.Assert(zCard.Err(), IsNil) - c.Assert(zCard.Val(), Equals, int64(2)) -} - -func (t *RedisTest) TestZCount(c *C) { - zAdd := t.client.ZAdd("zset", redis.Z{1, "one"}) - c.Assert(zAdd.Err(), IsNil) - zAdd = t.client.ZAdd("zset", redis.Z{2, "two"}) - c.Assert(zAdd.Err(), IsNil) - zAdd = t.client.ZAdd("zset", redis.Z{3, "three"}) - c.Assert(zAdd.Err(), IsNil) - - zCount := t.client.ZCount("zset", "-inf", "+inf") - c.Assert(zCount.Err(), IsNil) - c.Assert(zCount.Val(), Equals, int64(3)) - - zCount = t.client.ZCount("zset", "(1", "3") - c.Assert(zCount.Err(), IsNil) - c.Assert(zCount.Val(), Equals, int64(2)) -} - -func (t *RedisTest) TestZIncrBy(c *C) { - zAdd := t.client.ZAdd("zset", redis.Z{1, "one"}) - c.Assert(zAdd.Err(), IsNil) - zAdd = t.client.ZAdd("zset", redis.Z{2, "two"}) - c.Assert(zAdd.Err(), IsNil) - - zIncrBy := t.client.ZIncrBy("zset", 2, "one") - c.Assert(zIncrBy.Err(), IsNil) - c.Assert(zIncrBy.Val(), Equals, float64(3)) - - val, err := t.client.ZRangeWithScores("zset", 0, -1).Result() - c.Assert(err, IsNil) - c.Assert(val, DeepEquals, []redis.Z{{2, "two"}, {3, "one"}}) -} - -func (t *RedisTest) TestZInterStore(c *C) { - zAdd := t.client.ZAdd("zset1", redis.Z{1, "one"}) - c.Assert(zAdd.Err(), IsNil) - zAdd = t.client.ZAdd("zset1", redis.Z{2, "two"}) - c.Assert(zAdd.Err(), IsNil) - - zAdd = t.client.ZAdd("zset2", redis.Z{1, "one"}) - c.Assert(zAdd.Err(), IsNil) - zAdd = t.client.ZAdd("zset2", redis.Z{2, "two"}) - c.Assert(zAdd.Err(), IsNil) - zAdd = t.client.ZAdd("zset3", redis.Z{3, "two"}) - c.Assert(zAdd.Err(), IsNil) - - zInterStore := t.client.ZInterStore( - "out", redis.ZStore{Weights: []int64{2, 3}}, "zset1", "zset2") - c.Assert(zInterStore.Err(), IsNil) - c.Assert(zInterStore.Val(), Equals, int64(2)) - - val, err := t.client.ZRangeWithScores("out", 0, -1).Result() - c.Assert(err, IsNil) - c.Assert(val, DeepEquals, []redis.Z{{5, "one"}, {10, "two"}}) -} - -func (t *RedisTest) TestZRange(c *C) { - zAdd := t.client.ZAdd("zset", redis.Z{1, "one"}) - c.Assert(zAdd.Err(), IsNil) - zAdd = t.client.ZAdd("zset", redis.Z{2, "two"}) - c.Assert(zAdd.Err(), IsNil) - zAdd = t.client.ZAdd("zset", redis.Z{3, "three"}) - c.Assert(zAdd.Err(), IsNil) - - zRange := t.client.ZRange("zset", 0, -1) - c.Assert(zRange.Err(), IsNil) - c.Assert(zRange.Val(), DeepEquals, []string{"one", "two", "three"}) - - zRange = t.client.ZRange("zset", 2, 3) - c.Assert(zRange.Err(), IsNil) - c.Assert(zRange.Val(), DeepEquals, []string{"three"}) - - zRange = t.client.ZRange("zset", -2, -1) - c.Assert(zRange.Err(), IsNil) - c.Assert(zRange.Val(), DeepEquals, []string{"two", "three"}) -} - -func (t *RedisTest) TestZRangeWithScores(c *C) { - zAdd := t.client.ZAdd("zset", redis.Z{1, "one"}) - c.Assert(zAdd.Err(), IsNil) - zAdd = t.client.ZAdd("zset", redis.Z{2, "two"}) - c.Assert(zAdd.Err(), IsNil) - zAdd = t.client.ZAdd("zset", redis.Z{3, "three"}) - c.Assert(zAdd.Err(), IsNil) - - val, err := t.client.ZRangeWithScores("zset", 0, -1).Result() - c.Assert(err, IsNil) - c.Assert(val, DeepEquals, []redis.Z{{1, "one"}, {2, "two"}, {3, "three"}}) - - val, err = t.client.ZRangeWithScores("zset", 2, 3).Result() - c.Assert(err, IsNil) - c.Assert(val, DeepEquals, []redis.Z{{3, "three"}}) - - val, err = t.client.ZRangeWithScores("zset", -2, -1).Result() - c.Assert(err, IsNil) - c.Assert(val, DeepEquals, []redis.Z{{2, "two"}, {3, "three"}}) -} - -func (t *RedisTest) TestZRangeByScore(c *C) { - zAdd := t.client.ZAdd("zset", redis.Z{1, "one"}) - c.Assert(zAdd.Err(), IsNil) - zAdd = t.client.ZAdd("zset", redis.Z{2, "two"}) - c.Assert(zAdd.Err(), IsNil) - zAdd = t.client.ZAdd("zset", redis.Z{3, "three"}) - c.Assert(zAdd.Err(), IsNil) - - zRangeByScore := t.client.ZRangeByScore("zset", redis.ZRangeByScore{ - Min: "-inf", - Max: "+inf", - }) - c.Assert(zRangeByScore.Err(), IsNil) - c.Assert(zRangeByScore.Val(), DeepEquals, []string{"one", "two", "three"}) - - zRangeByScore = t.client.ZRangeByScore("zset", redis.ZRangeByScore{ - Min: "1", - Max: "2", - }) - c.Assert(zRangeByScore.Err(), IsNil) - c.Assert(zRangeByScore.Val(), DeepEquals, []string{"one", "two"}) - - zRangeByScore = t.client.ZRangeByScore("zset", redis.ZRangeByScore{ - Min: "(1", - Max: "2", - }) - c.Assert(zRangeByScore.Err(), IsNil) - c.Assert(zRangeByScore.Val(), DeepEquals, []string{"two"}) - - zRangeByScore = t.client.ZRangeByScore("zset", redis.ZRangeByScore{ - Min: "(1", - Max: "(2", - }) - c.Assert(zRangeByScore.Err(), IsNil) - c.Assert(zRangeByScore.Val(), DeepEquals, []string{}) -} - -func (t *RedisTest) TestZRangeByScoreWithScoresMap(c *C) { - zAdd := t.client.ZAdd("zset", redis.Z{1, "one"}) - c.Assert(zAdd.Err(), IsNil) - zAdd = t.client.ZAdd("zset", redis.Z{2, "two"}) - c.Assert(zAdd.Err(), IsNil) - zAdd = t.client.ZAdd("zset", redis.Z{3, "three"}) - c.Assert(zAdd.Err(), IsNil) - - val, err := t.client.ZRangeByScoreWithScores("zset", redis.ZRangeByScore{ - Min: "-inf", - Max: "+inf", - }).Result() - c.Assert(err, IsNil) - c.Assert(val, DeepEquals, []redis.Z{{1, "one"}, {2, "two"}, {3, "three"}}) - - val, err = t.client.ZRangeByScoreWithScores("zset", redis.ZRangeByScore{ - Min: "1", - Max: "2", - }).Result() - c.Assert(err, IsNil) - c.Assert(val, DeepEquals, []redis.Z{{1, "one"}, {2, "two"}}) - - val, err = t.client.ZRangeByScoreWithScores("zset", redis.ZRangeByScore{ - Min: "(1", - Max: "2", - }).Result() - c.Assert(err, IsNil) - c.Assert(val, DeepEquals, []redis.Z{{2, "two"}}) - - val, err = t.client.ZRangeByScoreWithScores("zset", redis.ZRangeByScore{ - Min: "(1", - Max: "(2", - }).Result() - c.Assert(err, IsNil) - c.Assert(val, DeepEquals, []redis.Z{}) -} - -func (t *RedisTest) TestZRank(c *C) { - zAdd := t.client.ZAdd("zset", redis.Z{1, "one"}) - c.Assert(zAdd.Err(), IsNil) - zAdd = t.client.ZAdd("zset", redis.Z{2, "two"}) - c.Assert(zAdd.Err(), IsNil) - zAdd = t.client.ZAdd("zset", redis.Z{3, "three"}) - c.Assert(zAdd.Err(), IsNil) - - zRank := t.client.ZRank("zset", "three") - c.Assert(zRank.Err(), IsNil) - c.Assert(zRank.Val(), Equals, int64(2)) - - zRank = t.client.ZRank("zset", "four") - c.Assert(zRank.Err(), Equals, redis.Nil) - c.Assert(zRank.Val(), Equals, int64(0)) -} - -func (t *RedisTest) TestZRem(c *C) { - zAdd := t.client.ZAdd("zset", redis.Z{1, "one"}) - c.Assert(zAdd.Err(), IsNil) - zAdd = t.client.ZAdd("zset", redis.Z{2, "two"}) - c.Assert(zAdd.Err(), IsNil) - zAdd = t.client.ZAdd("zset", redis.Z{3, "three"}) - c.Assert(zAdd.Err(), IsNil) - - zRem := t.client.ZRem("zset", "two") - c.Assert(zRem.Err(), IsNil) - c.Assert(zRem.Val(), Equals, int64(1)) - - val, err := t.client.ZRangeWithScores("zset", 0, -1).Result() - c.Assert(err, IsNil) - c.Assert(val, DeepEquals, []redis.Z{{1, "one"}, {3, "three"}}) -} - -func (t *RedisTest) TestZRemRangeByRank(c *C) { - zAdd := t.client.ZAdd("zset", redis.Z{1, "one"}) - c.Assert(zAdd.Err(), IsNil) - zAdd = t.client.ZAdd("zset", redis.Z{2, "two"}) - c.Assert(zAdd.Err(), IsNil) - zAdd = t.client.ZAdd("zset", redis.Z{3, "three"}) - c.Assert(zAdd.Err(), IsNil) - - zRemRangeByRank := t.client.ZRemRangeByRank("zset", 0, 1) - c.Assert(zRemRangeByRank.Err(), IsNil) - c.Assert(zRemRangeByRank.Val(), Equals, int64(2)) - - val, err := t.client.ZRangeWithScores("zset", 0, -1).Result() - c.Assert(err, IsNil) - c.Assert(val, DeepEquals, []redis.Z{{3, "three"}}) -} - -func (t *RedisTest) TestZRemRangeByScore(c *C) { - zAdd := t.client.ZAdd("zset", redis.Z{1, "one"}) - c.Assert(zAdd.Err(), IsNil) - zAdd = t.client.ZAdd("zset", redis.Z{2, "two"}) - c.Assert(zAdd.Err(), IsNil) - zAdd = t.client.ZAdd("zset", redis.Z{3, "three"}) - c.Assert(zAdd.Err(), IsNil) - - zRemRangeByScore := t.client.ZRemRangeByScore("zset", "-inf", "(2") - c.Assert(zRemRangeByScore.Err(), IsNil) - c.Assert(zRemRangeByScore.Val(), Equals, int64(1)) - - val, err := t.client.ZRangeWithScores("zset", 0, -1).Result() - c.Assert(err, IsNil) - c.Assert(val, DeepEquals, []redis.Z{{2, "two"}, {3, "three"}}) -} - -func (t *RedisTest) TestZRevRange(c *C) { - zAdd := t.client.ZAdd("zset", redis.Z{1, "one"}) - c.Assert(zAdd.Err(), IsNil) - zAdd = t.client.ZAdd("zset", redis.Z{2, "two"}) - c.Assert(zAdd.Err(), IsNil) - zAdd = t.client.ZAdd("zset", redis.Z{3, "three"}) - c.Assert(zAdd.Err(), IsNil) - - zRevRange := t.client.ZRevRange("zset", "0", "-1") - c.Assert(zRevRange.Err(), IsNil) - c.Assert(zRevRange.Val(), DeepEquals, []string{"three", "two", "one"}) - - zRevRange = t.client.ZRevRange("zset", "2", "3") - c.Assert(zRevRange.Err(), IsNil) - c.Assert(zRevRange.Val(), DeepEquals, []string{"one"}) - - zRevRange = t.client.ZRevRange("zset", "-2", "-1") - c.Assert(zRevRange.Err(), IsNil) - c.Assert(zRevRange.Val(), DeepEquals, []string{"two", "one"}) -} - -func (t *RedisTest) TestZRevRangeWithScoresMap(c *C) { - zAdd := t.client.ZAdd("zset", redis.Z{1, "one"}) - c.Assert(zAdd.Err(), IsNil) - zAdd = t.client.ZAdd("zset", redis.Z{2, "two"}) - c.Assert(zAdd.Err(), IsNil) - zAdd = t.client.ZAdd("zset", redis.Z{3, "three"}) - c.Assert(zAdd.Err(), IsNil) - - val, err := t.client.ZRevRangeWithScores("zset", "0", "-1").Result() - c.Assert(err, IsNil) - c.Assert(val, DeepEquals, []redis.Z{{3, "three"}, {2, "two"}, {1, "one"}}) - - val, err = t.client.ZRevRangeWithScores("zset", "2", "3").Result() - c.Assert(err, IsNil) - c.Assert(val, DeepEquals, []redis.Z{{1, "one"}}) - - val, err = t.client.ZRevRangeWithScores("zset", "-2", "-1").Result() - c.Assert(err, IsNil) - c.Assert(val, DeepEquals, []redis.Z{{2, "two"}, {1, "one"}}) -} - -func (t *RedisTest) TestZRevRangeByScore(c *C) { - zadd := t.client.ZAdd("zset", redis.Z{1, "one"}) - c.Assert(zadd.Err(), IsNil) - zadd = t.client.ZAdd("zset", redis.Z{2, "two"}) - c.Assert(zadd.Err(), IsNil) - zadd = t.client.ZAdd("zset", redis.Z{3, "three"}) - c.Assert(zadd.Err(), IsNil) - - vals, err := t.client.ZRevRangeByScore( - "zset", redis.ZRangeByScore{Max: "+inf", Min: "-inf"}).Result() - c.Assert(err, IsNil) - c.Assert(vals, DeepEquals, []string{"three", "two", "one"}) - - vals, err = t.client.ZRevRangeByScore( - "zset", redis.ZRangeByScore{Max: "2", Min: "(1"}).Result() - c.Assert(err, IsNil) - c.Assert(vals, DeepEquals, []string{"two"}) - - vals, err = t.client.ZRevRangeByScore( - "zset", redis.ZRangeByScore{Max: "(2", Min: "(1"}).Result() - c.Assert(err, IsNil) - c.Assert(vals, DeepEquals, []string{}) -} - -func (t *RedisTest) TestZRevRangeByScoreWithScores(c *C) { - zadd := t.client.ZAdd("zset", redis.Z{1, "one"}) - c.Assert(zadd.Err(), IsNil) - zadd = t.client.ZAdd("zset", redis.Z{2, "two"}) - c.Assert(zadd.Err(), IsNil) - zadd = t.client.ZAdd("zset", redis.Z{3, "three"}) - c.Assert(zadd.Err(), IsNil) - - vals, err := t.client.ZRevRangeByScoreWithScores( - "zset", redis.ZRangeByScore{Max: "+inf", Min: "-inf"}).Result() - c.Assert(err, IsNil) - c.Assert(vals, DeepEquals, []redis.Z{{3, "three"}, {2, "two"}, {1, "one"}}) -} - -func (t *RedisTest) TestZRevRangeByScoreWithScoresMap(c *C) { - zAdd := t.client.ZAdd("zset", redis.Z{1, "one"}) - c.Assert(zAdd.Err(), IsNil) - zAdd = t.client.ZAdd("zset", redis.Z{2, "two"}) - c.Assert(zAdd.Err(), IsNil) - zAdd = t.client.ZAdd("zset", redis.Z{3, "three"}) - c.Assert(zAdd.Err(), IsNil) - - val, err := t.client.ZRevRangeByScoreWithScores( - "zset", redis.ZRangeByScore{Max: "+inf", Min: "-inf"}).Result() - c.Assert(err, IsNil) - c.Assert(val, DeepEquals, []redis.Z{{3, "three"}, {2, "two"}, {1, "one"}}) - - val, err = t.client.ZRevRangeByScoreWithScores( - "zset", redis.ZRangeByScore{Max: "2", Min: "(1"}).Result() - c.Assert(err, IsNil) - c.Assert(val, DeepEquals, []redis.Z{{2, "two"}}) - - val, err = t.client.ZRevRangeByScoreWithScores( - "zset", redis.ZRangeByScore{Max: "(2", Min: "(1"}).Result() - c.Assert(err, IsNil) - c.Assert(val, DeepEquals, []redis.Z{}) -} - -func (t *RedisTest) TestZRevRank(c *C) { - zAdd := t.client.ZAdd("zset", redis.Z{1, "one"}) - c.Assert(zAdd.Err(), IsNil) - zAdd = t.client.ZAdd("zset", redis.Z{2, "two"}) - c.Assert(zAdd.Err(), IsNil) - zAdd = t.client.ZAdd("zset", redis.Z{3, "three"}) - c.Assert(zAdd.Err(), IsNil) - - zRevRank := t.client.ZRevRank("zset", "one") - c.Assert(zRevRank.Err(), IsNil) - c.Assert(zRevRank.Val(), Equals, int64(2)) - - zRevRank = t.client.ZRevRank("zset", "four") - c.Assert(zRevRank.Err(), Equals, redis.Nil) - c.Assert(zRevRank.Val(), Equals, int64(0)) -} - -func (t *RedisTest) TestZScore(c *C) { - zAdd := t.client.ZAdd("zset", redis.Z{1.001, "one"}) - c.Assert(zAdd.Err(), IsNil) - - zScore := t.client.ZScore("zset", "one") - c.Assert(zScore.Err(), IsNil) - c.Assert(zScore.Val(), Equals, float64(1.001)) -} - -func (t *RedisTest) TestZUnionStore(c *C) { - zAdd := t.client.ZAdd("zset1", redis.Z{1, "one"}) - c.Assert(zAdd.Err(), IsNil) - zAdd = t.client.ZAdd("zset1", redis.Z{2, "two"}) - c.Assert(zAdd.Err(), IsNil) - - zAdd = t.client.ZAdd("zset2", redis.Z{1, "one"}) - c.Assert(zAdd.Err(), IsNil) - zAdd = t.client.ZAdd("zset2", redis.Z{2, "two"}) - c.Assert(zAdd.Err(), IsNil) - zAdd = t.client.ZAdd("zset2", redis.Z{3, "three"}) - c.Assert(zAdd.Err(), IsNil) - - zUnionStore := t.client.ZUnionStore( - "out", redis.ZStore{Weights: []int64{2, 3}}, "zset1", "zset2") - c.Assert(zUnionStore.Err(), IsNil) - c.Assert(zUnionStore.Val(), Equals, int64(3)) - - val, err := t.client.ZRangeWithScores("out", 0, -1).Result() - c.Assert(err, IsNil) - c.Assert(val, DeepEquals, []redis.Z{{5, "one"}, {9, "three"}, {10, "two"}}) -} - -//------------------------------------------------------------------------------ - -func (t *RedisTest) TestPatternPubSub(c *C) { - pubsub := t.client.PubSub() - defer func() { - c.Assert(pubsub.Close(), IsNil) - }() - - c.Assert(pubsub.PSubscribe("mychannel*"), IsNil) - - pub := t.client.Publish("mychannel1", "hello") - c.Assert(pub.Err(), IsNil) - c.Assert(pub.Val(), Equals, int64(1)) - - c.Assert(pubsub.PUnsubscribe("mychannel*"), IsNil) - - { - msgi, err := pubsub.ReceiveTimeout(time.Second) - c.Assert(err, IsNil) - subscr := msgi.(*redis.Subscription) - c.Assert(subscr.Kind, Equals, "psubscribe") - c.Assert(subscr.Channel, Equals, "mychannel*") - c.Assert(subscr.Count, Equals, 1) - } - - { - msgi, err := pubsub.ReceiveTimeout(time.Second) - c.Assert(err, IsNil) - subscr := msgi.(*redis.PMessage) - c.Assert(subscr.Channel, Equals, "mychannel1") - c.Assert(subscr.Pattern, Equals, "mychannel*") - c.Assert(subscr.Payload, Equals, "hello") - } - - { - msgi, err := pubsub.ReceiveTimeout(time.Second) - c.Assert(err, IsNil) - subscr := msgi.(*redis.Subscription) - c.Assert(subscr.Kind, Equals, "punsubscribe") - c.Assert(subscr.Channel, Equals, "mychannel*") - c.Assert(subscr.Count, Equals, 0) - } - - { - msgi, err := pubsub.ReceiveTimeout(time.Second) - c.Assert(err.(net.Error).Timeout(), Equals, true) - c.Assert(msgi, IsNil) - } -} - -func (t *RedisTest) TestPubSub(c *C) { - pubsub := t.client.PubSub() - defer func() { - c.Assert(pubsub.Close(), IsNil) - }() - - c.Assert(pubsub.Subscribe("mychannel", "mychannel2"), IsNil) - - pub := t.client.Publish("mychannel", "hello") - c.Assert(pub.Err(), IsNil) - c.Assert(pub.Val(), Equals, int64(1)) - - pub = t.client.Publish("mychannel2", "hello2") - c.Assert(pub.Err(), IsNil) - c.Assert(pub.Val(), Equals, int64(1)) - - c.Assert(pubsub.Unsubscribe("mychannel", "mychannel2"), IsNil) - - { - msgi, err := pubsub.ReceiveTimeout(time.Second) - c.Assert(err, IsNil) - subscr := msgi.(*redis.Subscription) - c.Assert(subscr.Kind, Equals, "subscribe") - c.Assert(subscr.Channel, Equals, "mychannel") - c.Assert(subscr.Count, Equals, 1) - } - - { - msgi, err := pubsub.ReceiveTimeout(time.Second) - c.Assert(err, IsNil) - subscr := msgi.(*redis.Subscription) - c.Assert(subscr.Kind, Equals, "subscribe") - c.Assert(subscr.Channel, Equals, "mychannel2") - c.Assert(subscr.Count, Equals, 2) - } - - { - msgi, err := pubsub.ReceiveTimeout(time.Second) - c.Assert(err, IsNil) - subscr := msgi.(*redis.Message) - c.Assert(subscr.Channel, Equals, "mychannel") - c.Assert(subscr.Payload, Equals, "hello") - } - - { - msgi, err := pubsub.ReceiveTimeout(time.Second) - c.Assert(err, IsNil) - msg := msgi.(*redis.Message) - c.Assert(msg.Channel, Equals, "mychannel2") - c.Assert(msg.Payload, Equals, "hello2") - } - - { - msgi, err := pubsub.ReceiveTimeout(time.Second) - c.Assert(err, IsNil) - subscr := msgi.(*redis.Subscription) - c.Assert(subscr.Kind, Equals, "unsubscribe") - c.Assert(subscr.Channel, Equals, "mychannel") - c.Assert(subscr.Count, Equals, 1) - } - - { - msgi, err := pubsub.ReceiveTimeout(time.Second) - c.Assert(err, IsNil) - subscr := msgi.(*redis.Subscription) - c.Assert(subscr.Kind, Equals, "unsubscribe") - c.Assert(subscr.Channel, Equals, "mychannel2") - c.Assert(subscr.Count, Equals, 0) - } - - { - msgi, err := pubsub.ReceiveTimeout(time.Second) - c.Assert(err.(net.Error).Timeout(), Equals, true) - c.Assert(msgi, IsNil) - } -} - -func (t *RedisTest) TestPubSubChannels(c *C) { - channels, err := t.client.PubSubChannels("mychannel*").Result() - c.Assert(err, IsNil) - c.Assert(channels, HasLen, 0) - c.Assert(channels, Not(IsNil)) - - pubsub := t.client.PubSub() - defer pubsub.Close() - - c.Assert(pubsub.Subscribe("mychannel", "mychannel2"), IsNil) - - channels, err = t.client.PubSubChannels("mychannel*").Result() - c.Assert(err, IsNil) - c.Assert(sortStrings(channels), DeepEquals, []string{"mychannel", "mychannel2"}) - - channels, err = t.client.PubSubChannels("").Result() - c.Assert(err, IsNil) - c.Assert(channels, HasLen, 0) - - channels, err = t.client.PubSubChannels("*").Result() - c.Assert(err, IsNil) - c.Assert(len(channels) >= 2, Equals, true) -} - -func (t *RedisTest) TestPubSubNumSub(c *C) { - pubsub := t.client.PubSub() - defer pubsub.Close() - - c.Assert(pubsub.Subscribe("mychannel", "mychannel2"), IsNil) - - channels, err := t.client.PubSubNumSub("mychannel", "mychannel2", "mychannel3").Result() - c.Assert(err, IsNil) - c.Assert( - channels, - DeepEquals, - []interface{}{"mychannel", int64(1), "mychannel2", int64(1), "mychannel3", int64(0)}, - ) -} - -func (t *RedisTest) TestPubSubNumPat(c *C) { - num, err := t.client.PubSubNumPat().Result() - c.Assert(err, IsNil) - c.Assert(num, Equals, int64(0)) - - pubsub := t.client.PubSub() - defer pubsub.Close() - - c.Assert(pubsub.PSubscribe("mychannel*"), IsNil) - - num, err = t.client.PubSubNumPat().Result() - c.Assert(err, IsNil) - c.Assert(num, Equals, int64(1)) -} - -//------------------------------------------------------------------------------ - -func (t *RedisTest) TestPipeline(c *C) { - set := t.client.Set("key2", "hello2") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - pipeline := t.client.Pipeline() - defer func() { - c.Assert(pipeline.Close(), IsNil) - }() - - set = pipeline.Set("key1", "hello1") - get := pipeline.Get("key2") - incr := pipeline.Incr("key3") - getNil := pipeline.Get("key4") - - cmds, err := pipeline.Exec() - c.Assert(err, Equals, redis.Nil) - c.Assert(cmds, HasLen, 4) - - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - c.Assert(get.Err(), IsNil) - c.Assert(get.Val(), Equals, "hello2") - - c.Assert(incr.Err(), IsNil) - c.Assert(incr.Val(), Equals, int64(1)) - - c.Assert(getNil.Err(), Equals, redis.Nil) - c.Assert(getNil.Val(), Equals, "") -} - -func (t *RedisTest) TestPipelineDiscardQueued(c *C) { - pipeline := t.client.Pipeline() - - pipeline.Get("key") - pipeline.Discard() - cmds, err := pipeline.Exec() - c.Assert(err, IsNil) - c.Assert(cmds, HasLen, 0) - - c.Assert(pipeline.Close(), IsNil) -} - -func (t *RedisTest) TestPipelined(c *C) { - var get *redis.StringCmd - cmds, err := t.client.Pipelined(func(pipe *redis.Pipeline) error { - get = pipe.Get("foo") - return nil - }) - c.Assert(err, Equals, redis.Nil) - c.Assert(cmds, HasLen, 1) - c.Assert(cmds[0], Equals, get) - c.Assert(get.Err(), Equals, redis.Nil) - c.Assert(get.Val(), Equals, "") -} - -func (t *RedisTest) TestPipelineErrValNotSet(c *C) { - pipeline := t.client.Pipeline() - defer func() { - c.Assert(pipeline.Close(), IsNil) - }() - - get := pipeline.Get("key") - c.Assert(get.Err(), IsNil) - c.Assert(get.Val(), Equals, "") -} - -func (t *RedisTest) TestPipelineRunQueuedOnEmptyQueue(c *C) { - pipeline := t.client.Pipeline() - defer func() { - c.Assert(pipeline.Close(), IsNil) - }() - - cmds, err := pipeline.Exec() - c.Assert(err, IsNil) - c.Assert(cmds, HasLen, 0) -} - -// TODO: make thread safe? -func (t *RedisTest) TestPipelineIncr(c *C) { - const N = 20000 - key := "TestPipelineIncr" - - pipeline := t.client.Pipeline() - - wg := &sync.WaitGroup{} - wg.Add(N) - for i := 0; i < N; i++ { - pipeline.Incr(key) - wg.Done() - } - wg.Wait() - - cmds, err := pipeline.Exec() - c.Assert(err, IsNil) - c.Assert(len(cmds), Equals, 20000) - for _, cmd := range cmds { - if cmd.Err() != nil { - c.Errorf("got %v, expected nil", cmd.Err()) - } - } - - get := t.client.Get(key) - c.Assert(get.Err(), IsNil) - c.Assert(get.Val(), Equals, strconv.Itoa(N)) - - c.Assert(pipeline.Close(), IsNil) -} - -func (t *RedisTest) TestPipelineEcho(c *C) { - const N = 1000 - - wg := &sync.WaitGroup{} - wg.Add(N) - for i := 0; i < N; i++ { - go func(i int) { - pipeline := t.client.Pipeline() - - msg1 := "echo" + strconv.Itoa(i) - msg2 := "echo" + strconv.Itoa(i+1) - - echo1 := pipeline.Echo(msg1) - echo2 := pipeline.Echo(msg2) - - cmds, err := pipeline.Exec() - c.Assert(err, IsNil) - c.Assert(cmds, HasLen, 2) - - c.Assert(echo1.Err(), IsNil) - c.Assert(echo1.Val(), Equals, msg1) - - c.Assert(echo2.Err(), IsNil) - c.Assert(echo2.Val(), Equals, msg2) - - c.Assert(pipeline.Close(), IsNil) - - wg.Done() - }(i) - } - wg.Wait() -} - -//------------------------------------------------------------------------------ - -func (t *RedisTest) TestMultiExec(c *C) { - multi := t.client.Multi() - defer func() { - c.Assert(multi.Close(), IsNil) - }() - - var ( - set *redis.StatusCmd - get *redis.StringCmd - ) - cmds, err := multi.Exec(func() error { - set = multi.Set("key", "hello") - get = multi.Get("key") - return nil - }) - c.Assert(err, IsNil) - c.Assert(cmds, HasLen, 2) - - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - c.Assert(get.Err(), IsNil) - c.Assert(get.Val(), Equals, "hello") -} - -func (t *RedisTest) TestMultiExecDiscard(c *C) { - multi := t.client.Multi() - defer func() { - c.Assert(multi.Close(), IsNil) - }() - - cmds, err := multi.Exec(func() error { - multi.Set("key1", "hello1") - multi.Discard() - multi.Set("key2", "hello2") - return nil - }) - c.Assert(err, IsNil) - c.Assert(cmds, HasLen, 1) - - get := t.client.Get("key1") - c.Assert(get.Err(), Equals, redis.Nil) - c.Assert(get.Val(), Equals, "") - - get = t.client.Get("key2") - c.Assert(get.Err(), IsNil) - c.Assert(get.Val(), Equals, "hello2") -} - -func (t *RedisTest) TestMultiExecEmpty(c *C) { - multi := t.client.Multi() - defer func() { - c.Assert(multi.Close(), IsNil) - }() - - cmds, err := multi.Exec(func() error { return nil }) - c.Assert(err, IsNil) - c.Assert(cmds, HasLen, 0) - - ping := multi.Ping() - c.Check(ping.Err(), IsNil) - c.Check(ping.Val(), Equals, "PONG") -} - -func (t *RedisTest) TestMultiExecOnEmptyQueue(c *C) { - multi := t.client.Multi() - defer func() { - c.Assert(multi.Close(), IsNil) - }() - - cmds, err := multi.Exec(func() error { return nil }) - c.Assert(err, IsNil) - c.Assert(cmds, HasLen, 0) -} - -func (t *RedisTest) TestMultiExecIncr(c *C) { - multi := t.client.Multi() - defer func() { - c.Assert(multi.Close(), IsNil) - }() - - cmds, err := multi.Exec(func() error { - for i := int64(0); i < 20000; i++ { - multi.Incr("key") - } - return nil - }) - c.Assert(err, IsNil) - c.Assert(len(cmds), Equals, 20000) - for _, cmd := range cmds { - if cmd.Err() != nil { - c.Errorf("got %v, expected nil", cmd.Err()) - } - } - - get := t.client.Get("key") - c.Assert(get.Err(), IsNil) - c.Assert(get.Val(), Equals, "20000") -} - -func (t *RedisTest) transactionalIncr(c *C) ([]redis.Cmder, error) { - multi := t.client.Multi() - defer func() { - c.Assert(multi.Close(), IsNil) - }() - - watch := multi.Watch("key") - c.Assert(watch.Err(), IsNil) - c.Assert(watch.Val(), Equals, "OK") - - get := multi.Get("key") - c.Assert(get.Err(), IsNil) - c.Assert(get.Val(), Not(Equals), redis.Nil) - - v, err := strconv.ParseInt(get.Val(), 10, 64) - c.Assert(err, IsNil) - - return multi.Exec(func() error { - multi.Set("key", strconv.FormatInt(v+1, 10)) - return nil - }) -} - -func (t *RedisTest) TestWatchUnwatch(c *C) { - var n = 10000 - if testing.Short() { - n = 1000 - } - - set := t.client.Set("key", "0") - c.Assert(set.Err(), IsNil) - - wg := &sync.WaitGroup{} - for i := 0; i < n; i++ { - wg.Add(1) - go func() { - defer wg.Done() - for { - cmds, err := t.transactionalIncr(c) - if err == redis.TxFailedErr { - continue - } - c.Assert(err, IsNil) - c.Assert(cmds, HasLen, 1) - c.Assert(cmds[0].Err(), IsNil) - break - } - }() - } - wg.Wait() - - val, err := t.client.Get("key").Int64() - c.Assert(err, IsNil) - c.Assert(val, Equals, int64(n)) -} - -//------------------------------------------------------------------------------ - -func (t *RedisTest) TestRaceEcho(c *C) { - var n = 10000 - if testing.Short() { - n = 1000 - } - - wg := &sync.WaitGroup{} - wg.Add(n) - for i := 0; i < n; i++ { - go func(i int) { - msg := "echo" + strconv.Itoa(i) - echo := t.client.Echo(msg) - c.Assert(echo.Err(), IsNil) - c.Assert(echo.Val(), Equals, msg) - wg.Done() - }(i) - } - wg.Wait() -} - -func (t *RedisTest) TestRaceIncr(c *C) { - var n = 10000 - if testing.Short() { - n = 1000 - } - - wg := &sync.WaitGroup{} - wg.Add(n) - for i := 0; i < n; i++ { - go func() { - incr := t.client.Incr("TestRaceIncr") - if err := incr.Err(); err != nil { - panic(err) - } - wg.Done() - }() - } - wg.Wait() - - val, err := t.client.Get("TestRaceIncr").Result() - c.Assert(err, IsNil) - c.Assert(val, Equals, strconv.Itoa(n)) -} - -//------------------------------------------------------------------------------ - -func (t *RedisTest) TestCmdBgRewriteAOF(c *C) { - r := t.client.BgRewriteAOF() - c.Assert(r.Err(), IsNil) - c.Assert(r.Val(), Equals, "Background append only file rewriting started") -} - -func (t *RedisTest) TestCmdBgSave(c *C) { - // workaround for "ERR Can't BGSAVE while AOF log rewriting is in progress" - time.Sleep(time.Second) - - r := t.client.BgSave() - c.Assert(r.Err(), IsNil) - c.Assert(r.Val(), Equals, "Background saving started") -} - -func (t *RedisTest) TestCmdClientKill(c *C) { - r := t.client.ClientKill("1.1.1.1:1111") - c.Assert(r.Err(), ErrorMatches, "ERR No such client") - c.Assert(r.Val(), Equals, "") -} - -func (t *RedisTest) TestCmdConfigGet(c *C) { - r := t.client.ConfigGet("*") - c.Assert(r.Err(), IsNil) - c.Assert(len(r.Val()) > 0, Equals, true) -} - -func (t *RedisTest) TestCmdConfigResetStat(c *C) { - r := t.client.ConfigResetStat() - c.Assert(r.Err(), IsNil) - c.Assert(r.Val(), Equals, "OK") -} - -func (t *RedisTest) TestCmdConfigSet(c *C) { - configGet := t.client.ConfigGet("maxmemory") - c.Assert(configGet.Err(), IsNil) - c.Assert(configGet.Val(), HasLen, 2) - c.Assert(configGet.Val()[0], Equals, "maxmemory") - - configSet := t.client.ConfigSet("maxmemory", configGet.Val()[1].(string)) - c.Assert(configSet.Err(), IsNil) - c.Assert(configSet.Val(), Equals, "OK") -} - -func (t *RedisTest) TestCmdDbSize(c *C) { - dbSize := t.client.DbSize() - c.Assert(dbSize.Err(), IsNil) - c.Assert(dbSize.Val(), Equals, int64(0)) -} - -func (t *RedisTest) TestCmdFlushAll(c *C) { - // TODO -} - -func (t *RedisTest) TestCmdFlushDb(c *C) { - // TODO -} - -func (t *RedisTest) TestCmdInfo(c *C) { - info := t.client.Info() - c.Assert(info.Err(), IsNil) - c.Assert(info.Val(), Not(Equals), "") -} - -func (t *RedisTest) TestCmdLastSave(c *C) { - lastSave := t.client.LastSave() - c.Assert(lastSave.Err(), IsNil) - c.Assert(lastSave.Val(), Not(Equals), 0) -} - -func (t *RedisTest) TestCmdSave(c *C) { - save := t.client.Save() - c.Assert(save.Err(), IsNil) - c.Assert(save.Val(), Equals, "OK") -} - -func (t *RedisTest) TestSlaveOf(c *C) { - slaveOf := t.client.SlaveOf("localhost", "8888") - c.Assert(slaveOf.Err(), IsNil) - c.Assert(slaveOf.Val(), Equals, "OK") - - slaveOf = t.client.SlaveOf("NO", "ONE") - c.Assert(slaveOf.Err(), IsNil) - c.Assert(slaveOf.Val(), Equals, "OK") -} - -func (t *RedisTest) TestTime(c *C) { - time := t.client.Time() - c.Assert(time.Err(), IsNil) - c.Assert(time.Val(), HasLen, 2) -} - -//------------------------------------------------------------------------------ - -func (t *RedisTest) TestScriptingEval(c *C) { - eval := t.client.Eval( - "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}", - []string{"key1", "key2"}, - []string{"first", "second"}, - ) - c.Assert(eval.Err(), IsNil) - c.Assert(eval.Val(), DeepEquals, []interface{}{"key1", "key2", "first", "second"}) - - eval = t.client.Eval( - "return redis.call('set',KEYS[1],'bar')", - []string{"foo"}, - []string{}, - ) - c.Assert(eval.Err(), IsNil) - c.Assert(eval.Val(), Equals, "OK") - - eval = t.client.Eval("return 10", []string{}, []string{}) - c.Assert(eval.Err(), IsNil) - c.Assert(eval.Val(), Equals, int64(10)) - - eval = t.client.Eval("return {1,2,{3,'Hello World!'}}", []string{}, []string{}) - c.Assert(eval.Err(), IsNil) - // DeepEquals can't compare nested slices. - c.Assert( - fmt.Sprintf("%#v", eval.Val()), - Equals, - `[]interface {}{1, 2, []interface {}{3, "Hello World!"}}`, - ) -} - -func (t *RedisTest) TestScriptingEvalSha(c *C) { - set := t.client.Set("foo", "bar") - c.Assert(set.Err(), IsNil) - c.Assert(set.Val(), Equals, "OK") - - eval := t.client.Eval("return redis.call('get','foo')", nil, nil) - c.Assert(eval.Err(), IsNil) - c.Assert(eval.Val(), Equals, "bar") - - evalSha := t.client.EvalSha("6b1bf486c81ceb7edf3c093f4c48582e38c0e791", nil, nil) - c.Assert(evalSha.Err(), IsNil) - c.Assert(evalSha.Val(), Equals, "bar") - - evalSha = t.client.EvalSha("ffffffffffffffffffffffffffffffffffffffff", nil, nil) - c.Assert(evalSha.Err(), ErrorMatches, "NOSCRIPT No matching script. Please use EVAL.") - c.Assert(evalSha.Val(), Equals, nil) -} - -func (t *RedisTest) TestScriptingScriptExists(c *C) { - scriptLoad := t.client.ScriptLoad("return 1") - c.Assert(scriptLoad.Err(), IsNil) - c.Assert(scriptLoad.Val(), Equals, "e0e1f9fabfc9d4800c877a703b823ac0578ff8db") - - scriptExists := t.client.ScriptExists( - "e0e1f9fabfc9d4800c877a703b823ac0578ff8db", - "ffffffffffffffffffffffffffffffffffffffff", - ) - c.Assert(scriptExists.Err(), IsNil) - c.Assert(scriptExists.Val(), DeepEquals, []bool{true, false}) -} - -func (t *RedisTest) TestScriptingScriptFlush(c *C) { - scriptFlush := t.client.ScriptFlush() - c.Assert(scriptFlush.Err(), IsNil) - c.Assert(scriptFlush.Val(), Equals, "OK") -} - -func (t *RedisTest) TestScriptingScriptKill(c *C) { - scriptKill := t.client.ScriptKill() - c.Assert(scriptKill.Err(), ErrorMatches, ".*No scripts in execution right now.") - c.Assert(scriptKill.Val(), Equals, "") -} - -func (t *RedisTest) TestScriptingScriptLoad(c *C) { - scriptLoad := t.client.ScriptLoad("return redis.call('get','foo')") - c.Assert(scriptLoad.Err(), IsNil) - c.Assert(scriptLoad.Val(), Equals, "6b1bf486c81ceb7edf3c093f4c48582e38c0e791") -} - -func (t *RedisTest) TestScriptingNewScript(c *C) { - s := redis.NewScript("return 1") - run := s.Run(t.client, nil, nil) - c.Assert(run.Err(), IsNil) - c.Assert(run.Val(), Equals, int64(1)) -} - -func (t *RedisTest) TestScriptingEvalAndPipeline(c *C) { - pipeline := t.client.Pipeline() - s := redis.NewScript("return 1") - run := s.Eval(pipeline, nil, nil) - _, err := pipeline.Exec() - c.Assert(err, IsNil) - c.Assert(run.Err(), IsNil) - c.Assert(run.Val(), Equals, int64(1)) -} - -func (t *RedisTest) TestScriptingEvalShaAndPipeline(c *C) { - s := redis.NewScript("return 1") - c.Assert(s.Load(t.client).Err(), IsNil) - - pipeline := t.client.Pipeline() - run := s.Eval(pipeline, nil, nil) - _, err := pipeline.Exec() - c.Assert(err, IsNil) - c.Assert(run.Err(), IsNil) - c.Assert(run.Val(), Equals, int64(1)) -} - -//------------------------------------------------------------------------------ - -func (t *RedisTest) TestCmdDebugObject(c *C) { - { - debug := t.client.DebugObject("foo") - c.Assert(debug.Err(), Not(IsNil)) - c.Assert(debug.Err().Error(), Equals, "ERR no such key") - } - - { - t.client.Set("foo", "bar") - debug := t.client.DebugObject("foo") - c.Assert(debug.Err(), IsNil) - c.Assert(debug.Val(), FitsTypeOf, "") - c.Assert(debug.Val(), Not(Equals), "") - } -} - -//------------------------------------------------------------------------------ - func BenchmarkRedisPing(b *testing.B) { b.StopTimer() client := redis.NewTCPClient(&redis.Options{ diff --git a/sentinel_test.go b/sentinel_test.go index ede59bd5..abbba925 100644 --- a/sentinel_test.go +++ b/sentinel_test.go @@ -5,181 +5,118 @@ import ( "os" "os/exec" "path/filepath" - "testing" - "text/template" - "time" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" "gopkg.in/redis.v2" ) -func startRedis(port string) (*exec.Cmd, error) { - cmd := exec.Command("redis-server", "--port", port) - if false { - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - } - if err := cmd.Start(); err != nil { - return nil, err - } - return cmd, nil -} +var _ = Describe("Sentinel", func() { -func startRedisSlave(port, slave string) (*exec.Cmd, error) { - cmd := exec.Command("redis-server", "--port", port, "--slaveof", "127.0.0.1", slave) - if false { - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - } - if err := cmd.Start(); err != nil { - return nil, err - } - return cmd, nil -} + const masterName = "mymaster" + const masterPort = "8123" + const sentinelPort = "8124" + const sentinelConf = ` +port ` + sentinelPort + ` -func startRedisSentinel(port, masterName, masterPort string) (*exec.Cmd, error) { - dir, err := ioutil.TempDir("", "sentinel") - if err != nil { - return nil, err - } - - sentinelConfFilepath := filepath.Join(dir, "sentinel.conf") - tpl, err := template.New("sentinel.conf").Parse(sentinelConf) - if err != nil { - return nil, err - } - - data := struct { - Port string - MasterName string - MasterPort string - }{ - Port: port, - MasterName: masterName, - MasterPort: masterPort, - } - if err := writeTemplateToFile(sentinelConfFilepath, tpl, data); err != nil { - return nil, err - } - - cmd := exec.Command("redis-server", sentinelConfFilepath, "--sentinel") - if true { - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - } - if err := cmd.Start(); err != nil { - return nil, err - } - - return cmd, nil -} - -func writeTemplateToFile(path string, t *template.Template, data interface{}) error { - f, err := os.Create(path) - if err != nil { - return err - } - defer f.Close() - return t.Execute(f, data) -} - -func TestSentinel(t *testing.T) { - masterName := "mymaster" - masterPort := "8123" - slavePort := "8124" - sentinelPort := "8125" - - masterCmd, err := startRedis(masterPort) - if err != nil { - t.Fatal(err) - } - defer masterCmd.Process.Kill() - - // Wait for master to start. - time.Sleep(200 * time.Millisecond) - - master := redis.NewTCPClient(&redis.Options{ - Addr: ":" + masterPort, - }) - if err := master.Ping().Err(); err != nil { - t.Fatal(err) - } - - slaveCmd, err := startRedisSlave(slavePort, masterPort) - if err != nil { - t.Fatal(err) - } - defer slaveCmd.Process.Kill() - - // Wait for slave to start. - time.Sleep(200 * time.Millisecond) - - slave := redis.NewTCPClient(&redis.Options{ - Addr: ":" + slavePort, - }) - if err := slave.Ping().Err(); err != nil { - t.Fatal(err) - } - - sentinelCmd, err := startRedisSentinel(sentinelPort, masterName, masterPort) - if err != nil { - t.Fatal(err) - } - defer sentinelCmd.Process.Kill() - - // Wait for sentinel to start. - time.Sleep(200 * time.Millisecond) - - sentinel := redis.NewTCPClient(&redis.Options{ - Addr: ":" + sentinelPort, - }) - if err := sentinel.Ping().Err(); err != nil { - t.Fatal(err) - } - defer sentinel.Shutdown() - - client := redis.NewFailoverClient(&redis.FailoverOptions{ - MasterName: masterName, - SentinelAddrs: []string{":" + sentinelPort}, - }) - - if err := client.Set("foo", "master").Err(); err != nil { - t.Fatal(err) - } - - val, err := master.Get("foo").Result() - if err != nil { - t.Fatal(err) - } - if val != "master" { - t.Fatalf(`got %q, expected "master"`, val) - } - - // Kill Redis master. - if err := masterCmd.Process.Kill(); err != nil { - t.Fatal(err) - } - if err := master.Ping().Err(); err == nil { - t.Fatalf("master was not killed") - } - - // Wait for Redis sentinel to elect new master. - time.Sleep(5 * time.Second) - - // Check that client picked up new master. - val, err = client.Get("foo").Result() - if err != nil { - t.Fatal(err) - } - if val != "master" { - t.Fatalf(`got %q, expected "master"`, val) - } -} - -var sentinelConf = ` -port {{ .Port }} - -sentinel monitor {{ .MasterName }} 127.0.0.1 {{ .MasterPort }} 1 -sentinel down-after-milliseconds {{ .MasterName }} 1000 -sentinel failover-timeout {{ .MasterName }} 2000 -sentinel parallel-syncs {{ .MasterName }} 1 +sentinel monitor ` + masterName + ` 127.0.0.1 ` + masterPort + ` 1 +sentinel down-after-milliseconds ` + masterName + ` 400 +sentinel failover-timeout ` + masterName + ` 800 +sentinel parallel-syncs ` + masterName + ` 1 ` + + var runCmd = func(name string, args ...string) *os.Process { + cmd := exec.Command(name, args...) + if false { + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + } + err := cmd.Start() + Expect(err).NotTo(HaveOccurred()) + return cmd.Process + } + + var connect = func(port string) *redis.Client { + client := redis.NewTCPClient(&redis.Options{ + Addr: ":" + port, + }) + Eventually(func() error { + return client.Ping().Err() + }, "1s", "100ms").ShouldNot(HaveOccurred()) + return client + } + + var startMaster = func() (*redis.Client, *os.Process) { + proc := runCmd("redis-server", "--port", masterPort) + return connect(masterPort), proc + } + + var startSlave = func(port string) (*redis.Client, *os.Process) { + proc := runCmd("redis-server", "--port", port, "--slaveof", "127.0.0.1", masterPort) + return connect(port), proc + } + + var startSentinel = func() *os.Process { + dir, err := ioutil.TempDir("", "sentinel") + Expect(err).NotTo(HaveOccurred()) + + fname := filepath.Join(dir, "sentinel.conf") + err = ioutil.WriteFile(fname, []byte(sentinelConf), 0664) + Expect(err).NotTo(HaveOccurred()) + + proc := runCmd("redis-server", fname, "--sentinel") + client := connect(sentinelPort) + client.Close() + return proc + } + + It("should facilitate failover", func() { + master, mproc := startMaster() + defer mproc.Kill() + slave1, sproc1 := startSlave("8125") + defer sproc1.Kill() + slave2, sproc2 := startSlave("8126") + defer sproc2.Kill() + sntproc := startSentinel() + defer sntproc.Kill() + + client := redis.NewFailoverClient(&redis.FailoverOptions{ + MasterName: masterName, + SentinelAddrs: []string{":" + sentinelPort}, + }) + defer client.Close() + + // Set value on master, verify + err := client.Set("foo", "master").Err() + Expect(err).NotTo(HaveOccurred()) + + val, err := master.Get("foo").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal("master")) + + // Wait until replicated + Eventually(func() string { + return slave1.Get("foo").Val() + }, "1s", "100ms").Should(Equal("master")) + Eventually(func() string { + return slave2.Get("foo").Val() + }, "1s", "100ms").Should(Equal("master")) + + // Kill master. + master.Shutdown() + Eventually(func() error { + return master.Ping().Err() + }, "5s", "100ms").Should(HaveOccurred()) + + // Wait for Redis sentinel to elect new master. + Eventually(func() string { + return slave1.Info().Val() + slave2.Info().Val() + }, "30s", "500ms").Should(ContainSubstring("role:master")) + + // Check that client picked up new master. + val, err = client.Get("foo").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal("master")) + }) + +}) From e16db84e4a8ceb914b3ce2d22db11727f46ab085 Mon Sep 17 00:00:00 2001 From: Dimitrij Denissenko Date: Thu, 15 Jan 2015 17:23:22 +0000 Subject: [PATCH 02/11] Better redis process abstraction --- redis_test.go | 74 ++++++++++++++++++++++++++++++++++++++++++ sentinel_test.go | 83 ++++++++++-------------------------------------- 2 files changed, 90 insertions(+), 67 deletions(-) diff --git a/redis_test.go b/redis_test.go index 8649241b..a1a0de15 100644 --- a/redis_test.go +++ b/redis_test.go @@ -2,6 +2,8 @@ package redis_test import ( "net" + "os" + "os/exec" "sort" "testing" "time" @@ -128,6 +130,78 @@ func sortStrings(slice []string) []string { return slice } +func execCmd(name string, args ...string) (*os.Process, error) { + cmd := exec.Command(name, args...) + if false { + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + } + return cmd.Process, cmd.Start() +} + +func connectTo(port string) (client *redis.Client, err error) { + client = redis.NewTCPClient(&redis.Options{ + Addr: ":" + port, + }) + + deadline := time.Now().Add(time.Second) + for time.Now().Before(deadline) { + if err = client.Ping().Err(); err == nil { + break + } + time.Sleep(100 * time.Millisecond) + } + return +} + +type redisProcess struct { + *os.Process + *redis.Client +} + +func (p *redisProcess) Close() error { + p.Client.Close() + return p.Kill() +} + +func startRedis(port string, args ...string) (*redisProcess, error) { + process, err := execCmd("redis-server", append([]string{"--port", port}, args...)...) + if err != nil { + return nil, err + } + client, err := connectTo(port) + if err != nil { + process.Kill() + return nil, err + } + return &redisProcess{process, client}, err +} + +func startSentinel(port, masterName, masterPort string) (*redisProcess, error) { + process, err := execCmd("redis-server", os.DevNull, "--sentinel", "--port", port) + if err != nil { + return nil, err + } + client, err := connectTo(port) + if err != nil { + process.Kill() + return nil, err + } + for _, cmd := range []*redis.StatusCmd{ + redis.NewStatusCmd("SENTINEL", "MONITOR", masterName, "127.0.0.1", masterPort, "1"), + redis.NewStatusCmd("SENTINEL", "SET", masterName, "down-after-milliseconds", "500"), + redis.NewStatusCmd("SENTINEL", "SET", masterName, "failover-timeout", "1000"), + redis.NewStatusCmd("SENTINEL", "SET", masterName, "parallel-syncs", "1"), + } { + client.Process(cmd) + if err := cmd.Err(); err != nil { + process.Kill() + return nil, err + } + } + return &redisProcess{process, client}, err +} + //------------------------------------------------------------------------------ func BenchmarkRedisPing(b *testing.B) { diff --git a/sentinel_test.go b/sentinel_test.go index abbba925..5404eec0 100644 --- a/sentinel_test.go +++ b/sentinel_test.go @@ -1,11 +1,6 @@ package redis_test import ( - "io/ioutil" - "os" - "os/exec" - "path/filepath" - . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "gopkg.in/redis.v2" @@ -16,69 +11,23 @@ var _ = Describe("Sentinel", func() { const masterName = "mymaster" const masterPort = "8123" const sentinelPort = "8124" - const sentinelConf = ` -port ` + sentinelPort + ` - -sentinel monitor ` + masterName + ` 127.0.0.1 ` + masterPort + ` 1 -sentinel down-after-milliseconds ` + masterName + ` 400 -sentinel failover-timeout ` + masterName + ` 800 -sentinel parallel-syncs ` + masterName + ` 1 -` - - var runCmd = func(name string, args ...string) *os.Process { - cmd := exec.Command(name, args...) - if false { - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - } - err := cmd.Start() - Expect(err).NotTo(HaveOccurred()) - return cmd.Process - } - - var connect = func(port string) *redis.Client { - client := redis.NewTCPClient(&redis.Options{ - Addr: ":" + port, - }) - Eventually(func() error { - return client.Ping().Err() - }, "1s", "100ms").ShouldNot(HaveOccurred()) - return client - } - - var startMaster = func() (*redis.Client, *os.Process) { - proc := runCmd("redis-server", "--port", masterPort) - return connect(masterPort), proc - } - - var startSlave = func(port string) (*redis.Client, *os.Process) { - proc := runCmd("redis-server", "--port", port, "--slaveof", "127.0.0.1", masterPort) - return connect(port), proc - } - - var startSentinel = func() *os.Process { - dir, err := ioutil.TempDir("", "sentinel") - Expect(err).NotTo(HaveOccurred()) - - fname := filepath.Join(dir, "sentinel.conf") - err = ioutil.WriteFile(fname, []byte(sentinelConf), 0664) - Expect(err).NotTo(HaveOccurred()) - - proc := runCmd("redis-server", fname, "--sentinel") - client := connect(sentinelPort) - client.Close() - return proc - } It("should facilitate failover", func() { - master, mproc := startMaster() - defer mproc.Kill() - slave1, sproc1 := startSlave("8125") - defer sproc1.Kill() - slave2, sproc2 := startSlave("8126") - defer sproc2.Kill() - sntproc := startSentinel() - defer sntproc.Kill() + master, err := startRedis(masterPort) + Expect(err).NotTo(HaveOccurred()) + defer master.Close() + + sentinel, err := startSentinel(sentinelPort, masterName, masterPort) + Expect(err).NotTo(HaveOccurred()) + defer sentinel.Close() + + slave1, err := startRedis("8125", "--slaveof", "127.0.0.1", masterPort) + Expect(err).NotTo(HaveOccurred()) + defer slave1.Close() + + slave2, err := startRedis("8126", "--slaveof", "127.0.0.1", masterPort) + Expect(err).NotTo(HaveOccurred()) + defer slave2.Close() client := redis.NewFailoverClient(&redis.FailoverOptions{ MasterName: masterName, @@ -87,7 +36,7 @@ sentinel parallel-syncs ` + masterName + ` 1 defer client.Close() // Set value on master, verify - err := client.Set("foo", "master").Err() + err = client.Set("foo", "master").Err() Expect(err).NotTo(HaveOccurred()) val, err := master.Get("foo").Result() From 8cef6c00f2b50db6ab140f321e2fc7f3036f58ae Mon Sep 17 00:00:00 2001 From: Dimitrij Denissenko Date: Sat, 17 Jan 2015 12:39:09 +0000 Subject: [PATCH 03/11] Fix travis install, added go1.4 to list of versions --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 00f40c6f..800e2bbc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,12 +7,13 @@ go: - 1.1 - 1.2 - 1.3 + - 1.4 - tip install: - go get gopkg.in/bufio.v1 - - go get onsi.github.io/ginkgo - - go get onsi.github.io/gomega + - go get github.com/onsi/ginkgo + - go get github.com/onsi/gomega - mkdir -p $HOME/gopath/src/gopkg.in - ln -s `pwd` $HOME/gopath/src/gopkg.in/redis.v2 From 1a56e736aa4acfd791a32fa9918bb4d28c02b473 Mon Sep 17 00:00:00 2001 From: Dimitrij Denissenko Date: Sun, 25 Jan 2015 12:33:30 +0000 Subject: [PATCH 04/11] Fixing travis build --- .travis.yml | 4 ++-- example_test.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 800e2bbc..e1f63234 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,6 @@ services: - redis-server go: - - 1.1 - 1.2 - 1.3 - 1.4 @@ -15,7 +14,8 @@ install: - go get github.com/onsi/ginkgo - go get github.com/onsi/gomega - mkdir -p $HOME/gopath/src/gopkg.in - - ln -s `pwd` $HOME/gopath/src/gopkg.in/redis.v2 + - mv $HOME/gopath/src/github.com/go-redis/redis $HOME/gopath/src/gopkg.in/redis.v2 + - cd $HOME/gopath/src/gopkg.in/redis.v2 before_script: - redis-server testdata/sentinel.conf --sentinel & diff --git a/example_test.go b/example_test.go index 8e9e5122..dbc95131 100644 --- a/example_test.go +++ b/example_test.go @@ -30,7 +30,7 @@ func ExampleNewTCPClient() { func ExampleNewFailoverClient() { client := redis.NewFailoverClient(&redis.FailoverOptions{ - MasterName: "mymaster", + MasterName: "master", SentinelAddrs: []string{":26379"}, }) From d7afd989b9c7a5f76882cb9fa2d035f255220e48 Mon Sep 17 00:00:00 2001 From: Dimitrij Denissenko Date: Sun, 25 Jan 2015 19:24:27 +0000 Subject: [PATCH 05/11] Migrate rate limiter test --- rate_limit_test.go | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/rate_limit_test.go b/rate_limit_test.go index 2f0d41a2..3febbaeb 100644 --- a/rate_limit_test.go +++ b/rate_limit_test.go @@ -1,31 +1,25 @@ package redis import ( - "sync" "testing" "time" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" ) -func TestRateLimiter(t *testing.T) { +var _ = Describe("RateLimiter", func() { var n = 100000 if testing.Short() { n = 1000 } - rl := newRateLimiter(time.Minute, n) - wg := &sync.WaitGroup{} - for i := 0; i < n; i++ { - wg.Add(1) - go func() { - if !rl.Check() { - panic("check failed") - } - wg.Done() - }() - } - wg.Wait() + It("should rate limit", func() { + rl := newRateLimiter(time.Minute, n) + for i := 0; i <= n; i++ { + Expect(rl.Check()).To(BeTrue()) + } + Expect(rl.Check()).To(BeFalse()) + }) - if rl.Check() && rl.Check() { - t.Fatal("check passed") - } -} +}) From 140a4d4f96cebda71aae74fd2ed6ce4e59037d3d Mon Sep 17 00:00:00 2001 From: Vladimir Mihailenco Date: Fri, 30 Jan 2015 15:32:07 +0200 Subject: [PATCH 06/11] Try to fix travis. --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d4290887..62a51b4c 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,4 @@ all: - go test ./... -cpu=1,2,4 + go test ./... + go test ./... -cpu=2 go test ./... -short -race From 22e4776c1e83bb578a5d92cf60a0ab71c280c92e Mon Sep 17 00:00:00 2001 From: Vladimir Mihailenco Date: Fri, 30 Jan 2015 15:35:40 +0200 Subject: [PATCH 07/11] travis: don't start sentinel. --- .travis.yml | 3 --- testdata/sentinel.conf | 6 ------ 2 files changed, 9 deletions(-) delete mode 100644 testdata/sentinel.conf diff --git a/.travis.yml b/.travis.yml index e1f63234..659ca58a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,6 +16,3 @@ install: - mkdir -p $HOME/gopath/src/gopkg.in - mv $HOME/gopath/src/github.com/go-redis/redis $HOME/gopath/src/gopkg.in/redis.v2 - cd $HOME/gopath/src/gopkg.in/redis.v2 - -before_script: - - redis-server testdata/sentinel.conf --sentinel & diff --git a/testdata/sentinel.conf b/testdata/sentinel.conf deleted file mode 100644 index 3da90b38..00000000 --- a/testdata/sentinel.conf +++ /dev/null @@ -1,6 +0,0 @@ -port 26379 - -sentinel monitor master 127.0.0.1 6379 1 -sentinel down-after-milliseconds master 2000 -sentinel failover-timeout master 5000 -sentinel parallel-syncs master 4 From 95cd890e40c501a2681af3801fe8d9b80c23eb11 Mon Sep 17 00:00:00 2001 From: Vladimir Mihailenco Date: Fri, 30 Jan 2015 15:41:57 +0200 Subject: [PATCH 08/11] Fix example. --- example_test.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/example_test.go b/example_test.go index dbc95131..ddcc1bf5 100644 --- a/example_test.go +++ b/example_test.go @@ -29,14 +29,10 @@ func ExampleNewTCPClient() { } func ExampleNewFailoverClient() { - client := redis.NewFailoverClient(&redis.FailoverOptions{ + redis.NewFailoverClient(&redis.FailoverOptions{ MasterName: "master", SentinelAddrs: []string{":26379"}, }) - - pong, err := client.Ping().Result() - fmt.Println(pong, err) - // Output: PONG } func ExampleClient() { From 15a90c831b6d765942b43000950955aabd8cb25b Mon Sep 17 00:00:00 2001 From: Vladimir Mihailenco Date: Fri, 30 Jan 2015 15:46:17 +0200 Subject: [PATCH 09/11] Redirect cmds output to stdout. --- redis_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/redis_test.go b/redis_test.go index a1a0de15..6053af63 100644 --- a/redis_test.go +++ b/redis_test.go @@ -132,7 +132,7 @@ func sortStrings(slice []string) []string { func execCmd(name string, args ...string) (*os.Process, error) { cmd := exec.Command(name, args...) - if false { + if true { cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr } From 7f87de6109bc610169db1a46ef7f89fa15d2d877 Mon Sep 17 00:00:00 2001 From: Vladimir Mihailenco Date: Fri, 30 Jan 2015 16:45:57 +0200 Subject: [PATCH 10/11] Make sentinel tests more reliable. --- redis.go | 9 ++++++++- redis_test.go | 9 +++++---- sentinel_test.go | 13 +++++++++---- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/redis.go b/redis.go index 0d15dc8f..285fb99e 100644 --- a/redis.go +++ b/redis.go @@ -170,6 +170,13 @@ type Options struct { IdleTimeout time.Duration } +func (opt *Options) getNetwork() string { + if opt.Network == "" { + return "tcp" + } + return opt.Network +} + func (opt *Options) getPoolSize() int { if opt.PoolSize == 0 { return 10 @@ -207,7 +214,7 @@ func NewClient(clOpt *Options) *Client { dialer := clOpt.Dialer if dialer == nil { dialer = func() (net.Conn, error) { - return net.DialTimeout(clOpt.Network, clOpt.Addr, opt.DialTimeout) + return net.DialTimeout(clOpt.getNetwork(), clOpt.Addr, opt.DialTimeout) } } return &Client{ diff --git a/redis_test.go b/redis_test.go index 6053af63..fde06f71 100644 --- a/redis_test.go +++ b/redis_test.go @@ -140,18 +140,19 @@ func execCmd(name string, args ...string) (*os.Process, error) { } func connectTo(port string) (client *redis.Client, err error) { - client = redis.NewTCPClient(&redis.Options{ + client = redis.NewClient(&redis.Options{ Addr: ":" + port, }) deadline := time.Now().Add(time.Second) for time.Now().Before(deadline) { if err = client.Ping().Err(); err == nil { - break + return client, nil } time.Sleep(100 * time.Millisecond) } - return + + return nil, err } type redisProcess struct { @@ -199,7 +200,7 @@ func startSentinel(port, masterName, masterPort string) (*redisProcess, error) { return nil, err } } - return &redisProcess{process, client}, err + return &redisProcess{process, client}, nil } //------------------------------------------------------------------------------ diff --git a/sentinel_test.go b/sentinel_test.go index 5404eec0..8e6bf865 100644 --- a/sentinel_test.go +++ b/sentinel_test.go @@ -51,6 +51,11 @@ var _ = Describe("Sentinel", func() { return slave2.Get("foo").Val() }, "1s", "100ms").Should(Equal("master")) + // Wait until slaves are picked up by sentinel. + Eventually(func() string { + return sentinel.Info().Val() + }, "10s", "100ms").Should(ContainSubstring("slaves=2")) + // Kill master. master.Shutdown() Eventually(func() error { @@ -60,12 +65,12 @@ var _ = Describe("Sentinel", func() { // Wait for Redis sentinel to elect new master. Eventually(func() string { return slave1.Info().Val() + slave2.Info().Val() - }, "30s", "500ms").Should(ContainSubstring("role:master")) + }, "30s", "1s").Should(ContainSubstring("role:master")) // Check that client picked up new master. - val, err = client.Get("foo").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal("master")) + Eventually(func() error { + return client.Get("foo").Err() + }, "5s", "100ms").ShouldNot(HaveOccurred()) }) }) From 377d92ae1aa096aa8678d0f4efc6932d8a1e0049 Mon Sep 17 00:00:00 2001 From: Vladimir Mihailenco Date: Fri, 30 Jan 2015 16:58:26 +0200 Subject: [PATCH 11/11] Relax test condition. --- pool_test.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pool_test.go b/pool_test.go index d2569f15..9797ce55 100644 --- a/pool_test.go +++ b/pool_test.go @@ -39,8 +39,10 @@ var _ = Describe("Pool", func() { Expect(err).NotTo(HaveOccurred()) Expect(val).To(Equal("PONG")) }) - Expect(client.Pool().Size()).To(Equal(10)) - Expect(client.Pool().Len()).To(Equal(10)) + pool := client.Pool() + Expect(pool.Size()).To(BeNumerically("<=", 10)) + Expect(pool.Len()).To(BeNumerically("<=", 10)) + Expect(pool.Size()).To(Equal(pool.Len())) }) It("should respect max on multi", func() {