diff --git a/tests/integration/network_stability_test.go b/tests/integration/network_stability_test.go new file mode 100644 index 0000000000..0d9731c44c --- /dev/null +++ b/tests/integration/network_stability_test.go @@ -0,0 +1,57 @@ +package pika_integration + +import ( + "net" + . "github.com/bsm/ginkgo/v2" + . "github.com/bsm/gomega" +) + +var _ = Describe("Telnet", func() { + Describe("core dump fix", func() { + It("should handle empty commands without crashing (telnet core dump fix)", func() { + conn, err := net.Dial("tcp", SINGLEADDR) + Expect(err).NotTo(HaveOccurred()) + defer conn.Close() + + _, err = conn.Write([]byte("\n")) + Expect(err).NotTo(HaveOccurred()) + + _, err = conn.Write([]byte("*1\r\n$4\r\nPING\r\n")) + Expect(err).NotTo(HaveOccurred()) + + buf := make([]byte, 1024) + n, err := conn.Read(buf) + Expect(err).NotTo(HaveOccurred()) + response := string(buf[:n]) + Expect(response).To(ContainSubstring("+PONG")) + + _, err = conn.Write([]byte("*2\r\n$4\r\nECHO\r\n$4\r\nTEST\r\n")) + Expect(err).NotTo(HaveOccurred()) + + n, err = conn.Read(buf) + Expect(err).NotTo(HaveOccurred()) + response = string(buf[:n]) + Expect(response).To(ContainSubstring("$4\r\nTEST")) + }) + + It("should handle multiple empty commands without crashing", func() { + conn, err := net.Dial("tcp", SINGLEADDR) + Expect(err).NotTo(HaveOccurred()) + defer conn.Close() + + for i := 0; i < 5; i++ { + _, err = conn.Write([]byte("\r\n")) + Expect(err).NotTo(HaveOccurred()) + } + + _, err = conn.Write([]byte("*1\r\n$4\r\nPING\r\n")) + Expect(err).NotTo(HaveOccurred()) + + buf := make([]byte, 1024) + n, err := conn.Read(buf) + Expect(err).NotTo(HaveOccurred()) + response := string(buf[:n]) + Expect(response).To(ContainSubstring("+PONG")) + }) + }) +}) \ No newline at end of file diff --git a/tests/integration/server_test.go b/tests/integration/server_test.go index 141592f9fe..580ba9b6fb 100644 --- a/tests/integration/server_test.go +++ b/tests/integration/server_test.go @@ -418,6 +418,31 @@ var _ = Describe("Server", func() { Expect(configRewrite.Err()).NotTo(HaveOccurred()) Expect(configRewrite.Val()).To(Equal("OK")) }) + + // Test for cache-value-item-max-size & max-key-size-in-cache + It("should handle cache size configurations correctly", func() { + configGet := client.ConfigGet(ctx, "cache-value-item-max-size") + Expect(configGet.Err()).NotTo(HaveOccurred()) + Expect(configGet.Val()).To(HaveKey("cache-value-item-max-size")) + + configGet2 := client.ConfigGet(ctx, "max-key-size-in-cache") + Expect(configGet2.Err()).NotTo(HaveOccurred()) + Expect(configGet2.Val()).To(HaveKey("max-key-size-in-cache")) + + configSet1 := client.ConfigSet(ctx, "cache-value-item-max-size", "1024") + Expect(configSet1.Err()).NotTo(HaveOccurred()) + Expect(configSet1.Val()).To(Equal("OK")) + + configSet2 := client.ConfigSet(ctx, "max-key-size-in-cache", "1048576") + Expect(configSet2.Err()).NotTo(HaveOccurred()) + Expect(configSet2.Val()).To(Equal("OK")) + + configGet3 := client.ConfigGet(ctx, "cache-value-item-max-size") + Expect(configGet3.Val()["cache-value-item-max-size"]).To(Equal("1024")) + + configGet4 := client.ConfigGet(ctx, "max-key-size-in-cache") + Expect(configGet4.Val()["max-key-size-in-cache"]).To(Equal("1048576")) + }) //It("should DBSize", func() { // Expect(client.Set(ctx, "key", "value", 0).Val()).To(Equal("OK")) // Expect(client.Do(ctx, "info", "keyspace", "1").Err()).NotTo(HaveOccurred()) @@ -739,5 +764,27 @@ var _ = Describe("Server", func() { Expect(client.Get(ctx, "foo").Err()).To(MatchError(redis.Nil)) Expect(client.Get(ctx, "key1").Err()).To(MatchError(redis.Nil)) }) + + //fix: added the correct loading of admin-cmd-list in the configuration file + It("should load admin-cmd-list from config correctly", func() { + configGet := client.ConfigGet(ctx, "admin-cmd-list") + Expect(configGet.Err()).NotTo(HaveOccurred()) + Expect(configGet.Val()).To(HaveLen(1)) + + adminCmdList, ok := configGet.Val()["admin-cmd-list"] + Expect(ok).To(BeTrue()) + + Expect(adminCmdList).To(ContainSubstring("auth")) + Expect(adminCmdList).To(ContainSubstring("config")) + Expect(adminCmdList).To(ContainSubstring("info")) + Expect(adminCmdList).To(ContainSubstring("ping")) + Expect(adminCmdList).To(ContainSubstring("monitor")) + }) + + // fix add auth command to admin-thread-pool + It("should process auth command in admin thread pool", func() { + auth := client.Do(ctx, "auth", "wrongpassword") + Expect(auth.Err()).To(HaveOccurred()) + }) }) }) diff --git a/tests/integration/set_test.go b/tests/integration/set_test.go index 70287a2f58..5ac48cff88 100644 --- a/tests/integration/set_test.go +++ b/tests/integration/set_test.go @@ -270,14 +270,26 @@ var _ = Describe("Set Commands", func() { 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("")) + 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)) + Expect(sMembers.Val()).To(HaveLen(2)) + + // 再添加一个元素进行批量弹出测试 + sAdd = client.SAdd(ctx, "set2", "one") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set2", "two") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + sAdd = client.SAdd(ctx, "set2", "three") + Expect(sAdd.Err()).NotTo(HaveOccurred()) + + // 测试多个元素弹出,应该返回数组 + sPopN := client.SPopN(ctx, "set2", 2) + Expect(sPopN.Err()).NotTo(HaveOccurred()) + Expect(sPopN.Val()).To(HaveLen(2)) err := client.Do(ctx, "SPOP", "set", 1, 2).Err() Expect(err).To(MatchError(ContainSubstring("ERR wrong number of arguments for 'spop' command"))) diff --git a/tests/unit/type/set.tcl b/tests/unit/type/set.tcl index 957082d95d..01039fb269 100644 --- a/tests/unit/type/set.tcl +++ b/tests/unit/type/set.tcl @@ -310,6 +310,31 @@ start_server { } } + test {SPOP response format for PHP Redis client compatibility} { + r del myset + r sadd myset "element1" "element2" "element3" + set single_pop [r spop myset] + assert {[lsearch {"element1" "element2" "element3"} $single_pop] >= 0} + + r del myset + r sadd myset "element1" "element2" "element3" + set single_array_pop [r spop myset 1] + assert_equal 1 [llength $single_array_pop] + assert {[lsearch {"element1" "element2" "element3"} [lindex $single_array_pop 0]] >= 0} + + r del myset + r sadd myset "element1" "element2" "element3" + set multi_pop [r spop myset 2] + assert_equal 2 [llength $multi_pop] + + r del emptyset + set empty_pop [r spop emptyset] + assert_equal {} $empty_pop + + set empty_array_pop [r spop emptyset 1] + assert_equal 0 [llength $empty_array_pop] + } + test "SRANDMEMBER with against non existing key" { r srandmember nonexisting_key 100 } {}