diff --git a/.github/workflows/pika.yml b/.github/workflows/pika.yml index 913348664c..227d2bee70 100644 --- a/.github/workflows/pika.yml +++ b/.github/workflows/pika.yml @@ -20,6 +20,11 @@ jobs: steps: - uses: actions/checkout@v3 + - name: Set up Go + uses: actions/setup-go@v3 + with: + go-version: 1.19 + - name: cache dependencies uses: actions/cache@v2 id: cache @@ -69,6 +74,13 @@ jobs: 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: | + cd ../tests/integration/ + chmod +x integrate_test.sh + sh integrate_test.sh + build_on_centos: runs-on: ubuntu-latest container: @@ -83,6 +95,11 @@ jobs: python3 -m pip install --upgrade pip python3 -m pip install redis + - name: Set up Go + uses: actions/setup-go@v3 + with: + go-version: 1.19 + - name: Install cmake run: | wget https://github.com/Kitware/CMake/releases/download/v3.26.4/cmake-3.26.4-linux-x86_64.sh @@ -129,6 +146,11 @@ jobs: steps: - uses: actions/checkout@v3 + - name: Set up Go + uses: actions/setup-go@v3 + with: + go-version: 1.19 + - name: cache dependencies uses: actions/cache@v2 id: cache @@ -175,4 +197,11 @@ jobs: working-directory: ${{ github.workspace }}/build run: | python3 ../tests/integration/pika_replication_test.py - python3 ../tests/unit/Blpop_Brpop_test.py \ No newline at end of file + python3 ../tests/unit/Blpop_Brpop_test.py + + - name: Run Go E2E Tests + working-directory: ${{ github.workspace }}/build + run: | + cd ../tests/integration/ + chmod +x integrate_test.sh + sh integrate_test.sh \ No newline at end of file diff --git a/src/pika_list.cc b/src/pika_list.cc index 7e7604f57c..67d709b668 100644 --- a/src/pika_list.cc +++ b/src/pika_list.cc @@ -331,6 +331,7 @@ void LPopCmd::DoInitial() { void LPopCmd::Do(std::shared_ptr slot) { std::vector elements; rocksdb::Status s = slot->db()->LPop(key_, count_, &elements); + if (s.ok()) { res_.AppendArrayLenUint64(elements.size()); for (const auto& element : elements) { diff --git a/tests/integration/csanning_test.go b/tests/integration/csanning_test.go new file mode 100644 index 0000000000..cfd7d16a09 --- /dev/null +++ b/tests/integration/csanning_test.go @@ -0,0 +1,89 @@ +package pika_integration + +import ( + "context" + "fmt" + + . "github.com/bsm/ginkgo/v2" + . "github.com/bsm/gomega" + "github.com/redis/go-redis/v9" +) + +var _ = Describe("Csanning Commands", func() { + ctx := context.TODO() + var client *redis.Client + + BeforeEach(func() { + client = redis.NewClient(pikaOptions1()) + Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred()) + }) + + AfterEach(func() { + Expect(client.Close()).NotTo(HaveOccurred()) + }) + + Describe("scanning", func() { + It("should Scan", func() { + for i := 0; i < 1000; i++ { + set := client.Set(ctx, fmt.Sprintf("key%d", i), "hello", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + } + + keys, cursor, err := client.Scan(ctx, 0, "", 0).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(keys).NotTo(BeEmpty()) + Expect(cursor).NotTo(BeZero()) + }) + + It("should ScanType", func() { + for i := 0; i < 1000; i++ { + set := client.Set(ctx, fmt.Sprintf("key%d", i), "hello", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + } + + keys, cursor, err := client.ScanType(ctx, 0, "", 0, "").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(keys).NotTo(BeEmpty()) + Expect(cursor).NotTo(BeZero()) + }) + + It("should SScan", func() { + for i := 0; i < 1000; i++ { + sadd := client.SAdd(ctx, "myset", fmt.Sprintf("member%d", i)) + Expect(sadd.Err()).NotTo(HaveOccurred()) + } + + keys, cursor, err := client.SScan(ctx, "myset", 0, "", 0).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(keys).NotTo(BeEmpty()) + Expect(cursor).NotTo(BeZero()) + }) + + It("should HScan", func() { + for i := 0; i < 1000; i++ { + sadd := client.HSet(ctx, "myhash", fmt.Sprintf("key%d", i), "hello") + Expect(sadd.Err()).NotTo(HaveOccurred()) + } + + keys, cursor, err := client.HScan(ctx, "myhash", 0, "", 0).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(keys).NotTo(BeEmpty()) + Expect(cursor).NotTo(BeZero()) + }) + + It("should ZScan", func() { + for i := 0; i < 1000; i++ { + err := client.ZAdd(ctx, "myset", redis.Z{ + Score: float64(i), + Member: fmt.Sprintf("member%d", i), + }).Err() + Expect(err).NotTo(HaveOccurred()) + } + + keys, cursor, err := client.ZScan(ctx, "myset", 0, "", 0).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(keys).NotTo(BeEmpty()) + Expect(cursor).NotTo(BeZero()) + }) + }) +}) diff --git a/tests/integration/geo_test.go b/tests/integration/geo_test.go new file mode 100644 index 0000000000..8d3fc403ed --- /dev/null +++ b/tests/integration/geo_test.go @@ -0,0 +1,417 @@ +package pika_integration + +import ( + "context" + + . "github.com/bsm/ginkgo/v2" + . "github.com/bsm/gomega" + "github.com/redis/go-redis/v9" +) + +var _ = Describe("Geo Commands", func() { + ctx := context.TODO() + var client *redis.Client + + BeforeEach(func() { + client = redis.NewClient(pikaOptions1()) + Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred()) + }) + + AfterEach(func() { + Expect(client.Close()).NotTo(HaveOccurred()) + }) + + Describe("Geo add and radius search", func() { + BeforeEach(func() { + n, err := client.GeoAdd( + ctx, + "Sicily", + &redis.GeoLocation{Longitude: 13.361389, Latitude: 38.115556, Name: "Palermo"}, + &redis.GeoLocation{Longitude: 15.087269, Latitude: 37.502669, Name: "Catania"}, + ).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(n).To(Equal(int64(2))) + }) + + It("should not add same geo location", func() { + geoAdd := client.GeoAdd( + ctx, + "Sicily", + &redis.GeoLocation{Longitude: 13.361389, Latitude: 38.115556, Name: "Palermo"}, + ) + Expect(geoAdd.Err()).NotTo(HaveOccurred()) + 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 geo radius and store the result", func() { + n, err := client.GeoRadiusStore(ctx, "Sicily", 15, 37, &redis.GeoRadiusQuery{ + Radius: 200, + Store: "result", + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(n).To(Equal(int64(2))) + + res, err := client.ZRangeWithScores(ctx, "result", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(res).To(ContainElement(redis.Z{ + Score: 3.479099956230698e+15, + Member: "Palermo", + })) + Expect(res).To(ContainElement(redis.Z{ + Score: 3.479447370796909e+15, + Member: "Catania", + })) + }) + + It("should geo radius and store dist", func() { + n, err := client.GeoRadiusStore(ctx, "Sicily", 15, 37, &redis.GeoRadiusQuery{ + Radius: 200, + StoreDist: "result", + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(n).To(Equal(int64(2))) + + res, err := client.ZRangeWithScores(ctx, "result", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(res).To(ContainElement(redis.Z{ + Score: 190.44242984775784, + Member: "Palermo", + })) + Expect(res).To(ContainElement(redis.Z{ + Score: 56.4412578701582, + Member: "Catania", + })) + }) + + //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. + // + // GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania" + // GEODIST Sicily Palermo Catania m + // "166274.15156960033" + // GEODIST Sicily Palermo Catania km + // "166.27415156960032" + dist, err := client.GeoDist(ctx, "Sicily", "Palermo", "Catania", "km").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(dist).To(BeNumerically("~", 166.27, 0.01)) + + dist, err = client.GeoDist(ctx, "Sicily", "Palermo", "Catania", "m").Result() + Expect(err).NotTo(HaveOccurred()) + 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 return geo position", func() { + pos, err := client.GeoPos(ctx, "Sicily", "Palermo", "Catania", "NonExisting").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(pos).To(ConsistOf([]*redis.GeoPos{ + { + Longitude: 13.361389338970184, + Latitude: 38.1155563954963, + }, + { + Longitude: 15.087267458438873, + Latitude: 37.50266842333162, + }, + nil, + })) + }) + + //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, + // }, + // })) + //}) + + //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", + // }, + // })) + //}) + }) +}) diff --git a/tests/integration/go.mod b/tests/integration/go.mod new file mode 100644 index 0000000000..6329f50d22 --- /dev/null +++ b/tests/integration/go.mod @@ -0,0 +1,14 @@ +module pika-integration + +go 1.19 + +require ( + github.com/bsm/ginkgo/v2 v2.7.0 + github.com/bsm/gomega v1.26.0 + github.com/redis/go-redis/v9 v9.0.4 +) + +require ( + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect +) diff --git a/tests/integration/hash_test.go b/tests/integration/hash_test.go new file mode 100644 index 0000000000..a8ad898672 --- /dev/null +++ b/tests/integration/hash_test.go @@ -0,0 +1,332 @@ +package pika_integration + +import ( + "context" + "time" + + . "github.com/bsm/ginkgo/v2" + . "github.com/bsm/gomega" + + "github.com/redis/go-redis/v9" +) + +var _ = Describe("List Commands", func() { + ctx := context.TODO() + var client *redis.Client + + BeforeEach(func() { + client = redis.NewClient(pikaOptions1()) + Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred()) + }) + + AfterEach(func() { + Expect(client.Close()).NotTo(HaveOccurred()) + }) + + Describe("hashes", func() { + It("should HDel", func() { + hSet := client.HSet(ctx, "hash", "key", "hello") + Expect(hSet.Err()).NotTo(HaveOccurred()) + + hDel := client.HDel(ctx, "hash", "key") + Expect(hDel.Err()).NotTo(HaveOccurred()) + Expect(hDel.Val()).To(Equal(int64(1))) + + hDel = client.HDel(ctx, "hash", "key") + Expect(hDel.Err()).NotTo(HaveOccurred()) + Expect(hDel.Val()).To(Equal(int64(0))) + }) + + It("should HExists", func() { + hSet := client.HSet(ctx, "hash", "key", "hello") + Expect(hSet.Err()).NotTo(HaveOccurred()) + + hExists := client.HExists(ctx, "hash", "key") + Expect(hExists.Err()).NotTo(HaveOccurred()) + Expect(hExists.Val()).To(Equal(true)) + + hExists = client.HExists(ctx, "hash", "key1") + Expect(hExists.Err()).NotTo(HaveOccurred()) + Expect(hExists.Val()).To(Equal(false)) + }) + + It("should HGet", func() { + hSet := client.HSet(ctx, "hash", "key", "hello") + Expect(hSet.Err()).NotTo(HaveOccurred()) + + hGet := client.HGet(ctx, "hash", "key") + Expect(hGet.Err()).NotTo(HaveOccurred()) + Expect(hGet.Val()).To(Equal("hello")) + + hGet = client.HGet(ctx, "hash", "key1") + Expect(hGet.Err()).To(Equal(redis.Nil)) + Expect(hGet.Val()).To(Equal("")) + }) + + It("should HGetAll", 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()) + + m, err := client.HGetAll(ctx, "hash").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(m).To(Equal(map[string]string{"key1": "hello1", "key2": "hello2"})) + }) + + It("should scan", func() { + now := time.Now() + + err := client.HMSet(ctx, "hash", "key1", "hello1", "key2", 123, "time", now.Format(time.RFC3339Nano)).Err() + Expect(err).NotTo(HaveOccurred()) + + res := client.HGetAll(ctx, "hash") + 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{}}, + })) + + //type data2 struct { + // Key1 string `redis:"key1"` + // Key2 int `redis:"key2"` + // Time time.Time `redis:"time"` + //} + ////err = client.HSet(ctx, "hash", &data2{ + //// Key1: "hello2", + //// Key2: 200, + //// Time: now, + ////}).Err() + ////Expect(err).NotTo(HaveOccurred()) + // + //var d2 data2 + //err = client.HMGet(ctx, "hash", "key1", "key2", "time").Scan(&d2) + //Expect(err).NotTo(HaveOccurred()) + //Expect(d2.Key1).To(Equal("hello2")) + //Expect(d2.Key2).To(Equal(200)) + //Expect(d2.Time.Unix()).To(Equal(now.Unix())) + }) + + It("should HIncrBy", func() { + hSet := client.HSet(ctx, "hash", "key", "5") + Expect(hSet.Err()).NotTo(HaveOccurred()) + + hIncrBy := client.HIncrBy(ctx, "hash", "key", 1) + Expect(hIncrBy.Err()).NotTo(HaveOccurred()) + Expect(hIncrBy.Val()).To(Equal(int64(6))) + + hIncrBy = client.HIncrBy(ctx, "hash", "key", -1) + Expect(hIncrBy.Err()).NotTo(HaveOccurred()) + Expect(hIncrBy.Val()).To(Equal(int64(5))) + + hIncrBy = client.HIncrBy(ctx, "hash", "key", -10) + Expect(hIncrBy.Err()).NotTo(HaveOccurred()) + Expect(hIncrBy.Val()).To(Equal(int64(-5))) + }) + + It("should HIncrByFloat", func() { + hSet := client.HSet(ctx, "hash", "field", "10.50") + Expect(hSet.Err()).NotTo(HaveOccurred()) + Expect(hSet.Val()).To(Equal(int64(1))) + + hIncrByFloat := client.HIncrByFloat(ctx, "hash", "field", 0.1) + Expect(hIncrByFloat.Err()).NotTo(HaveOccurred()) + Expect(hIncrByFloat.Val()).To(Equal(10.6)) + + hSet = client.HSet(ctx, "hash", "field", "5.0e3") + Expect(hSet.Err()).NotTo(HaveOccurred()) + Expect(hSet.Val()).To(Equal(int64(0))) + + hIncrByFloat = client.HIncrByFloat(ctx, "hash", "field", 2.0e2) + Expect(hIncrByFloat.Err()).NotTo(HaveOccurred()) + Expect(hIncrByFloat.Val()).To(Equal(float64(5200))) + }) + + It("should HKeys", func() { + hkeys := client.HKeys(ctx, "hash") + Expect(hkeys.Err()).NotTo(HaveOccurred()) + Expect(hkeys.Val()).To(Equal([]string{})) + + hset := client.HSet(ctx, "hash", "key1", "hello1") + Expect(hset.Err()).NotTo(HaveOccurred()) + hset = client.HSet(ctx, "hash", "key2", "hello2") + Expect(hset.Err()).NotTo(HaveOccurred()) + + hkeys = client.HKeys(ctx, "hash") + Expect(hkeys.Err()).NotTo(HaveOccurred()) + Expect(hkeys.Val()).To(Equal([]string{"key1", "key2"})) + }) + + It("should HLen", func() { + hSet := client.HSet(ctx, "hash", "key1", "hello1") + Expect(hSet.Err()).NotTo(HaveOccurred()) + hSet = client.HSet(ctx, "hash", "key2", "hello2") + Expect(hSet.Err()).NotTo(HaveOccurred()) + + hLen := client.HLen(ctx, "hash") + Expect(hLen.Err()).NotTo(HaveOccurred()) + Expect(hLen.Val()).To(Equal(int64(2))) + }) + + It("should HMGet", func() { + err := client.HSet(ctx, "hash", "key1", "hello1").Err() + Expect(err).NotTo(HaveOccurred()) + + vals, err := client.HMGet(ctx, "hash", "key1").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]interface{}{"hello1"})) + }) + + It("should HSet", func() { + _, err := client.Del(ctx, "hash").Result() + Expect(err).NotTo(HaveOccurred()) + + ok, err := client.HSet(ctx, "hash", map[string]interface{}{ + "key1": "hello1", + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(ok).To(Equal(int64(1))) + + ok, err = client.HSet(ctx, "hash", map[string]interface{}{ + "key2": "hello2", + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(ok).To(Equal(int64(1))) + + v, err := client.HGet(ctx, "hash", "key1").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(v).To(Equal("hello1")) + + v, err = client.HGet(ctx, "hash", "key2").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(v).To(Equal("hello2")) + + keys, err := client.HKeys(ctx, "hash").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(keys).To(ConsistOf([]string{"key1", "key2"})) + }) + + It("should HSet", func() { + hSet := client.HSet(ctx, "hash", "key", "hello") + Expect(hSet.Err()).NotTo(HaveOccurred()) + Expect(hSet.Val()).To(Equal(int64(1))) + + hGet := client.HGet(ctx, "hash", "key") + Expect(hGet.Err()).NotTo(HaveOccurred()) + Expect(hGet.Val()).To(Equal("hello")) + + // 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"` + } + + // 命令格式不对:hset hash set1 val1 set2 1024 set3 2000000 set4 + //hSet = client.HSet(ctx, "hash", &set{ + // Set1: "val1", + // Set2: 1024, + // Set3: 2 * time.Millisecond, + // Set4: nil, + // Set5: map[string]interface{}{"k1": 1}, + //}) + //Expect(hSet.Err()).NotTo(HaveOccurred()) + //Expect(hSet.Val()).To(Equal(int64(4))) + + //hMGet := client.HMGet(ctx, "hash", "set1", "set2", "set3", "set4", "set5", "set6") + //Expect(hMGet.Err()).NotTo(HaveOccurred()) + //Expect(hMGet.Val()).To(Equal([]interface{}{ + // "val1", + // "1024", + // strconv.Itoa(int(2 * time.Millisecond.Nanoseconds())), + // "", + // nil, + // nil, + //})) + + //hSet = client.HSet(ctx, "hash2", &set{ + // Set1: "val2", + // Set6: "val", + //}) + //Expect(hSet.Err()).NotTo(HaveOccurred()) + //Expect(hSet.Val()).To(Equal(int64(5))) + // + //hMGet = client.HMGet(ctx, "hash2", "set1", "set6") + //Expect(hMGet.Err()).NotTo(HaveOccurred()) + //Expect(hMGet.Val()).To(Equal([]interface{}{ + // "val2", + // "val", + //})) + }) + + It("should HSetNX", func() { + res := client.Del(ctx, "hash") + Expect(res.Err()).NotTo(HaveOccurred()) + + hSetNX := client.HSetNX(ctx, "hash", "key", "hello") + Expect(hSetNX.Err()).NotTo(HaveOccurred()) + Expect(hSetNX.Val()).To(Equal(true)) + + hSetNX = client.HSetNX(ctx, "hash", "key", "hello") + Expect(hSetNX.Err()).NotTo(HaveOccurred()) + Expect(hSetNX.Val()).To(Equal(false)) + + hGet := client.HGet(ctx, "hash", "key") + Expect(hGet.Err()).NotTo(HaveOccurred()) + Expect(hGet.Val()).To(Equal("hello")) + }) + + It("should HVals", func() { + err := client.HSet(ctx, "hash121", "key1", "hello1").Err() + Expect(err).NotTo(HaveOccurred()) + err = client.HSet(ctx, "hash121", "key2", "hello2").Err() + Expect(err).NotTo(HaveOccurred()) + + v, err := client.HVals(ctx, "hash121").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(v).To(Equal([]string{"hello1", "hello2"})) + + var slice []string + err = client.HVals(ctx, "hash121").ScanSlice(&slice) + Expect(err).NotTo(HaveOccurred()) + 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"}}), + // )) + //}) + }) +}) diff --git a/tests/integration/hyperloglog_test.go b/tests/integration/hyperloglog_test.go new file mode 100644 index 0000000000..67a54a006f --- /dev/null +++ b/tests/integration/hyperloglog_test.go @@ -0,0 +1,48 @@ +package pika_integration + +import ( + "context" + + . "github.com/bsm/ginkgo/v2" + . "github.com/bsm/gomega" + "github.com/redis/go-redis/v9" +) + +var _ = Describe("Hyperloglog Commands", func() { + ctx := context.TODO() + var client *redis.Client + + BeforeEach(func() { + client = redis.NewClient(pikaOptions1()) + Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred()) + }) + + AfterEach(func() { + Expect(client.Close()).NotTo(HaveOccurred()) + }) + + Describe("hyperloglog", func() { + It("should PFMerge", func() { + pfAdd := client.PFAdd(ctx, "hll1", "1", "2", "3", "4", "5") + Expect(pfAdd.Err()).NotTo(HaveOccurred()) + + pfCount := client.PFCount(ctx, "hll1") + Expect(pfCount.Err()).NotTo(HaveOccurred()) + Expect(pfCount.Val()).To(Equal(int64(5))) + + pfAdd = client.PFAdd(ctx, "hll2", "a", "b", "c", "d", "e") + Expect(pfAdd.Err()).NotTo(HaveOccurred()) + + pfMerge := client.PFMerge(ctx, "hllMerged", "hll1", "hll2") + Expect(pfMerge.Err()).NotTo(HaveOccurred()) + + pfCount = client.PFCount(ctx, "hllMerged") + Expect(pfCount.Err()).NotTo(HaveOccurred()) + Expect(pfCount.Val()).To(Equal(int64(10))) + + pfCount = client.PFCount(ctx, "hll1", "hll2") + Expect(pfCount.Err()).NotTo(HaveOccurred()) + Expect(pfCount.Val()).To(Equal(int64(10))) + }) + }) +}) diff --git a/tests/integration/integrate_test.sh b/tests/integration/integrate_test.sh new file mode 100755 index 0000000000..4fbcb92da0 --- /dev/null +++ b/tests/integration/integrate_test.sh @@ -0,0 +1,18 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +go mod tidy +go test \ No newline at end of file diff --git a/tests/integration/list_test.go b/tests/integration/list_test.go new file mode 100644 index 0000000000..66768e77b0 --- /dev/null +++ b/tests/integration/list_test.go @@ -0,0 +1,739 @@ +package pika_integration + +import ( + "context" + "time" + + . "github.com/bsm/ginkgo/v2" + . "github.com/bsm/gomega" + + "github.com/redis/go-redis/v9" +) + +var _ = Describe("List Commands", func() { + ctx := context.TODO() + var client *redis.Client + + BeforeEach(func() { + client = redis.NewClient(pikaOptions1()) + Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred()) + }) + + AfterEach(func() { + Expect(client.Close()).NotTo(HaveOccurred()) + }) + + Describe("lists", func() { + It("should BLPop", func() { + rPush := client.RPush(ctx, "list1", "a", "b", "c") + Expect(rPush.Err()).NotTo(HaveOccurred()) + + bLPop := client.BLPop(ctx, 0, "list1", "list2") + Expect(bLPop.Err()).NotTo(HaveOccurred()) + Expect(bLPop.Val()).To(Equal([]string{"list1", "a"})) + }) + + It("should BLPopBlocks", func() { + started := make(chan bool) + done := make(chan bool) + go func() { + defer GinkgoRecover() + + started <- true + bLPop := client.BLPop(ctx, 0, "list") + Expect(bLPop.Err()).NotTo(HaveOccurred()) + Expect(bLPop.Val()).To(Equal([]string{"list", "a"})) + done <- true + }() + <-started + + select { + case <-done: + Fail("BLPop is not blocked") + case <-time.After(time.Second): + // ok + } + + rPush := client.RPush(ctx, "list", "a") + Expect(rPush.Err()).NotTo(HaveOccurred()) + + select { + case <-done: + // ok + case <-time.After(time.Second): + Fail("BLPop is still blocked") + } + }) + + It("should BLPop timeout", func() { + val, err := client.BLPop(ctx, time.Second, "list1").Result() + Expect(err).To(Equal(redis.Nil)) + Expect(val).To(BeNil()) + + Expect(client.Ping(ctx).Err()).NotTo(HaveOccurred()) + + 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 BRPop", func() { + rPush := client.RPush(ctx, "list1", "a", "b", "c") + Expect(rPush.Err()).NotTo(HaveOccurred()) + + bRPop := client.BRPop(ctx, 0, "list1", "list2") + Expect(bRPop.Err()).NotTo(HaveOccurred()) + Expect(bRPop.Val()).To(Equal([]string{"list1", "c"})) + }) + + It("should BRPop blocks", func() { + started := make(chan bool) + done := make(chan bool) + go func() { + defer GinkgoRecover() + + started <- true + brpop := client.BRPop(ctx, 0, "list") + Expect(brpop.Err()).NotTo(HaveOccurred()) + Expect(brpop.Val()).To(Equal([]string{"list", "a"})) + done <- true + }() + <-started + + select { + case <-done: + Fail("BRPop is not blocked") + case <-time.After(time.Second): + // ok + } + + rPush := client.RPush(ctx, "list", "a") + Expect(rPush.Err()).NotTo(HaveOccurred()) + + select { + case <-done: + // ok + case <-time.After(time.Second): + Fail("BRPop is still blocked") + // ok + } + }) + + //It("should BRPopLPush", func() { + // _, err := client.BRPopLPush(ctx, "list1", "list2", time.Second).Result() + // Expect(err).To(Equal(redis.Nil)) + // + // err = client.RPush(ctx, "list1", "a", "b", "c").Err() + // Expect(err).NotTo(HaveOccurred()) + // + // v, err := client.BRPopLPush(ctx, "list1", "list2", 0).Result() + // Expect(err).NotTo(HaveOccurred()) + // Expect(v).To(Equal("c")) + //}) + + //It("should LCS", func() { + // err := client.MSet(ctx, "key1", "ohmytext", "key2", "mynewtext").Err() + // Expect(err).NotTo(HaveOccurred()) + // + // lcs, err := client.LCS(ctx, &redis.LCSQuery{ + // Key1: "key1", + // Key2: "key2", + // }).Result() + // + // Expect(err).NotTo(HaveOccurred()) + // Expect(lcs.MatchString).To(Equal("mytext")) + // + // lcs, err = client.LCS(ctx, &redis.LCSQuery{ + // Key1: "nonexistent_key1", + // Key2: "key2", + // }).Result() + // + // Expect(err).NotTo(HaveOccurred()) + // Expect(lcs.MatchString).To(Equal("")) + // + // lcs, err = client.LCS(ctx, &redis.LCSQuery{ + // Key1: "key1", + // Key2: "key2", + // Len: true, + // }).Result() + // Expect(err).NotTo(HaveOccurred()) + // Expect(lcs.MatchString).To(Equal("")) + // Expect(lcs.Len).To(Equal(int64(6))) + // + // lcs, err = client.LCS(ctx, &redis.LCSQuery{ + // Key1: "key1", + // Key2: "key2", + // Idx: true, + // }).Result() + // Expect(err).NotTo(HaveOccurred()) + // Expect(lcs.MatchString).To(Equal("")) + // Expect(lcs.Len).To(Equal(int64(6))) + // Expect(lcs.Matches).To(Equal([]redis.LCSMatchedPosition{ + // { + // Key1: redis.LCSPosition{Start: 4, End: 7}, + // Key2: redis.LCSPosition{Start: 5, End: 8}, + // MatchLen: 0, + // }, + // { + // Key1: redis.LCSPosition{Start: 2, End: 3}, + // Key2: redis.LCSPosition{Start: 0, End: 1}, + // MatchLen: 0, + // }, + // })) + // + // lcs, err = client.LCS(ctx, &redis.LCSQuery{ + // Key1: "key1", + // Key2: "key2", + // Idx: true, + // MinMatchLen: 3, + // WithMatchLen: true, + // }).Result() + // Expect(err).NotTo(HaveOccurred()) + // Expect(lcs.MatchString).To(Equal("")) + // Expect(lcs.Len).To(Equal(int64(6))) + // Expect(lcs.Matches).To(Equal([]redis.LCSMatchedPosition{ + // { + // Key1: redis.LCSPosition{Start: 4, End: 7}, + // Key2: redis.LCSPosition{Start: 5, End: 8}, + // MatchLen: 4, + // }, + // })) + // + // _, err = client.Set(ctx, "keywithstringvalue", "golang", 0).Result() + // Expect(err).NotTo(HaveOccurred()) + // _, err = client.LPush(ctx, "keywithnonstringvalue", "somevalue").Result() + // Expect(err).NotTo(HaveOccurred()) + // _, err = client.LCS(ctx, &redis.LCSQuery{ + // Key1: "keywithstringvalue", + // Key2: "keywithnonstringvalue", + // }).Result() + // Expect(err).To(HaveOccurred()) + // Expect(err.Error()).To(Equal("ERR The specified keys must contain string values")) + //}) + + It("should LIndex", func() { + lPush := client.LPush(ctx, "list", "World") + Expect(lPush.Err()).NotTo(HaveOccurred()) + lPush = client.LPush(ctx, "list", "Hello") + Expect(lPush.Err()).NotTo(HaveOccurred()) + + lIndex := client.LIndex(ctx, "list", 0) + Expect(lIndex.Err()).NotTo(HaveOccurred()) + Expect(lIndex.Val()).To(Equal("Hello")) + + lIndex = client.LIndex(ctx, "list", -1) + Expect(lIndex.Err()).NotTo(HaveOccurred()) + Expect(lIndex.Val()).To(Equal("World")) + + lIndex = client.LIndex(ctx, "list", 3) + Expect(lIndex.Err()).To(Equal(redis.Nil)) + Expect(lIndex.Val()).To(Equal("")) + }) + + It("should LInsert", func() { + rPush := client.RPush(ctx, "list", "Hello") + Expect(rPush.Err()).NotTo(HaveOccurred()) + rPush = client.RPush(ctx, "list", "World") + Expect(rPush.Err()).NotTo(HaveOccurred()) + + lInsert := client.LInsert(ctx, "list", "BEFORE", "World", "There") + Expect(lInsert.Err()).NotTo(HaveOccurred()) + Expect(lInsert.Val()).To(Equal(int64(3))) + + lRange := client.LRange(ctx, "list", 0, -1) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{"Hello", "There", "World"})) + }) + + //It("should LMPop", func() { + // err := client.LPush(ctx, "list1", "one", "two", "three", "four", "five").Err() + // Expect(err).NotTo(HaveOccurred()) + // + // err = client.LPush(ctx, "list2", "a", "b", "c", "d", "e").Err() + // Expect(err).NotTo(HaveOccurred()) + // + // key, val, err := client.LMPop(ctx, "left", 3, "list1", "list2").Result() + // Expect(err).NotTo(HaveOccurred()) + // Expect(key).To(Equal("list1")) + // Expect(val).To(Equal([]string{"five", "four", "three"})) + // + // key, val, err = client.LMPop(ctx, "right", 3, "list1", "list2").Result() + // Expect(err).NotTo(HaveOccurred()) + // Expect(key).To(Equal("list1")) + // Expect(val).To(Equal([]string{"one", "two"})) + // + // key, val, err = client.LMPop(ctx, "left", 1, "list1", "list2").Result() + // Expect(err).NotTo(HaveOccurred()) + // Expect(key).To(Equal("list2")) + // Expect(val).To(Equal([]string{"e"})) + // + // key, val, err = client.LMPop(ctx, "right", 10, "list1", "list2").Result() + // Expect(err).NotTo(HaveOccurred()) + // Expect(key).To(Equal("list2")) + // Expect(val).To(Equal([]string{"a", "b", "c", "d"})) + // + // err = client.LMPop(ctx, "left", 10, "list1", "list2").Err() + // Expect(err).To(Equal(redis.Nil)) + // + // err = client.Set(ctx, "list3", 1024, 0).Err() + // Expect(err).NotTo(HaveOccurred()) + // + // err = client.LMPop(ctx, "left", 10, "list1", "list2", "list3").Err() + // Expect(err.Error()).To(Equal("WRONGTYPE Operation against a key holding the wrong kind of value")) + // + // err = client.LMPop(ctx, "right", 0, "list1", "list2").Err() + // Expect(err).To(HaveOccurred()) + //}) + + //It("should BLMPop", func() { + // err := client.LPush(ctx, "list1", "one", "two", "three", "four", "five").Err() + // Expect(err).NotTo(HaveOccurred()) + // + // err = client.LPush(ctx, "list2", "a", "b", "c", "d", "e").Err() + // Expect(err).NotTo(HaveOccurred()) + // + // key, val, err := client.BLMPop(ctx, 0, "left", 3, "list1", "list2").Result() + // Expect(err).NotTo(HaveOccurred()) + // Expect(key).To(Equal("list1")) + // Expect(val).To(Equal([]string{"five", "four", "three"})) + // + // key, val, err = client.BLMPop(ctx, 0, "right", 3, "list1", "list2").Result() + // Expect(err).NotTo(HaveOccurred()) + // Expect(key).To(Equal("list1")) + // Expect(val).To(Equal([]string{"one", "two"})) + // + // key, val, err = client.BLMPop(ctx, 0, "left", 1, "list1", "list2").Result() + // Expect(err).NotTo(HaveOccurred()) + // Expect(key).To(Equal("list2")) + // Expect(val).To(Equal([]string{"e"})) + // + // key, val, err = client.BLMPop(ctx, 0, "right", 10, "list1", "list2").Result() + // Expect(err).NotTo(HaveOccurred()) + // Expect(key).To(Equal("list2")) + // Expect(val).To(Equal([]string{"a", "b", "c", "d"})) + // + //}) + // + //It("should BLMPopBlocks", func() { + // started := make(chan bool) + // done := make(chan bool) + // go func() { + // defer GinkgoRecover() + // + // started <- true + // key, val, err := client.BLMPop(ctx, 0, "left", 1, "list_list").Result() + // Expect(err).NotTo(HaveOccurred()) + // Expect(key).To(Equal("list_list")) + // Expect(val).To(Equal([]string{"a"})) + // done <- true + // }() + // <-started + // + // select { + // case <-done: + // Fail("BLMPop is not blocked") + // case <-time.After(time.Second): + // //ok + // } + // + // _, err := client.LPush(ctx, "list_list", "a").Result() + // Expect(err).NotTo(HaveOccurred()) + // + // select { + // case <-done: + // //ok + // case <-time.After(time.Second): + // Fail("BLMPop is still blocked") + // } + //}) + + //It("should BLMPop timeout", func() { + // _, val, err := client.BLMPop(ctx, time.Second, "left", 1, "list1").Result() + // Expect(err).To(Equal(redis.Nil)) + // Expect(val).To(BeNil()) + // + // Expect(client.Ping(ctx).Err()).NotTo(HaveOccurred()) + // + // 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 LLen", func() { + lPush := client.LPush(ctx, "list", "World") + Expect(lPush.Err()).NotTo(HaveOccurred()) + lPush = client.LPush(ctx, "list", "Hello") + Expect(lPush.Err()).NotTo(HaveOccurred()) + + lLen := client.LLen(ctx, "list") + Expect(lLen.Err()).NotTo(HaveOccurred()) + Expect(lLen.Val()).To(Equal(int64(2))) + }) + + // 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 LPopCount", func() { + rPush := client.RPush(ctx, "list11", "one") + Expect(rPush.Err()).NotTo(HaveOccurred()) + rPush = client.RPush(ctx, "list11", "two") + Expect(rPush.Err()).NotTo(HaveOccurred()) + rPush = client.RPush(ctx, "list11", "three") + Expect(rPush.Err()).NotTo(HaveOccurred()) + rPush = client.RPush(ctx, "list11", "four") + Expect(rPush.Err()).NotTo(HaveOccurred()) + + lPopCount := client.LPopCount(ctx, "list11", 2) + Expect(lPopCount.Err()).NotTo(HaveOccurred()) + Expect(lPopCount.Val()).To(Equal([]string{"one", "two"})) + + lRange := client.LRange(ctx, "list11", 0, -1) + Expect(lRange.Err()).NotTo(HaveOccurred()) + 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)) + //}) + + //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})) + //}) + + It("should LPush", func() { + lPush := client.LPush(ctx, "list", "World") + Expect(lPush.Err()).NotTo(HaveOccurred()) + lPush = client.LPush(ctx, "list", "Hello") + Expect(lPush.Err()).NotTo(HaveOccurred()) + + lRange := client.LRange(ctx, "list", 0, -1) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{"Hello", "World"})) + }) + + It("should LPushX", func() { + lPush := client.LPush(ctx, "list", "World") + Expect(lPush.Err()).NotTo(HaveOccurred()) + + lPushX := client.LPushX(ctx, "list", "Hello") + Expect(lPushX.Err()).NotTo(HaveOccurred()) + Expect(lPushX.Val()).To(Equal(int64(2))) + + lPush = client.LPush(ctx, "list1", "three") + Expect(lPush.Err()).NotTo(HaveOccurred()) + Expect(lPush.Val()).To(Equal(int64(1))) + + lPushX = client.LPushX(ctx, "list1", "two", "one") + Expect(lPushX.Err()).NotTo(HaveOccurred()) + Expect(lPushX.Val()).To(Equal(int64(3))) + + lPushX = client.LPushX(ctx, "list2", "Hello") + Expect(lPushX.Err()).NotTo(HaveOccurred()) + Expect(lPushX.Val()).To(Equal(int64(0))) + + lRange := client.LRange(ctx, "list", 0, -1) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{"Hello", "World"})) + + lRange = client.LRange(ctx, "list1", 0, -1) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{"one", "two", "three"})) + + lRange = client.LRange(ctx, "list2", 0, -1) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{})) + }) + + It("should LRange", 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()) + + lRange := client.LRange(ctx, "list", 0, 0) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{"one"})) + + lRange = client.LRange(ctx, "list", -3, 2) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{"one", "two", "three"})) + + lRange = client.LRange(ctx, "list", -100, 100) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{"one", "two", "three"})) + + lRange = client.LRange(ctx, "list", 5, 10) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{})) + }) + + It("should LRem", func() { + rPush := client.RPush(ctx, "list", "hello") + Expect(rPush.Err()).NotTo(HaveOccurred()) + rPush = client.RPush(ctx, "list", "hello") + Expect(rPush.Err()).NotTo(HaveOccurred()) + rPush = client.RPush(ctx, "list", "key") + Expect(rPush.Err()).NotTo(HaveOccurred()) + rPush = client.RPush(ctx, "list", "hello") + Expect(rPush.Err()).NotTo(HaveOccurred()) + + lRem := client.LRem(ctx, "list", -2, "hello") + Expect(lRem.Err()).NotTo(HaveOccurred()) + Expect(lRem.Val()).To(Equal(int64(2))) + + lRange := client.LRange(ctx, "list", 0, -1) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{"hello", "key"})) + }) + + It("should LSet", 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()) + + lSet := client.LSet(ctx, "list", 0, "four") + Expect(lSet.Err()).NotTo(HaveOccurred()) + Expect(lSet.Val()).To(Equal("OK")) + + lSet = client.LSet(ctx, "list", -2, "five") + Expect(lSet.Err()).NotTo(HaveOccurred()) + Expect(lSet.Val()).To(Equal("OK")) + + lRange := client.LRange(ctx, "list", 0, -1) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{"four", "five", "three"})) + }) + + It("should LTrim", 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()) + + lTrim := client.LTrim(ctx, "list", 1, -1) + Expect(lTrim.Err()).NotTo(HaveOccurred()) + Expect(lTrim.Val()).To(Equal("OK")) + + lRange := client.LRange(ctx, "list", 0, -1) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{"two", "three"})) + }) + + // 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 RPopCount", func() { + rPush := client.RPush(ctx, "list", "one", "two", "three", "four") + Expect(rPush.Err()).NotTo(HaveOccurred()) + Expect(rPush.Val()).To(Equal(int64(4))) + + rPopCount := client.RPopCount(ctx, "list", 2) + Expect(rPopCount.Err()).NotTo(HaveOccurred()) + Expect(rPopCount.Val()).To(Equal([]string{"four", "three"})) + + lRange := client.LRange(ctx, "list", 0, -1) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{"one", "two"})) + }) + + It("should RPopLPush", 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()) + + rPopLPush := client.RPopLPush(ctx, "list", "list2") + Expect(rPopLPush.Err()).NotTo(HaveOccurred()) + Expect(rPopLPush.Val()).To(Equal("three")) + + lRange := client.LRange(ctx, "list", 0, -1) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{"one", "two"})) + + lRange = client.LRange(ctx, "list2", 0, -1) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{"three"})) + }) + + It("should RPush", func() { + rPush := client.RPush(ctx, "list", "Hello") + Expect(rPush.Err()).NotTo(HaveOccurred()) + Expect(rPush.Val()).To(Equal(int64(1))) + + rPush = client.RPush(ctx, "list", "World") + Expect(rPush.Err()).NotTo(HaveOccurred()) + Expect(rPush.Val()).To(Equal(int64(2))) + + lRange := client.LRange(ctx, "list", 0, -1) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{"Hello", "World"})) + }) + + It("should RPushX", func() { + rPush := client.RPush(ctx, "list", "Hello") + Expect(rPush.Err()).NotTo(HaveOccurred()) + Expect(rPush.Val()).To(Equal(int64(1))) + + rPushX := client.RPushX(ctx, "list", "World") + Expect(rPushX.Err()).NotTo(HaveOccurred()) + Expect(rPushX.Val()).To(Equal(int64(2))) + + rPush = client.RPush(ctx, "list1", "one") + Expect(rPush.Err()).NotTo(HaveOccurred()) + Expect(rPush.Val()).To(Equal(int64(1))) + + rPushX = client.RPushX(ctx, "list1", "two", "three") + Expect(rPushX.Err()).NotTo(HaveOccurred()) + Expect(rPushX.Val()).To(Equal(int64(3))) + + rPushX = client.RPushX(ctx, "list2", "World") + Expect(rPushX.Err()).NotTo(HaveOccurred()) + Expect(rPushX.Val()).To(Equal(int64(0))) + + lRange := client.LRange(ctx, "list", 0, -1) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{"Hello", "World"})) + + lRange = client.LRange(ctx, "list1", 0, -1) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{"one", "two", "three"})) + + lRange = client.LRange(ctx, "list2", 0, -1) + Expect(lRange.Err()).NotTo(HaveOccurred()) + 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"})) + //}) + + //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"})) + //}) + }) +}) diff --git a/tests/integration/main_test.go b/tests/integration/main_test.go new file mode 100644 index 0000000000..f48bef9637 --- /dev/null +++ b/tests/integration/main_test.go @@ -0,0 +1,14 @@ +package pika_integration + +import ( + "testing" + + . "github.com/bsm/ginkgo/v2" + + . "github.com/bsm/gomega" +) + +func TestPika(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Pika integration test") +} diff --git a/tests/integration/options.go b/tests/integration/options.go new file mode 100644 index 0000000000..3e3320a310 --- /dev/null +++ b/tests/integration/options.go @@ -0,0 +1,42 @@ +package pika_integration + +import ( + "time" + + "github.com/redis/go-redis/v9" +) + +type TimeValue struct { + time.Time +} + +func (t *TimeValue) ScanRedis(s string) (err error) { + t.Time, err = time.Parse(time.RFC3339Nano, s) + return +} + +func pikaOptions1() *redis.Options { + return &redis.Options{ + Addr: "127.0.0.1:9221", + DB: 0, + DialTimeout: 10 * time.Second, + ReadTimeout: 30 * time.Second, + WriteTimeout: 30 * time.Second, + MaxRetries: -1, + PoolSize: 10, + PoolTimeout: 30 * time.Second, + } +} + +func pikaOptions2() *redis.Options { + return &redis.Options{ + Addr: "127.0.0.1:9231", + DB: 0, + DialTimeout: 10 * time.Second, + ReadTimeout: 30 * time.Second, + WriteTimeout: 30 * time.Second, + MaxRetries: -1, + PoolSize: 10, + PoolTimeout: 30 * time.Second, + } +} diff --git a/tests/integration/server_test.go b/tests/integration/server_test.go new file mode 100644 index 0000000000..e2ce6d6df9 --- /dev/null +++ b/tests/integration/server_test.go @@ -0,0 +1,418 @@ +package pika_integration + +import ( + "context" + "time" + + . "github.com/bsm/ginkgo/v2" + . "github.com/bsm/gomega" + "github.com/redis/go-redis/v9" +) + +var _ = Describe("Server", func() { + ctx := context.TODO() + var client *redis.Client + + BeforeEach(func() { + client = redis.NewClient(pikaOptions1()) + Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred()) + }) + + AfterEach(func() { + Expect(client.Close()).NotTo(HaveOccurred()) + }) + + Describe("server", func() { + It("should Auth", func() { + cmds, err := client.Pipelined(ctx, func(pipe redis.Pipeliner) error { + pipe.Auth(ctx, "112121") + pipe.Auth(ctx, "") + 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))) + //}) + + It("should Echo", func() { + pipe := client.Pipeline() + echo := pipe.Echo(ctx, "hello") + _, err := pipe.Exec(ctx) + Expect(err).NotTo(HaveOccurred()) + + Expect(echo.Err()).NotTo(HaveOccurred()) + Expect(echo.Val()).To(Equal("hello")) + }) + + It("should Ping", func() { + ping := client.Ping(ctx) + Expect(ping.Err()).NotTo(HaveOccurred()) + 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) + _, err := pipe.Exec(ctx) + Expect(err).NotTo(HaveOccurred()) + + 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")) + //}) + + It("should BgRewriteAOF", func() { + Skip("flaky test") + + val, err := client.BgRewriteAOF(ctx).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(ContainSubstring("Background append only file rewriting")) + }) + + // 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) + Expect(res.Err()).NotTo(HaveOccurred()) + _ = client.Set(ctx, "bgsava_key2", "bgsava_value3", 0) + Expect(res.Err()).NotTo(HaveOccurred()) + _ = client.HSet(ctx, "bgsava_key3", "bgsava_value", 0) + Expect(res.Err()).NotTo(HaveOccurred()) + + res2, err2 := client.BgSave(ctx).Result() + Expect(err2).NotTo(HaveOccurred()) + Expect(res.Err()).NotTo(HaveOccurred()) + Expect(res2).To(ContainSubstring("Background saving started")) + + res = client.Set(ctx, "bgsava_key", "bgsava_value", 0) + Expect(res.Err()).NotTo(HaveOccurred()) + res = client.Set(ctx, "bgsava_key2", "bgsava_value2", 0) + Expect(res.Err()).NotTo(HaveOccurred()) + res = client.Set(ctx, "bgsava_key3", "bgsava_value3", 0) + Expect(res.Err()).NotTo(HaveOccurred()) + hSet := client.HSet(ctx, "bgsava_key4", "bgsava_value4", 0) + Expect(hSet.Err()).NotTo(HaveOccurred()) + + _, err := client.Del(ctx, "bgsava_key").Result() + Expect(err).NotTo(HaveOccurred()) + + res2, err2 = client.BgSave(ctx).Result() + Expect(err2).NotTo(HaveOccurred()) + Expect(res.Err()).NotTo(HaveOccurred()) + Expect(res2).To(ContainSubstring("Background saving started")) + + val, err := client.Get(ctx, "bgsava_key2").Result() + Expect(res.Err()).NotTo(HaveOccurred()) + Expect(val).To(ContainSubstring("bgsava_value2")) + + _, err = client.Del(ctx, "bgsava_key4").Result() + Expect(err).NotTo(HaveOccurred()) + + get := client.Get(ctx, "bgsava_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)) + //}) + + It("should ClientSetName and ClientGetName", func() { + pipe := client.Pipeline() + set := pipe.ClientSetName(ctx, "theclientname") + get := pipe.ClientGetName(ctx) + _, err := pipe.Exec(ctx) + Expect(err).NotTo(HaveOccurred()) + + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(BeTrue()) + + Expect(get.Err()).NotTo(HaveOccurred()) + Expect(get.Val()).To(Equal("theclientname")) + }) + + It("should ConfigGet", func() { + val, err := client.ConfigGet(ctx, "*").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).NotTo(BeEmpty()) + }) + + It("should ConfigResetStat", func() { + r := client.ConfigResetStat(ctx) + Expect(r.Err()).NotTo(HaveOccurred()) + Expect(r.Val()).To(Equal("OK")) + }) + + It("should ConfigSet", func() { + configGet := client.ConfigGet(ctx, "maxmemory") + Expect(configGet.Err()).NotTo(HaveOccurred()) + Expect(configGet.Val()).To(HaveLen(1)) + _, ok := configGet.Val()["maxmemory"] + Expect(ok).To(BeTrue()) + + //configSet := client.ConfigSet(ctx, "maxmemory", configGet.Val()["maxmemory"]) + //Expect(configSet.Err()).NotTo(HaveOccurred()) + //Expect(configSet.Val()).To(Equal("OK")) + }) + + It("should ConfigRewrite", func() { + configRewrite := client.ConfigRewrite(ctx) + Expect(configRewrite.Err()).NotTo(HaveOccurred()) + Expect(configRewrite.Val()).To(Equal("OK")) + }) + + It("should DBSize", func() { + size, err := client.DBSize(ctx).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(size).To(Equal(int64(0))) + }) + + It("should Info", func() { + info := client.Info(ctx) + Expect(info.Err()).NotTo(HaveOccurred()) + Expect(info.Val()).NotTo(Equal("")) + }) + + It("should Info cpu", func() { + 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 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 Time", func() { + tm, err := client.Time(ctx).Result() + Expect(err).NotTo(HaveOccurred()) + 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")) + //}) + }) +}) diff --git a/tests/integration/set_test.go b/tests/integration/set_test.go new file mode 100644 index 0000000000..82b01412d1 --- /dev/null +++ b/tests/integration/set_test.go @@ -0,0 +1,383 @@ +package pika_integration + +import ( + "context" + + . "github.com/bsm/ginkgo/v2" + . "github.com/bsm/gomega" + "github.com/redis/go-redis/v9" +) + +var _ = Describe("List Commands", func() { + ctx := context.TODO() + var client *redis.Client + + BeforeEach(func() { + client = redis.NewClient(pikaOptions1()) + Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred()) + }) + + AfterEach(func() { + Expect(client.Close()).NotTo(HaveOccurred()) + }) + + Describe("sets", func() { + It("should SAdd", func() { + sAdd := client.SAdd(ctx, "set", "Hello") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + Expect(sAdd.Val()).To(Equal(int64(1))) + + sAdd = client.SAdd(ctx, "set", "World") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + Expect(sAdd.Val()).To(Equal(int64(1))) + + sAdd = client.SAdd(ctx, "set", "World") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + Expect(sAdd.Val()).To(Equal(int64(0))) + + sMembers := client.SMembers(ctx, "set") + Expect(sMembers.Err()).NotTo(HaveOccurred()) + Expect(sMembers.Val()).To(ConsistOf([]string{"Hello", "World"})) + }) + + It("should SAdd strings", func() { + set := []string{"Hello", "World", "World"} + sAdd := client.SAdd(ctx, "set", set) + Expect(sAdd.Err()).NotTo(HaveOccurred()) + Expect(sAdd.Val()).To(Equal(int64(2))) + + sMembers := client.SMembers(ctx, "set") + Expect(sMembers.Err()).NotTo(HaveOccurred()) + Expect(sMembers.Val()).To(ConsistOf([]string{"Hello", "World"})) + }) + + It("should SCard", func() { + sAdd := client.SAdd(ctx, "set", "Hello") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + Expect(sAdd.Val()).To(Equal(int64(1))) + + sAdd = client.SAdd(ctx, "set", "World") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + Expect(sAdd.Val()).To(Equal(int64(1))) + + sCard := client.SCard(ctx, "set") + Expect(sCard.Err()).NotTo(HaveOccurred()) + Expect(sCard.Val()).To(Equal(int64(2))) + }) + + It("should SDiff", func() { + sAdd := client.SAdd(ctx, "set1", "a") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set1", "b") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set1", "c") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sAdd = client.SAdd(ctx, "set2", "c") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set2", "d") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set2", "e") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sDiff := client.SDiff(ctx, "set1", "set2") + Expect(sDiff.Err()).NotTo(HaveOccurred()) + Expect(sDiff.Val()).To(ConsistOf([]string{"a", "b"})) + }) + + It("should SDiffStore", func() { + sAdd := client.SAdd(ctx, "set1", "a") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set1", "b") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set1", "c") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sAdd = client.SAdd(ctx, "set2", "c") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set2", "d") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set2", "e") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sDiffStore := client.SDiffStore(ctx, "set", "set1", "set2") + Expect(sDiffStore.Err()).NotTo(HaveOccurred()) + Expect(sDiffStore.Val()).To(Equal(int64(2))) + + sMembers := client.SMembers(ctx, "set") + Expect(sMembers.Err()).NotTo(HaveOccurred()) + Expect(sMembers.Val()).To(ConsistOf([]string{"a", "b"})) + }) + + It("should SInter", func() { + sAdd := client.SAdd(ctx, "set1", "a") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set1", "b") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set1", "c") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sAdd = client.SAdd(ctx, "set2", "c") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set2", "d") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set2", "e") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sInter := client.SInter(ctx, "set1", "set2") + Expect(sInter.Err()).NotTo(HaveOccurred()) + Expect(sInter.Val()).To(Equal([]string{"c"})) + }) + + //It("should SInterCard", func() { + // sAdd := client.SAdd(ctx, "set1", "a") + // Expect(sAdd.Err()).NotTo(HaveOccurred()) + // sAdd = client.SAdd(ctx, "set1", "b") + // Expect(sAdd.Err()).NotTo(HaveOccurred()) + // sAdd = client.SAdd(ctx, "set1", "c") + // Expect(sAdd.Err()).NotTo(HaveOccurred()) + // + // sAdd = client.SAdd(ctx, "set2", "b") + // Expect(sAdd.Err()).NotTo(HaveOccurred()) + // sAdd = client.SAdd(ctx, "set2", "c") + // Expect(sAdd.Err()).NotTo(HaveOccurred()) + // sAdd = client.SAdd(ctx, "set2", "d") + // Expect(sAdd.Err()).NotTo(HaveOccurred()) + // sAdd = client.SAdd(ctx, "set2", "e") + // Expect(sAdd.Err()).NotTo(HaveOccurred()) + // // limit 0 means no limit,see https://redis.io/commands/sintercard/ for more details + // sInterCard := client.SInterCard(ctx, 0, "set1", "set2") + // Expect(sInterCard.Err()).NotTo(HaveOccurred()) + // Expect(sInterCard.Val()).To(Equal(int64(2))) + // + // sInterCard = client.SInterCard(ctx, 1, "set1", "set2") + // Expect(sInterCard.Err()).NotTo(HaveOccurred()) + // Expect(sInterCard.Val()).To(Equal(int64(1))) + // + // sInterCard = client.SInterCard(ctx, 3, "set1", "set2") + // Expect(sInterCard.Err()).NotTo(HaveOccurred()) + // Expect(sInterCard.Val()).To(Equal(int64(2))) + //}) + + It("should SInterStore", func() { + sAdd := client.SAdd(ctx, "set1", "a") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set1", "b") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set1", "c") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sAdd = client.SAdd(ctx, "set2", "c") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set2", "d") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set2", "e") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sInterStore := client.SInterStore(ctx, "set", "set1", "set2") + Expect(sInterStore.Err()).NotTo(HaveOccurred()) + Expect(sInterStore.Val()).To(Equal(int64(1))) + + sMembers := client.SMembers(ctx, "set") + Expect(sMembers.Err()).NotTo(HaveOccurred()) + Expect(sMembers.Val()).To(Equal([]string{"c"})) + }) + + It("should IsMember", func() { + sAdd := client.SAdd(ctx, "set", "one") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sIsMember := client.SIsMember(ctx, "set", "one") + Expect(sIsMember.Err()).NotTo(HaveOccurred()) + Expect(sIsMember.Val()).To(Equal(true)) + + sIsMember = client.SIsMember(ctx, "set", "two") + Expect(sIsMember.Err()).NotTo(HaveOccurred()) + Expect(sIsMember.Val()).To(Equal(false)) + }) + + //It("should SMIsMember", func() { + // sAdd := client.SAdd(ctx, "set", "one") + // Expect(sAdd.Err()).NotTo(HaveOccurred()) + // + // sMIsMember := client.SMIsMember(ctx, "set", "one", "two") + // Expect(sMIsMember.Err()).NotTo(HaveOccurred()) + // Expect(sMIsMember.Val()).To(Equal([]bool{true, false})) + //}) + + It("should SMembers", func() { + sAdd := client.SAdd(ctx, "set", "Hello") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set", "World") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sMembers := client.SMembers(ctx, "set") + Expect(sMembers.Err()).NotTo(HaveOccurred()) + Expect(sMembers.Val()).To(ConsistOf([]string{"Hello", "World"})) + }) + + It("should SMembersMap", func() { + sAdd := client.SAdd(ctx, "set", "Hello") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set", "World") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sMembersMap := client.SMembersMap(ctx, "set") + Expect(sMembersMap.Err()).NotTo(HaveOccurred()) + Expect(sMembersMap.Val()).To(Equal(map[string]struct{}{"Hello": {}, "World": {}})) + }) + + It("should SMove", func() { + sAdd := client.SAdd(ctx, "set1", "one") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set1", "two") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sAdd = client.SAdd(ctx, "set2", "three") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sMove := client.SMove(ctx, "set1", "set2", "two") + Expect(sMove.Err()).NotTo(HaveOccurred()) + Expect(sMove.Val()).To(Equal(true)) + + sMembers := client.SMembers(ctx, "set1") + Expect(sMembers.Err()).NotTo(HaveOccurred()) + Expect(sMembers.Val()).To(Equal([]string{"one"})) + + sMembers = client.SMembers(ctx, "set2") + Expect(sMembers.Err()).NotTo(HaveOccurred()) + Expect(sMembers.Val()).To(ConsistOf([]string{"three", "two"})) + }) + + It("should SPop", func() { + sAdd := client.SAdd(ctx, "set", "one") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set", "two") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set", "three") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + // 报错:redis: can't parse reply="*1" reading string + //sPop := client.SPop(ctx, "set") + //Expect(sPop.Err()).NotTo(HaveOccurred()) + //Expect(sPop.Val()).NotTo(Equal("")) + + sMembers := client.SMembers(ctx, "set") + Expect(sMembers.Err()).NotTo(HaveOccurred()) + Expect(sMembers.Val()).To(HaveLen(3)) + }) + + It("should SPopN", func() { + sAdd := client.SAdd(ctx, "set", "one") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set", "two") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set", "three") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set", "four") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sPopN := client.SPopN(ctx, "set", 1) + Expect(sPopN.Err()).NotTo(HaveOccurred()) + Expect(sPopN.Val()).NotTo(Equal([]string{""})) + + sMembers := client.SMembers(ctx, "set") + Expect(sMembers.Err()).NotTo(HaveOccurred()) + Expect(sMembers.Val()).To(HaveLen(3)) + + sPopN = client.SPopN(ctx, "set", 4) + Expect(sPopN.Err()).NotTo(HaveOccurred()) + Expect(sPopN.Val()).To(HaveLen(3)) + + sMembers = client.SMembers(ctx, "set") + Expect(sMembers.Err()).NotTo(HaveOccurred()) + Expect(sMembers.Val()).To(HaveLen(0)) + }) + + It("should SRandMember and SRandMemberN", func() { + err := client.SAdd(ctx, "set", "one").Err() + Expect(err).NotTo(HaveOccurred()) + err = client.SAdd(ctx, "set", "two").Err() + Expect(err).NotTo(HaveOccurred()) + err = client.SAdd(ctx, "set", "three").Err() + Expect(err).NotTo(HaveOccurred()) + + members, err := client.SMembers(ctx, "set").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(members).To(HaveLen(3)) + + member, err := client.SRandMember(ctx, "set").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(member).NotTo(Equal("")) + + members, err = client.SRandMemberN(ctx, "set", 2).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(members).To(HaveLen(2)) + }) + + It("should SRem", func() { + sAdd := client.SAdd(ctx, "set", "one") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set", "two") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set", "three") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sRem := client.SRem(ctx, "set", "one") + Expect(sRem.Err()).NotTo(HaveOccurred()) + Expect(sRem.Val()).To(Equal(int64(1))) + + sRem = client.SRem(ctx, "set", "four") + Expect(sRem.Err()).NotTo(HaveOccurred()) + Expect(sRem.Val()).To(Equal(int64(0))) + + sMembers := client.SMembers(ctx, "set") + Expect(sMembers.Err()).NotTo(HaveOccurred()) + Expect(sMembers.Val()).To(ConsistOf([]string{"three", "two"})) + }) + + It("should SUnion", func() { + sAdd := client.SAdd(ctx, "set1", "a") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set1", "b") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set1", "c") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sAdd = client.SAdd(ctx, "set2", "c") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set2", "d") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set2", "e") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sUnion := client.SUnion(ctx, "set1", "set2") + Expect(sUnion.Err()).NotTo(HaveOccurred()) + Expect(sUnion.Val()).To(HaveLen(5)) + }) + + It("should SUnionStore", func() { + sAdd := client.SAdd(ctx, "set1", "a") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set1", "b") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set1", "c") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sAdd = client.SAdd(ctx, "set2", "c") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set2", "d") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set2", "e") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + sUnionStore := client.SUnionStore(ctx, "set", "set1", "set2") + Expect(sUnionStore.Err()).NotTo(HaveOccurred()) + Expect(sUnionStore.Val()).To(Equal(int64(5))) + + sMembers := client.SMembers(ctx, "set") + Expect(sMembers.Err()).NotTo(HaveOccurred()) + Expect(sMembers.Val()).To(HaveLen(5)) + }) + }) +}) diff --git a/tests/integration/slowlog_test.go b/tests/integration/slowlog_test.go new file mode 100644 index 0000000000..5f13606acb --- /dev/null +++ b/tests/integration/slowlog_test.go @@ -0,0 +1,42 @@ +package pika_integration + +import ( + "context" + + . "github.com/bsm/ginkgo/v2" + . "github.com/bsm/gomega" + "github.com/redis/go-redis/v9" +) + +var _ = Describe("Slowlog Commands", func() { + ctx := context.TODO() + var client *redis.Client + + BeforeEach(func() { + client = redis.NewClient(pikaOptions1()) + Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred()) + }) + + AfterEach(func() { + Expect(client.Close()).NotTo(HaveOccurred()) + }) + + Describe("SlowLogGet", func() { + It("returns slow query result", func() { + const key = "slowlog-log-slower-than" + + old := client.ConfigGet(ctx, key).Val() + client.ConfigSet(ctx, key, "0") + defer client.ConfigSet(ctx, key, old[key]) + + err := client.Do(ctx, "slowlog", "reset").Err() + Expect(err).NotTo(HaveOccurred()) + + client.Set(ctx, "test", "true", 0) + + result, err := client.SlowLogGet(ctx, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(len(result)).NotTo(BeZero()) + }) + }) +}) diff --git a/tests/integration/start_master_and_slave.sh b/tests/integration/start_master_and_slave.sh index ed2923d19f..c2b6a01c38 100644 --- a/tests/integration/start_master_and_slave.sh +++ b/tests/integration/start_master_and_slave.sh @@ -9,4 +9,4 @@ sed -i '' -e 's|databases : 1|databases : 2|' -e 's|port : 9221|port : 9231|' -e ./pika -c ./pika_master.conf ./pika -c ./pika_slave.conf #ensure both master and slave are ready -sleep 10 +sleep 10 \ No newline at end of file diff --git a/tests/integration/string_test.go b/tests/integration/string_test.go new file mode 100644 index 0000000000..c8473dc3b9 --- /dev/null +++ b/tests/integration/string_test.go @@ -0,0 +1,943 @@ +package pika_integration + +import ( + "context" + "strconv" + "time" + + . "github.com/bsm/ginkgo/v2" + . "github.com/bsm/gomega" + + "github.com/redis/go-redis/v9" +) + +var _ = Describe("String Commands", func() { + ctx := context.TODO() + var client *redis.Client + + BeforeEach(func() { + client = redis.NewClient(pikaOptions1()) + Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred()) + }) + + AfterEach(func() { + Expect(client.Close()).NotTo(HaveOccurred()) + }) + + 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")) + }) + + 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 Decr", func() { + set := client.Set(ctx, "key", "10", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + decr := client.Decr(ctx, "key") + Expect(decr.Err()).NotTo(HaveOccurred()) + Expect(decr.Val()).To(Equal(int64(9))) + + set = client.Set(ctx, "key", "234293482390480948029348230948", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + //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 DecrBy", func() { + set := client.Set(ctx, "key", "10", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + decrBy := client.DecrBy(ctx, "key", 5) + Expect(decrBy.Err()).NotTo(HaveOccurred()) + Expect(decrBy.Val()).To(Equal(int64(5))) + }) + + It("should Get", func() { + get := client.Get(ctx, "_") + Expect(get.Err()).To(Equal(redis.Nil)) + Expect(get.Val()).To(Equal("")) + + 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")) + }) + + 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))) + }) + + 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")) + + getRange := client.GetRange(ctx, "key", 0, 3) + Expect(getRange.Err()).NotTo(HaveOccurred()) + Expect(getRange.Val()).To(Equal("This")) + + getRange = client.GetRange(ctx, "key", -3, -1) + Expect(getRange.Err()).NotTo(HaveOccurred()) + Expect(getRange.Val()).To(Equal("ing")) + + getRange = client.GetRange(ctx, "key", 0, -1) + Expect(getRange.Err()).NotTo(HaveOccurred()) + Expect(getRange.Val()).To(Equal("This is a string")) + + getRange = client.GetRange(ctx, "key", 10, 100) + Expect(getRange.Err()).NotTo(HaveOccurred()) + Expect(getRange.Val()).To(Equal("string")) + }) + + It("should GetSet", func() { + incr := client.Incr(ctx, "key") + Expect(incr.Err()).NotTo(HaveOccurred()) + Expect(incr.Val()).To(Equal(int64(1))) + + getSet := client.GetSet(ctx, "key", "0") + Expect(getSet.Err()).NotTo(HaveOccurred()) + Expect(getSet.Val()).To(Equal("1")) + + 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")) + }) + + It("should IncrBy", func() { + set := client.Set(ctx, "key", "10", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + incrBy := client.IncrBy(ctx, "key", 5) + Expect(incrBy.Err()).NotTo(HaveOccurred()) + Expect(incrBy.Val()).To(Equal(int64(15))) + }) + + It("should IncrByFloat", func() { + set := client.Set(ctx, "key", "10.50", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + incrByFloat := client.IncrByFloat(ctx, "key", 0.1) + Expect(incrByFloat.Err()).NotTo(HaveOccurred()) + Expect(incrByFloat.Val()).To(Equal(10.6)) + + set = client.Set(ctx, "key", "5.0e3", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + incrByFloat = client.IncrByFloat(ctx, "key", 2.0e2) + Expect(incrByFloat.Err()).NotTo(HaveOccurred()) + Expect(incrByFloat.Val()).To(Equal(float64(5200))) + }) + + It("should IncrByFloatOverflow", func() { + incrByFloat := client.IncrByFloat(ctx, "key", 996945661) + Expect(incrByFloat.Err()).NotTo(HaveOccurred()) + Expect(incrByFloat.Val()).To(Equal(float64(996945661))) + }) + + 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 scan Mget", func() { + now := time.Now() + + err := client.MSet(ctx, "key1", "hello1", "key2", 123, "time", now.Format(time.RFC3339Nano)).Err() + Expect(err).NotTo(HaveOccurred()) + + 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 MSetNX", func() { + mSetNX := client.MSetNX(ctx, "MSetNXkey1", "hello1", "MSetNXkey2", "hello2") + Expect(mSetNX.Err()).NotTo(HaveOccurred()) + Expect(mSetNX.Val()).To(Equal(true)) + + mSetNX = client.MSetNX(ctx, "MSetNXkey1", "hello1", "MSetNXkey2", "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)) + }) + + //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 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("")) + }) + + 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")) + }) + + // 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("")) + }) + + //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 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")) + }) + + //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)) + }) + + 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")) + }) + + 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 SetNX", func() { + _, err := client.Del(ctx, "key").Result() + Expect(err).NotTo(HaveOccurred()) + + setNX := client.SetNX(ctx, "key", "hello", 0) + Expect(setNX.Err()).NotTo(HaveOccurred()) + Expect(setNX.Val()).To(Equal(true)) + + setNX = client.SetNX(ctx, "key", "hello2", 0) + Expect(setNX.Err()).NotTo(HaveOccurred()) + Expect(setNX.Val()).To(Equal(false)) + + get := client.Get(ctx, "key") + Expect(get.Err()).NotTo(HaveOccurred()) + Expect(get.Val()).To(Equal("hello")) + }) + + It("should SetNX with expiration", func() { + _, err := client.Del(ctx, "key").Result() + Expect(err).NotTo(HaveOccurred()) + + isSet, err := client.SetNX(ctx, "key", "hello", time.Second).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(isSet).To(Equal(true)) + + isSet, err = client.SetNX(ctx, "key", "hello2", time.Second).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(isSet).To(Equal(false)) + + val, err := client.Get(ctx, "key").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal("hello")) + }) + + //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() + Expect(err).NotTo(HaveOccurred()) + Expect(isSet).To(Equal(false)) + + err = client.Set(ctx, "key", "hello", 0).Err() + Expect(err).NotTo(HaveOccurred()) + + isSet, err = client.SetXX(ctx, "key", "hello2", 0).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(isSet).To(Equal(true)) + + val, err := client.Get(ctx, "key").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal("hello2")) + }) + + It("should SetXX with expiration", func() { + isSet, err := client.SetXX(ctx, "SetXXkey11111", "hello2", time.Second*1000).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(isSet).To(Equal(false)) + + err = client.Set(ctx, "SetXXkey11111", "hello", time.Second).Err() + Expect(err).NotTo(HaveOccurred()) + + isSet, err = client.SetXX(ctx, "SetXXkey11111", "hello2", time.Second).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(isSet).To(Equal(true)) + + val, err := client.Get(ctx, "SetXXkey11111").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal("hello2")) + }) + + 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)) + + err = client.Set(ctx, "key", "hello", time.Second).Err() + Expect(err).NotTo(HaveOccurred()) + + isSet, err = client.SetXX(ctx, "key", "hello2", 5*time.Second).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(isSet).To(Equal(true)) + + //isSet, err = client.SetXX(ctx, "key", "hello3", redis.KeepTTL).Result() + //Expect(err).NotTo(HaveOccurred()) + //Expect(isSet).To(Equal(true)) + + val, err := client.Get(ctx, "key").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal("hello2")) + + // 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)) + }) + + It("should SetRange", func() { + set := client.Set(ctx, "key", "Hello World", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + range_ := client.SetRange(ctx, "key", 6, "Redis") + Expect(range_.Err()).NotTo(HaveOccurred()) + Expect(range_.Val()).To(Equal(int64(11))) + + get := client.Get(ctx, "key") + Expect(get.Err()).NotTo(HaveOccurred()) + Expect(get.Val()).To(Equal("Hello Redis")) + }) + + It("should StrLen", func() { + set := client.Set(ctx, "key", "hello", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + strLen := client.StrLen(ctx, "key") + Expect(strLen.Err()).NotTo(HaveOccurred()) + Expect(strLen.Val()).To(Equal(int64(5))) + + strLen = client.StrLen(ctx, "_") + Expect(strLen.Err()).NotTo(HaveOccurred()) + Expect(strLen.Val()).To(Equal(int64(0))) + }) + + //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.")) + //}) + + }) +}) diff --git a/tests/integration/aof-race.tcl b/tests/integration/tcl/aof-race.tcl similarity index 100% rename from tests/integration/aof-race.tcl rename to tests/integration/tcl/aof-race.tcl diff --git a/tests/integration/aof.tcl b/tests/integration/tcl/aof.tcl similarity index 100% rename from tests/integration/aof.tcl rename to tests/integration/tcl/aof.tcl diff --git a/tests/integration/convert-zipmap-hash-on-load.tcl b/tests/integration/tcl/convert-zipmap-hash-on-load.tcl similarity index 100% rename from tests/integration/convert-zipmap-hash-on-load.tcl rename to tests/integration/tcl/convert-zipmap-hash-on-load.tcl diff --git a/tests/integration/rdb.tcl b/tests/integration/tcl/rdb.tcl similarity index 100% rename from tests/integration/rdb.tcl rename to tests/integration/tcl/rdb.tcl diff --git a/tests/integration/redis-cli.tcl b/tests/integration/tcl/redis-cli.tcl similarity index 100% rename from tests/integration/redis-cli.tcl rename to tests/integration/tcl/redis-cli.tcl diff --git a/tests/integration/replication-2.tcl b/tests/integration/tcl/replication-2.tcl similarity index 100% rename from tests/integration/replication-2.tcl rename to tests/integration/tcl/replication-2.tcl diff --git a/tests/integration/replication-3.tcl b/tests/integration/tcl/replication-3.tcl similarity index 100% rename from tests/integration/replication-3.tcl rename to tests/integration/tcl/replication-3.tcl diff --git a/tests/integration/replication-4.tcl b/tests/integration/tcl/replication-4.tcl similarity index 100% rename from tests/integration/replication-4.tcl rename to tests/integration/tcl/replication-4.tcl diff --git a/tests/integration/replication-psync.tcl b/tests/integration/tcl/replication-psync.tcl similarity index 100% rename from tests/integration/replication-psync.tcl rename to tests/integration/tcl/replication-psync.tcl diff --git a/tests/integration/replication.tcl b/tests/integration/tcl/replication.tcl similarity index 100% rename from tests/integration/replication.tcl rename to tests/integration/tcl/replication.tcl diff --git a/tests/integration/zset_test.go b/tests/integration/zset_test.go new file mode 100644 index 0000000000..2b9b8fc5f3 --- /dev/null +++ b/tests/integration/zset_test.go @@ -0,0 +1,937 @@ +package pika_integration + +import ( + "context" + "strconv" + "time" + + . "github.com/bsm/ginkgo/v2" + . "github.com/bsm/gomega" + + "github.com/redis/go-redis/v9" +) + +var _ = Describe("Zset Commands", func() { + ctx := context.TODO() + var client *redis.Client + + BeforeEach(func() { + client = redis.NewClient(pikaOptions1()) + Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred()) + }) + + AfterEach(func() { + Expect(client.Close()).NotTo(HaveOccurred()) + }) + + 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")) + }) + + 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 Decr", func() { + set := client.Set(ctx, "key", "10", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + decr := client.Decr(ctx, "key") + Expect(decr.Err()).NotTo(HaveOccurred()) + Expect(decr.Val()).To(Equal(int64(9))) + + set = client.Set(ctx, "key", "234293482390480948029348230948", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + //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 DecrBy", func() { + set := client.Set(ctx, "key", "10", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + decrBy := client.DecrBy(ctx, "key", 5) + Expect(decrBy.Err()).NotTo(HaveOccurred()) + Expect(decrBy.Val()).To(Equal(int64(5))) + }) + + It("should Get", func() { + get := client.Get(ctx, "_") + Expect(get.Err()).To(Equal(redis.Nil)) + Expect(get.Val()).To(Equal("")) + + 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")) + }) + + 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))) + }) + + 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")) + + getRange := client.GetRange(ctx, "key", 0, 3) + Expect(getRange.Err()).NotTo(HaveOccurred()) + Expect(getRange.Val()).To(Equal("This")) + + getRange = client.GetRange(ctx, "key", -3, -1) + Expect(getRange.Err()).NotTo(HaveOccurred()) + Expect(getRange.Val()).To(Equal("ing")) + + getRange = client.GetRange(ctx, "key", 0, -1) + Expect(getRange.Err()).NotTo(HaveOccurred()) + Expect(getRange.Val()).To(Equal("This is a string")) + + getRange = client.GetRange(ctx, "key", 10, 100) + Expect(getRange.Err()).NotTo(HaveOccurred()) + Expect(getRange.Val()).To(Equal("string")) + }) + + It("should GetSet", func() { + incr := client.Incr(ctx, "key") + Expect(incr.Err()).NotTo(HaveOccurred()) + Expect(incr.Val()).To(Equal(int64(1))) + + getSet := client.GetSet(ctx, "key", "0") + Expect(getSet.Err()).NotTo(HaveOccurred()) + Expect(getSet.Val()).To(Equal("1")) + + 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")) + }) + + It("should IncrBy", func() { + set := client.Set(ctx, "key", "10", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + incrBy := client.IncrBy(ctx, "key", 5) + Expect(incrBy.Err()).NotTo(HaveOccurred()) + Expect(incrBy.Val()).To(Equal(int64(15))) + }) + + It("should IncrByFloat", func() { + set := client.Set(ctx, "key", "10.50", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + incrByFloat := client.IncrByFloat(ctx, "key", 0.1) + Expect(incrByFloat.Err()).NotTo(HaveOccurred()) + Expect(incrByFloat.Val()).To(Equal(10.6)) + + set = client.Set(ctx, "key", "5.0e3", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + incrByFloat = client.IncrByFloat(ctx, "key", 2.0e2) + Expect(incrByFloat.Err()).NotTo(HaveOccurred()) + Expect(incrByFloat.Val()).To(Equal(float64(5200))) + }) + + It("should IncrByFloatOverflow", func() { + incrByFloat := client.IncrByFloat(ctx, "key", 996945661) + Expect(incrByFloat.Err()).NotTo(HaveOccurred()) + Expect(incrByFloat.Val()).To(Equal(float64(996945661))) + }) + + 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 scan Mget", func() { + now := time.Now() + + err := client.MSet(ctx, "key1", "hello1", "key2", 123, "time", now.Format(time.RFC3339Nano)).Err() + Expect(err).NotTo(HaveOccurred()) + + 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 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)) + }) + + //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 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("")) + }) + + 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")) + }) + + // 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("")) + }) + + //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 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")) + }) + + //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)) + }) + + 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")) + }) + + 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 SetNX", func() { + setNX := client.SetNX(ctx, "key", "hello", 0) + Expect(setNX.Err()).NotTo(HaveOccurred()) + Expect(setNX.Val()).To(Equal(true)) + + setNX = client.SetNX(ctx, "key", "hello2", 0) + Expect(setNX.Err()).NotTo(HaveOccurred()) + Expect(setNX.Val()).To(Equal(false)) + + get := client.Get(ctx, "key") + Expect(get.Err()).NotTo(HaveOccurred()) + Expect(get.Val()).To(Equal("hello")) + }) + + 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)) + + isSet, err = client.SetNX(ctx, "key", "hello2", time.Second).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(isSet).To(Equal(false)) + + val, err := client.Get(ctx, "key").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal("hello")) + }) + + //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() + Expect(err).NotTo(HaveOccurred()) + Expect(isSet).To(Equal(false)) + + err = client.Set(ctx, "key", "hello", 0).Err() + Expect(err).NotTo(HaveOccurred()) + + isSet, err = client.SetXX(ctx, "key", "hello2", 0).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(isSet).To(Equal(true)) + + val, err := client.Get(ctx, "key").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal("hello2")) + }) + + 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)) + + err = client.Set(ctx, "key", "hello", time.Second).Err() + Expect(err).NotTo(HaveOccurred()) + + isSet, err = client.SetXX(ctx, "key", "hello2", time.Second).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(isSet).To(Equal(true)) + + val, err := client.Get(ctx, "key").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal("hello2")) + }) + + 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)) + + err = client.Set(ctx, "key", "hello", time.Second).Err() + Expect(err).NotTo(HaveOccurred()) + + isSet, err = client.SetXX(ctx, "key", "hello2", 5*time.Second).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(isSet).To(Equal(true)) + + //isSet, err = client.SetXX(ctx, "key", "hello3", redis.KeepTTL).Result() + //Expect(err).NotTo(HaveOccurred()) + //Expect(isSet).To(Equal(true)) + + val, err := client.Get(ctx, "key").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal("hello2")) + + // 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)) + }) + + It("should SetRange", func() { + set := client.Set(ctx, "key", "Hello World", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + range_ := client.SetRange(ctx, "key", 6, "Redis") + Expect(range_.Err()).NotTo(HaveOccurred()) + Expect(range_.Val()).To(Equal(int64(11))) + + get := client.Get(ctx, "key") + Expect(get.Err()).NotTo(HaveOccurred()) + Expect(get.Val()).To(Equal("Hello Redis")) + }) + + It("should StrLen", func() { + set := client.Set(ctx, "key", "hello", 0) + Expect(set.Err()).NotTo(HaveOccurred()) + Expect(set.Val()).To(Equal("OK")) + + strLen := client.StrLen(ctx, "key") + Expect(strLen.Err()).NotTo(HaveOccurred()) + Expect(strLen.Val()).To(Equal(int64(5))) + + strLen = client.StrLen(ctx, "_") + Expect(strLen.Err()).NotTo(HaveOccurred()) + Expect(strLen.Val()).To(Equal(int64(0))) + }) + + //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.")) + //}) + + }) +})