ronantakizawa/codereview-bench huggingface dataset:
Repository: DiceDB/dice
File: internal/eval/eval.go (Go)

Code before:
		// Execute the JSONPath query
		_, err := expr.Modify(jsonData, func(value any) (interface{}, bool) {
			newValue, resultString, isModified := incrementValue(value, isIncrFloat, incrFloat, incrInt)
			resultArray = append(resultArray, resultString)
			return newValue, isModified
		})
		if err != nil {
			return diceerrors.NewErrWithMessage("invalid JSONPath")
		}
	}

	resultString := `[` + strings.Join(resultArray, ",") + `]`

	obj.Value = jsonData
	return clientio.Encode(resultString, false)
}


func evalDUMP(args []string, store *dstore.Store) []byte {
    if len(args) < 1 {
        return diceerrors.NewErrArity("DUMP")
    }
    key := args[0]
    obj := store.Get(key)
    if obj == nil {
        return diceerrors.NewErrWithFormattedMessage("-ERR could not perform this operation on a key that doesn't exist")
    }
	
    serializedValue, err := rdbSerialize(obj)
    if err != nil {
        return diceerrors.NewErrWithMessage("serialization failed")
    }
	encodedResult := base64.StdEncoding.EncodeToString(serializedValue)
    return clientio.Encode(encodedResult, false)
}

func evalRestore(args []string, store *dstore.Store) []byte {
	if len(args) < 3 {
		return diceerrors.NewErrArity("RESTORE")
	}

	key := args[0]
	ttlStr:=args[1]
	ttl, _ := strconv.ParseInt(ttlStr, 10, 64)
	
	encodedValue := args[2]
	serializedData, err := base64.StdEncoding.DecodeString(encodedValue)
	if err != nil {
		return diceerrors.NewErrWithMessage("failed to decode base64 value")
	}


Review comment (suggestion):
Let's keep it consistent with Redis output for non-existent key.
```
127.0.0.1:6379> DUMP k1
(nil)
```

Code after:

func evalSINTER(args []string, store *dstore.Store) []byte {
	if len(args) < 2 {
		return diceerrors.NewErrArity("SINTER")
	}

	sets := make([]map[string]struct{}, 0, len(args))

	var empty = 0

	for _, arg := range args {
		// Get the set object from the store.
		obj := store.Get(arg)

		if obj == nil {
			empty++
			continue
		}

		// If the object exists, check if it is a set object.
		if err := object.AssertType(obj.TypeEncoding, object.ObjTypeSet); err != nil {
			return diceerrors.NewErrWithFormattedMessage(diceerrors.WrongTypeErr)
		}

		if err := object.AssertEncoding(obj.TypeEncoding, object.ObjEncodingSetStr); err != nil {
			return diceerrors.NewErrWithFormattedMessage(diceerrors.WrongTypeErr)
		}

		// Get the set object.
		set := obj.Value.(map[string]struct{})
		sets = append(sets, set)
	}

	if empty > 0 {
		return clientio.Encode([]string{}, false)
	}

	// sort the sets by the number of elements in the set
	// we will iterate over the smallest set
	// and check if the element is present in all the other sets
	sort.Slice(sets, func(i, j int) bool {
		return len(sets[i]) < len(sets[j])
	})

	count := 0
	resultSet := make(map[string]struct{}, len(sets[0]))

	// init the result set with the first set
	// store the number of elements in the first set in count
	// we will decrement the count if we do not find the elements in the other sets
	for k := range sets[0] {
Repository: DiceDB/dice
File: internal/eval/eval.go (Go)

Code before:
	ttl, _ := strconv.ParseInt(ttlStr, 10, 64)
	
	encodedValue := args[2]
	serializedData, err := base64.StdEncoding.DecodeString(encodedValue)
	if err != nil {
		return diceerrors.NewErrWithMessage("failed to decode base64 value")
	}

	obj, err := rdbDeserialize(serializedData)
	if err != nil {
		return diceerrors.NewErrWithMessage("deserialization failed: " + err.Error())
	}

	newobj:=store.NewObj(obj.Value,ttl,obj.TypeEncoding,obj.TypeEncoding)
	var keepttl=true

	if(ttl>0){
		store.Put(key, newobj, dstore.WithKeepTTL(keepttl))
	}else{
		store.Put(key,obj)
	}
	
	return clientio.RespOK
}

func rdbDeserialize(data []byte) (*object.Obj, error) {
	if len(data) < 3 {
		return nil, errors.New("insufficient data for deserialization")
	}
	objType := data[1] 
	switch objType {
	case 0x00:
		return readString(data[2:])
	case 0xC0: // Integer type
		return readInt(data[2:])
	default:
		return nil, errors.New("unsupported object type")
	}
}

func readString(data []byte) (*object.Obj, error) {
	buf := bytes.NewReader(data)
	var strLen uint32
	if err := binary.Read(buf, binary.BigEndian, &strLen); err != nil {
		return nil, err
	}

	strBytes := make([]byte, strLen)
	if _, err := buf.Read(strBytes); err != nil {
		return nil, err
	}

Review comment (suggestion):
I'd suggest moving DUMP and Restore to a single file like `BITPOS` maybe. Both function are related and all these other functions in these file won't be required for other commands here anyways.

Code after:

	count := 0
	resultSet := make(map[string]struct{}, len(sets[0]))

	// init the result set with the first set
	// store the number of elements in the first set in count
	// we will decrement the count if we do not find the elements in the other sets
	for k := range sets[0] {
		resultSet[k] = struct{}{}
		count++
	}

	for i := 1; i < len(sets); i++ {
		if count == 0 {
			break
		}
		for k := range resultSet {
			if _, ok := sets[i][k]; !ok {
				delete(resultSet, k)
				count--
			}
		}
	}

	if count == 0 {
		return clientio.Encode([]string{}, false)
	}

	members := make([]string, 0, len(resultSet))
	for k := range resultSet {
		members = append(members, k)
	}
	return clientio.Encode(members, false)
}

// PFADD Adds all the element arguments to the HyperLogLog data structure stored at the variable
// name specified as first argument.
//
// Returns:
// If the approximated cardinality estimated by the HyperLogLog changed after executing the command,
// returns 1, otherwise 0 is returned.
func evalPFADD(args []string, store *dstore.Store) []byte {
	if len(args) < 1 {
		return diceerrors.NewErrArity("PFADD")
	}

	key := args[0]
	obj := store.Get(key)

	// If key doesn't exist prior initial cardinality changes hence return 1
	if obj == nil {
Repository: DiceDB/dice
File: internal/eval/eval.go (Go)

Code before:
		return clientio.Encode("", false)
	}

	var str string
	switch _, oEnc := object.ExtractTypeEncoding(obj); oEnc {
	case object.ObjEncodingEmbStr, object.ObjEncodingRaw:
		if val, ok := obj.Value.(string); ok {
			str = val
		} else {
			return diceerrors.NewErrWithMessage("expected string but got another type")
		}
	case object.ObjEncodingInt:
		str = strconv.FormatInt(obj.Value.(int64), 10)
	default:
		return diceerrors.NewErrWithFormattedMessage(diceerrors.WrongTypeErr)
	}

	if start < 0 {
		start = len(str) + start
	}

	if end < 0 {
		end = len(str) + end
	}

	if str == "" || start >= len(str) || end < 0 || start > end {
		return clientio.Encode("", false)
	}

	if start < 0 {
		start = 0
	}

	if end >= len(str) {
		end = len(str) - 1
	}

	return clientio.Encode(str[start:end+1], false)
}


Review comment (bug):
I believe this could be broken down for better readability. The check for empty string could be done right after switch construct. Once you are sure that string has length > 0, you could add the checks for normalising the start and end.

Code after:
		return diceerrors.NewErrWithFormattedMessage(diceerrors.IntOrOutOfRangeErr)
	}

	var str string
	switch _, oEnc := object.ExtractTypeEncoding(obj); oEnc {
	case object.ObjEncodingEmbStr, object.ObjEncodingRaw:
		if val, ok := obj.Value.(string); ok {
			str = val
		} else {
			return diceerrors.NewErrWithMessage("expected string but got another type")
		}
	case object.ObjEncodingInt:
		str = strconv.FormatInt(obj.Value.(int64), 10)
	default:
		return diceerrors.NewErrWithFormattedMessage(diceerrors.WrongTypeErr)
	}

	if str == "" {
		return clientio.Encode("", false)
	}

	if start < 0 {
		start = len(str) + start
	}

	if end < 0 {
		end = len(str) + end
	}

	if start >= len(str) || end < 0 || start > end {
		return clientio.Encode("", false)
	}

	if start < 0 {
		start = 0
	}

	if end >= len(str) {
		end = len(str) - 1
	}

	return clientio.Encode(str[start:end+1], false)
}
Repository: DiceDB/dice
File: internal/server/multitherading.go (Go)

Code before:
	}
}

// gather collects the responses from multiple shards and writes the results into the provided buffer.
// It first waits for responses from all the shards and then processes the result based on the command type (SingleShard, Custom, or Multishard).
func (s *AsyncServer) gather(redisCmd *cmd.RedisCmd, buf *bytes.Buffer, numShards int, c CmdType) {
	// Loop to wait for messages from numberof shards
	var evalResp []eval.EvalResponse
	for i := 0; i < numShards; i++ {
		resp, ok := <-s.ioChan
		if ok {
			evalResp = append(evalResp, resp.EvalResponse)
		}
	}

	// Check if command supports multisharding
	val, ok := WorkerCmdsMeta[redisCmd.Cmd]
	if !ok {
		buf.Write(evalResp[0].Result.([]byte))
		return
	}

	switch c {
	case SingleShard, Custom:
		if evalResp[0].Error != nil {
			buf.WriteString(evalResp[0].Error.Error())
			return
		}
		buf.Write(evalResp[0].Result.([]byte))

	case Multishard:
		buf.Write(val.Gather(evalResp...))
	}
}


Review comment (suggestion):
I am not sure whether the string will replace the characters \r\n hence kept it as a byte slice. But if you can check an error scenario then it would be great. 

Code after:
	}
}

// gather collects the responses from multiple shards and writes the results into the provided buffer.
// It first waits for responses from all the shards and then processes the result based on the command type (SingleShard, Custom, or Multishard).
func (s *AsyncServer) gather(redisCmd *cmd.RedisCmd, buf *bytes.Buffer, numShards int, c CmdType) {
	// Loop to wait for messages from numberof shards
	var evalResp []eval.EvalResponse
	for i := 0; i < numShards; i++ {
		resp, ok := <-s.ioChan
		if ok {
			evalResp = append(evalResp, resp.EvalResponse)
		}
	}

	// Check if command supports multisharding
	val, ok := WorkerCmdsMeta[redisCmd.Cmd]
	if !ok {
		buf.Write(evalResp[0].Result.([]byte))
		return
	}

	switch c {
	case SingleShard, Custom:
		if evalResp[0].Error != nil {
			buf.Write([]byte(evalResp[0].Error.Error()))
			return
		}
		buf.Write(evalResp[0].Result.([]byte))

	case Multishard:
		buf.Write(val.Gather(evalResp...))
	}
}
Repository: DiceDB/dice
File: internal/eval/eval_test.go (Go)

Code before:
			setup: func() {
				key := "EXISTING_KEY"
				value := "mock_value"
				obj := &object.Obj{
					Value:          value,
					LastAccessedAt: uint32(time.Now().Unix()),
				}
				store.Put(key, obj)

			},
			input:  []string{"EXISTING_KEY", strconv.FormatInt(-1, 10)},
			output: []byte("-ERR invalid expire time in 'expire' command\r\n"),
		},
	}

	runEvalTests(t, tests, evalEXPIRE, store)
}

func testEvalEXPIRETIME(t *testing.T, store *dstore.Store) {
	tests := map[string]evalTestCase{
		"wrong number of args": {
			input:  []string{"KEY1", "KEY2"},
			output: []byte("-ERR wrong number of arguments for 'expiretime' command\r\n"),
		},
		"key does not exist": {
			input:  []string{"NONEXISTENT_KEY"},
			output: clientio.RespMinusTwo,
		},
		"key exists without expiry": {
			setup: func() {
				key := "EXISTING_KEY"
				value := "mock_value"
				obj := &object.Obj{
					Value:          value,
					LastAccessedAt: uint32(time.Now().Unix()),
				}
				store.Put(key, obj)
			},
			input:  []string{"EXISTING_KEY"},
			output: clientio.RespMinusOne,
		},
		"key exists with expiry": {
			setup: func() {
				key := "EXISTING_KEY"
				value := "mock_value"
				obj := &object.Obj{
					Value:          value,
					LastAccessedAt: uint32(time.Now().Unix()),
				}
				store.Put(key, obj)


Review comment (bug):
This is incorrect, redis gives the following output when running EXPIRE command with empty expiry: `ERR wrong number of arguments for command`

Code after:
			setup: func() {
				key := "EXISTING_KEY"
				value := "mock_value"
				obj := &object.Obj{
					Value:          value,
					LastAccessedAt: uint32(time.Now().Unix()),
				}
				store.Put(key, obj)

			},
			input:  []string{"EXISTING_KEY", strconv.FormatInt(-1, 10)},
			output: []byte("-ERR invalid expire time in 'expire' command\r\n"),
		},
		"invalid expiry time exists - empty string": {
			setup: func() {
				key := "EXISTING_KEY"
				value := "mock_value"
				obj := &object.Obj{
					Value:          value,
					LastAccessedAt: uint32(time.Now().Unix()),
				}
				store.Put(key, obj)

			},
			input:  []string{"EXISTING_KEY", ""},
			output: []byte("-ERR value is not an integer or out of range\r\n"),
		},
		"invalid expiry time exists - with float number": {
			setup: func() {
				key := "EXISTING_KEY"
				value := "mock_value"
				obj := &object.Obj{
					Value:          value,
					LastAccessedAt: uint32(time.Now().Unix()),
				}
				store.Put(key, obj)

			},
			input:  []string{"EXISTING_KEY", "0.456"},
			output: []byte("-ERR value is not an integer or out of range\r\n"),
		},
	}

	runEvalTests(t, tests, evalEXPIRE, store)
}

func testEvalEXPIRETIME(t *testing.T, store *dstore.Store) {
	tests := map[string]evalTestCase{
		"wrong number of args": {
			input:  []string{"KEY1", "KEY2"},
			output: []byte("-ERR wrong number of arguments for 'expiretime' command\r\n"),
Repository: DiceDB/dice
File: internal/eval/hmap.go (Go)

Code before:
		value = *val
	default:
		return nil, diceerrors.NewErrWithFormattedMessage(diceerrors.WrongTypeErr)
	}

	return clientio.Encode(value, false), nil
}

func (h HashMap) incrementValue(field string, increment int64) (int64, error) {
	val, ok := h[field]
	if !ok {
		h[field] = fmt.Sprintf("%v", increment)
		return increment, nil
	}

	i, err := strconv.ParseInt(val, 10, 64)
	if err != nil {
		return -1, diceerrors.NewErr(diceerrors.HashValueNotIntegerErr)
	}

	total := i + increment
	h[field] = fmt.Sprintf("%v", total)

	return total, nil
}


Review comment (bug):
Another suggestion here would be to check overflow after incrementing. Please check the following scenario:
![image](https://github.com/user-attachments/assets/71f9325b-f4de-43d9-aaa8-3146ca3f913b)


Code after:
		}
		value = *val
	default:
		return nil, diceerrors.NewErrWithFormattedMessage(diceerrors.WrongTypeErr)
	}

	return clientio.Encode(value, false), nil
}

func (h HashMap) incrementValue(field string, increment int64) (int64, error) {
	val, ok := h[field]
	if !ok {
		h[field] = fmt.Sprintf("%v", increment)
		return increment, nil
	}

	i, err := strconv.ParseInt(val, 10, 64)
	if err != nil {
		return -1, diceerrors.NewErr(diceerrors.HashValueNotIntegerErr)
	}

	if (i > 0 && increment > 0 && i > math.MaxInt64-increment) || (i < 0 && increment < 0 && i < math.MinInt64-increment) {
		return -1, diceerrors.NewErr(diceerrors.IncrDecrOverflowErr)
	}

	total := i + increment
	h[field] = fmt.Sprintf("%v", total)

	return total, nil
}
Repository: DiceDB/dice
File: internal/eval/eval.go (Go)

Code before:
	}

	keyValuePairs := args[1:]
	hashMap, numKeys, err := hashMapBuilder(keyValuePairs, hashMap)
	if err != nil {
		return diceerrors.NewErrWithMessage(err.Error())
	}

	obj = store.NewObj(hashMap, -1, object.ObjTypeHashMap, object.ObjEncodingHashMap)

	store.Put(key, obj)

	return clientio.Encode(numKeys, false)
}

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

	key := args[0]

	obj := store.Get(key)

	var hashMap HashMap
	var results []string

	if obj != nil {
		if err := object.AssertTypeAndEncoding(obj.TypeEncoding, object.ObjTypeHashMap, object.ObjEncodingHashMap); err != nil {
			return diceerrors.NewErrWithMessage(diceerrors.WrongTypeErr)
		}
		hashMap = obj.Value.(HashMap)
	}

	for hmKey, hmValue := range hashMap {
		results = append(results, hmKey, hmValue)
	}

	return clientio.Encode(results, false)
}

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

	key := args[0]
	hmKey := args[1]

	val, errWithMessage := getValueFromHashMap(key, hmKey, store)
	if errWithMessage != nil {

Review comment (bug):
Error handling needs to be improved. Instead of directly returning errWithMessage, it would be better to wrap it with additional context for better readability and debugging. You can use `diceerrors.NewErrWithFormattedMessage(errWithMessage)`.

For example:
```go
errWithMessage := object.AssertTypeAndEncoding(obj.TypeEncoding, object.ObjTypeJSON, object.ObjEncodingJSON)
if errWithMessage != nil {
    return diceerrors.NewErrWithFormattedMessage(errWithMessage)
}

Code after:
	}

	keyValuePairs := args[1:]
	hashMap, numKeys, err := hashMapBuilder(keyValuePairs, hashMap)
	if err != nil {
		return diceerrors.NewErrWithMessage(err.Error())
	}

	obj = store.NewObj(hashMap, -1, object.ObjTypeHashMap, object.ObjEncodingHashMap)

	store.Put(key, obj)

	return clientio.Encode(numKeys, false)
}

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

	key := args[0]
	hmKey := args[1]

	val, errWithMessage := getValueFromHashMap(key, hmKey, store)
	if errWithMessage != nil {
		return errWithMessage
	}
	if !bytes.Equal(val, clientio.RespNIL) { // hmKey is already present in hash map
		return clientio.RespZero
	}

	evalHSET(args, store)
	return clientio.RespOne
}

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

	key := args[0]

	obj := store.Get(key)

	var hashMap HashMap
	var results []string

	if obj != nil {
		if err := object.AssertTypeAndEncoding(obj.TypeEncoding, object.ObjTypeHashMap, object.ObjEncodingHashMap); err != nil {
			return diceerrors.NewErrWithMessage(diceerrors.WrongTypeErr)
		}
Repository: DiceDB/dice
File: integration_tests/commands/async/append_test.go (Go)

Code before:
		{
			name: "APPEND to Integer Values",
			commands: []string{
				"DEL key",
				"APPEND key 1",
				"APPEND key 2",
				"GET key",
				"SET key 1",
				"APPEND key 2",
				"GET key",
			},
			expected: []interface{}{int64(0), int64(1), int64(2), "12", "OK", int64(2), "12"},
		},
	}

	for fuzzType, charset := range types {
		buf := ""
		commands := []string{"DEL key"}
		expected := []interface{}{int64(0)}

		for i := 0; i < 1000; i++ {
			bin := randString(rand.Intn(10)+1, charset)
			buf += bin
			commands = append(commands, "APPEND key "+bin)
			expected = append(expected, int64(len(buf)))
		}

		commands = append(commands, "GET key")
		expected = append(expected, buf)

		testCases = append(testCases, struct {
			name     string
			commands []string
			expected []interface{}
		}{
			name:     "APPEND Fuzzing with " + fuzzType,
			commands: commands,
			expected: expected,
		})
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			FireCommand(conn, "DEL key")

			for i, cmd := range tc.commands {
				result := FireCommand(conn, cmd)
				assert.DeepEqual(t, tc.expected[i], result)
			}
		})
	}

Review comment (bug):
why are we running a for loop for so many values? This looks more like a benchmark. A test should ideally be fast, small, easy to follow, and easy to debug.

We probably don't need so many iterations.

Code after:
		{
			name: "APPEND with Various Data Types",
			commands: []string{
				"LPUSH listKey lValue",     // Add element to a list
				"SETBIT bitKey 0 1",        // Set a bit in a bitmap
				"HSET hashKey hKey hValue", // Set a field in a hash
				"SADD setKey sValue",       // Add element to a set
				"APPEND listKey value",     // Attempt to append to a list
				"APPEND bitKey value",      // Attempt to append to a bitmap
				"APPEND hashKey value",     // Attempt to append to a hash
				"APPEND setKey value",      // Attempt to append to a set
			},
			expected: []interface{}{"OK", int64(0), int64(1), int64(1), setErrorMsg, setErrorMsg, setErrorMsg, setErrorMsg},
		},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			FireCommand(conn, "DEL key")

			for i, cmd := range tc.commands {
				result := FireCommand(conn, cmd)
				assert.DeepEqual(t, tc.expected[i], result)
			}
		})
	}
}
Repository: DiceDB/dice
File: integration_tests/commands/async/append_test.go (Go)

Code before:
package async

import (
	"math/rand"
	"testing"
	"time"

	"gotest.tools/v3/assert"
)

func randString(n int, charset string) string {
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	b := make([]byte, n)
	for i := range b {
		b[i] = charset[r.Intn(len(charset))]
	}
	return string(b)
}

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

	types := map[string]string{
		"binary": "01",
		"alpha":  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
		"compr":  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",
	}

	testCases := []struct {
		name     string
		commands []string
		expected []interface{}
	}{

Review comment (bug):
A good way to understand the kind of tests you should be trying to write is to look at the redis documentation for the command, and ensure that every single case being talked about there is easily being tested as a part of your function.

Additionally, ensure that you are covering any potential edge cases.

Code after:
package async

import (
	"testing"

	"gotest.tools/v3/assert"
)

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

	FireCommand(conn, "DEL key listKey bitKey hashKey setKey")
	defer FireCommand(conn, "DEL key listKey bitKey hashKey setKey")

	setErrorMsg := "WRONGTYPE Operation against a key holding the wrong kind of value"
	testCases := []struct {
		name     string
		commands []string
		expected []interface{}
	}{
		{
			name: "APPEND After SET and DEL",
			commands: []string{
				"SET key value",
				"APPEND key value",
				"GET key",
				"APPEND key 100",
				"GET key",
				"DEL key",
				"APPEND key value",
				"GET key",
			},
			expected: []interface{}{"OK", int64(10), "valuevalue", int64(13), "valuevalue100", int64(1), int64(5), "value"},
Repository: DiceDB/dice
File: integration_tests/commands/async/append_test.go (Go)

Code before:
package async

import (
	"testing"

	"gotest.tools/v3/assert"
)

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

	setErrorMsg := "WRONGTYPE Operation against a key holding the wrong kind of value"
	testCases := []struct {
		name     string
		commands []string
		expected []interface{}
	}{
		{
			name: "APPEND After SET and DEL",
			commands: []string{
				"SET key value",
				"APPEND key value",
				"GET key",
				"APPEND key 100",
				"GET key",
				"DEL key",
				"APPEND key value",
				"GET key",
			},
			expected: []interface{}{"OK", int64(10), "valuevalue", int64(13), "valuevalue100", int64(1), int64(5), "value"},
		},
		{
			name: "APPEND to Integer Values",
			commands: []string{
				"DEL key",
				"APPEND key 1",

Review comment (suggestion):
Cleanup before and after the test to ensure stability
```suggestion

        FireCommand(conn, "DEL key listKey bitKey hashKey setKey")
	defer FireCommand(conn, "DEL key listKey bitKey hashKey setKey")

```

Code after:
package async

import (
	"testing"

	"gotest.tools/v3/assert"
)

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

	FireCommand(conn, "DEL key listKey bitKey hashKey setKey")
	defer FireCommand(conn, "DEL key listKey bitKey hashKey setKey")

	setErrorMsg := "WRONGTYPE Operation against a key holding the wrong kind of value"
	testCases := []struct {
		name     string
		commands []string
		expected []interface{}
	}{
		{
			name: "APPEND After SET and DEL",
			commands: []string{
				"SET key value",
				"APPEND key value",
				"GET key",
				"APPEND key 100",
				"GET key",
				"DEL key",
				"APPEND key value",
				"GET key",
			},
			expected: []interface{}{"OK", int64(10), "valuevalue", int64(13), "valuevalue100", int64(1), int64(5), "value"},
		},
		{
			name: "APPEND to Integer Values",