You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@kvrocks.apache.org by GitBox <gi...@apache.org> on 2022/10/07 05:49:51 UTC

[GitHub] [incubator-kvrocks] git-hulk commented on a diff in pull request #956: Move TCL test unit/introspection to Go case

git-hulk commented on code in PR #956:
URL: https://github.com/apache/incubator-kvrocks/pull/956#discussion_r989703612


##########
tests/gocase/unit/introspection/introspection_test.go:
##########
@@ -20,33 +20,223 @@
 package introspection
 
 import (
+	"context"
+	"fmt"
+	"strconv"
+	"strings"
 	"testing"
+	"time"
 
 	"github.com/apache/incubator-kvrocks/tests/gocase/util"
+	"github.com/go-redis/redis/v9"
 	"github.com/stretchr/testify/require"
 )
 
 func TestIntrospection(t *testing.T) {
 	srv := util.StartServer(t, map[string]string{})
 	defer srv.Close()
 
-	t.Run("PING", func(t *testing.T) {
+	ctx := context.Background()
+	rdb := srv.NewClient()
+	defer func() { require.NoError(t, rdb.Close()) }()
+
+	t.Run("CLIENT LIST", func(t *testing.T) {
+		v := rdb.ClientList(ctx).Val()
+		require.Regexp(t, "id=.* addr=.*:.* fd=.* name=.* age=.* idle=.* flags=N namespace=.* qbuf=.* .*obuf=.* cmd=client.*", v)
+	})
+
+	t.Run("MONITOR can log executed commands", func(t *testing.T) {
 		c := srv.NewTCPClient()
 		defer func() { require.NoError(t, c.Close()) }()
-		require.NoError(t, c.WriteArgs("PING"))
-		r, err := c.ReadLine()
+		require.NoError(t, c.WriteArgs("MONITOR"))
+		v, err := c.ReadLine()
+		require.NoError(t, err)
+		require.Equal(t, "+OK", v)
+		require.NoError(t, rdb.Set(ctx, "foo", "bar", 0).Err())
+		require.NoError(t, rdb.Get(ctx, "foo").Err())
+		v, err = c.ReadLine()
 		require.NoError(t, err)
-		require.Equal(t, r, "+PONG")
-		require.NoError(t, c.WriteArgs("PING", "PONG"))
-		r, err = c.ReadLine()
+		require.Regexp(t, ".*set.*foo.*bar.*", v)
+		v, err = c.ReadLine()
+		require.NoError(t, err)
+		require.Regexp(t, ".*get.*foo.*", v)
+	})
+
+	t.Run("CLIENT GETNAME should return NIL if name is not assigned", func(t *testing.T) {
+		require.EqualError(t, rdb.ClientGetName(ctx).Err(), redis.Nil.Error())
+	})
+
+	t.Run("CLIENT LIST shows empty fields for unassigned names", func(t *testing.T) {
+		require.Regexp(t, ".*name= .*", rdb.ClientList(ctx).Val())
+	})
+
+	t.Run("CLIENT SETNAME does not accept spaces", func(t *testing.T) {
+		require.Error(t, rdb.Do(ctx, "CLIENT", "SETNAME", "foo bar").Err())
+	})
+
+	t.Run("CLIENT SETNAME can assign a name to this connection", func(t *testing.T) {
+		r := rdb.Do(ctx, "CLIENT", "SETNAME", "myname")
+		require.NoError(t, r.Err())
+		require.Equal(t, "OK", r.Val())
+		require.Regexp(t, ".*name=myname.*", rdb.ClientList(ctx).Val())
+	})
+
+	t.Run("CLIENT SETNAME can assign a name to this connection", func(t *testing.T) {
+		r := rdb.Do(ctx, "CLIENT", "SETNAME", "myname")
+		require.NoError(t, r.Err())
+		require.Equal(t, "OK", r.Val())
+		require.Regexp(t, ".*name=myname.*", rdb.ClientList(ctx).Val())
+	})
+
+	t.Run("CLIENT SETNAME can change the name of an existing connection", func(t *testing.T) {
+		r := rdb.Do(ctx, "CLIENT", "SETNAME", "someothername")
+		require.NoError(t, r.Err())
+		require.Equal(t, "OK", r.Val())
+		require.Regexp(t, ".*name=someothername.*", rdb.ClientList(ctx).Val())
+	})
+
+	t.Run("After CLIENT SETNAME, connection can still be closed", func(t *testing.T) {
+		func() {
+			c := srv.NewClient()
+			defer func() { require.NoError(t, c.Close()) }()
+			r := c.Do(ctx, "CLIENT", "SETNAME", "foobar")
+			require.NoError(t, r.Err())
+			require.Equal(t, "OK", r.Val())
+			require.Regexp(t, ".*name=foobar.*", rdb.ClientList(ctx).Val())
+		}()
+
+		// now the client should no longer be listed
+		require.Eventually(t, func() bool {
+			r := rdb.ClientList(ctx).Val()
+			return !strings.Contains(r, "foobar")
+		}, 5*time.Second, 100*time.Millisecond)
+	})
+
+	t.Run("Kill normal client", func(t *testing.T) {
+		defer func() { rdb = srv.NewClient() }()
+
+		c := srv.NewClient()
+		defer func() { require.NoError(t, c.Close()) }()
+		r := c.Do(ctx, "CLIENT", "SETNAME", "normal")
+		require.NoError(t, r.Err())
+		require.Equal(t, "OK", r.Val())
+		require.Regexp(t, ".*name=normal.*", rdb.ClientList(ctx).Val())
+
+		require.EqualValues(t, 1, rdb.ClientKillByFilter(ctx, "skipme", "yes", "type", "normal").Val())
+		require.EqualValues(t, 1, rdb.ClientKillByFilter(ctx, "skipme", "no", "type", "normal").Val())
+
+		// reconnect
+		rdb = srv.NewClient()
+		defer func() { require.NoError(t, rdb.Close()) }()
+
+		// now the client should no longer be listed
+		require.Eventually(t, func() bool {
+			r := rdb.ClientList(ctx).Val()
+			return !strings.Contains(r, "normal")
+		}, 5*time.Second, 100*time.Millisecond)
+	})
+
+	t.Run("Kill pubsub client", func(t *testing.T) {
+		// subscribe clients
+		c0 := srv.NewClient()
+		defer func() { require.NoError(t, c0.Close()) }()
+		require.NoError(t, c0.Do(ctx, "CLIENT", "SETNAME", "pubsub").Err())
+		r := c0.Do(ctx, "SUBSCRIBE", "foo")
+		require.NoError(t, r.Err())
+		require.Equal(t, "[subscribe foo 1]", fmt.Sprintf("%v", r.Val()))
+
+		// psubscribe clients
+		c1 := srv.NewClient()
+		defer func() { require.NoError(t, c1.Close()) }()
+		require.NoError(t, c1.Do(ctx, "CLIENT", "SETNAME", "pubsub").Err())
+		r = c1.Do(ctx, "PSUBSCRIBE", "bar.*")
+		require.NoError(t, r.Err())
+		require.Equal(t, "[psubscribe bar.* 1]", fmt.Sprintf("%v", r.Val()))
+
+		// normal clients
+		c2 := srv.NewClient()
+		require.NoError(t, c2.Do(ctx, "CLIENT", "SETNAME", "normal").Err())
+		defer func() { require.NoError(t, c2.Close()) }()
+
+		require.EqualValues(t, 2, rdb.ClientKillByFilter(ctx, "type", "pubsub").Val())
+
+		// now the pubsub client should no longer be listed
+		// but normal client should not be dropped
+		require.Eventually(t, func() bool {
+			r := rdb.ClientList(ctx).Val()
+			fmt.Printf("CLIENT LIST: %v\n", r)
+			return strings.Count(r, "pubsub") == 0 && strings.Count(r, "normal") == 1
+		}, 5*time.Second, 100*time.Millisecond)
+	})
+
+	t.Run("DEBUG will freeze server", func(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"))

Review Comment:
   ```suggestion
   		require.NoError(t, c.WriteArgs("DEBUG", "sleep", "2.2"))
   		
   	    // Sleep 100ms to prevent the successive set command to be executed
   		// before the debug command since there are in the different connection.
   		time.Sleep(100 * time.Millisecond)
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@kvrocks.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org