diff --git a/src/main/java/redis/clients/jedis/args/BitOP.java b/src/main/java/redis/clients/jedis/args/BitOP.java index 2ca6c198fc..2042d56359 100644 --- a/src/main/java/redis/clients/jedis/args/BitOP.java +++ b/src/main/java/redis/clients/jedis/args/BitOP.java @@ -7,7 +7,7 @@ */ public enum BitOP implements Rawable { - AND, OR, XOR, NOT; + AND, OR, XOR, NOT, DIFF, DIFF1, ANDOR, ONE; private final byte[] raw; diff --git a/src/main/java/redis/clients/jedis/commands/BitBinaryCommands.java b/src/main/java/redis/clients/jedis/commands/BitBinaryCommands.java index e773742bad..2b69e12314 100644 --- a/src/main/java/redis/clients/jedis/commands/BitBinaryCommands.java +++ b/src/main/java/redis/clients/jedis/commands/BitBinaryCommands.java @@ -26,5 +26,13 @@ public interface BitBinaryCommands { List bitfieldReadonly(byte[] key, byte[]... arguments); + /** + * Bitop Command Perform a bitwise operation + * between multiple keys and store the result in the destKey. + * @param op can be AND, OR, XOR, NOT, DIFF, DIFF1, ANDOR and ONE + * @param destKey + * @param srcKeys + * @return The size of the string stored in the destKey + */ long bitop(BitOP op, byte[] destKey, byte[]... srcKeys); } diff --git a/src/main/java/redis/clients/jedis/commands/BitCommands.java b/src/main/java/redis/clients/jedis/commands/BitCommands.java index 704f29c52f..87975a9107 100644 --- a/src/main/java/redis/clients/jedis/commands/BitCommands.java +++ b/src/main/java/redis/clients/jedis/commands/BitCommands.java @@ -99,7 +99,7 @@ public interface BitCommands { /** * Bitop Command * Perform a bitwise operation between multiple keys (containing string values) and store the result in the destKey. - * @param op can be AND, OR, XOR or NOT + * @param op can be AND, OR, XOR, NOT, DIFF, DIFF1, ANDOR and ONE * @param destKey * @param srcKeys * @return The size of the string stored in the destKey diff --git a/src/test/java/redis/clients/jedis/commands/jedis/BitCommandsTest.java b/src/test/java/redis/clients/jedis/commands/jedis/BitCommandsTest.java index 95c88d8656..4709f4ecdf 100644 --- a/src/test/java/redis/clients/jedis/commands/jedis/BitCommandsTest.java +++ b/src/test/java/redis/clients/jedis/commands/jedis/BitCommandsTest.java @@ -20,6 +20,7 @@ import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; @@ -308,4 +309,286 @@ public void testBinaryBitfieldReadonly() { assertEquals(1L, responses2.get(0).longValue()); } + @Test + @SinceRedisVersion("8.1.240") + public void bitOpDiff() { + // Use single-byte values for simplicity + byte[] key1 = new byte[] { (byte) 0b00000111 }; // bits 0,1,2 set + byte[] key2 = new byte[] { (byte) 0b00000010 }; // bit 1 set + byte[] key3 = new byte[] { (byte) 0b00000100 }; // bit 2 set + String destKey = "resultDiff"; + + // Set keys using byte arrays + jedis.set("key1".getBytes(), key1); + jedis.set("key2".getBytes(), key2); + jedis.set("key3".getBytes(), key3); + + // DIFF(key1, key2, key3) = key1 AND NOT(key2 OR key3) + // key1 = 00000111 (bits 0,1,2 set) + // key2 = 00000010 (bit 1 set) + // key3 = 00000100 (bit 2 set) + // key2 OR key3 = 00000110 (bits 1,2 set) + // NOT(key2 OR key3) = 11111001 (all bits except 1,2 set) + // key1 AND NOT(key2 OR key3) = 00000001 (only bit 0 set) + jedis.bitop(BitOP.DIFF, destKey, "key1", "key2", "key3"); + + // Get result as bytes + byte[] resultBytes = jedis.get(destKey).getBytes(); + + // Expected result: 00000001 (only bit 0 set) + byte[] expectedBytes = new byte[] { (byte) 0b00000001 }; + + // Verify the result + assertArrayEquals(expectedBytes, resultBytes); + } + + @Test + @SinceRedisVersion("8.1.240") + public void bitOpDiff1() { + // Use single-byte values for simplicity + byte[] key1 = new byte[] { (byte) 0x07 }; // 00000111 - bits 0,1,2 set + byte[] key2 = new byte[] { (byte) 0x02 }; // 00000010 - bit 1 set + byte[] key3 = new byte[] { (byte) 0x04 }; // 00000100 - bit 2 set + String destKey = "resultDiff1"; + + // Set keys using byte arrays + jedis.set("key1".getBytes(), key1); + jedis.set("key2".getBytes(), key2); + jedis.set("key3".getBytes(), key3); + + // DIFF1(key1, key2, key3) = NOT(key1) AND (key2 OR key3) + // key1 = 00000111 (bits 0,1,2 set) + // key2 = 00000010 (bit 1 set) + // key3 = 00000100 (bit 2 set) + // key2 OR key3 = 00000110 (bits 1,2 set) + // NOT(key1) = 11111000 (all bits except 0,1,2 set) + // NOT(key1) AND (key2 OR key3) = 00000000 (no bits set) + jedis.bitop(BitOP.DIFF1, destKey, "key1", "key2", "key3"); + + // Get result as bytes + byte[] resultBytes = jedis.get(destKey).getBytes(); + + // Expected result: 00000000 (no bits set) + byte[] expectedBytes = new byte[] { (byte) 0x00 }; + + // Verify the result + assertArrayEquals(expectedBytes, resultBytes); + } + + @Test + @SinceRedisVersion("8.1.240") + public void bitOpAndor() { + // Use single-byte values for simplicity + byte[] key1 = new byte[] { (byte) 0x07 }; // 00000111 - bits 0,1,2 set + byte[] key2 = new byte[] { (byte) 0x02 }; // 00000010 - bit 1 set + byte[] key3 = new byte[] { (byte) 0x04 }; // 00000100 - bit 2 set + String destKey = "resultAndor"; + + // Set keys using byte arrays + jedis.set("key1".getBytes(), key1); + jedis.set("key2".getBytes(), key2); + jedis.set("key3".getBytes(), key3); + + // ANDOR(key1, key2, key3) = key1 AND (key2 OR key3) + // key1 = 00000111 (bits 0,1,2 set) + // key2 = 00000010 (bit 1 set) + // key3 = 00000100 (bit 2 set) + // key2 OR key3 = 00000110 (bits 1,2 set) + // key1 AND (key2 OR key3) = 00000110 (bits 1,2 set) + jedis.bitop(BitOP.ANDOR, destKey, "key1", "key2", "key3"); + + // Get result as bytes + byte[] resultBytes = jedis.get(destKey).getBytes(); + + // Expected result: 00000110 (bits 1,2 set) + byte[] expectedBytes = new byte[] { (byte) 0x06 }; + + // Verify the result + assertArrayEquals(expectedBytes, resultBytes); + } + + @Test + @SinceRedisVersion("8.1.240") + public void bitOpOne() { + // Use single-byte values for simplicity + byte[] key1 = new byte[] { (byte) 0x01 }; // 00000001 - bit 0 set + byte[] key2 = new byte[] { (byte) 0x02 }; // 00000010 - bit 1 set + byte[] key3 = new byte[] { (byte) 0x04 }; // 00000100 - bit 2 set + String destKey = "resultOne"; + + // Set keys using byte arrays + jedis.set("key1".getBytes(), key1); + jedis.set("key2".getBytes(), key2); + jedis.set("key3".getBytes(), key3); + + // ONE(key1, key2, key3) = bits set in exactly one of the inputs + // key1 = 00000001 (bit 0 set) + // key2 = 00000010 (bit 1 set) + // key3 = 00000100 (bit 2 set) + // Result = 00000111 (bits 0,1,2 set - each in exactly one input) + jedis.bitop(BitOP.ONE, destKey, "key1", "key2", "key3"); + + // Get result as bytes + byte[] resultBytes = jedis.get(destKey).getBytes(); + + // Expected result: 00000111 (bits 0,1,2 set) + byte[] expectedBytes = new byte[] { (byte) 0x07 }; + + // Verify the result + assertArrayEquals(expectedBytes, resultBytes); + } + + @Test + @SinceRedisVersion("8.1.240") + public void bitOpDiffBinary() { + byte[] key1 = { (byte) 0x07 }; // 00000111 - bits 0,1,2 set + byte[] key2 = { (byte) 0x02 }; // 00000010 - bit 1 set + byte[] key3 = { (byte) 0x04 }; // 00000100 - bit 2 set + byte[] dest = "resultDiffBinary".getBytes(); + + jedis.set("key1".getBytes(), key1); + jedis.set("key2".getBytes(), key2); + jedis.set("key3".getBytes(), key3); + + // DIFF(key1, key2, key3) = key1 AND NOT(key2 OR key3) + // key1 = 00000111 (bits 0,1,2 set) + // key2 = 00000010 (bit 1 set) + // key3 = 00000100 (bit 2 set) + // key2 OR key3 = 00000110 (bits 1,2 set) + // NOT(key2 OR key3) = 11111001 (all bits except 1,2 set) + // key1 AND NOT(key2 OR key3) = 00000001 (only bit 0 set) + jedis.bitop(BitOP.DIFF, dest, "key1".getBytes(), "key2".getBytes(), "key3".getBytes()); + + // Expected result: 00000001 (only bit 0 set) + byte[] expectedBytes = new byte[] { (byte) 0x01 }; + + // Verify the result + assertArrayEquals(expectedBytes, jedis.get(dest)); + } + + @Test + @SinceRedisVersion("8.1.240") + public void bitOpDiff1Binary() { + byte[] key1 = { (byte) 0x07 }; // 00000111 - bits 0,1,2 set + byte[] key2 = { (byte) 0x02 }; // 00000010 - bit 1 set + byte[] key3 = { (byte) 0x04 }; // 00000100 - bit 2 set + byte[] dest = "resultDiff1Binary".getBytes(); + + jedis.set("key1".getBytes(), key1); + jedis.set("key2".getBytes(), key2); + jedis.set("key3".getBytes(), key3); + + // DIFF1(key1, key2, key3) = NOT(key1) AND (key2 OR key3) + // key1 = 00000111 (bits 0,1,2 set) + // key2 = 00000010 (bit 1 set) + // key3 = 00000100 (bit 2 set) + // key2 OR key3 = 00000110 (bits 1,2 set) + // NOT(key1) = 11111000 (all bits except 0,1,2 set) + // NOT(key1) AND (key2 OR key3) = 00000000 (no bits set) + jedis.bitop(BitOP.DIFF1, dest, "key1".getBytes(), "key2".getBytes(), "key3".getBytes()); + + // Expected result: 00000000 (no bits set) + byte[] expectedBytes = new byte[] { (byte) 0x00 }; + + // Verify the result + assertArrayEquals(expectedBytes, jedis.get(dest)); + } + + @Test + @SinceRedisVersion("8.1.240") + public void bitOpAndorBinary() { + byte[] key1 = { (byte) 0x07 }; // 00000111 - bits 0,1,2 set + byte[] key2 = { (byte) 0x02 }; // 00000010 - bit 1 set + byte[] key3 = { (byte) 0x04 }; // 00000100 - bit 2 set + byte[] dest = "resultAndorBinary".getBytes(); + + jedis.set("key1".getBytes(), key1); + jedis.set("key2".getBytes(), key2); + jedis.set("key3".getBytes(), key3); + + // ANDOR(key1, key2, key3) = key1 AND (key2 OR key3) + // key1 = 00000111 (bits 0,1,2 set) + // key2 = 00000010 (bit 1 set) + // key3 = 00000100 (bit 2 set) + // key2 OR key3 = 00000110 (bits 1,2 set) + // key1 AND (key2 OR key3) = 00000110 (bits 1,2 set) + jedis.bitop(BitOP.ANDOR, dest, "key1".getBytes(), "key2".getBytes(), "key3".getBytes()); + + // Expected result: 00000110 (bits 1,2 set) + byte[] expectedBytes = new byte[] { (byte) 0x06 }; + + // Verify the result + assertArrayEquals(expectedBytes, jedis.get(dest)); + } + + @Test + @SinceRedisVersion("8.1.240") + public void bitOpOneBinary() { + byte[] key1 = { (byte) 0x01 }; // 00000001 - bit 0 set + byte[] key2 = { (byte) 0x02 }; // 00000010 - bit 1 set + byte[] key3 = { (byte) 0x04 }; // 00000100 - bit 2 set + byte[] dest = "resultOneBinary".getBytes(); + + jedis.set("key1".getBytes(), key1); + jedis.set("key2".getBytes(), key2); + jedis.set("key3".getBytes(), key3); + + // ONE(key1, key2, key3) = bits set in exactly one of the inputs + // key1 = 00000001 (bit 0 set) + // key2 = 00000010 (bit 1 set) + // key3 = 00000100 (bit 2 set) + // Result = 00000111 (bits 0,1,2 set - each in exactly one input) + jedis.bitop(BitOP.ONE, dest, "key1".getBytes(), "key2".getBytes(), "key3".getBytes()); + + // Expected result: 00000111 (bits 0,1,2 set) + byte[] expectedBytes = new byte[] { (byte) 0x07 }; + + // Verify the result + assertArrayEquals(expectedBytes, jedis.get(dest)); + } + + @Test + @SinceRedisVersion("8.1.240") + public void bitOpDiffSingleSourceShouldFail() { + assertThrows(JedisDataException.class, () -> jedis.bitop(BitOP.DIFF, "dest", "src1")); + } + + @Test + @SinceRedisVersion("8.1.240") + public void bitOpDiff1SingleSourceShouldFail() { + assertThrows(JedisDataException.class, () -> jedis.bitop(BitOP.DIFF1, "dest", "src1")); + } + + @Test + @SinceRedisVersion("8.1.240") + public void bitOpAndorSingleSourceShouldFail() { + assertThrows(JedisDataException.class, () -> jedis.bitop(BitOP.ANDOR, "dest", "src1")); + } + + @Test + @SinceRedisVersion("8.1.240") + public void bitOpDiffBinarySingleSourceShouldFail() { + byte[] dest = "dest".getBytes(); + byte[] src1 = "src1".getBytes(); + + assertThrows(JedisDataException.class, () -> jedis.bitop(BitOP.DIFF, dest, src1)); + } + + @Test + @SinceRedisVersion("8.1.240") + public void bitOpDiff1BinarySingleSourceShouldFail() { + byte[] dest = "dest".getBytes(); + byte[] src1 = "src1".getBytes(); + + assertThrows(JedisDataException.class, () -> jedis.bitop(BitOP.DIFF1, dest, src1)); + } + + @Test + @SinceRedisVersion("8.1.240") + public void bitOpAndorBinarySingleSourceShouldFail() { + byte[] dest = "dest".getBytes(); + byte[] src1 = "src1".getBytes(); + + assertThrows(JedisDataException.class, () -> jedis.bitop(BitOP.ANDOR, dest, src1)); + } } diff --git a/src/test/java/redis/clients/jedis/commands/unified/BitCommandsTestBase.java b/src/test/java/redis/clients/jedis/commands/unified/BitCommandsTestBase.java index 55a2e6a646..d3c4da08b7 100644 --- a/src/test/java/redis/clients/jedis/commands/unified/BitCommandsTestBase.java +++ b/src/test/java/redis/clients/jedis/commands/unified/BitCommandsTestBase.java @@ -292,4 +292,294 @@ public void testBinaryBitfieldReadonly() { assertEquals(1L, responses2.get(0).longValue()); } + @Test + @SinceRedisVersion("8.1.240") + public void bitOpDiff() { + // Use single-byte values for simplicity + byte[] key1 = new byte[] { (byte) 0x07 }; // 00000111 - bits 0,1,2 set + byte[] key2 = new byte[] { (byte) 0x02 }; // 00000010 - bit 1 set + byte[] key3 = new byte[] { (byte) 0x04 }; // 00000100 - bit 2 set + String destKey = "{bitOp:key:}resultDiff"; + + // Set keys using byte arrays + jedis.set("{bitOp:key:}1".getBytes(), key1); + jedis.set("{bitOp:key:}2".getBytes(), key2); + jedis.set("{bitOp:key:}3".getBytes(), key3); + + // DIFF(key1, key2, key3) = key1 AND NOT(key2 OR key3) + // key1 = 00000111 (bits 0,1,2 set) + // key2 = 00000010 (bit 1 set) + // key3 = 00000100 (bit 2 set) + // key2 OR key3 = 00000110 (bits 1,2 set) + // NOT(key2 OR key3) = 11111001 (all bits except 1,2 set) + // key1 AND NOT(key2 OR key3) = 00000001 (only bit 0 set) + jedis.bitop(BitOP.DIFF, destKey, "{bitOp:key:}1", "{bitOp:key:}2", "{bitOp:key:}3"); + + // Get result as bytes + byte[] resultBytes = jedis.get(destKey).getBytes(); + + // Expected result: 00000001 (only bit 0 set) + byte[] expectedBytes = new byte[] { (byte) 0x01 }; + + // Verify the result + assertArrayEquals(expectedBytes, resultBytes); + } + + @Test + @SinceRedisVersion("8.1.240") + public void bitOpDiff1() { + // Use single-byte values for simplicity + byte[] key1 = new byte[] { (byte) 0x07 }; // 00000111 - bits 0,1,2 set + byte[] key2 = new byte[] { (byte) 0x02 }; // 00000010 - bit 1 set + byte[] key3 = new byte[] { (byte) 0x04 }; // 00000100 - bit 2 set + String destKey = "{bitOp:key:}resultDiff1"; + + // Set keys using byte arrays + jedis.set("{bitOp:key:}1".getBytes(), key1); + jedis.set("{bitOp:key:}2".getBytes(), key2); + jedis.set("{bitOp:key:}3".getBytes(), key3); + + // DIFF1(key1, key2, key3) = NOT(key1) AND (key2 OR key3) + // key1 = 00000111 (bits 0,1,2 set) + // key2 = 00000010 (bit 1 set) + // key3 = 00000100 (bit 2 set) + // key2 OR key3 = 00000110 (bits 1,2 set) + // NOT(key1) = 11111000 (all bits except 0,1,2 set) + // NOT(key1) AND (key2 OR key3) = 00000000 (no bits set) + jedis.bitop(BitOP.DIFF1, destKey, "{bitOp:key:}1", "{bitOp:key:}2", "{bitOp:key:}3"); + + // Get result as bytes + byte[] resultBytes = jedis.get(destKey).getBytes(); + + // Expected result: 00000000 (no bits set) + byte[] expectedBytes = new byte[] { (byte) 0x00 }; + + // Verify the result + assertArrayEquals(expectedBytes, resultBytes); + } + + @Test + @SinceRedisVersion("8.1.240") + public void bitOpAndor() { + // Use single-byte values for simplicity + byte[] key1 = new byte[] { (byte) 0x07 }; // 00000111 - bits 0,1,2 set + byte[] key2 = new byte[] { (byte) 0x02 }; // 00000010 - bit 1 set + byte[] key3 = new byte[] { (byte) 0x04 }; // 00000100 - bit 2 set + String destKey = "{bitOp:key:}resultAndor"; + + // Set keys using byte arrays + jedis.set("{bitOp:key:}1".getBytes(), key1); + jedis.set("{bitOp:key:}2".getBytes(), key2); + jedis.set("{bitOp:key:}3".getBytes(), key3); + + // ANDOR(key1, key2, key3) = key1 AND (key2 OR key3) + // key1 = 00000111 (bits 0,1,2 set) + // key2 = 00000010 (bit 1 set) + // key3 = 00000100 (bit 2 set) + // key2 OR key3 = 00000110 (bits 1,2 set) + // key1 AND (key2 OR key3) = 00000110 (bits 1,2 set) + jedis.bitop(BitOP.ANDOR, destKey, "{bitOp:key:}1", "{bitOp:key:}2", "{bitOp:key:}3"); + + // Get result as bytes + byte[] resultBytes = jedis.get(destKey).getBytes(); + + // Expected result: 00000110 (bits 1,2 set) + byte[] expectedBytes = new byte[] { (byte) 0x06 }; + + // Verify the result + assertArrayEquals(expectedBytes, resultBytes); + } + + @Test + @SinceRedisVersion("8.1.240") + public void bitOpOne() { + // Use single-byte values for simplicity + byte[] key1 = new byte[] { (byte) 0x01 }; // 00000001 - bit 0 set + byte[] key2 = new byte[] { (byte) 0x02 }; // 00000010 - bit 1 set + byte[] key3 = new byte[] { (byte) 0x04 }; // 00000100 - bit 2 set + String destKey = "{bitOp:key:}resultOne"; + + // Set keys using byte arrays + jedis.set("{bitOp:key:}1".getBytes(), key1); + jedis.set("{bitOp:key:}2".getBytes(), key2); + jedis.set("{bitOp:key:}3".getBytes(), key3); + + // ONE(key1, key2, key3) = bits set in exactly one of the inputs + // key1 = 00000001 (bit 0 set) + // key2 = 00000010 (bit 1 set) + // key3 = 00000100 (bit 2 set) + // Result = 00000111 (bits 0,1,2 set - each in exactly one input) + jedis.bitop(BitOP.ONE, destKey, "{bitOp:key:}1", "{bitOp:key:}2", "{bitOp:key:}3"); + + // Get result as bytes + byte[] resultBytes = jedis.get(destKey).getBytes(); + + // Expected result: 00000111 (bits 0,1,2 set) + byte[] expectedBytes = new byte[] { (byte) 0x07 }; + + // Verify the result + assertArrayEquals(expectedBytes, resultBytes); + } + + @Test + @SinceRedisVersion("8.1.240") + public void bitOpDiffBinary() { + byte[] key1 = { (byte) 0x07 }; // 00000111 - bits 0,1,2 set + byte[] key2 = { (byte) 0x02 }; // 00000010 - bit 1 set + byte[] key3 = { (byte) 0x04 }; // 00000100 - bit 2 set + byte[] dest = "{bitOp:key:}resultDiffBinary".getBytes(); + + jedis.set("{bitOp:key:}1".getBytes(), key1); + jedis.set("{bitOp:key:}2".getBytes(), key2); + jedis.set("{bitOp:key:}3".getBytes(), key3); + + // DIFF(key1, key2, key3) = key1 AND NOT(key2 OR key3) + // key1 = 00000111 (bits 0,1,2 set) + // key2 = 00000010 (bit 1 set) + // key3 = 00000100 (bit 2 set) + // key2 OR key3 = 00000110 (bits 1,2 set) + // NOT(key2 OR key3) = 11111001 (all bits except 1,2 set) + // key1 AND NOT(key2 OR key3) = 00000001 (only bit 0 set) + jedis.bitop(BitOP.DIFF, dest, "{bitOp:key:}1".getBytes(), "{bitOp:key:}2".getBytes(), + "{bitOp:key:}3".getBytes()); + + // Expected result: 00000001 (only bit 0 set) + byte[] expectedBytes = new byte[] { (byte) 0x01 }; + + // Verify the result + assertArrayEquals(expectedBytes, jedis.get(dest)); + } + + @Test + @SinceRedisVersion("8.1.240") + public void bitOpDiff1Binary() { + byte[] key1 = { (byte) 0x07 }; // 00000111 - bits 0,1,2 set + byte[] key2 = { (byte) 0x02 }; // 00000010 - bit 1 set + byte[] key3 = { (byte) 0x04 }; // 00000100 - bit 2 set + byte[] dest = "{bitOp:key:}resultDiff1Binary".getBytes(); + + jedis.set("{bitOp:key:}1".getBytes(), key1); + jedis.set("{bitOp:key:}2".getBytes(), key2); + jedis.set("{bitOp:key:}3".getBytes(), key3); + + // DIFF1(key1, key2, key3) = NOT(key1) AND (key2 OR key3) + // key1 = 00000111 (bits 0,1,2 set) + // key2 = 00000010 (bit 1 set) + // key3 = 00000100 (bit 2 set) + // key2 OR key3 = 00000110 (bits 1,2 set) + // NOT(key1) = 11111000 (all bits except 0,1,2 set) + // NOT(key1) AND (key2 OR key3) = 00000000 (no bits set) + jedis.bitop(BitOP.DIFF1, dest, "{bitOp:key:}1".getBytes(), "{bitOp:key:}2".getBytes(), + "{bitOp:key:}3".getBytes()); + + // Expected result: 00000000 (no bits set) + byte[] expectedBytes = new byte[] { (byte) 0x00 }; + + // Verify the result + assertArrayEquals(expectedBytes, jedis.get(dest)); + } + + @Test + @SinceRedisVersion("8.1.240") + public void bitOpAndorBinary() { + byte[] key1 = { (byte) 0x07 }; // 00000111 - bits 0,1,2 set + byte[] key2 = { (byte) 0x02 }; // 00000010 - bit 1 set + byte[] key3 = { (byte) 0x04 }; // 00000100 - bit 2 set + byte[] dest = "{bitOp:key:}resultAndorBinary".getBytes(); + + jedis.set("{bitOp:key:}1".getBytes(), key1); + jedis.set("{bitOp:key:}2".getBytes(), key2); + jedis.set("{bitOp:key:}3".getBytes(), key3); + + // ANDOR(key1, key2, key3) = key1 AND (key2 OR key3) + // key1 = 00000111 (bits 0,1,2 set) + // key2 = 00000010 (bit 1 set) + // key3 = 00000100 (bit 2 set) + // key2 OR key3 = 00000110 (bits 1,2 set) + // key1 AND (key2 OR key3) = 00000110 (bits 1,2 set) + jedis.bitop(BitOP.ANDOR, dest, "{bitOp:key:}1".getBytes(), "{bitOp:key:}2".getBytes(), + "{bitOp:key:}3".getBytes()); + + // Expected result: 00000110 (bits 1,2 set) + byte[] expectedBytes = new byte[] { (byte) 0x06 }; + + // Verify the result + assertArrayEquals(expectedBytes, jedis.get(dest)); + } + + @Test + @SinceRedisVersion("8.1.240") + public void bitOpOneBinary() { + byte[] key1 = { (byte) 0x01 }; // 00000001 - bit 0 set + byte[] key2 = { (byte) 0x02 }; // 00000010 - bit 1 set + byte[] key3 = { (byte) 0x04 }; // 00000100 - bit 2 set + byte[] dest = "{bitOp:key:}resultOneBinary".getBytes(); + + jedis.set("{bitOp:key:}1".getBytes(), key1); + jedis.set("{bitOp:key:}2".getBytes(), key2); + jedis.set("{bitOp:key:}3".getBytes(), key3); + + // ONE(key1, key2, key3) = bits set in exactly one of the inputs + // key1 = 00000001 (bit 0 set) + // key2 = 00000010 (bit 1 set) + // key3 = 00000100 (bit 2 set) + // Result = 00000111 (bits 0,1,2 set - each in exactly one input) + jedis.bitop(BitOP.ONE, dest, "{bitOp:key:}1".getBytes(), "{bitOp:key:}2".getBytes(), + "{bitOp:key:}3".getBytes()); + + // Expected result: 00000111 (bits 0,1,2 set) + byte[] expectedBytes = new byte[] { (byte) 0x07 }; + + // Verify the result + assertArrayEquals(expectedBytes, jedis.get(dest)); + } + + @Test + @SinceRedisVersion("8.1.240") + public void bitOpDiffSingleSourceShouldFail() { + assertThrows(JedisDataException.class, + () -> jedis.bitop(BitOP.DIFF, "{bitOp:key:}dest", "{bitOp:key:}{bitOp:key:}src1")); + } + + @Test + @SinceRedisVersion("8.1.240") + public void bitOpDiff1SingleSourceShouldFail() { + assertThrows(JedisDataException.class, + () -> jedis.bitop(BitOP.DIFF1, "{bitOp:key:}dest", "{bitOp:key:}src1")); + } + + @Test + @SinceRedisVersion("8.1.240") + public void bitOpAndorSingleSourceShouldFail() { + assertThrows(JedisDataException.class, + () -> jedis.bitop(BitOP.ANDOR, "{bitOp:key:}dest", "{bitOp:key:}src1")); + } + + @Test + @SinceRedisVersion("8.1.240") + public void bitOpDiffBinarySingleSourceShouldFail() { + byte[] dest = "{bitOp:key:}dest".getBytes(); + byte[] src1 = "{bitOp:key:}src1".getBytes(); + + assertThrows(JedisDataException.class, () -> jedis.bitop(BitOP.DIFF, dest, src1)); + } + + @Test + @SinceRedisVersion("8.1.240") + public void bitOpDiff1BinarySingleSourceShouldFail() { + byte[] dest = "{bitOp:key:}dest".getBytes(); + byte[] src1 = "{bitOp:key:}src1".getBytes(); + + assertThrows(JedisDataException.class, () -> jedis.bitop(BitOP.DIFF1, dest, src1)); + } + + @Test + @SinceRedisVersion("8.1.240") + public void bitOpAndorBinarySingleSourceShouldFail() { + byte[] dest = "{bitOp:key:}dest".getBytes(); + byte[] src1 = "{bitOp:key:}src1".getBytes(); + + assertThrows(JedisDataException.class, () -> jedis.bitop(BitOP.ANDOR, dest, src1)); + } + }