diff --git a/src/modules/sorted_set/commands.go b/src/modules/sorted_set/commands.go index 93ea4ab..efbbe36 100644 --- a/src/modules/sorted_set/commands.go +++ b/src/modules/sorted_set/commands.go @@ -960,12 +960,14 @@ func handleZSCORE(ctx context.Context, cmd []string, server utils.Server, conn * } func handleZREMRANGEBYSCORE(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 := zremrangebyscoreKeyFunc(cmd) + if err != nil { + return nil, err } + key := keys[0] + deletedCount := 0 - key := cmd[1] minimum, err := strconv.ParseFloat(cmd[2], 64) if err != nil { @@ -978,10 +980,10 @@ func handleZREMRANGEBYSCORE(ctx context.Context, cmd []string, server utils.Serv } if !server.KeyExists(key) { - return []byte("+(nil)\r\n\r\n"), nil + return []byte(":0\r\n\r\n"), nil } - if _, err := server.KeyLock(ctx, key); err != nil { + if _, err = server.KeyLock(ctx, key); err != nil { return nil, err } defer server.KeyUnlock(key) @@ -1066,20 +1068,20 @@ func handleZREMRANGEBYRANK(ctx context.Context, cmd []string, server utils.Serve } func handleZREMRANGEBYLEX(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 := zremrangebylexKeyFunc(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 } - _, err := server.KeyLock(ctx, key) - if err != nil { + if _, err = server.KeyLock(ctx, key); err != nil { return nil, err } defer server.KeyUnlock(key) @@ -1091,10 +1093,10 @@ func handleZREMRANGEBYLEX(ctx context.Context, cmd []string, server utils.Server members := set.GetAll() - // Check if all the members have the same score. If not, return nil + // Check if all the members have the same score. If not, return 0 for i := 0; i < len(members)-1; 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 } } diff --git a/src/modules/sorted_set/commands_test.go b/src/modules/sorted_set/commands_test.go index 4b3decf..a6c214c 100644 --- a/src/modules/sorted_set/commands_test.go +++ b/src/modules/sorted_set/commands_test.go @@ -2106,10 +2106,129 @@ func Test_HandleZREM(t *testing.T) { if rv.Integer() != test.expectedResponse { t.Errorf("expected response %d, got %d", test.expectedResponse, rv.Integer()) } + // Check if the expected sorted set is the same at the current one + if test.expectedValues != nil { + for key, expectedSet := range test.expectedValues { + if _, err = mockServer.KeyRLock(context.Background(), key); err != nil { + t.Error(err) + } + set, ok := mockServer.GetValue(key).(*SortedSet) + if !ok { + t.Errorf("expected value at key \"%s\" to be a sorted set, got another type", key) + } + if !set.Equals(expectedSet) { + t.Errorf("exptected sorted set %+v, got %+v", expectedSet, set) + } + } + } } } -func Test_HandleZREMRANGEBYSCORE(t *testing.T) {} +func Test_HandleZREMRANGEBYSCORE(t *testing.T) { + mockServer := server.NewServer(server.Opts{}) + + tests := []struct { + preset bool + presetValues map[string]interface{} + command []string + expectedValues map[string]*SortedSet + expectedResponse int + expectedError error + }{ + { // 1. Successfully remove multiple elements with scores inside the provided range + preset: true, + presetValues: map[string]interface{}{ + "key1": NewSortedSet([]MemberParam{ + {value: "one", score: 1}, {value: "two", score: 2}, + {value: "three", score: 3}, {value: "four", score: 4}, + {value: "five", score: 5}, {value: "six", score: 6}, + {value: "seven", score: 7}, {value: "eight", score: 8}, + {value: "nine", score: 9}, {value: "ten", score: 10}, + }), + }, + command: []string{"ZREMRANGEBYSCORE", "key1", "3", "7"}, + expectedValues: map[string]*SortedSet{ + "key1": NewSortedSet([]MemberParam{ + {value: "one", score: 1}, {value: "two", score: 2}, {value: "eight", score: 8}, + {value: "nine", score: 9}, {value: "ten", score: 10}, + }), + }, + expectedResponse: 5, + expectedError: nil, + }, + { // 2. If key does not exist, return 0 + preset: false, + presetValues: nil, + command: []string{"ZREMRANGEBYSCORE", "key2", "2", "4"}, + expectedValues: nil, + expectedResponse: 0, + expectedError: nil, + }, + { // 3. Return error key is not a sorted set + preset: true, + presetValues: map[string]interface{}{ + "key3": "Default value", + }, + command: []string{"ZREMRANGEBYSCORE", "key3", "4", "4"}, + expectedError: errors.New("value at key3 is not a sorted set"), + }, + { // 4. Command too short + preset: false, + command: []string{"ZREMRANGEBYSCORE", "key4", "3"}, + expectedError: errors.New(utils.WRONG_ARGS_RESPONSE), + }, + { // 5. Command too long + preset: false, + command: []string{"ZREMRANGEBYSCORE", "key5", "4", "5", "8"}, + expectedError: errors.New(utils.WRONG_ARGS_RESPONSE), + }, + } + + for _, test := range tests { + if test.preset { + for key, value := range test.presetValues { + if _, err := mockServer.CreateKeyAndLock(context.Background(), key); err != nil { + t.Error(err) + } + mockServer.SetValue(context.Background(), key, value) + mockServer.KeyUnlock(key) + } + } + res, err := handleZREMRANGEBYSCORE(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.NewBuffer(res)) + rv, _, err := rd.ReadValue() + if err != nil { + t.Error(err) + } + if rv.Integer() != test.expectedResponse { + t.Errorf("expected response %d, got %d", test.expectedResponse, rv.Integer()) + } + // Check if the expected values are the same + if test.expectedValues != nil { + for key, expectedSet := range test.expectedValues { + if _, err = mockServer.KeyRLock(context.Background(), key); err != nil { + t.Error(err) + } + set, ok := mockServer.GetValue(key).(*SortedSet) + if !ok { + t.Errorf("expected value at key \"%s\" to be a sorted set, got another type", key) + } + if !set.Equals(expectedSet) { + t.Errorf("exptected sorted set %+v, got %+v", expectedSet, set) + } + } + } + } +} func Test_HandleZREMRANGEBYRANK(t *testing.T) {}