123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277 |
- package redis_test
- import (
- "bytes"
- "fmt"
- "net"
- "strconv"
- "testing"
- "time"
- . "github.com/onsi/ginkgo"
- . "github.com/onsi/gomega"
- "gopkg.in/redis.v5"
- )
- var _ = Describe("races", func() {
- var client *redis.Client
- var C, N int
- BeforeEach(func() {
- client = redis.NewClient(redisOptions())
- Expect(client.FlushDb().Err()).To(BeNil())
- C, N = 10, 1000
- if testing.Short() {
- C = 4
- N = 100
- }
- })
- AfterEach(func() {
- err := client.Close()
- Expect(err).NotTo(HaveOccurred())
- })
- It("should echo", func() {
- perform(C, func(id int) {
- for i := 0; i < N; i++ {
- msg := fmt.Sprintf("echo %d %d", id, i)
- echo, err := client.Echo(msg).Result()
- Expect(err).NotTo(HaveOccurred())
- Expect(echo).To(Equal(msg))
- }
- })
- })
- It("should incr", func() {
- key := "TestIncrFromGoroutines"
- perform(C, func(id int) {
- for i := 0; i < N; i++ {
- err := client.Incr(key).Err()
- Expect(err).NotTo(HaveOccurred())
- }
- })
- val, err := client.Get(key).Int64()
- Expect(err).NotTo(HaveOccurred())
- Expect(val).To(Equal(int64(C * N)))
- })
- It("should handle many keys", func() {
- perform(C, func(id int) {
- for i := 0; i < N; i++ {
- err := client.Set(
- fmt.Sprintf("keys.key-%d-%d", id, i),
- fmt.Sprintf("hello-%d-%d", id, i),
- 0,
- ).Err()
- Expect(err).NotTo(HaveOccurred())
- }
- })
- keys := client.Keys("keys.*")
- Expect(keys.Err()).NotTo(HaveOccurred())
- Expect(len(keys.Val())).To(Equal(C * N))
- })
- It("should handle many keys 2", func() {
- perform(C, func(id int) {
- keys := []string{"non-existent-key"}
- for i := 0; i < N; i++ {
- key := fmt.Sprintf("keys.key-%d", i)
- keys = append(keys, key)
- err := client.Set(key, fmt.Sprintf("hello-%d", i), 0).Err()
- Expect(err).NotTo(HaveOccurred())
- }
- keys = append(keys, "non-existent-key")
- vals, err := client.MGet(keys...).Result()
- Expect(err).NotTo(HaveOccurred())
- Expect(len(vals)).To(Equal(N + 2))
- for i := 0; i < N; i++ {
- Expect(vals[i+1]).To(Equal(fmt.Sprintf("hello-%d", i)))
- }
- Expect(vals[0]).To(BeNil())
- Expect(vals[N+1]).To(BeNil())
- })
- })
- It("should handle big vals in Get", func() {
- C, N = 4, 100
- bigVal := bytes.Repeat([]byte{'*'}, 1<<17) // 128kb
- err := client.Set("key", bigVal, 0).Err()
- Expect(err).NotTo(HaveOccurred())
- // Reconnect to get new connection.
- Expect(client.Close()).To(BeNil())
- client = redis.NewClient(redisOptions())
- perform(C, func(id int) {
- for i := 0; i < N; i++ {
- got, err := client.Get("key").Bytes()
- Expect(err).NotTo(HaveOccurred())
- Expect(got).To(Equal(bigVal))
- }
- })
- })
- It("should handle big vals in Set", func() {
- C, N = 4, 100
- bigVal := bytes.Repeat([]byte{'*'}, 1<<17) // 128kb
- perform(C, func(id int) {
- for i := 0; i < N; i++ {
- err := client.Set("key", bigVal, 0).Err()
- Expect(err).NotTo(HaveOccurred())
- }
- })
- })
- It("should PubSub", func() {
- connPool := client.Pool()
- perform(C, func(id int) {
- for i := 0; i < N; i++ {
- pubsub, err := client.Subscribe(fmt.Sprintf("mychannel%d", id))
- Expect(err).NotTo(HaveOccurred())
- go func() {
- defer GinkgoRecover()
- time.Sleep(time.Millisecond)
- err := pubsub.Close()
- Expect(err).NotTo(HaveOccurred())
- }()
- _, err = pubsub.ReceiveMessage()
- Expect(err.Error()).To(ContainSubstring("closed"))
- val := "echo" + strconv.Itoa(i)
- echo, err := client.Echo(val).Result()
- Expect(err).NotTo(HaveOccurred())
- Expect(echo).To(Equal(val))
- }
- })
- Expect(connPool.Len()).To(Equal(connPool.FreeLen()))
- Expect(connPool.Len()).To(BeNumerically("<=", 10))
- })
- It("should select db", func() {
- err := client.Set("db", 1, 0).Err()
- Expect(err).NotTo(HaveOccurred())
- perform(C, func(id int) {
- opt := redisOptions()
- opt.DB = id
- client := redis.NewClient(opt)
- for i := 0; i < N; i++ {
- err := client.Set("db", id, 0).Err()
- Expect(err).NotTo(HaveOccurred())
- n, err := client.Get("db").Int64()
- Expect(err).NotTo(HaveOccurred())
- Expect(n).To(Equal(int64(id)))
- }
- err := client.Close()
- Expect(err).NotTo(HaveOccurred())
- })
- n, err := client.Get("db").Int64()
- Expect(err).NotTo(HaveOccurred())
- Expect(n).To(Equal(int64(1)))
- })
- It("should select DB with read timeout", func() {
- perform(C, func(id int) {
- opt := redisOptions()
- opt.DB = id
- opt.ReadTimeout = time.Nanosecond
- client := redis.NewClient(opt)
- perform(C, func(id int) {
- err := client.Ping().Err()
- Expect(err).To(HaveOccurred())
- Expect(err.(net.Error).Timeout()).To(BeTrue())
- })
- err := client.Close()
- Expect(err).NotTo(HaveOccurred())
- })
- })
- It("should Watch/Unwatch", func() {
- err := client.Set("key", "0", 0).Err()
- Expect(err).NotTo(HaveOccurred())
- perform(C, func(id int) {
- for i := 0; i < N; i++ {
- err := client.Watch(func(tx *redis.Tx) error {
- val, err := tx.Get("key").Result()
- Expect(err).NotTo(HaveOccurred())
- Expect(val).NotTo(Equal(redis.Nil))
- num, err := strconv.ParseInt(val, 10, 64)
- Expect(err).NotTo(HaveOccurred())
- cmds, err := tx.Pipelined(func(pipe *redis.Pipeline) error {
- pipe.Set("key", strconv.FormatInt(num+1, 10), 0)
- return nil
- })
- Expect(cmds).To(HaveLen(1))
- return err
- }, "key")
- if err == redis.TxFailedErr {
- i--
- continue
- }
- Expect(err).NotTo(HaveOccurred())
- }
- })
- val, err := client.Get("key").Int64()
- Expect(err).NotTo(HaveOccurred())
- Expect(val).To(Equal(int64(C * N)))
- })
- It("should Pipeline", func() {
- perform(C, func(id int) {
- pipe := client.Pipeline()
- for i := 0; i < N; i++ {
- pipe.Echo(fmt.Sprint(i))
- }
- cmds, err := pipe.Exec()
- Expect(err).NotTo(HaveOccurred())
- Expect(cmds).To(HaveLen(N))
- for i := 0; i < N; i++ {
- Expect(cmds[i].(*redis.StringCmd).Val()).To(Equal(fmt.Sprint(i)))
- }
- })
- })
- It("should Pipeline", func() {
- pipe := client.Pipeline()
- perform(N, func(id int) {
- pipe.Incr("key")
- })
- cmds, err := pipe.Exec()
- Expect(err).NotTo(HaveOccurred())
- Expect(cmds).To(HaveLen(N))
- n, err := client.Get("key").Int64()
- Expect(err).NotTo(HaveOccurred())
- Expect(n).To(Equal(int64(N)))
- })
- })
|