diff --git a/echovault/api_generic.go b/echovault/api_generic.go index 2530592..cb6236d 100644 --- a/echovault/api_generic.go +++ b/echovault/api_generic.go @@ -475,14 +475,12 @@ func (server *EchoVault) Decr(key string) (int, error) { // Returns: The new value of the key after the increment operation as an integer. func (server *EchoVault) IncrBy(key string, value string) (int, error) { // Construct the command - cmd := []string{"DECRBY", key, value} - + cmd := []string{"INCRBY", key, value} // Execute the command b, err := server.handleCommand(server.context, internal.EncodeCommand(cmd), nil, false, true) if err != nil { return 0, err } - // Parse the integer response return internal.ParseIntegerResponse(b) } diff --git a/echovault/api_generic_test.go b/echovault/api_generic_test.go index 1ae3a5f..2815faf 100644 --- a/echovault/api_generic_test.go +++ b/echovault/api_generic_test.go @@ -1048,75 +1048,6 @@ func TestEchoVault_DECR(t *testing.T) { } } -func TestEchoVault_DECRBY(t *testing.T) { - server := createEchoVault() - - tests := []struct { - name string - key string - decrement string - presetValues map[string]internal.KeyData - want int - wantErr bool - }{ - { - name: "1. Decrement non-existent key by 4", - key: "DecrByKey1", - decrement: "4", - presetValues: nil, - want: -4, - wantErr: false, - }, - { - name: "2. Decrement existing key with integer value by 3", - key: "DecrByKey2", - decrement: "3", - presetValues: map[string]internal.KeyData{ - "DecrByKey2": {Value: "-5"}, - }, - want: -8, - wantErr: false, - }, - { - name: "3. Decrement existing key with non-integer value by 2", - key: "DecrByKey3", - decrement: "2", - presetValues: map[string]internal.KeyData{ - "DecrByKey3": {Value: "not_an_int"}, - }, - want: 0, - wantErr: true, - }, - { - name: "4. Decrement existing key with int64 value by 7", - key: "DecrByKey4", - decrement: "7", - presetValues: map[string]internal.KeyData{ - "DecrByKey4": {Value: int64(10)}, - }, - want: 3, - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.presetValues != nil { - for k, d := range tt.presetValues { - presetKeyData(server, context.Background(), k, d) - } - } - got, err := server.DecrBy(tt.key, tt.decrement) - if (err != nil) != tt.wantErr { - t.Errorf("DecrBy() error = %v, wantErr %v", err, tt.wantErr) - return - } - if got != tt.want { - t.Errorf("DecrBy() got = %v, want %v", got, tt.want) - } - }) - } -} - func TestEchoVault_INCRBY(t *testing.T) { server := createEchoVault() @@ -1185,3 +1116,71 @@ func TestEchoVault_INCRBY(t *testing.T) { }) } } + +func TestEchoVault_DECRBY(t *testing.T) { + server := createEchoVault() + + tests := []struct { + name string + key string + decrement string + presetValues map[string]internal.KeyData + want int + wantErr bool + }{ + { + name: "1. Decrement non-existent key by 4", + key: "DecrByKey1", + decrement: "4", + presetValues: nil, + want: -4, + wantErr: false, + }, + { + name: "2. Decrement existing key with integer value by 3", + key: "DecrByKey2", + decrement: "3", + presetValues: map[string]internal.KeyData{ + "DecrByKey2": {Value: "-5"}, + }, + want: -8, + wantErr: false, + }, + { + name: "3. Decrement existing key with non-integer value by 2", + key: "DecrByKey3", + decrement: "2", + presetValues: map[string]internal.KeyData{ + "DecrByKey3": {Value: "not_an_int"}, + }, + want: 0, + wantErr: true, + }, + { + name: "4. Decrement existing key with int64 value by 7", + key: "DecrByKey4", + decrement: "7", + presetValues: map[string]internal.KeyData{ + "DecrByKey4": {Value: int64(10)}}, + want: 3, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.presetValues != nil { + for k, d := range tt.presetValues { + presetKeyData(server, context.Background(), k, d) + } + } + got, err := server.DecrBy(tt.key, tt.decrement) + if (err != nil) != tt.wantErr { + t.Errorf("IncrBy() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("IncrBy() got = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/internal/modules/generic/commands_test.go b/internal/modules/generic/commands_test.go index 28a9c3c..df57584 100644 --- a/internal/modules/generic/commands_test.go +++ b/internal/modules/generic/commands_test.go @@ -2266,4 +2266,110 @@ func Test_Generic(t *testing.T) { }) } }) + + t.Run("Test_HandlerDECRBY", func(t *testing.T) { + t.Parallel() + conn, err := internal.GetConnection("localhost", port) + if err != nil { + t.Error(err) + return + } + defer func() { + _ = conn.Close() + }() + client := resp.NewConn(conn) + + tests := []struct { + name string + key string + decrement string + presetValue interface{} + command []resp.Value + expectedResponse int64 + expectedError error + }{ + { + name: "1. Decrement non-existent key by 4", + key: "DecrByKey1", + decrement: "4", + presetValue: nil, + command: []resp.Value{resp.StringValue("DECRBY"), resp.StringValue("DecrByKey1"), resp.StringValue("4")}, + expectedResponse: -4, + expectedError: nil, + }, + { + name: "2. Decrement existing key with integer value by 3", + key: "DecrByKey2", + decrement: "3", + presetValue: "5", + command: []resp.Value{resp.StringValue("DECRBY"), resp.StringValue("DecrByKey2"), resp.StringValue("3")}, + expectedResponse: 2, + expectedError: nil, + }, + { + name: "3. Decrement existing key with non-integer value by 2", + key: "DecrByKey3", + decrement: "2", + presetValue: "not_an_int", + command: []resp.Value{resp.StringValue("DECRBY"), resp.StringValue("DecrByKey3"), resp.StringValue("2")}, + expectedResponse: 0, + expectedError: errors.New("value is not an integer or out of range"), + }, + { + name: "4. Decrement existing key with int64 value by 7", + key: "DecrByKey4", + decrement: "7", + presetValue: int64(10), + command: []resp.Value{resp.StringValue("DECRBY"), resp.StringValue("DecrByKey4"), resp.StringValue("7")}, + expectedResponse: 3, + expectedError: nil, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + if test.presetValue != nil { + command := []resp.Value{resp.StringValue("SET"), resp.StringValue(test.key), resp.StringValue(fmt.Sprintf("%v", test.presetValue))} + if err = client.WriteArray(command); err != nil { + t.Error(err) + } + res, _, err := client.ReadValue() + if err != nil { + t.Error(err) + } + if !strings.EqualFold(res.String(), "OK") { + t.Errorf("expected preset response to be OK, got %s", res.String()) + } + } + + if err = client.WriteArray(test.command); err != nil { + t.Error(err) + } + + res, _, err := client.ReadValue() + if err != nil { + t.Error(err) + } + + if test.expectedError != nil { + if !strings.Contains(res.Error().Error(), test.expectedError.Error()) { + t.Errorf("expected error \"%s\", got \"%s\"", test.expectedError.Error(), err.Error()) + } + return + } + + if err != nil { + t.Error(err) + } else { + responseInt, err := strconv.ParseInt(res.String(), 10, 64) + if err != nil { + t.Errorf("error parsing response to int64: %s", err) + } + if responseInt != test.expectedResponse { + t.Errorf("expected response %d, got %d", test.expectedResponse, responseInt) + } + } + }) + } + }) }