Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/main/java/redis/clients/jedis/args/BitOP.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,13 @@ public interface BitBinaryCommands {

List<Long> bitfieldReadonly(byte[] key, byte[]... arguments);

/**
* <b><a href="http://redis.io/commands/bitop">Bitop Command</a></b>
* 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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ public interface BitCommands {
/**
* <b><a href="http://redis.io/commands/bitop">Bitop Command</a></b>
* 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
Expand Down
283 changes: 283 additions & 0 deletions src/test/java/redis/clients/jedis/commands/jedis/BitCommandsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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) 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 = "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) 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 = "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));
}
}
Loading
Loading