Added config flags max-memory and eviction-policy to manage memory usage. Created ParseMemory utility function to parse max-memory value into bytes. Created LFU cache to be used with heap data structure for managing LFU cache.

This commit is contained in:
Kelvin Clement Mwinuka
2024-03-01 16:25:04 +08:00
parent 97b41da729
commit e569bf6837
30 changed files with 364 additions and 228 deletions
+1
View File
@@ -32,6 +32,7 @@ CMD "./server" \
"--restore-snapshot=${RESTORE_SNAPSHOT}" \
"--restore-aof=${RESTORE_AOF}" \
"--aof-sync-strategy=${AOF_SYNC_STRATEGY}" \
"--max-memory=${MAX_MEMORY}" \
# List of server cert/key pairs
"--cert-key-pair=${CERT_KEY_PAIR_1}" \
"--cert-key-pair=${CERT_KEY_PAIR_2}" \
+1
View File
@@ -30,6 +30,7 @@ services:
- RESTORE_SNAPSHOT=false
- RESTORE_AOF=true
- AOF_SYNC_STRATEGY=everysec
- MAX_MEMORY=100kb
# List of server cert/key pairs
- CERT_KEY_PAIR_1=/etc/ssl/certs/echovault/server/server1.crt,/etc/ssl/certs/echovault/server/server1.key
- CERT_KEY_PAIR_2=/etc/ssl/certs/echovault/server/server2.crt,/etc/ssl/certs/echovault/server/server2.key
+56
View File
@@ -1 +1,57 @@
package eviction
import (
"container/heap"
"slices"
)
type EntryLFU struct {
key string // The key, matching the key in the store
count int // The number of times this key has been accessed
index int // The index of the entry in the heap
}
type Cache []*EntryLFU
func (cache *Cache) Len() int {
return len(*cache)
}
func (cache *Cache) Less(i, j int) bool {
return (*cache)[i].count > (*cache)[j].count
}
func (cache *Cache) Swap(i, j int) {
(*cache)[i], (*cache)[j] = (*cache)[j], (*cache)[i]
(*cache)[i].index = i
(*cache)[j].index = j
}
func (cache *Cache) Push(key any) {
n := len(*cache)
*cache = append(*cache, &EntryLFU{
key: key.(string),
count: 1,
index: n,
})
}
func (cache *Cache) Pop() any {
old := *cache
n := len(old)
entry := old[n-1]
old[n-1] = nil
entry.index = -1
*cache = old[0 : n-1]
return entry.key
}
func (cache *Cache) Update(key string) {
// Get the item with key
entryIdx := slices.IndexFunc(*cache, func(e *EntryLFU) bool {
return e.key == key
})
entry := (*cache)[entryIdx]
entry.count += 1
heap.Fix(cache, entryIdx)
}
+12 -12
View File
@@ -16,7 +16,7 @@ import (
func handleAuth(ctx context.Context, cmd []string, server utils.Server, conn *net.Conn) ([]byte, error) {
if len(cmd) < 2 || len(cmd) > 3 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
acl, ok := server.GetACL().(*ACL)
if !ok {
@@ -25,12 +25,12 @@ func handleAuth(ctx context.Context, cmd []string, server utils.Server, conn *ne
if err := acl.AuthenticateConnection(ctx, conn, cmd); err != nil {
return nil, err
}
return []byte(utils.OK_RESPONSE), nil
return []byte(utils.OkResponse), nil
}
func handleGetUser(ctx context.Context, cmd []string, server utils.Server, conn *net.Conn) ([]byte, error) {
if len(cmd) != 3 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
acl, ok := server.GetACL().(*ACL)
@@ -146,7 +146,7 @@ func handleGetUser(ctx context.Context, cmd []string, server utils.Server, conn
func handleCat(ctx context.Context, cmd []string, server utils.Server, conn *net.Conn) ([]byte, error) {
if len(cmd) > 3 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
categories := make(map[string][]string)
@@ -225,12 +225,12 @@ func handleSetUser(ctx context.Context, cmd []string, server utils.Server, conn
if err := acl.SetUser(ctx, cmd[2:]); err != nil {
return nil, err
}
return []byte(utils.OK_RESPONSE), nil
return []byte(utils.OkResponse), nil
}
func handleDelUser(ctx context.Context, cmd []string, server utils.Server, conn *net.Conn) ([]byte, error) {
if len(cmd) < 3 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
acl, ok := server.GetACL().(*ACL)
if !ok {
@@ -239,7 +239,7 @@ func handleDelUser(ctx context.Context, cmd []string, server utils.Server, conn
if err := acl.DeleteUser(ctx, cmd[2:]); err != nil {
return nil, err
}
return []byte(utils.OK_RESPONSE), nil
return []byte(utils.OkResponse), nil
}
func handleWhoAmI(ctx context.Context, cmd []string, server utils.Server, conn *net.Conn) ([]byte, error) {
@@ -253,7 +253,7 @@ func handleWhoAmI(ctx context.Context, cmd []string, server utils.Server, conn *
func handleList(ctx context.Context, cmd []string, server utils.Server, conn *net.Conn) ([]byte, error) {
if len(cmd) > 2 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
acl, ok := server.GetACL().(*ACL)
if !ok {
@@ -349,7 +349,7 @@ func handleList(ctx context.Context, cmd []string, server utils.Server, conn *ne
func handleLoad(ctx context.Context, cmd []string, server utils.Server, conn *net.Conn) ([]byte, error) {
if len(cmd) != 3 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
acl, ok := server.GetACL().(*ACL)
@@ -409,12 +409,12 @@ func handleLoad(ctx context.Context, cmd []string, server utils.Server, conn *ne
}
}
return []byte(utils.OK_RESPONSE), nil
return []byte(utils.OkResponse), nil
}
func handleSave(ctx context.Context, cmd []string, server utils.Server, conn *net.Conn) ([]byte, error) {
if len(cmd) > 2 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
acl, ok := server.GetACL().(*ACL)
@@ -465,7 +465,7 @@ func handleSave(ctx context.Context, cmd []string, server utils.Server, conn *ne
return nil, err
}
return []byte(utils.OK_RESPONSE), nil
return []byte(utils.OkResponse), nil
}
func Commands() []utils.Command {
+3 -3
View File
@@ -148,7 +148,7 @@ func handleCommandList(ctx context.Context, cmd []string, server utils.Server, _
res = fmt.Sprintf("*%d\r\n%s", count, res)
return []byte(res), nil
default:
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
}
@@ -226,7 +226,7 @@ Allows for filtering by ACL category or glob pattern.`,
if err := server.TakeSnapshot(); err != nil {
return nil, err
}
return []byte(utils.OK_RESPONSE), nil
return []byte(utils.OkResponse), nil
},
},
{
@@ -257,7 +257,7 @@ Allows for filtering by ACL category or glob pattern.`,
if err := server.RewriteAOF(); err != nil {
return nil, err
}
return []byte(utils.OK_RESPONSE), nil
return []byte(utils.OkResponse), nil
},
},
}
+4 -4
View File
@@ -28,7 +28,7 @@ func handleSet(ctx context.Context, cmd []string, server utils.Server, conn *net
}
server.SetValue(ctx, key, utils.AdaptType(cmd[2]))
server.KeyUnlock(key)
return []byte(utils.OK_RESPONSE), nil
return []byte(utils.OkResponse), nil
}
if _, err := server.KeyLock(ctx, key); err != nil {
@@ -38,7 +38,7 @@ func handleSet(ctx context.Context, cmd []string, server utils.Server, conn *net
server.SetValue(ctx, key, utils.AdaptType(cmd[2]))
server.KeyUnlock(key)
return []byte(utils.OK_RESPONSE), nil
return []byte(utils.OkResponse), nil
}
func handleSetNX(ctx context.Context, cmd []string, server utils.Server, conn *net.Conn) ([]byte, error) {
@@ -57,7 +57,7 @@ func handleSetNX(ctx context.Context, cmd []string, server utils.Server, conn *n
server.SetValue(ctx, key, utils.AdaptType(cmd[2]))
server.KeyUnlock(key)
return []byte(utils.OK_RESPONSE), nil
return []byte(utils.OkResponse), nil
}
func handleMSet(ctx context.Context, cmd []string, server utils.Server, conn *net.Conn) ([]byte, error) {
@@ -111,7 +111,7 @@ func handleMSet(ctx context.Context, cmd []string, server utils.Server, conn *ne
server.SetValue(ctx, k, v.value)
}
return []byte(utils.OK_RESPONSE), nil
return []byte(utils.OkResponse), nil
}
func handleCopy(ctx context.Context, cmd []string, server *utils.Server, _ *net.Conn) ([]byte, error) {
+2 -2
View File
@@ -41,13 +41,13 @@ func Test_HandleSET(t *testing.T) {
command: []string{"SET"},
expectedResponse: "",
expectedValue: nil,
expectedErr: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedErr: errors.New(utils.WrongArgsResponse),
},
{
command: []string{"SET", "test", "one", "two", "three"},
expectedResponse: "",
expectedValue: nil,
expectedErr: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedErr: errors.New(utils.WrongArgsResponse),
},
}
+2 -2
View File
@@ -7,14 +7,14 @@ import (
func setKeyFunc(cmd []string) ([]string, error) {
if len(cmd) != 3 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return []string{cmd[1]}, nil
}
func setNXKeyFunc(cmd []string) ([]string, error) {
if len(cmd) != 3 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return []string{cmd[1]}, nil
}
+3 -3
View File
@@ -68,11 +68,11 @@ func Test_HandleGET(t *testing.T) {
}{
{
command: []string{"GET"},
expected: utils.WRONG_ARGS_RESPONSE,
expected: utils.WrongArgsResponse,
},
{
command: []string{"GET", "key", "test"},
expected: utils.WRONG_ARGS_RESPONSE,
expected: utils.WrongArgsResponse,
},
}
for _, test := range errorTests {
@@ -115,7 +115,7 @@ func Test_HandleMGET(t *testing.T) {
presetValues: []string{"value5"},
command: []string{"MGET"},
expected: nil,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
+2 -2
View File
@@ -7,14 +7,14 @@ import (
func getKeyFunc(cmd []string) ([]string, error) {
if len(cmd) != 2 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return []string{cmd[1]}, nil
}
func mgetKeyFunc(cmd []string) ([]string, error) {
if len(cmd) < 2 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:], nil
}
+18 -18
View File
@@ -94,7 +94,7 @@ func Test_HandleHSET(t *testing.T) {
command: []string{"HSET", "field1"},
expectedResponse: 0,
expectedValue: map[string]interface{}{},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
@@ -193,7 +193,7 @@ func Test_HandleHINCRBY(t *testing.T) {
command: []string{"HINCRBY", "key5"},
expectedResponse: 0,
expectedValue: map[string]interface{}{},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // Command too long
preset: false,
@@ -202,7 +202,7 @@ func Test_HandleHINCRBY(t *testing.T) {
command: []string{"HINCRBY", "key6", "field1", "23", "45"},
expectedResponse: 0,
expectedValue: map[string]interface{}{},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // Error when increment by float does not pass valid float
preset: false,
@@ -336,7 +336,7 @@ func Test_HandleHGET(t *testing.T) {
command: []string{"HGET", "key4"},
expectedResponse: 0,
expectedValue: map[string]interface{}{},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
@@ -427,7 +427,7 @@ func Test_HandleHSTRLEN(t *testing.T) {
command: []string{"HSTRLEN", "key3"},
expectedResponse: 0,
expectedValue: map[string]interface{}{},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // Trying to get lengths on a non hash map returns error
preset: true,
@@ -513,7 +513,7 @@ func Test_HandleHVALS(t *testing.T) {
command: []string{"HVALS"},
expectedResponse: nil,
expectedValue: map[string]interface{}{},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // Command too long
preset: false,
@@ -522,7 +522,7 @@ func Test_HandleHVALS(t *testing.T) {
command: []string{"HVALS", "key4", "key4"},
expectedResponse: nil,
expectedValue: map[string]interface{}{},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // Trying to get lengths on a non hash map returns error
preset: true,
@@ -695,14 +695,14 @@ func Test_HandleHRANDFIELD(t *testing.T) {
key: "key10",
presetValue: map[string]interface{}{},
command: []string{"HRANDFIELD"},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // Command too long
preset: false,
key: "key11",
presetValue: map[string]interface{}{},
command: []string{"HRANDFIELD", "key11", "key11", "key11", "key11"},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // Trying to get random field on a non hash map returns error
preset: true,
@@ -819,7 +819,7 @@ func Test_HandleHLEN(t *testing.T) {
command: []string{"HLEN"},
expectedResponse: 0,
expectedValue: map[string]interface{}{},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // Command too long
preset: false,
@@ -828,7 +828,7 @@ func Test_HandleHLEN(t *testing.T) {
command: []string{"HLEN", "key4", "key4"},
expectedResponse: 0,
expectedValue: map[string]interface{}{},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // Trying to get lengths on a non hash map returns error
preset: true,
@@ -909,7 +909,7 @@ func Test_HandleHKeys(t *testing.T) {
command: []string{"HKEYS"},
expectedResponse: nil,
expectedValue: map[string]interface{}{},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // Command too long
preset: false,
@@ -918,7 +918,7 @@ func Test_HandleHKeys(t *testing.T) {
command: []string{"HKEYS", "key4", "key4"},
expectedResponse: nil,
expectedValue: map[string]interface{}{},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // Trying to get lengths on a non hash map returns error
preset: true,
@@ -1006,7 +1006,7 @@ func Test_HandleHGETALL(t *testing.T) {
command: []string{"HGETALL"},
expectedResponse: nil,
expectedValue: map[string]interface{}{},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // Command too long
preset: false,
@@ -1015,7 +1015,7 @@ func Test_HandleHGETALL(t *testing.T) {
command: []string{"HGETALL", "key4", "key4"},
expectedResponse: nil,
expectedValue: map[string]interface{}{},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // Trying to get lengths on a non hash map returns error
preset: true,
@@ -1114,7 +1114,7 @@ func Test_HandleHEXISTS(t *testing.T) {
command: []string{"HEXISTS", "key3"},
expectedResponse: nil,
expectedValue: map[string]interface{}{},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // Command too long
preset: false,
@@ -1123,7 +1123,7 @@ func Test_HandleHEXISTS(t *testing.T) {
command: []string{"HEXISTS", "key4", "field1", "field2"},
expectedResponse: nil,
expectedValue: map[string]interface{}{},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // Trying to get lengths on a non hash map returns error
preset: true,
@@ -1213,7 +1213,7 @@ func Test_HandleHDEL(t *testing.T) {
command: []string{"HDEL", "key4"},
expectedResponse: nil,
expectedValue: map[string]interface{}{},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // Trying to get lengths on a non hash map returns error
preset: true,
+12 -12
View File
@@ -7,42 +7,42 @@ import (
func hsetKeyFunc(cmd []string) ([]string, error) {
if len(cmd) < 4 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:2], nil
}
func hsetnxKeyFunc(cmd []string) ([]string, error) {
if len(cmd) < 4 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:2], nil
}
func hgetKeyFunc(cmd []string) ([]string, error) {
if len(cmd) < 3 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:2], nil
}
func hstrlenKeyFunc(cmd []string) ([]string, error) {
if len(cmd) < 3 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:2], nil
}
func hvalsKeyFunc(cmd []string) ([]string, error) {
if len(cmd) != 2 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:], nil
}
func hrandfieldKeyFunc(cmd []string) ([]string, error) {
if len(cmd) < 2 || len(cmd) > 4 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
if len(cmd) == 2 {
return cmd[1:], nil
@@ -52,42 +52,42 @@ func hrandfieldKeyFunc(cmd []string) ([]string, error) {
func hlenKeyFunc(cmd []string) ([]string, error) {
if len(cmd) != 2 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:], nil
}
func hkeysKeyFunc(cmd []string) ([]string, error) {
if len(cmd) != 2 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:], nil
}
func hincrbyKeyFunc(cmd []string) ([]string, error) {
if len(cmd) != 4 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:2], nil
}
func hgetallKeyFunc(cmd []string) ([]string, error) {
if len(cmd) != 2 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:], nil
}
func hexistsKeyFunc(cmd []string) ([]string, error) {
if len(cmd) != 3 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:2], nil
}
func hdelKeyFunc(cmd []string) ([]string, error) {
if len(cmd) < 3 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:2], nil
}
+7 -7
View File
@@ -183,7 +183,7 @@ func handleLSet(ctx context.Context, cmd []string, server utils.Server, conn *ne
list[index] = utils.AdaptType(cmd[3])
server.SetValue(ctx, key, list)
return []byte(utils.OK_RESPONSE), nil
return []byte(utils.OkResponse), nil
}
func handleLTrim(ctx context.Context, cmd []string, server utils.Server, conn *net.Conn) ([]byte, error) {
@@ -224,11 +224,11 @@ func handleLTrim(ctx context.Context, cmd []string, server utils.Server, conn *n
if end == -1 || end > len(list) {
server.SetValue(ctx, key, list[start:])
return []byte(utils.OK_RESPONSE), nil
return []byte(utils.OkResponse), nil
}
server.SetValue(ctx, key, list[start:end])
return []byte(utils.OK_RESPONSE), nil
return []byte(utils.OkResponse), nil
}
func handleLRem(ctx context.Context, cmd []string, server utils.Server, conn *net.Conn) ([]byte, error) {
@@ -294,7 +294,7 @@ func handleLRem(ctx context.Context, cmd []string, server utils.Server, conn *ne
server.SetValue(ctx, key, list)
return []byte(utils.OK_RESPONSE), nil
return []byte(utils.OkResponse), nil
}
func handleLMove(ctx context.Context, cmd []string, server utils.Server, conn *net.Conn) ([]byte, error) {
@@ -351,7 +351,7 @@ func handleLMove(ctx context.Context, cmd []string, server utils.Server, conn *n
}
}
return []byte(utils.OK_RESPONSE), nil
return []byte(utils.OkResponse), nil
}
func handleLPush(ctx context.Context, cmd []string, server utils.Server, conn *net.Conn) ([]byte, error) {
@@ -393,7 +393,7 @@ func handleLPush(ctx context.Context, cmd []string, server utils.Server, conn *n
}
server.SetValue(ctx, key, append(newElems, l...))
return []byte(utils.OK_RESPONSE), nil
return []byte(utils.OkResponse), nil
}
func handleRPush(ctx context.Context, cmd []string, server utils.Server, conn *net.Conn) ([]byte, error) {
@@ -436,7 +436,7 @@ func handleRPush(ctx context.Context, cmd []string, server utils.Server, conn *n
}
server.SetValue(ctx, key, append(l, newElems...))
return []byte(utils.OK_RESPONSE), nil
return []byte(utils.OkResponse), nil
}
func handlePop(ctx context.Context, cmd []string, server utils.Server, conn *net.Conn) ([]byte, error) {
+18 -18
View File
@@ -47,7 +47,7 @@ func Test_HandleLLEN(t *testing.T) {
command: []string{"LLEN"},
expectedResponse: 0,
expectedValue: nil,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // Command too long
preset: false,
@@ -56,7 +56,7 @@ func Test_HandleLLEN(t *testing.T) {
command: []string{"LLEN", "key4", "key4"},
expectedResponse: 0,
expectedValue: nil,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // Trying to get lengths on a non-list returns error
preset: true,
@@ -150,7 +150,7 @@ func Test_HandleLINDEX(t *testing.T) {
command: []string{"LINDEX", "key3"},
expectedResponse: 0,
expectedValue: nil,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // Command too long
preset: false,
@@ -159,7 +159,7 @@ func Test_HandleLINDEX(t *testing.T) {
command: []string{"LINDEX", "key4", "0", "20"},
expectedResponse: 0,
expectedValue: nil,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // Trying to get element by index on a non-list returns error
preset: true,
@@ -283,7 +283,7 @@ func Test_HandleLRANGE(t *testing.T) {
command: []string{"LRANGE", "key5"},
expectedResponse: nil,
expectedValue: nil,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // Command too long
preset: false,
@@ -292,7 +292,7 @@ func Test_HandleLRANGE(t *testing.T) {
command: []string{"LRANGE", "key6", "0", "element", "element"},
expectedResponse: nil,
expectedValue: nil,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // Error when executing command on non-list command
preset: true,
@@ -437,7 +437,7 @@ func Test_HandleLSET(t *testing.T) {
command: []string{"LSET", "key5"},
expectedResponse: 0,
expectedValue: nil,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // Command too long
preset: false,
@@ -446,7 +446,7 @@ func Test_HandleLSET(t *testing.T) {
command: []string{"LSET", "key6", "0", "element", "element"},
expectedResponse: 0,
expectedValue: nil,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // Trying to get element by index on a non-list returns error
preset: true,
@@ -586,7 +586,7 @@ func Test_HandleLTRIM(t *testing.T) {
command: []string{"LTRIM", "key5"},
expectedResponse: 0,
expectedValue: nil,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // Command too long
preset: false,
@@ -595,7 +595,7 @@ func Test_HandleLTRIM(t *testing.T) {
command: []string{"LTRIM", "key6", "0", "element", "element"},
expectedResponse: 0,
expectedValue: nil,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // Trying to get element by index on a non-list returns error
preset: true,
@@ -723,7 +723,7 @@ func Test_HandleLREM(t *testing.T) {
command: []string{"LREM", "key5"},
expectedResponse: nil,
expectedValue: nil,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // Command too long
preset: false,
@@ -732,7 +732,7 @@ func Test_HandleLREM(t *testing.T) {
command: []string{"LREM", "key6", "0", "element", "element"},
expectedResponse: nil,
expectedValue: nil,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // Throw error when count is not an integer
preset: false,
@@ -939,7 +939,7 @@ func Test_HandleLMOVE(t *testing.T) {
command: []string{"LMOVE", "source9", "destination9"},
expectedResponse: nil,
expectedValue: map[string]interface{}{},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{
// 10. Throw error when command is too long
@@ -948,7 +948,7 @@ func Test_HandleLMOVE(t *testing.T) {
command: []string{"LMOVE", "source10", "destination10", "LEFT", "LEFT", "RIGHT"},
expectedResponse: nil,
expectedValue: map[string]interface{}{},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{
// 11. Throw error when WHEREFROM argument is not LEFT/RIGHT
@@ -1066,7 +1066,7 @@ func Test_HandleLPUSH(t *testing.T) {
command: []string{"LPUSH", "key5"},
expectedResponse: nil,
expectedValue: nil,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // LPUSHX command returns error on non-existent list
preset: false,
@@ -1167,7 +1167,7 @@ func Test_HandleRPUSH(t *testing.T) {
command: []string{"RPUSH", "key5"},
expectedResponse: nil,
expectedValue: nil,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // RPUSHX command returns error on non-existent list
preset: false,
@@ -1259,7 +1259,7 @@ func Test_HandlePop(t *testing.T) {
command: []string{"LPOP"},
expectedResponse: 0,
expectedValue: nil,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // Command too long
preset: false,
@@ -1268,7 +1268,7 @@ func Test_HandlePop(t *testing.T) {
command: []string{"LPOP", "key4", "key4"},
expectedResponse: 0,
expectedValue: nil,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // Trying to execute LPOP from a non-list item return an error
preset: true,
+10 -10
View File
@@ -7,70 +7,70 @@ import (
func lpushKeyFunc(cmd []string) ([]string, error) {
if len(cmd) < 3 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return []string{cmd[1]}, nil
}
func popKeyFunc(cmd []string) ([]string, error) {
if len(cmd) != 2 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return []string{cmd[1]}, nil
}
func llenKeyFunc(cmd []string) ([]string, error) {
if len(cmd) != 2 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return []string{cmd[1]}, nil
}
func lrangeKeyFunc(cmd []string) ([]string, error) {
if len(cmd) != 4 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return []string{cmd[1]}, nil
}
func lindexKeyFunc(cmd []string) ([]string, error) {
if len(cmd) != 3 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return []string{cmd[1]}, nil
}
func lsetKeyFunc(cmd []string) ([]string, error) {
if len(cmd) != 4 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return []string{cmd[1]}, nil
}
func ltrimKeyFunc(cmd []string) ([]string, error) {
if len(cmd) != 4 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return []string{cmd[1]}, nil
}
func lremKeyFunc(cmd []string) ([]string, error) {
if len(cmd) != 4 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return []string{cmd[1]}, nil
}
func rpushKeyFunc(cmd []string) ([]string, error) {
if len(cmd) < 3 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return []string{cmd[1]}, nil
}
func lmoveKeyFunc(cmd []string) ([]string, error) {
if len(cmd) != 5 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return []string{cmd[1], cmd[2]}, nil
}
+1 -1
View File
@@ -11,7 +11,7 @@ import (
func handlePing(ctx context.Context, cmd []string, server utils.Server, conn *net.Conn) ([]byte, error) {
switch len(cmd) {
default:
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
case 1:
return []byte("+PONG\r\n"), nil
case 2:
+1 -1
View File
@@ -32,7 +32,7 @@ func Test_HandlePing(t *testing.T) {
{
command: []string{"PING", "Hello, world!", "Once more"},
expected: "",
expectedErr: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedErr: errors.New(utils.WrongArgsResponse),
},
}
+7 -7
View File
@@ -18,7 +18,7 @@ func handleSubscribe(ctx context.Context, cmd []string, server utils.Server, con
channels := cmd[1:]
if len(channels) == 0 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
switch strings.ToLower(cmd[0]) {
@@ -55,15 +55,15 @@ func handlePublish(ctx context.Context, cmd []string, server utils.Server, conn
return nil, errors.New("could not load pubsub module")
}
if len(cmd) != 3 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
pubsub.Publish(ctx, cmd[2], cmd[1])
return []byte(utils.OK_RESPONSE), nil
return []byte(utils.OkResponse), nil
}
func handlePubSubChannels(ctx context.Context, cmd []string, server utils.Server, conn *net.Conn) ([]byte, error) {
if len(cmd) > 3 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
pubsub, ok := server.GetPubSub().(*PubSub)
@@ -106,7 +106,7 @@ func Commands() []utils.Command {
KeyExtractionFunc: func(cmd []string) ([]string, error) {
// Treat the channels as keys
if len(cmd) < 2 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:], nil
},
@@ -120,7 +120,7 @@ func Commands() []utils.Command {
KeyExtractionFunc: func(cmd []string) ([]string, error) {
// Treat the patterns as keys
if len(cmd) < 2 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:], nil
},
@@ -134,7 +134,7 @@ func Commands() []utils.Command {
KeyExtractionFunc: func(cmd []string) ([]string, error) {
// Treat the channel as a key
if len(cmd) != 3 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return []string{cmd[1]}, nil
},
+1 -1
View File
@@ -272,7 +272,7 @@ func handleSINTERCARD(ctx context.Context, cmd []string, server utils.Server, co
return strings.EqualFold(s, "limit")
})
if limitIdx >= 0 && limitIdx < 2 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
if limitIdx != -1 {
limitIdx += 1
+22 -22
View File
@@ -55,7 +55,7 @@ func Test_HandleSADD(t *testing.T) {
command: []string{"SADD", "key4"},
expectedValue: nil,
expectedResponse: 0,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
@@ -148,7 +148,7 @@ func Test_HandleSCARD(t *testing.T) {
command: []string{"SCARD"},
expectedValue: nil,
expectedResponse: 0,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // 5. Command too long
preset: false,
@@ -156,7 +156,7 @@ func Test_HandleSCARD(t *testing.T) {
command: []string{"SCARD", "key5", "key5"},
expectedValue: nil,
expectedResponse: 0,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
@@ -256,7 +256,7 @@ func Test_HandleSDIFF(t *testing.T) {
preset: false,
command: []string{"SDIFF"},
expectedResponse: []string{},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
@@ -372,7 +372,7 @@ func Test_HandleSDIFFSTORE(t *testing.T) {
preset: false,
command: []string{"SDIFFSTORE", "destination6"},
expectedResponse: 0,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
@@ -489,7 +489,7 @@ func Test_HandleSINTER(t *testing.T) {
preset: false,
command: []string{"SINTER"},
expectedResponse: []string{},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
@@ -604,7 +604,7 @@ func Test_HandleSINTERCARD(t *testing.T) {
preset: false,
command: []string{"SINTERSTORE"},
expectedResponse: 0,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
@@ -718,7 +718,7 @@ func Test_HandleSINTERSTORE(t *testing.T) {
preset: false,
command: []string{"SINTERSTORE", "destination6"},
expectedResponse: 0,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
@@ -808,14 +808,14 @@ func Test_HandleSISMEMBER(t *testing.T) {
key: "key4",
command: []string{"SISMEMBER", "key4"},
expectedResponse: 0,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // 5. Command too long
preset: false,
key: "key5",
command: []string{"SISMEMBER", "key5", "one", "two", "three"},
expectedResponse: 0,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
@@ -887,13 +887,13 @@ func Test_HandleSMEMBERS(t *testing.T) {
preset: false,
command: []string{"SMEMBERS"},
expectedResponse: []string{},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // 5. Command too long
preset: false,
command: []string{"SMEMBERS", "key5", "key6"},
expectedResponse: []string{},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
@@ -975,7 +975,7 @@ func Test_HandleSMISMEMBER(t *testing.T) {
key: "key4",
command: []string{"SMISMEMBER", "key4"},
expectedResponse: nil,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
@@ -1081,12 +1081,12 @@ func Test_HandleSMOVE(t *testing.T) {
{ // 5. Command too short
preset: false,
command: []string{"SMOVE", "source5", "source6"},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // 6. Command too long
preset: false,
command: []string{"SMOVE", "source5", "source6", "member1", "member2"},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
@@ -1176,12 +1176,12 @@ func Test_HandleSPOP(t *testing.T) {
{ // 5. Command too short
preset: false,
command: []string{"SPOP"},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // 6. Command too long
preset: false,
command: []string{"SPOP", "source5", "source6", "member1", "member2"},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // 7. Throw error when count is not an integer
preset: false,
@@ -1287,12 +1287,12 @@ func Test_HandleSRANDMEMBER(t *testing.T) {
{ // 5. Command too short
preset: false,
command: []string{"SRANDMEMBER"},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // 6. Command too long
preset: false,
command: []string{"SRANDMEMBER", "source5", "source6", "member1", "member2"},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // 7. Throw error when count is not an integer
preset: false,
@@ -1403,7 +1403,7 @@ func Test_HandleSREM(t *testing.T) {
{ // 4. Command too short
preset: false,
command: []string{"SREM", "key"},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
@@ -1511,7 +1511,7 @@ func Test_HandleSUNION(t *testing.T) {
preset: false,
command: []string{"SUNION"},
expectedResponse: []string{},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
@@ -1605,7 +1605,7 @@ func Test_HandleSUNIONSTORE(t *testing.T) {
preset: false,
command: []string{"SUNIONSTORE", "destination6"},
expectedResponse: 0,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
+16 -16
View File
@@ -9,42 +9,42 @@ import (
func saddKeyFunc(cmd []string) ([]string, error) {
if len(cmd) < 3 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return []string{cmd[1]}, nil
}
func scardKeyFunc(cmd []string) ([]string, error) {
if len(cmd) != 2 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return []string{cmd[1]}, nil
}
func sdiffKeyFunc(cmd []string) ([]string, error) {
if len(cmd) < 2 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:], nil
}
func sdiffstoreKeyFunc(cmd []string) ([]string, error) {
if len(cmd) < 3 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:], nil
}
func sinterKeyFunc(cmd []string) ([]string, error) {
if len(cmd) < 2 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:], nil
}
func sintercardKeyFunc(cmd []string) ([]string, error) {
if len(cmd) < 2 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
limitIdx := slices.IndexFunc(cmd, func(s string) bool {
@@ -60,70 +60,70 @@ func sintercardKeyFunc(cmd []string) ([]string, error) {
func sinterstoreKeyFunc(cmd []string) ([]string, error) {
if len(cmd) < 3 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:], nil
}
func sismemberKeyFunc(cmd []string) ([]string, error) {
if len(cmd) != 3 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:], nil
}
func smembersKeyFunc(cmd []string) ([]string, error) {
if len(cmd) != 2 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return []string{cmd[1]}, nil
}
func smismemberKeyFunc(cmd []string) ([]string, error) {
if len(cmd) < 3 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return []string{cmd[1]}, nil
}
func smoveKeyFunc(cmd []string) ([]string, error) {
if len(cmd) != 4 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:3], nil
}
func spopKeyFunc(cmd []string) ([]string, error) {
if len(cmd) < 2 || len(cmd) > 3 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:2], nil
}
func srandmemberKeyFunc(cmd []string) ([]string, error) {
if len(cmd) < 2 || len(cmd) > 3 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:2], nil
}
func sremKeyFunc(cmd []string) ([]string, error) {
if len(cmd) < 3 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return []string{cmd[1]}, nil
}
func sunionKeyFunc(cmd []string) ([]string, error) {
if len(cmd) < 2 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:], nil
}
func sunionstoreKeyFunc(cmd []string) ([]string, error) {
if len(cmd) < 3 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:], nil
}
+3 -3
View File
@@ -309,7 +309,7 @@ func handleZDIFF(ctx context.Context, cmd []string, server utils.Server, conn *n
return strings.EqualFold(s, "withscores")
})
if withscoresIndex > -1 && withscoresIndex < 2 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
locks := make(map[string]bool)
@@ -638,7 +638,7 @@ func handleZMPOP(ctx context.Context, cmd []string, server utils.Server, conn *n
})
if countIdx != -1 {
if countIdx < 2 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
if countIdx == len(cmd)-1 {
return nil, errors.New("count must be a positive integer")
@@ -660,7 +660,7 @@ func handleZMPOP(ctx context.Context, cmd []string, server utils.Server, conn *n
})
if policyIdx != -1 {
if policyIdx < 2 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
policy = strings.ToLower(cmd[policyIdx])
if modifierIdx == -1 || (policyIdx < modifierIdx) {
+40 -40
View File
@@ -196,7 +196,7 @@ func Test_HandleZADD(t *testing.T) {
command: []string{"ZADD", "key11"},
expectedValue: nil,
expectedResponse: 0,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // 12. Throw error when score/member entries are do not match
preset: false,
@@ -303,7 +303,7 @@ func Test_HandleZCARD(t *testing.T) {
command: []string{"ZCARD"},
expectedValue: nil,
expectedResponse: 0,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // 4. Command too long
preset: false,
@@ -312,7 +312,7 @@ func Test_HandleZCARD(t *testing.T) {
command: []string{"ZCARD", "key4", "key5"},
expectedValue: nil,
expectedResponse: 0,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // 5. Return error when not a sorted set
preset: true,
@@ -442,7 +442,7 @@ func Test_HandleZCOUNT(t *testing.T) {
command: []string{"ZCOUNT"},
expectedValue: nil,
expectedResponse: 0,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // 7. Command too long
preset: false,
@@ -451,7 +451,7 @@ func Test_HandleZCOUNT(t *testing.T) {
command: []string{"ZCOUNT", "key4", "min", "max", "count"},
expectedValue: nil,
expectedResponse: 0,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // 8. Throw error when value at the key is not a sorted set
preset: true,
@@ -564,7 +564,7 @@ func Test_HandleZLEXCOUNT(t *testing.T) {
command: []string{"ZLEXCOUNT"},
expectedValue: nil,
expectedResponse: 0,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // 6. Command too long
preset: false,
@@ -573,7 +573,7 @@ func Test_HandleZLEXCOUNT(t *testing.T) {
command: []string{"ZLEXCOUNT", "key6", "min", "max", "count"},
expectedValue: nil,
expectedResponse: 0,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
@@ -724,7 +724,7 @@ func Test_HandleZDIFF(t *testing.T) {
preset: false,
command: []string{"ZDIFF"},
expectedResponse: [][]string{},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
@@ -899,7 +899,7 @@ func Test_HandleZDIFFSTORE(t *testing.T) {
preset: false,
command: []string{"ZDIFFSTORE", "destination6"},
expectedResponse: 0,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
@@ -1109,13 +1109,13 @@ func Test_HandleZINCRBY(t *testing.T) {
key: "key11",
command: []string{"ZINCRBY", "key11", "one"},
expectedResponse: "",
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // 12. Command too long
key: "key12",
command: []string{"ZINCRBY", "key12", "one", "1", "2"},
expectedResponse: "",
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
@@ -1335,7 +1335,7 @@ func Test_HandleZMPOP(t *testing.T) {
{ // 9. Command too short
preset: false,
command: []string{"ZMPOP"},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
@@ -1501,12 +1501,12 @@ func Test_HandleZPOP(t *testing.T) {
{ // 6. Command too short
preset: false,
command: []string{"ZPOPMAX"},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // 7. Command too long
preset: false,
command: []string{"ZPOPMAX", "key7", "6", "3"},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
@@ -1606,7 +1606,7 @@ func Test_HandleZMSCORE(t *testing.T) {
{ // 9. Command too short
preset: false,
command: []string{"ZMSCORE"},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
@@ -1701,12 +1701,12 @@ func Test_HandleZSCORE(t *testing.T) {
{ // 5. Command too short
preset: false,
command: []string{"ZSCORE"},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // 6. Command too long
preset: false,
command: []string{"ZSCORE", "key5", "one", "two"},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
@@ -1806,12 +1806,12 @@ func Test_HandleZRANDMEMBER(t *testing.T) {
{ // 5. Command too short
preset: false,
command: []string{"ZRANDMEMBER"},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // 6. Command too long
preset: false,
command: []string{"ZRANDMEMBER", "source5", "source6", "member1", "member2"},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // 7. Throw error when count is not an integer
preset: false,
@@ -1971,12 +1971,12 @@ func Test_HandleZRANK(t *testing.T) {
{ // 5. Command too short
preset: false,
command: []string{"ZRANK"},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // 6. Command too long
preset: false,
command: []string{"ZRANK", "key5", "one", "WITHSCORES", "two"},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
@@ -2074,7 +2074,7 @@ func Test_HandleZREM(t *testing.T) {
{ // 9. Command too short
preset: false,
command: []string{"ZREM"},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
@@ -2175,12 +2175,12 @@ func Test_HandleZREMRANGEBYSCORE(t *testing.T) {
{ // 4. Command too short
preset: false,
command: []string{"ZREMRANGEBYSCORE", "key4", "3"},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // 5. Command too long
preset: false,
command: []string{"ZREMRANGEBYSCORE", "key5", "4", "5", "8"},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
@@ -2303,7 +2303,7 @@ func Test_HandleZREMRANGEBYRANK(t *testing.T) {
{ // 4. Command too short
preset: false,
command: []string{"ZREMRANGEBYRANK", "key4", "3"},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // 5. Return error when start index is out of bounds
preset: true,
@@ -2340,7 +2340,7 @@ func Test_HandleZREMRANGEBYRANK(t *testing.T) {
{ // 7. Command too long
preset: false,
command: []string{"ZREMRANGEBYRANK", "key7", "4", "5", "8"},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
@@ -2466,12 +2466,12 @@ func Test_HandleZREMRANGEBYLEX(t *testing.T) {
{ // 4. Command too short
preset: false,
command: []string{"ZREMRANGEBYLEX", "key4", "a"},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // 5. Command too long
preset: false,
command: []string{"ZREMRANGEBYLEX", "key5", "a", "b", "c"},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
@@ -2709,14 +2709,14 @@ func Test_HandleZRANGE(t *testing.T) {
presetValues: nil,
command: []string{"ZRANGE", "key15", "1"},
expectedResponse: [][]string{},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // 16 Command too long
preset: false,
presetValues: nil,
command: []string{"ZRANGE", "key16", "a", "h", "BYLEX", "WITHSCORES", "LIMIT", "-4", "9", "REV", "WITHSCORES"},
expectedResponse: [][]string{},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
@@ -2991,14 +2991,14 @@ func Test_HandleZRANGESTORE(t *testing.T) {
presetValues: nil,
command: []string{"ZRANGE", "key15", "1"},
expectedResponse: 0,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // 16 Command too long
preset: false,
presetValues: nil,
command: []string{"ZRANGE", "destination16", "key16", "a", "h", "BYLEX", "WITHSCORES", "LIMIT", "-4", "9", "REV", "WITHSCORES"},
expectedResponse: 0,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
@@ -3272,7 +3272,7 @@ func Test_HandleZINTER(t *testing.T) {
},
command: []string{"ZINTER", "WEIGHTS", "5", "4"},
expectedResponse: nil,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // 11. Throw an error if any of the provided keys are not sorted sets
preset: true,
@@ -3312,7 +3312,7 @@ func Test_HandleZINTER(t *testing.T) {
preset: false,
command: []string{"ZINTER"},
expectedResponse: [][]string{},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
@@ -3617,7 +3617,7 @@ func Test_HandleZINTERSTORE(t *testing.T) {
},
command: []string{"ZINTERSTORE", "WEIGHTS", "5", "4"},
expectedResponse: 0,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // 11. Throw an error if any of the provided keys are not sorted sets
preset: true,
@@ -3657,7 +3657,7 @@ func Test_HandleZINTERSTORE(t *testing.T) {
preset: false,
command: []string{"ZINTERSTORE"},
expectedResponse: 0,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
@@ -3956,7 +3956,7 @@ func Test_HandleZUNION(t *testing.T) {
},
command: []string{"ZUNION", "WEIGHTS", "5", "4"},
expectedResponse: nil,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // 11. Throw an error if any of the provided keys are not sorted sets
preset: true,
@@ -3998,7 +3998,7 @@ func Test_HandleZUNION(t *testing.T) {
{ // 13. Command too short
preset: false,
command: []string{"ZUNION"},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
@@ -4335,7 +4335,7 @@ func Test_HandleZUNIONSTORE(t *testing.T) {
},
command: []string{"ZUNIONSTORE", "WEIGHTS", "5", "4"},
expectedResponse: 0,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // 11. Throw an error if any of the provided keys are not sorted sets
preset: true,
@@ -4382,7 +4382,7 @@ func Test_HandleZUNIONSTORE(t *testing.T) {
preset: false,
command: []string{"ZUNIONSTORE"},
expectedResponse: 0,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
+29 -29
View File
@@ -9,28 +9,28 @@ import (
func zaddKeyFunc(cmd []string) ([]string, error) {
if len(cmd) < 4 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:2], nil
}
func zcardKeyFunc(cmd []string) ([]string, error) {
if len(cmd) != 2 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:], nil
}
func zcountKeyFunc(cmd []string) ([]string, error) {
if len(cmd) != 4 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:2], nil
}
func zdiffKeyFunc(cmd []string) ([]string, error) {
if len(cmd) < 2 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
withscoresIndex := slices.IndexFunc(cmd, func(s string) bool {
@@ -46,21 +46,21 @@ func zdiffKeyFunc(cmd []string) ([]string, error) {
func zdiffstoreKeyFunc(cmd []string) ([]string, error) {
if len(cmd) < 3 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[2:], nil
}
func zincrbyKeyFunc(cmd []string) ([]string, error) {
if len(cmd) != 4 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:2], nil
}
func zinterKeyFunc(cmd []string) ([]string, error) {
if len(cmd) < 2 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
endIdx := slices.IndexFunc(cmd[1:], func(s string) bool {
if strings.EqualFold(s, "WEIGHTS") ||
@@ -76,12 +76,12 @@ func zinterKeyFunc(cmd []string) ([]string, error) {
if endIdx >= 1 {
return cmd[1:endIdx], nil
}
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
func zinterstoreKeyFunc(cmd []string) ([]string, error) {
if len(cmd) < 2 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
endIdx := slices.IndexFunc(cmd[1:], func(s string) bool {
if strings.EqualFold(s, "WEIGHTS") ||
@@ -97,12 +97,12 @@ func zinterstoreKeyFunc(cmd []string) ([]string, error) {
if endIdx >= 2 {
return cmd[1:endIdx], nil
}
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
func zmpopKeyFunc(cmd []string) ([]string, error) {
if len(cmd) < 2 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
endIdx := slices.IndexFunc(cmd, func(s string) bool {
return slices.Contains([]string{"MIN", "MAX", "COUNT"}, strings.ToUpper(s))
@@ -113,103 +113,103 @@ func zmpopKeyFunc(cmd []string) ([]string, error) {
if endIdx >= 2 {
return cmd[1:endIdx], nil
}
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
func zmscoreKeyFunc(cmd []string) ([]string, error) {
if len(cmd) < 3 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:2], nil
}
func zpopKeyFunc(cmd []string) ([]string, error) {
if len(cmd) < 2 || len(cmd) > 3 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:2], nil
}
func zrandmemberKeyFunc(cmd []string) ([]string, error) {
if len(cmd) < 2 || len(cmd) > 4 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:2], nil
}
func zrankKeyFunc(cmd []string) ([]string, error) {
if len(cmd) < 3 || len(cmd) > 4 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:2], nil
}
func zremKeyFunc(cmd []string) ([]string, error) {
if len(cmd) < 3 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:2], nil
}
func zrevrankKeyFunc(cmd []string) ([]string, error) {
if len(cmd) < 3 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:2], nil
}
func zscoreKeyFunc(cmd []string) ([]string, error) {
if len(cmd) != 3 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:2], nil
}
func zremrangebylexKeyFunc(cmd []string) ([]string, error) {
if len(cmd) != 4 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:2], nil
}
func zremrangebyrankKeyFunc(cmd []string) ([]string, error) {
if len(cmd) != 4 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:2], nil
}
func zremrangebyscoreKeyFunc(cmd []string) ([]string, error) {
if len(cmd) != 4 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:2], nil
}
func zlexcountKeyFunc(cmd []string) ([]string, error) {
if len(cmd) != 4 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:2], nil
}
func zrangeKeyCount(cmd []string) ([]string, error) {
if len(cmd) < 4 || len(cmd) > 10 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:2], nil
}
func zrangeStoreKeyFunc(cmd []string) ([]string, error) {
if len(cmd) < 5 || len(cmd) > 11 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return cmd[1:3], nil
}
func zunionKeyFunc(cmd []string) ([]string, error) {
if len(cmd) < 2 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
endIdx := slices.IndexFunc(cmd[1:], func(s string) bool {
if strings.EqualFold(s, "WEIGHTS") ||
@@ -225,12 +225,12 @@ func zunionKeyFunc(cmd []string) ([]string, error) {
if endIdx >= 1 {
return cmd[1:endIdx], nil
}
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
func zunionstoreKeyFunc(cmd []string) ([]string, error) {
if len(cmd) < 2 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
endIdx := slices.IndexFunc(cmd[1:], func(s string) bool {
if strings.EqualFold(s, "WEIGHTS") ||
@@ -246,5 +246,5 @@ func zunionstoreKeyFunc(cmd []string) ([]string, error) {
if endIdx >= 1 {
return cmd[1:endIdx], nil
}
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
+6 -6
View File
@@ -95,13 +95,13 @@ func Test_HandleSetRange(t *testing.T) {
preset: false,
command: []string{"SETRANGE", "key"},
expectedResponse: 0,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // Command too long
preset: false,
command: []string{"SETRANGE", "key", "offset", "value", "value1"},
expectedResponse: 0,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
@@ -182,7 +182,7 @@ func Test_HandleStrLen(t *testing.T) {
presetValue: "",
command: []string{"STRLEN"},
expectedResponse: 0,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // Too many args
preset: false,
@@ -190,7 +190,7 @@ func Test_HandleStrLen(t *testing.T) {
presetValue: "",
command: []string{"STRLEN", "test4", "test5"},
expectedResponse: 0,
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
}
@@ -286,12 +286,12 @@ func Test_HandleSubStr(t *testing.T) {
},
{ // Command too short
command: []string{"SUBSTR", "key", "10"},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{
// Command too long
command: []string{"SUBSTR", "key", "10", "15", "20"},
expectedError: errors.New(utils.WRONG_ARGS_RESPONSE),
expectedError: errors.New(utils.WrongArgsResponse),
},
{ // Start index is not an integer
command: []string{"SUBSTR", "key", "start", "10"},
+3 -3
View File
@@ -7,21 +7,21 @@ import (
func setRangeKeyFunc(cmd []string) ([]string, error) {
if len(cmd) != 4 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return []string{cmd[1]}, nil
}
func strLenKeyFunc(cmd []string) ([]string, error) {
if len(cmd) != 2 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return []string{cmd[1]}, nil
}
func subStrKeyFunc(cmd []string) ([]string, error) {
if len(cmd) != 4 {
return nil, errors.New(utils.WRONG_ARGS_RESPONSE)
return nil, errors.New(utils.WrongArgsResponse)
}
return []string{cmd[1]}, nil
}
+1 -3
View File
@@ -36,8 +36,6 @@ func (server *Server) handleCommand(ctx context.Context, message []byte, conn *n
return nil, err
}
fmt.Println(cmd)
command, err := server.getCommand(cmd[0])
if err != nil {
return nil, err
@@ -96,7 +94,7 @@ func (server *Server) handleCommand(ctx context.Context, message []byte, conn *n
// Forward message to leader and return immediate OK response
if server.Config.ForwardCommand {
server.memberList.ForwardDataMutation(ctx, message)
return []byte(utils.OK_RESPONSE), nil
return []byte(utils.OkResponse), nil
}
return nil, errors.New("not cluster leader, cannot carry out command")
+40 -1
View File
@@ -4,6 +4,7 @@ import (
"encoding/json"
"errors"
"flag"
"fmt"
"log"
"os"
"path"
@@ -37,6 +38,8 @@ type Config struct {
RestoreSnapshot bool `json:"RestoreSnapshot" yaml:"RestoreSnapshot"`
RestoreAOF bool `json:"RestoreAOF" yaml:"RestoreAOF"`
AOFSyncStrategy string `json:"AOFSyncStrategy" yaml:"AOFSyncStrategy"`
MaxMemory int `json:"MaxMemory" yaml:"MaxMemory"`
EvictionPolicy string `json:"EvictionPolicy" yaml:"EvictionPolicy"`
}
func GetConfig() (Config, error) {
@@ -75,7 +78,41 @@ The options are 'always' for syncing on each command, 'everysec' to sync every s
return nil
})
tls := flag.Bool("tls", false, "Start the server in TLS mode. Default is false")
maxMemory := -1
flag.Func("max-memory", `Upper memory limit before triggering eviction.
Supported units (kb, mb, gb, tb, pb). There is no limit by default.`, func(memory string) error {
b, err := ParseMemory(memory)
if err != nil {
return err
}
maxMemory = b
return nil
})
evictionPolicy := NoEviction
flag.Func("eviction-policy", `The eviction policy used to remove keys when max-memory is reached. The options are:
1) noeviction - Do not evict any keys even when max-memory is exceeded.
2) allkeys-lfu - Evict the least frequently used keys.
3) allkeys-lru - Evict the least recently used keys.
4) volatile-lfu - Evict the least frequently used keys with an expiration.
5) volatile-lru - Evict the least recently used keys with an expiration.
6) allkeys-random - Evict random keys until we get under the max-memory limit.
7) volatile-random - Evict random keys with an expiration.
8) volatile-ttl - Evict the keys with the shortest remaining ttl.`, func(policy string) error {
policies := []string{
NoEviction,
AllKeysLFU, AllKeysLRU, AllKeysRandom,
VolatileLFU, VolatileLRU, VolatileRandom, VolatileTTL,
}
policyIdx := slices.Index(policies, strings.ToLower(policy))
if policyIdx == -1 {
return fmt.Errorf("policy %s is not a valid policy", policy)
}
evictionPolicy = strings.ToLower(policy)
return nil
})
tls := flag.Bool("tls", false, "Start the server in TLS mode. Default is false.")
mtls := flag.Bool("mtls", false, "Use mTLS to verify the client.")
port := flag.Int("port", 7480, "Port to use. Default is 7480")
serverId := flag.String("server-id", "1", "Server ID in raft cluster. Leave empty for client.")
@@ -138,6 +175,8 @@ It is a plain text value by default but you can provide a SHA256 hash by adding
RestoreSnapshot: *restoreSnapshot,
RestoreAOF: *restoreAOF,
AOFSyncStrategy: aofSyncStrategy,
MaxMemory: maxMemory,
EvictionPolicy: evictionPolicy,
}
if len(*config) > 0 {
+13 -2
View File
@@ -25,6 +25,17 @@ const (
)
const (
OK_RESPONSE = "+OK\r\n"
WRONG_ARGS_RESPONSE = "wrong number of arguments"
OkResponse = "+OK\r\n"
WrongArgsResponse = "wrong number of arguments"
)
const (
NoEviction = "noeviction"
AllKeysLRU = "allkeys-lru"
AllKeysLFU = "allkeys=lfu"
VolatileLRU = "volatile-lru"
VolatileLFU = "volatile-lfu"
AllKeysRandom = "allkeys-random"
VolatileRandom = "volatile-random"
VolatileTTL = "volatile-ttl"
)
+30
View File
@@ -4,11 +4,13 @@ import (
"bufio"
"bytes"
"errors"
"fmt"
"io"
"log"
"math/big"
"net"
"slices"
"strconv"
"strings"
"time"
@@ -130,3 +132,31 @@ func AbsInt(n int) int {
}
return n
}
// ParseMemory returns an integer representing the bytes in the memory string
func ParseMemory(memory string) (int, error) {
// Parse memory strings such as "100mb", "16gb"
memString := memory[0 : len(memory)-2]
bytesInt, err := strconv.ParseInt(memString, 10, 64)
if err != nil {
return 0, err
}
memUnit := strings.ToLower(memory[len(memory)-2:])
switch memUnit {
case "kb":
bytesInt *= 1024
case "mb":
bytesInt *= 1024 * 1024
case "gb":
bytesInt *= 1024 * 1024 * 1024
case "tb":
bytesInt *= 1024 * 1024 * 1024 * 1024
case "pb":
bytesInt *= 1024 * 1024 * 1024 * 1024 * 1024
default:
return 0, fmt.Errorf("memory unit %s not supported, use (kb, mb, gb, tb, pb) ", memUnit)
}
return int(bytesInt), nil
}