...

Source file src/github.com/go-redis/redis/race_test.go

Documentation: github.com/go-redis/redis

     1  package redis_test
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"net"
     7  	"strconv"
     8  	"sync/atomic"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/go-redis/redis"
    13  
    14  	. "github.com/onsi/ginkgo"
    15  	. "github.com/onsi/gomega"
    16  )
    17  
    18  var _ = Describe("races", func() {
    19  	var client *redis.Client
    20  	var C, N int
    21  
    22  	BeforeEach(func() {
    23  		client = redis.NewClient(redisOptions())
    24  		Expect(client.FlushDB().Err()).To(BeNil())
    25  
    26  		C, N = 10, 1000
    27  		if testing.Short() {
    28  			C = 4
    29  			N = 100
    30  		}
    31  	})
    32  
    33  	AfterEach(func() {
    34  		err := client.Close()
    35  		Expect(err).NotTo(HaveOccurred())
    36  	})
    37  
    38  	It("should echo", func() {
    39  		perform(C, func(id int) {
    40  			for i := 0; i < N; i++ {
    41  				msg := fmt.Sprintf("echo %d %d", id, i)
    42  				echo, err := client.Echo(msg).Result()
    43  				Expect(err).NotTo(HaveOccurred())
    44  				Expect(echo).To(Equal(msg))
    45  			}
    46  		})
    47  	})
    48  
    49  	It("should incr", func() {
    50  		key := "TestIncrFromGoroutines"
    51  
    52  		perform(C, func(id int) {
    53  			for i := 0; i < N; i++ {
    54  				err := client.Incr(key).Err()
    55  				Expect(err).NotTo(HaveOccurred())
    56  			}
    57  		})
    58  
    59  		val, err := client.Get(key).Int64()
    60  		Expect(err).NotTo(HaveOccurred())
    61  		Expect(val).To(Equal(int64(C * N)))
    62  	})
    63  
    64  	It("should handle many keys", func() {
    65  		perform(C, func(id int) {
    66  			for i := 0; i < N; i++ {
    67  				err := client.Set(
    68  					fmt.Sprintf("keys.key-%d-%d", id, i),
    69  					fmt.Sprintf("hello-%d-%d", id, i),
    70  					0,
    71  				).Err()
    72  				Expect(err).NotTo(HaveOccurred())
    73  			}
    74  		})
    75  
    76  		keys := client.Keys("keys.*")
    77  		Expect(keys.Err()).NotTo(HaveOccurred())
    78  		Expect(len(keys.Val())).To(Equal(C * N))
    79  	})
    80  
    81  	It("should handle many keys 2", func() {
    82  		perform(C, func(id int) {
    83  			keys := []string{"non-existent-key"}
    84  			for i := 0; i < N; i++ {
    85  				key := fmt.Sprintf("keys.key-%d", i)
    86  				keys = append(keys, key)
    87  
    88  				err := client.Set(key, fmt.Sprintf("hello-%d", i), 0).Err()
    89  				Expect(err).NotTo(HaveOccurred())
    90  			}
    91  			keys = append(keys, "non-existent-key")
    92  
    93  			vals, err := client.MGet(keys...).Result()
    94  			Expect(err).NotTo(HaveOccurred())
    95  			Expect(len(vals)).To(Equal(N + 2))
    96  
    97  			for i := 0; i < N; i++ {
    98  				Expect(vals[i+1]).To(Equal(fmt.Sprintf("hello-%d", i)))
    99  			}
   100  
   101  			Expect(vals[0]).To(BeNil())
   102  			Expect(vals[N+1]).To(BeNil())
   103  		})
   104  	})
   105  
   106  	It("should handle big vals in Get", func() {
   107  		C, N = 4, 100
   108  
   109  		bigVal := bigVal()
   110  
   111  		err := client.Set("key", bigVal, 0).Err()
   112  		Expect(err).NotTo(HaveOccurred())
   113  
   114  		// Reconnect to get new connection.
   115  		Expect(client.Close()).To(BeNil())
   116  		client = redis.NewClient(redisOptions())
   117  
   118  		perform(C, func(id int) {
   119  			for i := 0; i < N; i++ {
   120  				got, err := client.Get("key").Bytes()
   121  				Expect(err).NotTo(HaveOccurred())
   122  				Expect(got).To(Equal(bigVal))
   123  			}
   124  		})
   125  	})
   126  
   127  	It("should handle big vals in Set", func() {
   128  		C, N = 4, 100
   129  
   130  		bigVal := bigVal()
   131  		perform(C, func(id int) {
   132  			for i := 0; i < N; i++ {
   133  				err := client.Set("key", bigVal, 0).Err()
   134  				Expect(err).NotTo(HaveOccurred())
   135  			}
   136  		})
   137  	})
   138  
   139  	It("should select db", func() {
   140  		err := client.Set("db", 1, 0).Err()
   141  		Expect(err).NotTo(HaveOccurred())
   142  
   143  		perform(C, func(id int) {
   144  			opt := redisOptions()
   145  			opt.DB = id
   146  			client := redis.NewClient(opt)
   147  			for i := 0; i < N; i++ {
   148  				err := client.Set("db", id, 0).Err()
   149  				Expect(err).NotTo(HaveOccurred())
   150  
   151  				n, err := client.Get("db").Int64()
   152  				Expect(err).NotTo(HaveOccurred())
   153  				Expect(n).To(Equal(int64(id)))
   154  			}
   155  			err := client.Close()
   156  			Expect(err).NotTo(HaveOccurred())
   157  		})
   158  
   159  		n, err := client.Get("db").Int64()
   160  		Expect(err).NotTo(HaveOccurred())
   161  		Expect(n).To(Equal(int64(1)))
   162  	})
   163  
   164  	It("should select DB with read timeout", func() {
   165  		perform(C, func(id int) {
   166  			opt := redisOptions()
   167  			opt.DB = id
   168  			opt.ReadTimeout = time.Nanosecond
   169  			client := redis.NewClient(opt)
   170  
   171  			perform(C, func(id int) {
   172  				err := client.Ping().Err()
   173  				Expect(err).To(HaveOccurred())
   174  				Expect(err.(net.Error).Timeout()).To(BeTrue())
   175  			})
   176  
   177  			err := client.Close()
   178  			Expect(err).NotTo(HaveOccurred())
   179  		})
   180  	})
   181  
   182  	It("should Watch/Unwatch", func() {
   183  		err := client.Set("key", "0", 0).Err()
   184  		Expect(err).NotTo(HaveOccurred())
   185  
   186  		perform(C, func(id int) {
   187  			for i := 0; i < N; i++ {
   188  				err := client.Watch(func(tx *redis.Tx) error {
   189  					val, err := tx.Get("key").Result()
   190  					Expect(err).NotTo(HaveOccurred())
   191  					Expect(val).NotTo(Equal(redis.Nil))
   192  
   193  					num, err := strconv.ParseInt(val, 10, 64)
   194  					Expect(err).NotTo(HaveOccurred())
   195  
   196  					cmds, err := tx.Pipelined(func(pipe redis.Pipeliner) error {
   197  						pipe.Set("key", strconv.FormatInt(num+1, 10), 0)
   198  						return nil
   199  					})
   200  					Expect(cmds).To(HaveLen(1))
   201  					return err
   202  				}, "key")
   203  				if err == redis.TxFailedErr {
   204  					i--
   205  					continue
   206  				}
   207  				Expect(err).NotTo(HaveOccurred())
   208  			}
   209  		})
   210  
   211  		val, err := client.Get("key").Int64()
   212  		Expect(err).NotTo(HaveOccurred())
   213  		Expect(val).To(Equal(int64(C * N)))
   214  	})
   215  
   216  	It("should Pipeline", func() {
   217  		perform(C, func(id int) {
   218  			pipe := client.Pipeline()
   219  			for i := 0; i < N; i++ {
   220  				pipe.Echo(fmt.Sprint(i))
   221  			}
   222  
   223  			cmds, err := pipe.Exec()
   224  			Expect(err).NotTo(HaveOccurred())
   225  			Expect(cmds).To(HaveLen(N))
   226  
   227  			for i := 0; i < N; i++ {
   228  				Expect(cmds[i].(*redis.StringCmd).Val()).To(Equal(fmt.Sprint(i)))
   229  			}
   230  		})
   231  	})
   232  
   233  	It("should Pipeline", func() {
   234  		pipe := client.Pipeline()
   235  		perform(N, func(id int) {
   236  			pipe.Incr("key")
   237  		})
   238  
   239  		cmds, err := pipe.Exec()
   240  		Expect(err).NotTo(HaveOccurred())
   241  		Expect(cmds).To(HaveLen(N))
   242  
   243  		n, err := client.Get("key").Int64()
   244  		Expect(err).NotTo(HaveOccurred())
   245  		Expect(n).To(Equal(int64(N)))
   246  	})
   247  
   248  	It("should TxPipeline", func() {
   249  		pipe := client.TxPipeline()
   250  		perform(N, func(id int) {
   251  			pipe.Incr("key")
   252  		})
   253  
   254  		cmds, err := pipe.Exec()
   255  		Expect(err).NotTo(HaveOccurred())
   256  		Expect(cmds).To(HaveLen(N))
   257  
   258  		n, err := client.Get("key").Int64()
   259  		Expect(err).NotTo(HaveOccurred())
   260  		Expect(n).To(Equal(int64(N)))
   261  	})
   262  
   263  	It("should BLPop", func() {
   264  		var received uint32
   265  		wg := performAsync(C, func(id int) {
   266  			for {
   267  				v, err := client.BLPop(3*time.Second, "list").Result()
   268  				if err != nil {
   269  					break
   270  				}
   271  				Expect(v).To(Equal([]string{"list", "hello"}))
   272  				atomic.AddUint32(&received, 1)
   273  			}
   274  		})
   275  
   276  		perform(C, func(id int) {
   277  			for i := 0; i < N; i++ {
   278  				err := client.LPush("list", "hello").Err()
   279  				Expect(err).NotTo(HaveOccurred())
   280  			}
   281  		})
   282  
   283  		wg.Wait()
   284  		Expect(received).To(Equal(uint32(C * N)))
   285  	})
   286  })
   287  
   288  var _ = Describe("cluster races", func() {
   289  	var client *redis.ClusterClient
   290  	var C, N int
   291  
   292  	BeforeEach(func() {
   293  		opt := redisClusterOptions()
   294  		client = cluster.clusterClient(opt)
   295  
   296  		C, N = 10, 1000
   297  		if testing.Short() {
   298  			C = 4
   299  			N = 100
   300  		}
   301  	})
   302  
   303  	AfterEach(func() {
   304  		err := client.Close()
   305  		Expect(err).NotTo(HaveOccurred())
   306  	})
   307  
   308  	It("should echo", func() {
   309  		perform(C, func(id int) {
   310  			for i := 0; i < N; i++ {
   311  				msg := fmt.Sprintf("echo %d %d", id, i)
   312  				echo, err := client.Echo(msg).Result()
   313  				Expect(err).NotTo(HaveOccurred())
   314  				Expect(echo).To(Equal(msg))
   315  			}
   316  		})
   317  	})
   318  
   319  	It("should get", func() {
   320  		perform(C, func(id int) {
   321  			for i := 0; i < N; i++ {
   322  				key := fmt.Sprintf("key_%d_%d", id, i)
   323  				_, err := client.Get(key).Result()
   324  				Expect(err).To(Equal(redis.Nil))
   325  			}
   326  		})
   327  	})
   328  
   329  	It("should incr", func() {
   330  		key := "TestIncrFromGoroutines"
   331  
   332  		perform(C, func(id int) {
   333  			for i := 0; i < N; i++ {
   334  				err := client.Incr(key).Err()
   335  				Expect(err).NotTo(HaveOccurred())
   336  			}
   337  		})
   338  
   339  		val, err := client.Get(key).Int64()
   340  		Expect(err).NotTo(HaveOccurred())
   341  		Expect(val).To(Equal(int64(C * N)))
   342  	})
   343  })
   344  
   345  func bigVal() []byte {
   346  	return bytes.Repeat([]byte{'*'}, 1<<17) // 128kb
   347  }
   348  

View as plain text