...

Source file src/github.com/redis/go-redis/v9/probabilistic_test.go

Documentation: github.com/redis/go-redis/v9

     1  package redis_test
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"math"
     7  
     8  	. "github.com/bsm/ginkgo/v2"
     9  	. "github.com/bsm/gomega"
    10  
    11  	"github.com/redis/go-redis/v9"
    12  )
    13  
    14  var _ = Describe("Probabilistic commands", Label("probabilistic"), func() {
    15  	ctx := context.TODO()
    16  
    17  	setupRedisClient := func(protocolVersion int) *redis.Client {
    18  		return redis.NewClient(&redis.Options{
    19  			Addr:     "localhost:6379",
    20  			DB:       0,
    21  			Protocol: protocolVersion,
    22  		})
    23  	}
    24  
    25  	protocols := []int{2, 3}
    26  	for _, protocol := range protocols {
    27  		protocol := protocol // capture loop variable for each context
    28  
    29  		Context(fmt.Sprintf("with protocol version %d", protocol), func() {
    30  			var client *redis.Client
    31  
    32  			BeforeEach(func() {
    33  				client = setupRedisClient(protocol)
    34  				Expect(client.FlushAll(ctx).Err()).NotTo(HaveOccurred())
    35  			})
    36  
    37  			AfterEach(func() {
    38  				if client != nil {
    39  					client.FlushDB(ctx)
    40  					client.Close()
    41  				}
    42  			})
    43  
    44  			Describe("bloom", Label("bloom"), func() {
    45  				It("should BFAdd", Label("bloom", "bfadd"), func() {
    46  					resultAdd, err := client.BFAdd(ctx, "testbf1", 1).Result()
    47  
    48  					Expect(err).NotTo(HaveOccurred())
    49  					Expect(resultAdd).To(BeTrue())
    50  
    51  					resultInfo, err := client.BFInfo(ctx, "testbf1").Result()
    52  
    53  					Expect(err).NotTo(HaveOccurred())
    54  					Expect(resultInfo).To(BeAssignableToTypeOf(redis.BFInfo{}))
    55  					Expect(resultInfo.ItemsInserted).To(BeEquivalentTo(int64(1)))
    56  				})
    57  
    58  				It("should BFCard", Label("bloom", "bfcard"), func() {
    59  					// This is a probabilistic data structure, and it's not always guaranteed that we will get back
    60  					// the exact number of inserted items, during hash collisions
    61  					// But with such a low number of items (only 3),
    62  					// the probability of a collision is very low, so we can expect to get back the exact number of items
    63  					_, err := client.BFAdd(ctx, "testbf1", "item1").Result()
    64  					Expect(err).NotTo(HaveOccurred())
    65  					_, err = client.BFAdd(ctx, "testbf1", "item2").Result()
    66  					Expect(err).NotTo(HaveOccurred())
    67  					_, err = client.BFAdd(ctx, "testbf1", 3).Result()
    68  					Expect(err).NotTo(HaveOccurred())
    69  
    70  					result, err := client.BFCard(ctx, "testbf1").Result()
    71  
    72  					Expect(err).NotTo(HaveOccurred())
    73  					Expect(result).To(BeEquivalentTo(int64(3)))
    74  				})
    75  
    76  				It("should BFExists", Label("bloom", "bfexists"), func() {
    77  					exists, err := client.BFExists(ctx, "testbf1", "item1").Result()
    78  					Expect(err).NotTo(HaveOccurred())
    79  					Expect(exists).To(BeFalse())
    80  
    81  					_, err = client.BFAdd(ctx, "testbf1", "item1").Result()
    82  					Expect(err).NotTo(HaveOccurred())
    83  
    84  					exists, err = client.BFExists(ctx, "testbf1", "item1").Result()
    85  
    86  					Expect(err).NotTo(HaveOccurred())
    87  					Expect(exists).To(BeTrue())
    88  				})
    89  
    90  				It("should BFInfo and BFReserve", Label("bloom", "bfinfo", "bfreserve"), func() {
    91  					err := client.BFReserve(ctx, "testbf1", 0.001, 2000).Err()
    92  					Expect(err).NotTo(HaveOccurred())
    93  
    94  					result, err := client.BFInfo(ctx, "testbf1").Result()
    95  					Expect(err).NotTo(HaveOccurred())
    96  					Expect(result).To(BeAssignableToTypeOf(redis.BFInfo{}))
    97  					Expect(result.Capacity).To(BeEquivalentTo(int64(2000)))
    98  				})
    99  
   100  				It("should BFInfoCapacity, BFInfoSize, BFInfoFilters, BFInfoItems, BFInfoExpansion, ", Label("bloom", "bfinfocapacity", "bfinfosize", "bfinfofilters", "bfinfoitems", "bfinfoexpansion"), func() {
   101  					err := client.BFReserve(ctx, "testbf1", 0.001, 2000).Err()
   102  					Expect(err).NotTo(HaveOccurred())
   103  
   104  					result, err := client.BFInfoCapacity(ctx, "testbf1").Result()
   105  					Expect(err).NotTo(HaveOccurred())
   106  					Expect(result.Capacity).To(BeEquivalentTo(int64(2000)))
   107  
   108  					result, err = client.BFInfoItems(ctx, "testbf1").Result()
   109  					Expect(err).NotTo(HaveOccurred())
   110  					Expect(result.ItemsInserted).To(BeEquivalentTo(int64(0)))
   111  
   112  					result, err = client.BFInfoSize(ctx, "testbf1").Result()
   113  					Expect(err).NotTo(HaveOccurred())
   114  					Expect(result.Size).To(BeEquivalentTo(int64(4056)))
   115  
   116  					err = client.BFReserveExpansion(ctx, "testbf2", 0.001, 2000, 3).Err()
   117  					Expect(err).NotTo(HaveOccurred())
   118  
   119  					result, err = client.BFInfoFilters(ctx, "testbf2").Result()
   120  					Expect(err).NotTo(HaveOccurred())
   121  					Expect(result.Filters).To(BeEquivalentTo(int64(1)))
   122  
   123  					result, err = client.BFInfoExpansion(ctx, "testbf2").Result()
   124  					Expect(err).NotTo(HaveOccurred())
   125  					Expect(result.ExpansionRate).To(BeEquivalentTo(int64(3)))
   126  				})
   127  
   128  				It("should BFInsert", Label("bloom", "bfinsert"), func() {
   129  					options := &redis.BFInsertOptions{
   130  						Capacity:   2000,
   131  						Error:      0.001,
   132  						Expansion:  3,
   133  						NonScaling: false,
   134  						NoCreate:   true,
   135  					}
   136  
   137  					_, err := client.BFInsert(ctx, "testbf1", options, "item1").Result()
   138  					Expect(err).To(HaveOccurred())
   139  					Expect(err).To(MatchError("ERR not found"))
   140  
   141  					options = &redis.BFInsertOptions{
   142  						Capacity:   2000,
   143  						Error:      0.001,
   144  						Expansion:  3,
   145  						NonScaling: false,
   146  						NoCreate:   false,
   147  					}
   148  
   149  					resultInsert, err := client.BFInsert(ctx, "testbf1", options, "item1").Result()
   150  					Expect(err).NotTo(HaveOccurred())
   151  					Expect(len(resultInsert)).To(BeEquivalentTo(1))
   152  
   153  					exists, err := client.BFExists(ctx, "testbf1", "item1").Result()
   154  					Expect(err).NotTo(HaveOccurred())
   155  					Expect(exists).To(BeTrue())
   156  
   157  					result, err := client.BFInfo(ctx, "testbf1").Result()
   158  					Expect(err).NotTo(HaveOccurred())
   159  					Expect(result).To(BeAssignableToTypeOf(redis.BFInfo{}))
   160  					Expect(result.Capacity).To(BeEquivalentTo(int64(2000)))
   161  					Expect(result.ExpansionRate).To(BeEquivalentTo(int64(3)))
   162  				})
   163  
   164  				It("should BFMAdd", Label("bloom", "bfmadd"), func() {
   165  					resultAdd, err := client.BFMAdd(ctx, "testbf1", "item1", "item2", "item3").Result()
   166  
   167  					Expect(err).NotTo(HaveOccurred())
   168  					Expect(len(resultAdd)).To(Equal(3))
   169  
   170  					resultInfo, err := client.BFInfo(ctx, "testbf1").Result()
   171  
   172  					Expect(err).NotTo(HaveOccurred())
   173  					Expect(resultInfo).To(BeAssignableToTypeOf(redis.BFInfo{}))
   174  					Expect(resultInfo.ItemsInserted).To(BeEquivalentTo(int64(3)))
   175  					resultAdd2, err := client.BFMAdd(ctx, "testbf1", "item1", "item2", "item4").Result()
   176  					Expect(err).NotTo(HaveOccurred())
   177  					Expect(resultAdd2[0]).To(BeFalse())
   178  					Expect(resultAdd2[1]).To(BeFalse())
   179  					Expect(resultAdd2[2]).To(BeTrue())
   180  				})
   181  
   182  				It("should BFMExists", Label("bloom", "bfmexists"), func() {
   183  					exist, err := client.BFMExists(ctx, "testbf1", "item1", "item2", "item3").Result()
   184  					Expect(err).NotTo(HaveOccurred())
   185  					Expect(len(exist)).To(Equal(3))
   186  					Expect(exist[0]).To(BeFalse())
   187  					Expect(exist[1]).To(BeFalse())
   188  					Expect(exist[2]).To(BeFalse())
   189  
   190  					_, err = client.BFMAdd(ctx, "testbf1", "item1", "item2", "item3").Result()
   191  					Expect(err).NotTo(HaveOccurred())
   192  
   193  					exist, err = client.BFMExists(ctx, "testbf1", "item1", "item2", "item3", "item4").Result()
   194  
   195  					Expect(err).NotTo(HaveOccurred())
   196  					Expect(len(exist)).To(Equal(4))
   197  					Expect(exist[0]).To(BeTrue())
   198  					Expect(exist[1]).To(BeTrue())
   199  					Expect(exist[2]).To(BeTrue())
   200  					Expect(exist[3]).To(BeFalse())
   201  				})
   202  
   203  				It("should BFReserveExpansion", Label("bloom", "bfreserveexpansion"), func() {
   204  					err := client.BFReserveExpansion(ctx, "testbf1", 0.001, 2000, 3).Err()
   205  					Expect(err).NotTo(HaveOccurred())
   206  
   207  					result, err := client.BFInfo(ctx, "testbf1").Result()
   208  					Expect(err).NotTo(HaveOccurred())
   209  					Expect(result).To(BeAssignableToTypeOf(redis.BFInfo{}))
   210  					Expect(result.Capacity).To(BeEquivalentTo(int64(2000)))
   211  					Expect(result.ExpansionRate).To(BeEquivalentTo(int64(3)))
   212  				})
   213  
   214  				It("should BFReserveNonScaling", Label("bloom", "bfreservenonscaling"), func() {
   215  					err := client.BFReserveNonScaling(ctx, "testbfns1", 0.001, 1000).Err()
   216  					Expect(err).NotTo(HaveOccurred())
   217  
   218  					_, err = client.BFInfo(ctx, "testbfns1").Result()
   219  					Expect(err).To(HaveOccurred())
   220  				})
   221  
   222  				It("should BFScanDump and BFLoadChunk", Label("bloom", "bfscandump", "bfloadchunk"), func() {
   223  					err := client.BFReserve(ctx, "testbfsd1", 0.001, 3000).Err()
   224  					Expect(err).NotTo(HaveOccurred())
   225  					for i := 0; i < 1000; i++ {
   226  						client.BFAdd(ctx, "testbfsd1", i)
   227  					}
   228  					infBefore := client.BFInfoSize(ctx, "testbfsd1")
   229  					fd := []redis.ScanDump{}
   230  					sd, err := client.BFScanDump(ctx, "testbfsd1", 0).Result()
   231  					for {
   232  						if sd.Iter == 0 {
   233  							break
   234  						}
   235  						Expect(err).NotTo(HaveOccurred())
   236  						fd = append(fd, sd)
   237  						sd, err = client.BFScanDump(ctx, "testbfsd1", sd.Iter).Result()
   238  					}
   239  					client.Del(ctx, "testbfsd1")
   240  					for _, e := range fd {
   241  						client.BFLoadChunk(ctx, "testbfsd1", e.Iter, e.Data)
   242  					}
   243  					infAfter := client.BFInfoSize(ctx, "testbfsd1")
   244  					Expect(infBefore).To(BeEquivalentTo(infAfter))
   245  				})
   246  
   247  				It("should BFReserveWithArgs", Label("bloom", "bfreserveargs"), func() {
   248  					options := &redis.BFReserveOptions{
   249  						Capacity:   2000,
   250  						Error:      0.001,
   251  						Expansion:  3,
   252  						NonScaling: false,
   253  					}
   254  					err := client.BFReserveWithArgs(ctx, "testbf", options).Err()
   255  					Expect(err).NotTo(HaveOccurred())
   256  
   257  					result, err := client.BFInfo(ctx, "testbf").Result()
   258  					Expect(err).NotTo(HaveOccurred())
   259  					Expect(result).To(BeAssignableToTypeOf(redis.BFInfo{}))
   260  					Expect(result.Capacity).To(BeEquivalentTo(int64(2000)))
   261  					Expect(result.ExpansionRate).To(BeEquivalentTo(int64(3)))
   262  				})
   263  			})
   264  
   265  			Describe("cuckoo", Label("cuckoo"), func() {
   266  				It("should CFAdd", Label("cuckoo", "cfadd"), func() {
   267  					add, err := client.CFAdd(ctx, "testcf1", "item1").Result()
   268  					Expect(err).NotTo(HaveOccurred())
   269  					Expect(add).To(BeTrue())
   270  
   271  					exists, err := client.CFExists(ctx, "testcf1", "item1").Result()
   272  					Expect(err).NotTo(HaveOccurred())
   273  					Expect(exists).To(BeTrue())
   274  
   275  					info, err := client.CFInfo(ctx, "testcf1").Result()
   276  					Expect(err).NotTo(HaveOccurred())
   277  					Expect(info).To(BeAssignableToTypeOf(redis.CFInfo{}))
   278  					Expect(info.NumItemsInserted).To(BeEquivalentTo(int64(1)))
   279  				})
   280  
   281  				It("should CFAddNX", Label("cuckoo", "cfaddnx"), func() {
   282  					add, err := client.CFAddNX(ctx, "testcf1", "item1").Result()
   283  					Expect(err).NotTo(HaveOccurred())
   284  					Expect(add).To(BeTrue())
   285  
   286  					exists, err := client.CFExists(ctx, "testcf1", "item1").Result()
   287  					Expect(err).NotTo(HaveOccurred())
   288  					Expect(exists).To(BeTrue())
   289  
   290  					result, err := client.CFAddNX(ctx, "testcf1", "item1").Result()
   291  					Expect(err).NotTo(HaveOccurred())
   292  					Expect(result).To(BeFalse())
   293  
   294  					info, err := client.CFInfo(ctx, "testcf1").Result()
   295  					Expect(err).NotTo(HaveOccurred())
   296  					Expect(info).To(BeAssignableToTypeOf(redis.CFInfo{}))
   297  					Expect(info.NumItemsInserted).To(BeEquivalentTo(int64(1)))
   298  				})
   299  
   300  				It("should CFCount", Label("cuckoo", "cfcount"), func() {
   301  					client.CFAdd(ctx, "testcf1", "item1")
   302  					cnt, err := client.CFCount(ctx, "testcf1", "item1").Result()
   303  					Expect(err).NotTo(HaveOccurred())
   304  					Expect(cnt).To(BeEquivalentTo(int64(1)))
   305  
   306  					err = client.CFAdd(ctx, "testcf1", "item1").Err()
   307  					Expect(err).NotTo(HaveOccurred())
   308  
   309  					cnt, err = client.CFCount(ctx, "testcf1", "item1").Result()
   310  					Expect(err).NotTo(HaveOccurred())
   311  					Expect(cnt).To(BeEquivalentTo(int64(2)))
   312  				})
   313  
   314  				It("should CFDel and CFExists", Label("cuckoo", "cfdel", "cfexists"), func() {
   315  					err := client.CFAdd(ctx, "testcf1", "item1").Err()
   316  					Expect(err).NotTo(HaveOccurred())
   317  
   318  					exists, err := client.CFExists(ctx, "testcf1", "item1").Result()
   319  					Expect(err).NotTo(HaveOccurred())
   320  					Expect(exists).To(BeTrue())
   321  
   322  					del, err := client.CFDel(ctx, "testcf1", "item1").Result()
   323  					Expect(err).NotTo(HaveOccurred())
   324  					Expect(del).To(BeTrue())
   325  
   326  					exists, err = client.CFExists(ctx, "testcf1", "item1").Result()
   327  					Expect(err).NotTo(HaveOccurred())
   328  					Expect(exists).To(BeFalse())
   329  				})
   330  
   331  				It("should CFInfo and CFReserve", Label("cuckoo", "cfinfo", "cfreserve"), func() {
   332  					err := client.CFReserve(ctx, "testcf1", 1000).Err()
   333  					Expect(err).NotTo(HaveOccurred())
   334  					err = client.CFReserveExpansion(ctx, "testcfe1", 1000, 1).Err()
   335  					Expect(err).NotTo(HaveOccurred())
   336  					err = client.CFReserveBucketSize(ctx, "testcfbs1", 1000, 4).Err()
   337  					Expect(err).NotTo(HaveOccurred())
   338  					err = client.CFReserveMaxIterations(ctx, "testcfmi1", 1000, 10).Err()
   339  					Expect(err).NotTo(HaveOccurred())
   340  
   341  					result, err := client.CFInfo(ctx, "testcf1").Result()
   342  					Expect(err).NotTo(HaveOccurred())
   343  					Expect(result).To(BeAssignableToTypeOf(redis.CFInfo{}))
   344  				})
   345  
   346  				It("should CFScanDump and CFLoadChunk", Label("bloom", "cfscandump", "cfloadchunk"), func() {
   347  					err := client.CFReserve(ctx, "testcfsd1", 1000).Err()
   348  					Expect(err).NotTo(HaveOccurred())
   349  					for i := 0; i < 1000; i++ {
   350  						Item := fmt.Sprintf("item%d", i)
   351  						client.CFAdd(ctx, "testcfsd1", Item)
   352  					}
   353  					infBefore := client.CFInfo(ctx, "testcfsd1")
   354  					fd := []redis.ScanDump{}
   355  					sd, err := client.CFScanDump(ctx, "testcfsd1", 0).Result()
   356  					for {
   357  						if sd.Iter == 0 {
   358  							break
   359  						}
   360  						Expect(err).NotTo(HaveOccurred())
   361  						fd = append(fd, sd)
   362  						sd, err = client.CFScanDump(ctx, "testcfsd1", sd.Iter).Result()
   363  					}
   364  					client.Del(ctx, "testcfsd1")
   365  					for _, e := range fd {
   366  						client.CFLoadChunk(ctx, "testcfsd1", e.Iter, e.Data)
   367  					}
   368  					infAfter := client.CFInfo(ctx, "testcfsd1")
   369  					Expect(infBefore).To(BeEquivalentTo(infAfter))
   370  				})
   371  
   372  				It("should CFInfo and CFReserveWithArgs", Label("cuckoo", "cfinfo", "cfreserveargs"), func() {
   373  					args := &redis.CFReserveOptions{
   374  						Capacity:      2048,
   375  						BucketSize:    3,
   376  						MaxIterations: 15,
   377  						Expansion:     2,
   378  					}
   379  
   380  					err := client.CFReserveWithArgs(ctx, "testcf1", args).Err()
   381  					Expect(err).NotTo(HaveOccurred())
   382  
   383  					result, err := client.CFInfo(ctx, "testcf1").Result()
   384  					Expect(err).NotTo(HaveOccurred())
   385  					Expect(result).To(BeAssignableToTypeOf(redis.CFInfo{}))
   386  					Expect(result.BucketSize).To(BeEquivalentTo(int64(3)))
   387  					Expect(result.MaxIteration).To(BeEquivalentTo(int64(15)))
   388  					Expect(result.ExpansionRate).To(BeEquivalentTo(int64(2)))
   389  				})
   390  
   391  				It("should CFInsert", Label("cuckoo", "cfinsert"), func() {
   392  					args := &redis.CFInsertOptions{
   393  						Capacity: 3000,
   394  						NoCreate: true,
   395  					}
   396  
   397  					_, err := client.CFInsert(ctx, "testcf1", args, "item1", "item2", "item3").Result()
   398  					Expect(err).To(HaveOccurred())
   399  
   400  					args = &redis.CFInsertOptions{
   401  						Capacity: 3000,
   402  						NoCreate: false,
   403  					}
   404  
   405  					result, err := client.CFInsert(ctx, "testcf1", args, "item1", "item2", "item3").Result()
   406  					Expect(err).NotTo(HaveOccurred())
   407  					Expect(len(result)).To(BeEquivalentTo(3))
   408  				})
   409  
   410  				It("should CFInsertNX", Label("cuckoo", "cfinsertnx"), func() {
   411  					args := &redis.CFInsertOptions{
   412  						Capacity: 3000,
   413  						NoCreate: true,
   414  					}
   415  
   416  					_, err := client.CFInsertNX(ctx, "testcf1", args, "item1", "item2", "item2").Result()
   417  					Expect(err).To(HaveOccurred())
   418  
   419  					args = &redis.CFInsertOptions{
   420  						Capacity: 3000,
   421  						NoCreate: false,
   422  					}
   423  
   424  					result, err := client.CFInsertNX(ctx, "testcf2", args, "item1", "item2", "item2").Result()
   425  					Expect(err).NotTo(HaveOccurred())
   426  					Expect(len(result)).To(BeEquivalentTo(3))
   427  					Expect(result[0]).To(BeEquivalentTo(int64(1)))
   428  					Expect(result[1]).To(BeEquivalentTo(int64(1)))
   429  					Expect(result[2]).To(BeEquivalentTo(int64(0)))
   430  				})
   431  
   432  				It("should CFMexists", Label("cuckoo", "cfmexists"), func() {
   433  					err := client.CFInsert(ctx, "testcf1", nil, "item1", "item2", "item3").Err()
   434  					Expect(err).NotTo(HaveOccurred())
   435  
   436  					result, err := client.CFMExists(ctx, "testcf1", "item1", "item2", "item3", "item4").Result()
   437  					Expect(err).NotTo(HaveOccurred())
   438  					Expect(len(result)).To(BeEquivalentTo(4))
   439  					Expect(result[0]).To(BeTrue())
   440  					Expect(result[1]).To(BeTrue())
   441  					Expect(result[2]).To(BeTrue())
   442  					Expect(result[3]).To(BeFalse())
   443  				})
   444  			})
   445  
   446  			Describe("CMS", Label("cms"), func() {
   447  				It("should CMSIncrBy", Label("cms", "cmsincrby"), func() {
   448  					err := client.CMSInitByDim(ctx, "testcms1", 5, 10).Err()
   449  					Expect(err).NotTo(HaveOccurred())
   450  
   451  					result, err := client.CMSIncrBy(ctx, "testcms1", "item1", 1, "item2", 2, "item3", 3).Result()
   452  					Expect(err).NotTo(HaveOccurred())
   453  					Expect(len(result)).To(BeEquivalentTo(3))
   454  					Expect(result[0]).To(BeEquivalentTo(int64(1)))
   455  					Expect(result[1]).To(BeEquivalentTo(int64(2)))
   456  					Expect(result[2]).To(BeEquivalentTo(int64(3)))
   457  				})
   458  
   459  				It("should CMSInitByDim and CMSInfo", Label("cms", "cmsinitbydim", "cmsinfo"), func() {
   460  					err := client.CMSInitByDim(ctx, "testcms1", 5, 10).Err()
   461  					Expect(err).NotTo(HaveOccurred())
   462  
   463  					info, err := client.CMSInfo(ctx, "testcms1").Result()
   464  					Expect(err).NotTo(HaveOccurred())
   465  
   466  					Expect(info).To(BeAssignableToTypeOf(redis.CMSInfo{}))
   467  					Expect(info.Width).To(BeEquivalentTo(int64(5)))
   468  					Expect(info.Depth).To(BeEquivalentTo(int64(10)))
   469  				})
   470  
   471  				It("should CMSInitByProb", Label("cms", "cmsinitbyprob"), func() {
   472  					err := client.CMSInitByProb(ctx, "testcms1", 0.002, 0.01).Err()
   473  					Expect(err).NotTo(HaveOccurred())
   474  
   475  					info, err := client.CMSInfo(ctx, "testcms1").Result()
   476  					Expect(err).NotTo(HaveOccurred())
   477  					Expect(info).To(BeAssignableToTypeOf(redis.CMSInfo{}))
   478  				})
   479  
   480  				It("should CMSMerge, CMSMergeWithWeight and CMSQuery", Label("cms", "cmsmerge", "cmsquery", "NonRedisEnterprise"), func() {
   481  					err := client.CMSMerge(ctx, "destCms1", "testcms2", "testcms3").Err()
   482  					Expect(err).To(HaveOccurred())
   483  					Expect(err).To(MatchError("CMS: key does not exist"))
   484  
   485  					err = client.CMSInitByDim(ctx, "destCms1", 5, 10).Err()
   486  					Expect(err).NotTo(HaveOccurred())
   487  					err = client.CMSInitByDim(ctx, "destCms2", 5, 10).Err()
   488  					Expect(err).NotTo(HaveOccurred())
   489  					err = client.CMSInitByDim(ctx, "cms1", 2, 20).Err()
   490  					Expect(err).NotTo(HaveOccurred())
   491  					err = client.CMSInitByDim(ctx, "cms2", 3, 20).Err()
   492  					Expect(err).NotTo(HaveOccurred())
   493  
   494  					err = client.CMSMerge(ctx, "destCms1", "cms1", "cms2").Err()
   495  					Expect(err).To(MatchError("CMS: width/depth is not equal"))
   496  
   497  					client.Del(ctx, "cms1", "cms2")
   498  
   499  					err = client.CMSInitByDim(ctx, "cms1", 5, 10).Err()
   500  					Expect(err).NotTo(HaveOccurred())
   501  					err = client.CMSInitByDim(ctx, "cms2", 5, 10).Err()
   502  					Expect(err).NotTo(HaveOccurred())
   503  
   504  					client.CMSIncrBy(ctx, "cms1", "item1", 1, "item2", 2)
   505  					client.CMSIncrBy(ctx, "cms2", "item2", 2, "item3", 3)
   506  
   507  					err = client.CMSMerge(ctx, "destCms1", "cms1", "cms2").Err()
   508  					Expect(err).NotTo(HaveOccurred())
   509  
   510  					result, err := client.CMSQuery(ctx, "destCms1", "item1", "item2", "item3").Result()
   511  					Expect(err).NotTo(HaveOccurred())
   512  					Expect(len(result)).To(BeEquivalentTo(3))
   513  					Expect(result[0]).To(BeEquivalentTo(int64(1)))
   514  					Expect(result[1]).To(BeEquivalentTo(int64(4)))
   515  					Expect(result[2]).To(BeEquivalentTo(int64(3)))
   516  
   517  					sourceSketches := map[string]int64{
   518  						"cms1": 1,
   519  						"cms2": 2,
   520  					}
   521  					err = client.CMSMergeWithWeight(ctx, "destCms2", sourceSketches).Err()
   522  					Expect(err).NotTo(HaveOccurred())
   523  
   524  					result, err = client.CMSQuery(ctx, "destCms2", "item1", "item2", "item3").Result()
   525  					Expect(err).NotTo(HaveOccurred())
   526  					Expect(len(result)).To(BeEquivalentTo(3))
   527  					Expect(result[0]).To(BeEquivalentTo(int64(1)))
   528  					Expect(result[1]).To(BeEquivalentTo(int64(6)))
   529  					Expect(result[2]).To(BeEquivalentTo(int64(6)))
   530  				})
   531  			})
   532  
   533  			Describe("TopK", Label("topk"), func() {
   534  				It("should TopKReserve, TopKInfo, TopKAdd, TopKQuery, TopKCount, TopKIncrBy, TopKList, TopKListWithCount", Label("topk", "topkreserve", "topkinfo", "topkadd", "topkquery", "topkcount", "topkincrby", "topklist", "topklistwithcount"), func() {
   535  					err := client.TopKReserve(ctx, "topk1", 3).Err()
   536  					Expect(err).NotTo(HaveOccurred())
   537  
   538  					resultInfo, err := client.TopKInfo(ctx, "topk1").Result()
   539  					Expect(err).NotTo(HaveOccurred())
   540  					Expect(resultInfo.K).To(BeEquivalentTo(int64(3)))
   541  
   542  					resultAdd, err := client.TopKAdd(ctx, "topk1", "item1", "item2", 3, "item1").Result()
   543  					Expect(err).NotTo(HaveOccurred())
   544  					Expect(len(resultAdd)).To(BeEquivalentTo(int64(4)))
   545  
   546  					resultQuery, err := client.TopKQuery(ctx, "topk1", "item1", "item2", 4, 3).Result()
   547  					Expect(err).NotTo(HaveOccurred())
   548  					Expect(len(resultQuery)).To(BeEquivalentTo(4))
   549  					Expect(resultQuery[0]).To(BeTrue())
   550  					Expect(resultQuery[1]).To(BeTrue())
   551  					Expect(resultQuery[2]).To(BeFalse())
   552  					Expect(resultQuery[3]).To(BeTrue())
   553  
   554  					resultCount, err := client.TopKCount(ctx, "topk1", "item1", "item2", "item3").Result()
   555  					Expect(err).NotTo(HaveOccurred())
   556  					Expect(len(resultCount)).To(BeEquivalentTo(3))
   557  					Expect(resultCount[0]).To(BeEquivalentTo(int64(2)))
   558  					Expect(resultCount[1]).To(BeEquivalentTo(int64(1)))
   559  					Expect(resultCount[2]).To(BeEquivalentTo(int64(0)))
   560  
   561  					resultIncr, err := client.TopKIncrBy(ctx, "topk1", "item1", 5, "item2", 10).Result()
   562  					Expect(err).NotTo(HaveOccurred())
   563  					Expect(len(resultIncr)).To(BeEquivalentTo(2))
   564  
   565  					resultCount, err = client.TopKCount(ctx, "topk1", "item1", "item2", "item3").Result()
   566  					Expect(err).NotTo(HaveOccurred())
   567  					Expect(len(resultCount)).To(BeEquivalentTo(3))
   568  					Expect(resultCount[0]).To(BeEquivalentTo(int64(7)))
   569  					Expect(resultCount[1]).To(BeEquivalentTo(int64(11)))
   570  					Expect(resultCount[2]).To(BeEquivalentTo(int64(0)))
   571  
   572  					resultList, err := client.TopKList(ctx, "topk1").Result()
   573  					Expect(err).NotTo(HaveOccurred())
   574  					Expect(len(resultList)).To(BeEquivalentTo(3))
   575  					Expect(resultList).To(ContainElements("item2", "item1", "3"))
   576  
   577  					resultListWithCount, err := client.TopKListWithCount(ctx, "topk1").Result()
   578  					Expect(err).NotTo(HaveOccurred())
   579  					Expect(len(resultListWithCount)).To(BeEquivalentTo(3))
   580  					Expect(resultListWithCount["3"]).To(BeEquivalentTo(int64(1)))
   581  					Expect(resultListWithCount["item1"]).To(BeEquivalentTo(int64(7)))
   582  					Expect(resultListWithCount["item2"]).To(BeEquivalentTo(int64(11)))
   583  				})
   584  
   585  				It("should TopKReserveWithOptions", Label("topk", "topkreservewithoptions"), func() {
   586  					err := client.TopKReserveWithOptions(ctx, "topk1", 3, 1500, 8, 0.5).Err()
   587  					Expect(err).NotTo(HaveOccurred())
   588  
   589  					resultInfo, err := client.TopKInfo(ctx, "topk1").Result()
   590  					Expect(err).NotTo(HaveOccurred())
   591  					Expect(resultInfo.K).To(BeEquivalentTo(int64(3)))
   592  					Expect(resultInfo.Width).To(BeEquivalentTo(int64(1500)))
   593  					Expect(resultInfo.Depth).To(BeEquivalentTo(int64(8)))
   594  					Expect(resultInfo.Decay).To(BeEquivalentTo(0.5))
   595  				})
   596  			})
   597  
   598  			Describe("t-digest", Label("tdigest"), func() {
   599  				It("should TDigestAdd, TDigestCreate, TDigestInfo, TDigestByRank, TDigestByRevRank, TDigestCDF, TDigestMax, TDigestMin, TDigestQuantile, TDigestRank, TDigestRevRank, TDigestTrimmedMean, TDigestReset, ", Label("tdigest", "tdigestadd", "tdigestcreate", "tdigestinfo", "tdigestbyrank", "tdigestbyrevrank", "tdigestcdf", "tdigestmax", "tdigestmin", "tdigestquantile", "tdigestrank", "tdigestrevrank", "tdigesttrimmedmean", "tdigestreset"), func() {
   600  					err := client.TDigestCreate(ctx, "tdigest1").Err()
   601  					Expect(err).NotTo(HaveOccurred())
   602  
   603  					info, err := client.TDigestInfo(ctx, "tdigest1").Result()
   604  					Expect(err).NotTo(HaveOccurred())
   605  					Expect(info.Observations).To(BeEquivalentTo(int64(0)))
   606  
   607  					// Test with empty sketch
   608  					byRank, err := client.TDigestByRank(ctx, "tdigest1", 0, 1, 2, 3).Result()
   609  					Expect(err).NotTo(HaveOccurred())
   610  					Expect(len(byRank)).To(BeEquivalentTo(4))
   611  
   612  					byRevRank, err := client.TDigestByRevRank(ctx, "tdigest1", 0, 1, 2).Result()
   613  					Expect(err).NotTo(HaveOccurred())
   614  					Expect(len(byRevRank)).To(BeEquivalentTo(3))
   615  
   616  					cdf, err := client.TDigestCDF(ctx, "tdigest1", 15, 35, 70).Result()
   617  					Expect(err).NotTo(HaveOccurred())
   618  					Expect(len(cdf)).To(BeEquivalentTo(3))
   619  
   620  					max, err := client.TDigestMax(ctx, "tdigest1").Result()
   621  					Expect(err).NotTo(HaveOccurred())
   622  					Expect(math.IsNaN(max)).To(BeTrue())
   623  
   624  					min, err := client.TDigestMin(ctx, "tdigest1").Result()
   625  					Expect(err).NotTo(HaveOccurred())
   626  					Expect(math.IsNaN(min)).To(BeTrue())
   627  
   628  					quantile, err := client.TDigestQuantile(ctx, "tdigest1", 0.1, 0.2).Result()
   629  					Expect(err).NotTo(HaveOccurred())
   630  					Expect(len(quantile)).To(BeEquivalentTo(2))
   631  
   632  					rank, err := client.TDigestRank(ctx, "tdigest1", 10, 20).Result()
   633  					Expect(err).NotTo(HaveOccurred())
   634  					Expect(len(rank)).To(BeEquivalentTo(2))
   635  
   636  					revRank, err := client.TDigestRevRank(ctx, "tdigest1", 10, 20).Result()
   637  					Expect(err).NotTo(HaveOccurred())
   638  					Expect(len(revRank)).To(BeEquivalentTo(2))
   639  
   640  					trimmedMean, err := client.TDigestTrimmedMean(ctx, "tdigest1", 0.1, 0.6).Result()
   641  					Expect(err).NotTo(HaveOccurred())
   642  					Expect(math.IsNaN(trimmedMean)).To(BeTrue())
   643  
   644  					// Add elements
   645  					err = client.TDigestAdd(ctx, "tdigest1", 10, 20, 30, 40, 50, 60, 70, 80, 90, 100).Err()
   646  					Expect(err).NotTo(HaveOccurred())
   647  
   648  					info, err = client.TDigestInfo(ctx, "tdigest1").Result()
   649  					Expect(err).NotTo(HaveOccurred())
   650  					Expect(info.Observations).To(BeEquivalentTo(int64(10)))
   651  
   652  					byRank, err = client.TDigestByRank(ctx, "tdigest1", 0, 1, 2).Result()
   653  					Expect(err).NotTo(HaveOccurred())
   654  					Expect(len(byRank)).To(BeEquivalentTo(3))
   655  					Expect(byRank[0]).To(BeEquivalentTo(float64(10)))
   656  					Expect(byRank[1]).To(BeEquivalentTo(float64(20)))
   657  					Expect(byRank[2]).To(BeEquivalentTo(float64(30)))
   658  
   659  					byRevRank, err = client.TDigestByRevRank(ctx, "tdigest1", 0, 1, 2).Result()
   660  					Expect(err).NotTo(HaveOccurred())
   661  					Expect(len(byRevRank)).To(BeEquivalentTo(3))
   662  					Expect(byRevRank[0]).To(BeEquivalentTo(float64(100)))
   663  					Expect(byRevRank[1]).To(BeEquivalentTo(float64(90)))
   664  					Expect(byRevRank[2]).To(BeEquivalentTo(float64(80)))
   665  
   666  					cdf, err = client.TDigestCDF(ctx, "tdigest1", 15, 35, 70).Result()
   667  					Expect(err).NotTo(HaveOccurred())
   668  					Expect(len(cdf)).To(BeEquivalentTo(3))
   669  					Expect(cdf[0]).To(BeEquivalentTo(0.1))
   670  					Expect(cdf[1]).To(BeEquivalentTo(0.3))
   671  					Expect(cdf[2]).To(BeEquivalentTo(0.65))
   672  
   673  					max, err = client.TDigestMax(ctx, "tdigest1").Result()
   674  					Expect(err).NotTo(HaveOccurred())
   675  					Expect(max).To(BeEquivalentTo(float64(100)))
   676  
   677  					min, err = client.TDigestMin(ctx, "tdigest1").Result()
   678  					Expect(err).NotTo(HaveOccurred())
   679  					Expect(min).To(BeEquivalentTo(float64(10)))
   680  
   681  					quantile, err = client.TDigestQuantile(ctx, "tdigest1", 0.1, 0.2).Result()
   682  					Expect(err).NotTo(HaveOccurred())
   683  					Expect(len(quantile)).To(BeEquivalentTo(2))
   684  					Expect(quantile[0]).To(BeEquivalentTo(float64(20)))
   685  					Expect(quantile[1]).To(BeEquivalentTo(float64(30)))
   686  
   687  					rank, err = client.TDigestRank(ctx, "tdigest1", 10, 20).Result()
   688  					Expect(err).NotTo(HaveOccurred())
   689  					Expect(len(rank)).To(BeEquivalentTo(2))
   690  					Expect(rank[0]).To(BeEquivalentTo(int64(0)))
   691  					Expect(rank[1]).To(BeEquivalentTo(int64(1)))
   692  
   693  					revRank, err = client.TDigestRevRank(ctx, "tdigest1", 10, 20).Result()
   694  					Expect(err).NotTo(HaveOccurred())
   695  					Expect(len(revRank)).To(BeEquivalentTo(2))
   696  					Expect(revRank[0]).To(BeEquivalentTo(int64(9)))
   697  					Expect(revRank[1]).To(BeEquivalentTo(int64(8)))
   698  
   699  					trimmedMean, err = client.TDigestTrimmedMean(ctx, "tdigest1", 0.1, 0.6).Result()
   700  					Expect(err).NotTo(HaveOccurred())
   701  					Expect(trimmedMean).To(BeEquivalentTo(float64(40)))
   702  
   703  					reset, err := client.TDigestReset(ctx, "tdigest1").Result()
   704  					Expect(err).NotTo(HaveOccurred())
   705  					Expect(reset).To(BeEquivalentTo("OK"))
   706  				})
   707  
   708  				It("should TDigestCreateWithCompression", Label("tdigest", "tcreatewithcompression"), func() {
   709  					err := client.TDigestCreateWithCompression(ctx, "tdigest1", 2000).Err()
   710  					Expect(err).NotTo(HaveOccurred())
   711  
   712  					info, err := client.TDigestInfo(ctx, "tdigest1").Result()
   713  					Expect(err).NotTo(HaveOccurred())
   714  					Expect(info.Compression).To(BeEquivalentTo(int64(2000)))
   715  				})
   716  
   717  				It("should TDigestMerge", Label("tdigest", "tmerge", "NonRedisEnterprise"), func() {
   718  					err := client.TDigestCreate(ctx, "tdigest1").Err()
   719  					Expect(err).NotTo(HaveOccurred())
   720  					err = client.TDigestAdd(ctx, "tdigest1", 10, 20, 30, 40, 50, 60, 70, 80, 90, 100).Err()
   721  					Expect(err).NotTo(HaveOccurred())
   722  
   723  					err = client.TDigestCreate(ctx, "tdigest2").Err()
   724  					Expect(err).NotTo(HaveOccurred())
   725  					err = client.TDigestAdd(ctx, "tdigest2", 15, 25, 35, 45, 55, 65, 75, 85, 95, 105).Err()
   726  					Expect(err).NotTo(HaveOccurred())
   727  
   728  					err = client.TDigestCreate(ctx, "tdigest3").Err()
   729  					Expect(err).NotTo(HaveOccurred())
   730  					err = client.TDigestAdd(ctx, "tdigest3", 50, 60, 70, 80, 90, 100, 110, 120, 130, 140).Err()
   731  					Expect(err).NotTo(HaveOccurred())
   732  
   733  					options := &redis.TDigestMergeOptions{
   734  						Compression: 1000,
   735  						Override:    false,
   736  					}
   737  					err = client.TDigestMerge(ctx, "tdigest1", options, "tdigest2", "tdigest3").Err()
   738  					Expect(err).NotTo(HaveOccurred())
   739  
   740  					info, err := client.TDigestInfo(ctx, "tdigest1").Result()
   741  					Expect(err).NotTo(HaveOccurred())
   742  					Expect(info.Observations).To(BeEquivalentTo(int64(30)))
   743  					Expect(info.Compression).To(BeEquivalentTo(int64(1000)))
   744  
   745  					max, err := client.TDigestMax(ctx, "tdigest1").Result()
   746  					Expect(err).NotTo(HaveOccurred())
   747  					Expect(max).To(BeEquivalentTo(float64(140)))
   748  				})
   749  			})
   750  		})
   751  	}
   752  })
   753  

View as plain text