From 3bb0871cbf881d9de9abe66f110f0de3316e8e8b Mon Sep 17 00:00:00 2001 From: bigdaronlee163 <49524138+bigdaronlee163@users.noreply.github.com> Date: Mon, 8 Aug 2022 14:12:40 +0800 Subject: [PATCH] Support TairRoaring module (#4) Support TairRoaring module Co-authored-by: bodong.ybd --- .github/workflows/go.yml | 1 + .gitignore | 3 +- go.mod | 8 + go.sum | 3 + tair/main_test.go | 4 +- tair/taircommands.go | 31 ++++ tair/tairroaring.go | 318 +++++++++++++++++++++++++++++++++++++++ tair/tairroaring_test.go | 287 +++++++++++++++++++++++++++++++++++ 8 files changed, 652 insertions(+), 3 deletions(-) create mode 100644 tair/tairroaring.go create mode 100644 tair/tairroaring_test.go diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 3ef8dd1..382fcf4 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -79,3 +79,4 @@ jobs: go test -v ./... -run TestTairStringTestSuite/TestTairStringTestSuite go test -v ./... -run TestTairStringTestSuite/TestTairHashTestSuite go test -v ./... -run TestTairStringTestSuite/TestTairZsetTestSuite + diff --git a/.gitignore b/.gitignore index 204c313..29560eb 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,7 @@ *.ipr *.iws .idea/ - +.vscode # Binaries for programs and plugins *.exe *.exe~ @@ -20,3 +20,4 @@ # Dependency directories (remove the comment below to include it) # vendor/ +main_test.go diff --git a/go.mod b/go.mod index 0e83d32..16f9bbf 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,8 @@ go 1.17 require ( github.com/go-redis/redis/v8 v8.11.5 + github.com/onsi/ginkgo v1.16.5 + github.com/onsi/gomega v1.18.1 github.com/stretchr/testify v1.8.0 ) @@ -11,7 +13,13 @@ require ( github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/fsnotify/fsnotify v1.4.9 // indirect + github.com/nxadm/tail v1.4.8 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect + golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect + golang.org/x/text v0.3.7 // indirect + gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 3b670f5..b524045 100644 --- a/go.sum +++ b/go.sum @@ -22,6 +22,7 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -38,6 +39,7 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108 github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.0.0 h1:CcuG/HvWNkkaqCUpJifQY8z7qEMBJya6aLPx6ftGyjQ= github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= @@ -104,6 +106,7 @@ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miE google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/tair/main_test.go b/tair/main_test.go index fb51528..a18a0b0 100644 --- a/tair/main_test.go +++ b/tair/main_test.go @@ -61,8 +61,8 @@ func redisOptions() *redis.Options { DialTimeout: 10 * time.Second, ReadTimeout: 30 * time.Second, WriteTimeout: 30 * time.Second, - - MaxRetries: -1, + Password: "xxx", + MaxRetries: -1, PoolSize: 10, PoolTimeout: 30 * time.Second, diff --git a/tair/taircommands.go b/tair/taircommands.go index b2a41d3..9295efa 100644 --- a/tair/taircommands.go +++ b/tair/taircommands.go @@ -94,4 +94,35 @@ type TairCmdable interface { ExHVals(ctx context.Context, key string) *redis.StringSliceCmd ExHGetAll(ctx context.Context, key string) *redis.StringStringMapCmd ExHScan(ctx context.Context, key string, cursor string) *redis.SliceCmd + + // TairRoaring + TrSetBit(ctx context.Context, key string, offset int64, value int64) *redis.IntCmd + TrSetBits(ctx context.Context, key string, fields ...int64) *redis.IntCmd + TrGetBit(ctx context.Context, key string, offset int64) *redis.IntCmd + TrGetBits(ctx context.Context, key string, fields ...int64) *redis.IntSliceCmd + TrClearBits(ctx context.Context, key string, fields ...int64) *redis.IntCmd + TrRange(ctx context.Context, key string, start int64, end int64) *redis.IntSliceCmd + TrRangeBitArray(ctx context.Context, key string, start int64, end int64) *redis.StringCmd + TrAppendBitArray(ctx context.Context, key string, offset int64, value string) *redis.IntCmd + TrSetRange(ctx context.Context, key string, start int64, end int64) *redis.IntCmd + TrFlipRange(ctx context.Context, key string, start int64, end string) *redis.IntCmd + TrBitCount(ctx context.Context, key string) *redis.IntCmd + TrBitCountRange(ctx context.Context, key string, start int64, end int64) *redis.IntCmd + TrMin(ctx context.Context, key string) *redis.IntCmd + TrMax(ctx context.Context, key string) *redis.IntCmd + TrOptimize(ctx context.Context, key string) *redis.StringCmd + TrStat(ctx context.Context, key string, json bool) *redis.StringCmd + TrBitPosCount(ctx context.Context, key string, value int64, count int64) *redis.IntCmd + TrBitPos(ctx context.Context, key string, value int64) *redis.IntCmd + TrRank(ctx context.Context, key string, offset int64) *redis.IntCmd + TrBitOp(ctx context.Context, destKey string, operation string, keys ...string) *redis.IntCmd + TrBitOpCard(ctx context.Context, operation string, keys ...string) *redis.IntCmd + TrScanCount(ctx context.Context, key string, cursor int64, count int64) *redis.SliceCmd + TrScan(ctx context.Context, key string, cursor int64) *redis.SliceCmd + TrDiff(ctx context.Context, destKey, key1, key2 string) *redis.StringCmd + TrSetIntArray(ctx context.Context, key string, fields ...int64) *redis.StringCmd + TrAppendIntArray(ctx context.Context, key string, fields ...int64) *redis.StringCmd + TrSetBitArray(ctx context.Context, key, value string) *redis.FloatCmd + TrJaccard(ctx context.Context, key1, key2 string) *redis.FloatCmd + TrContains(ctx context.Context, key1, key2 string) *redis.BoolCmd } diff --git a/tair/tairroaring.go b/tair/tairroaring.go new file mode 100644 index 0000000..3fb5c50 --- /dev/null +++ b/tair/tairroaring.go @@ -0,0 +1,318 @@ +package tair + +import ( + "context" + "github.com/go-redis/redis/v8" +) + +func (tc tairCmdable) TrSetBit(ctx context.Context, key string, offset int64, value int64) *redis.IntCmd { + a := make([]interface{}, 4) + a[0] = "tr.setbit" + a[1] = key + a[2] = offset + a[3] = value + cmd := redis.NewIntCmd(ctx, a...) + _ = tc(ctx, cmd) + return cmd +} + +func (tc tairCmdable) TrSetBits(ctx context.Context, key string, fields ...int64) *redis.IntCmd { + a := make([]interface{}, 2) + a[0] = "tr.setbits" + a[1] = key + for _, f := range fields { + a = append(a, f) + } + cmd := redis.NewIntCmd(ctx, a...) + _ = tc(ctx, cmd) + return cmd +} +func (tc tairCmdable) TrGetBit(ctx context.Context, key string, offset int64) *redis.IntCmd { + a := make([]interface{}, 3) + a[0] = "tr.getbit" + a[1] = key + a[2] = offset + cmd := redis.NewIntCmd(ctx, a...) + _ = tc(ctx, cmd) + return cmd +} + +func (tc tairCmdable) TrGetBits(ctx context.Context, key string, fields ...int64) *redis.IntSliceCmd { + a := make([]interface{}, 2) + a[0] = "tr.getbits" + a[1] = key + for _, f := range fields { + a = append(a, f) + } + cmd := redis.NewIntSliceCmd(ctx, a...) + _ = tc(ctx, cmd) + return cmd +} + +func (tc tairCmdable) TrClearBits(ctx context.Context, key string, fields ...int64) *redis.IntCmd { + a := make([]interface{}, 2) + a[0] = "tr.clearbits" + a[1] = key + for _, f := range fields { + a = append(a, f) + } + cmd := redis.NewIntCmd(ctx, a...) + _ = tc(ctx, cmd) + return cmd +} + +func (tc tairCmdable) TrRange(ctx context.Context, key string, start int64, end int64) *redis.IntSliceCmd { + a := make([]interface{}, 4) + a[0] = "tr.range" + a[1] = key + a[2] = start + a[3] = end + cmd := redis.NewIntSliceCmd(ctx, a...) + _ = tc(ctx, cmd) + return cmd +} + +func (tc tairCmdable) TrRangeBitArray(ctx context.Context, key string, start int64, end int64) *redis.StringCmd { + a := make([]interface{}, 4) + a[0] = "tr.rangebitarray" + a[1] = key + a[2] = start + a[3] = end + cmd := redis.NewStringCmd(ctx, a...) + _ = tc(ctx, cmd) + return cmd +} + +func (tc tairCmdable) TrAppendBitArray(ctx context.Context, key string, offset int64, value string) *redis.IntCmd { + a := make([]interface{}, 4) + a[0] = "tr.appendbitarray" + a[1] = key + a[2] = offset + a[3] = value + cmd := redis.NewIntCmd(ctx, a...) + _ = tc(ctx, cmd) + return cmd +} + +func (tc tairCmdable) TrSetRange(ctx context.Context, key string, start int64, end int64) *redis.IntCmd { + a := make([]interface{}, 4) + a[0] = "tr.setrange" + a[1] = key + a[2] = start + a[3] = end + cmd := redis.NewIntCmd(ctx, a...) + _ = tc(ctx, cmd) + return cmd +} + +func (tc tairCmdable) TrFlipRange(ctx context.Context, key string, start int64, end string) *redis.IntCmd { + a := make([]interface{}, 4) + a[0] = "tr.fliprange" + a[1] = key + a[2] = start + a[3] = end + cmd := redis.NewIntCmd(ctx, a...) + _ = tc(ctx, cmd) + return cmd +} + +func (tc tairCmdable) TrBitCount(ctx context.Context, key string) *redis.IntCmd { + a := make([]interface{}, 2) + a[0] = "tr.bitcount" + a[1] = key + cmd := redis.NewIntCmd(ctx, a...) + _ = tc(ctx, cmd) + return cmd +} + +func (tc tairCmdable) TrBitCountRange(ctx context.Context, key string, start int64, end int64) *redis.IntCmd { + a := make([]interface{}, 4) + a[0] = "tr.bitcount" + a[1] = key + a[2] = start + a[3] = end + cmd := redis.NewIntCmd(ctx, a...) + _ = tc(ctx, cmd) + return cmd +} + +func (tc tairCmdable) TrMin(ctx context.Context, key string) *redis.IntCmd { + a := make([]interface{}, 2) + a[0] = "tr.min" + a[1] = key + cmd := redis.NewIntCmd(ctx, a...) + _ = tc(ctx, cmd) + return cmd +} + +func (tc tairCmdable) TrMax(ctx context.Context, key string) *redis.IntCmd { + a := make([]interface{}, 2) + a[0] = "tr.max" + a[1] = key + cmd := redis.NewIntCmd(ctx, a...) + _ = tc(ctx, cmd) + return cmd +} + +func (tc tairCmdable) TrOptimize(ctx context.Context, key string) *redis.StringCmd { + a := make([]interface{}, 2) + a[0] = "tr.optimize" + a[1] = key + cmd := redis.NewStringCmd(ctx, a...) + _ = tc(ctx, cmd) + return cmd +} + +func (tc tairCmdable) TrStat(ctx context.Context, key string, json bool) *redis.StringCmd { + a := make([]interface{}, 2) + a[0] = "tr.stat" + a[1] = key + if json { + a = append(a, "JSON") + } + cmd := redis.NewStringCmd(ctx, a...) + _ = tc(ctx, cmd) + return cmd +} +func (tc tairCmdable) TrBitPosCount(ctx context.Context, key string, value int64, count int64) *redis.IntCmd { + a := make([]interface{}, 4) + a[0] = "tr.bitpos" + a[1] = key + a[2] = value + a[3] = count + cmd := redis.NewIntCmd(ctx, a...) + _ = tc(ctx, cmd) + return cmd +} + +func (tc tairCmdable) TrBitPos(ctx context.Context, key string, value int64) *redis.IntCmd { + a := make([]interface{}, 3) + a[0] = "tr.bitpos" + a[1] = key + a[2] = value + cmd := redis.NewIntCmd(ctx, a...) + _ = tc(ctx, cmd) + return cmd +} + +func (tc tairCmdable) TrRank(ctx context.Context, key string, offset int64) *redis.IntCmd { + a := make([]interface{}, 3) + a[0] = "tr.rank" + a[1] = key + a[2] = offset + cmd := redis.NewIntCmd(ctx, a...) + _ = tc(ctx, cmd) + return cmd +} + +func (tc tairCmdable) TrBitOp(ctx context.Context, destKey string, operation string, keys ...string) *redis.IntCmd { + a := make([]interface{}, 3) + a[0] = "tr.bitop" + a[1] = destKey + a[2] = operation + for _, k := range keys { + a = append(a, k) + } + cmd := redis.NewIntCmd(ctx, a...) + _ = tc(ctx, cmd) + return cmd +} + +func (tc tairCmdable) TrBitOpCard(ctx context.Context, operation string, keys ...string) *redis.IntCmd { + a := make([]interface{}, 2) + a[0] = "tr.bitopcard" + a[1] = operation + for _, k := range keys { + a = append(a, k) + } + cmd := redis.NewIntCmd(ctx, a...) + _ = tc(ctx, cmd) + return cmd +} + +func (tc tairCmdable) TrScanCount(ctx context.Context, key string, cursor int64, count int64) *redis.SliceCmd { + a := make([]interface{}, 5) + a[0] = "tr.scan" + a[1] = key + a[2] = cursor + a[3] = "COUNT" + a[4] = count + cmd := redis.NewSliceCmd(ctx, a...) + _ = tc(ctx, cmd) + return cmd +} + +func (tc tairCmdable) TrScan(ctx context.Context, key string, cursor int64) *redis.SliceCmd { + a := make([]interface{}, 3) + a[0] = "tr.scan" + a[1] = key + a[2] = cursor + cmd := redis.NewSliceCmd(ctx, a...) + _ = tc(ctx, cmd) + return cmd +} + +func (tc tairCmdable) TrDiff(ctx context.Context, destKey, key1, key2 string) *redis.StringCmd { + a := make([]interface{}, 4) + a[0] = "tr.diff" + a[1] = destKey + a[2] = key1 + a[3] = key2 + cmd := redis.NewStringCmd(ctx, a...) + _ = tc(ctx, cmd) + return cmd +} + +func (tc tairCmdable) TrSetIntArray(ctx context.Context, key string, fields ...int64) *redis.StringCmd { + a := make([]interface{}, 4) + a[0] = "tr.setintarray" + a[1] = key + for _, f := range fields { + a = append(a, f) + } + cmd := redis.NewStringCmd(ctx, a...) + _ = tc(ctx, cmd) + return cmd +} + +func (tc tairCmdable) TrAppendIntArray(ctx context.Context, key string, fields ...int64) *redis.StringCmd { + a := make([]interface{}, 2) + a[0] = "tr.appendintarray" + a[1] = key + for _, f := range fields { + a = append(a, f) + } + cmd := redis.NewStringCmd(ctx, a...) + _ = tc(ctx, cmd) + return cmd +} + +func (tc tairCmdable) TrSetBitArray(ctx context.Context, key, value string) *redis.FloatCmd { + a := make([]interface{}, 4) + a[0] = "tr.setbitarray" + a[1] = key + a[2] = value + cmd := redis.NewFloatCmd(ctx, a...) + _ = tc(ctx, cmd) + return cmd +} + +func (tc tairCmdable) TrJaccard(ctx context.Context, key1, key2 string) *redis.FloatCmd { + a := make([]interface{}, 3) + a[0] = "tr.jaccard" + a[1] = key1 + a[2] = key2 + cmd := redis.NewFloatCmd(ctx, a...) + _ = tc(ctx, cmd) + return cmd +} + +func (tc tairCmdable) TrContains(ctx context.Context, key1, key2 string) *redis.BoolCmd { + a := make([]interface{}, 3) + a[0] = "tr.contains" + a[1] = key1 + a[2] = key2 + cmd := redis.NewBoolCmd(ctx, a...) + _ = tc(ctx, cmd) + return cmd +} diff --git a/tair/tairroaring_test.go b/tair/tairroaring_test.go new file mode 100644 index 0000000..28b34ba --- /dev/null +++ b/tair/tairroaring_test.go @@ -0,0 +1,287 @@ +package tair_test + +import ( + "github.com/alibaba/tair-go/tair" + "github.com/go-redis/redis/v8" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/suite" + "testing" +) + +type TairRoaringTestSuite struct { + suite.Suite + tairClient *tair.TairClient +} + +func (suite *TairRoaringTestSuite) SetupTest() { + suite.tairClient = tair.NewTairClient(redisOptions()) + assert.Equal(suite.T(), "OK", suite.tairClient.FlushDB(ctx).Val()) +} + +func (suite *TairRoaringTestSuite) TearDownTest() { + assert.NoError(suite.T(), suite.tairClient.Close()) +} + +func (suite *TairRoaringTestSuite) TestTrSetBit() { + result, err := suite.tairClient.TrSetBit(ctx, "foo", 10, 1).Result() + assert.NoError(suite.T(), err) + assert.Equal(suite.T(), result, int64(0)) + + result2, err2 := suite.tairClient.TrSetBit(ctx, "foo", 20, 1).Result() + assert.NoError(suite.T(), err2) + assert.Equal(suite.T(), result2, int64(0)) + + result3, err3 := suite.tairClient.TrSetBit(ctx, "foo", 30, 1).Result() + assert.NoError(suite.T(), err3) + assert.Equal(suite.T(), result3, int64(0)) + + result4, err4 := suite.tairClient.TrSetBit(ctx, "foo", 30, 0).Result() + assert.NoError(suite.T(), err4) + assert.Equal(suite.T(), result4, int64(1)) +} + +func (suite *TairRoaringTestSuite) TestSetBitsBitCountClearBits() { + result, err := suite.tairClient.TrSetBits(ctx, "foo", 1, 3, 5, 7, 9).Result() + assert.NoError(suite.T(), err) + assert.Equal(suite.T(), result, int64(5)) + + result1, err1 := suite.tairClient.TrBitCount(ctx, "foo").Result() + assert.NoError(suite.T(), err1) + assert.Equal(suite.T(), result1, int64(5)) + + result2, err2 := suite.tairClient.TrSetBits(ctx, "foo", 5, 7, 9, 11, 13).Result() + assert.NoError(suite.T(), err2) + assert.Equal(suite.T(), result2, int64(7)) + + result5, err5 := suite.tairClient.TrBitCount(ctx, "foo").Result() + assert.NoError(suite.T(), err5) + assert.Equal(suite.T(), result5, int64(7)) + + result3, err3 := suite.tairClient.TrClearBits(ctx, "foo", 5, 6, 7, 8, 9).Result() + assert.NoError(suite.T(), err3) + assert.Equal(suite.T(), result3, int64(3)) + + result7, err7 := suite.tairClient.TrBitCount(ctx, "foo").Result() + assert.NoError(suite.T(), err7) + assert.Equal(suite.T(), result7, int64(4)) + + result8, err8 := suite.tairClient.TrGetBits(ctx, "foo", 1, 2, 3, 4, 5).Result() + assert.NoError(suite.T(), err8) + assert.Equal(suite.T(), result8, []int64{1, 0, 1, 0, 0}) +} + +func (suite *TairRoaringTestSuite) TestTrSetBitsTaRange() { + result, err := suite.tairClient.TrSetBits(ctx, "foo", 1, 3, 5, 7, 9).Result() + assert.NoError(suite.T(), err) + assert.Equal(suite.T(), result, int64(5)) + + result1, err1 := suite.tairClient.TrRange(ctx, "foo", 1, 5).Result() + assert.NoError(suite.T(), err1) + assert.Equal(suite.T(), result1, []int64{1, 3, 5}) + + result3, err3 := suite.tairClient.TrRange(ctx, "foo", 0, 4).Result() + assert.NoError(suite.T(), err3) + assert.Equal(suite.T(), result3, []int64{1, 3}) +} + +func (suite *TairRoaringTestSuite) TestTrRange() { + suite.tairClient.TrSetBits(ctx, "foo", 1, 3, 5, 7, 9) + result, err := suite.tairClient.TrRange(ctx, "foo", 1, 5).Result() + assert.NoError(suite.T(), err) + assert.Equal(suite.T(), result, []int64{1, 3, 5}) + result1, err1 := suite.tairClient.TrRange(ctx, "foo", 0, 4).Result() + assert.NoError(suite.T(), err1) + assert.Equal(suite.T(), result1, []int64{1, 3}) +} + +func (suite *TairRoaringTestSuite) TestAppendBitArray() { + result, err := suite.tairClient.TrAppendBitArray(ctx, "foo", 0, "101010101").Result() + assert.NoError(suite.T(), err) + assert.Equal(suite.T(), result, int64(5)) + + result1, err1 := suite.tairClient.TrRange(ctx, "foo", 0, 10).Result() + assert.NoError(suite.T(), err1) + assert.Equal(suite.T(), result1, []int64{1, 3, 5, 7, 9}) + + suite.tairClient.Del(ctx, "foo") + result2, err2 := suite.tairClient.TrAppendBitArray(ctx, "foo", -1, "101010101").Result() + assert.NoError(suite.T(), err2) + assert.Equal(suite.T(), result2, int64(5)) + result3, err3 := suite.tairClient.TrRange(ctx, "foo", 0, 10).Result() + assert.NoError(suite.T(), err3) + assert.Equal(suite.T(), result3, []int64{0, 2, 4, 6, 8}) +} + +func (suite *TairRoaringTestSuite) TestScanCount() { + result1, err1 := suite.tairClient.TrScan(ctx, "no-key", 0).Result() + assert.NoError(suite.T(), err1) + assert.Equal(suite.T(), result1[0], int64(0)) + assert.Equal(suite.T(), result1[1], make([]interface{}, 0)) + + result2, err2 := suite.tairClient.TrSetBits(ctx, "foo", 1, 3, 5, 7, 9).Result() + assert.NoError(suite.T(), err2) + assert.Equal(suite.T(), result2, int64(5)) + + result3, err3 := suite.tairClient.TrScan(ctx, "foo", 0).Result() + assert.NoError(suite.T(), err3) + assert.Equal(suite.T(), result3[0], int64(0)) + assert.Equal(suite.T(), result3[1], append(make([]interface{}, 0), int64(1), int64(3), int64(5), int64(7), int64(9))) + + result4, err4 := suite.tairClient.TrScanCount(ctx, "foo", 4, 2).Result() + assert.NoError(suite.T(), err4) + assert.Equal(suite.T(), result4[0], int64(9)) + assert.Equal(suite.T(), result4[1], append(make([]interface{}, 0), int64(5), int64(7))) +} + +func (suite *TairRoaringTestSuite) TestStatus() { + result, err := suite.tairClient.TrSetBits(ctx, "foo", 1, 2, 3, 4, 5, 6, 7, 8, 9).Result() + assert.NoError(suite.T(), err) + assert.Equal(suite.T(), result, int64(9)) + + result2, err2 := suite.tairClient.TrOptimize(ctx, "foo").Result() + assert.NoError(suite.T(), err2) + assert.Equal(suite.T(), result2, "OK") + + result3, err3 := suite.tairClient.TrBitCount(ctx, "foo").Result() + assert.NoError(suite.T(), err3) + assert.Equal(suite.T(), result3, int64(9)) + + result4, err4 := suite.tairClient.TrBitCountRange(ctx, "foo", 0, 5).Result() + assert.NoError(suite.T(), err4) + assert.Equal(suite.T(), result4, int64(5)) + + result5, err5 := suite.tairClient.TrBitCountRange(ctx, "foo", 9, 20).Result() + assert.NoError(suite.T(), err5) + assert.Equal(suite.T(), result5, int64(1)) + + result6, err6 := suite.tairClient.TrBitPos(ctx, "foo", 1).Result() + assert.NoError(suite.T(), err6) + assert.Equal(suite.T(), result6, int64(1)) + + result7, err7 := suite.tairClient.TrBitPos(ctx, "foo", 1).Result() + assert.NoError(suite.T(), err7) + assert.Equal(suite.T(), result7, int64(1)) + + result8, err8 := suite.tairClient.TrBitPosCount(ctx, "foo", 1, 2).Result() + assert.NoError(suite.T(), err8) + assert.Equal(suite.T(), result8, int64(2)) + + result9, err9 := suite.tairClient.TrBitPosCount(ctx, "foo", 1, -4).Result() + assert.NoError(suite.T(), err9) + assert.Equal(suite.T(), result9, int64(6)) + + result10, err10 := suite.tairClient.TrBitPosCount(ctx, "foo", 0, 1).Result() + assert.NoError(suite.T(), err10) + assert.Equal(suite.T(), result10, int64(0)) + + result11, err11 := suite.tairClient.TrStat(ctx, "foo", false).Result() + assert.NoError(suite.T(), err11) + assert.Equal(suite.T(), result11, "cardinality: 9\r\n"+ + "number of containers: 1\r\n"+ + "max value: 9\r\n"+ + "min value: 1\r\n"+ + "sum value: 45\r\n"+ + "number of array containers: 0\r\n"+ + "\tarray container values: 0\r\n"+ + "\tarray container bytes: 0\r\n"+ + "number of bitset containers: 0\r\n"+ + "\tbitset container values: 0\r\n"+ + "\tbitset container bytes: 0\r\n"+ + "number of run containers: 1\r\n"+ + "\trun container values: 9\r\n"+ + "\trun container bytes: 6\r\n") +} + +func (suite *TairRoaringTestSuite) TestEmptyKey() { + result, err := suite.tairClient.TrRange(ctx, "foo", 0, 4).Result() + assert.NoError(suite.T(), err) + assert.Equal(suite.T(), result, []int64{}) + + result1, err1 := suite.tairClient.TrMin(ctx, "foo").Result() + assert.NoError(suite.T(), err1) + assert.Equal(suite.T(), result1, int64(-1)) + + result2, err2 := suite.tairClient.TrMax(ctx, "foo").Result() + assert.NoError(suite.T(), err2) + assert.Equal(suite.T(), result2, int64(-1)) + + result3, err3 := suite.tairClient.TrRank(ctx, "foo", 1).Result() + assert.NoError(suite.T(), err3) + assert.Equal(suite.T(), result3, int64(-1)) + + _, err4 := suite.tairClient.TrStat(ctx, "foo", false).Result() + assert.Equal(suite.T(), err4, redis.Nil) + + _, err5 := suite.tairClient.TrOptimize(ctx, "foo").Result() + assert.Equal(suite.T(), err5, redis.Nil) + + result6, err6 := suite.tairClient.TrBitCount(ctx, "foo").Result() + assert.NoError(suite.T(), err6) + assert.Equal(suite.T(), result6, int64(0)) + + result7, err7 := suite.tairClient.TrClearBits(ctx, "foo", 1, 3, 5).Result() + assert.NoError(suite.T(), err7) + assert.Equal(suite.T(), result7, int64(0)) +} + +func (suite *TairRoaringTestSuite) TestBitOpTest() { + result, err := suite.tairClient.TrAppendIntArray(ctx, "foo", 1, 3, 5, 7, 9).Result() + assert.NoError(suite.T(), err) + assert.Equal(suite.T(), result, "OK") + + result1, err1 := suite.tairClient.TrAppendIntArray(ctx, "bar", 2, 4, 6, 8, 10).Result() + assert.NoError(suite.T(), err1) + assert.Equal(suite.T(), result1, "OK") + + result2, err2 := suite.tairClient.TrBitOp(ctx, "dest", "OR", "foo", "bar").Result() + assert.NoError(suite.T(), err2) + assert.Equal(suite.T(), result2, int64(10)) + + result3, err3 := suite.tairClient.TrBitOpCard(ctx, "AND", "foo", "bar").Result() + assert.NoError(suite.T(), err3) + assert.Equal(suite.T(), result3, int64(0)) +} + +func (suite *TairRoaringTestSuite) TestGetMany() { + result, err := suite.tairClient.TrAppendIntArray(ctx, "foo", 1, 3, 5, 7, 9, 11, 13, 15, 17, 19).Result() + assert.NoError(suite.T(), err) + assert.Equal(suite.T(), result, "OK") + + result1, err1 := suite.tairClient.TrRange(ctx, "foo", 0, 4).Result() + assert.NoError(suite.T(), err1) + assert.Equal(suite.T(), result1, []int64{1, 3}) +} + +func (suite *TairRoaringTestSuite) TestMultiKey() { + result, err := suite.tairClient.TrSetBits(ctx, "foo", 1, 3, 5, 7, 9).Result() + assert.NoError(suite.T(), err) + assert.Equal(suite.T(), result, int64(5)) + + result1, err1 := suite.tairClient.TrSetBits(ctx, "bar", 2, 4, 6, 8, 10).Result() + assert.NoError(suite.T(), err1) + assert.Equal(suite.T(), result1, int64(5)) + + result2, err2 := suite.tairClient.TrSetRange(ctx, "baz", 1, 10).Result() + assert.NoError(suite.T(), err2) + assert.Equal(suite.T(), result2, int64(10)) + + result3, err3 := suite.tairClient.TrContains(ctx, "foo", "bar").Result() + assert.NoError(suite.T(), err3) + assert.Equal(suite.T(), result3, false) + + result4, err4 := suite.tairClient.TrContains(ctx, "foo", "baz").Result() + assert.NoError(suite.T(), err4) + assert.Equal(suite.T(), result4, true) + + result5, err5 := suite.tairClient.TrJaccard(ctx, "foo", "baz").Result() + assert.NoError(suite.T(), err5) + assert.Equal(suite.T(), result5, 0.5) + + result6, err6 := suite.tairClient.TrDiff(ctx, "result", "foo", "bar").Result() + assert.NoError(suite.T(), err6) + assert.Equal(suite.T(), result6, "OK") +} + +func TestTairRoaringTestSuite(t *testing.T) { + suite.Run(t, new(TairRoaringTestSuite)) +}