race_test.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. package redis_test
  2. import (
  3. "bytes"
  4. "fmt"
  5. "net"
  6. "strconv"
  7. "testing"
  8. "time"
  9. . "github.com/onsi/ginkgo"
  10. . "github.com/onsi/gomega"
  11. "gopkg.in/redis.v5"
  12. )
  13. var _ = Describe("races", func() {
  14. var client *redis.Client
  15. var C, N int
  16. BeforeEach(func() {
  17. client = redis.NewClient(redisOptions())
  18. Expect(client.FlushDb().Err()).To(BeNil())
  19. C, N = 10, 1000
  20. if testing.Short() {
  21. C = 4
  22. N = 100
  23. }
  24. })
  25. AfterEach(func() {
  26. err := client.Close()
  27. Expect(err).NotTo(HaveOccurred())
  28. })
  29. It("should echo", func() {
  30. perform(C, func(id int) {
  31. for i := 0; i < N; i++ {
  32. msg := fmt.Sprintf("echo %d %d", id, i)
  33. echo, err := client.Echo(msg).Result()
  34. Expect(err).NotTo(HaveOccurred())
  35. Expect(echo).To(Equal(msg))
  36. }
  37. })
  38. })
  39. It("should incr", func() {
  40. key := "TestIncrFromGoroutines"
  41. perform(C, func(id int) {
  42. for i := 0; i < N; i++ {
  43. err := client.Incr(key).Err()
  44. Expect(err).NotTo(HaveOccurred())
  45. }
  46. })
  47. val, err := client.Get(key).Int64()
  48. Expect(err).NotTo(HaveOccurred())
  49. Expect(val).To(Equal(int64(C * N)))
  50. })
  51. It("should handle many keys", func() {
  52. perform(C, func(id int) {
  53. for i := 0; i < N; i++ {
  54. err := client.Set(
  55. fmt.Sprintf("keys.key-%d-%d", id, i),
  56. fmt.Sprintf("hello-%d-%d", id, i),
  57. 0,
  58. ).Err()
  59. Expect(err).NotTo(HaveOccurred())
  60. }
  61. })
  62. keys := client.Keys("keys.*")
  63. Expect(keys.Err()).NotTo(HaveOccurred())
  64. Expect(len(keys.Val())).To(Equal(C * N))
  65. })
  66. It("should handle many keys 2", func() {
  67. perform(C, func(id int) {
  68. keys := []string{"non-existent-key"}
  69. for i := 0; i < N; i++ {
  70. key := fmt.Sprintf("keys.key-%d", i)
  71. keys = append(keys, key)
  72. err := client.Set(key, fmt.Sprintf("hello-%d", i), 0).Err()
  73. Expect(err).NotTo(HaveOccurred())
  74. }
  75. keys = append(keys, "non-existent-key")
  76. vals, err := client.MGet(keys...).Result()
  77. Expect(err).NotTo(HaveOccurred())
  78. Expect(len(vals)).To(Equal(N + 2))
  79. for i := 0; i < N; i++ {
  80. Expect(vals[i+1]).To(Equal(fmt.Sprintf("hello-%d", i)))
  81. }
  82. Expect(vals[0]).To(BeNil())
  83. Expect(vals[N+1]).To(BeNil())
  84. })
  85. })
  86. It("should handle big vals in Get", func() {
  87. C, N = 4, 100
  88. bigVal := bytes.Repeat([]byte{'*'}, 1<<17) // 128kb
  89. err := client.Set("key", bigVal, 0).Err()
  90. Expect(err).NotTo(HaveOccurred())
  91. // Reconnect to get new connection.
  92. Expect(client.Close()).To(BeNil())
  93. client = redis.NewClient(redisOptions())
  94. perform(C, func(id int) {
  95. for i := 0; i < N; i++ {
  96. got, err := client.Get("key").Bytes()
  97. Expect(err).NotTo(HaveOccurred())
  98. Expect(got).To(Equal(bigVal))
  99. }
  100. })
  101. })
  102. It("should handle big vals in Set", func() {
  103. C, N = 4, 100
  104. bigVal := bytes.Repeat([]byte{'*'}, 1<<17) // 128kb
  105. perform(C, func(id int) {
  106. for i := 0; i < N; i++ {
  107. err := client.Set("key", bigVal, 0).Err()
  108. Expect(err).NotTo(HaveOccurred())
  109. }
  110. })
  111. })
  112. It("should PubSub", func() {
  113. connPool := client.Pool()
  114. perform(C, func(id int) {
  115. for i := 0; i < N; i++ {
  116. pubsub, err := client.Subscribe(fmt.Sprintf("mychannel%d", id))
  117. Expect(err).NotTo(HaveOccurred())
  118. go func() {
  119. defer GinkgoRecover()
  120. time.Sleep(time.Millisecond)
  121. err := pubsub.Close()
  122. Expect(err).NotTo(HaveOccurred())
  123. }()
  124. _, err = pubsub.ReceiveMessage()
  125. Expect(err.Error()).To(ContainSubstring("closed"))
  126. val := "echo" + strconv.Itoa(i)
  127. echo, err := client.Echo(val).Result()
  128. Expect(err).NotTo(HaveOccurred())
  129. Expect(echo).To(Equal(val))
  130. }
  131. })
  132. Expect(connPool.Len()).To(Equal(connPool.FreeLen()))
  133. Expect(connPool.Len()).To(BeNumerically("<=", 10))
  134. })
  135. It("should select db", func() {
  136. err := client.Set("db", 1, 0).Err()
  137. Expect(err).NotTo(HaveOccurred())
  138. perform(C, func(id int) {
  139. opt := redisOptions()
  140. opt.DB = id
  141. client := redis.NewClient(opt)
  142. for i := 0; i < N; i++ {
  143. err := client.Set("db", id, 0).Err()
  144. Expect(err).NotTo(HaveOccurred())
  145. n, err := client.Get("db").Int64()
  146. Expect(err).NotTo(HaveOccurred())
  147. Expect(n).To(Equal(int64(id)))
  148. }
  149. err := client.Close()
  150. Expect(err).NotTo(HaveOccurred())
  151. })
  152. n, err := client.Get("db").Int64()
  153. Expect(err).NotTo(HaveOccurred())
  154. Expect(n).To(Equal(int64(1)))
  155. })
  156. It("should select DB with read timeout", func() {
  157. perform(C, func(id int) {
  158. opt := redisOptions()
  159. opt.DB = id
  160. opt.ReadTimeout = time.Nanosecond
  161. client := redis.NewClient(opt)
  162. perform(C, func(id int) {
  163. err := client.Ping().Err()
  164. Expect(err).To(HaveOccurred())
  165. Expect(err.(net.Error).Timeout()).To(BeTrue())
  166. })
  167. err := client.Close()
  168. Expect(err).NotTo(HaveOccurred())
  169. })
  170. })
  171. It("should Watch/Unwatch", func() {
  172. err := client.Set("key", "0", 0).Err()
  173. Expect(err).NotTo(HaveOccurred())
  174. perform(C, func(id int) {
  175. for i := 0; i < N; i++ {
  176. err := client.Watch(func(tx *redis.Tx) error {
  177. val, err := tx.Get("key").Result()
  178. Expect(err).NotTo(HaveOccurred())
  179. Expect(val).NotTo(Equal(redis.Nil))
  180. num, err := strconv.ParseInt(val, 10, 64)
  181. Expect(err).NotTo(HaveOccurred())
  182. cmds, err := tx.Pipelined(func(pipe *redis.Pipeline) error {
  183. pipe.Set("key", strconv.FormatInt(num+1, 10), 0)
  184. return nil
  185. })
  186. Expect(cmds).To(HaveLen(1))
  187. return err
  188. }, "key")
  189. if err == redis.TxFailedErr {
  190. i--
  191. continue
  192. }
  193. Expect(err).NotTo(HaveOccurred())
  194. }
  195. })
  196. val, err := client.Get("key").Int64()
  197. Expect(err).NotTo(HaveOccurred())
  198. Expect(val).To(Equal(int64(C * N)))
  199. })
  200. It("should Pipeline", func() {
  201. perform(C, func(id int) {
  202. pipe := client.Pipeline()
  203. for i := 0; i < N; i++ {
  204. pipe.Echo(fmt.Sprint(i))
  205. }
  206. cmds, err := pipe.Exec()
  207. Expect(err).NotTo(HaveOccurred())
  208. Expect(cmds).To(HaveLen(N))
  209. for i := 0; i < N; i++ {
  210. Expect(cmds[i].(*redis.StringCmd).Val()).To(Equal(fmt.Sprint(i)))
  211. }
  212. })
  213. })
  214. It("should Pipeline", func() {
  215. pipe := client.Pipeline()
  216. perform(N, func(id int) {
  217. pipe.Incr("key")
  218. })
  219. cmds, err := pipe.Exec()
  220. Expect(err).NotTo(HaveOccurred())
  221. Expect(cmds).To(HaveLen(N))
  222. n, err := client.Get("key").Int64()
  223. Expect(err).NotTo(HaveOccurred())
  224. Expect(n).To(Equal(int64(N)))
  225. })
  226. })