Skip to content

Commit 7a5bce1

Browse files
authored
Extensive unit tests for the CommandObjects class (#3796)
Write isolated unit test for the different methods of the CommandObjects class. These can be tested by themselves, without considerations like cluster, sentinel or other orthogonal aspects. Structure the tests into logical groups, similar to how the Redis commands are documented on the redis.io website. For each group of commands there is a corresponding test class. The main goal is to have the test code as readable as possible. The methods are kept to a minimum length in general. Sometimes, due to required data preparation, this is not possible. Another goal is to have this as a sort of documentation. Ideally someone who reads these tests should be able to grasp what the Redis commands are doing. This being said, the tests still focus on testing the client. For example negative cases are rarely included, and mostly when they impact the client, for example the parsing of the response. It is not the goal of these tests to test the Redis server itself. Co-authored-by: Gabriel Erzse <[email protected]>
1 parent c7a1687 commit 7a5bce1

26 files changed

+10023
-0
lines changed

pom.xml

+6
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,12 @@
127127
<version>${jackson.version}</version>
128128
<scope>test</scope>
129129
</dependency>
130+
<dependency>
131+
<groupId>net.javacrumbs.json-unit</groupId>
132+
<artifactId>json-unit</artifactId>
133+
<version>2.38.0</version> <!-- 3.x requires Java 17 -->
134+
<scope>test</scope>
135+
</dependency>
130136

131137
<!-- circuit breaker / failover -->
132138
<dependency>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
package redis.clients.jedis.commands.commandobjects;
2+
3+
import static org.hamcrest.MatcherAssert.assertThat;
4+
import static org.hamcrest.Matchers.contains;
5+
import static org.hamcrest.Matchers.equalTo;
6+
7+
import java.util.List;
8+
9+
import org.junit.Test;
10+
import redis.clients.jedis.RedisProtocol;
11+
import redis.clients.jedis.args.BitCountOption;
12+
import redis.clients.jedis.args.BitOP;
13+
import redis.clients.jedis.params.BitPosParams;
14+
15+
/**
16+
* Tests related to <a href="https://redis.io/commands/?group=bitmap">Bitmap</a> commands.
17+
*/
18+
public class CommandObjectsBitmapCommandsTest extends CommandObjectsStandaloneTestBase {
19+
20+
public CommandObjectsBitmapCommandsTest(RedisProtocol protocol) {
21+
super(protocol);
22+
}
23+
24+
@Test
25+
public void testSetbitAndGetbit() {
26+
String key = "bitKey";
27+
long offset = 10;
28+
29+
Boolean initialValue = exec(commandObjects.getbit(key, offset));
30+
assertThat(initialValue, equalTo(false));
31+
32+
Boolean setbit = exec(commandObjects.setbit(key, offset, true));
33+
assertThat(setbit, equalTo(false)); // original value returned
34+
35+
Boolean finalValue = exec(commandObjects.getbit(key, offset));
36+
assertThat(finalValue, equalTo(true));
37+
}
38+
39+
@Test
40+
public void testSetbitAndGetbitBinary() {
41+
byte[] key = "bitKeyBytes".getBytes();
42+
long offset = 10;
43+
44+
Boolean initialValue = exec(commandObjects.getbit(key, offset));
45+
assertThat(initialValue, equalTo(false));
46+
47+
Boolean setbit = exec(commandObjects.setbit(key, offset, true));
48+
assertThat(setbit, equalTo(false)); // original value returned
49+
50+
Boolean finalValue = exec(commandObjects.getbit(key, offset));
51+
assertThat(finalValue, equalTo(true));
52+
}
53+
54+
@Test
55+
public void testBitcount() {
56+
String key = "bitcountKey";
57+
byte[] keyBytes = key.getBytes();
58+
59+
// Set some bits
60+
exec(commandObjects.setbit(key, 1, true));
61+
exec(commandObjects.setbit(key, 2, true));
62+
exec(commandObjects.setbit(key, 7, true)); // This makes 1 byte with 3 bits set
63+
exec(commandObjects.setbit(key, 8, true)); // Next byte, first bit set
64+
65+
Long bitcountFullString = exec(commandObjects.bitcount(key));
66+
assertThat(bitcountFullString, equalTo(4L));
67+
68+
Long bitcountFirstByte = exec(commandObjects.bitcount(key, 0, 0));
69+
assertThat(bitcountFirstByte, equalTo(3L));
70+
71+
Long bitcountFullStringBinary = exec(commandObjects.bitcount(keyBytes));
72+
assertThat(bitcountFullStringBinary, equalTo(4L));
73+
74+
Long bitcountFirstByteBinary = exec(commandObjects.bitcount(keyBytes, 0, 0));
75+
assertThat(bitcountFirstByteBinary, equalTo(3L));
76+
77+
Long bitcountFirstSixBits = exec(commandObjects.bitcount(key, 0, 5, BitCountOption.BIT));
78+
assertThat(bitcountFirstSixBits, equalTo(2L));
79+
80+
Long bitcountFirstSixBitsBinary = exec(commandObjects.bitcount(keyBytes, 0, 5, BitCountOption.BIT));
81+
assertThat(bitcountFirstSixBitsBinary, equalTo(2L));
82+
}
83+
84+
@Test
85+
public void testBitpos() {
86+
String key = "bitposKey";
87+
byte[] keyBytes = key.getBytes();
88+
89+
// Set some bits
90+
exec(commandObjects.setbit(key, 10, true));
91+
exec(commandObjects.setbit(key, 22, true));
92+
exec(commandObjects.setbit(key, 30, true));
93+
94+
Long firstSetBit = exec(commandObjects.bitpos(key, true));
95+
assertThat(firstSetBit, equalTo(10L));
96+
97+
Long firstUnsetBit = exec(commandObjects.bitpos(key, false));
98+
assertThat(firstUnsetBit, equalTo(0L));
99+
100+
BitPosParams params = new BitPosParams(15, 25).modifier(BitCountOption.BIT);
101+
102+
Long firstSetBitInRange = exec(commandObjects.bitpos(key, true, params));
103+
assertThat(firstSetBitInRange, equalTo(22L));
104+
105+
Long firstUnsetBitInRange = exec(commandObjects.bitpos(key, false, params));
106+
assertThat(firstUnsetBitInRange, equalTo(15L));
107+
108+
Long firstSetBitBinary = exec(commandObjects.bitpos(keyBytes, true));
109+
assertThat(firstSetBitBinary, equalTo(10L));
110+
111+
Long firstUnsetBitBinary = exec(commandObjects.bitpos(keyBytes, false));
112+
assertThat(firstUnsetBitBinary, equalTo(0L));
113+
114+
Long firstSetBitInRangeBinary = exec(commandObjects.bitpos(keyBytes, true, params));
115+
assertThat(firstSetBitInRangeBinary, equalTo(22L));
116+
117+
Long firstUnsetBitInRangeBinary = exec(commandObjects.bitpos(keyBytes, false, params));
118+
assertThat(firstUnsetBitInRangeBinary, equalTo(15L));
119+
}
120+
121+
@Test
122+
public void testBitfield() {
123+
String key = "bitfieldKey";
124+
125+
List<Long> bitfieldResult = exec(commandObjects.bitfield(
126+
key, "INCRBY", "i5", "100", "7", "GET", "i5", "100"));
127+
128+
// Contains the result of the INCRBY operation, and the result of the GET operation.
129+
assertThat(bitfieldResult, contains(7L, 7L));
130+
131+
List<Long> bitfieldRoResult = exec(commandObjects.bitfieldReadonly(
132+
key, "GET", "i4", "100"));
133+
assertThat(bitfieldRoResult, contains(3L));
134+
}
135+
136+
@Test
137+
public void testBitfieldBinary() {
138+
byte[] key = "bitfieldKeyBytes".getBytes();
139+
140+
List<Long> bitfieldResult = exec(commandObjects.bitfield(key,
141+
"INCRBY".getBytes(), "i5".getBytes(), "100".getBytes(), "7".getBytes(),
142+
"GET".getBytes(), "i5".getBytes(), "100".getBytes()));
143+
144+
// Contains the result of the INCRBY operation, and the result of the GET operation.
145+
assertThat(bitfieldResult, contains(7L, 7L));
146+
147+
List<Long> bitfieldRoResult = exec(commandObjects.bitfieldReadonly(key,
148+
"GET".getBytes(), "i4".getBytes(), "100".getBytes()));
149+
assertThat(bitfieldRoResult, contains(3L));
150+
}
151+
152+
@Test
153+
public void testBitop() {
154+
String srcKey1 = "srcKey1";
155+
String srcKey2 = "srcKey2";
156+
String destKey = "destKey";
157+
158+
// Set some bits
159+
exec(commandObjects.setbit(srcKey1, 1, true));
160+
exec(commandObjects.setbit(srcKey1, 2, true));
161+
exec(commandObjects.setbit(srcKey1, 3, true));
162+
163+
exec(commandObjects.setbit(srcKey2, 1, true));
164+
exec(commandObjects.setbit(srcKey2, 3, true));
165+
166+
Long bitopResult = exec(commandObjects.bitop(BitOP.AND, destKey, srcKey1, srcKey2));
167+
assertThat(bitopResult, equalTo(1L)); // 1 byte stored
168+
169+
assertThat(exec(commandObjects.getbit(destKey, 1)), equalTo(true));
170+
assertThat(exec(commandObjects.getbit(destKey, 2)), equalTo(false));
171+
assertThat(exec(commandObjects.getbit(destKey, 3)), equalTo(true));
172+
}
173+
174+
@Test
175+
public void testBitopBinary() {
176+
byte[] srcKey1 = "srcKey1".getBytes();
177+
byte[] srcKey2 = "srcKey2".getBytes();
178+
byte[] destKey = "destKey".getBytes();
179+
180+
// Set some bits
181+
exec(commandObjects.setbit(srcKey1, 1, true));
182+
exec(commandObjects.setbit(srcKey1, 2, true));
183+
exec(commandObjects.setbit(srcKey1, 3, true));
184+
185+
exec(commandObjects.setbit(srcKey2, 1, true));
186+
exec(commandObjects.setbit(srcKey2, 3, true));
187+
188+
Long bitopResult = exec(commandObjects.bitop(BitOP.XOR, destKey, srcKey1, srcKey2));
189+
assertThat(bitopResult, equalTo(1L)); // 1 byte stored
190+
191+
assertThat(exec(commandObjects.getbit(new String(destKey), 1)), equalTo(false));
192+
assertThat(exec(commandObjects.getbit(new String(destKey), 2)), equalTo(true));
193+
assertThat(exec(commandObjects.getbit(new String(destKey), 3)), equalTo(false));
194+
}
195+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
package redis.clients.jedis.commands.commandobjects;
2+
3+
import static org.hamcrest.MatcherAssert.assertThat;
4+
import static org.hamcrest.Matchers.contains;
5+
import static org.hamcrest.Matchers.equalTo;
6+
import static org.hamcrest.Matchers.hasEntry;
7+
import static org.hamcrest.Matchers.notNullValue;
8+
9+
import java.util.List;
10+
import java.util.Map;
11+
12+
import org.junit.Test;
13+
import redis.clients.jedis.RedisProtocol;
14+
import redis.clients.jedis.bloom.BFInsertParams;
15+
import redis.clients.jedis.bloom.BFReserveParams;
16+
17+
/**
18+
* Tests related to <a href="https://redis.io/commands/?group=bf">Bloom Filter</a> commands.
19+
*/
20+
public class CommandObjectsBloomFilterCommandsTest extends CommandObjectsModulesTestBase {
21+
22+
public CommandObjectsBloomFilterCommandsTest(RedisProtocol protocol) {
23+
super(protocol);
24+
}
25+
26+
@Test
27+
public void testBfAddAndExists() {
28+
String key = "testBf";
29+
30+
String reserve = exec(commandObjects.bfReserve(key, 0.01, 1000));
31+
assertThat(reserve, equalTo("OK"));
32+
33+
boolean add = exec(commandObjects.bfAdd(key, "item1"));
34+
assertThat(add, equalTo(true));
35+
36+
boolean exists = exec(commandObjects.bfExists(key, "item1"));
37+
assertThat(exists, equalTo(true));
38+
39+
boolean notExists = exec(commandObjects.bfExists(key, "item2"));
40+
assertThat(notExists, equalTo(false));
41+
}
42+
43+
@Test
44+
public void testBfInsert() {
45+
String key = "testBf";
46+
47+
String reserve = exec(commandObjects.bfReserve(key, 0.01, 1000));
48+
assertThat(reserve, equalTo("OK"));
49+
50+
List<Boolean> insert = exec(commandObjects.bfInsert(key, "item1", "item2"));
51+
assertThat(insert, contains(true, true));
52+
53+
BFInsertParams insertParams = new BFInsertParams().noCreate().capacity(1000);
54+
55+
List<Boolean> insertWithParams = exec(commandObjects.bfInsert(key, insertParams, "item1", "item2"));
56+
assertThat(insertWithParams, contains(false, false));
57+
58+
assertThat(exec(commandObjects.bfExists(key, "item1")), equalTo(true));
59+
assertThat(exec(commandObjects.bfExists(key, "item2")), equalTo(true));
60+
assertThat(exec(commandObjects.bfExists(key, "item3")), equalTo(false));
61+
}
62+
63+
@Test
64+
public void testBfMAddMExistsAndCard() {
65+
String key = "testBf";
66+
67+
String reserve = exec(commandObjects.bfReserve(key, 0.01, 1000));
68+
assertThat(reserve, equalTo("OK"));
69+
70+
List<Boolean> mAdd = exec(commandObjects.bfMAdd(key, "item1", "item2", "item3"));
71+
assertThat(mAdd, contains(true, true, true));
72+
73+
List<Boolean> mExists = exec(commandObjects.bfMExists(key, "item1", "item2", "item3", "item4"));
74+
assertThat(mExists, contains(true, true, true, false));
75+
76+
Long card = exec(commandObjects.bfCard(key));
77+
assertThat(card, equalTo(3L));
78+
}
79+
80+
@Test
81+
public void testBfScanDumpAndLoadChunk() {
82+
String key = "test";
83+
84+
String reserve = exec(commandObjects.bfReserve(key, 0.01, 5000));
85+
assertThat(reserve, equalTo("OK"));
86+
87+
for (int i = 0; i < 1000; i++) {
88+
Boolean add = exec(commandObjects.bfAdd(key, "item" + i));
89+
assertThat(add, equalTo(true));
90+
}
91+
92+
String newKey = "testBfLoadChunk";
93+
94+
long iterator = 0;
95+
do {
96+
Map.Entry<Long, byte[]> scanDumpResult = exec(commandObjects.bfScanDump(key, iterator));
97+
98+
iterator = scanDumpResult.getKey();
99+
100+
if (iterator > 0) {
101+
byte[] data = scanDumpResult.getValue();
102+
103+
assertThat(data, notNullValue());
104+
105+
String loadChunk = exec(commandObjects.bfLoadChunk(newKey, iterator, data));
106+
assertThat(loadChunk, equalTo("OK"));
107+
}
108+
} while (iterator != 0);
109+
110+
// verify destination
111+
for (int i = 0; i < 1000; i++) {
112+
Boolean exists = exec(commandObjects.bfExists(newKey, "item" + i));
113+
assertThat(exists, equalTo(true));
114+
}
115+
116+
Boolean missingItem = exec(commandObjects.bfExists(newKey, "item1001"));
117+
assertThat(missingItem, equalTo(false));
118+
}
119+
120+
@Test
121+
public void testBfInfo() {
122+
String key = "testBf";
123+
124+
double errorRate = 0.01;
125+
long capacity = 1000;
126+
BFReserveParams reserveParams = new BFReserveParams().expansion(2);
127+
128+
String reserve = exec(commandObjects.bfReserve(key, errorRate, capacity, reserveParams));
129+
assertThat(reserve, equalTo("OK"));
130+
131+
Boolean add = exec(commandObjects.bfAdd(key, "item1"));
132+
assertThat(add, equalTo(true));
133+
134+
Map<String, Object> info = exec(commandObjects.bfInfo(key));
135+
assertThat(info, hasEntry("Capacity", 1000L));
136+
assertThat(info, hasEntry("Number of items inserted", 1L));
137+
}
138+
}

0 commit comments

Comments
 (0)