From 00c0fb54424dd2a2e7650f5e6355b67e3d71cbb0 Mon Sep 17 00:00:00 2001 From: Kelvin Clement Mwinuka Date: Tue, 20 Feb 2024 03:39:13 +0800 Subject: [PATCH] Implemented test for ZLEXCOUNT command handler --- src/modules/sorted_set/commands.go | 16 +-- src/modules/sorted_set/commands_test.go | 135 +++++++++++++++++++++++- 2 files changed, 141 insertions(+), 10 deletions(-) diff --git a/src/modules/sorted_set/commands.go b/src/modules/sorted_set/commands.go index 3e65a8e..1b63236 100644 --- a/src/modules/sorted_set/commands.go +++ b/src/modules/sorted_set/commands.go @@ -255,19 +255,20 @@ func handleZCOUNT(ctx context.Context, cmd []string, server utils.Server, conn * } func handleZLEXCOUNT(ctx context.Context, cmd []string, server utils.Server, conn *net.Conn) ([]byte, error) { - if len(cmd) != 4 { - return nil, errors.New(utils.WRONG_ARGS_RESPONSE) + keys, err := zlexcountKeyFunc(cmd) + if err != nil { + return nil, err } - key := cmd[1] + key := keys[0] minimum := cmd[2] maximum := cmd[3] if !server.KeyExists(key) { - return []byte("+(nil)\r\n\r\n"), nil + return []byte(":0\r\n\r\n"), nil } - if _, err := server.KeyRLock(ctx, key); err != nil { + if _, err = server.KeyRLock(ctx, key); err != nil { return nil, err } defer server.KeyRUnlock(key) @@ -282,7 +283,7 @@ func handleZLEXCOUNT(ctx context.Context, cmd []string, server utils.Server, con // Check if all members has the same score for i := 0; i < len(members)-2; i++ { if members[i].score != members[i+1].score { - return []byte("+(nil)\r\n\r\n"), nil + return []byte(":0\r\n\r\n"), nil } } @@ -1756,7 +1757,8 @@ The elements are ordered from lowest score to highest score`, Command: "zlexcount", Categories: []string{utils.SortedSetCategory, utils.ReadCategory, utils.SlowCategory}, Description: `(ZLEXCOUNT key min max) Returns the number of elements in within the sorted set within the -lexicographical range between min and max`, +lexicographical range between min and max. Returns 0, if the keys does not exist or if all the members do not have +the same score. If the value held at key is not a sorted set, an error is returned`, Sync: false, KeyExtractionFunc: zlexcountKeyFunc, HandlerFunc: handleZLEXCOUNT, diff --git a/src/modules/sorted_set/commands_test.go b/src/modules/sorted_set/commands_test.go index 7cbe3fa..3a6cebc 100644 --- a/src/modules/sorted_set/commands_test.go +++ b/src/modules/sorted_set/commands_test.go @@ -271,7 +271,7 @@ func Test_HandleZCARD(t *testing.T) { tests := []struct { preset bool - presetValue *SortedSet + presetValue interface{} key string command []string expectedValue *SortedSet @@ -318,6 +318,15 @@ func Test_HandleZCARD(t *testing.T) { expectedResponse: 0, expectedError: errors.New(utils.WRONG_ARGS_RESPONSE), }, + { // 5. Return error when not a sorted set + preset: true, + presetValue: "Default value", + key: "key5", + command: []string{"ZCARD", "key5"}, + expectedValue: nil, + expectedResponse: 0, + expectedError: errors.New("value at key5 is not a sorted set"), + }, } for _, test := range tests { @@ -354,7 +363,7 @@ func Test_HandleZCOUNT(t *testing.T) { tests := []struct { preset bool - presetValue *SortedSet + presetValue interface{} key string command []string expectedValue *SortedSet @@ -448,6 +457,15 @@ func Test_HandleZCOUNT(t *testing.T) { expectedResponse: 0, expectedError: errors.New(utils.WRONG_ARGS_RESPONSE), }, + { // 8. Throw error when value at the key is not a sorted set + preset: true, + presetValue: "Default value", + key: "key8", + command: []string{"ZCOUNT", "key8", "1", "10"}, + expectedValue: nil, + expectedResponse: 0, + expectedError: errors.New("value at key8 is not a sorted set"), + }, } for _, test := range tests { @@ -479,7 +497,118 @@ func Test_HandleZCOUNT(t *testing.T) { } } -func Test_HandleZLEXCOUNT(t *testing.T) {} +func Test_HandleZLEXCOUNT(t *testing.T) { + mockServer := server.NewServer(server.Opts{}) + + tests := []struct { + preset bool + presetValue interface{} + key string + command []string + expectedValue *SortedSet + expectedResponse int + expectedError error + }{ + { // 1. Get entire count using infinity boundaries + preset: true, + presetValue: NewSortedSet([]MemberParam{ + {value: "e", score: Score(1)}, + {value: "f", score: Score(1)}, + {value: "g", score: Score(1)}, + {value: "h", score: Score(1)}, + {value: "i", score: Score(1)}, + {value: "j", score: Score(1)}, + {value: "k", score: Score(1)}, + }), + key: "key1", + command: []string{"ZLEXCOUNT", "key1", "f", "j"}, + expectedValue: nil, + expectedResponse: 5, + expectedError: nil, + }, + { // 2. Return 0 when the members do not have the same score + preset: true, + presetValue: NewSortedSet([]MemberParam{ + {value: "a", score: Score(5.5)}, + {value: "b", score: Score(67.77)}, + {value: "c", score: Score(10)}, + {value: "d", score: Score(1083.13)}, + {value: "e", score: Score(11)}, + {value: "f", score: Score(math.Inf(-1))}, + {value: "g", score: Score(math.Inf(1))}, + }), + key: "key2", + command: []string{"ZLEXCOUNT", "key2", "a", "b"}, + expectedValue: nil, + expectedResponse: 0, + expectedError: nil, + }, + { // 3. Return 0 when the key does not exist + preset: false, + presetValue: nil, + key: "key3", + command: []string{"ZLEXCOUNT", "key3", "a", "z"}, + expectedValue: nil, + expectedResponse: 0, + expectedError: nil, + }, + { // 4. Return error when the value at the key is not a sorted set + preset: true, + presetValue: "Default value", + key: "key4", + command: []string{"ZLEXCOUNT", "key4", "a", "z"}, + expectedValue: nil, + expectedResponse: 0, + expectedError: errors.New("value at key4 is not a sorted set"), + }, + { // 5. Command is too short + preset: false, + presetValue: nil, + key: "key5", + command: []string{"ZLEXCOUNT"}, + expectedValue: nil, + expectedResponse: 0, + expectedError: errors.New(utils.WRONG_ARGS_RESPONSE), + }, + { // 6. Command too long + preset: false, + presetValue: nil, + key: "key6", + command: []string{"ZLEXCOUNT", "key6", "min", "max", "count"}, + expectedValue: nil, + expectedResponse: 0, + expectedError: errors.New(utils.WRONG_ARGS_RESPONSE), + }, + } + + for _, test := range tests { + if test.preset { + if _, err := mockServer.CreateKeyAndLock(context.Background(), test.key); err != nil { + t.Error(err) + } + mockServer.SetValue(context.Background(), test.key, test.presetValue) + mockServer.KeyUnlock(test.key) + } + res, err := handleZLEXCOUNT(context.Background(), test.command, mockServer, nil) + if test.expectedError != nil { + if err.Error() != test.expectedError.Error() { + t.Errorf("expected error \"%s\", got \"%s\"", test.expectedError.Error(), err.Error()) + } + continue + } + if err != nil { + t.Error(err) + } + rd := resp.NewReader(bytes.NewReader(res)) + rv, _, err := rd.ReadValue() + if err != nil { + t.Error(err) + } + if rv.Integer() != test.expectedResponse { + t.Errorf("expected response %d at key \"%s\", got %d", test.expectedResponse, test.key, rv.Integer()) + } + } +} func Test_HandleZDIFF(t *testing.T) {}