Repository: fppt/jedis-mock
Pull request #119 (2021-05-08 09:18:26)

Fix hincrbyfloat and incrbyfloat
1. `incrbyfloat` causes exception
2. when incremented by int value, `hincrbyfloat` returns float instead of int


Patch:
diff --git a/src/main/java/com/github/fppt/jedismock/operations/RO_hincrbyfloat.java b/src/main/java/com/github/fppt/jedismock/operations/RO_hincrbyfloat.java
index cd9d41b..d5f8e70 100644
--- a/src/main/java/com/github/fppt/jedismock/operations/RO_hincrbyfloat.java
+++ b/src/main/java/com/github/fppt/jedismock/operations/RO_hincrbyfloat.java
@@ -4,22 +4,24 @@ import com.github.fppt.jedismock.server.Response;
 import com.github.fppt.jedismock.server.Slice;
 import com.github.fppt.jedismock.storage.RedisBase;
 
+import java.math.BigDecimal;
 import java.util.List;
 
-import static com.github.fppt.jedismock.Utils.convertToDouble;
-
 class RO_hincrbyfloat extends RO_hincrby {
     RO_hincrbyfloat(RedisBase base, List<Slice> params) {
         super(base, params);
     }
 
     Slice hsetValue(Slice key1, Slice key2, Slice value) {
-        double numericValue = convertToDouble(String.valueOf(value));
+        BigDecimal numericValue = new BigDecimal(value.toString());
         Slice foundValue = base().getValue(key1, key2);
         if (foundValue != null) {
-            numericValue = convertToDouble(new String(foundValue.data())) + numericValue;
+            numericValue = numericValue.add(new BigDecimal((new String(foundValue.data()))));
         }
-        Slice res = Slice.create(String.valueOf(numericValue));
+        String data = String.valueOf(BigDecimal.valueOf(numericValue.intValue()).compareTo(numericValue) == 0
+                ? numericValue.intValue() : numericValue);
+
+        Slice res = Slice.create(data);
         base().putValue(key1, key2, res, -1L);
 
         return Response.bulkString(res);
diff --git a/src/main/java/com/github/fppt/jedismock/operations/RO_incrOrDecrByFloat.java b/src/main/java/com/github/fppt/jedismock/operations/RO_incrOrDecrByFloat.java
index e7ef657..b48c2c3 100644
--- a/src/main/java/com/github/fppt/jedismock/operations/RO_incrOrDecrByFloat.java
+++ b/src/main/java/com/github/fppt/jedismock/operations/RO_incrOrDecrByFloat.java
@@ -4,28 +4,29 @@ import com.github.fppt.jedismock.server.Response;
 import com.github.fppt.jedismock.server.Slice;
 import com.github.fppt.jedismock.storage.RedisBase;
 
+import java.math.BigDecimal;
 import java.util.List;
 
-import static com.github.fppt.jedismock.Utils.convertToDouble;
-
 abstract class RO_incrOrDecrByFloat extends AbstractRedisOperation {
     RO_incrOrDecrByFloat(RedisBase base, List<Slice> params) {
         super(base, params);
     }
 
-    abstract double incrementOrDecrementValue(List<Slice> params);
-
     Slice response() {
         Slice key = params().get(0);
-        double d = incrementOrDecrementValue(params());
-        Slice v = base().getValue(key);
-        if (v == null) {
-            base().putValue(key, Slice.create(String.valueOf(d)));
-            return Response.doubleValue(d);
+        BigDecimal numericValue = new BigDecimal(params().get(1).toString());
+
+        Slice foundValue = base().getValue(key);
+        if (foundValue != null) {
+            numericValue = numericValue.add(new BigDecimal((new String(foundValue.data()))));
         }
 
-        double r = convertToDouble(new String(v.data())) + d;
-        base().putValue(key, Slice.create(String.valueOf(r)));
-        return Response.doubleValue(r);
+        String data = String.valueOf(BigDecimal.valueOf(numericValue.intValue()).compareTo(numericValue) == 0
+                ? numericValue.intValue() : numericValue);
+
+        Slice res = Slice.create(data);
+        base().putValue(key, res);
+
+        return Response.bulkString(res);
     }
 }
diff --git a/src/main/java/com/github/fppt/jedismock/operations/RO_incrbyfloat.java b/src/main/java/com/github/fppt/jedismock/operations/RO_incrbyfloat.java
index 3ea852b..cd6c0e5 100644
--- a/src/main/java/com/github/fppt/jedismock/operations/RO_incrbyfloat.java
+++ b/src/main/java/com/github/fppt/jedismock/operations/RO_incrbyfloat.java
@@ -5,14 +5,8 @@ import com.github.fppt.jedismock.server.Slice;
 
 import java.util.List;
 
-import static com.github.fppt.jedismock.Utils.convertToDouble;
-
 class RO_incrbyfloat extends RO_incrOrDecrByFloat {
     RO_incrbyfloat(RedisBase base, List<Slice> params) {
         super(base, params);
     }
-
-    double incrementOrDecrementValue(List<Slice> params){
-        return convertToDouble(String.valueOf(params.get(1)));
-    }
 }


Test patch:
diff --git a/src/test/java/com/github/fppt/jedismock/TestRedisOperationExecutor.java b/src/test/java/com/github/fppt/jedismock/TestRedisOperationExecutor.java
index 6ef7af8..7383ef5 100644
--- a/src/test/java/com/github/fppt/jedismock/TestRedisOperationExecutor.java
+++ b/src/test/java/com/github/fppt/jedismock/TestRedisOperationExecutor.java
@@ -154,9 +154,9 @@ public class TestRedisOperationExecutor {
 
     @Test
     public void testIncrByFloat() throws ParseErrorException {
-        assertCommandEquals(5.0, array("incrbyfloat", "a", "5"));
-        assertCommandEquals(11.01, array("incrbyfloat", "a", "6.01"));
-        assertCommandEquals(9.51, array("incrbyfloat", "a", "-1.5"));
+        assertCommandEquals("5", array("incrbyfloat", "a", "5"));
+        assertCommandEquals("11.01", array("incrbyfloat", "a", "6.01"));
+        assertCommandEquals("9.51", array("incrbyfloat", "a", "-1.5"));
         assertCommandOK(array("set", "a", "b"));
         assertCommandError(array("incrbyfloat", "a", "1"));
     }
diff --git a/src/test/java/com/github/fppt/jedismock/comparisontests/SimpleOperationsTest.java b/src/test/java/com/github/fppt/jedismock/comparisontests/SimpleOperationsTest.java
index 2212a74..8efe351 100644
--- a/src/test/java/com/github/fppt/jedismock/comparisontests/SimpleOperationsTest.java
+++ b/src/test/java/com/github/fppt/jedismock/comparisontests/SimpleOperationsTest.java
@@ -253,6 +253,7 @@ public class SimpleOperationsTest {
         assertEquals(31.41, jedis.hincrByFloat(key, "E", 0.01), 0.00001);
     }
 
+
     @TestTemplate
     public void whenAddingToASet_ensureCountIsUpdated(Jedis jedis) {
         String key = "my-counted-set-key";
@@ -910,6 +911,62 @@ public class SimpleOperationsTest {
         assertTrue(ttl > 0);
     }
 
+    @TestTemplate
+    public void whenIncrementingWithIncrByFloat_ensureValuesAreCorrect(Jedis jedis) {
+        jedis.flushDB();
+        jedis.set("key", "0");
+        jedis.incrByFloat("key", 1.);
+        assertEquals("1", jedis.get("key"));
+        jedis.incrByFloat("key", 1.5);
+        assertEquals("2.5", jedis.get("key"));
+    }
+
+    @TestTemplate
+    public void whenIncrementingWithHIncrByFloat_ensureValuesAreCorrect(Jedis jedis) {
+        jedis.flushDB();
+        jedis.hset("key", "subkey", "0");
+        jedis.hincrByFloat("key", "subkey", 1.);
+        assertEquals("1", jedis.hget("key", "subkey"));
+        jedis.hincrByFloat("key", "subkey", 1.5);
+        assertEquals("2.5", jedis.hget("key", "subkey"));
+    }
+
+    @TestTemplate
+    public void whenIncrementingWithIncrBy_ensureValuesAreCorrect(Jedis jedis) {
+        jedis.flushDB();
+        jedis.set("key", "0");
+        jedis.incrBy("key", 1);
+        assertEquals("1", jedis.get("key"));
+        jedis.incrBy("key", 2);
+        assertEquals("3", jedis.get("key"));
+    }
+
+    @TestTemplate
+    public void whenIncrementingWithHIncrBy_ensureValuesAreCorrect(Jedis jedis) {
+        jedis.flushDB();
+        jedis.hset("key", "subkey", "0");
+        jedis.hincrBy("key", "subkey", 1);
+        assertEquals("1", jedis.hget("key", "subkey"));
+        jedis.hincrBy("key", "subkey", 2);
+        assertEquals("3", jedis.hget("key", "subkey"));
+    }
+
+    @TestTemplate
+    public void whenIncrementingText_ensureException(Jedis jedis) {
+        jedis.flushDB();
+        jedis.set("key", "foo");
+        assertThrows(JedisDataException.class, ()->jedis.incrBy("key", 1));
+        assertThrows(JedisDataException.class, ()->jedis.incrByFloat("key", 1.5));
+    }
+
+    @TestTemplate
+    public void whenHIncrementingText_ensureException(Jedis jedis) {
+        jedis.flushDB();
+        jedis.hset("key", "subkey", "foo");
+        assertThrows(JedisDataException.class, ()->jedis.hincrBy("key", "subkey", 1));
+        assertThrows(JedisDataException.class, ()->jedis.hincrByFloat("key", "subkey", 1.5));
+    }
+
     @TestTemplate
     public void decrDoesNotClearTtl(Jedis jedis) {
         jedis.flushDB();