diff --git a/.github/workflows/pika.yml b/.github/workflows/pika.yml index f7fd4deac4..291df582f2 100644 --- a/.github/workflows/pika.yml +++ b/.github/workflows/pika.yml @@ -68,12 +68,6 @@ jobs: chmod +x ../tests/integration/start_master_and_slave.sh ../tests/integration/start_master_and_slave.sh - - name: Run Python E2E Tests - working-directory: ${{ github.workspace }}/build - run: | - python3 ../tests/integration/pika_replication_test.py - python3 ../tests/unit/Blpop_Brpop_test.py - - name: Run Go E2E Tests working-directory: ${{ github.workspace }}/build run: | @@ -81,6 +75,7 @@ jobs: chmod +x integrate_test.sh sh integrate_test.sh + build_on_centos: runs-on: ubuntu-latest container: @@ -89,7 +84,7 @@ jobs: steps: - name: Install deps run: | - yum install -y wget git autoconf centos-release-scl + yum install -y wget git autoconf centos-release-scl gcc yum install -y devtoolset-10-gcc devtoolset-10-gcc-c++ devtoolset-10-make devtoolset-10-bin-util yum install -y llvm-toolset-7 llvm-toolset-7-clang tcl which python3 python3 -m pip install --upgrade pip @@ -134,11 +129,12 @@ jobs: chmod +x ../tests/integration/start_master_and_slave.sh ../tests/integration/start_master_and_slave.sh - - name: Run Python E2E Tests + - name: Run Go E2E Tests working-directory: ${{ github.workspace }}/build run: | - python3 ../tests/integration/pika_replication_test.py - python3 ../tests/unit/Blpop_Brpop_test.py + cd ../tests/integration/ + chmod +x integrate_test.sh + sh integrate_test.sh build_on_macos: runs-on: macos-latest @@ -193,12 +189,6 @@ jobs: chmod +x ../tests/integration/start_master_and_slave.sh ../tests/integration/start_master_and_slave.sh - - name: Run Python E2E Tests - working-directory: ${{ github.workspace }}/build - run: | - python3 ../tests/integration/pika_replication_test.py - python3 ../tests/unit/Blpop_Brpop_test.py - - name: Run Go E2E Tests working-directory: ${{ github.workspace }}/build run: | diff --git a/tests/integration/csanning_test.go b/tests/integration/csanning_test.go index cfd7d16a09..43c5e59b29 100644 --- a/tests/integration/csanning_test.go +++ b/tests/integration/csanning_test.go @@ -3,6 +3,7 @@ package pika_integration import ( "context" "fmt" + "time" . "github.com/bsm/ginkgo/v2" . "github.com/bsm/gomega" @@ -16,6 +17,7 @@ var _ = Describe("Csanning Commands", func() { BeforeEach(func() { client = redis.NewClient(pikaOptions1()) Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred()) + time.Sleep(1 * time.Second) }) AfterEach(func() { diff --git a/tests/integration/geo_test.go b/tests/integration/geo_test.go index 8d3fc403ed..c08a845154 100644 --- a/tests/integration/geo_test.go +++ b/tests/integration/geo_test.go @@ -2,6 +2,7 @@ package pika_integration import ( "context" + "time" . "github.com/bsm/ginkgo/v2" . "github.com/bsm/gomega" @@ -15,6 +16,7 @@ var _ = Describe("Geo Commands", func() { BeforeEach(func() { client = redis.NewClient(pikaOptions1()) Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred()) + time.Sleep(1 * time.Second) }) AfterEach(func() { @@ -43,15 +45,14 @@ var _ = Describe("Geo Commands", func() { Expect(geoAdd.Val()).To(Equal(int64(0))) }) - //It("should search geo radius", func() { - // res, err := client.GeoRadius(ctx, "Sicily", 15, 37, &redis.GeoRadiusQuery{ - // Radius: 200, - // }).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(res).To(HaveLen(2)) - // Expect(res[0].Name).To(Equal("Palermo")) - // Expect(res[1].Name).To(Equal("Catania")) - //}) + It("should search geo radius", func() { + res := client.Do(ctx, "GEORADIUS", "Sicily", 15, 37, 200, "km", "WITHDIST", "WITHCOORD") + //res, err := client.GeoRadius(ctx, "Sicily", 15, 37, &redis.GeoRadiusQuery{ + // Radius: 200, + //}).Result() + Expect(res.Err()).NotTo(HaveOccurred()) + Expect(res.Val()).To(HaveLen(2)) + }) It("should geo radius and store the result", func() { n, err := client.GeoRadiusStore(ctx, "Sicily", 15, 37, &redis.GeoRadiusQuery{ @@ -93,89 +94,6 @@ var _ = Describe("Geo Commands", func() { })) }) - //It("should search geo radius with options", func() { - // res, err := client.GeoRadius(ctx, "Sicily", 15, 37, &redis.GeoRadiusQuery{ - // Radius: 200, - // Unit: "km", - // WithGeoHash: true, - // WithCoord: true, - // WithDist: true, - // Count: 2, - // Sort: "ASC", - // }).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(res).To(HaveLen(2)) - // Expect(res[1].Name).To(Equal("Palermo")) - // Expect(res[1].Dist).To(Equal(190.4424)) - // Expect(res[1].GeoHash).To(Equal(int64(3479099956230698))) - // Expect(res[1].Longitude).To(Equal(13.361389338970184)) - // Expect(res[1].Latitude).To(Equal(38.115556395496299)) - // Expect(res[0].Name).To(Equal("Catania")) - // Expect(res[0].Dist).To(Equal(56.4413)) - // Expect(res[0].GeoHash).To(Equal(int64(3479447370796909))) - // Expect(res[0].Longitude).To(Equal(15.087267458438873)) - // Expect(res[0].Latitude).To(Equal(37.50266842333162)) - //}) - - //It("should search geo radius with WithDist=false", func() { - // res, err := client.GeoRadius(ctx, "Sicily", 15, 37, &redis.GeoRadiusQuery{ - // Radius: 200, - // Unit: "km", - // WithGeoHash: true, - // WithCoord: true, - // Count: 2, - // Sort: "ASC", - // }).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(res).To(HaveLen(2)) - // Expect(res[1].Name).To(Equal("Palermo")) - // Expect(res[1].Dist).To(Equal(float64(0))) - // Expect(res[1].GeoHash).To(Equal(int64(3479099956230698))) - // Expect(res[1].Longitude).To(Equal(13.361389338970184)) - // Expect(res[1].Latitude).To(Equal(38.115556395496299)) - // Expect(res[0].Name).To(Equal("Catania")) - // Expect(res[0].Dist).To(Equal(float64(0))) - // Expect(res[0].GeoHash).To(Equal(int64(3479447370796909))) - // Expect(res[0].Longitude).To(Equal(15.087267458438873)) - // Expect(res[0].Latitude).To(Equal(37.50266842333162)) - //}) - - //It("should search geo radius by member with options", func() { - // res, err := client.GeoRadiusByMember(ctx, "Sicily", "Catania", &redis.GeoRadiusQuery{ - // Radius: 200, - // Unit: "km", - // WithGeoHash: true, - // WithCoord: true, - // WithDist: true, - // Count: 2, - // Sort: "ASC", - // }).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(res).To(HaveLen(2)) - // Expect(res[0].Name).To(Equal("Catania")) - // Expect(res[0].Dist).To(Equal(0.0)) - // Expect(res[0].GeoHash).To(Equal(int64(3479447370796909))) - // Expect(res[0].Longitude).To(Equal(15.087267458438873)) - // Expect(res[0].Latitude).To(Equal(37.50266842333162)) - // Expect(res[1].Name).To(Equal("Palermo")) - // Expect(res[1].Dist).To(Equal(166.2742)) - // Expect(res[1].GeoHash).To(Equal(int64(3479099956230698))) - // Expect(res[1].Longitude).To(Equal(13.361389338970184)) - // Expect(res[1].Latitude).To(Equal(38.115556395496299)) - //}) - - //It("should search geo radius with no results", func() { - // res, err := client.GeoRadius(ctx, "Sicily", 99, 37, &redis.GeoRadiusQuery{ - // Radius: 200, - // Unit: "km", - // WithGeoHash: true, - // WithCoord: true, - // WithDist: true, - // }).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(res).To(HaveLen(0)) - //}) - It("should get geo distance with unit options", func() { // From Redis CLI, note the difference in rounding in m vs // km on Redis itself. @@ -194,11 +112,11 @@ var _ = Describe("Geo Commands", func() { Expect(dist).To(BeNumerically("~", 166274.15, 0.01)) }) -// It("should get geo hash in string representation", func() { -// hashes, err := client.GeoHash(ctx, "Sicily", "Palermo", "Catania").Result() -// Expect(err).NotTo(HaveOccurred()) -// Expect(hashes).To(ConsistOf([]string{"sqc8b49rny0", "sqdtr74hyu0"})) -// }) + //It("should get geo hash in string representation", func() { + // hashes, err := client.GeoHash(ctx, "Sicily", "Palermo", "Catania").Result() + // Expect(err).NotTo(HaveOccurred()) + // Expect(hashes).To(ConsistOf([]string{"sqc8b49rny0", "sqdtr74hyu0"})) + //}) It("should return geo position", func() { pos, err := client.GeoPos(ctx, "Sicily", "Palermo", "Catania", "NonExisting").Result() @@ -216,202 +134,202 @@ var _ = Describe("Geo Commands", func() { })) }) - //It("should geo search", func() { - // q := &redis.GeoSearchQuery{ - // Member: "Catania", - // BoxWidth: 400, - // BoxHeight: 100, - // BoxUnit: "km", - // Sort: "asc", - // } - // val, err := client.GeoSearch(ctx, "Sicily", q).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(val).To(Equal([]string{"Catania"})) - // - // q.BoxHeight = 400 - // val, err = client.GeoSearch(ctx, "Sicily", q).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(val).To(Equal([]string{"Catania", "Palermo"})) - // - // q.Count = 1 - // val, err = client.GeoSearch(ctx, "Sicily", q).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(val).To(Equal([]string{"Catania"})) - // - // q.CountAny = true - // val, err = client.GeoSearch(ctx, "Sicily", q).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(val).To(Equal([]string{"Palermo"})) - // - // q = &redis.GeoSearchQuery{ - // Member: "Catania", - // Radius: 100, - // RadiusUnit: "km", - // Sort: "asc", - // } - // val, err = client.GeoSearch(ctx, "Sicily", q).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(val).To(Equal([]string{"Catania"})) - // - // q.Radius = 400 - // val, err = client.GeoSearch(ctx, "Sicily", q).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(val).To(Equal([]string{"Catania", "Palermo"})) - // - // q.Count = 1 - // val, err = client.GeoSearch(ctx, "Sicily", q).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(val).To(Equal([]string{"Catania"})) - // - // q.CountAny = true - // val, err = client.GeoSearch(ctx, "Sicily", q).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(val).To(Equal([]string{"Palermo"})) - // - // q = &redis.GeoSearchQuery{ - // Longitude: 15, - // Latitude: 37, - // BoxWidth: 200, - // BoxHeight: 200, - // BoxUnit: "km", - // Sort: "asc", - // } - // val, err = client.GeoSearch(ctx, "Sicily", q).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(val).To(Equal([]string{"Catania"})) - // - // q.BoxWidth, q.BoxHeight = 400, 400 - // val, err = client.GeoSearch(ctx, "Sicily", q).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(val).To(Equal([]string{"Catania", "Palermo"})) - // - // q.Count = 1 - // val, err = client.GeoSearch(ctx, "Sicily", q).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(val).To(Equal([]string{"Catania"})) - // - // q.CountAny = true - // val, err = client.GeoSearch(ctx, "Sicily", q).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(val).To(Equal([]string{"Palermo"})) - // - // q = &redis.GeoSearchQuery{ - // Longitude: 15, - // Latitude: 37, - // Radius: 100, - // RadiusUnit: "km", - // Sort: "asc", - // } - // val, err = client.GeoSearch(ctx, "Sicily", q).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(val).To(Equal([]string{"Catania"})) - // - // q.Radius = 200 - // val, err = client.GeoSearch(ctx, "Sicily", q).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(val).To(Equal([]string{"Catania", "Palermo"})) - // - // q.Count = 1 - // val, err = client.GeoSearch(ctx, "Sicily", q).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(val).To(Equal([]string{"Catania"})) - // - // q.CountAny = true - // val, err = client.GeoSearch(ctx, "Sicily", q).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(val).To(Equal([]string{"Palermo"})) - //}) - // - //It("should geo search with options", func() { - // q := &redis.GeoSearchLocationQuery{ - // GeoSearchQuery: redis.GeoSearchQuery{ - // Longitude: 15, - // Latitude: 37, - // Radius: 200, - // RadiusUnit: "km", - // Sort: "asc", - // }, - // WithHash: true, - // WithDist: true, - // WithCoord: true, - // } - // val, err := client.GeoSearchLocation(ctx, "Sicily", q).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(val).To(Equal([]redis.GeoLocation{ - // { - // Name: "Catania", - // Longitude: 15.08726745843887329, - // Latitude: 37.50266842333162032, - // Dist: 56.4413, - // GeoHash: 3479447370796909, - // }, - // { - // Name: "Palermo", - // Longitude: 13.36138933897018433, - // Latitude: 38.11555639549629859, - // Dist: 190.4424, - // GeoHash: 3479099956230698, - // }, - // })) - //}) + PIt("should geo search", func() { + q := &redis.GeoSearchQuery{ + Member: "Catania", + BoxWidth: 400, + BoxHeight: 100, + BoxUnit: "km", + Sort: "asc", + } + val, err := client.GeoSearch(ctx, "Sicily", q).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]string{"Catania"})) - //It("should geo search store", func() { - // q := &redis.GeoSearchStoreQuery{ - // GeoSearchQuery: redis.GeoSearchQuery{ - // Longitude: 15, - // Latitude: 37, - // Radius: 200, - // RadiusUnit: "km", - // Sort: "asc", - // }, - // StoreDist: false, - // } - // - // val, err := client.GeoSearchStore(ctx, "Sicily", "key1", q).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(val).To(Equal(int64(2))) - // - // q.StoreDist = true - // val, err = client.GeoSearchStore(ctx, "Sicily", "key2", q).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(val).To(Equal(int64(2))) - // - // loc, err := client.GeoSearchLocation(ctx, "key1", &redis.GeoSearchLocationQuery{ - // GeoSearchQuery: q.GeoSearchQuery, - // WithCoord: true, - // WithDist: true, - // WithHash: true, - // }).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(loc).To(Equal([]redis.GeoLocation{ - // { - // Name: "Catania", - // Longitude: 15.08726745843887329, - // Latitude: 37.50266842333162032, - // Dist: 56.4413, - // GeoHash: 3479447370796909, - // }, - // { - // Name: "Palermo", - // Longitude: 13.36138933897018433, - // Latitude: 38.11555639549629859, - // Dist: 190.4424, - // GeoHash: 3479099956230698, - // }, - // })) - // - // v, err := client.ZRangeWithScores(ctx, "key2", 0, -1).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(v).To(Equal([]redis.Z{ - // { - // Score: 56.441257870158204, - // Member: "Catania", - // }, - // { - // Score: 190.44242984775784, - // Member: "Palermo", - // }, - // })) - //}) + q.BoxHeight = 400 + val, err = client.GeoSearch(ctx, "Sicily", q).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]string{"Catania", "Palermo"})) + + q.Count = 1 + val, err = client.GeoSearch(ctx, "Sicily", q).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]string{"Catania"})) + + q.CountAny = true + val, err = client.GeoSearch(ctx, "Sicily", q).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]string{"Palermo"})) + + q = &redis.GeoSearchQuery{ + Member: "Catania", + Radius: 100, + RadiusUnit: "km", + Sort: "asc", + } + val, err = client.GeoSearch(ctx, "Sicily", q).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]string{"Catania"})) + + q.Radius = 400 + val, err = client.GeoSearch(ctx, "Sicily", q).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]string{"Catania", "Palermo"})) + + q.Count = 1 + val, err = client.GeoSearch(ctx, "Sicily", q).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]string{"Catania"})) + + q.CountAny = true + val, err = client.GeoSearch(ctx, "Sicily", q).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]string{"Palermo"})) + + q = &redis.GeoSearchQuery{ + Longitude: 15, + Latitude: 37, + BoxWidth: 200, + BoxHeight: 200, + BoxUnit: "km", + Sort: "asc", + } + val, err = client.GeoSearch(ctx, "Sicily", q).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]string{"Catania"})) + + q.BoxWidth, q.BoxHeight = 400, 400 + val, err = client.GeoSearch(ctx, "Sicily", q).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]string{"Catania", "Palermo"})) + + q.Count = 1 + val, err = client.GeoSearch(ctx, "Sicily", q).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]string{"Catania"})) + + q.CountAny = true + val, err = client.GeoSearch(ctx, "Sicily", q).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]string{"Palermo"})) + + q = &redis.GeoSearchQuery{ + Longitude: 15, + Latitude: 37, + Radius: 100, + RadiusUnit: "km", + Sort: "asc", + } + val, err = client.GeoSearch(ctx, "Sicily", q).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]string{"Catania"})) + + q.Radius = 200 + val, err = client.GeoSearch(ctx, "Sicily", q).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]string{"Catania", "Palermo"})) + + q.Count = 1 + val, err = client.GeoSearch(ctx, "Sicily", q).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]string{"Catania"})) + + q.CountAny = true + val, err = client.GeoSearch(ctx, "Sicily", q).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]string{"Palermo"})) + }) + + PIt("should geo search with options", func() { + q := &redis.GeoSearchLocationQuery{ + GeoSearchQuery: redis.GeoSearchQuery{ + Longitude: 15, + Latitude: 37, + Radius: 200, + RadiusUnit: "km", + Sort: "asc", + }, + WithHash: true, + WithDist: true, + WithCoord: true, + } + val, err := client.GeoSearchLocation(ctx, "Sicily", q).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]redis.GeoLocation{ + { + Name: "Catania", + Longitude: 15.08726745843887329, + Latitude: 37.50266842333162032, + Dist: 56.4413, + GeoHash: 3479447370796909, + }, + { + Name: "Palermo", + Longitude: 13.36138933897018433, + Latitude: 38.11555639549629859, + Dist: 190.4424, + GeoHash: 3479099956230698, + }, + })) + }) + + PIt("should geo search store", func() { + q := &redis.GeoSearchStoreQuery{ + GeoSearchQuery: redis.GeoSearchQuery{ + Longitude: 15, + Latitude: 37, + Radius: 200, + RadiusUnit: "km", + Sort: "asc", + }, + StoreDist: false, + } + + val, err := client.GeoSearchStore(ctx, "Sicily", "key1", q).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal(int64(2))) + + q.StoreDist = true + val, err = client.GeoSearchStore(ctx, "Sicily", "key2", q).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal(int64(2))) + + loc, err := client.GeoSearchLocation(ctx, "key1", &redis.GeoSearchLocationQuery{ + GeoSearchQuery: q.GeoSearchQuery, + WithCoord: true, + WithDist: true, + WithHash: true, + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(loc).To(Equal([]redis.GeoLocation{ + { + Name: "Catania", + Longitude: 15.08726745843887329, + Latitude: 37.50266842333162032, + Dist: 56.4413, + GeoHash: 3479447370796909, + }, + { + Name: "Palermo", + Longitude: 13.36138933897018433, + Latitude: 38.11555639549629859, + Dist: 190.4424, + GeoHash: 3479099956230698, + }, + })) + + v, err := client.ZRangeWithScores(ctx, "key2", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(v).To(Equal([]redis.Z{ + { + Score: 56.441257870158204, + Member: "Catania", + }, + { + Score: 190.44242984775784, + Member: "Palermo", + }, + })) + }) }) }) diff --git a/tests/integration/hash_test.go b/tests/integration/hash_test.go index a8ad898672..57c47fd4e8 100644 --- a/tests/integration/hash_test.go +++ b/tests/integration/hash_test.go @@ -6,7 +6,6 @@ import ( . "github.com/bsm/ginkgo/v2" . "github.com/bsm/gomega" - "github.com/redis/go-redis/v9" ) @@ -17,6 +16,7 @@ var _ = Describe("List Commands", func() { BeforeEach(func() { client = redis.NewClient(pikaOptions1()) Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred()) + time.Sleep(1 * time.Second) }) AfterEach(func() { @@ -228,14 +228,14 @@ var _ = Describe("List Commands", func() { // set struct // MSet struct - type set struct { - Set1 string `redis:"set1"` - Set2 int16 `redis:"set2"` - Set3 time.Duration `redis:"set3"` - Set4 interface{} `redis:"set4"` - Set5 map[string]interface{} `redis:"-"` - Set6 string `redis:"set6,omitempty"` - } + //type set struct { + // Set1 string `redis:"set1"` + // Set2 int16 `redis:"set2"` + // Set3 time.Duration `redis:"set3"` + // Set4 interface{} `redis:"set4"` + // Set5 map[string]interface{} `redis:"-"` + // Set6 string `redis:"set6,omitempty"` + //} // 命令格式不对:hset hash set1 val1 set2 1024 set3 2000000 set4 //hSet = client.HSet(ctx, "hash", &set{ @@ -307,26 +307,26 @@ var _ = Describe("List Commands", func() { Expect(slice).To(Equal([]string{"hello1", "hello2"})) }) - //It("should HRandField", func() { - // err := client.HSet(ctx, "hash", "key1", "hello1").Err() - // Expect(err).NotTo(HaveOccurred()) - // err = client.HSet(ctx, "hash", "key2", "hello2").Err() - // Expect(err).NotTo(HaveOccurred()) - // - // //v := client.HRandField(ctx, "hash", 1) - // //Expect(v.Err()).NotTo(HaveOccurred()) - // //Expect(v.Val()).To(Or(Equal([]string{"key1"}), Equal([]string{"key2"}))) - // - // v := client.HRandField(ctx, "hash", 0) - // Expect(v.Err()).NotTo(HaveOccurred()) - // Expect(v.Val()).To(HaveLen(0)) - // - // kv, err := client.HRandFieldWithValues(ctx, "hash", 1).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(kv).To(Or( - // Equal([]redis.KeyValue{{Key: "key1", Value: "hello1"}}), - // Equal([]redis.KeyValue{{Key: "key2", Value: "hello2"}}), - // )) - //}) + PIt("should HRandField", func() { + err := client.HSet(ctx, "hash", "key1", "hello1").Err() + Expect(err).NotTo(HaveOccurred()) + err = client.HSet(ctx, "hash", "key2", "hello2").Err() + Expect(err).NotTo(HaveOccurred()) + + //v := client.HRandField(ctx, "hash", 1) + //Expect(v.Err()).NotTo(HaveOccurred()) + //Expect(v.Val()).To(Or(Equal([]string{"key1"}), Equal([]string{"key2"}))) + + v := client.HRandField(ctx, "hash", 0) + Expect(v.Err()).NotTo(HaveOccurred()) + Expect(v.Val()).To(HaveLen(0)) + + kv, err := client.HRandFieldWithValues(ctx, "hash", 1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(kv).To(Or( + Equal([]redis.KeyValue{{Key: "key1", Value: "hello1"}}), + Equal([]redis.KeyValue{{Key: "key2", Value: "hello2"}}), + )) + }) }) }) diff --git a/tests/integration/hyperloglog_test.go b/tests/integration/hyperloglog_test.go index 67a54a006f..3b9217c0cb 100644 --- a/tests/integration/hyperloglog_test.go +++ b/tests/integration/hyperloglog_test.go @@ -2,6 +2,7 @@ package pika_integration import ( "context" + "time" . "github.com/bsm/ginkgo/v2" . "github.com/bsm/gomega" @@ -15,6 +16,7 @@ var _ = Describe("Hyperloglog Commands", func() { BeforeEach(func() { client = redis.NewClient(pikaOptions1()) Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred()) + time.Sleep(1 * time.Second) }) AfterEach(func() { diff --git a/tests/integration/list_test.go b/tests/integration/list_test.go index 66768e77b0..8612871b10 100644 --- a/tests/integration/list_test.go +++ b/tests/integration/list_test.go @@ -6,7 +6,6 @@ import ( . "github.com/bsm/ginkgo/v2" . "github.com/bsm/gomega" - "github.com/redis/go-redis/v9" ) @@ -17,6 +16,7 @@ var _ = Describe("List Commands", func() { BeforeEach(func() { client = redis.NewClient(pikaOptions1()) Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred()) + time.Sleep(1 * time.Second) }) AfterEach(func() { @@ -373,22 +373,22 @@ var _ = Describe("List Commands", func() { }) // todo fix: https://github.com/OpenAtomFoundation/pika/issues/1791 - //It("should LPop", func() { - // rPush := client.RPush(ctx, "list", "one") - // Expect(rPush.Err()).NotTo(HaveOccurred()) - // rPush = client.RPush(ctx, "list", "two") - // Expect(rPush.Err()).NotTo(HaveOccurred()) - // rPush = client.RPush(ctx, "list", "three") - // Expect(rPush.Err()).NotTo(HaveOccurred()) - // - // lPop := client.LPop(ctx, "list") - // Expect(lPop.Err()).NotTo(HaveOccurred()) - // Expect(lPop.Val()).To(Equal("one")) - // - // lRange := client.LRange(ctx, "list", 0, -1) - // Expect(lRange.Err()).NotTo(HaveOccurred()) - // Expect(lRange.Val()).To(Equal([]string{"two", "three"})) - //}) + It("should LPop", func() { + rPush := client.RPush(ctx, "list", "one") + Expect(rPush.Err()).NotTo(HaveOccurred()) + rPush = client.RPush(ctx, "list", "two") + Expect(rPush.Err()).NotTo(HaveOccurred()) + rPush = client.RPush(ctx, "list", "three") + Expect(rPush.Err()).NotTo(HaveOccurred()) + + lPop := client.LPop(ctx, "list") + Expect(lPop.Err()).NotTo(HaveOccurred()) + Expect(lPop.Val()).To(Equal("one")) + + lRange := client.LRange(ctx, "list", 0, -1) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{"two", "three"})) + }) It("should LPopCount", func() { rPush := client.RPush(ctx, "list11", "one") @@ -409,61 +409,61 @@ var _ = Describe("List Commands", func() { Expect(lRange.Val()).To(Equal([]string{"three", "four"})) }) - //It("should LPos", func() { - // rPush := client.RPush(ctx, "list", "a") - // Expect(rPush.Err()).NotTo(HaveOccurred()) - // rPush = client.RPush(ctx, "list", "b") - // Expect(rPush.Err()).NotTo(HaveOccurred()) - // rPush = client.RPush(ctx, "list", "c") - // Expect(rPush.Err()).NotTo(HaveOccurred()) - // rPush = client.RPush(ctx, "list", "b") - // Expect(rPush.Err()).NotTo(HaveOccurred()) - // - // lPos := client.LPos(ctx, "list", "b", redis.LPosArgs{}) - // Expect(lPos.Err()).NotTo(HaveOccurred()) - // Expect(lPos.Val()).To(Equal(int64(1))) - // - // lPos = client.LPos(ctx, "list", "b", redis.LPosArgs{Rank: 2}) - // Expect(lPos.Err()).NotTo(HaveOccurred()) - // Expect(lPos.Val()).To(Equal(int64(3))) - // - // lPos = client.LPos(ctx, "list", "b", redis.LPosArgs{Rank: -2}) - // Expect(lPos.Err()).NotTo(HaveOccurred()) - // Expect(lPos.Val()).To(Equal(int64(1))) - // - // lPos = client.LPos(ctx, "list", "b", redis.LPosArgs{Rank: 2, MaxLen: 1}) - // Expect(lPos.Err()).To(Equal(redis.Nil)) - // - // lPos = client.LPos(ctx, "list", "z", redis.LPosArgs{}) - // Expect(lPos.Err()).To(Equal(redis.Nil)) - //}) + PIt("should LPos", func() { + rPush := client.RPush(ctx, "list", "a") + Expect(rPush.Err()).NotTo(HaveOccurred()) + rPush = client.RPush(ctx, "list", "b") + Expect(rPush.Err()).NotTo(HaveOccurred()) + rPush = client.RPush(ctx, "list", "c") + Expect(rPush.Err()).NotTo(HaveOccurred()) + rPush = client.RPush(ctx, "list", "b") + Expect(rPush.Err()).NotTo(HaveOccurred()) - //It("should LPosCount", func() { - // rPush := client.RPush(ctx, "list", "a") - // Expect(rPush.Err()).NotTo(HaveOccurred()) - // rPush = client.RPush(ctx, "list", "b") - // Expect(rPush.Err()).NotTo(HaveOccurred()) - // rPush = client.RPush(ctx, "list", "c") - // Expect(rPush.Err()).NotTo(HaveOccurred()) - // rPush = client.RPush(ctx, "list", "b") - // Expect(rPush.Err()).NotTo(HaveOccurred()) - // - // lPos := client.LPosCount(ctx, "list", "b", 2, redis.LPosArgs{}) - // Expect(lPos.Err()).NotTo(HaveOccurred()) - // Expect(lPos.Val()).To(Equal([]int64{1, 3})) - // - // lPos = client.LPosCount(ctx, "list", "b", 2, redis.LPosArgs{Rank: 2}) - // Expect(lPos.Err()).NotTo(HaveOccurred()) - // Expect(lPos.Val()).To(Equal([]int64{3})) - // - // lPos = client.LPosCount(ctx, "list", "b", 1, redis.LPosArgs{Rank: 1, MaxLen: 1}) - // Expect(lPos.Err()).NotTo(HaveOccurred()) - // Expect(lPos.Val()).To(Equal([]int64{})) - // - // lPos = client.LPosCount(ctx, "list", "b", 1, redis.LPosArgs{Rank: 1, MaxLen: 0}) - // Expect(lPos.Err()).NotTo(HaveOccurred()) - // Expect(lPos.Val()).To(Equal([]int64{1})) - //}) + lPos := client.LPos(ctx, "list", "b", redis.LPosArgs{}) + Expect(lPos.Err()).NotTo(HaveOccurred()) + Expect(lPos.Val()).To(Equal(int64(1))) + + lPos = client.LPos(ctx, "list", "b", redis.LPosArgs{Rank: 2}) + Expect(lPos.Err()).NotTo(HaveOccurred()) + Expect(lPos.Val()).To(Equal(int64(3))) + + lPos = client.LPos(ctx, "list", "b", redis.LPosArgs{Rank: -2}) + Expect(lPos.Err()).NotTo(HaveOccurred()) + Expect(lPos.Val()).To(Equal(int64(1))) + + lPos = client.LPos(ctx, "list", "b", redis.LPosArgs{Rank: 2, MaxLen: 1}) + Expect(lPos.Err()).To(Equal(redis.Nil)) + + lPos = client.LPos(ctx, "list", "z", redis.LPosArgs{}) + Expect(lPos.Err()).To(Equal(redis.Nil)) + }) + + PIt("should LPosCount", func() { + rPush := client.RPush(ctx, "list", "a") + Expect(rPush.Err()).NotTo(HaveOccurred()) + rPush = client.RPush(ctx, "list", "b") + Expect(rPush.Err()).NotTo(HaveOccurred()) + rPush = client.RPush(ctx, "list", "c") + Expect(rPush.Err()).NotTo(HaveOccurred()) + rPush = client.RPush(ctx, "list", "b") + Expect(rPush.Err()).NotTo(HaveOccurred()) + + lPos := client.LPosCount(ctx, "list", "b", 2, redis.LPosArgs{}) + Expect(lPos.Err()).NotTo(HaveOccurred()) + Expect(lPos.Val()).To(Equal([]int64{1, 3})) + + lPos = client.LPosCount(ctx, "list", "b", 2, redis.LPosArgs{Rank: 2}) + Expect(lPos.Err()).NotTo(HaveOccurred()) + Expect(lPos.Val()).To(Equal([]int64{3})) + + lPos = client.LPosCount(ctx, "list", "b", 1, redis.LPosArgs{Rank: 1, MaxLen: 1}) + Expect(lPos.Err()).NotTo(HaveOccurred()) + Expect(lPos.Val()).To(Equal([]int64{})) + + lPos = client.LPosCount(ctx, "list", "b", 1, redis.LPosArgs{Rank: 1, MaxLen: 0}) + Expect(lPos.Err()).NotTo(HaveOccurred()) + Expect(lPos.Val()).To(Equal([]int64{1})) + }) It("should LPush", func() { lPush := client.LPush(ctx, "list", "World") @@ -592,22 +592,22 @@ var _ = Describe("List Commands", func() { }) // todo fix: https://github.com/OpenAtomFoundation/pika/issues/1791 - //It("should RPop", func() { - // rPush := client.RPush(ctx, "list", "one") - // Expect(rPush.Err()).NotTo(HaveOccurred()) - // rPush = client.RPush(ctx, "list", "two") - // Expect(rPush.Err()).NotTo(HaveOccurred()) - // rPush = client.RPush(ctx, "list", "three") - // Expect(rPush.Err()).NotTo(HaveOccurred()) - // - // rPop := client.RPop(ctx, "list") - // Expect(rPop.Err()).NotTo(HaveOccurred()) - // Expect(rPop.Val()).To(Equal("three")) - // - // lRange := client.LRange(ctx, "list", 0, -1) - // Expect(lRange.Err()).NotTo(HaveOccurred()) - // Expect(lRange.Val()).To(Equal([]string{"one", "two"})) - //}) + It("should RPop", func() { + rPush := client.RPush(ctx, "list", "one") + Expect(rPush.Err()).NotTo(HaveOccurred()) + rPush = client.RPush(ctx, "list", "two") + Expect(rPush.Err()).NotTo(HaveOccurred()) + rPush = client.RPush(ctx, "list", "three") + Expect(rPush.Err()).NotTo(HaveOccurred()) + + rPop := client.RPop(ctx, "list") + Expect(rPop.Err()).NotTo(HaveOccurred()) + Expect(rPop.Val()).To(Equal("three")) + + lRange := client.LRange(ctx, "list", 0, -1) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{"one", "two"})) + }) It("should RPopCount", func() { rPush := client.RPush(ctx, "list", "one", "two", "three", "four") @@ -692,48 +692,48 @@ var _ = Describe("List Commands", func() { Expect(lRange.Val()).To(Equal([]string{})) }) - //It("should LMove", func() { - // rPush := client.RPush(ctx, "lmove1", "ichi") - // Expect(rPush.Err()).NotTo(HaveOccurred()) - // Expect(rPush.Val()).To(Equal(int64(1))) - // - // rPush = client.RPush(ctx, "lmove1", "ni") - // Expect(rPush.Err()).NotTo(HaveOccurred()) - // Expect(rPush.Val()).To(Equal(int64(2))) - // - // rPush = client.RPush(ctx, "lmove1", "san") - // Expect(rPush.Err()).NotTo(HaveOccurred()) - // Expect(rPush.Val()).To(Equal(int64(3))) - // - // lMove := client.LMove(ctx, "lmove1", "lmove2", "RIGHT", "LEFT") - // Expect(lMove.Err()).NotTo(HaveOccurred()) - // Expect(lMove.Val()).To(Equal("san")) - // - // lRange := client.LRange(ctx, "lmove2", 0, -1) - // Expect(lRange.Err()).NotTo(HaveOccurred()) - // Expect(lRange.Val()).To(Equal([]string{"san"})) - //}) + PIt("should LMove", func() { + rPush := client.RPush(ctx, "lmove1", "ichi") + Expect(rPush.Err()).NotTo(HaveOccurred()) + Expect(rPush.Val()).To(Equal(int64(1))) - //It("should BLMove", func() { - // rPush := client.RPush(ctx, "blmove1", "ichi") - // Expect(rPush.Err()).NotTo(HaveOccurred()) - // Expect(rPush.Val()).To(Equal(int64(1))) - // - // rPush = client.RPush(ctx, "blmove1", "ni") - // Expect(rPush.Err()).NotTo(HaveOccurred()) - // Expect(rPush.Val()).To(Equal(int64(2))) - // - // rPush = client.RPush(ctx, "blmove1", "san") - // Expect(rPush.Err()).NotTo(HaveOccurred()) - // Expect(rPush.Val()).To(Equal(int64(3))) - // - // blMove := client.BLMove(ctx, "blmove1", "blmove2", "RIGHT", "LEFT", time.Second) - // Expect(blMove.Err()).NotTo(HaveOccurred()) - // Expect(blMove.Val()).To(Equal("san")) - // - // lRange := client.LRange(ctx, "blmove2", 0, -1) - // Expect(lRange.Err()).NotTo(HaveOccurred()) - // Expect(lRange.Val()).To(Equal([]string{"san"})) - //}) + rPush = client.RPush(ctx, "lmove1", "ni") + Expect(rPush.Err()).NotTo(HaveOccurred()) + Expect(rPush.Val()).To(Equal(int64(2))) + + rPush = client.RPush(ctx, "lmove1", "san") + Expect(rPush.Err()).NotTo(HaveOccurred()) + Expect(rPush.Val()).To(Equal(int64(3))) + + lMove := client.LMove(ctx, "lmove1", "lmove2", "RIGHT", "LEFT") + Expect(lMove.Err()).NotTo(HaveOccurred()) + Expect(lMove.Val()).To(Equal("san")) + + lRange := client.LRange(ctx, "lmove2", 0, -1) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{"san"})) + }) + + PIt("should BLMove", func() { + rPush := client.RPush(ctx, "blmove1", "ichi") + Expect(rPush.Err()).NotTo(HaveOccurred()) + Expect(rPush.Val()).To(Equal(int64(1))) + + rPush = client.RPush(ctx, "blmove1", "ni") + Expect(rPush.Err()).NotTo(HaveOccurred()) + Expect(rPush.Val()).To(Equal(int64(2))) + + rPush = client.RPush(ctx, "blmove1", "san") + Expect(rPush.Err()).NotTo(HaveOccurred()) + Expect(rPush.Val()).To(Equal(int64(3))) + + blMove := client.BLMove(ctx, "blmove1", "blmove2", "RIGHT", "LEFT", time.Second) + Expect(blMove.Err()).NotTo(HaveOccurred()) + Expect(blMove.Val()).To(Equal("san")) + + lRange := client.LRange(ctx, "blmove2", 0, -1) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{"san"})) + }) }) }) diff --git a/tests/integration/main_test.go b/tests/integration/main_test.go index f48bef9637..53a46fd0a8 100644 --- a/tests/integration/main_test.go +++ b/tests/integration/main_test.go @@ -4,7 +4,6 @@ import ( "testing" . "github.com/bsm/ginkgo/v2" - . "github.com/bsm/gomega" ) diff --git a/tests/integration/pika_replication_test.py b/tests/integration/pika_replication_test.py deleted file mode 100644 index 6b816a64d9..0000000000 --- a/tests/integration/pika_replication_test.py +++ /dev/null @@ -1,939 +0,0 @@ -# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # -# This is the basic replication tests for pika -# -# It's also the tests for the issues and pr below: -# relevent issue: -# https://github.com/OpenAtomFoundation/pika/issues/1638 -# https://github.com/OpenAtomFoundation/pika/issues/1608 -# relevent pr: -# https://github.com/OpenAtomFoundation/pika/pull/1658 -# https://github.com/OpenAtomFoundation/pika/issues/1638 -# -# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # -import threading -import time -import redis -import random -import string - - -def test_del_replication(): - print("start del multiple keys replication test") - # 创建Redis客户端 - master = redis.Redis(host=master_ip, port=int(master_port), db=0) - slave = redis.Redis(host=slave_ip, port=int(slave_port), db=0) - if delay_slave_of: - slave.slaveof("no", "one") - else: - slave.slaveof(master_ip, master_port) - time.sleep(1) - # 执行日志中的操作 - master.delete('blist0', 'blist1', 'blist2', 'blist3') - master.delete('blist100', 'blist101', 'blist102', 'blist103') - master.delete('blist0', 'blist1', 'blist2', 'blist3') - - master.rpush('blist3', 'v2') - master.lpush('blist2', 'v2') - master.lpop('blist3') - master.rpop('blist2') - - master.lpush('blist2', 'v2') - master.lpop('blist2') - master.rpush('blist3', 'v2') - master.rpop('blist3') - - master.lpush('blist2', 'v2') - master.lpop('blist2') - master.rpush('blist3', 'v2') - master.lpush('blist2', 'v2') - - master.rpop('blist3') - master.lpop('blist2') - master.lpush('blist2', 'v2') - master.rpush('blist3', 'v2') - - master.rpop('blist3') - master.lpop('blist2') - master.rpush('blist3', 'v2') - master.lpush('blist2', 'v2') - - master.rpop('blist3') - master.rpush('blist3', 'v2') - master.lpush('blist2', 'v2') - master.rpush('blist3', 'v2') - - master.rpush('blist3', 'v2') - master.lpush('blist2', 'v2') - master.lpush('blist2', 'v2') - master.rpush('blist3', 'v2') - - master.lpush('blist2', 'v2') - master.rpush('blist3', 'v2') - master.delete('blist1', 'large', 'blist2') - - master.rpush('blist1', 'a', 'large', 'c') - master.rpush('blist2', 'd', 'large', 'f') - - master.lpop('blist1') - master.rpop('blist1') - master.lpop('blist2') - master.rpop('blist2') - - master.delete('blist3') - master.lpop('blist2') - master.rpop('blist1') - - if delay_slave_of: - slave.slaveof(master_ip, master_port) - time.sleep(25) - else: - time.sleep(10) - # Retrieve all keys from the master and slave - m_keys = master.keys() - s_keys = slave.keys() - - # print(m_keys) - # print(s_keys) - # Check if the keys in the master and slave are the same - assert set(m_keys) == set(s_keys), f'Expected: s_keys == m_keys, but got s_keys: {s_keys}, m_keys: {m_keys}' - - lists_ = ['blist1', 'blist2', 'blist3'] - for this_list in lists_: - # Check if the length of the list stored at this_list is the same in master and slave - assert master.llen(this_list) == slave.llen(this_list), \ - f'Expected: master.llen({this_list}) == slave.llen({this_list}), but got {master.llen(this_list)} != {slave.llen(this_list)}' - # Check if each element in the list is the same in the master and slave - for i in range(0, master.llen(this_list)): - mv = master.lindex(this_list, i) - sv = slave.lindex(this_list, i) - assert mv == sv, \ - f"Expected: master.lindex({this_list}, {i}) == slave.lindex({this_list}, {i}), but got {mv} != {sv}" - - master.close() - slave.close() - print("Del multiple keys replication OK [Passed]") - - -def test_msetnx_replication(): - print("start test_msetnx_replication") - master = redis.Redis(host=master_ip, port=int(master_port), db=0) - slave = redis.Redis(host=slave_ip, port=int(slave_port), db=0) - if delay_slave_of: - slave.slaveof("no", "one") - else: - slave.slaveof(master_ip, master_port) - time.sleep(1) - - master.delete('1mset_key', '2mset_key', '3mset_key', '4mset_key') - - def random_mset_thread(keys_): - pika = redis.Redis(host=master_ip, port=int(master_port), db=0) - for i in range(0, 3): - kvs1 = {} - kvs2 = {} - kvs3 = {} - kvs4 = {} - letters = string.ascii_letters - for key in keys_: - kvs1[key] = ''.join(random.choice(letters) for _ in range(5)) - kvs2[key] = ''.join(random.choice(letters) for _ in range(5)) - kvs3[key] = ''.join(random.choice(letters) for _ in range(5)) - kvs4[key] = ''.join(random.choice(letters) for _ in range(5)) - pika.set(keys_[2], ''.join(random.choice(letters) for _ in range(5))) - pika.set(keys_[3], ''.join(random.choice(letters) for _ in range(5))) - pika.delete(*keys_) - pika.msetnx(kvs1) - pika.set(keys_[0], ''.join(random.choice(letters) for _ in range(5))) - pika.set(keys_[1], ''.join(random.choice(letters) for _ in range(5))) - pika.delete(*keys_) - pika.msetnx(kvs2) - pika.set(keys_[1], ''.join(random.choice(letters) for _ in range(5))) - pika.set(keys_[2], ''.join(random.choice(letters) for _ in range(5))) - pika.set(keys_[0], ''.join(random.choice(letters) for _ in range(5))) - pika.delete(*keys_) - pika.msetnx(kvs3) - pika.set(keys_[3], ''.join(random.choice(letters) for _ in range(5))) - pika.set(keys_[0], ''.join(random.choice(letters) for _ in range(5))) - pika.set(keys_[1], ''.join(random.choice(letters) for _ in range(5))) - pika.delete(*keys_) - pika.msetnx(kvs4) - pika.set(keys_[3], ''.join(random.choice(letters) for _ in range(5))) - - keys = ['1mset_key', '2mset_key', '3mset_key', '4mset_key'] - threads = [] - for i in range(0, 50): - t = threading.Thread(target=random_mset_thread, args=(keys,)) - threads.append(t) - - for t in threads: - t.start() - for t in threads: - t.join() - - if delay_slave_of: - slave.slaveof(master_ip, master_port) - time.sleep(25) - else: - time.sleep(10) - - for key in keys: - m_v = master.get(key) - s_v = slave.get(key) - assert m_v == s_v, f'Expected: master_v == slave_v, but got slave_v:{s_v}, master_v:{m_v}, using key:{key}' - print("test_msetnx_replication OK [Passed]") - - -def test_mset_replication(): - print("start test_mset_replication") - master = redis.Redis(host=master_ip, port=int(master_port), db=0) - slave = redis.Redis(host=slave_ip, port=int(slave_port), db=0) - if delay_slave_of: - slave.slaveof("no", "one") - else: - slave.slaveof(master_ip, master_port) - time.sleep(1) - - keys = ['1mset_key', '2mset_key', '3mset_key', '4mset_key'] - master.delete('1mset_key', '2mset_key', '3mset_key', '4mset_key') - - def random_mset_thread(keys_): - pika = redis.Redis(host=master_ip, port=int(master_port), db=0) - for i in range(0, 3): - kvs1 = {} - kvs2 = {} - kvs3 = {} - kvs4 = {} - letters = string.ascii_letters - for key in keys_: - kvs1[key] = ''.join(random.choice(letters) for _ in range(5)) - kvs2[key] = ''.join(random.choice(letters) for _ in range(5)) - kvs3[key] = ''.join(random.choice(letters) for _ in range(5)) - kvs4[key] = ''.join(random.choice(letters) for _ in range(5)) - pika.set(keys_[2], ''.join(random.choice(letters) for _ in range(5))) - pika.set(keys_[3], ''.join(random.choice(letters) for _ in range(5))) - pika.mset(kvs1) - pika.set(keys_[0], ''.join(random.choice(letters) for _ in range(5))) - pika.set(keys_[1], ''.join(random.choice(letters) for _ in range(5))) - pika.mset(kvs2) - pika.set(keys_[1], ''.join(random.choice(letters) for _ in range(5))) - pika.set(keys_[2], ''.join(random.choice(letters) for _ in range(5))) - pika.set(keys_[0], ''.join(random.choice(letters) for _ in range(5))) - pika.mset(kvs3) - pika.set(keys_[3], ''.join(random.choice(letters) for _ in range(5))) - pika.set(keys_[0], ''.join(random.choice(letters) for _ in range(5))) - pika.set(keys_[1], ''.join(random.choice(letters) for _ in range(5))) - pika.mset(kvs4) - pika.set(keys_[3], ''.join(random.choice(letters) for _ in range(5))) - - threads = [] - for i in range(0, 50): - t = threading.Thread(target=random_mset_thread, args=(keys,)) - threads.append(t) - - for t in threads: - t.start() - for t in threads: - t.join() - - if delay_slave_of: - slave.slaveof(master_ip, master_port) - time.sleep(25) - else: - time.sleep(10) - - for key in keys: - m_v = master.get(key) - s_v = slave.get(key) - assert m_v == s_v, f'Expected: master_v == slave_v, but got slave_v:{s_v}, master_v:{m_v}, using key:{key}' - print("test_mset_replication OK [Passed]") - - -def test_smove_replication(): - print("start test_smove_replication") - - master = redis.Redis(host=master_ip, port=int(master_port), db=0) - slave = redis.Redis(host=slave_ip, port=int(slave_port), db=0) - - if delay_slave_of: - slave.slaveof("no", "one") - else: - slave.slaveof(master_ip, master_port) - time.sleep(1) - - master.delete('source_set', 'dest_set') - - def random_smove_thread(): - pika = redis.Redis(host=master_ip, port=int(master_port), db=0) - letters = string.ascii_letters - for i in range(0, 1): - member = ''.join(random.choice(letters) for _ in range(5)) - pika.sadd('source_set', member) - pika.sadd('source_set', member) - pika.sadd('source_set', member) - pika.srem('dest_set', member) - pika.srem('dest_set', member) - pika.smove('source_set', 'dest_set', member) - - threads = [] - for i in range(0, 10): - t = threading.Thread(target=random_smove_thread) - threads.append(t) - - for t in threads: - t.start() - for t in threads: - t.join() - - if delay_slave_of: - slave.slaveof(master_ip, master_port) - time.sleep(25) - else: - time.sleep(10) - m_source_set = master.smembers('source_set') - m_dest_set = master.smembers('dest_set') - s_source_set = slave.smembers('source_set') - s_dest_set = slave.smembers('dest_set') - - assert m_source_set == s_source_set, f'Expected: source_set on master == source_set on slave, but got source_set on slave:{s_source_set}, source_set on master:{m_source_set}' - assert m_dest_set == s_dest_set, f'Expected: dest_set on master == dest_set on slave, but got dest_set on slave:{s_dest_set}, dest_set on master:{m_dest_set}' - print("start test_smove_replication OK [Passed]") - - -def test_rpoplpush_replication(): - print("start test_rpoplpush_replication") - master = redis.Redis(host=master_ip, port=int(master_port), db=0) - slave = redis.Redis(host=slave_ip, port=int(slave_port), db=0) - if delay_slave_of: - slave.slaveof("no", "one") - else: - slave.slaveof(master_ip, master_port) - time.sleep(1) - - master.delete('blist0', 'blist1', 'blist') - - def rpoplpush_thread1(): - nonlocal master - for i in range(0, 50): - letters = string.ascii_letters - random_str1 = ''.join(random.choice(letters) for _ in range(5)) - random_str2 = ''.join(random.choice(letters) for _ in range(5)) - random_str3 = ''.join(random.choice(letters) for _ in range(5)) - master.lpush('blist0', random_str1) - master.rpoplpush('blist0', 'blist') - master.lpush('blist', random_str1, random_str2, random_str3) - - master.lpop('blist') - master.rpop('blist') - master.lpush('blist0', random_str3) - master.rpoplpush('blist0', 'blist') - master.rpush('blist', random_str3, random_str2, random_str1) - master.lpop('blist') - master.lpush('blist0', random_str2) - master.rpoplpush('blist0', 'blist') - master.rpop('blist') - - t1 = threading.Thread(target=rpoplpush_thread1) - t2 = threading.Thread(target=rpoplpush_thread1) - t3 = threading.Thread(target=rpoplpush_thread1) - t4 = threading.Thread(target=rpoplpush_thread1) - t5 = threading.Thread(target=rpoplpush_thread1) - t6 = threading.Thread(target=rpoplpush_thread1) - t7 = threading.Thread(target=rpoplpush_thread1) - t8 = threading.Thread(target=rpoplpush_thread1) - t9 = threading.Thread(target=rpoplpush_thread1) - t10 = threading.Thread(target=rpoplpush_thread1) - t1.start() - t2.start() - t3.start() - t4.start() - t5.start() - t6.start() - t7.start() - t8.start() - t9.start() - t10.start() - - t1.join() - t2.join() - t3.join() - t4.join() - t5.join() - t6.join() - t7.join() - t8.join() - t9.join() - t10.join() - - if delay_slave_of: - slave.slaveof(master_ip, master_port) - time.sleep(25) - else: - time.sleep(10) - m_keys = master.keys() - s_keys = slave.keys() - assert s_keys == m_keys, f'Expected: s_keys == m_keys, but got s_keys: {s_keys}, m_keys: {m_keys}' - - for i in range(0, master.llen('blist')): - # print(master.lindex('blist', i)) - # print(slave.lindex('blist', i)) - assert master.lindex('blist', i) == slave.lindex('blist', i), \ - f"Expected:master.lindex('blist', i) == slave.linex('blist', i), but got False when i = {i}" - print("test_rpoplpush_replication OK [Passed]") - - -def test_sdiffstore_replication(): - print("start test_sdiffstore_replication") - - master = redis.Redis(host=master_ip, port=int(master_port), db=0) - slave = redis.Redis(host=slave_ip, port=int(slave_port), db=0) - if delay_slave_of: - slave.slaveof("no", "one") - else: - slave.slaveof(master_ip, master_port) - time.sleep(1) - - master.delete('set1', 'set2', 'dest_set') - - def random_sdiffstore_thread(): - pika = redis.Redis(host=master_ip, port=int(master_port), db=0) - letters = string.ascii_letters - for i in range(0, 10): - pika.sadd('set1', ''.join(random.choice(letters) for _ in range(5))) - pika.sadd('set2', ''.join(random.choice(letters) for _ in range(5))) - pika.sadd('set1', ''.join(random.choice(letters) for _ in range(5))) - pika.sadd('set2', ''.join(random.choice(letters) for _ in range(5))) - pika.sadd('set1', ''.join(random.choice(letters) for _ in range(5))) - pika.sadd('set2', ''.join(random.choice(letters) for _ in range(5))) - pika.sadd('set1', ''.join(random.choice(letters) for _ in range(5))) - pika.sadd('set2', ''.join(random.choice(letters) for _ in range(5))) - pika.sadd('set2', ''.join(random.choice(letters) for _ in range(5))) - pika.sadd('set1', ''.join(random.choice(letters) for _ in range(5))) - pika.sadd('set1', ''.join(random.choice(letters) for _ in range(5))) - pika.sadd('set1', ''.join(random.choice(letters) for _ in range(5))) - pika.sadd('set2', ''.join(random.choice(letters) for _ in range(5))) - pika.sadd('set2', ''.join(random.choice(letters) for _ in range(5))) - pika.sadd('set1', ''.join(random.choice(letters) for _ in range(5))) - pika.sadd('set2', ''.join(random.choice(letters) for _ in range(5))) - pika.sadd('dest_set', ''.join(random.choice(letters) for _ in range(5))) - pika.sdiffstore('dest_set', 'set1', 'set2') - - threads = [] - for i in range(0, 10): - t = threading.Thread(target=random_sdiffstore_thread) - threads.append(t) - - for t in threads: - t.start() - for t in threads: - t.join() - - if delay_slave_of: - slave.slaveof(master_ip, master_port) - time.sleep(25) - else: - time.sleep(10) - - m_set1 = master.smembers('set1') - m_set2 = master.smembers('set2') - m_dest_set = master.smembers('dest_set') - s_set1 = slave.smembers('set1') - s_set2 = slave.smembers('set2') - s_dest_set = slave.smembers('dest_set') - - assert m_set1 == s_set1, f'Expected: set1 on master == set1 on slave, but got set1 on slave:{s_set1}, set1 on master:{m_set1}' - assert m_set2 == s_set2, f'Expected: set2 on master == set2 on slave, but got set2 on slave:{s_set2}, set2 on master:{m_set2}' - assert m_dest_set == s_dest_set, f'Expected: dest_set on master == dest_set on slave, but got dest_set on slave:{s_dest_set}, dest_set on master:{m_dest_set}' - print("test_sdiffstore_replication OK [Passed]") - - -def test_sinterstore_replication(): - print("start test_sinterstore_replication") - - master = redis.Redis(host=master_ip, port=int(master_port), db=0) - slave = redis.Redis(host=slave_ip, port=int(slave_port), db=0) - if delay_slave_of: - slave.slaveof("no", "one") - else: - slave.slaveof(master_ip, master_port) - time.sleep(1) - - master.delete('set1', 'set2', 'dest_set') - - def random_sinterstore_thread(): - pika = redis.Redis(host=master_ip, port=int(master_port), db=0) - letters = string.ascii_letters - for i in range(0, 10): - member = ''.join(random.choice(letters) for _ in range(5)) - member2 = ''.join(random.choice(letters) for _ in range(5)) - member3 = ''.join(random.choice(letters) for _ in range(5)) - member4 = ''.join(random.choice(letters) for _ in range(5)) - member5 = ''.join(random.choice(letters) for _ in range(5)) - member6 = ''.join(random.choice(letters) for _ in range(5)) - pika.sadd('set1', member) - pika.sadd('set2', member) - pika.sadd('set1', member2) - pika.sadd('set2', member2) - pika.sadd('set1', member3) - pika.sadd('set2', member3) - pika.sadd('set1', member4) - pika.sadd('set2', member4) - pika.sadd('set1', member5) - pika.sadd('set2', member5) - pika.sadd('set1', member6) - pika.sadd('set2', member6) - pika.sadd('dest_set', ''.join(random.choice(letters) for _ in range(5))) - pika.sinterstore('dest_set', 'set1', 'set2') - pika.sadd('dest_set', ''.join(random.choice(letters) for _ in range(5))) - - threads = [] - for i in range(0, 10): - t = threading.Thread(target=random_sinterstore_thread) - threads.append(t) - - for t in threads: - t.start() - for t in threads: - t.join() - - if delay_slave_of: - slave.slaveof(master_ip, master_port) - time.sleep(25) - else: - time.sleep(10) - - m_dest_set = master.smembers('dest_set') - s_dest_set = slave.smembers('dest_set') - - assert m_dest_set == s_dest_set, f'Expected: dest_set on master == dest_set on slave, but got dest_set on slave:{s_dest_set}, dest_set on master:{m_dest_set}' - print("test_sinterstore_replication OK [Passed]") - - -def test_zunionstore_replication(): - print("start test_zunionstore_replication") - - master = redis.Redis(host=master_ip, port=int(master_port), db=0) - slave = redis.Redis(host=slave_ip, port=int(slave_port), db=0) - if delay_slave_of: - slave.slaveof("no", "one") - else: - slave.slaveof(master_ip, master_port) - time.sleep(1) - - master.delete('zset1', 'zset2', 'zset_out') - - def random_zunionstore_thread(): - pika = redis.Redis(host=master_ip, port=int(master_port), db=0) - for i in range(0, 10): - pika.zadd('zset1', {''.join(random.choice(string.ascii_letters) for _ in range(5)): random.randint(1, 5)}) - pika.zadd('zset2', {''.join(random.choice(string.ascii_letters) for _ in range(5)): random.randint(1, 5)}) - pika.zadd('zset2', {''.join(random.choice(string.ascii_letters) for _ in range(5)): random.randint(1, 5)}) - pika.zadd('zset1', {''.join(random.choice(string.ascii_letters) for _ in range(5)): random.randint(1, 5)}) - pika.zadd('zset2', {''.join(random.choice(string.ascii_letters) for _ in range(5)): random.randint(1, 5)}) - pika.zadd('zset1', {''.join(random.choice(string.ascii_letters) for _ in range(5)): random.randint(1, 5)}) - pika.zadd('zset2', {''.join(random.choice(string.ascii_letters) for _ in range(5)): random.randint(1, 5)}) - pika.zadd('zset2', {''.join(random.choice(string.ascii_letters) for _ in range(5)): random.randint(1, 5)}) - pika.zadd('zset1', {''.join(random.choice(string.ascii_letters) for _ in range(5)): random.randint(1, 5)}) - pika.zadd('zset1', {''.join(random.choice(string.ascii_letters) for _ in range(5)): random.randint(1, 5)}) - pika.zadd('zset2', {''.join(random.choice(string.ascii_letters) for _ in range(5)): random.randint(1, 5)}) - pika.zadd('zset1', {''.join(random.choice(string.ascii_letters) for _ in range(5)): random.randint(1, 5)}) - pika.zunionstore('zset_out', ['zset1', 'zset2']) - pika.zadd('zset_out', - {''.join(random.choice(string.ascii_letters) for _ in range(5)): random.randint(1, 5)}) - - threads = [] - for i in range(0, 10): - t = threading.Thread(target=random_zunionstore_thread) - threads.append(t) - - for t in threads: - t.start() - for t in threads: - t.join() - if delay_slave_of: - slave.slaveof(master_ip, master_port) - time.sleep(25) - else: - time.sleep(10) - - m_zset_out = master.zrange('zset_out', 0, -1, withscores=True) - s_zset_out = slave.zrange('zset_out', 0, -1, withscores=True) - - assert m_zset_out == s_zset_out, f'Expected: zset_out on master == zset_out on slave, but got zset_out on slave:{s_zset_out}, zset_out on master:{m_zset_out}' - print("test_zunionstore_replication OK [Passed]") - - -def test_zinterstore_replication(): - print("start test_zinterstore_replication") - - master = redis.Redis(host=master_ip, port=int(master_port), db=0) - slave = redis.Redis(host=slave_ip, port=int(slave_port), db=0) - if delay_slave_of: - slave.slaveof("no", "one") - else: - slave.slaveof(master_ip, master_port) - time.sleep(1) - - master.delete('zset1', 'zset2', 'zset_out') - - def random_zinterstore_thread(): - pika = redis.Redis(host=master_ip, port=int(master_port), db=0) - for i in range(0, 10): - member = ''.join(random.choice(string.ascii_letters) for _ in range(5)) - member2 = ''.join(random.choice(string.ascii_letters) for _ in range(5)) - member3 = ''.join(random.choice(string.ascii_letters) for _ in range(5)) - member4 = ''.join(random.choice(string.ascii_letters) for _ in range(5)) - pika.zadd('zset1', {member: random.randint(1, 5)}) - pika.zadd('zset2', {member: random.randint(1, 5)}) - pika.zadd('zset1', {member2: random.randint(1, 5)}) - pika.zadd('zset2', {member2: random.randint(1, 5)}) - pika.zadd('zset1', {member3: random.randint(1, 5)}) - pika.zadd('zset2', {member3: random.randint(1, 5)}) - pika.zadd('zset1', {member4: random.randint(1, 5)}) - pika.zadd('zset2', {member4: random.randint(1, 5)}) - pika.zinterstore('zset_out', ['zset1', 'zset2']) - - - threads = [] - for i in range(0, 10): - t = threading.Thread(target=random_zinterstore_thread) - threads.append(t) - - for t in threads: - t.start() - for t in threads: - t.join() - - if delay_slave_of: - slave.slaveof(master_ip, master_port) - time.sleep(25) - else: - time.sleep(10) - - m_zset_out = master.zrange('zset_out', 0, -1, withscores=True) - s_zset_out = slave.zrange('zset_out', 0, -1, withscores=True) - - if len(m_zset_out) != len(s_zset_out): - print(f"Length mismatch: Master has {len(m_zset_out)} elements, Slave has {len(s_zset_out)} elements") - - for i, (m_item, s_item) in enumerate(zip(m_zset_out, s_zset_out)): - if m_item != s_item: - print(f"Mismatch at rank {i + 1}: Master has {m_item}, Slave has {s_item}") - - assert m_zset_out == s_zset_out, f'Expected: zset_out on master == zset_out on slave, but got zset_out on slave:{s_zset_out}, zset_out on master:{m_zset_out}' - - print("test_zinterstore_replication OK [Passed]") - - -def test_sunionstore_replication(): - print("start test_sunionstore_replication") - - master = redis.Redis(host=master_ip, port=int(master_port), db=0) - slave = redis.Redis(host=slave_ip, port=int(slave_port), db=0) - if delay_slave_of: - slave.slaveof("no", "one") - else: - slave.slaveof(master_ip, master_port) - time.sleep(1) - - master.delete('set1', 'set2', 'set_out') - - def random_sunionstore_thread(): - pika = redis.Redis(host=master_ip, port=int(master_port), db=0) - for i in range(0, 10): - pika.sadd('set1', ''.join(random.choice(string.ascii_letters) for _ in range(5))) - pika.sadd('set2', ''.join(random.choice(string.ascii_letters) for _ in range(5))) - pika.sadd('set1', ''.join(random.choice(string.ascii_letters) for _ in range(5))) - pika.sadd('set1', ''.join(random.choice(string.ascii_letters) for _ in range(5))) - pika.sadd('set2', ''.join(random.choice(string.ascii_letters) for _ in range(5))) - pika.sadd('set1', ''.join(random.choice(string.ascii_letters) for _ in range(5))) - pika.sadd('set1', ''.join(random.choice(string.ascii_letters) for _ in range(5))) - pika.sadd('set2', ''.join(random.choice(string.ascii_letters) for _ in range(5))) - pika.sadd('set2', ''.join(random.choice(string.ascii_letters) for _ in range(5))) - pika.sadd('set2', ''.join(random.choice(string.ascii_letters) for _ in range(5))) - pika.sadd('set1', ''.join(random.choice(string.ascii_letters) for _ in range(5))) - pika.sadd('set2', ''.join(random.choice(string.ascii_letters) for _ in range(5))) - pika.sadd('set1', ''.join(random.choice(string.ascii_letters) for _ in range(5))) - pika.sadd('set2', ''.join(random.choice(string.ascii_letters) for _ in range(5))) - pika.sunionstore('set_out', ['set1', 'set2']) - - threads = [] - for i in range(0, 10): - t = threading.Thread(target=random_sunionstore_thread) - threads.append(t) - - for t in threads: - t.start() - for t in threads: - t.join() - - if delay_slave_of: - slave.slaveof(master_ip, master_port) - time.sleep(25) - else: - time.sleep(10) - - m_set_out = master.smembers('set_out') - s_set_out = slave.smembers('set_out') - - assert m_set_out == s_set_out, f'Expected: set_out on master == set_out on slave, but got set_out on slave:{s_set_out}, set_out on master:{m_set_out}' - print("test_sunionstore_replication OK [Passed]") - - -def test_bitop_replication(): - print("start test_bitop_replication") - - master = redis.Redis(host=master_ip, port=int(master_port), db=0) - slave = redis.Redis(host=slave_ip, port=int(slave_port), db=0) - if delay_slave_of: - slave.slaveof("no", "one") - else: - slave.slaveof(master_ip, master_port) - time.sleep(1) - - master.delete('bitkey1', 'bitkey2', 'bitkey_out1', 'bitkey_out2') - - def random_bitop_thread(): - pika = redis.Redis(host=master_ip, port=int(master_port), db=0) - for i in range(0, 100): # Consider increasing the range to a larger number to get more meaningful results. - offset1 = random.randint(0, 100) # You may want to adjust the range based on your use case. - offset2 = random.randint(0, 100) # You may want to adjust the range based on your use case. - value1 = random.choice([0, 1]) - value2 = random.choice([0, 1]) - pika.setbit('bitkey1', offset1, value1) - pika.setbit('bitkey2', offset1, value1) - pika.bitop('AND', 'bitkey_out1', 'bitkey1', 'bitkey2') - pika.setbit('bitkey1', offset1 + offset2, value2) - pika.setbit('bitkey2', offset2, value2) - pika.bitop('OR', 'bitkey_out2', 'bitkey1', 'bitkey2') - - threads = [] - for i in range(0, 10): - t = threading.Thread(target=random_bitop_thread) - threads.append(t) - - for t in threads: - t.start() - for t in threads: - t.join() - if delay_slave_of: - slave.slaveof(master_ip, master_port) - time.sleep(25) - else: - time.sleep(10) - - m_key_out_count1 = master.bitcount('bitkey_out1') - s_key_out_count1 = slave.bitcount('bitkey_out1') - - m_key_out_count2 = master.bitcount('bitkey_out2') - s_key_out_count2 = slave.bitcount('bitkey_out2') - - assert m_key_out_count1 == s_key_out_count1, f'Expected: bitcount of bitkey_out1 on master == bitcount of bitkey_out1 on slave, but got bitcount of bitkey_out1 on slave:{s_key_out_count1}, bitcount of bitkey_out1 on master:{m_key_out_count1}' - assert m_key_out_count2 == s_key_out_count2, f'Expected: bitcount of bitkey_out2 on master == bitcount of bitkey_out2 on slave, but got bitcount of bitkey_out2 on slave:{s_key_out_count2}, bitcount of bitkey_out1 on master:{m_key_out_count2}' - print("test_bitop_replication OK [Passed]") - - -def test_pfmerge_replication(): - print("start test_pfmerge_replication") - - master = redis.Redis(host=master_ip, port=int(master_port), db=0) - slave = redis.Redis(host=slave_ip, port=int(slave_port), db=0) - if delay_slave_of: - slave.slaveof("no", "one") - else: - slave.slaveof(master_ip, master_port) - time.sleep(1) - - master.delete('hll1', 'hll2', 'hll_out') - - def random_pfmerge_thread(): - pika = redis.Redis(host=master_ip, port=int(master_port), db=0) - for i in range(0, 1): - pika.pfadd('hll1', ''.join(random.choice(string.ascii_letters) for _ in range(5))) - pika.pfadd('hll2', ''.join(random.choice(string.ascii_letters) for _ in range(5))) - pika.pfadd('hll2', ''.join(random.choice(string.ascii_letters) for _ in range(5))) - pika.pfadd('hll1', ''.join(random.choice(string.ascii_letters) for _ in range(5))) - pika.pfadd('hll2', ''.join(random.choice(string.ascii_letters) for _ in range(5))) - pika.pfadd('hll1', ''.join(random.choice(string.ascii_letters) for _ in range(5))) - pika.pfadd('hll2', ''.join(random.choice(string.ascii_letters) for _ in range(5))) - pika.pfadd('hll1', ''.join(random.choice(string.ascii_letters) for _ in range(5))) - pika.pfadd('hll_out', ''.join(random.choice(string.ascii_letters) for _ in range(5))) - pika.pfmerge('hll_out', 'hll1', 'hll2') - pika.pfadd('hll_out', ''.join(random.choice(string.ascii_letters) for _ in range(5))) - - threads = [] - for i in range(0, 50): - t = threading.Thread(target=random_pfmerge_thread) - threads.append(t) - - for t in threads: - t.start() - for t in threads: - t.join() - if delay_slave_of: - slave.slaveof(master_ip, master_port) - time.sleep(25) - else: - time.sleep(10) - - m_hll_out = master.pfcount('hll_out') - s_hll_out = slave.pfcount('hll_out') - - assert m_hll_out == s_hll_out, f'Expected: hll_out on master == hll_out on slave, but got hll_out on slave:{s_hll_out}, hll_out on master:{m_hll_out}' - print("test_pfmerge_replication OK [Passed]") - -def test_migrateslot_replication(): - print("start test_migrateslot_replication") - master = redis.Redis(host=master_ip, port=int(master_port), db=0) - slave = redis.Redis(host=slave_ip, port=int(slave_port), db=0) - - # open slot migrate - master.config_set("slotmigrate", "yes") - slave.config_set("slotmigrate", "no") - - setKey1 = "setKey_000" - setKey2 = "setKey_001" - setKey3 = "setKey_002" - setKey4 = "setKey_store" - - slave.slaveof(master_ip, master_port) - time.sleep(20) - - master.delete(setKey1) - master.delete(setKey2) - master.delete(setKey3) - master.delete(setKey4) - - letters = string.ascii_letters - master.sadd(setKey1, ''.join(random.choice(letters) for _ in range(5))) - master.sadd(setKey2, ''.join(random.choice(letters) for _ in range(5))) - master.sadd(setKey1, ''.join(random.choice(letters) for _ in range(5))) - master.sadd(setKey2, ''.join(random.choice(letters) for _ in range(5))) - master.sadd(setKey1, ''.join(random.choice(letters) for _ in range(5))) - master.sadd(setKey2, ''.join(random.choice(letters) for _ in range(5))) - master.sadd(setKey1, ''.join(random.choice(letters) for _ in range(5))) - master.sadd(setKey2, ''.join(random.choice(letters) for _ in range(5))) - master.sadd(setKey3, ''.join(random.choice(letters) for _ in range(5))) - master.sadd(setKey1, ''.join(random.choice(letters) for _ in range(5))) - master.sadd(setKey3, ''.join(random.choice(letters) for _ in range(5))) - master.sadd(setKey2, ''.join(random.choice(letters) for _ in range(5))) - master.sadd(setKey3, ''.join(random.choice(letters) for _ in range(5))) - master.sadd(setKey2, ''.join(random.choice(letters) for _ in range(5))) - master.sadd(setKey1, ''.join(random.choice(letters) for _ in range(5))) - master.sadd(setKey3, ''.join(random.choice(letters) for _ in range(5))) - master.sdiffstore(setKey4, setKey1, setKey2) - - time.sleep(25) - - m_set1 = master.smembers(setKey1) - m_set2 = master.smembers(setKey2) - m_set3 = master.smembers(setKey3) - m_dest_set = master.smembers(setKey4) - s_set1 = slave.smembers(setKey1) - s_set2 = slave.smembers(setKey2) - s_set3 = slave.smembers(setKey3) - s_dest_set = slave.smembers(setKey4) - - assert m_set1 == s_set1, f'Expected: set1 on master == set1 on slave, but got set1 on slave:{s_set1}, set1 on master:{m_set1}' - assert m_set2 == s_set2, f'Expected: set2 on master == set2 on slave, but got set2 on slave:{s_set2}, set2 on master:{m_set2}' - assert m_set3 == s_set3, f'Expected: set3 on master == set3 on slave, but got set3 on slave:{s_set3}, set3 on master:{m_set3}' - assert m_dest_set == s_dest_set, f'Expected: dest_set on master == dest_set on slave, but got dest_set on slave:{s_dest_set}, dest_set on master:{m_dest_set}' - - # disconnect mster and slave - slave.slaveof("no", "one") - - master.sadd(setKey1, ''.join(random.choice(letters) for _ in range(5))) - master.sadd(setKey2, ''.join(random.choice(letters) for _ in range(5))) - master.sadd(setKey1, ''.join(random.choice(letters) for _ in range(5))) - master.sadd(setKey2, ''.join(random.choice(letters) for _ in range(5))) - master.sadd(setKey1, ''.join(random.choice(letters) for _ in range(5))) - master.sadd(setKey2, ''.join(random.choice(letters) for _ in range(5))) - master.sadd(setKey1, ''.join(random.choice(letters) for _ in range(5))) - master.sadd(setKey2, ''.join(random.choice(letters) for _ in range(5))) - master.sadd(setKey3, ''.join(random.choice(letters) for _ in range(5))) - master.sadd(setKey1, ''.join(random.choice(letters) for _ in range(5))) - master.sadd(setKey3, ''.join(random.choice(letters) for _ in range(5))) - master.sadd(setKey2, ''.join(random.choice(letters) for _ in range(5))) - master.sadd(setKey3, ''.join(random.choice(letters) for _ in range(5))) - master.sadd(setKey2, ''.join(random.choice(letters) for _ in range(5))) - master.sadd(setKey1, ''.join(random.choice(letters) for _ in range(5))) - master.sadd(setKey3, ''.join(random.choice(letters) for _ in range(5))) - master.sdiffstore(setKey4, setKey1, setKey2) - - # reconnect mster and slave - slave.slaveof(master_ip, master_port) - time.sleep(25) - - m_set1 = master.smembers(setKey1) - m_set2 = master.smembers(setKey2) - m_set3 = master.smembers(setKey3) - m_dest_set = master.smembers(setKey4) - time.sleep(15) - s_set1 = slave.smembers(setKey1) - s_set2 = slave.smembers(setKey2) - s_set3 = slave.smembers(setKey3) - s_dest_set = slave.smembers(setKey4) - - assert m_set1 == s_set1, f'Expected: set1 on master == set1 on slave, but got set1 on slave:{s_set1}, set1 on master:{m_set1}' - assert m_set2 == s_set2, f'Expected: set2 on master == set2 on slave, but got set2 on slave:{s_set2}, set2 on master:{m_set2}' - assert m_set3 == s_set3, f'Expected: set3 on master == set3 on slave, but got set3 on slave:{s_set3}, set3 on master:{m_set3}' - assert m_dest_set == s_dest_set, f'Expected: dest_set on master == dest_set on slave, but got dest_set on slave:{s_dest_set}, dest_set on master:{m_dest_set}' - - # slave node should not has slot key - s_keys = slave.keys() - for key in s_keys: - assert not (str(key).startswith("_internal:slotkey:4migrate:") or str(key).startswith("_internal:slottag:4migrate:")), f'Expected: slave should not has slot key, but got {key}' - - master.config_set("slotmigrate", "no") - - i_keys = master.keys("_internal:slotkey:4migrate*") - master.delete(*i_keys) - print("test_migrateslot_replication OK [Passed]") - -master_ip = '127.0.0.1' -master_port = '9221' -slave_ip = '127.0.0.1' -slave_port = '9231' - - -# ---------For Github Action---------Start -# Simulate the slave server goes down and After being disconnected for a while, it reconnects to the master server. -delay_slave_of = False #Don't change this to True, unless you've added a long sleep after every slaveof - -test_migrateslot_replication() -master = redis.Redis(host=master_ip, port=int(master_port), db=0) -slave = redis.Redis(host=slave_ip, port=int(slave_port), db=0) -slave.slaveof(master_ip, master_port) -time.sleep(25) -test_rpoplpush_replication() -test_bitop_replication() -test_msetnx_replication() -test_mset_replication() -test_smove_replication() -test_del_replication() -test_pfmerge_replication() -test_sdiffstore_replication() -test_sinterstore_replication() -test_zunionstore_replication() -test_zinterstore_replication() -test_sunionstore_replication() -# ---------For Github Action---------End - - -# ---------For Local Stress Test---------Start -# delay_slave_of = False -# for i in range(0, 200): -# test_rpoplpush_replication() -# test_bitop_replication() -# test_del_replication() -# test_msetnx_replication() -# test_mset_replication() -# test_smove_replication() -# test_pfmerge_replication() -# test_sunionstore_replication() -# test_sdiffstore_replication() -# test_sinterstore_replication() -# test_zunionstore_replication() -# test_zinterstore_replication() -# delay_slave_of = not delay_slave_of -# ---------For Local Stress Test---------End - diff --git a/tests/integration/pubsub_test.go b/tests/integration/pubsub_test.go new file mode 100644 index 0000000000..fd6de6fee5 --- /dev/null +++ b/tests/integration/pubsub_test.go @@ -0,0 +1,455 @@ +package pika_integration + +import ( + "bytes" + "context" + "net" + "sync" + "time" + + . "github.com/bsm/ginkgo/v2" + . "github.com/bsm/gomega" + "github.com/redis/go-redis/v9" +) + +func bigVal() []byte { + return bytes.Repeat([]byte{'*'}, 1<<17) // 128kb +} + +var _ = Describe("PubSub", func() { + var client *redis.Client + var client2 *redis.Client + ctx := context.TODO() + + BeforeEach(func() { + client = redis.NewClient(pikaOptions1()) + client2 = redis.NewClient(pikaOptions1()) + Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred()) + Expect(client2.FlushDB(ctx).Err()).NotTo(HaveOccurred()) + time.Sleep(2 * time.Second) + }) + + AfterEach(func() { + Expect(client.Close()).NotTo(HaveOccurred()) + Expect(client2.Close()).NotTo(HaveOccurred()) + }) + + It("implements Stringer", func() { + pubsub := client.PSubscribe(ctx, "mychannel*") + defer pubsub.Close() + + Expect(pubsub.String()).To(Equal("PubSub(mychannel*)")) + }) + + It("should support pattern matching", func() { + pubsub := client.PSubscribe(ctx, "mychannel*") + defer pubsub.Close() + + { + msgi, err := pubsub.ReceiveTimeout(ctx, time.Second) + Expect(err).NotTo(HaveOccurred()) + subscr := msgi.(*redis.Subscription) + Expect(subscr.Kind).To(Equal("psubscribe")) + Expect(subscr.Channel).To(Equal("mychannel*")) + Expect(subscr.Count).To(Equal(1)) + } + + { + msgi, err := pubsub.ReceiveTimeout(ctx, time.Second) + Expect(err.(net.Error).Timeout()).To(Equal(true)) + Expect(msgi).To(BeNil()) + } + + n, err := client.Publish(ctx, "mychannel1", "hello").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(n).To(Equal(int64(1))) + + Expect(pubsub.PUnsubscribe(ctx, "mychannel*")).NotTo(HaveOccurred()) + + { + msgi, err := pubsub.ReceiveTimeout(ctx, time.Second) + Expect(err).NotTo(HaveOccurred()) + subscr := msgi.(*redis.Message) + Expect(subscr.Channel).To(Equal("mychannel1")) + Expect(subscr.Pattern).To(Equal("mychannel*")) + Expect(subscr.Payload).To(Equal("hello")) + } + + { + msgi, err := pubsub.ReceiveTimeout(ctx, time.Second) + Expect(err).NotTo(HaveOccurred()) + subscr := msgi.(*redis.Subscription) + Expect(subscr.Kind).To(Equal("punsubscribe")) + Expect(subscr.Channel).To(Equal("mychannel*")) + Expect(subscr.Count).To(Equal(0)) + } + + stats := client.PoolStats() + Expect(stats.Misses).To(Equal(uint32(1))) + }) + + It("should pub/sub channels", func() { + res, err := client.Do(ctx, "pubsub", "channels").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(res).To(BeEmpty()) + + _ = client.Subscribe(ctx, "mychannel", "mychannel2") + time.Sleep(1 * time.Second) + c2res := client2.Do(ctx, "pubsub", "channels") + Expect(c2res.Err()).NotTo(HaveOccurred()) + Expect(c2res.Val()).To(ConsistOf([]string{"mychannel", "mychannel2"})) + + channels, err := client2.PubSubChannels(ctx, "z*").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(channels).To(BeEmpty()) + + channels, err = client.PubSubChannels(ctx, "").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(len(channels)).To(BeNumerically(">=", 2)) + defer func() { + _ = client.Do(ctx, "unsubscribe", "mychannel", "mychannel2") + }() + }) + + PIt("should return the numbers of subscribers", func() { + pubsub := client.Subscribe(ctx, "mychannel", "mychannel2") + defer pubsub.Close() + + channels, err := client2.PubSubNumSub(ctx, "mychannel", "mychannel2", "mychannel3").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(channels).To(Equal(map[string]int64{ + "mychannel": 1, + "mychannel2": 1, + "mychannel3": 0, + })) + }) + + PIt("should return the numbers of subscribers by pattern", func() { + num, err := client.PubSubNumPat(ctx).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(num).To(Equal(int64(0))) + + _ = client.PSubscribe(ctx, "*") + defer func() { + _ = client.Do(ctx, "unsubscribe", "*") + }() + + num2 := client2.Do(ctx, "pubsub", "numpat") + Expect(num2.Err()).NotTo(HaveOccurred()) + Expect(num2.Val()).To(Equal(int64(1))) + }) + + It("should pub/sub", func() { + pubsub := client.Subscribe(ctx, "mychannel", "mychannel2") + defer pubsub.Close() + + { + msgi, err := pubsub.ReceiveTimeout(ctx, time.Second) + Expect(err).NotTo(HaveOccurred()) + subscr := msgi.(*redis.Subscription) + Expect(subscr.Kind).To(Equal("subscribe")) + Expect(subscr.Channel).To(Equal("mychannel")) + Expect(subscr.Count).To(Equal(1)) + } + + { + msgi, err := pubsub.ReceiveTimeout(ctx, time.Second) + Expect(err).NotTo(HaveOccurred()) + subscr := msgi.(*redis.Subscription) + Expect(subscr.Kind).To(Equal("subscribe")) + Expect(subscr.Channel).To(Equal("mychannel2")) + Expect(subscr.Count).To(Equal(2)) + } + + { + msgi, err := pubsub.ReceiveTimeout(ctx, time.Second) + Expect(err.(net.Error).Timeout()).To(Equal(true)) + Expect(msgi).NotTo(HaveOccurred()) + } + + n, err := client.Publish(ctx, "mychannel", "hello").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(n).To(Equal(int64(1))) + + n, err = client.Publish(ctx, "mychannel2", "hello2").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(n).To(Equal(int64(1))) + + Expect(pubsub.Unsubscribe(ctx, "mychannel", "mychannel2")).NotTo(HaveOccurred()) + + { + msgi, err := pubsub.ReceiveTimeout(ctx, time.Second) + Expect(err).NotTo(HaveOccurred()) + msg := msgi.(*redis.Message) + Expect(msg.Channel).To(Equal("mychannel")) + Expect(msg.Payload).To(Equal("hello")) + } + + { + msgi, err := pubsub.ReceiveTimeout(ctx, time.Second) + Expect(err).NotTo(HaveOccurred()) + msg := msgi.(*redis.Message) + Expect(msg.Channel).To(Equal("mychannel2")) + Expect(msg.Payload).To(Equal("hello2")) + } + + { + msgi, err := pubsub.ReceiveTimeout(ctx, time.Second) + Expect(err).NotTo(HaveOccurred()) + subscr := msgi.(*redis.Subscription) + Expect(subscr.Kind).To(Equal("unsubscribe")) + Expect(subscr.Channel).To(Equal("mychannel")) + Expect(subscr.Count).To(Equal(1)) + } + + { + msgi, err := pubsub.ReceiveTimeout(ctx, time.Second) + Expect(err).NotTo(HaveOccurred()) + subscr := msgi.(*redis.Subscription) + Expect(subscr.Kind).To(Equal("unsubscribe")) + Expect(subscr.Channel).To(Equal("mychannel2")) + Expect(subscr.Count).To(Equal(0)) + } + + stats := client.PoolStats() + Expect(stats.Misses).To(Equal(uint32(1))) + }) + + PIt("should sharded pub/sub", func() { + pubsub := client.SSubscribe(ctx, "mychannel", "mychannel2") + defer pubsub.Close() + + { + msgi, err := pubsub.ReceiveTimeout(ctx, time.Second) + Expect(err).NotTo(HaveOccurred()) + subscr := msgi.(*redis.Subscription) + Expect(subscr.Kind).To(Equal("ssubscribe")) + Expect(subscr.Channel).To(Equal("mychannel")) + Expect(subscr.Count).To(Equal(1)) + } + + { + msgi, err := pubsub.ReceiveTimeout(ctx, time.Second) + Expect(err).NotTo(HaveOccurred()) + subscr := msgi.(*redis.Subscription) + Expect(subscr.Kind).To(Equal("ssubscribe")) + Expect(subscr.Channel).To(Equal("mychannel2")) + Expect(subscr.Count).To(Equal(2)) + } + + { + msgi, err := pubsub.ReceiveTimeout(ctx, time.Second) + Expect(err.(net.Error).Timeout()).To(Equal(true)) + Expect(msgi).NotTo(HaveOccurred()) + } + + n, err := client.SPublish(ctx, "mychannel", "hello").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(n).To(Equal(int64(1))) + + n, err = client.SPublish(ctx, "mychannel2", "hello2").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(n).To(Equal(int64(1))) + + Expect(pubsub.SUnsubscribe(ctx, "mychannel", "mychannel2")).NotTo(HaveOccurred()) + + { + msgi, err := pubsub.ReceiveTimeout(ctx, time.Second) + Expect(err).NotTo(HaveOccurred()) + msg := msgi.(*redis.Message) + Expect(msg.Channel).To(Equal("mychannel")) + Expect(msg.Payload).To(Equal("hello")) + } + + { + msgi, err := pubsub.ReceiveTimeout(ctx, time.Second) + Expect(err).NotTo(HaveOccurred()) + msg := msgi.(*redis.Message) + Expect(msg.Channel).To(Equal("mychannel2")) + Expect(msg.Payload).To(Equal("hello2")) + } + + { + msgi, err := pubsub.ReceiveTimeout(ctx, time.Second) + Expect(err).NotTo(HaveOccurred()) + subscr := msgi.(*redis.Subscription) + Expect(subscr.Kind).To(Equal("sunsubscribe")) + Expect(subscr.Channel).To(Equal("mychannel")) + Expect(subscr.Count).To(Equal(1)) + } + + { + msgi, err := pubsub.ReceiveTimeout(ctx, time.Second) + Expect(err).NotTo(HaveOccurred()) + subscr := msgi.(*redis.Subscription) + Expect(subscr.Kind).To(Equal("sunsubscribe")) + Expect(subscr.Channel).To(Equal("mychannel2")) + Expect(subscr.Count).To(Equal(0)) + } + + stats := client.PoolStats() + Expect(stats.Misses).To(Equal(uint32(1))) + }) + + It("should ping/pong", func() { + _ = client.Subscribe(ctx, "mychannel") + res := client.Do(ctx, "ping") + Expect(res.Err()).NotTo(HaveOccurred()) + Expect(res.Val()).To(Equal("PONG")) + defer func() { + _ = client.Do(ctx, "unsubscribe", "mychannel") + }() + }) + + It("should multi-ReceiveMessage", func() { + pubsub := client.Subscribe(ctx, "mychannel") + defer pubsub.Close() + + subscr, err := pubsub.ReceiveTimeout(ctx, time.Second) + Expect(err).NotTo(HaveOccurred()) + Expect(subscr).To(Equal(&redis.Subscription{ + Kind: "subscribe", + Channel: "mychannel", + Count: 1, + })) + + err = client.Publish(ctx, "mychannel", "hello").Err() + Expect(err).NotTo(HaveOccurred()) + + err = client.Publish(ctx, "mychannel", "world").Err() + Expect(err).NotTo(HaveOccurred()) + + msg, err := pubsub.ReceiveMessage(ctx) + Expect(err).NotTo(HaveOccurred()) + Expect(msg.Channel).To(Equal("mychannel")) + Expect(msg.Payload).To(Equal("hello")) + + msg, err = pubsub.ReceiveMessage(ctx) + Expect(err).NotTo(HaveOccurred()) + Expect(msg.Channel).To(Equal("mychannel")) + Expect(msg.Payload).To(Equal("world")) + }) + + It("should return on Close", func() { + pubsub := client.Subscribe(ctx, "mychannel") + defer pubsub.Close() + + var wg sync.WaitGroup + wg.Add(1) + go func() { + defer GinkgoRecover() + + wg.Done() + defer wg.Done() + + _, err := pubsub.ReceiveMessage(ctx) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(SatisfyAny( + Equal("redis: client is closed"), + ContainSubstring("use of closed network connection"), + )) + }() + + wg.Wait() + wg.Add(1) + + Expect(pubsub.Close()).NotTo(HaveOccurred()) + + wg.Wait() + }) + + It("should ReceiveMessage without a subscription", func() { + timeout := 100 * time.Millisecond + + pubsub := client.Subscribe(ctx) + defer pubsub.Close() + + var wg sync.WaitGroup + wg.Add(1) + go func() { + defer GinkgoRecover() + defer wg.Done() + + time.Sleep(timeout) + + err := pubsub.Subscribe(ctx, "mychannel") + Expect(err).NotTo(HaveOccurred()) + + time.Sleep(timeout) + + err = client.Publish(ctx, "mychannel", "hello").Err() + Expect(err).NotTo(HaveOccurred()) + }() + + msg, err := pubsub.ReceiveMessage(ctx) + Expect(err).NotTo(HaveOccurred()) + Expect(msg.Channel).To(Equal("mychannel")) + Expect(msg.Payload).To(Equal("hello")) + + wg.Wait() + }) + + It("handles big message payload", func() { + pubsub := client.Subscribe(ctx, "mychannel") + defer pubsub.Close() + + ch := pubsub.Channel() + + bigVal := bigVal() + err := client.Publish(ctx, "mychannel", bigVal).Err() + Expect(err).NotTo(HaveOccurred()) + + var msg *redis.Message + Eventually(ch).Should(Receive(&msg)) + Expect(msg.Channel).To(Equal("mychannel")) + Expect(msg.Payload).To(Equal(string(bigVal))) + }) + + It("supports concurrent Ping and Receive", func() { + const N = 100 + + pubsub := client.Subscribe(ctx, "mychannel") + defer pubsub.Close() + + done := make(chan struct{}) + go func() { + defer GinkgoRecover() + + for i := 0; i < N; i++ { + _, err := pubsub.ReceiveTimeout(ctx, 5*time.Second) + Expect(err).NotTo(HaveOccurred()) + } + close(done) + }() + + for i := 0; i < N; i++ { + err := pubsub.Ping(ctx) + Expect(err).NotTo(HaveOccurred()) + } + + select { + case <-done: + case <-time.After(30 * time.Second): + Fail("timeout") + } + }) + + PIt("should ChannelMessage", func() { + pubsub := client.Subscribe(ctx, "mychannel") + defer pubsub.Close() + + ch := pubsub.Channel( + redis.WithChannelSize(10), + redis.WithChannelHealthCheckInterval(1*time.Second), + ) + + text := "test channel message" + err := client.Publish(ctx, "mychannel", text).Err() + Expect(err).NotTo(HaveOccurred()) + + var msg *redis.Message + Eventually(ch).Should(Receive(&msg)) + Expect(msg.Channel).To(Equal("mychannel")) + Expect(msg.Payload).To(Equal(text)) + }) +}) diff --git a/tests/integration/replication_test.go b/tests/integration/replication_test.go new file mode 100644 index 0000000000..663ec4a169 --- /dev/null +++ b/tests/integration/replication_test.go @@ -0,0 +1,525 @@ +package pika_integration + +import ( + "context" + "fmt" + "math/rand" + "os/exec" + "strings" + "time" + + . "github.com/bsm/ginkgo/v2" + . "github.com/bsm/gomega" + "github.com/redis/go-redis/v9" +) + +func cleanEnv(ctx context.Context, clientMaster, clientSlave *redis.Client) { + r := clientSlave.Do(ctx, "slaveof", "no", "one") + Expect(r.Err()).NotTo(HaveOccurred()) + Expect(r.Val()).To(Equal("OK")) + r = clientSlave.Do(ctx, "clearreplicationid") + r = clientMaster.Do(ctx, "clearreplicationid") + cmd := exec.Command("rm", "-rf", "/home/runner/work/pika/pika/dump") + err := cmd.Run() + if err != nil { + fmt.Println("remove dump fail!") + } + cmd = exec.Command("rm", "-rf", "/Users/runner/work/pika/pika/dump") + err = cmd.Run() + if err != nil { + fmt.Println("remove dump fail!") + } + cmd = exec.Command("rm", "-rf", "/__w/pika/pika/dump") + err = cmd.Run() + if err != nil { + fmt.Println("remove dump fail!") + } + +} + +func trySlave(ctx context.Context, clientSlave *redis.Client, ip string, port string) bool { + Expect(clientSlave.Do(ctx, "slaveof", ip, port).Val()).To(Equal("OK")) + infoRes := clientSlave.Info(ctx, "replication") + Expect(infoRes.Err()).NotTo(HaveOccurred()) + Expect(infoRes.Val()).To(ContainSubstring("role:slave")) + var count = 0 + for { + infoRes = clientSlave.Info(ctx, "replication") + Expect(infoRes.Err()).NotTo(HaveOccurred()) + count++ + if strings.Contains(infoRes.Val(), "master_link_status:up") { + return true + } else if count > 200 { + return false + } + time.Sleep(1 * time.Second) + } +} + +func randomString(length int) string { + rand.Seed(time.Now().UnixNano()) + b := make([]byte, length) + rand.Read(b) + return fmt.Sprintf("%x", b)[:length] +} + +func randomInt(max int) int { + rand.Seed(time.Now().UnixNano()) + return rand.Intn(max) +} + +func rpoplpushThread(ctx *context.Context, clientMaster *redis.Client) { + for i := 0; i < 10; i++ { + letters1 := randomString(5) + letters2 := randomString(5) + letters3 := randomString(5) + + clientMaster.LPush(*ctx, "blist0", letters1) + clientMaster.RPopLPush(*ctx, "blist0", "blist") + clientMaster.LPush(*ctx, "blist", letters1, letters2, letters3) + + clientMaster.LPop(*ctx, "blist") + clientMaster.RPop(*ctx, "blist") + clientMaster.LPush(*ctx, "blist0", letters3) + clientMaster.RPopLPush(*ctx, "blist0", "blist") + clientMaster.RPush(*ctx, "blist", letters3, letters2, letters1) + clientMaster.LPop(*ctx, "blist") + clientMaster.LPush(*ctx, "blist0", letters2) + clientMaster.RPopLPush(*ctx, "blist0", "blist") + clientMaster.RPop(*ctx, "blist") + } +} + +func randomBitopThread(ctx *context.Context, clientMaster *redis.Client) { + for i := 0; i < 20; i++ { + offset1 := randomInt(100) + offset2 := randomInt(100) + value1 := randomInt(1) + value2 := randomInt(1) + + clientMaster.SetBit(*ctx, "bitkey1", int64(offset1), value1) + clientMaster.SetBit(*ctx, "bitkey2", int64(offset1), value1) + clientMaster.BitOpAnd(*ctx, "bitkey_out", "bitkey1", "bitkey2") + clientMaster.SetBit(*ctx, "bitkey1", int64(offset1+offset2), value2) + clientMaster.SetBit(*ctx, "bitkey2", int64(offset2), value2) + clientMaster.BitOpOr(*ctx, "bitkey_out2", "bitkey1", "bitkey2") + } +} + +func randomSmoveThread(ctx *context.Context, clientMaster *redis.Client) { + member := randomString(5) + clientMaster.SAdd(*ctx, "sourceSet", member) + clientMaster.SAdd(*ctx, "sourceSet", member) + clientMaster.SAdd(*ctx, "sourceSet", member) + clientMaster.SRem(*ctx, "destSet", member) + clientMaster.SRem(*ctx, "destSet", member) + clientMaster.SMove(*ctx, "sourceSet", "destSet", member) +} + +func randomSdiffstoreThread(ctx *context.Context, clientMaster *redis.Client) { + for i := 0; i < 5; i++ { + clientMaster.SAdd(*ctx, "set1", randomString(5)) + clientMaster.SAdd(*ctx, "set2", randomString(5)) + clientMaster.SAdd(*ctx, "set1", randomString(5)) + clientMaster.SAdd(*ctx, "set2", randomString(5)) + clientMaster.SAdd(*ctx, "set1", randomString(5)) + clientMaster.SAdd(*ctx, "set2", randomString(5)) + clientMaster.SAdd(*ctx, "set1", randomString(5)) + clientMaster.SAdd(*ctx, "set2", randomString(5)) + clientMaster.SAdd(*ctx, "set1", randomString(5)) + clientMaster.SAdd(*ctx, "set2", randomString(5)) + clientMaster.SAdd(*ctx, "set1", randomString(5)) + clientMaster.SAdd(*ctx, "set2", randomString(5)) + clientMaster.SAdd(*ctx, "dest_set", randomString(5)) + clientMaster.SDiffStore(*ctx, "dest_set", "set1", "set2") + } +} + +func randomSinterstoreThread(ctx *context.Context, clientMaster *redis.Client) { + for i := 0; i < 5; i++ { + member := randomString(5) + member2 := randomString(5) + member3 := randomString(5) + member4 := randomString(5) + member5 := randomString(5) + member6 := randomString(5) + clientMaster.SAdd(*ctx, "set1", member) + clientMaster.SAdd(*ctx, "set2", member) + clientMaster.SAdd(*ctx, "set1", member2) + clientMaster.SAdd(*ctx, "set2", member2) + clientMaster.SAdd(*ctx, "set1", member3) + clientMaster.SAdd(*ctx, "set2", member3) + clientMaster.SAdd(*ctx, "set1", member4) + clientMaster.SAdd(*ctx, "set2", member4) + clientMaster.SAdd(*ctx, "set1", member5) + clientMaster.SAdd(*ctx, "set2", member5) + clientMaster.SAdd(*ctx, "set1", member6) + clientMaster.SAdd(*ctx, "set2", member6) + clientMaster.SInterStore(*ctx, "dest_set", "set1", "set2") + clientMaster.SAdd(*ctx, "dest_set", randomString(5)) + } +} + +func test_del_replication(ctx *context.Context, clientMaster, clientSlave *redis.Client) { + clientMaster.Del(*ctx, "blist0", "blist1", "blist2", "blist3") + clientMaster.Del(*ctx, "blist100", "blist101", "blist102", "blist103") + clientMaster.Del(*ctx, "blist0", "blist1", "blist2", "blist3") + clientMaster.RPush(*ctx, "blist3", "v2") + clientMaster.RPush(*ctx, "blist2", "v2") + clientMaster.RPop(*ctx, "blist2") + clientMaster.LPop(*ctx, "blist3") + + clientMaster.LPush(*ctx, "blist2", "v2") + clientMaster.LPop(*ctx, "blist2") + clientMaster.RPush(*ctx, "blist3", "v2") + clientMaster.RPop(*ctx, "blist3") + + clientMaster.LPush(*ctx, "blist2", "v2") + clientMaster.LPop(*ctx, "blist2") + clientMaster.RPush(*ctx, "blist3", "v2") + clientMaster.LPush(*ctx, "blist2", "v2") + + clientMaster.RPop(*ctx, "blist3") + clientMaster.LPop(*ctx, "blist2") + clientMaster.LPush(*ctx, "blist2", "v2") + clientMaster.RPush(*ctx, "blist3", "v2") + + clientMaster.RPop(*ctx, "blist3") + clientMaster.LPop(*ctx, "blist2") + clientMaster.RPush(*ctx, "blist3", "v2") + clientMaster.LPush(*ctx, "blist2", "v2") + + clientMaster.RPop(*ctx, "blist3") + clientMaster.RPush(*ctx, "blist3", "v2") + clientMaster.LPush(*ctx, "blist2", "v2") + clientMaster.RPush(*ctx, "blist3", "v2") + + clientMaster.RPush(*ctx, "blist3", "v2") + clientMaster.LPush(*ctx, "blist2", "v2") + clientMaster.RPush(*ctx, "blist3", "v2") + clientMaster.LPush(*ctx, "blist2", "v2") + + clientMaster.LPush(*ctx, "blist2", "v2") + clientMaster.RPush(*ctx, "blist3", "v2") + clientMaster.Del(*ctx, "blist1", "large", "blist2") + + clientMaster.RPush(*ctx, "blist1", "a", "latge", "c") + clientMaster.RPush(*ctx, "blist2", "d", "latge", "f") + + clientMaster.LPop(*ctx, "blist1") + clientMaster.RPop(*ctx, "blist1") + clientMaster.LPop(*ctx, "blist2") + clientMaster.RPop(*ctx, "blist2") + + clientMaster.Del(*ctx, "blist3") + clientMaster.LPop(*ctx, "blist2") + clientMaster.RPop(*ctx, "blist1") + time.Sleep(25 * time.Second) + + for i := int64(0); i < clientMaster.LLen(*ctx, "blist1").Val(); i++ { + Expect(clientMaster.LIndex(*ctx, "blist", i)).To(Equal(clientSlave.LIndex(*ctx, "blist", i))) + } + for i := int64(0); i < clientMaster.LLen(*ctx, "blist2").Val(); i++ { + Expect(clientMaster.LIndex(*ctx, "blist2", i)).To(Equal(clientSlave.LIndex(*ctx, "blist2", i))) + } + for i := int64(0); i < clientMaster.LLen(*ctx, "blist3").Val(); i++ { + Expect(clientMaster.LIndex(*ctx, "blist3", i)).To(Equal(clientSlave.LIndex(*ctx, "blist3", i))) + } + +} + +func randomZunionstoreThread(ctx *context.Context, clientMaster *redis.Client) { + for i := 0; i < 5; i++ { + clientMaster.Do(*ctx, "zadd", "zset1", randomInt(10), randomString(5)) + clientMaster.Do(*ctx, "zadd", "zset2", randomInt(10), randomString(5)) + clientMaster.Do(*ctx, "zadd", "zset2", randomInt(10), randomString(5)) + clientMaster.Do(*ctx, "zadd", "zset1", randomInt(10), randomString(5)) + clientMaster.Do(*ctx, "zadd", "zset2", randomInt(10), randomString(5)) + clientMaster.Do(*ctx, "zadd", "zset1", randomInt(10), randomString(5)) + clientMaster.Do(*ctx, "zadd", "zset2", randomInt(10), randomString(5)) + clientMaster.Do(*ctx, "zadd", "zset2", randomInt(10), randomString(5)) + clientMaster.Do(*ctx, "zadd", "zset1", randomInt(10), randomString(5)) + clientMaster.Do(*ctx, "zadd", "zset1", randomInt(10), randomString(5)) + clientMaster.Do(*ctx, "zadd", "zset2", randomInt(10), randomString(5)) + clientMaster.Do(*ctx, "zadd", "zset1", randomInt(10), randomString(5)) + clientMaster.ZUnionStore(*ctx, "zset_out", &redis.ZStore{Keys: []string{"zset1", "zset2"}, Weights: []float64{1, 1}}) + clientMaster.Do(*ctx, "zadd", "zset_out", randomInt(10), randomString(5)) + } +} + +func randomZinterstoreThread(ctx *context.Context, clientMaster *redis.Client) { + for i := 0; i < 5; i++ { + member := randomString(5) + member2 := randomString(5) + member3 := randomString(5) + member4 := randomString(5) + clientMaster.Do(*ctx, "zadd", "zset1", randomInt(5), member) + clientMaster.Do(*ctx, "zadd", "zset2", randomInt(5), member) + clientMaster.Do(*ctx, "zadd", "zset2", randomInt(5), member2) + clientMaster.Do(*ctx, "zadd", "zset1", randomInt(5), member2) + clientMaster.Do(*ctx, "zadd", "zset2", randomInt(5), member3) + clientMaster.Do(*ctx, "zadd", "zset1", randomInt(5), member3) + clientMaster.Do(*ctx, "zadd", "zset2", randomInt(5), member4) + clientMaster.Do(*ctx, "zadd", "zset2", randomInt(5), member4) + clientMaster.ZInterStore(*ctx, "zset_out", &redis.ZStore{Keys: []string{"zset1", "zset2"}, Weights: []float64{1, 1}}) + } +} + +func randomSunionstroeThread(ctx *context.Context, clientMaster *redis.Client) { + for i := 0; i < 5; i++ { + clientMaster.SAdd(*ctx, "set1", randomString(5)) + clientMaster.SAdd(*ctx, "set2", randomString(5)) + clientMaster.SAdd(*ctx, "set1", randomString(5)) + clientMaster.SAdd(*ctx, "set1", randomString(5)) + clientMaster.SAdd(*ctx, "set2", randomString(5)) + clientMaster.SAdd(*ctx, "set1", randomString(5)) + clientMaster.SAdd(*ctx, "set1", randomString(5)) + clientMaster.SAdd(*ctx, "set2", randomString(5)) + clientMaster.SAdd(*ctx, "set2", randomString(5)) + clientMaster.SAdd(*ctx, "set2", randomString(5)) + clientMaster.SAdd(*ctx, "set1", randomString(5)) + clientMaster.SAdd(*ctx, "set2", randomString(5)) + clientMaster.SAdd(*ctx, "set1", randomString(5)) + clientMaster.SAdd(*ctx, "set2", randomString(5)) + clientMaster.SUnionStore(*ctx, "set_out", "set1", "set2") + + } +} + +//func randomPfmergeThread(ctx *context.Context, clientMaster *redis.Client) { +// clientMaster.PFAdd(*ctx, "hll1", randomString(5)) +// clientMaster.PFAdd(*ctx, "hll2", randomString(5)) +// clientMaster.PFAdd(*ctx, "hll2", randomString(5)) +// clientMaster.PFAdd(*ctx, "hll1", randomString(5)) +// clientMaster.PFAdd(*ctx, "hll2", randomString(5)) +// clientMaster.PFAdd(*ctx, "hll1", randomString(5)) +// clientMaster.PFAdd(*ctx, "hll2", randomString(5)) +// clientMaster.PFAdd(*ctx, "hll1", randomString(5)) +// clientMaster.PFAdd(*ctx, "hll_out", randomString(5)) +// clientMaster.PFMerge(*ctx, "hll_out", "hll1", "hll2") +// clientMaster.PFAdd(*ctx, "hll_out", randomString(5)) +//} + +var _ = Describe("shuould replication ", func() { + Describe("all replication test", func() { + ctx := context.TODO() + var clientSlave *redis.Client + var clientMaster *redis.Client + + BeforeEach(func() { + clientMaster = redis.NewClient(pikaOptions1()) + clientSlave = redis.NewClient(pikaOptions2()) + cleanEnv(ctx, clientMaster, clientSlave) + Expect(clientSlave.FlushDB(ctx).Err()).NotTo(HaveOccurred()) + Expect(clientMaster.FlushDB(ctx).Err()).NotTo(HaveOccurred()) + time.Sleep(2 * time.Second) + }) + AfterEach(func() { + cleanEnv(ctx, clientMaster, clientSlave) + Expect(clientSlave.Close()).NotTo(HaveOccurred()) + Expect(clientMaster.Close()).NotTo(HaveOccurred()) + }) + It("Let The slave become a replica of The master ", func() { + infoRes := clientSlave.Info(ctx, "replication") + Expect(infoRes.Err()).NotTo(HaveOccurred()) + Expect(infoRes.Val()).To(ContainSubstring("role:master")) + infoRes = clientMaster.Info(ctx, "replication") + Expect(infoRes.Err()).NotTo(HaveOccurred()) + Expect(infoRes.Val()).To(ContainSubstring("role:master")) + + var count = 0 + for { + res := trySlave(ctx, clientSlave, "127.0.0.1", "9221") + if res { + break + } else if count > 4 { + break + } else { + cleanEnv(ctx, clientMaster, clientSlave) + count++ + } + } + + infoRes = clientSlave.Info(ctx, "replication") + Expect(infoRes.Err()).NotTo(HaveOccurred()) + Expect(infoRes.Val()).To(ContainSubstring("master_link_status:up")) + + infoRes = clientMaster.Info(ctx, "replication") + Expect(infoRes.Err()).NotTo(HaveOccurred()) + Expect(infoRes.Val()).To(ContainSubstring("connected_slaves:1")) + + slaveWrite := clientSlave.Set(ctx, "foo", "bar", 0) + Expect(slaveWrite.Err()).To(MatchError("ERR Server in read-only")) + + clientMaster.Del(ctx, "blist0", "blist1", "blist") + go rpoplpushThread(&ctx, clientMaster) + go rpoplpushThread(&ctx, clientMaster) + go rpoplpushThread(&ctx, clientMaster) + go rpoplpushThread(&ctx, clientMaster) + time.Sleep(25 * time.Second) + for i := int64(0); i < clientMaster.LLen(ctx, "blist").Val(); i++ { + Expect(clientMaster.LIndex(ctx, "blist", i)).To(Equal(clientSlave.LIndex(ctx, "blist", i))) + } + + Expect(clientMaster.Del(ctx, "bitkey1", "bitkey2", "bitkey_out1", "bitkey_out2").Err()).NotTo(HaveOccurred()) + go randomBitopThread(&ctx, clientMaster) + go randomBitopThread(&ctx, clientMaster) + go randomBitopThread(&ctx, clientMaster) + go randomBitopThread(&ctx, clientMaster) + time.Sleep(25 * time.Second) + master_key_out_count1 := clientMaster.Do(ctx, "bitcount", "bitkey_out1", 0, -1) + slave_key_out_count1 := clientSlave.Do(ctx, "bitcount", "bitkey_out1", 0, -1) + Expect(master_key_out_count1.Val()).To(Equal(slave_key_out_count1.Val())) + + master_key_out_count2 := clientMaster.Do(ctx, "bitcount", "bitkey_out2", 0, -1) + slave_key_out_count2 := clientSlave.Do(ctx, "bitcount", "bitkey_out2", 0, -1) + Expect(master_key_out_count2.Val()).To(Equal(slave_key_out_count2.Val())) + + clientMaster.Del(ctx, "source_set", "dest_set") + go randomSmoveThread(&ctx, clientMaster) + go randomSmoveThread(&ctx, clientMaster) + go randomSmoveThread(&ctx, clientMaster) + go randomSmoveThread(&ctx, clientMaster) + time.Sleep(25 * time.Second) + master_source_set := clientMaster.SMembers(ctx, "sourceSet") + Expect(master_source_set.Err()).NotTo(HaveOccurred()) + slave_source_set := clientSlave.SMembers(ctx, "sourceSet") + Expect(slave_source_set.Err()).NotTo(HaveOccurred()) + Expect(master_source_set.Val()).To(Equal(slave_source_set.Val())) + + master_dest_set := clientMaster.SMembers(ctx, "destSet") + Expect(master_dest_set.Err()).NotTo(HaveOccurred()) + slave_dest_set := clientSlave.SMembers(ctx, "destSet") + Expect(slave_dest_set.Err()).NotTo(HaveOccurred()) + Expect(master_dest_set.Val()).To(Equal(slave_dest_set.Val())) + + test_del_replication(&ctx, clientMaster, clientSlave) + + clientMaster.Del(ctx, "set1", "set2", "dest_set") + go randomSdiffstoreThread(&ctx, clientMaster) + go randomSdiffstoreThread(&ctx, clientMaster) + go randomSdiffstoreThread(&ctx, clientMaster) + go randomSdiffstoreThread(&ctx, clientMaster) + time.Sleep(25 * time.Second) + + master_set1 := clientMaster.SMembers(ctx, "set1") + Expect(master_set1.Err()).NotTo(HaveOccurred()) + slave_set1 := clientSlave.SMembers(ctx, "set1") + Expect(slave_set1.Err()).NotTo(HaveOccurred()) + Expect(master_set1.Val()).To(Equal(slave_set1.Val())) + + master_set2 := clientMaster.SMembers(ctx, "set2") + Expect(master_set2.Err()).NotTo(HaveOccurred()) + slave_set2 := clientSlave.SMembers(ctx, "set2") + Expect(slave_set2.Err()).NotTo(HaveOccurred()) + Expect(master_set2.Val()).To(Equal(slave_set2.Val())) + + master_dest_store_set := clientMaster.SMembers(ctx, "dest_set") + Expect(master_dest_store_set.Err()).NotTo(HaveOccurred()) + slave_dest_store_set := clientSlave.SMembers(ctx, "dest_set") + Expect(slave_dest_store_set.Err()).NotTo(HaveOccurred()) + Expect(master_dest_store_set.Val()).To(Equal(slave_dest_store_set.Val())) + + clientMaster.Del(ctx, "set1", "set2", "dest_set") + go randomSinterstoreThread(&ctx, clientMaster) + go randomSinterstoreThread(&ctx, clientMaster) + go randomSinterstoreThread(&ctx, clientMaster) + go randomSinterstoreThread(&ctx, clientMaster) + time.Sleep(25 * time.Second) + master_dest_interstore_set := clientMaster.SMembers(ctx, "dest_set") + Expect(master_dest_interstore_set.Err()).NotTo(HaveOccurred()) + slave_dest_interstore_set := clientSlave.SMembers(ctx, "dest_set") + Expect(slave_dest_interstore_set.Err()).NotTo(HaveOccurred()) + Expect(master_dest_interstore_set.Val()).To(Equal(slave_dest_interstore_set.Val())) + + //clientMaster.FlushAll(ctx) + //time.Sleep(3 * time.Second) + //go randomPfmergeThread(&ctx, clientMaster) + //go randomPfmergeThread(&ctx, clientMaster) + //go randomPfmergeThread(&ctx, clientMaster) + //go randomPfmergeThread(&ctx, clientMaster) + //time.Sleep(10 * time.Second) + //master_hll_out := clientMaster.PFCount(ctx, "hll_out") + //Expect(master_hll_out.Err()).NotTo(HaveOccurred()) + //slave_hll_out := clientSlave.PFCount(ctx, "hll_out") + //Expect(slave_hll_out.Err()).NotTo(HaveOccurred()) + //Expect(master_hll_out.Val()).To(Equal(slave_hll_out.Val())) + + clientMaster.Del(ctx, "zset1", "zset2", "zset_out") + go randomZunionstoreThread(&ctx, clientMaster) + go randomZunionstoreThread(&ctx, clientMaster) + go randomZunionstoreThread(&ctx, clientMaster) + go randomZunionstoreThread(&ctx, clientMaster) + time.Sleep(25 * time.Second) + master_zset_out := clientMaster.ZRange(ctx, "zset_out", 0, -1) + Expect(master_zset_out.Err()).NotTo(HaveOccurred()) + slave_zset_out := clientSlave.ZRange(ctx, "zset_out", 0, -1) + Expect(slave_zset_out.Err()).NotTo(HaveOccurred()) + Expect(master_zset_out.Val()).To(Equal(slave_zset_out.Val())) + + clientMaster.Del(ctx, "zset1", "zset2", "zset_out") + go randomZinterstoreThread(&ctx, clientMaster) + go randomZinterstoreThread(&ctx, clientMaster) + go randomZinterstoreThread(&ctx, clientMaster) + go randomZinterstoreThread(&ctx, clientMaster) + time.Sleep(25 * time.Second) + master_dest_interstore_set = clientMaster.SMembers(ctx, "dest_set") + Expect(master_dest_interstore_set.Err()).NotTo(HaveOccurred()) + slave_dest_interstore_set = clientSlave.SMembers(ctx, "dest_set") + Expect(slave_dest_interstore_set.Err()).NotTo(HaveOccurred()) + Expect(master_dest_interstore_set.Val()).To(Equal(slave_dest_interstore_set.Val())) + + clientMaster.Del(ctx, "set1", "set2", "set_out") + go randomSunionstroeThread(&ctx, clientMaster) + go randomSunionstroeThread(&ctx, clientMaster) + go randomSunionstroeThread(&ctx, clientMaster) + go randomSunionstroeThread(&ctx, clientMaster) + time.Sleep(25 * time.Second) + master_unionstore_set := clientMaster.SMembers(ctx, "set_out") + Expect(master_unionstore_set.Err()).NotTo(HaveOccurred()) + slave_unionstore_set := clientSlave.SMembers(ctx, "set_out") + Expect(slave_unionstore_set.Err()).NotTo(HaveOccurred()) + Expect(master_unionstore_set.Val()).To(Equal(slave_unionstore_set.Val())) + }) + + It("slaveof itself should return err", func() { + infoRes := clientSlave.Info(ctx, "replication") + Expect(infoRes.Err()).NotTo(HaveOccurred()) + Expect(infoRes.Val()).To(ContainSubstring("role:master")) + infoRes = clientMaster.Info(ctx, "replication") + Expect(infoRes.Err()).NotTo(HaveOccurred()) + Expect(infoRes.Val()).To(ContainSubstring("role:master")) + Expect(clientSlave.Do(ctx, "slaveof", "127.0.0.1", "9231").Err()).To(MatchError("ERR The master ip:port and the slave ip:port are the same")) + }) + + It("test slaveof with localhost&port", func() { + infoRes := clientSlave.Info(ctx, "replication") + Expect(infoRes.Err()).NotTo(HaveOccurred()) + Expect(infoRes.Val()).To(ContainSubstring("role:master")) + infoRes = clientMaster.Info(ctx, "replication") + Expect(infoRes.Err()).NotTo(HaveOccurred()) + Expect(infoRes.Val()).To(ContainSubstring("role:master")) + + var count = 0 + for { + res := trySlave(ctx, clientSlave, "localhost", "9221") + if res { + break + } else if count > 4 { + break + } else { + cleanEnv(ctx, clientMaster, clientSlave) + count++ + } + } + infoRes = clientSlave.Info(ctx, "replication") + Expect(infoRes.Err()).NotTo(HaveOccurred()) + Expect(infoRes.Val()).To(ContainSubstring("master_link_status:up")) + infoRes = clientMaster.Info(ctx, "replication") + Expect(infoRes.Err()).NotTo(HaveOccurred()) + Expect(infoRes.Val()).To(ContainSubstring("connected_slaves:1")) + }) + + }) + +}) diff --git a/tests/integration/server_test.go b/tests/integration/server_test.go index e2ce6d6df9..9d97b86a5e 100644 --- a/tests/integration/server_test.go +++ b/tests/integration/server_test.go @@ -16,6 +16,7 @@ var _ = Describe("Server", func() { BeforeEach(func() { client = redis.NewClient(pikaOptions1()) Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred()) + time.Sleep(1 * time.Second) }) AfterEach(func() { @@ -23,35 +24,66 @@ var _ = Describe("Server", func() { }) Describe("server", func() { - It("should Auth", func() { - cmds, err := client.Pipelined(ctx, func(pipe redis.Pipeliner) error { - pipe.Auth(ctx, "112121") - pipe.Auth(ctx, "") + It("should Auth", func() { + r := client.Do(ctx, "AUTH", "foo") + Expect(r.Err()).To(MatchError("ERR Client sent AUTH, but no password is set")) + + r = client.Do(ctx, "config", "set", "requirepass", "foobar") + Expect(r.Val()).To(Equal("OK")) + + r = client.Do(ctx, "AUTH", "wrong!") + Expect(r.Err()).To(MatchError("ERR invalid password")) + + r = client.Do(ctx, "AUTH", "foo", "bar") + Expect(r.Err()).To(MatchError("ERR wrong number of arguments for 'auth' command")) + + r = client.Do(ctx, "AUTH", "foobar") + Expect(r.Val()).To(Equal("OK")) + + r = client.Do(ctx, "config", "set", "requirepass", "") + Expect(r.Val()).To(Equal("OK")) + + }) + + It("should hello", func() { + cmds, _ := client.Pipelined(ctx, func(pipe redis.Pipeliner) error { + pipe.Hello(ctx, 1, "", "", "") + pipe.Hello(ctx, 2, "", "", "") + pipe.Hello(ctx, 3, "", "", "") return nil }) - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("ERR Client sent AUTH, but no password is set")) - Expect(cmds[0].Err().Error()).To(ContainSubstring("ERR Client sent AUTH, but no password is set")) - Expect(cmds[1].Err().Error()).To(ContainSubstring("ERR Client sent AUTH, but no password is set")) - - stats := client.PoolStats() - Expect(stats.Hits).To(Equal(uint32(1))) - Expect(stats.Misses).To(Equal(uint32(1))) - Expect(stats.Timeouts).To(Equal(uint32(0))) - Expect(stats.TotalConns).To(Equal(uint32(1))) - Expect(stats.IdleConns).To(Equal(uint32(1))) - }) - - //It("should hello", func() { - // cmds, err := client.Pipelined(ctx, func(pipe redis.Pipeliner) error { - // pipe.Hello(ctx, 2, "", "", "") - // return nil - // }) - // Expect(err).NotTo(HaveOccurred()) - // m, err := cmds[0].(*redis.MapStringInterfaceCmd).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(m["proto"]).To(Equal(int64(2))) - //}) + _, err1 := cmds[0].(*redis.MapStringInterfaceCmd).Result() + m2, err2 := cmds[1].(*redis.MapStringInterfaceCmd).Result() + m3, err3 := cmds[2].(*redis.MapStringInterfaceCmd).Result() + Expect(err1).To(MatchError("ERR -NOPROTO unsupported protocol version")) + + Expect(err2).NotTo(HaveOccurred()) + Expect(m2["proto"]).To(Equal(int64(2))) + + Expect(err3).NotTo(HaveOccurred()) + Expect(m3["proto"]).To(Equal(int64(2))) + + r := client.Do(ctx, "hello", "auth") + Expect(r.Err()).To(MatchError("ERR Protocol version is not an integer or out of range")) + + r = client.Do(ctx, "hello", "3", "SETNAME", "pika") + Expect(r.Err()).NotTo(HaveOccurred()) + + r = client.Do(ctx, "CLIENT", "GETNAME") + Expect(r.Val()).To(Equal("pika")) + + r = client.Do(ctx, "config", "set", "requirepass", "foobar") + Expect(r.Val()).To(Equal("OK")) + + r = client.Do(ctx, "hello", "3", "auth", "wrong") + Expect(r.Err()).To(MatchError("ERR invalid password")) + + r = client.Do(ctx, "hello", "3", "auth", "foobar") + Expect(r.Err()).NotTo(HaveOccurred()) + + r = client.Do(ctx, "config", "set", "requirepass", "") + + }) It("should Echo", func() { pipe := client.Pipeline() @@ -69,17 +101,6 @@ var _ = Describe("Server", func() { Expect(ping.Val()).To(Equal("PONG")) }) - //It("should Wait", func() { - // const wait = 3 * time.Second - // - // // assume testing on single redis instance - // start := time.Now() - // val, err := client.Wait(ctx, 1, wait).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(val).To(Equal(int64(0))) - // Expect(time.Now()).To(BeTemporally("~", start.Add(wait), 3*time.Second)) - //}) - It("should Select", func() { pipe := client.Pipeline() sel := pipe.Select(ctx, 0) @@ -88,17 +109,11 @@ var _ = Describe("Server", func() { Expect(sel.Err()).NotTo(HaveOccurred()) Expect(sel.Val()).To(Equal("OK")) - }) - //It("should SwapDB", func() { - // pipe := client.Pipeline() - // sel := pipe.SwapDB(ctx, 1, 2) - // _, err := pipe.Exec(ctx) - // Expect(err).NotTo(HaveOccurred()) - // - // Expect(sel.Err()).NotTo(HaveOccurred()) - // Expect(sel.Val()).To(Equal("OK")) - //}) + sel = pipe.Select(ctx, 4) + _, err = pipe.Exec(ctx) + Expect(err).To(MatchError("ERR invalid DB index for 'select DB index is out of range'")) + }) It("should BgRewriteAOF", func() { Skip("flaky test") @@ -110,11 +125,11 @@ var _ = Describe("Server", func() { // Test scenario: Execute the del command, after executing bgsave, the get data will be wrong It("should BgSave", func() { - res := client.Set(ctx, "bgsava_key", "bgsava_value", 0) + res := client.Set(ctx, "bgsave_key", "bgsave_value", 0) Expect(res.Err()).NotTo(HaveOccurred()) - _ = client.Set(ctx, "bgsava_key2", "bgsava_value3", 0) + _ = client.Set(ctx, "bgsave_key2", "bgsave_value3", 0) Expect(res.Err()).NotTo(HaveOccurred()) - _ = client.HSet(ctx, "bgsava_key3", "bgsava_value", 0) + _ = client.HSet(ctx, "bgsave_key3", "bgsave_value", 0) Expect(res.Err()).NotTo(HaveOccurred()) res2, err2 := client.BgSave(ctx).Result() @@ -122,16 +137,16 @@ var _ = Describe("Server", func() { Expect(res.Err()).NotTo(HaveOccurred()) Expect(res2).To(ContainSubstring("Background saving started")) - res = client.Set(ctx, "bgsava_key", "bgsava_value", 0) + res = client.Set(ctx, "bgsave_key", "bgsave_value", 0) Expect(res.Err()).NotTo(HaveOccurred()) - res = client.Set(ctx, "bgsava_key2", "bgsava_value2", 0) + res = client.Set(ctx, "bgsave_key2", "bgsave_value2", 0) Expect(res.Err()).NotTo(HaveOccurred()) - res = client.Set(ctx, "bgsava_key3", "bgsava_value3", 0) + res = client.Set(ctx, "bgsave_key3", "bgsave_value3", 0) Expect(res.Err()).NotTo(HaveOccurred()) - hSet := client.HSet(ctx, "bgsava_key4", "bgsava_value4", 0) + hSet := client.HSet(ctx, "bgsave_key4", "bgsave_value4", 0) Expect(hSet.Err()).NotTo(HaveOccurred()) - _, err := client.Del(ctx, "bgsava_key").Result() + _, err := client.Del(ctx, "bgsave_key").Result() Expect(err).NotTo(HaveOccurred()) res2, err2 = client.BgSave(ctx).Result() @@ -139,103 +154,28 @@ var _ = Describe("Server", func() { Expect(res.Err()).NotTo(HaveOccurred()) Expect(res2).To(ContainSubstring("Background saving started")) - val, err := client.Get(ctx, "bgsava_key2").Result() + val, err := client.Get(ctx, "bgsave_key2").Result() Expect(res.Err()).NotTo(HaveOccurred()) - Expect(val).To(ContainSubstring("bgsava_value2")) + Expect(val).To(ContainSubstring("bgsave_value2")) - _, err = client.Del(ctx, "bgsava_key4").Result() + _, err = client.Del(ctx, "bgsave_key4").Result() Expect(err).NotTo(HaveOccurred()) - get := client.Get(ctx, "bgsava_key3") + get := client.Get(ctx, "bgsave_key3") Expect(get.Err()).NotTo(HaveOccurred()) - Expect(get.Val()).To(Equal("bgsava_value3")) - }) - - //It("Should CommandGetKeys", func() { - // keys, err := client.CommandGetKeys(ctx, "MSET", "a", "b", "c", "d", "e", "f").Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(keys).To(Equal([]string{"a", "c", "e"})) - // - // keys, err = client.CommandGetKeys(ctx, "EVAL", "not consulted", "3", "key1", "key2", "key3", "arg1", "arg2", "arg3", "argN").Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(keys).To(Equal([]string{"key1", "key2", "key3"})) - // - // keys, err = client.CommandGetKeys(ctx, "SORT", "mylist", "ALPHA", "STORE", "outlist").Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(keys).To(Equal([]string{"mylist", "outlist"})) - // - // _, err = client.CommandGetKeys(ctx, "FAKECOMMAND", "arg1", "arg2").Result() - // Expect(err).To(HaveOccurred()) - // Expect(err).To(MatchError("ERR Invalid command specified")) - //}) - - //It("should CommandGetKeysAndFlags", func() { - // keysAndFlags, err := client.CommandGetKeysAndFlags(ctx, "LMOVE", "mylist1", "mylist2", "left", "left").Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(keysAndFlags).To(Equal([]redis.KeyFlags{ - // { - // Key: "mylist1", - // Flags: []string{"RW", "access", "delete"}, - // }, - // { - // Key: "mylist2", - // Flags: []string{"RW", "insert"}, - // }, - // })) - // - // _, err = client.CommandGetKeysAndFlags(ctx, "FAKECOMMAND", "arg1", "arg2").Result() - // Expect(err).To(HaveOccurred()) - // Expect(err).To(MatchError("ERR Invalid command specified")) - //}) - - // todo 存在bug,待修复 - //It("should ClientKill", func() { - // r := client.ClientKill(ctx, "1.1.1.1:1111") - // Expect(r.Err()).To(MatchError("ERR No such client")) - // Expect(r.Val()).To(Equal("")) - //}) - - //It("should ClientKillByFilter", func() { - // r := client.ClientKillByFilter(ctx, "TYPE", "test") - // Expect(r.Err()).To(MatchError("ERR Unknown client type 'test'")) - // Expect(r.Val()).To(Equal(int64(0))) - //}) - - //It("should ClientID", func() { - // err := client.ClientID(ctx).Err() - // Expect(err).NotTo(HaveOccurred()) - // Expect(client.ClientID(ctx).Val()).To(BeNumerically(">=", 0)) - //}) - // - //It("should ClientUnblock", func() { - // id := client.ClientID(ctx).Val() - // r, err := client.ClientUnblock(ctx, id).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(r).To(Equal(int64(0))) - //}) - // - //It("should ClientUnblockWithError", func() { - // id := client.ClientID(ctx).Val() - // r, err := client.ClientUnblockWithError(ctx, id).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(r).To(Equal(int64(0))) - //}) - - //It("should ClientInfo", func() { - // info, err := client.ClientInfo(ctx).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(info).NotTo(BeNil()) - //}) - - //It("should ClientPause", func() { - // err := client.ClientPause(ctx, time.Second).Err() - // Expect(err).NotTo(HaveOccurred()) - // - // start := time.Now() - // err = client.Ping(ctx).Err() - // Expect(err).NotTo(HaveOccurred()) - // Expect(time.Now()).To(BeTemporally("~", start.Add(time.Second), 800*time.Millisecond)) - //}) + Expect(get.Val()).To(Equal("bgsave_value3")) + }) + + It("should ClientKill", func() { + r := client.ClientKill(ctx, "1.1.1.1:1111") + Expect(r.Err()).To(MatchError("ERR No such client")) + Expect(r.Val()).To(Equal("")) + }) + + It("should client list", func() { + Expect(client.ClientList(ctx).Val()).NotTo(BeEmpty()) + Expect(client.ClientList(ctx).Val()).To(ContainSubstring("addr=")) + }) It("should ClientSetName and ClientGetName", func() { pipe := client.Pipeline() @@ -282,7 +222,19 @@ var _ = Describe("Server", func() { }) It("should DBSize", func() { + Expect(client.Set(ctx, "key", "value", 0).Val()).To(Equal("OK")) + Expect(client.Do(ctx, "info", "keyspace", "1").Err()).NotTo(HaveOccurred()) + time.Sleep(1 * time.Second) size, err := client.DBSize(ctx).Result() + time.Sleep(500 * time.Millisecond) + Expect(err).NotTo(HaveOccurred()) + Expect(size).To(Equal(int64(1))) + + Expect(client.Del(ctx, "key").Val()).To(Equal(int64(1))) + Expect(client.Do(ctx, "info", "keyspace", "1").Err()).NotTo(HaveOccurred()) + time.Sleep(1 * time.Second) + size, err = client.DBSize(ctx).Result() + time.Sleep(500 * time.Millisecond) Expect(err).NotTo(HaveOccurred()) Expect(size).To(Equal(int64(0))) }) @@ -291,6 +243,19 @@ var _ = Describe("Server", func() { info := client.Info(ctx) Expect(info.Err()).NotTo(HaveOccurred()) Expect(info.Val()).NotTo(Equal("")) + + info = client.Info(ctx, "replication") + Expect(info.Err()).NotTo(HaveOccurred()) + Expect(info.Val()).NotTo(Equal("")) + Expect(info.Val()).To(ContainSubstring("ReplicationID")) + Expect(info.Val()).To(ContainSubstring("role")) + Expect(info.Val()).To(ContainSubstring("connected_slaves")) + + info = client.Info(ctx, "cpu") + Expect(info.Err()).NotTo(HaveOccurred()) + Expect(info.Val()).NotTo(Equal("")) + Expect(info.Val()).To(ContainSubstring(`used_cpu_sys`)) + }) It("should Info cpu", func() { @@ -300,41 +265,64 @@ var _ = Describe("Server", func() { Expect(info.Val()).To(ContainSubstring(`used_cpu_sys`)) }) - //It("should Info cpu and memory", func() { - // info := client.Info(ctx, "cpu", "memory") - // Expect(info.Err()).NotTo(HaveOccurred()) - // Expect(info.Val()).NotTo(Equal("")) - // Expect(info.Val()).To(ContainSubstring(`used_cpu_sys`)) - // Expect(info.Val()).To(ContainSubstring(`memory`)) - //}) - // - //It("should LastSave", func() { - // lastSave := client.LastSave(ctx) - // Expect(lastSave.Err()).NotTo(HaveOccurred()) - // Expect(lastSave.Val()).NotTo(Equal(0)) - //}) - - //It("should Save", func() { - // - // val := client.Save(ctx) - // fmt.Println(val) - // - // // workaround for "ERR Background save already in progress" - // Eventually(func() string { - // return client.Save(ctx).Val() - // }, "10s").Should(Equal("OK")) - //}) - - // todo 待回滚 - //It("should SlaveOf", func() { - // slaveOf := client.SlaveOf(ctx, "localhost", "8888") - // Expect(slaveOf.Err()).NotTo(HaveOccurred()) - // Expect(slaveOf.Val()).To(Equal("OK")) - // - // slaveOf = client.SlaveOf(ctx, "NO", "ONE") - // Expect(slaveOf.Err()).NotTo(HaveOccurred()) - // Expect(slaveOf.Val()).To(Equal("OK")) - //}) + It("should keyspace", func() { + r := client.Set(ctx, "key", "value", 0) + Expect(r.Err()).NotTo(HaveOccurred()) + Expect(r.Val()).To(Equal("OK")) + Expect(client.Get(ctx, "key").Val()).To(Equal("value")) + Expect(client.Del(ctx, "key").Val()).To(Equal(int64(1))) + Expect(client.Get(ctx, "key").Err()).To(MatchError(redis.Nil)) + + Expect(client.Set(ctx, "key1", "value1", 0).Val()).To(Equal("OK")) + Expect(client.Set(ctx, "key2", "value2", 0).Val()).To(Equal("OK")) + Expect(client.Set(ctx, "key3", "value3", 0).Val()).To(Equal("OK")) + Expect(client.Del(ctx, "key1", "key2", "key3").Val()).To(Equal(int64(3))) + + Expect(client.Set(ctx, "key_1", "value1", 0).Val()).To(Equal("OK")) + Expect(client.Set(ctx, "key_2", "value2", 0).Val()).To(Equal("OK")) + Expect(client.Keys(ctx, "key_*").Val()).To(Equal([]string{"key_1", "key_2"})) + + Expect(client.Set(ctx, "key1", "value1", 0).Val()).To(Equal("OK")) + Expect(client.Set(ctx, "key2", "value2", 0).Val()).To(Equal("OK")) + Expect(client.Keys(ctx, "*").Err()).NotTo(HaveOccurred()) + + Expect(client.Do(ctx, "info", "keyspace", "1").Err()).NotTo(HaveOccurred()) + time.Sleep(100 * time.Millisecond) + Expect(client.Do(ctx, "dbsize").Val()).To(Equal(int64(4))) + + Expect(client.Del(ctx, "key_1", "key_2", "key1", "key2").Val()).To(Equal(int64(4))) + + Expect(client.Set(ctx, "NewKey", "value", 0).Val()).To(Equal("OK")) + Expect(client.Exists(ctx, "NewKey").Val()).To(Equal(int64(1))) + Expect(client.Del(ctx, "NewKey").Val()).To(Equal(int64(1))) + Expect(client.Exists(ctx, "NewKey").Val()).To(Equal(int64(0))) + + Expect(client.Do(ctx, "foocommand").Err()).To(MatchError("ERR unknown command \"foocommand\"")) + + }) + + It("should Incr", func() { + Expect(client.Incr(ctx, "nonexist").Val()).To(Equal(int64(1))) + Expect(client.Get(ctx, "nonexist").Val()).To(Equal("1")) + + Expect(client.Incr(ctx, "nonexist").Val()).To(Equal(int64(2))) + + Expect(client.Set(ctx, "existval", 10, 0).Val()).To(Equal("OK")) + Expect(client.Incr(ctx, "existval").Val()).To(Equal(int64(11))) + + Expect(client.IncrByFloat(ctx, "nonexist2", 1.0).Val()).To(Equal(float64(1))) + Expect(client.Get(ctx, "nonexist2").Val()).To(Equal("1")) + Expect(client.IncrByFloat(ctx, "nonexist2", 0.99).Val()).To(Equal(1.99)) + + }) + + It("should Incr big num", func() { + Expect(client.Set(ctx, "existval", 17179869184, 0).Val()).To(Equal("OK")) + Expect(client.Incr(ctx, "existval").Val()).To(Equal(int64(17179869185))) + + Expect(client.Set(ctx, "existval2", 17179869184, 0).Val()).To(Equal("OK")) + Expect(client.IncrBy(ctx, "existval2", 17179869184).Val()).To(Equal(int64(34359738368))) + }) It("should Time", func() { tm, err := client.Time(ctx).Result() @@ -342,77 +330,241 @@ var _ = Describe("Server", func() { Expect(tm).To(BeTemporally("~", time.Now(), 3*time.Second)) }) - //It("should Command", func() { - // cmds, err := client.Command(ctx).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(len(cmds)).To(BeNumerically("~", 240, 25)) - // - // cmd := cmds["mget"] - // Expect(cmd.Name).To(Equal("mget")) - // Expect(cmd.Arity).To(Equal(int8(-2))) - // Expect(cmd.Flags).To(ContainElement("readonly")) - // Expect(cmd.FirstKeyPos).To(Equal(int8(1))) - // Expect(cmd.LastKeyPos).To(Equal(int8(-1))) - // Expect(cmd.StepCount).To(Equal(int8(1))) - // - // cmd = cmds["ping"] - // Expect(cmd.Name).To(Equal("ping")) - // Expect(cmd.Arity).To(Equal(int8(-1))) - // Expect(cmd.Flags).To(ContainElement("fast")) - // Expect(cmd.FirstKeyPos).To(Equal(int8(0))) - // Expect(cmd.LastKeyPos).To(Equal(int8(0))) - // Expect(cmd.StepCount).To(Equal(int8(0))) - //}) - // - //It("should return all command names", func() { - // cmdList := client.CommandList(ctx, nil) - // Expect(cmdList.Err()).NotTo(HaveOccurred()) - // cmdNames := cmdList.Val() - // - // Expect(cmdNames).NotTo(BeEmpty()) - // - // // Assert that some expected commands are present in the list - // Expect(cmdNames).To(ContainElement("get")) - // Expect(cmdNames).To(ContainElement("set")) - // Expect(cmdNames).To(ContainElement("hset")) - //}) - // - //It("should filter commands by module", func() { - // filter := &redis.FilterBy{ - // Module: "JSON", - // } - // cmdList := client.CommandList(ctx, filter) - // Expect(cmdList.Err()).NotTo(HaveOccurred()) - // Expect(cmdList.Val()).To(HaveLen(0)) - //}) - // - //It("should filter commands by ACL category", func() { - // - // filter := &redis.FilterBy{ - // ACLCat: "admin", - // } - // - // cmdList := client.CommandList(ctx, filter) - // Expect(cmdList.Err()).NotTo(HaveOccurred()) - // cmdNames := cmdList.Val() - // - // // Assert that the returned list only contains commands from the admin ACL category - // Expect(len(cmdNames)).To(BeNumerically(">", 10)) - //}) - // - //It("should filter commands by pattern", func() { - // filter := &redis.FilterBy{ - // Pattern: "*GET*", - // } - // cmdList := client.CommandList(ctx, filter) - // Expect(cmdList.Err()).NotTo(HaveOccurred()) - // cmdNames := cmdList.Val() - // - // // Assert that the returned list only contains commands that match the given pattern - // Expect(cmdNames).To(ContainElement("get")) - // Expect(cmdNames).To(ContainElement("getbit")) - // Expect(cmdNames).To(ContainElement("getrange")) - // Expect(cmdNames).NotTo(ContainElement("set")) - //}) + It("should unlink", func() { + command := "UNLINK" + Expect(client.MSet(ctx, "key1", "value1", "key2", "value2").Val()).To(Equal("OK")) + Expect(client.Do(ctx, command, "key1", "key2").Val()).To(Equal(int64(2))) + Expect(client.Exists(ctx, "key", "key2").Val()).To(Equal(int64(0))) + + Expect(client.LPush(ctx, "mlist", "value1", "value2").Val()).To(Equal(int64(2))) + Expect(client.Do(ctx, command, "mlist").Val()).To(Equal(int64(1))) + Expect(client.Exists(ctx, "mlist").Val()).To(Equal(int64(0))) + + Expect(client.SAdd(ctx, "mset", "value1", "value2").Val()).To(Equal(int64(2))) + Expect(client.Do(ctx, command, "mset").Val()).To(Equal(int64(1))) + Expect(client.Exists(ctx, "mset").Val()).To(Equal(int64(0))) + + Expect(client.HSet(ctx, "mhash", "key1", "value1").Val()).To(Equal(int64(1))) + Expect(client.HSet(ctx, "mhash", "key2", "value2").Val()).To(Equal(int64(1))) + Expect(client.Do(ctx, command, "mhash").Val()).To(Equal(int64(1))) + Expect(client.Exists(ctx, "mhash").Val()).To(Equal(int64(0))) + }) + + It("should type", func() { + Expect(client.Set(ctx, "key", "value", 0).Val()).To(Equal("OK")) + Expect(client.LPush(ctx, "mlist", "hello").Val()).To(Equal(int64(1))) + Expect(client.SAdd(ctx, "mset", "world").Val()).To(Equal(int64(1))) + + Expect(client.Type(ctx, "key").Val()).To(Equal("string")) + Expect(client.Type(ctx, "mlist").Val()).To(Equal("list")) + Expect(client.Type(ctx, "mset").Val()).To(Equal("set")) + }) }) + + Describe("Bit", func() { + It("should BitCount", func() { + set := client.Set(ctx, "key", "foobar", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + bitCount := client.BitCount(ctx, "key", nil) + Expect(bitCount.Err()).NotTo(HaveOccurred()) + Expect(bitCount.Val()).To(Equal(int64(26))) + + bitCount = client.BitCount(ctx, "key", &redis.BitCount{ + Start: 0, + End: 0, + }) + Expect(bitCount.Err()).NotTo(HaveOccurred()) + Expect(bitCount.Val()).To(Equal(int64(4))) + + bitCount = client.BitCount(ctx, "key", &redis.BitCount{ + Start: 1, + End: 1, + }) + Expect(bitCount.Err()).NotTo(HaveOccurred()) + Expect(bitCount.Val()).To(Equal(int64(6))) + }) + + It("should BitOpAnd", func() { + set := client.Set(ctx, "key1", "1", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + set = client.Set(ctx, "key2", "0", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + bitOpAnd := client.BitOpAnd(ctx, "dest", "key1", "key2") + Expect(bitOpAnd.Err()).NotTo(HaveOccurred()) + Expect(bitOpAnd.Val()).To(Equal(int64(1))) + + get := client.Get(ctx, "dest") + Expect(get.Err()).NotTo(HaveOccurred()) + Expect(get.Val()).To(Equal("0")) + }) + + It("should BitOpOr", func() { + set := client.Set(ctx, "key1", "1", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + set = client.Set(ctx, "key2", "0", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + bitOpOr := client.BitOpOr(ctx, "dest", "key1", "key2") + Expect(bitOpOr.Err()).NotTo(HaveOccurred()) + Expect(bitOpOr.Val()).To(Equal(int64(1))) + + get := client.Get(ctx, "dest") + Expect(get.Err()).NotTo(HaveOccurred()) + Expect(get.Val()).To(Equal("1")) + }) + + It("should BitOpXor", func() { + set := client.Set(ctx, "key1", "\xff", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + set = client.Set(ctx, "key2", "\x0f", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + bitOpXor := client.BitOpXor(ctx, "dest", "key1", "key2") + Expect(bitOpXor.Err()).NotTo(HaveOccurred()) + Expect(bitOpXor.Val()).To(Equal(int64(1))) + + get := client.Get(ctx, "dest") + Expect(get.Err()).NotTo(HaveOccurred()) + Expect(get.Val()).To(Equal("\xf0")) + }) + + It("should BitOpNot", func() { + set := client.Set(ctx, "key1", "\x00", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + bitOpNot := client.BitOpNot(ctx, "dest", "key1") + Expect(bitOpNot.Err()).NotTo(HaveOccurred()) + Expect(bitOpNot.Val()).To(Equal(int64(1))) + + get := client.Get(ctx, "dest") + Expect(get.Err()).NotTo(HaveOccurred()) + Expect(get.Val()).To(Equal("\xff")) + }) + + It("should BitPos", func() { + err := client.Set(ctx, "mykey", "\xff\xf0\x00", 0).Err() + Expect(err).NotTo(HaveOccurred()) + + pos, err := client.BitPos(ctx, "mykey", 0).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(pos).To(Equal(int64(12))) + + pos, err = client.BitPos(ctx, "mykey", 1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(pos).To(Equal(int64(0))) + + pos, err = client.BitPos(ctx, "mykey", 0, 2).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(pos).To(Equal(int64(16))) + + pos, err = client.BitPos(ctx, "mykey", 1, 2).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(pos).To(Equal(int64(-1))) + + pos, err = client.BitPos(ctx, "mykey", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(pos).To(Equal(int64(16))) + + pos, err = client.BitPos(ctx, "mykey", 1, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(pos).To(Equal(int64(-1))) + + pos, err = client.BitPos(ctx, "mykey", 0, 2, 1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(pos).To(Equal(int64(-1))) + + pos, err = client.BitPos(ctx, "mykey", 0, 0, -3).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(pos).To(Equal(int64(-1))) + + pos, err = client.BitPos(ctx, "mykey", 0, 0, 0).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(pos).To(Equal(int64(-1))) + }) + + It("should BitPosSpan", func() { + err := client.Set(ctx, "mykey", "\x00\xff\x00", 0).Err() + Expect(err).NotTo(HaveOccurred()) + }) + + It("should SetBit", func() { + Expect(client.SetBit(ctx, "bit", 10086, 1).Val()).To(Equal(int64(0))) + Expect(client.GetBit(ctx, "bit", 10086).Val()).To(Equal(int64(1))) + Expect(client.GetBit(ctx, "bit", 100).Val()).To(Equal(int64(0))) + }) + + It("should GetBit", func() { + setBit := client.SetBit(ctx, "key", 7, 1) + Expect(setBit.Err()).NotTo(HaveOccurred()) + Expect(setBit.Val()).To(Equal(int64(0))) + + getBit := client.GetBit(ctx, "key", 0) + Expect(getBit.Err()).NotTo(HaveOccurred()) + Expect(getBit.Val()).To(Equal(int64(0))) + + getBit = client.GetBit(ctx, "key", 7) + Expect(getBit.Err()).NotTo(HaveOccurred()) + Expect(getBit.Val()).To(Equal(int64(1))) + + getBit = client.GetBit(ctx, "key", 100) + Expect(getBit.Err()).NotTo(HaveOccurred()) + Expect(getBit.Val()).To(Equal(int64(0))) + }) + }) + + Describe("Expire", func() { + It("should expire", func() { + Expect(client.Set(ctx, "key_3s", "value", 0).Val()).To(Equal("OK")) + Expect(client.Expire(ctx, "key_3s", 3*time.Second).Val()).To(Equal(true)) + Expect(client.TTL(ctx, "key").Val()).NotTo(Equal(int64(-2))) + + time.Sleep(4 * time.Second) + Expect(client.TTL(ctx, "key_3s").Val()).To(Equal(time.Duration(-2))) + Expect(client.Get(ctx, "key_3s").Err()).To(MatchError(redis.Nil)) + Expect(client.Exists(ctx, "key_3s").Val()).To(Equal(int64(0))) + + Expect(client.Do(ctx, "expire", "foo", "bar").Err()).To(MatchError("ERR value is not an integer or out of range")) + + }) + + It("should pexpire", func() { + Expect(client.Set(ctx, "key_3000ms", "value", 0).Val()).To(Equal("OK")) + Expect(client.PExpire(ctx, "key_3000ms", 3000*time.Millisecond).Val()).To(Equal(true)) + Expect(client.PTTL(ctx, "key").Val()).NotTo(Equal(int64(-2))) + + time.Sleep(4 * time.Second) + Expect(client.PTTL(ctx, "key_3000ms").Val()).To(Equal(time.Duration(-2))) + Expect(client.Get(ctx, "key_3000ms").Err()).To(MatchError(redis.Nil)) + Expect(client.Exists(ctx, "key_3000ms").Val()).To(Equal(int64(0))) + + Expect(client.Do(ctx, "pexpire", "key_3000ms", "err").Err()).To(MatchError("ERR value is not an integer or out of range")) + }) + + It("should expireat", func() { + Expect(client.Set(ctx, "foo", "bar", 0).Val()).To(Equal("OK")) + Expect(client.Do(ctx, "expireat", "foo", "1293840000").Val()).To(Equal(int64(1))) + Expect(client.Exists(ctx, "foo").Val()).To(Equal(int64(0))) + }) + + It("should pexpirat", func() { + Expect(client.Set(ctx, "foo", "bar", 0).Val()).To(Equal("OK")) + Expect(client.Do(ctx, "pexpireat", "foo", "1293840000").Val()).To(Equal(int64(1))) + Expect(client.Exists(ctx, "foo").Val()).To(Equal(int64(0))) + + }) + }) + }) diff --git a/tests/integration/set_test.go b/tests/integration/set_test.go index 82b01412d1..8e765e4c7a 100644 --- a/tests/integration/set_test.go +++ b/tests/integration/set_test.go @@ -2,6 +2,7 @@ package pika_integration import ( "context" + "time" . "github.com/bsm/ginkgo/v2" . "github.com/bsm/gomega" @@ -15,6 +16,7 @@ var _ = Describe("List Commands", func() { BeforeEach(func() { client = redis.NewClient(pikaOptions1()) Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred()) + time.Sleep(1 * time.Second) }) AfterEach(func() { diff --git a/tests/integration/slowlog_test.go b/tests/integration/slowlog_test.go index 5f13606acb..782d774311 100644 --- a/tests/integration/slowlog_test.go +++ b/tests/integration/slowlog_test.go @@ -2,6 +2,7 @@ package pika_integration import ( "context" + "time" . "github.com/bsm/ginkgo/v2" . "github.com/bsm/gomega" @@ -15,6 +16,7 @@ var _ = Describe("Slowlog Commands", func() { BeforeEach(func() { client = redis.NewClient(pikaOptions1()) Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred()) + time.Sleep(1 * time.Second) }) AfterEach(func() { diff --git a/tests/integration/start_master_and_slave.sh b/tests/integration/start_master_and_slave.sh index c2b6a01c38..4bb0c29252 100644 --- a/tests/integration/start_master_and_slave.sh +++ b/tests/integration/start_master_and_slave.sh @@ -4,8 +4,8 @@ cp ../tests/conf/pika.conf ./pika_master.conf cp ../tests/conf/pika.conf ./pika_slave.conf mkdir slave_data -sed -i '' -e 's|databases : 1|databases : 2|' -e 's|#daemonize : yes|daemonize : yes|' ./pika_master.conf -sed -i '' -e 's|databases : 1|databases : 2|' -e 's|port : 9221|port : 9231|' -e 's|log-path : ./log/|log-path : ./slave_data/log/|' -e 's|db-path : ./db/|db-path : ./slave_data/db/|' -e 's|dump-path : ./dump/|dump-path : ./slave_data/dump/|' -e 's|pidfile : ./pika.pid|pidfile : ./slave_data/pika.pid|' -e 's|db-sync-path : ./dbsync/|db-sync-path : ./slave_data/dbsync/|' -e 's|#daemonize : yes|daemonize : yes|' ./pika_slave.conf +sed -i '' -e 's|databases : 1|databases : 2|' -e 's|timeout : 60|timeout : 100000|' -e 's|#daemonize : yes|daemonize : yes|' ./pika_master.conf +sed -i '' -e 's|databases : 1|databases : 2|' -e 's|timeout : 60|timeout : 100000|' -e 's|port : 9221|port : 9231|' -e 's|log-path : ./log/|log-path : ./slave_data/log/|' -e 's|db-path : ./db/|db-path : ./slave_data/db/|' -e 's|dump-path : ./dump/|dump-path : ./slave_data/dump/|' -e 's|pidfile : ./pika.pid|pidfile : ./slave_data/pika.pid|' -e 's|db-sync-path : ./dbsync/|db-sync-path : ./slave_data/dbsync/|' -e 's|#daemonize : yes|daemonize : yes|' ./pika_slave.conf ./pika -c ./pika_master.conf ./pika -c ./pika_slave.conf #ensure both master and slave are ready diff --git a/tests/integration/string_test.go b/tests/integration/string_test.go index c8473dc3b9..760cb7bd1d 100644 --- a/tests/integration/string_test.go +++ b/tests/integration/string_test.go @@ -18,6 +18,7 @@ var _ = Describe("String Commands", func() { BeforeEach(func() { client = redis.NewClient(pikaOptions1()) Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred()) + time.Sleep(1 * time.Second) }) AfterEach(func() { diff --git a/tests/integration/zset_test.go b/tests/integration/zset_test.go index 2b9b8fc5f3..b2f9d680f9 100644 --- a/tests/integration/zset_test.go +++ b/tests/integration/zset_test.go @@ -2,7 +2,6 @@ package pika_integration import ( "context" - "strconv" "time" . "github.com/bsm/ginkgo/v2" @@ -18,920 +17,1934 @@ var _ = Describe("Zset Commands", func() { BeforeEach(func() { client = redis.NewClient(pikaOptions1()) Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred()) + time.Sleep(1 * time.Second) }) AfterEach(func() { Expect(client.Close()).NotTo(HaveOccurred()) }) + PIt("should BZPopMax", func() { + err := client.ZAdd(ctx, "zset1", redis.Z{ + Score: 1, + Member: "one", + }).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset1", redis.Z{ + Score: 2, + Member: "two", + }).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset1", redis.Z{ + Score: 3, + Member: "three", + }).Err() + Expect(err).NotTo(HaveOccurred()) + + member, err := client.BZPopMax(ctx, 0, "zset1", "zset2").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(member).To(Equal(&redis.ZWithKey{ + Z: redis.Z{ + Score: 3, + Member: "three", + }, + Key: "zset1", + })) + }) - Describe("strings", func() { - It("should Append", func() { - n, err := client.Exists(ctx, "key__11").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(n).To(Equal(int64(0))) - - appendRes := client.Append(ctx, "key", "Hello") - Expect(appendRes.Err()).NotTo(HaveOccurred()) - Expect(appendRes.Val()).To(Equal(int64(5))) - - appendRes = client.Append(ctx, "key", " World") - Expect(appendRes.Err()).NotTo(HaveOccurred()) - Expect(appendRes.Val()).To(Equal(int64(11))) - - get := client.Get(ctx, "key") - Expect(get.Err()).NotTo(HaveOccurred()) - Expect(get.Val()).To(Equal("Hello World")) - }) - - It("should BitCount", func() { - set := client.Set(ctx, "key", "foobar", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - bitCount := client.BitCount(ctx, "key", nil) - Expect(bitCount.Err()).NotTo(HaveOccurred()) - Expect(bitCount.Val()).To(Equal(int64(26))) - - bitCount = client.BitCount(ctx, "key", &redis.BitCount{ - Start: 0, - End: 0, - }) - Expect(bitCount.Err()).NotTo(HaveOccurred()) - Expect(bitCount.Val()).To(Equal(int64(4))) - - bitCount = client.BitCount(ctx, "key", &redis.BitCount{ - Start: 1, - End: 1, - }) - Expect(bitCount.Err()).NotTo(HaveOccurred()) - Expect(bitCount.Val()).To(Equal(int64(6))) - }) - - It("should BitOpAnd", func() { - set := client.Set(ctx, "key1", "1", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - set = client.Set(ctx, "key2", "0", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - bitOpAnd := client.BitOpAnd(ctx, "dest", "key1", "key2") - Expect(bitOpAnd.Err()).NotTo(HaveOccurred()) - Expect(bitOpAnd.Val()).To(Equal(int64(1))) - - get := client.Get(ctx, "dest") - Expect(get.Err()).NotTo(HaveOccurred()) - Expect(get.Val()).To(Equal("0")) - }) - - It("should BitOpOr", func() { - set := client.Set(ctx, "key1", "1", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - set = client.Set(ctx, "key2", "0", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - bitOpOr := client.BitOpOr(ctx, "dest", "key1", "key2") - Expect(bitOpOr.Err()).NotTo(HaveOccurred()) - Expect(bitOpOr.Val()).To(Equal(int64(1))) - - get := client.Get(ctx, "dest") - Expect(get.Err()).NotTo(HaveOccurred()) - Expect(get.Val()).To(Equal("1")) - }) - - It("should BitOpXor", func() { - set := client.Set(ctx, "key1", "\xff", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - set = client.Set(ctx, "key2", "\x0f", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - bitOpXor := client.BitOpXor(ctx, "dest", "key1", "key2") - Expect(bitOpXor.Err()).NotTo(HaveOccurred()) - Expect(bitOpXor.Val()).To(Equal(int64(1))) - - get := client.Get(ctx, "dest") - Expect(get.Err()).NotTo(HaveOccurred()) - Expect(get.Val()).To(Equal("\xf0")) - }) - - It("should BitOpNot", func() { - set := client.Set(ctx, "key1", "\x00", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - bitOpNot := client.BitOpNot(ctx, "dest", "key1") - Expect(bitOpNot.Err()).NotTo(HaveOccurred()) - Expect(bitOpNot.Val()).To(Equal(int64(1))) - - get := client.Get(ctx, "dest") - Expect(get.Err()).NotTo(HaveOccurred()) - Expect(get.Val()).To(Equal("\xff")) + PIt("should BZPopMax blocks", func() { + started := make(chan bool) + done := make(chan bool) + go func() { + defer GinkgoRecover() + + started <- true + bZPopMax := client.BZPopMax(ctx, 0, "zset") + Expect(bZPopMax.Err()).NotTo(HaveOccurred()) + Expect(bZPopMax.Val()).To(Equal(&redis.ZWithKey{ + Z: redis.Z{ + Member: "a", + Score: 1, + }, + Key: "zset", + })) + done <- true + }() + <-started + + select { + case <-done: + Fail("BZPopMax is not blocked") + case <-time.After(time.Second): + // ok + } + + zAdd := client.ZAdd(ctx, "zset", redis.Z{ + Member: "a", + Score: 1, }) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + + select { + case <-done: + // ok + case <-time.After(time.Second): + Fail("BZPopMax is still blocked") + } + }) - It("should BitPos", func() { - err := client.Set(ctx, "mykey", "\xff\xf0\x00", 0).Err() - Expect(err).NotTo(HaveOccurred()) - - pos, err := client.BitPos(ctx, "mykey", 0).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(pos).To(Equal(int64(12))) - - pos, err = client.BitPos(ctx, "mykey", 1).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(pos).To(Equal(int64(0))) - - pos, err = client.BitPos(ctx, "mykey", 0, 2).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(pos).To(Equal(int64(16))) - - pos, err = client.BitPos(ctx, "mykey", 1, 2).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(pos).To(Equal(int64(-1))) - - pos, err = client.BitPos(ctx, "mykey", 0, -1).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(pos).To(Equal(int64(16))) - - pos, err = client.BitPos(ctx, "mykey", 1, -1).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(pos).To(Equal(int64(-1))) + PIt("should BZPopMax timeout", func() { + val, err := client.BZPopMax(ctx, time.Second, "zset1").Result() + Expect(err).To(Equal(redis.Nil)) + Expect(val).To(BeNil()) - pos, err = client.BitPos(ctx, "mykey", 0, 2, 1).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(pos).To(Equal(int64(-1))) + Expect(client.Ping(ctx).Err()).NotTo(HaveOccurred()) - pos, err = client.BitPos(ctx, "mykey", 0, 0, -3).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(pos).To(Equal(int64(-1))) + stats := client.PoolStats() + Expect(stats.Hits).To(Equal(uint32(2))) + Expect(stats.Misses).To(Equal(uint32(1))) + Expect(stats.Timeouts).To(Equal(uint32(0))) + }) - pos, err = client.BitPos(ctx, "mykey", 0, 0, 0).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(pos).To(Equal(int64(-1))) - }) + PIt("should BZPopMin", func() { + err := client.ZAdd(ctx, "zset1", redis.Z{ + Score: 1, + Member: "one", + }).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset1", redis.Z{ + Score: 2, + Member: "two", + }).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset1", redis.Z{ + Score: 3, + Member: "three", + }).Err() + Expect(err).NotTo(HaveOccurred()) + + member, err := client.BZPopMin(ctx, 0, "zset1", "zset2").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(member).To(Equal(&redis.ZWithKey{ + Z: redis.Z{ + Score: 1, + Member: "one", + }, + Key: "zset1", + })) + }) - It("should BitPosSpan", func() { - err := client.Set(ctx, "mykey", "\x00\xff\x00", 0).Err() - Expect(err).NotTo(HaveOccurred()) + PIt("should BZPopMin blocks", func() { + started := make(chan bool) + done := make(chan bool) + go func() { + defer GinkgoRecover() + + started <- true + bZPopMin := client.BZPopMin(ctx, 0, "zset") + Expect(bZPopMin.Err()).NotTo(HaveOccurred()) + Expect(bZPopMin.Val()).To(Equal(&redis.ZWithKey{ + Z: redis.Z{ + Member: "a", + Score: 1, + }, + Key: "zset", + })) + done <- true + }() + <-started + + select { + case <-done: + Fail("BZPopMin is not blocked") + case <-time.After(time.Second): + // ok + } + + zAdd := client.ZAdd(ctx, "zset", redis.Z{ + Member: "a", + Score: 1, }) + Expect(zAdd.Err()).NotTo(HaveOccurred()) + + select { + case <-done: + // ok + case <-time.After(time.Second): + Fail("BZPopMin is still blocked") + } + }) - It("should Decr", func() { - set := client.Set(ctx, "key", "10", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) + PIt("should BZPopMin timeout", func() { + val, err := client.BZPopMin(ctx, time.Second, "zset1").Result() + Expect(err).To(Equal(redis.Nil)) + Expect(val).To(BeNil()) - decr := client.Decr(ctx, "key") - Expect(decr.Err()).NotTo(HaveOccurred()) - Expect(decr.Val()).To(Equal(int64(9))) + Expect(client.Ping(ctx).Err()).NotTo(HaveOccurred()) - set = client.Set(ctx, "key", "234293482390480948029348230948", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) + stats := client.PoolStats() + Expect(stats.Hits).To(Equal(uint32(2))) + Expect(stats.Misses).To(Equal(uint32(1))) + Expect(stats.Timeouts).To(Equal(uint32(0))) + }) - //decr = client.Decr(ctx, "key") - //Expect(set.Err()).NotTo(HaveOccurred()) - //Expect(decr.Err()).To(MatchError("ERR value is not an integer or out of range")) - //Expect(decr.Val()).To(Equal(int64(-1))) - }) + It("should ZAdd", func() { + added, err := client.ZAdd(ctx, "zset", redis.Z{ + Score: 1, + Member: "one", + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(added).To(Equal(int64(1))) + + added, err = client.ZAdd(ctx, "zset", redis.Z{ + Score: 1, + Member: "uno", + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(added).To(Equal(int64(1))) + + added, err = client.ZAdd(ctx, "zset", redis.Z{ + Score: 2, + Member: "two", + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(added).To(Equal(int64(1))) + + added, err = client.ZAdd(ctx, "zset", redis.Z{ + Score: 3, + Member: "two", + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(added).To(Equal(int64(0))) + + vals, err := client.ZRangeWithScores(ctx, "zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{ + Score: 1, + Member: "one", + }, { + Score: 1, + Member: "uno", + }, { + Score: 3, + Member: "two", + }})) + }) - It("should DecrBy", func() { - set := client.Set(ctx, "key", "10", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) + It("should ZAdd bytes", func() { + added, err := client.ZAdd(ctx, "zset", redis.Z{ + Score: 1, + Member: []byte("one"), + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(added).To(Equal(int64(1))) + + added, err = client.ZAdd(ctx, "zset", redis.Z{ + Score: 1, + Member: []byte("uno"), + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(added).To(Equal(int64(1))) + + added, err = client.ZAdd(ctx, "zset", redis.Z{ + Score: 2, + Member: []byte("two"), + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(added).To(Equal(int64(1))) + + added, err = client.ZAdd(ctx, "zset", redis.Z{ + Score: 3, + Member: []byte("two"), + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(added).To(Equal(int64(0))) + + vals, err := client.ZRangeWithScores(ctx, "zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{ + Score: 1, + Member: "one", + }, { + Score: 1, + Member: "uno", + }, { + Score: 3, + Member: "two", + }})) + }) - decrBy := client.DecrBy(ctx, "key", 5) - Expect(decrBy.Err()).NotTo(HaveOccurred()) - Expect(decrBy.Val()).To(Equal(int64(5))) - }) + PIt("should ZAddArgsGTAndLT", func() { + // Test only the GT+LT options. + added, err := client.ZAddArgs(ctx, "zset", redis.ZAddArgs{ + GT: true, + Members: []redis.Z{{Score: 1, Member: "one"}}, + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(added).To(Equal(int64(1))) + + vals, err := client.ZRangeWithScores(ctx, "zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{Score: 1, Member: "one"}})) + + added, err = client.ZAddArgs(ctx, "zset", redis.ZAddArgs{ + GT: true, + Members: []redis.Z{{Score: 2, Member: "one"}}, + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(added).To(Equal(int64(0))) + + vals, err = client.ZRangeWithScores(ctx, "zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{Score: 2, Member: "one"}})) + + added, err = client.ZAddArgs(ctx, "zset", redis.ZAddArgs{ + LT: true, + Members: []redis.Z{{Score: 1, Member: "one"}}, + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(added).To(Equal(int64(0))) + + vals, err = client.ZRangeWithScores(ctx, "zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{Score: 1, Member: "one"}})) + }) - It("should Get", func() { - get := client.Get(ctx, "_") - Expect(get.Err()).To(Equal(redis.Nil)) - Expect(get.Val()).To(Equal("")) + PIt("should ZAddArgsLT", func() { + added, err := client.ZAddLT(ctx, "zset", redis.Z{ + Score: 2, + Member: "one", + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(added).To(Equal(int64(1))) + + vals, err := client.ZRangeWithScores(ctx, "zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{Score: 2, Member: "one"}})) + + added, err = client.ZAddLT(ctx, "zset", redis.Z{ + Score: 3, + Member: "one", + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(added).To(Equal(int64(0))) + + vals, err = client.ZRangeWithScores(ctx, "zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{Score: 2, Member: "one"}})) + + added, err = client.ZAddLT(ctx, "zset", redis.Z{ + Score: 1, + Member: "one", + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(added).To(Equal(int64(0))) + + vals, err = client.ZRangeWithScores(ctx, "zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{Score: 1, Member: "one"}})) + }) - set := client.Set(ctx, "key", "hello", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) + PIt("should ZAddArgsGT", func() { + added, err := client.ZAddGT(ctx, "zset", redis.Z{ + Score: 2, + Member: "one", + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(added).To(Equal(int64(1))) + + vals, err := client.ZRangeWithScores(ctx, "zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{Score: 2, Member: "one"}})) + + added, err = client.ZAddGT(ctx, "zset", redis.Z{ + Score: 3, + Member: "one", + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(added).To(Equal(int64(0))) + + vals, err = client.ZRangeWithScores(ctx, "zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{Score: 3, Member: "one"}})) + + added, err = client.ZAddGT(ctx, "zset", redis.Z{ + Score: 1, + Member: "one", + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(added).To(Equal(int64(0))) + + vals, err = client.ZRangeWithScores(ctx, "zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{Score: 3, Member: "one"}})) + }) - get = client.Get(ctx, "key") - Expect(get.Err()).NotTo(HaveOccurred()) - Expect(get.Val()).To(Equal("hello")) - }) + PIt("should ZAddArgsNX", func() { + added, err := client.ZAddNX(ctx, "zset", redis.Z{ + Score: 1, + Member: "one", + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(added).To(Equal(int64(1))) + + vals, err := client.ZRangeWithScores(ctx, "zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{Score: 1, Member: "one"}})) + + added, err = client.ZAddNX(ctx, "zset", redis.Z{ + Score: 2, + Member: "one", + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(added).To(Equal(int64(0))) + + vals, err = client.ZRangeWithScores(ctx, "zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{Score: 1, Member: "one"}})) + }) - It("should GetBit", func() { - setBit := client.SetBit(ctx, "key", 7, 1) - Expect(setBit.Err()).NotTo(HaveOccurred()) - Expect(setBit.Val()).To(Equal(int64(0))) + PIt("should ZAddArgsXX", func() { + added, err := client.ZAddXX(ctx, "zset", redis.Z{ + Score: 1, + Member: "one", + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(added).To(Equal(int64(0))) + + vals, err := client.ZRangeWithScores(ctx, "zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(BeEmpty()) + + added, err = client.ZAdd(ctx, "zset", redis.Z{ + Score: 1, + Member: "one", + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(added).To(Equal(int64(1))) + + added, err = client.ZAddXX(ctx, "zset", redis.Z{ + Score: 2, + Member: "one", + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(added).To(Equal(int64(0))) + + vals, err = client.ZRangeWithScores(ctx, "zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{Score: 2, Member: "one"}})) + }) - getBit := client.GetBit(ctx, "key", 0) - Expect(getBit.Err()).NotTo(HaveOccurred()) - Expect(getBit.Val()).To(Equal(int64(0))) + PIt("should ZAddArgsCh", func() { + changed, err := client.ZAddArgs(ctx, "zset", redis.ZAddArgs{ + Ch: true, + Members: []redis.Z{ + {Score: 1, Member: "one"}, + }, + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(changed).To(Equal(int64(1))) + + changed, err = client.ZAddArgs(ctx, "zset", redis.ZAddArgs{ + Ch: true, + Members: []redis.Z{ + {Score: 1, Member: "one"}, + }, + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(changed).To(Equal(int64(0))) + }) - getBit = client.GetBit(ctx, "key", 7) - Expect(getBit.Err()).NotTo(HaveOccurred()) - Expect(getBit.Val()).To(Equal(int64(1))) + PIt("should ZAddArgsNXCh", func() { + changed, err := client.ZAddArgs(ctx, "zset", redis.ZAddArgs{ + NX: true, + Ch: true, + Members: []redis.Z{ + {Score: 1, Member: "one"}, + }, + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(changed).To(Equal(int64(1))) + + vals, err := client.ZRangeWithScores(ctx, "zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{Score: 1, Member: "one"}})) + + changed, err = client.ZAddArgs(ctx, "zset", redis.ZAddArgs{ + NX: true, + Ch: true, + Members: []redis.Z{ + {Score: 2, Member: "one"}, + }, + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(changed).To(Equal(int64(0))) + + vals, err = client.ZRangeWithScores(ctx, "zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{ + Score: 1, + Member: "one", + }})) + }) - getBit = client.GetBit(ctx, "key", 100) - Expect(getBit.Err()).NotTo(HaveOccurred()) - Expect(getBit.Val()).To(Equal(int64(0))) - }) + PIt("should ZAddArgsXXCh", func() { + changed, err := client.ZAddArgs(ctx, "zset", redis.ZAddArgs{ + XX: true, + Ch: true, + Members: []redis.Z{ + {Score: 1, Member: "one"}, + }, + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(changed).To(Equal(int64(0))) + + vals, err := client.ZRangeWithScores(ctx, "zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(BeEmpty()) + + added, err := client.ZAdd(ctx, "zset", redis.Z{ + Score: 1, + Member: "one", + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(added).To(Equal(int64(1))) + + changed, err = client.ZAddArgs(ctx, "zset", redis.ZAddArgs{ + XX: true, + Ch: true, + Members: []redis.Z{ + {Score: 2, Member: "one"}, + }, + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(changed).To(Equal(int64(1))) + + vals, err = client.ZRangeWithScores(ctx, "zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{Score: 2, Member: "one"}})) + }) - It("should GetRange", func() { - set := client.Set(ctx, "key", "This is a string", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) + PIt("should ZAddArgsIncr", func() { + score, err := client.ZAddArgsIncr(ctx, "zset", redis.ZAddArgs{ + Members: []redis.Z{ + {Score: 1, Member: "one"}, + }, + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(score).To(Equal(float64(1))) + + vals, err := client.ZRangeWithScores(ctx, "zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{Score: 1, Member: "one"}})) + + score, err = client.ZAddArgsIncr(ctx, "zset", redis.ZAddArgs{ + Members: []redis.Z{ + {Score: 1, Member: "one"}, + }, + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(score).To(Equal(float64(2))) + + vals, err = client.ZRangeWithScores(ctx, "zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{Score: 2, Member: "one"}})) + }) - getRange := client.GetRange(ctx, "key", 0, 3) - Expect(getRange.Err()).NotTo(HaveOccurred()) - Expect(getRange.Val()).To(Equal("This")) + PIt("should ZAddArgsIncrNX", func() { + score, err := client.ZAddArgsIncr(ctx, "zset", redis.ZAddArgs{ + NX: true, + Members: []redis.Z{ + {Score: 1, Member: "one"}, + }, + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(score).To(Equal(float64(1))) + + vals, err := client.ZRangeWithScores(ctx, "zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{Score: 1, Member: "one"}})) + + score, err = client.ZAddArgsIncr(ctx, "zset", redis.ZAddArgs{ + NX: true, + Members: []redis.Z{ + {Score: 1, Member: "one"}, + }, + }).Result() + Expect(err).To(Equal(redis.Nil)) + Expect(score).To(Equal(float64(0))) + + vals, err = client.ZRangeWithScores(ctx, "zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{Score: 1, Member: "one"}})) + }) - getRange = client.GetRange(ctx, "key", -3, -1) - Expect(getRange.Err()).NotTo(HaveOccurred()) - Expect(getRange.Val()).To(Equal("ing")) + PIt("should ZAddArgsIncrXX", func() { + score, err := client.ZAddArgsIncr(ctx, "zset", redis.ZAddArgs{ + XX: true, + Members: []redis.Z{ + {Score: 1, Member: "one"}, + }, + }).Result() + Expect(err).To(Equal(redis.Nil)) + Expect(score).To(Equal(float64(0))) + + vals, err := client.ZRangeWithScores(ctx, "zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(BeEmpty()) + + added, err := client.ZAdd(ctx, "zset", redis.Z{ + Score: 1, + Member: "one", + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(added).To(Equal(int64(1))) + + score, err = client.ZAddArgsIncr(ctx, "zset", redis.ZAddArgs{ + XX: true, + Members: []redis.Z{ + {Score: 1, Member: "one"}, + }, + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(score).To(Equal(float64(2))) + + vals, err = client.ZRangeWithScores(ctx, "zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{Score: 2, Member: "one"}})) + }) - getRange = client.GetRange(ctx, "key", 0, -1) - Expect(getRange.Err()).NotTo(HaveOccurred()) - Expect(getRange.Val()).To(Equal("This is a string")) + It("should ZCard", func() { + err := client.ZAdd(ctx, "zset", redis.Z{ + Score: 1, + Member: "one", + }).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{ + Score: 2, + Member: "two", + }).Err() + Expect(err).NotTo(HaveOccurred()) + + card, err := client.ZCard(ctx, "zset").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(card).To(Equal(int64(2))) + }) - getRange = client.GetRange(ctx, "key", 10, 100) - Expect(getRange.Err()).NotTo(HaveOccurred()) - Expect(getRange.Val()).To(Equal("string")) - }) + It("should ZCount", func() { + err := client.ZAdd(ctx, "zset", redis.Z{ + Score: 1, + Member: "one", + }).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{ + Score: 2, + Member: "two", + }).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{ + Score: 3, + Member: "three", + }).Err() + Expect(err).NotTo(HaveOccurred()) + + count, err := client.ZCount(ctx, "zset", "-inf", "+inf").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(count).To(Equal(int64(3))) + + count, err = client.ZCount(ctx, "zset", "(1", "3").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(count).To(Equal(int64(2))) + + count, err = client.ZLexCount(ctx, "zset", "-", "+").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(count).To(Equal(int64(3))) + }) - It("should GetSet", func() { - incr := client.Incr(ctx, "key") - Expect(incr.Err()).NotTo(HaveOccurred()) - Expect(incr.Val()).To(Equal(int64(1))) + It("should ZIncrBy", func() { + err := client.ZAdd(ctx, "zset", redis.Z{ + Score: 1, + Member: "one", + }).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{ + Score: 2, + Member: "two", + }).Err() + Expect(err).NotTo(HaveOccurred()) + + n, err := client.ZIncrBy(ctx, "zset", 2, "one").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(n).To(Equal(float64(3))) + + val, err := client.ZRangeWithScores(ctx, "zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]redis.Z{{ + Score: 2, + Member: "two", + }, { + Score: 3, + Member: "one", + }})) + }) - getSet := client.GetSet(ctx, "key", "0") - Expect(getSet.Err()).NotTo(HaveOccurred()) - Expect(getSet.Val()).To(Equal("1")) + It("should ZInterStore", func() { + err := client.ZAdd(ctx, "zset1", redis.Z{ + Score: 1, + Member: "one", + }).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset1", redis.Z{ + Score: 2, + Member: "two", + }).Err() + Expect(err).NotTo(HaveOccurred()) + + err = client.ZAdd(ctx, "zset2", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset2", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset3", redis.Z{Score: 3, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + + n, err := client.ZInterStore(ctx, "out", &redis.ZStore{ + Keys: []string{"zset1", "zset2"}, + Weights: []float64{2, 3}, + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(n).To(Equal(int64(2))) + + vals, err := client.ZRangeWithScores(ctx, "out", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{ + Score: 5, + Member: "one", + }, { + Score: 10, + Member: "two", + }})) + }) - get := client.Get(ctx, "key") - Expect(get.Err()).NotTo(HaveOccurred()) - Expect(get.Val()).To(Equal("0")) - }) - // - //It("should GetEX", func() { - // set := client.Set(ctx, "key", "value", 100*time.Second) - // Expect(set.Err()).NotTo(HaveOccurred()) - // Expect(set.Val()).To(Equal("OK")) - // - // ttl := client.TTL(ctx, "key") - // Expect(ttl.Err()).NotTo(HaveOccurred()) - // Expect(ttl.Val()).To(BeNumerically("~", 100*time.Second, 3*time.Second)) - // - // getEX := client.GetEx(ctx, "key", 200*time.Second) - // Expect(getEX.Err()).NotTo(HaveOccurred()) - // Expect(getEX.Val()).To(Equal("value")) - // - // ttl = client.TTL(ctx, "key") - // Expect(ttl.Err()).NotTo(HaveOccurred()) - // Expect(ttl.Val()).To(BeNumerically("~", 200*time.Second, 3*time.Second)) - //}) - - //It("should GetDel", func() { - // set := client.Set(ctx, "key", "value", 0) - // Expect(set.Err()).NotTo(HaveOccurred()) - // Expect(set.Val()).To(Equal("OK")) - // - // getDel := client.GetDel(ctx, "key") - // Expect(getDel.Err()).NotTo(HaveOccurred()) - // Expect(getDel.Val()).To(Equal("value")) - // - // get := client.Get(ctx, "key") - // Expect(get.Err()).To(Equal(redis.Nil)) - //}) - - It("should Incr", func() { - set := client.Set(ctx, "key", "10", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - incr := client.Incr(ctx, "key") - Expect(incr.Err()).NotTo(HaveOccurred()) - Expect(incr.Val()).To(Equal(int64(11))) - - get := client.Get(ctx, "key") - Expect(get.Err()).NotTo(HaveOccurred()) - Expect(get.Val()).To(Equal("11")) - }) + PIt("should ZMPop", func() { + err := client.ZAdd(ctx, "zset", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 3, Member: "three"}).Err() + Expect(err).NotTo(HaveOccurred()) + + err = client.ZAdd(ctx, "zset2", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset2", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset2", redis.Z{Score: 3, Member: "three"}).Err() + Expect(err).NotTo(HaveOccurred()) + + key, elems, err := client.ZMPop(ctx, "min", 1, "zset").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(key).To(Equal("zset")) + Expect(elems).To(Equal([]redis.Z{{ + Score: 1, + Member: "one", + }})) + + _, _, err = client.ZMPop(ctx, "min", 1, "nosuchkey").Result() + Expect(err).To(Equal(redis.Nil)) + + err = client.ZAdd(ctx, "myzset", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "myzset", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "myzset", redis.Z{Score: 3, Member: "three"}).Err() + Expect(err).NotTo(HaveOccurred()) + + key, elems, err = client.ZMPop(ctx, "min", 1, "myzset").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(key).To(Equal("myzset")) + Expect(elems).To(Equal([]redis.Z{{ + Score: 1, + Member: "one", + }})) + + key, elems, err = client.ZMPop(ctx, "max", 10, "myzset").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(key).To(Equal("myzset")) + Expect(elems).To(Equal([]redis.Z{{ + Score: 3, + Member: "three", + }, { + Score: 2, + Member: "two", + }})) + + err = client.ZAdd(ctx, "myzset2", redis.Z{Score: 4, Member: "four"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "myzset2", redis.Z{Score: 5, Member: "five"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "myzset2", redis.Z{Score: 6, Member: "six"}).Err() + Expect(err).NotTo(HaveOccurred()) + + key, elems, err = client.ZMPop(ctx, "min", 10, "myzset", "myzset2").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(key).To(Equal("myzset2")) + Expect(elems).To(Equal([]redis.Z{{ + Score: 4, + Member: "four", + }, { + Score: 5, + Member: "five", + }, { + Score: 6, + Member: "six", + }})) + }) - It("should IncrBy", func() { - set := client.Set(ctx, "key", "10", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) + PIt("should BZMPop", func() { + err := client.ZAdd(ctx, "zset", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 3, Member: "three"}).Err() + Expect(err).NotTo(HaveOccurred()) + + err = client.ZAdd(ctx, "zset2", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset2", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset2", redis.Z{Score: 3, Member: "three"}).Err() + Expect(err).NotTo(HaveOccurred()) + + key, elems, err := client.BZMPop(ctx, 0, "min", 1, "zset").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(key).To(Equal("zset")) + Expect(elems).To(Equal([]redis.Z{{ + Score: 1, + Member: "one", + }})) + key, elems, err = client.BZMPop(ctx, 0, "max", 1, "zset").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(key).To(Equal("zset")) + Expect(elems).To(Equal([]redis.Z{{ + Score: 3, + Member: "three", + }})) + key, elems, err = client.BZMPop(ctx, 0, "min", 10, "zset").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(key).To(Equal("zset")) + Expect(elems).To(Equal([]redis.Z{{ + Score: 2, + Member: "two", + }})) + + key, elems, err = client.BZMPop(ctx, 0, "max", 10, "zset2").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(key).To(Equal("zset2")) + Expect(elems).To(Equal([]redis.Z{{ + Score: 3, + Member: "three", + }, { + Score: 2, + Member: "two", + }, { + Score: 1, + Member: "one", + }})) + + err = client.ZAdd(ctx, "myzset", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + key, elems, err = client.BZMPop(ctx, 0, "min", 10, "myzset").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(key).To(Equal("myzset")) + Expect(elems).To(Equal([]redis.Z{{ + Score: 1, + Member: "one", + }})) + + err = client.ZAdd(ctx, "myzset2", redis.Z{Score: 4, Member: "four"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "myzset2", redis.Z{Score: 5, Member: "five"}).Err() + Expect(err).NotTo(HaveOccurred()) + + key, elems, err = client.BZMPop(ctx, 0, "min", 10, "myzset", "myzset2").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(key).To(Equal("myzset2")) + Expect(elems).To(Equal([]redis.Z{{ + Score: 4, + Member: "four", + }, { + Score: 5, + Member: "five", + }})) + }) - incrBy := client.IncrBy(ctx, "key", 5) - Expect(incrBy.Err()).NotTo(HaveOccurred()) - Expect(incrBy.Val()).To(Equal(int64(15))) - }) + PIt("should BZMPopBlocks", func() { + started := make(chan bool) + done := make(chan bool) + go func() { + defer GinkgoRecover() - It("should IncrByFloat", func() { - set := client.Set(ctx, "key", "10.50", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) + started <- true + key, elems, err := client.BZMPop(ctx, 0, "min", 1, "list_list").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(key).To(Equal("list_list")) + Expect(elems).To(Equal([]redis.Z{{ + Score: 1, + Member: "one", + }})) + done <- true + }() + <-started + + select { + case <-done: + Fail("BZMPop is not blocked") + case <-time.After(time.Second): + // ok + } + + err := client.ZAdd(ctx, "list_list", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + + select { + case <-done: + // ok + case <-time.After(time.Second): + Fail("BZMPop is still blocked") + } + }) - incrByFloat := client.IncrByFloat(ctx, "key", 0.1) - Expect(incrByFloat.Err()).NotTo(HaveOccurred()) - Expect(incrByFloat.Val()).To(Equal(10.6)) + PIt("should BZMPop timeout", func() { + _, val, err := client.BZMPop(ctx, time.Second, "min", 1, "list1").Result() + Expect(err).To(Equal(redis.Nil)) + Expect(val).To(BeNil()) - set = client.Set(ctx, "key", "5.0e3", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) + Expect(client.Ping(ctx).Err()).NotTo(HaveOccurred()) - incrByFloat = client.IncrByFloat(ctx, "key", 2.0e2) - Expect(incrByFloat.Err()).NotTo(HaveOccurred()) - Expect(incrByFloat.Val()).To(Equal(float64(5200))) - }) + stats := client.PoolStats() + Expect(stats.Hits).To(Equal(uint32(2))) + Expect(stats.Misses).To(Equal(uint32(1))) + Expect(stats.Timeouts).To(Equal(uint32(0))) + }) - It("should IncrByFloatOverflow", func() { - incrByFloat := client.IncrByFloat(ctx, "key", 996945661) - Expect(incrByFloat.Err()).NotTo(HaveOccurred()) - Expect(incrByFloat.Val()).To(Equal(float64(996945661))) - }) + PIt("should ZMScore", func() { + zmScore := client.ZMScore(ctx, "zset", "one", "three") + Expect(zmScore.Err()).NotTo(HaveOccurred()) + Expect(zmScore.Val()).To(HaveLen(2)) + Expect(zmScore.Val()[0]).To(Equal(float64(0))) + + err := client.ZAdd(ctx, "zset", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 3, Member: "three"}).Err() + Expect(err).NotTo(HaveOccurred()) + + zmScore = client.ZMScore(ctx, "zset", "one", "three") + Expect(zmScore.Err()).NotTo(HaveOccurred()) + Expect(zmScore.Val()).To(HaveLen(2)) + Expect(zmScore.Val()[0]).To(Equal(float64(1))) + + zmScore = client.ZMScore(ctx, "zset", "four") + Expect(zmScore.Err()).NotTo(HaveOccurred()) + Expect(zmScore.Val()).To(HaveLen(1)) + + zmScore = client.ZMScore(ctx, "zset", "four", "one") + Expect(zmScore.Err()).NotTo(HaveOccurred()) + Expect(zmScore.Val()).To(HaveLen(2)) + }) - It("should MSetMGet", func() { - mSet := client.MSet(ctx, "key1", "hello1", "key2", "hello2") - Expect(mSet.Err()).NotTo(HaveOccurred()) - Expect(mSet.Val()).To(Equal("OK")) - - mGet := client.MGet(ctx, "key1", "key2", "_") - Expect(mGet.Err()).NotTo(HaveOccurred()) - Expect(mGet.Val()).To(Equal([]interface{}{"hello1", "hello2", nil})) - - // MSet struct - type set struct { - Set1 string `redis:"set1"` - Set2 int16 `redis:"set2"` - Set3 time.Duration `redis:"set3"` - Set4 interface{} `redis:"set4"` - Set5 map[string]interface{} `redis:"-"` - } - mSet = client.MSet(ctx, &set{ - Set1: "val1", - Set2: 1024, - Set3: 2 * time.Millisecond, - Set4: nil, - Set5: map[string]interface{}{"k1": 1}, - }) - Expect(mSet.Err()).NotTo(HaveOccurred()) - Expect(mSet.Val()).To(Equal("OK")) - - mGet = client.MGet(ctx, "set1", "set2", "set3", "set4") - Expect(mGet.Err()).NotTo(HaveOccurred()) - Expect(mGet.Val()).To(Equal([]interface{}{ - "val1", - "1024", - strconv.Itoa(int(2 * time.Millisecond.Nanoseconds())), - "", - })) - }) + It("should ZPopMax", func() { + err := client.ZAdd(ctx, "zset", redis.Z{ + Score: 1, + Member: "one", + }).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{ + Score: 2, + Member: "two", + }).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{ + Score: 3, + Member: "three", + }).Err() + Expect(err).NotTo(HaveOccurred()) + + members, err := client.ZPopMax(ctx, "zset").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(members).To(Equal([]redis.Z{{ + Score: 3, + Member: "three", + }})) + + // adding back 3 + err = client.ZAdd(ctx, "zset", redis.Z{ + Score: 3, + Member: "three", + }).Err() + Expect(err).NotTo(HaveOccurred()) + members, err = client.ZPopMax(ctx, "zset", 2).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(members).To(Equal([]redis.Z{{ + Score: 3, + Member: "three", + }, { + Score: 2, + Member: "two", + }})) + + // adding back 2 & 3 + err = client.ZAdd(ctx, "zset", redis.Z{ + Score: 3, + Member: "three", + }).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{ + Score: 2, + Member: "two", + }).Err() + Expect(err).NotTo(HaveOccurred()) + members, err = client.ZPopMax(ctx, "zset", 10).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(members).To(Equal([]redis.Z{{ + Score: 3, + Member: "three", + }, { + Score: 2, + Member: "two", + }, { + Score: 1, + Member: "one", + }})) + }) - It("should scan Mget", func() { - now := time.Now() + It("should ZPopMin", func() { + err := client.ZAdd(ctx, "zset", redis.Z{ + Score: 1, + Member: "one", + }).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{ + Score: 2, + Member: "two", + }).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{ + Score: 3, + Member: "three", + }).Err() + Expect(err).NotTo(HaveOccurred()) + + members, err := client.ZPopMin(ctx, "zset").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(members).To(Equal([]redis.Z{{ + Score: 1, + Member: "one", + }})) + + // adding back 1 + err = client.ZAdd(ctx, "zset", redis.Z{ + Score: 1, + Member: "one", + }).Err() + Expect(err).NotTo(HaveOccurred()) + members, err = client.ZPopMin(ctx, "zset", 2).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(members).To(Equal([]redis.Z{{ + Score: 1, + Member: "one", + }, { + Score: 2, + Member: "two", + }})) + + // adding back 1 & 2 + err = client.ZAdd(ctx, "zset", redis.Z{ + Score: 1, + Member: "one", + }).Err() + Expect(err).NotTo(HaveOccurred()) + + err = client.ZAdd(ctx, "zset", redis.Z{ + Score: 2, + Member: "two", + }).Err() + Expect(err).NotTo(HaveOccurred()) + + members, err = client.ZPopMin(ctx, "zset", 10).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(members).To(Equal([]redis.Z{{ + Score: 1, + Member: "one", + }, { + Score: 2, + Member: "two", + }, { + Score: 3, + Member: "three", + }})) + }) - err := client.MSet(ctx, "key1", "hello1", "key2", 123, "time", now.Format(time.RFC3339Nano)).Err() - Expect(err).NotTo(HaveOccurred()) + It("should ZRange", func() { + err := client.ZAdd(ctx, "zset", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 3, Member: "three"}).Err() + Expect(err).NotTo(HaveOccurred()) + + zRange := client.ZRange(ctx, "zset", 0, -1) + Expect(zRange.Err()).NotTo(HaveOccurred()) + Expect(zRange.Val()).To(Equal([]string{"one", "two", "three"})) + + zRange = client.ZRange(ctx, "zset", 2, 3) + Expect(zRange.Err()).NotTo(HaveOccurred()) + Expect(zRange.Val()).To(Equal([]string{"three"})) + + zRange = client.ZRange(ctx, "zset", -2, -1) + Expect(zRange.Err()).NotTo(HaveOccurred()) + Expect(zRange.Val()).To(Equal([]string{"two", "three"})) + }) - res := client.MGet(ctx, "key1", "key2", "_", "time") - Expect(res.Err()).NotTo(HaveOccurred()) - - type data struct { - Key1 string `redis:"key1"` - Key2 int `redis:"key2"` - Time TimeValue `redis:"time"` - } - var d data - Expect(res.Scan(&d)).NotTo(HaveOccurred()) - Expect(d.Time.UnixNano()).To(Equal(now.UnixNano())) - d.Time.Time = time.Time{} - Expect(d).To(Equal(data{ - Key1: "hello1", - Key2: 123, - Time: TimeValue{Time: time.Time{}}, - })) - }) + It("should ZRangeWithScores", func() { + err := client.ZAdd(ctx, "zset", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 3, Member: "three"}).Err() + Expect(err).NotTo(HaveOccurred()) + + vals, err := client.ZRangeWithScores(ctx, "zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{ + Score: 1, + Member: "one", + }, { + Score: 2, + Member: "two", + }, { + Score: 3, + Member: "three", + }})) + + vals, err = client.ZRangeWithScores(ctx, "zset", 2, 3).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{Score: 3, Member: "three"}})) + + vals, err = client.ZRangeWithScores(ctx, "zset", -2, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{ + Score: 2, + Member: "two", + }, { + Score: 3, + Member: "three", + }})) + }) - It("should MSetNX", func() { - mSetNX := client.MSetNX(ctx, "key1", "hello1", "key2", "hello2") - Expect(mSetNX.Err()).NotTo(HaveOccurred()) - Expect(mSetNX.Val()).To(Equal(true)) - - mSetNX = client.MSetNX(ctx, "key2", "hello1", "key3", "hello2") - Expect(mSetNX.Err()).NotTo(HaveOccurred()) - Expect(mSetNX.Val()).To(Equal(false)) - - // set struct - // MSet struct - type set struct { - Set1 string `redis:"set1"` - Set2 int16 `redis:"set2"` - Set3 time.Duration `redis:"set3"` - Set4 interface{} `redis:"set4"` - Set5 map[string]interface{} `redis:"-"` - } - mSetNX = client.MSetNX(ctx, &set{ - Set1: "val1", - Set2: 1024, - Set3: 2 * time.Millisecond, - Set4: nil, - Set5: map[string]interface{}{"k1": 1}, - }) - Expect(mSetNX.Err()).NotTo(HaveOccurred()) - Expect(mSetNX.Val()).To(Equal(true)) - }) + PIt("should ZRangeArgs", func() { + added, err := client.ZAddArgs(ctx, "zset", redis.ZAddArgs{ + Members: []redis.Z{ + {Score: 1, Member: "one"}, + {Score: 2, Member: "two"}, + {Score: 3, Member: "three"}, + {Score: 4, Member: "four"}, + }, + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(added).To(Equal(int64(4))) + + zRange, err := client.ZRangeArgs(ctx, redis.ZRangeArgs{ + Key: "zset", + Start: 1, + Stop: 4, + ByScore: true, + Rev: true, + Offset: 1, + Count: 2, + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(zRange).To(Equal([]string{"three", "two"})) + + zRange, err = client.ZRangeArgs(ctx, redis.ZRangeArgs{ + Key: "zset", + Start: "-", + Stop: "+", + ByLex: true, + Rev: true, + Offset: 2, + Count: 2, + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(zRange).To(Equal([]string{"two", "one"})) + + zRange, err = client.ZRangeArgs(ctx, redis.ZRangeArgs{ + Key: "zset", + Start: "(1", + Stop: "(4", + ByScore: true, + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(zRange).To(Equal([]string{"two", "three"})) + + // withScores. + zSlice, err := client.ZRangeArgsWithScores(ctx, redis.ZRangeArgs{ + Key: "zset", + Start: 1, + Stop: 4, + ByScore: true, + Rev: true, + Offset: 1, + Count: 2, + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(zSlice).To(Equal([]redis.Z{ + {Score: 3, Member: "three"}, + {Score: 2, Member: "two"}, + })) + }) - //It("should SetWithArgs with TTL", func() { - // args := redis.SetArgs{ - // TTL: 500 * time.Millisecond, - // } - // err := client.SetArgs(ctx, "key", "hello", args).Err() - // Expect(err).NotTo(HaveOccurred()) - // - // val, err := client.Get(ctx, "key").Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(val).To(Equal("hello")) - // - // Eventually(func() error { - // return client.Get(ctx, "key").Err() - // }, "2s", "100ms").Should(Equal(redis.Nil)) - //}) - - // todo 语法不对,单独支持 - //It("should SetWithArgs with expiration date", func() { - // expireAt := time.Now().AddDate(1, 1, 1) - // args := redis.SetArgs{ - // ExpireAt: expireAt, - // } - // err := client.SetArgs(ctx, "key", "hello", args).Err() - // Expect(err).NotTo(HaveOccurred()) - // - // val, err := client.Get(ctx, "key").Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(val).To(Equal("hello")) - // - // // check the key has an expiration date - // // (so a TTL value different of -1) - // ttl := client.TTL(ctx, "key") - // Expect(ttl.Err()).NotTo(HaveOccurred()) - // Expect(ttl.Val()).ToNot(Equal(-1)) - //}) - - //It("should SetWithArgs with negative expiration date", func() { - // args := redis.SetArgs{ - // ExpireAt: time.Now().AddDate(-3, 1, 1), - // } - // // redis accepts a timestamp less than the current date - // // but returns nil when trying to get the key - // err := client.SetArgs(ctx, "key", "hello", args).Err() - // Expect(err).NotTo(HaveOccurred()) - // - // val, err := client.Get(ctx, "key").Result() - // Expect(err).To(Equal(redis.Nil)) - // Expect(val).To(Equal("")) - //}) - - It("should SetWithArgs with keepttl", func() { - // Set with ttl - argsWithTTL := redis.SetArgs{ - TTL: 5 * time.Second, - } - set := client.SetArgs(ctx, "key", "hello", argsWithTTL) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Result()).To(Equal("OK")) - - // Set with keepttl - //argsWithKeepTTL := redis.SetArgs{ - // KeepTTL: true, - //} - //set = client.SetArgs(ctx, "key", "hello567", argsWithKeepTTL) - //Expect(set.Err()).NotTo(HaveOccurred()) - //Expect(set.Result()).To(Equal("OK")) - // - //ttl := client.TTL(ctx, "key") - //Expect(ttl.Err()).NotTo(HaveOccurred()) - //// set keepttl will Retain the ttl associated with the key - //Expect(ttl.Val().Nanoseconds()).NotTo(Equal(-1)) + It("should ZRangeByScore", func() { + err := client.ZAdd(ctx, "zset", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 3, Member: "three"}).Err() + Expect(err).NotTo(HaveOccurred()) + + zRangeByScore := client.ZRangeByScore(ctx, "zset", &redis.ZRangeBy{ + Min: "-inf", + Max: "+inf", }) + Expect(zRangeByScore.Err()).NotTo(HaveOccurred()) + Expect(zRangeByScore.Val()).To(Equal([]string{"one", "two", "three"})) - It("should SetWithArgs with NX mode and key exists", func() { - err := client.Set(ctx, "key", "hello", 0).Err() - Expect(err).NotTo(HaveOccurred()) - - args := redis.SetArgs{ - Mode: "nx", - } - val, err := client.SetArgs(ctx, "key", "hello", args).Result() - Expect(err).To(Equal(redis.Nil)) - Expect(val).To(Equal("")) + zRangeByScore = client.ZRangeByScore(ctx, "zset", &redis.ZRangeBy{ + Min: "1", + Max: "2", }) + Expect(zRangeByScore.Err()).NotTo(HaveOccurred()) + Expect(zRangeByScore.Val()).To(Equal([]string{"one", "two"})) - It("should SetWithArgs with NX mode and key does not exist", func() { - args := redis.SetArgs{ - Mode: "nx", - } - val, err := client.SetArgs(ctx, "key", "hello", args).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal("OK")) + zRangeByScore = client.ZRangeByScore(ctx, "zset", &redis.ZRangeBy{ + Min: "(1", + Max: "2", }) + Expect(zRangeByScore.Err()).NotTo(HaveOccurred()) + Expect(zRangeByScore.Val()).To(Equal([]string{"two"})) - // todo 待支持 - //It("should SetWithArgs with NX mode and GET option", func() { - // args := redis.SetArgs{ - // Mode: "nx", - // Get: true, - // } - // val, err := client.SetArgs(ctx, "key", "hello", args).Result() - // Expect(err).To(Equal(redis.Nil)) - // Expect(val).To(Equal("")) - //}) - - //It("should SetWithArgs with expiration, NX mode, and key does not exist", func() { - // args := redis.SetArgs{ - // TTL: 500 * time.Millisecond, - // Mode: "nx", - // } - // val, err := client.SetArgs(ctx, "key", "hello", args).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(val).To(Equal("OK")) - // - // Eventually(func() error { - // return client.Get(ctx, "key").Err() - // }, "1s", "100ms").Should(Equal(redis.Nil)) - //}) - - It("should SetWithArgs with expiration, NX mode, and key exists", func() { - e := client.Set(ctx, "key", "hello", 0) - Expect(e.Err()).NotTo(HaveOccurred()) - - args := redis.SetArgs{ - TTL: 500 * time.Millisecond, - Mode: "nx", - } - val, err := client.SetArgs(ctx, "key", "world", args).Result() - Expect(err).To(Equal(redis.Nil)) - Expect(val).To(Equal("")) + zRangeByScore = client.ZRangeByScore(ctx, "zset", &redis.ZRangeBy{ + Min: "(1", + Max: "(2", }) + Expect(zRangeByScore.Err()).NotTo(HaveOccurred()) + Expect(zRangeByScore.Val()).To(Equal([]string{})) + }) - //It("should SetWithArgs with expiration, NX mode, and GET option", func() { - // args := redis.SetArgs{ - // TTL: 500 * time.Millisecond, - // Mode: "nx", - // Get: true, - // } - // val, err := client.SetArgs(ctx, "key", "hello", args).Result() - // Expect(err).To(Equal(redis.Nil)) - // Expect(val).To(Equal("")) - //}) - - It("should SetWithArgs with XX mode and key does not exist", func() { - args := redis.SetArgs{ - Mode: "xx", - } - val, err := client.SetArgs(ctx, "key", "world", args).Result() - Expect(err).To(Equal(redis.Nil)) - Expect(val).To(Equal("")) + It("should ZRangeByLex", func() { + err := client.ZAdd(ctx, "zset", redis.Z{ + Score: 0, + Member: "a", + }).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{ + Score: 0, + Member: "b", + }).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{ + Score: 0, + Member: "c", + }).Err() + Expect(err).NotTo(HaveOccurred()) + + zRangeByLex := client.ZRangeByLex(ctx, "zset", &redis.ZRangeBy{ + Min: "-", + Max: "+", }) + Expect(zRangeByLex.Err()).NotTo(HaveOccurred()) + Expect(zRangeByLex.Val()).To(Equal([]string{"a", "b", "c"})) - It("should SetWithArgs with XX mode and key exists", func() { - e := client.Set(ctx, "key", "hello", 0).Err() - Expect(e).NotTo(HaveOccurred()) - - args := redis.SetArgs{ - Mode: "xx", - } - val, err := client.SetArgs(ctx, "key", "world", args).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal("OK")) + zRangeByLex = client.ZRangeByLex(ctx, "zset", &redis.ZRangeBy{ + Min: "[a", + Max: "[b", }) + Expect(zRangeByLex.Err()).NotTo(HaveOccurred()) + Expect(zRangeByLex.Val()).To(Equal([]string{"a", "b"})) - //It("should SetWithArgs with XX mode and GET option, and key exists", func() { - // e := client.Set(ctx, "key", "hello", 0).Err() - // Expect(e).NotTo(HaveOccurred()) - // - // args := redis.SetArgs{ - // Mode: "xx", - // Get: true, - // } - // val, err := client.SetArgs(ctx, "key", "world", args).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(val).To(Equal("hello")) - //}) - - //It("should SetWithArgs with XX mode and GET option, and key does not exist", func() { - // args := redis.SetArgs{ - // Mode: "xx", - // Get: true, - // } - // - // val, err := client.SetArgs(ctx, "key", "world", args).Result() - // Expect(err).To(Equal(redis.Nil)) - // Expect(val).To(Equal("")) - //}) - - //It("should SetWithArgs with expiration, XX mode, GET option, and key does not exist", func() { - // args := redis.SetArgs{ - // TTL: 500 * time.Millisecond, - // Mode: "xx", - // Get: true, - // } - // - // val, err := client.SetArgs(ctx, "key", "world", args).Result() - // Expect(err).To(Equal(redis.Nil)) - // Expect(val).To(Equal("")) - //}) - - //It("should SetWithArgs with expiration, XX mode, GET option, and key exists", func() { - // e := client.Set(ctx, "key", "hello", 0) - // Expect(e.Err()).NotTo(HaveOccurred()) - // - // args := redis.SetArgs{ - // TTL: 500 * time.Millisecond, - // Mode: "xx", - // Get: true, - // } - // - // val, err := client.SetArgs(ctx, "key", "world", args).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(val).To(Equal("hello")) - // - // Eventually(func() error { - // return client.Get(ctx, "key").Err() - // }, "1s", "100ms").Should(Equal(redis.Nil)) - //}) - - //It("should SetWithArgs with Get and key does not exist yet", func() { - // args := redis.SetArgs{ - // Get: true, - // } - // - // val, err := client.SetArgs(ctx, "key", "hello", args).Result() - // Expect(err).To(Equal(redis.Nil)) - // Expect(val).To(Equal("")) - //}) - - //It("should SetWithArgs with Get and key exists", func() { - // e := client.Set(ctx, "key", "hello", 0) - // Expect(e.Err()).NotTo(HaveOccurred()) - // - // args := redis.SetArgs{ - // Get: true, - // } - // - // val, err := client.SetArgs(ctx, "key", "world", args).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(val).To(Equal("hello")) - //}) - - //It("should Pipelined SetArgs with Get and key exists", func() { - // e := client.Set(ctx, "key", "hello", 0) - // Expect(e.Err()).NotTo(HaveOccurred()) - // - // args := redis.SetArgs{ - // Get: true, - // } - // - // pipe := client.Pipeline() - // setArgs := pipe.SetArgs(ctx, "key", "world", args) - // _, err := pipe.Exec(ctx) - // Expect(err).NotTo(HaveOccurred()) - // - // Expect(setArgs.Err()).NotTo(HaveOccurred()) - // Expect(setArgs.Val()).To(Equal("hello")) - //}) - - //It("should Set with expiration", func() { - // err := client.Set(ctx, "key", "hello", 100*time.Millisecond).Err() - // Expect(err).NotTo(HaveOccurred()) - // - // val, err := client.Get(ctx, "key").Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(val).To(Equal("hello")) - // - // Eventually(func() error { - // return client.Get(ctx, "key").Err() - // }, "1s", "100ms").Should(Equal(redis.Nil)) - //}) - - It("should Set with keepttl", func() { - // set with ttl - set := client.Set(ctx, "key", "hello", 5*time.Second) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - // set with keepttl - // mset key1 hello1 key2 123 time 2023-05-19T15:42:06.880088+08:00 - //set = client.Set(ctx, "key", "hello1", redis.KeepTTL) - //Expect(set.Err()).NotTo(HaveOccurred()) - //Expect(set.Val()).To(Equal("OK")) - - ttl := client.TTL(ctx, "key") - Expect(ttl.Err()).NotTo(HaveOccurred()) - // set keepttl will Retain the ttl associated with the key - Expect(ttl.Val().Nanoseconds()).NotTo(Equal(-1)) + zRangeByLex = client.ZRangeByLex(ctx, "zset", &redis.ZRangeBy{ + Min: "(a", + Max: "[b", }) + Expect(zRangeByLex.Err()).NotTo(HaveOccurred()) + Expect(zRangeByLex.Val()).To(Equal([]string{"b"})) - It("should SetGet", func() { - set := client.Set(ctx, "key", "hello", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - get := client.Get(ctx, "key") - Expect(get.Err()).NotTo(HaveOccurred()) - Expect(get.Val()).To(Equal("hello")) + zRangeByLex = client.ZRangeByLex(ctx, "zset", &redis.ZRangeBy{ + Min: "(a", + Max: "(b", }) + Expect(zRangeByLex.Err()).NotTo(HaveOccurred()) + Expect(zRangeByLex.Val()).To(Equal([]string{})) + }) - It("should SetEX", func() { - err := client.SetEx(ctx, "key", "hello", 1*time.Second).Err() - Expect(err).NotTo(HaveOccurred()) - - val, err := client.Get(ctx, "key").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal("hello")) - - Eventually(func() error { - return client.Get(ctx, "foo").Err() - }, "2s", "100ms").Should(Equal(redis.Nil)) - }) + It("should ZRangeByScoreWithScoresMap", func() { + err := client.ZAdd(ctx, "zset", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 3, Member: "three"}).Err() + Expect(err).NotTo(HaveOccurred()) + + vals, err := client.ZRangeByScoreWithScores(ctx, "zset", &redis.ZRangeBy{ + Min: "-inf", + Max: "+inf", + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{ + Score: 1, + Member: "one", + }, { + Score: 2, + Member: "two", + }, { + Score: 3, + Member: "three", + }})) + + vals, err = client.ZRangeByScoreWithScores(ctx, "zset", &redis.ZRangeBy{ + Min: "1", + Max: "2", + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{ + Score: 1, + Member: "one", + }, { + Score: 2, + Member: "two", + }})) + + vals, err = client.ZRangeByScoreWithScores(ctx, "zset", &redis.ZRangeBy{ + Min: "(1", + Max: "2", + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{Score: 2, Member: "two"}})) + + vals, err = client.ZRangeByScoreWithScores(ctx, "zset", &redis.ZRangeBy{ + Min: "(1", + Max: "(2", + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{})) + }) - It("should SetNX", func() { - setNX := client.SetNX(ctx, "key", "hello", 0) - Expect(setNX.Err()).NotTo(HaveOccurred()) - Expect(setNX.Val()).To(Equal(true)) + PIt("should ZRangeStore", func() { + added, err := client.ZAddArgs(ctx, "zset", redis.ZAddArgs{ + Members: []redis.Z{ + {Score: 1, Member: "one"}, + {Score: 2, Member: "two"}, + {Score: 3, Member: "three"}, + {Score: 4, Member: "four"}, + }, + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(added).To(Equal(int64(4))) + + rangeStore, err := client.ZRangeStore(ctx, "new-zset", redis.ZRangeArgs{ + Key: "zset", + Start: 1, + Stop: 4, + ByScore: true, + Rev: true, + Offset: 1, + Count: 2, + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(rangeStore).To(Equal(int64(2))) + + zRange, err := client.ZRange(ctx, "new-zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(zRange).To(Equal([]string{"two", "three"})) + }) - setNX = client.SetNX(ctx, "key", "hello2", 0) - Expect(setNX.Err()).NotTo(HaveOccurred()) - Expect(setNX.Val()).To(Equal(false)) + It("should ZRank", func() { + err := client.ZAdd(ctx, "zset", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 3, Member: "three"}).Err() + Expect(err).NotTo(HaveOccurred()) + + zRank := client.ZRank(ctx, "zset", "three") + Expect(zRank.Err()).NotTo(HaveOccurred()) + Expect(zRank.Val()).To(Equal(int64(2))) + + zRank = client.ZRank(ctx, "zset", "four") + Expect(zRank.Err()).To(Equal(redis.Nil)) + Expect(zRank.Val()).To(Equal(int64(0))) + }) - get := client.Get(ctx, "key") - Expect(get.Err()).NotTo(HaveOccurred()) - Expect(get.Val()).To(Equal("hello")) - }) + PIt("should ZRankWithScore", func() { + err := client.ZAdd(ctx, "zset", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 3, Member: "three"}).Err() + Expect(err).NotTo(HaveOccurred()) + + zRankWithScore := client.ZRankWithScore(ctx, "zset", "one") + Expect(zRankWithScore.Err()).NotTo(HaveOccurred()) + Expect(zRankWithScore.Result()).To(Equal(redis.RankScore{Rank: 0, Score: 1})) + + zRankWithScore = client.ZRankWithScore(ctx, "zset", "two") + Expect(zRankWithScore.Err()).NotTo(HaveOccurred()) + Expect(zRankWithScore.Result()).To(Equal(redis.RankScore{Rank: 1, Score: 2})) + + zRankWithScore = client.ZRankWithScore(ctx, "zset", "three") + Expect(zRankWithScore.Err()).NotTo(HaveOccurred()) + Expect(zRankWithScore.Result()).To(Equal(redis.RankScore{Rank: 2, Score: 3})) + + zRankWithScore = client.ZRankWithScore(ctx, "zset", "four") + Expect(zRankWithScore.Err()).To(HaveOccurred()) + Expect(zRankWithScore.Err()).To(Equal(redis.Nil)) + }) - It("should SetNX with expiration", func() { - isSet, err := client.SetNX(ctx, "key", "hello", time.Second).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(isSet).To(Equal(true)) + It("should ZRem", func() { + err := client.ZAdd(ctx, "zset", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 3, Member: "three"}).Err() + Expect(err).NotTo(HaveOccurred()) + + zRem := client.ZRem(ctx, "zset", "two") + Expect(zRem.Err()).NotTo(HaveOccurred()) + Expect(zRem.Val()).To(Equal(int64(1))) + + vals, err := client.ZRangeWithScores(ctx, "zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{ + Score: 1, + Member: "one", + }, { + Score: 3, + Member: "three", + }})) + }) - isSet, err = client.SetNX(ctx, "key", "hello2", time.Second).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(isSet).To(Equal(false)) + It("should ZRemRangeByRank", func() { + err := client.ZAdd(ctx, "zset", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 3, Member: "three"}).Err() + Expect(err).NotTo(HaveOccurred()) + + zRemRangeByRank := client.ZRemRangeByRank(ctx, "zset", 0, 1) + Expect(zRemRangeByRank.Err()).NotTo(HaveOccurred()) + Expect(zRemRangeByRank.Val()).To(Equal(int64(2))) + + vals, err := client.ZRangeWithScores(ctx, "zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{ + Score: 3, + Member: "three", + }})) + }) - val, err := client.Get(ctx, "key").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal("hello")) - }) + It("should ZRemRangeByScore", func() { + err := client.ZAdd(ctx, "zset", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 3, Member: "three"}).Err() + Expect(err).NotTo(HaveOccurred()) + + zRemRangeByScore := client.ZRemRangeByScore(ctx, "zset", "-inf", "(2") + Expect(zRemRangeByScore.Err()).NotTo(HaveOccurred()) + Expect(zRemRangeByScore.Val()).To(Equal(int64(1))) + + vals, err := client.ZRangeWithScores(ctx, "zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{ + Score: 2, + Member: "two", + }, { + Score: 3, + Member: "three", + }})) + }) - //It("should SetNX with keepttl", func() { - // isSet, err := client.SetNX(ctx, "key", "hello1", redis.KeepTTL).Result() - // Expect(err).NotTo(HaveOccurred()) - // Expect(isSet).To(Equal(true)) - // - // ttl := client.TTL(ctx, "key") - // Expect(ttl.Err()).NotTo(HaveOccurred()) - // Expect(ttl.Val().Nanoseconds()).To(Equal(int64(-1))) - //}) - - It("should SetXX", func() { - isSet, err := client.SetXX(ctx, "key", "hello2", 0).Result() + It("should ZRemRangeByLex", func() { + zz := []redis.Z{ + {Score: 0, Member: "aaaa"}, + {Score: 0, Member: "b"}, + {Score: 0, Member: "c"}, + {Score: 0, Member: "d"}, + {Score: 0, Member: "e"}, + {Score: 0, Member: "foo"}, + {Score: 0, Member: "zap"}, + {Score: 0, Member: "zip"}, + {Score: 0, Member: "ALPHA"}, + {Score: 0, Member: "alpha"}, + } + for _, z := range zz { + err := client.ZAdd(ctx, "zset", z).Err() Expect(err).NotTo(HaveOccurred()) - Expect(isSet).To(Equal(false)) + } - err = client.Set(ctx, "key", "hello", 0).Err() - Expect(err).NotTo(HaveOccurred()) + n, err := client.ZRemRangeByLex(ctx, "zset", "[alpha", "[omega").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(n).To(Equal(int64(6))) - isSet, err = client.SetXX(ctx, "key", "hello2", 0).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(isSet).To(Equal(true)) + vals, err := client.ZRange(ctx, "zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]string{"ALPHA", "aaaa", "zap", "zip"})) + }) - val, err := client.Get(ctx, "key").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal("hello2")) - }) + It("should ZRevRange", func() { + err := client.ZAdd(ctx, "zset", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 3, Member: "three"}).Err() + Expect(err).NotTo(HaveOccurred()) + + zRevRange := client.ZRevRange(ctx, "zset", 0, -1) + Expect(zRevRange.Err()).NotTo(HaveOccurred()) + Expect(zRevRange.Val()).To(Equal([]string{"three", "two", "one"})) + + zRevRange = client.ZRevRange(ctx, "zset", 2, 3) + Expect(zRevRange.Err()).NotTo(HaveOccurred()) + Expect(zRevRange.Val()).To(Equal([]string{"one"})) + + zRevRange = client.ZRevRange(ctx, "zset", -2, -1) + Expect(zRevRange.Err()).NotTo(HaveOccurred()) + Expect(zRevRange.Val()).To(Equal([]string{"two", "one"})) + }) - It("should SetXX with expiration", func() { - isSet, err := client.SetXX(ctx, "key", "hello2", time.Second).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(isSet).To(Equal(false)) + It("should ZRevRangeWithScoresMap", func() { + err := client.ZAdd(ctx, "zset", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 3, Member: "three"}).Err() + Expect(err).NotTo(HaveOccurred()) + + val, err := client.ZRevRangeWithScores(ctx, "zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]redis.Z{{ + Score: 3, + Member: "three", + }, { + Score: 2, + Member: "two", + }, { + Score: 1, + Member: "one", + }})) + + val, err = client.ZRevRangeWithScores(ctx, "zset", 2, 3).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]redis.Z{{Score: 1, Member: "one"}})) + + val, err = client.ZRevRangeWithScores(ctx, "zset", -2, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]redis.Z{{ + Score: 2, + Member: "two", + }, { + Score: 1, + Member: "one", + }})) + }) - err = client.Set(ctx, "key", "hello", time.Second).Err() - Expect(err).NotTo(HaveOccurred()) + It("should ZRevRangeByScore", func() { + err := client.ZAdd(ctx, "zset", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 3, Member: "three"}).Err() + Expect(err).NotTo(HaveOccurred()) + + vals, err := client.ZRevRangeByScore( + ctx, "zset", &redis.ZRangeBy{Max: "+inf", Min: "-inf"}).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]string{"three", "two", "one"})) + + vals, err = client.ZRevRangeByScore( + ctx, "zset", &redis.ZRangeBy{Max: "2", Min: "(1"}).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]string{"two"})) + + vals, err = client.ZRevRangeByScore( + ctx, "zset", &redis.ZRangeBy{Max: "(2", Min: "(1"}).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]string{})) + }) - isSet, err = client.SetXX(ctx, "key", "hello2", time.Second).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(isSet).To(Equal(true)) + It("should ZRevRangeByLex", func() { + err := client.ZAdd(ctx, "zset", redis.Z{Score: 0, Member: "a"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 0, Member: "b"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 0, Member: "c"}).Err() + Expect(err).NotTo(HaveOccurred()) + + vals, err := client.ZRevRangeByLex( + ctx, "zset", &redis.ZRangeBy{Max: "+", Min: "-"}).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]string{"c", "b", "a"})) + + vals, err = client.ZRevRangeByLex( + ctx, "zset", &redis.ZRangeBy{Max: "[b", Min: "(a"}).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]string{"b"})) + + vals, err = client.ZRevRangeByLex( + ctx, "zset", &redis.ZRangeBy{Max: "(b", Min: "(a"}).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]string{})) + }) - val, err := client.Get(ctx, "key").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal("hello2")) - }) + It("should ZRevRangeByScoreWithScores", func() { + err := client.ZAdd(ctx, "zset", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 3, Member: "three"}).Err() + Expect(err).NotTo(HaveOccurred()) + + vals, err := client.ZRevRangeByScoreWithScores( + ctx, "zset", &redis.ZRangeBy{Max: "+inf", Min: "-inf"}).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{ + Score: 3, + Member: "three", + }, { + Score: 2, + Member: "two", + }, { + Score: 1, + Member: "one", + }})) + }) - It("should SetXX with keepttl", func() { - isSet, err := client.SetXX(ctx, "key", "hello2", time.Second).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(isSet).To(Equal(false)) + It("should ZRevRangeByScoreWithScoresMap", func() { + err := client.ZAdd(ctx, "zset", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 3, Member: "three"}).Err() + Expect(err).NotTo(HaveOccurred()) + + vals, err := client.ZRevRangeByScoreWithScores( + ctx, "zset", &redis.ZRangeBy{Max: "+inf", Min: "-inf"}).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{ + Score: 3, + Member: "three", + }, { + Score: 2, + Member: "two", + }, { + Score: 1, + Member: "one", + }})) + + vals, err = client.ZRevRangeByScoreWithScores( + ctx, "zset", &redis.ZRangeBy{Max: "2", Min: "(1"}).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{Score: 2, Member: "two"}})) + + vals, err = client.ZRevRangeByScoreWithScores( + ctx, "zset", &redis.ZRangeBy{Max: "(2", Min: "(1"}).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{})) + }) - err = client.Set(ctx, "key", "hello", time.Second).Err() - Expect(err).NotTo(HaveOccurred()) + It("should ZRevRank", func() { + err := client.ZAdd(ctx, "zset", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 3, Member: "three"}).Err() + Expect(err).NotTo(HaveOccurred()) + + zRevRank := client.ZRevRank(ctx, "zset", "one") + Expect(zRevRank.Err()).NotTo(HaveOccurred()) + Expect(zRevRank.Val()).To(Equal(int64(2))) + + zRevRank = client.ZRevRank(ctx, "zset", "four") + Expect(zRevRank.Err()).To(Equal(redis.Nil)) + Expect(zRevRank.Val()).To(Equal(int64(0))) + }) - isSet, err = client.SetXX(ctx, "key", "hello2", 5*time.Second).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(isSet).To(Equal(true)) + PIt("should ZRevRankWithScore", func() { + err := client.ZAdd(ctx, "zset", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 3, Member: "three"}).Err() + Expect(err).NotTo(HaveOccurred()) + + zRevRankWithScore := client.ZRevRankWithScore(ctx, "zset", "one") + Expect(zRevRankWithScore.Err()).NotTo(HaveOccurred()) + Expect(zRevRankWithScore.Result()).To(Equal(redis.RankScore{Rank: 2, Score: 1})) + + zRevRankWithScore = client.ZRevRankWithScore(ctx, "zset", "two") + Expect(zRevRankWithScore.Err()).NotTo(HaveOccurred()) + Expect(zRevRankWithScore.Result()).To(Equal(redis.RankScore{Rank: 1, Score: 2})) + + zRevRankWithScore = client.ZRevRankWithScore(ctx, "zset", "three") + Expect(zRevRankWithScore.Err()).NotTo(HaveOccurred()) + Expect(zRevRankWithScore.Result()).To(Equal(redis.RankScore{Rank: 0, Score: 3})) + + zRevRankWithScore = client.ZRevRankWithScore(ctx, "zset", "four") + Expect(zRevRankWithScore.Err()).To(HaveOccurred()) + Expect(zRevRankWithScore.Err()).To(Equal(redis.Nil)) + }) - //isSet, err = client.SetXX(ctx, "key", "hello3", redis.KeepTTL).Result() - //Expect(err).NotTo(HaveOccurred()) - //Expect(isSet).To(Equal(true)) + It("should ZScore", func() { + zAdd := client.ZAdd(ctx, "zset", redis.Z{Score: 1.001, Member: "one"}) + Expect(zAdd.Err()).NotTo(HaveOccurred()) - val, err := client.Get(ctx, "key").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal("hello2")) + zScore := client.ZScore(ctx, "zset", "one") + Expect(zScore.Err()).NotTo(HaveOccurred()) + Expect(zScore.Val()).To(Equal(1.001)) + }) - // set keepttl will Retain the ttl associated with the key - ttl, err := client.TTL(ctx, "key").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(ttl).NotTo(Equal(-1)) - }) + PIt("should ZUnion", func() { + err := client.ZAddArgs(ctx, "zset1", redis.ZAddArgs{ + Members: []redis.Z{ + {Score: 1, Member: "one"}, + {Score: 2, Member: "two"}, + }, + }).Err() + Expect(err).NotTo(HaveOccurred()) + + err = client.ZAddArgs(ctx, "zset2", redis.ZAddArgs{ + Members: []redis.Z{ + {Score: 1, Member: "one"}, + {Score: 2, Member: "two"}, + {Score: 3, Member: "three"}, + }, + }).Err() + Expect(err).NotTo(HaveOccurred()) + + union, err := client.ZUnion(ctx, redis.ZStore{ + Keys: []string{"zset1", "zset2"}, + Weights: []float64{2, 3}, + Aggregate: "sum", + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(union).To(Equal([]string{"one", "three", "two"})) + + unionScores, err := client.ZUnionWithScores(ctx, redis.ZStore{ + Keys: []string{"zset1", "zset2"}, + Weights: []float64{2, 3}, + Aggregate: "sum", + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(unionScores).To(Equal([]redis.Z{ + {Score: 5, Member: "one"}, + {Score: 9, Member: "three"}, + {Score: 10, Member: "two"}, + })) + }) - It("should SetRange", func() { - set := client.Set(ctx, "key", "Hello World", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) + It("should ZUnionStore", func() { + err := client.ZAdd(ctx, "zset1", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset1", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + + err = client.ZAdd(ctx, "zset2", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset2", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset2", redis.Z{Score: 3, Member: "three"}).Err() + Expect(err).NotTo(HaveOccurred()) + + n, err := client.ZUnionStore(ctx, "out", &redis.ZStore{ + Keys: []string{"zset1", "zset2"}, + Weights: []float64{2, 3}, + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(n).To(Equal(int64(3))) + + val, err := client.ZRangeWithScores(ctx, "out", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]redis.Z{{ + Score: 5, + Member: "one", + }, { + Score: 9, + Member: "three", + }, { + Score: 10, + Member: "two", + }})) + }) - range_ := client.SetRange(ctx, "key", 6, "Redis") - Expect(range_.Err()).NotTo(HaveOccurred()) - Expect(range_.Val()).To(Equal(int64(11))) + PIt("should ZRandMember", func() { + err := client.ZAdd(ctx, "zset", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + + v := client.ZRandMember(ctx, "zset", 1) + Expect(v.Err()).NotTo(HaveOccurred()) + Expect(v.Val()).To(Or(Equal([]string{"one"}), Equal([]string{"two"}))) + + v = client.ZRandMember(ctx, "zset", 0) + Expect(v.Err()).NotTo(HaveOccurred()) + Expect(v.Val()).To(HaveLen(0)) + + kv, err := client.ZRandMemberWithScores(ctx, "zset", 1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(kv).To(Or( + Equal([]redis.Z{{Member: "one", Score: 1}}), + Equal([]redis.Z{{Member: "two", Score: 2}}), + )) + }) - get := client.Get(ctx, "key") - Expect(get.Err()).NotTo(HaveOccurred()) - Expect(get.Val()).To(Equal("Hello Redis")) - }) + PIt("should ZDiff", func() { + err := client.ZAdd(ctx, "zset1", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset1", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset1", redis.Z{Score: 3, Member: "three"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset2", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + + v, err := client.ZDiff(ctx, "zset1", "zset2").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(v).To(Equal([]string{"two", "three"})) + }) - It("should StrLen", func() { - set := client.Set(ctx, "key", "hello", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) + PIt("should ZDiffWithScores", func() { + err := client.ZAdd(ctx, "zset1", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset1", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset1", redis.Z{Score: 3, Member: "three"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset2", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + + v, err := client.ZDiffWithScores(ctx, "zset1", "zset2").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(v).To(Equal([]redis.Z{ + { + Member: "two", + Score: 2, + }, + { + Member: "three", + Score: 3, + }, + })) + }) - strLen := client.StrLen(ctx, "key") - Expect(strLen.Err()).NotTo(HaveOccurred()) - Expect(strLen.Val()).To(Equal(int64(5))) + PIt("should ZInter", func() { + err := client.ZAdd(ctx, "zset1", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset1", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset2", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset2", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset2", redis.Z{Score: 3, Member: "three"}).Err() + Expect(err).NotTo(HaveOccurred()) + + v, err := client.ZInter(ctx, &redis.ZStore{ + Keys: []string{"zset1", "zset2"}, + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(v).To(Equal([]string{"one", "two"})) + }) - strLen = client.StrLen(ctx, "_") - Expect(strLen.Err()).NotTo(HaveOccurred()) - Expect(strLen.Val()).To(Equal(int64(0))) - }) + PIt("should ZInterCard", func() { + err := client.ZAdd(ctx, "zset1", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset1", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset2", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset2", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset2", redis.Z{Score: 3, Member: "three"}).Err() + Expect(err).NotTo(HaveOccurred()) + + // limit 0 means no limit + sInterCard := client.ZInterCard(ctx, 0, "zset1", "zset2") + Expect(sInterCard.Err()).NotTo(HaveOccurred()) + Expect(sInterCard.Val()).To(Equal(int64(2))) + + sInterCard = client.ZInterCard(ctx, 1, "zset1", "zset2") + Expect(sInterCard.Err()).NotTo(HaveOccurred()) + Expect(sInterCard.Val()).To(Equal(int64(1))) + + sInterCard = client.ZInterCard(ctx, 3, "zset1", "zset2") + Expect(sInterCard.Err()).NotTo(HaveOccurred()) + Expect(sInterCard.Val()).To(Equal(int64(2))) + }) - //It("should Copy", func() { - // set := client.Set(ctx, "key", "hello", 0) - // Expect(set.Err()).NotTo(HaveOccurred()) - // Expect(set.Val()).To(Equal("OK")) - // - // copy := client.Copy(ctx, "key", "newKey", redisOptions().DB, false) - // Expect(copy.Err()).NotTo(HaveOccurred()) - // Expect(copy.Val()).To(Equal(int64(1))) - // - // // Value is available by both keys now - // getOld := client.Get(ctx, "key") - // Expect(getOld.Err()).NotTo(HaveOccurred()) - // Expect(getOld.Val()).To(Equal("hello")) - // getNew := client.Get(ctx, "newKey") - // Expect(getNew.Err()).NotTo(HaveOccurred()) - // Expect(getNew.Val()).To(Equal("hello")) - // - // // Overwriting an existing key should not succeed - // overwrite := client.Copy(ctx, "newKey", "key", redisOptions().DB, false) - // Expect(overwrite.Val()).To(Equal(int64(0))) - // - // // Overwrite is allowed when replace=rue - // replace := client.Copy(ctx, "newKey", "key", redisOptions().DB, true) - // Expect(replace.Val()).To(Equal(int64(1))) - //}) - - //It("should acl dryrun", func() { - // dryRun := client.ACLDryRun(ctx, "default", "get", "randomKey") - // Expect(dryRun.Err()).NotTo(HaveOccurred()) - // Expect(dryRun.Val()).To(Equal("OK")) - //}) - - //It("should fail module loadex", func() { - // dryRun := client.ModuleLoadex(ctx, &redis.ModuleLoadexConfig{ - // Path: "/path/to/non-existent-library.so", - // Conf: map[string]interface{}{ - // "param1": "value1", - // }, - // Args: []interface{}{ - // "arg1", - // }, - // }) - // Expect(dryRun.Err()).To(HaveOccurred()) - // Expect(dryRun.Err().Error()).To(Equal("ERR Error loading the extension. Please check the server logs.")) - //}) + PIt("should ZInterWithScores", func() { + err := client.ZAdd(ctx, "zset1", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset1", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset2", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset2", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset2", redis.Z{Score: 3, Member: "three"}).Err() + Expect(err).NotTo(HaveOccurred()) + + v, err := client.ZInterWithScores(ctx, &redis.ZStore{ + Keys: []string{"zset1", "zset2"}, + Weights: []float64{2, 3}, + Aggregate: "Max", + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(v).To(Equal([]redis.Z{ + { + Member: "one", + Score: 3, + }, + { + Member: "two", + Score: 6, + }, + })) + }) + PIt("should ZDiffStore", func() { + err := client.ZAdd(ctx, "zset1", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset1", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset2", redis.Z{Score: 1, Member: "one"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset2", redis.Z{Score: 2, Member: "two"}).Err() + Expect(err).NotTo(HaveOccurred()) + err = client.ZAdd(ctx, "zset2", redis.Z{Score: 3, Member: "three"}).Err() + Expect(err).NotTo(HaveOccurred()) + v, err := client.ZDiffStore(ctx, "out1", "zset1", "zset2").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(v).To(Equal(int64(0))) + v, err = client.ZDiffStore(ctx, "out1", "zset2", "zset1").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(v).To(Equal(int64(1))) + vals, err := client.ZRangeWithScores(ctx, "out1", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{ + Score: 3, + Member: "three", + }})) }) })