ronantakizawa/codereview-bench huggingface dataset:
Repository: DiceDB/dice
File: integration_tests/commands/toggle_test.go (Go)

Code before:
package commands

import (
	"testing"

	"github.com/dicedb/dice/testutils"
	"gotest.tools/v3/assert"
)

func TestEvalJSONTOGGLE(t *testing.T) {
    conn := getLocalConnection()
    defer conn.Close()

	simpleJSON :=`{"name":true,"age":false}`

    testCases := []struct {
        name     string
        commands []string
        expected []interface{}
    }{
        {
			name:     "JSON.TOGGLE with existing key",
			commands: []string{`JSON.SET user $ `+ simpleJSON, "JSON.TOGGLE user $.name"},
			expected: []interface{}{"OK", []any{int64(0)}},
		},
        {
            name:     "JSON.TOGGLE with non-existing key",
            commands: []string{"JSON.TOGGLE user $.flag"},
            expected: []interface{}{"ERR could not perform this operation on a key that doesn't exist"},
        },
        {
			name:     "JSON.TOGGLE with invalid path",
			commands: []string{`JSON.SET testkey $ ` + simpleJSON, "JSON.TOGGLE user $.invalidPath"},
			expected: []interface{}{"WRONGTYPE Operation against a key holding the wrong kind of value", "ERR could not perform this operation on a key that doesn't exist"},
		},
        {
            name:     "JSON.TOGGLE with invalid command format",
            commands: []string{"JSON.TOGGLE testKey"},
            expected: []interface{}{"ERR wrong number of arguments for 'json.toggle' command"},

Review comment (suggestion):
Also add a test case where the json structure is similar to : `{field: true, nested: {field: false, nested: {field: true}}}` and the user calls `JSON.TOGGLE key $..field`
It will be good to validate the final JSON structure too using `JSON.GET` call. Same for the integration tests.
```sh
0.0.0.0:6379> JSON.SET doc $ '{"field": true, "nested":{"field":false, "nested":{"field": true}}}'
OK
0.0.0.0:6379> JSON.GET doc
"{\"field\":true,\"nested\":{\"field\":false,\"nested\":{\"field\":true}}}"
0.0.0.0:6379> JSON.TOGGLE doc $..field
1) (integer) 0
2) (integer) 1
3) (integer) 0
0.0.0.0:6379> JSON.GET doc
"{\"field\":false,\"nested\":{\"field\":true,\"nested\":{\"field\":false}}}"
```

Code after:
package commands

import (
	"encoding/json"

	"testing"

	"github.com/dicedb/dice/testutils"
	"gotest.tools/v3/assert"
)

func compareJSON(t *testing.T, expected, actual string) {
	var expectedMap map[string]interface{}
	var actualMap map[string]interface{}

	err1 := json.Unmarshal([]byte(expected), &expectedMap)
	err2 := json.Unmarshal([]byte(actual), &actualMap)

	assert.NilError(t, err1)
	assert.NilError(t, err2)

	assert.DeepEqual(t, expectedMap, actualMap)
}

func TestEvalJSONTOGGLE(t *testing.T) {
	conn := getLocalConnection()
	defer conn.Close()

	simpleJSON := `{"name":true,"age":false}`
	complexJson := `{"field":true,"nested":{"field":false,"nested":{"field":true}}}`

	testCases := []struct {
		name     string
		commands []string
		expected []interface{}
	}{
		{
			name:     "JSON.TOGGLE with existing key",
			commands: []string{`JSON.SET user $ ` + simpleJSON, "JSON.TOGGLE user $.name"},
Repository: DiceDB/dice
File: internal/eval/eval.go (Go)

Code before:
    if modified {
        newObj := &object.Obj{
            Value:        jsonData,
            TypeEncoding: object.ObjTypeJSON,
        }
        exp, ok := dstore.GetExpiry(obj, store)
        var exDurationMs int64 = -1
        if ok {
            exDurationMs = int64(exp - uint64(utils.GetCurrentTime().UnixMilli()))
        }
        if exDurationMs > 0 {
            store.SetExpiry(newObj, exDurationMs)
        }
        store.Put(key, newObj)
    }

    toggleResults = reverseResults(toggleResults)
    return clientio.Encode(toggleResults, false)
}

func boolToInt(b bool) int {
    if b {
        return 1
    }
    return 0
}

func reverseResults(results []interface{}) []interface{} {
    reversed := make([]interface{}, len(results))
    for i, v := range results {
        reversed[len(results)-1-i] = v
    }
    return reversed
}

// evalJSONSET stores a JSON value at the specified key
// args must contain at least the key, path (unused in this implementation), and JSON string
// Returns encoded error response if incorrect number of arguments
// Returns encoded error if the JSON string is invalid
// Returns response.RespOK if the JSON value is successfully stored
func evalJSONSET(args []string, store *dstore.Store) []byte {
	// Check if there are enough arguments
	if len(args) < 3 {
		return diceerrors.NewErrArity("JSON.SET")
	}

	key := args[0]
	path := args[1]
	jsonStr := args[2]
	for i := 3; i < len(args); i++ {
		switch args[i] {

Review comment (suggestion):
```suggestion
func boolToInt(b bool) int {
    return int(b)
}

```

Code after:
	// Default path is root if not specified
	path := defaultRootPath
	if len(args) > 1 {
		path = args[1]
	}
	// Retrieve the object from the database
	obj := store.Get(key)
	if obj == nil {
		return clientio.RespNIL
	}

	errWithMessage := object.AssertTypeAndEncoding(obj.TypeEncoding, object.ObjTypeJSON, object.ObjEncodingJSON)
	if errWithMessage != nil {
		return errWithMessage
	}

	jsonData := obj.Value

	if path == defaultRootPath {
		_, err := sonic.Marshal(jsonData)
		if err != nil {
			return diceerrors.NewErrWithMessage("could not serialize result")
		}
		// If path is root and len(args) == 1, return "object" instantly
		if len(args) == 1 {
			return clientio.Encode(utils.ObjectType, false)
		}
	}

	// Parse the JSONPath expression
	expr, err := jp.ParseString(path)
	if err != nil {
		return diceerrors.NewErrWithMessage("invalid JSONPath")
	}

	results := expr.Get(jsonData)
	if len(results) == 0 {
		return clientio.RespEmptyArray
	}

	typeList := make([]string, 0, len(results))
	for _, result := range results {
		jsonType := utils.GetJSONFieldType(result)
		typeList = append(typeList, jsonType)
	}
	return clientio.Encode(typeList, false)
}

// evalJSONGET retrieves a JSON value stored at the specified key
// args must contain at least the key;  (path unused in this implementation)
// Returns response.RespNIL if key is expired or it does not exist
Repository: DiceDB/dice
File: internal/eval/eval.go (Go)

Code before:
		}

		// add memory used by storage object
		size += int(unsafe.Sizeof(obj)) + calculateMemory(obj.LastAccessedAt) + calculateMemory(obj.TypeEncoding)

		return clientio.Encode(size, false)
	}

	// handle nested paths
	var results []any = []any{}
	if path != defaultRootPath {

		// check if path is valid
		expr, err := jp.ParseString(path)
		if err != nil {
			return diceerrors.NewErrWithMessage("invalid JSON path")
		}

		results = expr.Get(obj.Value)

		// handle error cases
		if len(results) == 0 {
			// handle out of bound index path for array json type
			isArray := utils.IsArray(obj.Value)
			if isArray {
				arr := obj.Value.([]any)
				reg := regexp.MustCompile(`^\$(\.|)\[(\d+|\*)\]`)
				matches := reg.FindStringSubmatch(path)

				if len(matches) == 3 {
					index, err := strconv.Atoi(matches[2])
					if err != nil {
						return diceerrors.NewErrWithMessage("unable to extract index")
					}
					if index >= len(arr) {
						return clientio.RespEmptyArray
					}
				}
			}

			// for rest json types, throw error
			return diceerrors.NewErrWithFormattedMessage("Path '$.%v' does not exist", path)
		}
	}

	// get memory used by each path
	sizeList := make([]interface{}, 0, len(results))
	for _, result := range results {
		size := calculateMemory(result)
		sizeList = append(sizeList, size)
	}

Review comment (performance):
You are casting types twice, once inside the `IsArray` method and once here. This adds to the latency.

You can replace the call to `IsArray` with the following:
```go
arr, ok := obj.Value.([]any)
if !ok {
  // return err
}
// use arr
```

Code after:
// It returns value's memory usage in bytes
func evalJSONDebugMemory(args []string, store *dstore.Store) []byte {
	if len(args) < 1 {
		return diceerrors.NewErrArity("json.debug")
	}
	key := args[0]

	// default path is root if not specified
	path := defaultRootPath
	if len(args) > 1 {
		path = args[1] // any more args are ignored for this command altogether
	}

	obj := store.Get(key)
	if obj == nil {
		return clientio.RespZero
	}

	// check if the object is a valid JSON
	errWithMessage := object.AssertTypeAndEncoding(obj.TypeEncoding, object.ObjTypeJSON, object.ObjEncodingJSON)
	if errWithMessage != nil {
		return errWithMessage
	}

	// handle root path
	if path == defaultRootPath {
		jsonData := obj.Value

		// memory used by json data
		size := calculateSizeInBytes(jsonData)
		if size == -1 {
			return diceerrors.NewErrWithMessage("unknown type")
		}

		// add memory used by storage object
		size += int(unsafe.Sizeof(obj)) + calculateSizeInBytes(obj.LastAccessedAt) + calculateSizeInBytes(obj.TypeEncoding)

		return clientio.Encode(size, false)
	}

	// handle nested paths
	var results []any = []any{}
	if path != defaultRootPath {
		// check if path is valid
		expr, err := jp.ParseString(path)
		if err != nil {
			return diceerrors.NewErrWithMessage("invalid JSON path")
		}

		results = expr.Get(obj.Value)
Repository: DiceDB/dice
File: internal/eval/eval.go (Go)

Code before:
					index, err := strconv.Atoi(matches[2])
					if err != nil {
						return diceerrors.NewErrWithMessage("unable to extract index")
					}
					if index >= len(arr) {
						return clientio.RespEmptyArray
					}
				}
			}

			// for rest json types, throw error
			return diceerrors.NewErrWithFormattedMessage("Path '$.%v' does not exist", path)
		}
	}

	// get memory used by each path
	sizeList := make([]interface{}, 0, len(results))
	for _, result := range results {
		size := calculateMemory(result)
		sizeList = append(sizeList, size)
	}

	return clientio.Encode(sizeList, false)
}

func calculateMemory(value interface{}) int {
	switch convertedValue := value.(type) {

	case string:
		return int(unsafe.Sizeof(value)) + len(convertedValue)

	case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64, bool, nil:
		return int(unsafe.Sizeof(value))

	// object
	case map[string]interface{}:
		size := int(unsafe.Sizeof(value))
		for k, v := range convertedValue {
			size += int(unsafe.Sizeof(k)) + len(k) + calculateMemory(v)
		}
		return size

	// array
	case []interface{}:
		size := int(unsafe.Sizeof(value))
		for _, elem := range convertedValue {
			size += calculateMemory(elem)
		}
		return size

	// unknown type

Review comment (suggestion):
nit:
```suggestion
func calculateSizeInBytes(value interface{}) int {
```

Code after:
		if size == -1 {
			return diceerrors.NewErrWithMessage("unknown type")
		}

		// add memory used by storage object
		size += int(unsafe.Sizeof(obj)) + calculateSizeInBytes(obj.LastAccessedAt) + calculateSizeInBytes(obj.TypeEncoding)

		return clientio.Encode(size, false)
	}

	// handle nested paths
	var results []any = []any{}
	if path != defaultRootPath {
		// check if path is valid
		expr, err := jp.ParseString(path)
		if err != nil {
			return diceerrors.NewErrWithMessage("invalid JSON path")
		}

		results = expr.Get(obj.Value)

		// handle error cases
		if len(results) == 0 {
			// this block will return '[]' for out of bound index for an array json type
			// this will maintain consistency with redis
			isArray := utils.IsArray(obj.Value)
			if isArray {
				arr, ok := obj.Value.([]any)
				if !ok {
					return diceerrors.NewErrWithMessage("invalid array json")
				}

				// extract index from arg
				reg := regexp.MustCompile(`^\$\.?\[(\d+|\*)\]`)
				matches := reg.FindStringSubmatch(path)

				if len(matches) == 2 {
					// convert index to int
					index, err := strconv.Atoi(matches[1])
					if err != nil {
						return diceerrors.NewErrWithMessage("unable to extract index")
					}

					// if index is out of bound return empty array
					if index >= len(arr) {
						return clientio.RespEmptyArray
					}
				}
			}

			// for rest json types, throw error
Repository: DiceDB/dice
File: internal/eval/eval.go (Go)

Code before:
		return diceerrors.NewErrArity("LLEN")
	}

	obj := store.Get(args[0])
	if obj == nil {
		return clientio.Encode(0, false)
	}

	// if object is a set type, return error
	if object.AssertType(obj.TypeEncoding, object.ObjTypeSet) == nil {
		return diceerrors.NewErrWithFormattedMessage(diceerrors.WrongTypeErr)
	}

	if err := object.AssertType(obj.TypeEncoding, object.ObjTypeByteList); err != nil {
		return clientio.Encode(err, false)
	}

	if err := object.AssertEncoding(obj.TypeEncoding, object.ObjEncodingDeque); err != nil {
		return clientio.Encode(err, false)
	}

	deq := obj.Value.(*Deque)
	return clientio.Encode(deq.Length, false)
}

// GETSET atomically sets key to value and returns the old value stored at key.
// Returns an error when key exists but does not hold a string value.
// Any previous time to live associated with the key is
// discarded on successful SET operation.
//
// Returns:
// Bulk string reply: the old value stored at the key.
// Nil reply: if the key does not exist.
func evalGETSET(args []string, store *dstore.Store) []byte {
	if len(args) != 2 {
		return diceerrors.NewErrArity("GETSET")
	}

	var key, value = args[0], args[1]
	getResp := evalGET([]string{key}, store)
	// Check if it's an error resp from GET
	if strings.HasPrefix(string(getResp), "-") {
		return getResp
	}

	// Previous TTL needs to be reset
	setResp := evalSET([]string{key, value}, store)
	// Check if it's an error resp from SET
	if strings.HasPrefix(string(setResp), "-") {
		return setResp
	}

Review comment (suggestion):
Can't we simply use 
```go
object.AssertTypeAndEncoding(obj.TypeEncoding, object.ObjTypeByteList, object.ObjEncodingDeque)
```

Code after:
		panic(fmt.Sprintf("unknown error: %v", err))
	}

	return clientio.Encode(x, false)
}

func evalLLEN(args []string, store *dstore.Store) []byte {
	if len(args) != 1 {
		return diceerrors.NewErrArity("LLEN")
	}

	obj := store.Get(args[0])
	if obj == nil {
		return clientio.Encode(0, false)
	}

	if err := object.AssertTypeAndEncoding(obj.TypeEncoding, object.ObjTypeByteList, object.ObjEncodingDeque); err != nil {
		return err
	}

	deq := obj.Value.(*Deque)
	return clientio.Encode(deq.Length, false)
}

// GETSET atomically sets key to value and returns the old value stored at key.
// Returns an error when key exists but does not hold a string value.
// Any previous time to live associated with the key is
// discarded on successful SET operation.
//
// Returns:
// Bulk string reply: the old value stored at the key.
// Nil reply: if the key does not exist.
func evalGETSET(args []string, store *dstore.Store) []byte {
	if len(args) != 2 {
		return diceerrors.NewErrArity("GETSET")
	}

	key, value := args[0], args[1]
	getResp := evalGET([]string{key}, store)
	// Check if it's an error resp from GET
	if strings.HasPrefix(string(getResp), "-") {
		return getResp
	}

	// Previous TTL needs to be reset
	setResp := evalSET([]string{key, value}, store)
	// Check if it's an error resp from SET
	if strings.HasPrefix(string(setResp), "-") {
		return setResp
	}
Repository: DiceDB/dice
File: internal/eval/eval.go (Go)

Code before:
	deq := obj.Value.(*Deque)
	x, err := deq.LPop()
	if err != nil {
		if err == ErrDequeEmpty {
			return clientio.RespNIL
		}
		panic(fmt.Sprintf("unknown error: %v", err))
	}

	return clientio.Encode(x, false)
}

func evalLLEN(args []string, store *dstore.Store) []byte {
	if len(args) != 1 {
		return diceerrors.NewErrArity("LLEN")
	}

	obj := store.Get(args[0])
	if obj == nil {
		return clientio.Encode(0, false)
	}

	// if object is a set type, return error
	if object.AssertType(obj.TypeEncoding, object.ObjTypeSet) == nil {
		return diceerrors.NewErrWithFormattedMessage(diceerrors.WrongTypeErr)
	}

	if err := object.AssertTypeAndEncoding(obj.TypeEncoding, object.ObjTypeByteList, object.ObjEncodingDeque); err != nil {
		return clientio.Encode(err, false)
	}

	deq := obj.Value.(*Deque)
	return clientio.Encode(deq.Length, false)
}

// GETSET atomically sets key to value and returns the old value stored at key.
// Returns an error when key exists but does not hold a string value.
// Any previous time to live associated with the key is
// discarded on successful SET operation.
//
// Returns:
// Bulk string reply: the old value stored at the key.
// Nil reply: if the key does not exist.
func evalGETSET(args []string, store *dstore.Store) []byte {
	if len(args) != 2 {
		return diceerrors.NewErrArity("GETSET")
	}

	key, value := args[0], args[1]
	getResp := evalGET([]string{key}, store)
	// Check if it's an error resp from GET

Review comment (suggestion):
I don't think this is required.
```suggestion
```

Code after:
	deq := obj.Value.(*Deque)
	x, err := deq.LPop()
	if err != nil {
		if err == ErrDequeEmpty {
			return clientio.RespNIL
		}
		panic(fmt.Sprintf("unknown error: %v", err))
	}

	return clientio.Encode(x, false)
}

func evalLLEN(args []string, store *dstore.Store) []byte {
	if len(args) != 1 {
		return diceerrors.NewErrArity("LLEN")
	}

	obj := store.Get(args[0])
	if obj == nil {
		return clientio.Encode(0, false)
	}

	if err := object.AssertTypeAndEncoding(obj.TypeEncoding, object.ObjTypeByteList, object.ObjEncodingDeque); err != nil {
		return err
	}

	deq := obj.Value.(*Deque)
	return clientio.Encode(deq.Length, false)
}

// GETSET atomically sets key to value and returns the old value stored at key.
// Returns an error when key exists but does not hold a string value.
// Any previous time to live associated with the key is
// discarded on successful SET operation.
//
// Returns:
// Bulk string reply: the old value stored at the key.
// Nil reply: if the key does not exist.
func evalGETSET(args []string, store *dstore.Store) []byte {
	if len(args) != 2 {
		return diceerrors.NewErrArity("GETSET")
	}

	key, value := args[0], args[1]
	getResp := evalGET([]string{key}, store)
	// Check if it's an error resp from GET
	if strings.HasPrefix(string(getResp), "-") {
		return getResp
	}

	// Previous TTL needs to be reset
Repository: DiceDB/dice
File: internal/eval/eval.go (Go)

Code before:
		if err == ErrDequeEmpty {
			return clientio.RespNIL
		}
		panic(fmt.Sprintf("unknown error: %v", err))
	}

	return clientio.Encode(x, false)
}

func evalLLEN(args []string, store *dstore.Store) []byte {
	if len(args) != 1 {
		return diceerrors.NewErrArity("LLEN")
	}

	obj := store.Get(args[0])
	if obj == nil {
		return clientio.Encode(0, false)
	}

	// if object is a set type, return error
	if object.AssertType(obj.TypeEncoding, object.ObjTypeSet) == nil {
		return diceerrors.NewErrWithFormattedMessage(diceerrors.WrongTypeErr)
	}

	if err := object.AssertTypeAndEncoding(obj.TypeEncoding, object.ObjTypeByteList, object.ObjEncodingDeque); err != nil {
		return clientio.Encode(err, false)
	}

	deq := obj.Value.(*Deque)
	return clientio.Encode(deq.Length, false)
}

// GETSET atomically sets key to value and returns the old value stored at key.
// Returns an error when key exists but does not hold a string value.
// Any previous time to live associated with the key is
// discarded on successful SET operation.
//
// Returns:
// Bulk string reply: the old value stored at the key.
// Nil reply: if the key does not exist.
func evalGETSET(args []string, store *dstore.Store) []byte {
	if len(args) != 2 {
		return diceerrors.NewErrArity("GETSET")
	}

	key, value := args[0], args[1]
	getResp := evalGET([]string{key}, store)
	// Check if it's an error resp from GET
	if strings.HasPrefix(string(getResp), "-") {
		return getResp
	}

Review comment (suggestion):
Return the error directly, it is already encoded. Include a test case validating the error message too.
```suggestion
		return err

Code after:
		if err == ErrDequeEmpty {
			return clientio.RespNIL
		}
		panic(fmt.Sprintf("unknown error: %v", err))
	}

	return clientio.Encode(x, false)
}

func evalLLEN(args []string, store *dstore.Store) []byte {
	if len(args) != 1 {
		return diceerrors.NewErrArity("LLEN")
	}

	obj := store.Get(args[0])
	if obj == nil {
		return clientio.Encode(0, false)
	}

	if err := object.AssertTypeAndEncoding(obj.TypeEncoding, object.ObjTypeByteList, object.ObjEncodingDeque); err != nil {
		return err
	}

	deq := obj.Value.(*Deque)
	return clientio.Encode(deq.Length, false)
}

// GETSET atomically sets key to value and returns the old value stored at key.
// Returns an error when key exists but does not hold a string value.
// Any previous time to live associated with the key is
// discarded on successful SET operation.
//
// Returns:
// Bulk string reply: the old value stored at the key.
// Nil reply: if the key does not exist.
func evalGETSET(args []string, store *dstore.Store) []byte {
	if len(args) != 2 {
		return diceerrors.NewErrArity("GETSET")
	}

	key, value := args[0], args[1]
	getResp := evalGET([]string{key}, store)
	// Check if it's an error resp from GET
	if strings.HasPrefix(string(getResp), "-") {
		return getResp
	}

	// Previous TTL needs to be reset
	setResp := evalSET([]string{key, value}, store)
	// Check if it's an error resp from SET
	if strings.HasPrefix(string(setResp), "-") {
Repository: DiceDB/dice
File: integration_tests/commands/setup.go (Go)

Code before:

func FireCommand(conn net.Conn, cmd string) interface{} {
	var err error
	args := testutils.ParseCommand(cmd)
	_, err = conn.Write(clientio.Encode(args, false))
	if err != nil {
		slog.Error(
			"error while firing command",
			slog.Any("error", err),
			slog.String("command", cmd),
		)
		os.Exit(1)
	}

	rp := clientio.NewRESPParser(conn)
	v, err := rp.DecodeOne()
	if err != nil {
		if err == io.EOF {
			return nil
		}
		slog.Error(
			"error while firing command",
			slog.Any("error", err),
			slog.String("command", cmd),
		)
		os.Exit(1)
	}
	return v
}

//nolint:unused
func fireCommandAndGetRESPParser(conn net.Conn, cmd string) *clientio.RESPParser {
	args := testutils.ParseCommand(cmd)
	_, err := conn.Write(clientio.Encode(args, false))
	if err != nil {
		slog.Error(
			"error while firing command",
			slog.Any("error", err),
			slog.String("command", cmd),
		)
		os.Exit(1)
	}

	return clientio.NewRESPParser(conn)
}

func RunTestServer(ctx context.Context, wg *sync.WaitGroup, opt TestServerOptions) {
	config.DiceConfig.Network.IOBufferLength = 16
	config.DiceConfig.Server.WriteAOFOnCleanup = true
	if opt.Port != 0 {
		config.DiceConfig.Server.Port = opt.Port

Review comment (suggestion):
Shall we write our own function wrapper like `func LogErrorFatal(l *slog.Logger, ..)` and use it instead of calling `os.Exit(1)`?
May be we can do this as part of package implementaion.

Code after:

func FireCommand(conn net.Conn, cmd string) interface{} {
	var err error
	args := testutils.ParseCommand(cmd)
	_, err = conn.Write(clientio.Encode(args, false))
	if err != nil {
		slog.Error(
			"error while firing command",
			slog.Any("error", err),
			slog.String("command", cmd),
		)
		os.Exit(1)
	}

	rp := clientio.NewRESPParser(conn)
	v, err := rp.DecodeOne()
	if err != nil {
		if err == io.EOF {
			return nil
		}
		slog.Error(
			"error while firing command",
			slog.Any("error", err),
			slog.String("command", cmd),
		)
		os.Exit(1)
	}
	return v
}

//nolint:unused
func fireCommandAndGetRESPParser(conn net.Conn, cmd string) *clientio.RESPParser {
	args := testutils.ParseCommand(cmd)
	_, err := conn.Write(clientio.Encode(args, false))
	if err != nil {
		slog.Error(
			"error while firing command",
			slog.Any("error", err),
			slog.String("command", cmd),
		)
		os.Exit(1)
	}

	return clientio.NewRESPParser(conn)
}

func RunTestServer(ctx context.Context, wg *sync.WaitGroup, opt TestServerOptions) {
	config.DiceConfig.Network.IOBufferLength = 16
	config.DiceConfig.Server.WriteAOFOnCleanup = false
	if opt.Port != 0 {
		config.DiceConfig.Server.Port = opt.Port