Skip to content

Commit 4b10f2e

Browse files
ggivosazzad16
andauthored
Test with 8.0-M04-pre (#4069)
* Test with 8.0-M03-pre * Test with 8.0-M03-pre * Test with 8.0-M03 * Test with 8.0-M04-pre * SearchDefaultDialectTest.testDialectsWithFTExplain Output of ft.explain has changed in Redis 8.0. Existing Jedis client ftExplain() API returns the raw output and does not perform any parsing/mapping, hence updating the test to verify only for received output when used with correct dialect & gets syntax error otherwise. * Update testAggregationBuilderAddScores test to match change in SEARCH module replacing default SCORER from TF-IDF to BM25. * Apply suggestions from code review Co-authored-by: M Sazzadul Hoque <[email protected]> * Address review comments * Update SearchDefaultDialectTest.java * Output of ft.explain  has changed in Redis 8.0. Existing Jedis client ftExplain() API returns the raw output  and does not perform any parsing/mapping, hence updating the test to verify only for received output when used with correct dialect & gets syntax error otherwise. * minor changes: format, private, unused variable, etc. --------- Co-authored-by: M Sazzadul Hoque <[email protected]>
1 parent 3e537f9 commit 4b10f2e

File tree

6 files changed

+149
-111
lines changed

6 files changed

+149
-111
lines changed

.github/workflows/test-on-docker.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ jobs:
3636
fail-fast: false
3737
matrix:
3838
redis_version:
39-
- "8.0-M02"
39+
- "8.0-M04-pre"
4040
- "7.4.1"
4141
- "7.2.6"
4242
# - "6.2.16"

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
PATH := ./redis-git/src:${PATH}
22

33
# Supported test env versions
4-
SUPPORTED_TEST_ENV_VERSIONS := 8.0-M02 7.4.1 7.2.6 6.2.16
5-
DEFAULT_TEST_ENV_VERSION := 8.0-M02
4+
SUPPORTED_TEST_ENV_VERSIONS := 8.0-M04-pre, 8.0-M02 7.4.1 7.2.6 6.2.16
5+
DEFAULT_TEST_ENV_VERSION := 8.0-M04-pre
66
REDIS_ENV_WORK_DIR := $(or ${REDIS_ENV_WORK_DIR},/tmp/redis-env-work)
77

88
define REDIS1_CONF

src/test/java/redis/clients/jedis/modules/search/AggregationTest.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import redis.clients.jedis.search.aggr.FtAggregateIteration;
3838
import redis.clients.jedis.search.schemafields.NumericField;
3939
import redis.clients.jedis.search.schemafields.TextField;
40+
import redis.clients.jedis.util.RedisConditions;
4041

4142
@RunWith(Parameterized.class)
4243
public class AggregationTest extends RedisModuleCommandsTestBase {
@@ -202,7 +203,7 @@ public void testAggregationBuilderVerbatim() {
202203
}
203204

204205
@Test
205-
@SinceRedisVersion(value="7.4.0", message="ADDSCORES")
206+
@SinceRedisVersion(value = "7.4.0", message = "ADDSCORES")
206207
public void testAggregationBuilderAddScores() {
207208
Schema sc = new Schema();
208209
sc.addSortableTextField("name", 1.0);
@@ -215,8 +216,15 @@ public void testAggregationBuilderAddScores() {
215216
.apply("@__score * 100", "normalized_score").dialect(3);
216217

217218
AggregationResult res = client.ftAggregate(index, r);
218-
assertEquals(2, res.getRow(0).getLong("__score"));
219-
assertEquals(200, res.getRow(0).getLong("normalized_score"));
219+
if (RedisConditions.of(client).moduleVersionIsGreatherThan("SEARCH", 79900)) {
220+
// Default scorer is BM25
221+
assertEquals(0.6931, res.getRow(0).getDouble("__score"), 0.0001);
222+
assertEquals(69.31, res.getRow(0).getDouble("normalized_score"), 0.01);
223+
} else {
224+
// Default scorer is TF-IDF
225+
assertEquals(2, res.getRow(0).getLong("__score"));
226+
assertEquals(200, res.getRow(0).getLong("normalized_score"));
227+
}
220228
}
221229

222230
@Test

src/test/java/redis/clients/jedis/modules/search/SearchDefaultDialectTest.java

Lines changed: 32 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,23 @@
11
package redis.clients.jedis.modules.search;
22

3-
import static org.junit.Assert.*;
3+
import static org.hamcrest.MatcherAssert.assertThat;
4+
import static org.hamcrest.Matchers.containsString;
5+
import static org.hamcrest.Matchers.emptyOrNullString;
6+
import static org.hamcrest.Matchers.not;
7+
import static org.junit.Assert.assertEquals;
8+
import static org.junit.Assert.assertNotNull;
9+
import static org.junit.Assert.assertThrows;
410
import static redis.clients.jedis.util.AssertUtil.assertOK;
511

612
import java.util.*;
713

8-
import org.hamcrest.MatcherAssert;
9-
import org.hamcrest.Matchers;
10-
import org.junit.Assert;
1114
import org.junit.BeforeClass;
1215
import org.junit.Test;
1316
import org.junit.runner.RunWith;
1417
import org.junit.runners.Parameterized;
1518

1619
import redis.clients.jedis.RedisProtocol;
20+
import redis.clients.jedis.UnifiedJedis;
1721
import redis.clients.jedis.exceptions.JedisDataException;
1822
import redis.clients.jedis.search.*;
1923
import redis.clients.jedis.search.schemafields.NumericField;
@@ -107,62 +111,34 @@ public void testDialectsWithFTExplain() throws Exception {
107111

108112
String q = "(*)";
109113
Query query = new Query(q).dialect(1);
110-
try {
111-
client.ftExplain(INDEX, query);
112-
fail();
113-
} catch (JedisDataException e) {
114-
assertTrue("Should contain 'Syntax error'", e.getMessage().contains("Syntax error"));
115-
}
116-
query = new Query(q); // dialect=default=2
117-
assertTrue("Should contain 'WILDCARD'", client.ftExplain(INDEX, query).contains("WILDCARD"));
114+
assertSyntaxError(query, client); // dialect=1 throws syntax error
115+
query = new Query(q); // dialect=default=2 should return execution plan
116+
assertThat(client.ftExplain(INDEX, query), containsString("WILDCARD"));
118117

119118
q = "$hello";
120119
query = new Query(q).dialect(1);
121-
try {
122-
client.ftExplain(INDEX, query);
123-
fail();
124-
} catch (JedisDataException e) {
125-
assertTrue("Should contain 'Syntax error'", e.getMessage().contains("Syntax error"));
126-
}
127-
query = new Query(q).addParam("hello", "hello"); // dialect=default=2
128-
assertTrue("Should contain 'UNION {\n hello\n +hello(expanded)\n}\n'",
129-
client.ftExplain(INDEX, query).contains("UNION {\n hello\n +hello(expanded)\n}\n"));
120+
assertSyntaxError(query, client); // dialect=1 throws syntax error
121+
query = new Query(q).addParam("hello", "hello"); // dialect=default=2 should return execution plan
122+
assertThat(client.ftExplain(INDEX, query), not(emptyOrNullString()));
123+
130124

131125
q = "@title:(@num:[0 10])";
132-
query = new Query(q).dialect(1);
133-
assertTrue("Should contain 'NUMERIC {0.000000 <= @num <= 10.000000}'",
134-
client.ftExplain(INDEX, query).contains("NUMERIC {0.000000 <= @num <= 10.000000}"));
126+
query = new Query(q).dialect(1); // dialect=1 should return execution plan
127+
assertThat(client.ftExplain(INDEX, query), not(emptyOrNullString()));
135128
query = new Query(q); // dialect=default=2
136-
try {
137-
client.ftExplain(INDEX, query);
138-
fail();
139-
} catch (JedisDataException e) {
140-
assertTrue("Should contain 'Syntax error'", e.getMessage().contains("Syntax error"));
141-
}
129+
assertSyntaxError(query, client); // dialect=2 throws syntax error
142130

143131
q = "@t1:@t2:@t3:hello";
144-
query = new Query(q).dialect(1);
145-
assertTrue("Should contain '@NULL:UNION {\n @NULL:hello\n @NULL:+hello(expanded)\n}\n'",
146-
client.ftExplain(INDEX, query).contains("@NULL:UNION {\n @NULL:hello\n @NULL:+hello(expanded)\n}\n"));
132+
query = new Query(q).dialect(1); // dialect=1 should return execution plan
133+
assertThat(client.ftExplain(INDEX, query), not(emptyOrNullString()));
147134
query = new Query(q); // dialect=default=2
148-
try {
149-
client.ftExplain(INDEX, query);
150-
fail();
151-
} catch (JedisDataException e) {
152-
assertTrue("Should contain 'Syntax error'", e.getMessage().contains("Syntax error"));
153-
}
135+
assertSyntaxError(query, client); // dialect=2 throws syntax error
154136

155137
q = "@title:{foo}}}}}";
156-
query = new Query(q).dialect(1);
157-
assertTrue("Should contain 'TAG:@title {\n foo\n}\n'",
158-
client.ftExplain(INDEX, query).contains("TAG:@title {\n foo\n}\n"));
138+
query = new Query(q).dialect(1); // dialect=1 should return execution plan
139+
assertThat(client.ftExplain(INDEX, query), not(emptyOrNullString()));
159140
query = new Query(q); // dialect=default=2
160-
try {
161-
client.ftExplain(INDEX, query);
162-
fail();
163-
} catch (JedisDataException e) {
164-
assertTrue("Should contain 'Syntax error'", e.getMessage().contains("Syntax error"));
165-
}
141+
assertSyntaxError(query, client); // dialect=2 throws syntax error
166142
}
167143

168144
@Test
@@ -194,9 +170,15 @@ public void testAggregationBuilderParamsDialect() {
194170
@Test
195171
public void dialectBoundSpellCheck() {
196172
client.ftCreate(INDEX, TextField.of("t"));
197-
JedisDataException error = Assert.assertThrows(JedisDataException.class,
173+
JedisDataException error = assertThrows(JedisDataException.class,
198174
() -> client.ftSpellCheck(INDEX, "Tooni toque kerfuffle",
199175
FTSpellCheckParams.spellCheckParams().dialect(0)));
200-
MatcherAssert.assertThat(error.getMessage(), Matchers.containsString("DIALECT requires a non negative integer"));
176+
assertThat(error.getMessage(), containsString("DIALECT requires a non negative integer"));
177+
}
178+
179+
private void assertSyntaxError(Query query, UnifiedJedis client) {
180+
JedisDataException error = assertThrows(JedisDataException.class,
181+
() -> client.ftExplain(INDEX, query));
182+
assertThat(error.getMessage(), containsString("Syntax error"));
201183
}
202184
}

src/test/java/redis/clients/jedis/modules/search/SearchTest.java

Lines changed: 26 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
package redis.clients.jedis.modules.search;
22

3+
import static org.hamcrest.MatcherAssert.assertThat;
4+
import static org.hamcrest.Matchers.containsString;
5+
import static org.hamcrest.Matchers.emptyOrNullString;
6+
import static org.hamcrest.Matchers.not;
37
import static org.junit.Assert.*;
48

59
import java.util.*;
610
import java.util.stream.Collectors;
711

8-
import io.redis.test.annotations.SinceRedisVersion;
912
import io.redis.test.utils.RedisVersion;
1013
import org.hamcrest.Matchers;
1114
import org.junit.Assume;
@@ -15,6 +18,7 @@
1518
import org.junit.runners.Parameterized;
1619

1720
import redis.clients.jedis.RedisProtocol;
21+
import redis.clients.jedis.UnifiedJedis;
1822
import redis.clients.jedis.exceptions.JedisDataException;
1923
import redis.clients.jedis.json.Path;
2024
import redis.clients.jedis.search.*;
@@ -1078,84 +1082,45 @@ public void testDialectsWithFTExplain() throws Exception {
10781082

10791083
String q = "(*)";
10801084
Query query = new Query(q).dialect(1);
1081-
try {
1082-
client.ftExplain(index, query);
1083-
fail();
1084-
} catch (JedisDataException e) {
1085-
assertTrue("Should contain 'Syntax error'", e.getMessage().contains("Syntax error"));
1086-
}
1085+
assertSyntaxError(query, client); // dialect=1 throws syntax error
10871086
query = new Query(q).dialect(2);
1088-
assertTrue("Should contain 'WILDCARD'", client.ftExplain(index, query).contains("WILDCARD"));
1087+
assertThat(client.ftExplain(index, query), containsString("WILDCARD"));
10891088

10901089
q = "$hello";
10911090
query = new Query(q).dialect(1);
1092-
try {
1093-
client.ftExplain(index, query);
1094-
fail();
1095-
} catch (JedisDataException e) {
1096-
assertTrue("Should contain 'Syntax error'", e.getMessage().contains("Syntax error"));
1097-
}
1091+
assertSyntaxError(query, client); // dialect=1 throws syntax error
10981092
query = new Query(q).dialect(2).addParam("hello", "hello");
1099-
assertTrue("Should contain 'UNION {\n hello\n +hello(expanded)\n}\n'",
1100-
client.ftExplain(index, query).contains("UNION {\n hello\n +hello(expanded)\n}\n"));
1093+
assertThat(client.ftExplain(index, query), not(emptyOrNullString()));
11011094

11021095
q = "@title:(@num:[0 10])";
11031096
query = new Query(q).dialect(1);
1104-
assertTrue("Should contain 'NUMERIC {0.000000 <= @num <= 10.000000}'",
1105-
client.ftExplain(index, query).contains("NUMERIC {0.000000 <= @num <= 10.000000}"));
1097+
assertThat(client.ftExplain(index, query), not(emptyOrNullString()));
11061098
query = new Query(q).dialect(2);
1107-
try {
1108-
client.ftExplain(index, query);
1109-
fail();
1110-
} catch (JedisDataException e) {
1111-
assertTrue("Should contain 'Syntax error'", e.getMessage().contains("Syntax error"));
1112-
}
1099+
assertSyntaxError(query, client); // dialect=2 throws syntax error
11131100

11141101
q = "@t1:@t2:@t3:hello";
11151102
query = new Query(q).dialect(1);
1116-
assertTrue("Should contain '@NULL:UNION {\n @NULL:hello\n @NULL:+hello(expanded)\n}\n'",
1117-
client.ftExplain(index, query).contains("@NULL:UNION {\n @NULL:hello\n @NULL:+hello(expanded)\n}\n"));
1103+
assertThat(client.ftExplain(index, query), not(emptyOrNullString()));
11181104
query = new Query(q).dialect(2);
1119-
try {
1120-
client.ftExplain(index, query);
1121-
fail();
1122-
} catch (JedisDataException e) {
1123-
assertTrue("Should contain 'Syntax error'", e.getMessage().contains("Syntax error"));
1124-
}
1105+
assertSyntaxError(query, client); // dialect=2 throws syntax error
11251106

11261107
q = "@title:{foo}}}}}";
11271108
query = new Query(q).dialect(1);
1128-
assertTrue("Should contain 'TAG:@title {\n foo\n}\n'",
1129-
client.ftExplain(index, query).contains("TAG:@title {\n foo\n}\n"));
1109+
assertThat(client.ftExplain(index, query), not(emptyOrNullString()));
11301110
query = new Query(q).dialect(2);
1131-
try {
1132-
client.ftExplain(index, query);
1133-
fail();
1134-
} catch (JedisDataException e) {
1135-
assertTrue("Should contain 'Syntax error'", e.getMessage().contains("Syntax error"));
1136-
}
1111+
assertSyntaxError(query, client); // dialect=2 throws syntax error
11371112

11381113
q = "*=>[KNN 10 @v $BLOB]";
11391114
query = new Query(q).addParam("BLOB", "aaaa").dialect(1);
1140-
try {
1141-
client.ftExplain(index, query);
1142-
fail();
1143-
} catch (JedisDataException e) {
1144-
assertTrue("Should contain 'Syntax error'", e.getMessage().contains("Syntax error"));
1145-
}
1115+
assertSyntaxError(query, client); // dialect=1 throws syntax error
11461116
query = new Query(q).addParam("BLOB", "aaaa").dialect(2);
1147-
assertTrue("Should contain '{K=10 nearest vector'", client.ftExplain(index, query).contains("{K=10 nearest vector"));
1117+
assertThat(client.ftExplain(index, query), not(emptyOrNullString()));
11481118

1149-
q = "*=>[knn $K @vec_field $BLOB as score]";
1119+
q = "*=>[knn $K @v $BLOB as score]";
11501120
query = new Query(q).addParam("BLOB", "aaaa").addParam("K", "10").dialect(1);
1151-
try {
1152-
client.ftExplain(index, query);
1153-
fail();
1154-
} catch (JedisDataException e) {
1155-
assertTrue("Should contain 'Syntax error'", e.getMessage().contains("Syntax error"));
1156-
}
1121+
assertSyntaxError(query, client); // dialect=1 throws syntax error
11571122
query = new Query(q).addParam("BLOB", "aaaa").addParam("K", "10").dialect(2);
1158-
assertTrue("Should contain '{K=10 nearest vector'", client.ftExplain(index, query).contains("{K=10 nearest vector"));
1123+
assertThat(client.ftExplain(index, query), not(emptyOrNullString()));
11591124
}
11601125

11611126
@org.junit.Ignore
@@ -1298,4 +1263,10 @@ public void searchIteration() throws Exception {
12981263
}
12991264
assertEquals(7, total);
13001265
}
1266+
1267+
void assertSyntaxError(Query query, UnifiedJedis client) {
1268+
JedisDataException error = assertThrows(JedisDataException.class,
1269+
() -> client.ftExplain(index, query));
1270+
assertThat(error.getMessage(), containsString("Syntax error"));
1271+
}
13011272
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package redis.clients.jedis.util;
2+
3+
import io.redis.test.utils.RedisVersion;
4+
import redis.clients.jedis.CommandArguments;
5+
import redis.clients.jedis.CommandObject;
6+
import redis.clients.jedis.Module;
7+
import redis.clients.jedis.UnifiedJedis;
8+
import redis.clients.jedis.resps.CommandInfo;
9+
10+
import java.util.List;
11+
import java.util.Map;
12+
import java.util.stream.Collectors;
13+
14+
import static redis.clients.jedis.BuilderFactory.MODULE_LIST;
15+
import static redis.clients.jedis.Protocol.Command.COMMAND;
16+
import static redis.clients.jedis.Protocol.Command.MODULE;
17+
import static redis.clients.jedis.Protocol.Keyword.LIST;
18+
19+
public class RedisConditions {
20+
21+
private final RedisVersion version;
22+
private final Map<String, Integer> modules;
23+
private final Map<String, CommandInfo> commands;
24+
25+
private RedisConditions(RedisVersion version, Map< String, CommandInfo> commands, Map<String, Integer> modules) {
26+
this.version = version;
27+
this.commands = commands;
28+
this.modules = modules;
29+
}
30+
31+
public static RedisConditions of(UnifiedJedis jedis) {
32+
RedisVersion version = RedisVersionUtil.getRedisVersion(jedis);
33+
34+
CommandObject<Map<String, CommandInfo>> commandInfoCmd
35+
= new CommandObject<>(new CommandArguments(COMMAND), CommandInfo.COMMAND_INFO_RESPONSE);
36+
Map<String, CommandInfo> commands = jedis.executeCommand(commandInfoCmd);
37+
38+
CommandObject<List<Module>> moduleListCmd
39+
= new CommandObject<>(new CommandArguments(MODULE).add(LIST), MODULE_LIST);
40+
41+
Map<String, Integer> modules = jedis.executeCommand(moduleListCmd)
42+
.stream()
43+
.collect(Collectors.toMap((m) -> m.getName().toUpperCase(), Module::getVersion));
44+
45+
return new RedisConditions(version, commands, modules);
46+
}
47+
48+
public RedisVersion getVersion() {
49+
return version;
50+
}
51+
52+
/**
53+
* @param command
54+
* @return {@code true} if the command is present.
55+
*/
56+
public boolean hasCommand(String command) {
57+
return commands.containsKey(command.toUpperCase());
58+
}
59+
60+
/**
61+
* @param module
62+
* @return {@code true} if the module is present.
63+
*/
64+
public boolean hasModule(String module) {
65+
return modules.containsKey(module.toUpperCase());
66+
}
67+
68+
/**
69+
* @param module
70+
* @param version
71+
* @return {@code true} if the module is present.
72+
*/
73+
public boolean moduleVersionIsGreatherThan(String module, int version) {
74+
Integer moduleVersion = modules.get(module.toUpperCase());
75+
return moduleVersion != null && moduleVersion > version;
76+
}
77+
}

0 commit comments

Comments
 (0)