You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kvrocks.apache.org by ti...@apache.org on 2022/10/08 05:59:59 UTC

[incubator-kvrocks] branch unstable updated: Move TCL test integration/rsid_psync to Go case (#959)

This is an automated email from the ASF dual-hosted git repository.

tison pushed a commit to branch unstable
in repository https://gitbox.apache.org/repos/asf/incubator-kvrocks.git


The following commit(s) were added to refs/heads/unstable by this push:
     new a8e06c7  Move TCL test integration/rsid_psync to Go case  (#959)
a8e06c7 is described below

commit a8e06c7e373f374e1528861fb96942ebbbb63b2f
Author: tison <wa...@gmail.com>
AuthorDate: Sat Oct 8 13:59:53 2022 +0800

    Move TCL test integration/rsid_psync to Go case  (#959)
    
    Signed-off-by: tison <wa...@gmail.com>
---
 kvrocks.conf                                       |   4 +-
 tests/gocase/integration/rsid/rsid_test.go         | 146 +++++++++++++++++++++
 tests/gocase/unit/info/info_test.go                |  24 ++--
 .../unit/introspection/introspection_test.go       |  16 +--
 tests/gocase/unit/multi/multi_test.go              |   6 +-
 tests/gocase/unit/scripting/scripting_test.go      |   2 +-
 tests/gocase/util/client.go                        |  16 ++-
 tests/gocase/util/server.go                        |  61 ++++++++-
 tests/tcl/tests/integration/rsid_psync.tcl         | 122 -----------------
 tests/tcl/tests/test_helper.tcl                    |   1 -
 10 files changed, 237 insertions(+), 161 deletions(-)

diff --git a/kvrocks.conf b/kvrocks.conf
index 2ef247b..1e3615d 100644
--- a/kvrocks.conf
+++ b/kvrocks.conf
@@ -1,7 +1,7 @@
 ################################ GENERAL #####################################
 
 # By default kvrocks listens for connections from localhost interface.
-# It is possible to listen to just one or multiple interfaces using 
+# It is possible to listen to just one or multiple interfaces using
 # the "bind" configuration directive, followed by one or more IP addresses.
 #
 # Examples:
@@ -745,7 +745,7 @@ rocksdb.write_options.low_pri no
 
 # If enabled, this writebatch will maintain the last insert positions of each
 # memtable as hints in concurrent write. It can improve write performance
-# in concurrent writes if keys in one writebatch are sequential. 
+# in concurrent writes if keys in one writebatch are sequential.
 #
 # Default: no
 rocksdb.write_options.memtable_insert_hint_per_batch no
diff --git a/tests/gocase/integration/rsid/rsid_test.go b/tests/gocase/integration/rsid/rsid_test.go
new file mode 100644
index 0000000..f6ad354
--- /dev/null
+++ b/tests/gocase/integration/rsid/rsid_test.go
@@ -0,0 +1,146 @@
+/*
+ * 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.
+ */
+
+package rsid
+
+import (
+	"context"
+	"testing"
+	"time"
+
+	"github.com/apache/incubator-kvrocks/tests/gocase/util"
+	"github.com/stretchr/testify/require"
+)
+
+func TestRSIDMasterAndReplicaYes(t *testing.T) {
+	ctx := context.Background()
+
+	srvA := util.StartServer(t, map[string]string{"use-rsid-psync": "yes"})
+	defer func() { srvA.Close() }()
+	rdbA := srvA.NewClient()
+	defer func() { require.NoError(t, rdbA.Close()) }()
+	require.NoError(t, rdbA.Set(ctx, "a", "b", 0).Err())
+
+	srvB := util.StartServer(t, map[string]string{"use-rsid-psync": "yes"})
+	defer func() { srvB.Close() }()
+	rdbB := srvB.NewClient()
+	defer func() { require.NoError(t, rdbB.Close()) }()
+	require.NoError(t, rdbB.Set(ctx, "c", "d", 0).Err())
+
+	t.Run("replica psync sequence is in the range the master wal but full sync", func(t *testing.T) {
+		require.Equal(t, util.FindInfoEntry(rdbA, "master_repl_offset"), util.FindInfoEntry(rdbB, "master_repl_offset"))
+		util.SlaveOf(t, rdbA, srvB)
+		util.WaitForSync(t, rdbA)
+		require.Equal(t, "1", util.FindInfoEntry(rdbB, "sync_full"))
+		require.Equal(t, "1", util.FindInfoEntry(rdbB, "sync_partial_ok"))
+	})
+
+	// A -->->-- B
+	// C -->->-- B
+	srvC := util.StartServer(t, map[string]string{"use-rsid-psync": "yes"})
+	defer func() { srvC.Close() }()
+	rdbC := srvC.NewClient()
+	defer func() { require.NoError(t, rdbC.Close()) }()
+	util.SlaveOf(t, rdbC, srvB)
+	util.WaitForSync(t, rdbC)
+
+	t.Run("chained replication can partially re-sync", func(t *testing.T) {
+		// C never sync with any slave
+		require.Equal(t, "0", util.FindInfoEntry(rdbC, "sync_partial_ok"))
+
+		// A -->>-- C, currently topology is A -->>-- C -->>-- B
+		util.SlaveOf(t, rdbA, srvC)
+		util.WaitForSync(t, rdbA)
+
+		require.Equal(t, "0", util.FindInfoEntry(rdbC, "sync_full"))
+		require.Equal(t, "1", util.FindInfoEntry(rdbC, "sync_partial_ok"))
+	})
+
+	t.Run("chained replication can propagate updates", func(t *testing.T) {
+		require.NoError(t, rdbB.Set(ctx, "master", "B", 0).Err())
+		util.WaitForOffsetSync(t, rdbB, rdbA)
+		require.Equal(t, "B", rdbA.Get(ctx, "master").Val())
+	})
+
+	t.Run("replica can partially re-sync after changing master but having the same history", func(t *testing.T) {
+		require.NoError(t, rdbA.SlaveOf(ctx, "127.0.0.1", "1025").Err())
+		time.Sleep(time.Second)
+
+		// now topology is:
+		// A -->->-- B
+		// C -->->-- B
+		util.SlaveOf(t, rdbA, srvB)
+		util.WaitForSync(t, rdbA)
+
+		// only partial sync, no full sync
+		require.Equal(t, "2", util.FindInfoEntry(rdbB, "sync_full"))
+		require.Equal(t, "3", util.FindInfoEntry(rdbB, "sync_partial_ok"))
+	})
+
+	t.Run("replica can partially re-sync again after restarting", func(t *testing.T) {
+		require.NoError(t, rdbC.ConfigRewrite(ctx).Err())
+
+		srvC.Restart()
+		rdbC := srvC.NewClient()
+		defer func() { require.NoError(t, rdbC.Close()) }()
+		util.WaitForSync(t, rdbC)
+
+		// do not increase sync_full, but increase sync_partial_ok
+		require.Equal(t, "2", util.FindInfoEntry(rdbB, "sync_full"))
+		require.Equal(t, "4", util.FindInfoEntry(rdbB, "sync_partial_ok"))
+	})
+}
+
+func TestRSIDMasterNoAndReplicaYes(t *testing.T) {
+	replica := util.StartServer(t, map[string]string{"use-rsid-psync": "yes"})
+	defer func() { replica.Close() }()
+	replicaClient := replica.NewClient()
+	defer func() { require.NoError(t, replicaClient.Close()) }()
+
+	srv := util.StartServer(t, map[string]string{"use-rsid-psync": "no"})
+	defer func() { srv.Close() }()
+	rdb := srv.NewClient()
+	defer func() { require.NoError(t, rdb.Close()) }()
+
+	t.Run("Replica (use-rsid-psync yes) can slaveof the master (use-rsid-psync no)", func(t *testing.T) {
+		util.SlaveOf(t, replicaClient, srv)
+		util.WaitForSync(t, replicaClient)
+		require.Equal(t, "1", util.FindInfoEntry(rdb, "sync_full"))
+		require.Equal(t, "1", util.FindInfoEntry(rdb, "sync_partial_ok"))
+	})
+}
+
+func TestRSIDMasterYesAndReplicaNo(t *testing.T) {
+	replica := util.StartServer(t, map[string]string{"use-rsid-psync": "no"})
+	defer func() { replica.Close() }()
+	replicaClient := replica.NewClient()
+	defer func() { require.NoError(t, replicaClient.Close()) }()
+
+	srv := util.StartServer(t, map[string]string{"use-rsid-psync": "yes"})
+	defer func() { srv.Close() }()
+	rdb := srv.NewClient()
+	defer func() { require.NoError(t, rdb.Close()) }()
+
+	t.Run("Replica (use-rsid-psync no) can slaveof the master (use-rsid-psync yes)", func(t *testing.T) {
+		util.SlaveOf(t, replicaClient, srv)
+		util.WaitForSync(t, replicaClient)
+		require.Equal(t, "0", util.FindInfoEntry(rdb, "sync_full"))
+		require.Equal(t, "1", util.FindInfoEntry(rdb, "sync_partial_ok"))
+	})
+}
diff --git a/tests/gocase/unit/info/info_test.go b/tests/gocase/unit/info/info_test.go
index f6aa1b6..1cb2365 100644
--- a/tests/gocase/unit/info/info_test.go
+++ b/tests/gocase/unit/info/info_test.go
@@ -55,21 +55,21 @@ func TestInfo(t *testing.T) {
 			time.Sleep(time.Second)
 		}
 
-		r := util.FindInfoEntry(t, rdb, "put_per_sec", "rocksdb")
+		r := util.FindInfoEntry(rdb, "put_per_sec", "rocksdb")
 		require.Greater(t, MustAtoi(t, r), 0)
-		r = util.FindInfoEntry(t, rdb, "get_per_sec", "rocksdb")
+		r = util.FindInfoEntry(rdb, "get_per_sec", "rocksdb")
 		require.Greater(t, MustAtoi(t, r), 0)
-		r = util.FindInfoEntry(t, rdb, "seek_per_sec", "rocksdb")
+		r = util.FindInfoEntry(rdb, "seek_per_sec", "rocksdb")
 		require.Greater(t, MustAtoi(t, r), 0)
-		r = util.FindInfoEntry(t, rdb, "next_per_sec", "rocksdb")
+		r = util.FindInfoEntry(rdb, "next_per_sec", "rocksdb")
 		require.Greater(t, MustAtoi(t, r), 0)
 	})
 
 	t.Run("get bgsave information by INFO", func(t *testing.T) {
-		require.Equal(t, "0", util.FindInfoEntry(t, rdb, "bgsave_in_progress", "persistence"))
-		require.Equal(t, "-1", util.FindInfoEntry(t, rdb, "last_bgsave_time", "persistence"))
-		require.Equal(t, "ok", util.FindInfoEntry(t, rdb, "last_bgsave_status", "persistence"))
-		require.Equal(t, "-1", util.FindInfoEntry(t, rdb, "last_bgsave_time_sec", "persistence"))
+		require.Equal(t, "0", util.FindInfoEntry(rdb, "bgsave_in_progress", "persistence"))
+		require.Equal(t, "-1", util.FindInfoEntry(rdb, "last_bgsave_time", "persistence"))
+		require.Equal(t, "ok", util.FindInfoEntry(rdb, "last_bgsave_status", "persistence"))
+		require.Equal(t, "-1", util.FindInfoEntry(rdb, "last_bgsave_time_sec", "persistence"))
 
 		r := rdb.Do(ctx, "bgsave")
 		v, err := r.Text()
@@ -77,14 +77,14 @@ func TestInfo(t *testing.T) {
 		require.Equal(t, "OK", v)
 
 		require.Eventually(t, func() bool {
-			e := MustAtoi(t, util.FindInfoEntry(t, rdb, "bgsave_in_progress", "persistence"))
+			e := MustAtoi(t, util.FindInfoEntry(rdb, "bgsave_in_progress", "persistence"))
 			return e == 0
 		}, 5*time.Second, 100*time.Millisecond)
 
-		lastBgsaveTime := MustAtoi(t, util.FindInfoEntry(t, rdb, "last_bgsave_time", "persistence"))
+		lastBgsaveTime := MustAtoi(t, util.FindInfoEntry(rdb, "last_bgsave_time", "persistence"))
 		require.Greater(t, lastBgsaveTime, 1640507660)
-		require.Equal(t, "ok", util.FindInfoEntry(t, rdb, "last_bgsave_status", "persistence"))
-		lastBgsaveTimeSec := MustAtoi(t, util.FindInfoEntry(t, rdb, "last_bgsave_time_sec", "persistence"))
+		require.Equal(t, "ok", util.FindInfoEntry(rdb, "last_bgsave_status", "persistence"))
+		lastBgsaveTimeSec := MustAtoi(t, util.FindInfoEntry(rdb, "last_bgsave_time_sec", "persistence"))
 		require.GreaterOrEqual(t, lastBgsaveTimeSec, 0)
 		require.Less(t, lastBgsaveTimeSec, 3)
 	})
diff --git a/tests/gocase/unit/introspection/introspection_test.go b/tests/gocase/unit/introspection/introspection_test.go
index f48bf54..ee406b8 100644
--- a/tests/gocase/unit/introspection/introspection_test.go
+++ b/tests/gocase/unit/introspection/introspection_test.go
@@ -172,7 +172,7 @@ func TestIntrospection(t *testing.T) {
 		// use TCPClient to avoid waiting for reply
 		c := srv.NewTCPClient()
 		defer func() { require.NoError(t, c.Close()) }()
-		require.NoError(t, c.WriteArgs("DEBUG", "sleep", "2.2"))
+		require.NoError(t, c.WriteArgs("DEBUG", "sleep", "2.5"))
 
 		// sleep 100ms to prevent the successive set command to be executed
 		// before the debug command since there are in the different connection.
@@ -197,11 +197,11 @@ func TestMultiServerIntrospection(t *testing.T) {
 
 	ctx := context.Background()
 
-	require.NoError(t, slaveClient.SlaveOf(ctx, master.Host(), fmt.Sprintf("%d", master.Port())).Err())
+	util.SlaveOf(t, slaveClient, master)
 	util.WaitForSync(t, slaveClient)
 
 	t.Run("Kill slave client", func(t *testing.T) {
-		count, err := strconv.Atoi(util.FindInfoEntry(t, masterClient, "sync_partial_ok"))
+		count, err := strconv.Atoi(util.FindInfoEntry(masterClient, "sync_partial_ok"))
 		require.NoError(t, err)
 
 		// kill slave connection
@@ -209,14 +209,14 @@ func TestMultiServerIntrospection(t *testing.T) {
 
 		// incr sync_partial_ok since slave reconnects
 		require.Eventually(t, func() bool {
-			newCount, err := strconv.Atoi(util.FindInfoEntry(t, masterClient, "sync_partial_ok"))
+			newCount, err := strconv.Atoi(util.FindInfoEntry(masterClient, "sync_partial_ok"))
 			require.NoError(t, err)
 			return newCount == count+1
 		}, 5*time.Second, 100*time.Millisecond)
 	})
 
 	t.Run("Kill master client", func(t *testing.T) {
-		count, err := strconv.Atoi(util.FindInfoEntry(t, masterClient, "sync_partial_ok"))
+		count, err := strconv.Atoi(util.FindInfoEntry(masterClient, "sync_partial_ok"))
 		require.NoError(t, err)
 
 		// kill master connection by type
@@ -224,12 +224,12 @@ func TestMultiServerIntrospection(t *testing.T) {
 
 		// incr sync_partial_ok since slave reconnects
 		require.Eventually(t, func() bool {
-			newCount, err := strconv.Atoi(util.FindInfoEntry(t, masterClient, "sync_partial_ok"))
+			newCount, err := strconv.Atoi(util.FindInfoEntry(masterClient, "sync_partial_ok"))
 			require.NoError(t, err)
 			return newCount == count+1
 		}, 5*time.Second, 100*time.Millisecond)
 
-		count, err = strconv.Atoi(util.FindInfoEntry(t, masterClient, "sync_partial_ok"))
+		count, err = strconv.Atoi(util.FindInfoEntry(masterClient, "sync_partial_ok"))
 		require.NoError(t, err)
 
 		// kill master connection by addr
@@ -237,7 +237,7 @@ func TestMultiServerIntrospection(t *testing.T) {
 
 		// incr sync_partial_ok since slave reconnects
 		require.Eventually(t, func() bool {
-			newCount, err := strconv.Atoi(util.FindInfoEntry(t, masterClient, "sync_partial_ok"))
+			newCount, err := strconv.Atoi(util.FindInfoEntry(masterClient, "sync_partial_ok"))
 			require.NoError(t, err)
 			return newCount == count+1
 		}, 5*time.Second, 100*time.Millisecond)
diff --git a/tests/gocase/unit/multi/multi_test.go b/tests/gocase/unit/multi/multi_test.go
index e4efc33..83ae59d 100644
--- a/tests/gocase/unit/multi/multi_test.go
+++ b/tests/gocase/unit/multi/multi_test.go
@@ -132,12 +132,12 @@ func TestMulti(t *testing.T) {
 				rdb := newSrv.NewClient()
 				defer func() { require.NoError(t, rdb.Close()) }()
 				require.NoError(t, rdb.Do(ctx, "MULTI").Err())
-				require.NoError(t, rdb.SlaveOf(ctx, srv.Host(), fmt.Sprintf("%d", srv.Port())).Err())
+				util.SlaveOf(t, rdb, srv)
 				require.NoError(t, rdb.ConfigRewrite(ctx).Err())
 				require.NoError(t, rdb.Do(ctx, "CLIENT", "KILL", "TYPE", "normal").Err())
 				require.NoError(t, rdb.Do(ctx, "CLIENT", "KILL", "TYPE", "PUBSUB").Err())
 				require.NoError(t, rdb.Do(ctx, "EXEC").Err())
-				require.Equal(t, "slave", util.FindInfoEntry(t, rdb, "role"))
+				require.Equal(t, "slave", util.FindInfoEntry(rdb, "role"))
 			}
 
 			{
@@ -149,7 +149,7 @@ func TestMulti(t *testing.T) {
 				require.NoError(t, rdb.Do(ctx, "CLIENT", "KILL", "TYPE", "normal").Err())
 				require.NoError(t, rdb.Do(ctx, "CLIENT", "KILL", "TYPE", "PUBSUB").Err())
 				require.NoError(t, rdb.Do(ctx, "EXEC").Err())
-				require.Equal(t, "master", util.FindInfoEntry(t, rdb, "role"))
+				require.Equal(t, "master", util.FindInfoEntry(rdb, "role"))
 			}
 		})
 	}()
diff --git a/tests/gocase/unit/scripting/scripting_test.go b/tests/gocase/unit/scripting/scripting_test.go
index 70593c6..3c1b2a0 100644
--- a/tests/gocase/unit/scripting/scripting_test.go
+++ b/tests/gocase/unit/scripting/scripting_test.go
@@ -488,7 +488,7 @@ func TestScriptingMasterSlave(t *testing.T) {
 
 	ctx := context.Background()
 
-	require.NoError(t, slaveClient.SlaveOf(ctx, master.Host(), fmt.Sprintf("%d", master.Port())).Err())
+	util.SlaveOf(t, slaveClient, master)
 	util.WaitForSync(t, slaveClient)
 
 	t.Run("SCRIPTING: script load on master, read on slave", func(t *testing.T) {
diff --git a/tests/gocase/util/client.go b/tests/gocase/util/client.go
index d999c11..1bc8d86 100644
--- a/tests/gocase/util/client.go
+++ b/tests/gocase/util/client.go
@@ -31,29 +31,35 @@ import (
 	"github.com/stretchr/testify/require"
 )
 
-func FindInfoEntry(t testing.TB, rdb *redis.Client, key string, section ...string) string {
+func FindInfoEntry(rdb *redis.Client, key string, section ...string) string {
 	r := rdb.Info(context.Background(), section...)
 	p := regexp.MustCompile(fmt.Sprintf("%s:(.+)", key))
 	ms := p.FindStringSubmatch(r.Val())
-	require.Len(t, ms, 2)
+	if len(ms) != 2 {
+		return ""
+	}
 	return strings.TrimSpace(ms[1])
 }
 
 func WaitForSync(t testing.TB, slave *redis.Client) {
 	require.Eventually(t, func() bool {
-		r := FindInfoEntry(t, slave, "master_link_status")
+		r := FindInfoEntry(slave, "master_link_status")
 		return r == "up"
 	}, 5*time.Second, 100*time.Millisecond)
 }
 
 func WaitForOffsetSync(t testing.TB, master, slave *redis.Client) {
 	require.Eventually(t, func() bool {
-		o1 := FindInfoEntry(t, master, "master_repl_offset")
-		o2 := FindInfoEntry(t, slave, "master_repl_offset")
+		o1 := FindInfoEntry(master, "master_repl_offset")
+		o2 := FindInfoEntry(slave, "master_repl_offset")
 		return o1 == o2
 	}, 5*time.Second, 100*time.Millisecond)
 }
 
+func SlaveOf(t testing.TB, slave *redis.Client, master *KvrocksServer) {
+	require.NoError(t, slave.SlaveOf(context.Background(), master.Host(), fmt.Sprintf("%d", master.Port())).Err())
+}
+
 func Populate(t testing.TB, rdb *redis.Client, prefix string, n, size int) {
 	ctx := context.Background()
 	p := rdb.Pipeline()
diff --git a/tests/gocase/util/server.go b/tests/gocase/util/server.go
index 35459db..a7f8bd7 100644
--- a/tests/gocase/util/server.go
+++ b/tests/gocase/util/server.go
@@ -44,7 +44,9 @@ type KvrocksServer struct {
 	cmd  *exec.Cmd
 	addr *net.TCPAddr
 
-	clean func()
+	configs map[string]string
+
+	clean func(bool)
 }
 
 func (s *KvrocksServer) HostPort() string {
@@ -77,13 +79,57 @@ func (s *KvrocksServer) NewTCPClient() *TCPClient {
 }
 
 func (s *KvrocksServer) Close() {
+	s.close(false)
+}
+
+func (s *KvrocksServer) close(keepDir bool) {
 	require.NoError(s.t, s.cmd.Process.Signal(syscall.SIGTERM))
 	timer := time.AfterFunc(defaultGracePeriod, func() {
 		require.NoError(s.t, s.cmd.Process.Kill())
 	})
 	defer timer.Stop()
 	require.NoError(s.t, s.cmd.Wait())
-	s.clean()
+	s.clean(keepDir)
+}
+
+func (s *KvrocksServer) Restart() {
+	s.close(true)
+
+	b := *binPath
+	require.NotEmpty(s.t, b, "please set the binary path by `-binPath`")
+	cmd := exec.Command(b)
+
+	dir := s.configs["dir"]
+	f, err := os.Open(filepath.Join(dir, "kvrocks.conf"))
+	require.NoError(s.t, err)
+	defer func() { require.NoError(s.t, f.Close()) }()
+
+	cmd.Args = append(cmd.Args, "-c", f.Name())
+
+	stdout, err := os.Create(filepath.Join(dir, "stdout"))
+	require.NoError(s.t, err)
+	cmd.Stdout = stdout
+	stderr, err := os.Create(filepath.Join(dir, "stderr"))
+	require.NoError(s.t, err)
+	cmd.Stderr = stderr
+
+	require.NoError(s.t, cmd.Start())
+
+	c := redis.NewClient(&redis.Options{Addr: s.addr.String()})
+	defer func() { require.NoError(s.t, c.Close()) }()
+	require.Eventually(s.t, func() bool {
+		err := c.Ping(context.Background()).Err()
+		return err == nil || err.Error() == "NOAUTH Authentication required."
+	}, time.Minute, time.Second)
+
+	s.cmd = cmd
+	s.clean = func(keepDir bool) {
+		require.NoError(s.t, stdout.Close())
+		require.NoError(s.t, stderr.Close())
+		if *deleteOnExit && !keepDir {
+			require.NoError(s.t, os.RemoveAll(dir))
+		}
+	}
 }
 
 func StartServer(t testing.TB, configs map[string]string) *KvrocksServer {
@@ -130,13 +176,14 @@ func StartServer(t testing.TB, configs map[string]string) *KvrocksServer {
 	}, time.Minute, time.Second)
 
 	return &KvrocksServer{
-		t:    t,
-		cmd:  cmd,
-		addr: addr,
-		clean: func() {
+		t:       t,
+		cmd:     cmd,
+		addr:    addr,
+		configs: configs,
+		clean: func(keepDir bool) {
 			require.NoError(t, stdout.Close())
 			require.NoError(t, stderr.Close())
-			if *deleteOnExit {
+			if *deleteOnExit && !keepDir {
 				require.NoError(t, os.RemoveAll(dir))
 			}
 		},
diff --git a/tests/tcl/tests/integration/rsid_psync.tcl b/tests/tcl/tests/integration/rsid_psync.tcl
deleted file mode 100644
index 8dd5f51..0000000
--- a/tests/tcl/tests/integration/rsid_psync.tcl
+++ /dev/null
@@ -1,122 +0,0 @@
-# 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.
-
-start_server {tags {"repl"} overrides {use-rsid-psync yes}} {
-    set A [srv 0 client]
-    r set a b
-
-    start_server {overrides {use-rsid-psync yes}} {
-        r set c d
-        set B [srv 0 client]
-
-        test {replica psync sequence is in the range the master wal but full sync} {
-            # same sequence
-            assert_equal [s -1 master_repl_offset] [s master_repl_offset]
-
-            $A slaveof [srv host] [srv port]
-            wait_for_sync $A
-
-            assert_equal 1 [s sync_full]
-            assert_equal 1 [s sync_partial_ok]
-        }
-
-        # A -->->-- B
-        # C -->->-- B
-        start_server {overrides {use-rsid-psync yes}} {
-            set C [srv 0 client]
-            set C_host [srv 0 host]
-            set C_port [srv 0 port]
-            
-            $C slaveof [srv -1 host] [srv -1 port]
-            wait_for_sync $C
-
-            test {chained replication can partially resync} {
-                # C never sync with any slave
-                assert_equal 0 [s sync_partial_ok]
-
-                # A -->>-- C, currently topology is A -->>-- C -->>-- B
-                $A slaveof $C_host $C_port
-                wait_for_sync $A
-
-                assert_equal 0 [s sync_full]
-                assert_equal 1 [s sync_partial_ok]
-            }
-
-            test {chained replication can propagate updates} {
-                $B set master B
-                wait_for_ofs_sync $A $B
-                assert_equal [$A get master] {B}
-            }
-
-            test {replica can partially resync after changing master but having the same history} {
-                $A slaveof 127.0.0.1 1025
-                after 1000
-
-                # now topology is
-                # A -->->-- B
-                # C -->->-- B
-                $A slaveof [srv -1 host] [srv -1 port]
-                wait_for_sync $A
-
-                # only partial sync, no full sync
-                assert_equal 2 [s -1 sync_full]
-                assert_equal 3 [s -1 sync_partial_ok]
-            }
-
-            test {replica can partially resync again after restarting} {
-                r config rewrite
-                restart_server 0 true false
-                wait_for_condition 200 500 {
-                    [s master_link_status] eq {up}
-                } else {
-                    fail "Replica C failed to resync with master B"
-                }
-
-                # don't increase sync_full, but increase sync_partial_ok
-                assert_equal 2 [s -1 sync_full]
-                assert_equal 4 [s -1 sync_partial_ok]
-            }
-        }
-    }
-}
-
-start_server {tags {"repl"} overrides {use-rsid-psync yes}} {
-    set replica [srv client]
-    start_server {} {
-        test {Replica(use-rsid-psync yes) can slaveof the master (use-rsid-psync no)} {
-            $replica slaveof [srv host] [srv port]
-            wait_for_sync $replica
-
-            assert_equal 1 [s sync_full]
-            assert_equal 1 [s sync_partial_ok]
-        }
-    }
-}
-
-start_server {tags {"repl"} overrides {use-rsid-psync no}} {
-    set replica [srv client]
-    start_server {overrides {use-rsid-psync yes}} {
-        test {Replica(use-rsid-psync no) can slaveof the master (use-rsid-psync yes)} {
-            $replica slaveof [srv host] [srv port]
-            wait_for_sync $replica
-
-            assert_equal 0 [s sync_full]
-            assert_equal 1 [s sync_partial_ok]
-        }
-    }
-}
-
diff --git a/tests/tcl/tests/test_helper.tcl b/tests/tcl/tests/test_helper.tcl
index dfb7801..ad63db0 100644
--- a/tests/tcl/tests/test_helper.tcl
+++ b/tests/tcl/tests/test_helper.tcl
@@ -43,7 +43,6 @@ set ::all_tests {
     integration/slotimport
     integration/redis-cli
     integration/replication
-    integration/rsid_psync
     integration/cluster
 }