From e126231c0130ff2e83d53dbc0c305a8eed20372e Mon Sep 17 00:00:00 2001
From: programming-services
 <69348895+programming-services@users.noreply.github.com>
Date: Tue, 14 Jun 2022 19:39:03 +0200
Subject: [PATCH] Added RedisMock::bitcount, RedisMock::getbit,
 RedisMock::setbit commands (#106)

* Added RedisMock::bitcount, RedisMock::getbit, RedisMock::setbit commands

Co-authored-by: Luke Adamczewski <luke.adamczewski@jobleads.com>
Co-authored-by: Oliver THEBAULT <Oliboy50@users.noreply.github.com>
---
 src/M6Web/Component/RedisMock/RedisMock.php   | 47 +++++++++++++++++++
 .../Component/RedisMock/RedisMockFactory.php  |  4 +-
 tests/units/RedisMock.php                     | 33 +++++++++++++
 3 files changed, 82 insertions(+), 2 deletions(-)

diff --git a/src/M6Web/Component/RedisMock/RedisMock.php b/src/M6Web/Component/RedisMock/RedisMock.php
index 186f35d..dc4177b 100644
--- a/src/M6Web/Component/RedisMock/RedisMock.php
+++ b/src/M6Web/Component/RedisMock/RedisMock.php
@@ -1316,4 +1316,51 @@ public function eval($script, $numberOfKeys, ...$arguments)
     {
         return;
     }
+
+    /**
+     * Mock the `bitcount` command
+     * @see https://redis.io/commands/bitcount
+     *
+     * @param  string $key
+     * @return int
+     */
+    public function bitcount($key)
+    {
+        return count(self::$dataValues[$this->storage][$key] ?? []);
+    }
+
+    /**
+     * Mock the `setbit` command
+     * @see https://redis.io/commands/setbit
+     *
+     * @param string $key
+     * @param int $offset
+     * @param int $value
+     * @return int original value before the update
+     */
+    public function setbit($key, $offset, $value)
+    {
+        if (!isset(self::$dataValues[$this->storage][$key])) {
+            self::$dataValues[$this->storage][$key] = [];
+        }
+
+        $originalValue = self::$dataValues[$this->storage][$key][$offset] ?? 0;
+
+        self::$dataValues[$this->storage][$key][$offset] = $value;
+
+        return $originalValue;
+    }
+
+    /**
+     * Mock the `getbit` command
+     * @see https://redis.io/commands/getbit
+     *
+     * @param string $key
+     * @param int $offset
+     * @return int
+     */
+    public function getbit($key, $offset)
+    {
+        return self::$dataValues[$this->storage][$key][$offset] ?? 0;
+    }
 }
diff --git a/src/M6Web/Component/RedisMock/RedisMockFactory.php b/src/M6Web/Component/RedisMock/RedisMockFactory.php
index 91c86fe..09578fe 100644
--- a/src/M6Web/Component/RedisMock/RedisMockFactory.php
+++ b/src/M6Web/Component/RedisMock/RedisMockFactory.php
@@ -4,10 +4,10 @@
 
 /**
  * Adapter allowing to setup a Redis Mock inheriting of an arbitrary class
- * 
+ *
  * WARNING ! RedisMock doesn't implement all Redis features and commands.
  * The mock can have undesired behavior if your parent class uses unsupported features.
- * 
+ *
  * @author Adrien Samson <asamson.externe@m6.fr>
  * @author Florent Dubost <fdubost.externe@m6.fr>
  */
diff --git a/tests/units/RedisMock.php b/tests/units/RedisMock.php
index 9e2a1f2..243fe7f 100644
--- a/tests/units/RedisMock.php
+++ b/tests/units/RedisMock.php
@@ -1918,4 +1918,37 @@ public function testScanCommand()
             ->isEqualTo([0, []]);
 
     }
+
+    public function testBitcountCommand()
+    {
+        $redisMock = new Redis();
+        $redisMock->setbit('myKey', 0, 0);
+        $redisMock->setbit('myKey', 1, 1);
+        $redisMock->setbit('myKey', 2, 1);
+
+        $this->assert->variable($redisMock->bitcount('myKey'))->isEqualTo(3);
+        $this->assert->variable($redisMock->bitcount('otherKey'))->isEqualTo(0);
+    }
+
+    public function testGetbitCommand()
+    {
+        $redisMock = new Redis();
+
+        $this->assert->variable($redisMock->getbit('myKey', 0))->isEqualTo(0);
+
+        $redisMock->setbit('myKey', 0, 1);
+        $this->assert->variable($redisMock->getbit('myKey', 0))->isEqualTo(1);
+    }
+
+    public function testSetbitCommand()
+    {
+        $redisMock = new Redis();
+
+        $this->assert->variable($redisMock->getbit('myKey', 0))->isEqualTo(0);
+
+        $returnValue = $redisMock->setbit('myKey', 0, 1);
+        $this->assert->variable($returnValue)->isEqualTo(0);
+        $returnValue = $redisMock->setbit('myKey', 0, 0);
+        $this->assert->variable($returnValue)->isEqualTo(1);
+    }
 }