From 9b3892b5a5f01f533e8522da67dfbb27c3d0c127 Mon Sep 17 00:00:00 2001 From: Tihomir Mateev Date: Wed, 21 Aug 2024 13:38:47 +0300 Subject: [PATCH] Added Pathv1 tests --- .../lettuce/core/RedisJsonCommandBuilder.java | 27 +-- .../core/json/RedisJsonIntegrationTests.java | 221 +++++++++++------- 2 files changed, 147 insertions(+), 101 deletions(-) diff --git a/src/main/java/io/lettuce/core/RedisJsonCommandBuilder.java b/src/main/java/io/lettuce/core/RedisJsonCommandBuilder.java index 3c3cf7def7..8291384768 100644 --- a/src/main/java/io/lettuce/core/RedisJsonCommandBuilder.java +++ b/src/main/java/io/lettuce/core/RedisJsonCommandBuilder.java @@ -14,14 +14,7 @@ import io.lettuce.core.json.JsonPath; import io.lettuce.core.json.arguments.JsonRangeArgs; import io.lettuce.core.json.arguments.JsonSetArgs; -import io.lettuce.core.output.BooleanOutput; -import io.lettuce.core.output.IntegerListOutput; -import io.lettuce.core.output.IntegerOutput; -import io.lettuce.core.output.JsonValueListOutput; -import io.lettuce.core.output.KeyListOutput; -import io.lettuce.core.output.NumberListOutput; -import io.lettuce.core.output.StatusOutput; -import io.lettuce.core.output.ValueListOutput; +import io.lettuce.core.output.*; import io.lettuce.core.protocol.BaseRedisCommandBuilder; import io.lettuce.core.protocol.Command; import io.lettuce.core.protocol.CommandArgs; @@ -55,7 +48,7 @@ Command> jsonArrappend(K key, JsonPath jsonPath, JsonValue(codec), args); + return createCommand(JSON_ARRAPPEND, (CommandOutput) new ArrayOutput<>(codec), args); } Command> jsonArrindex(K key, JsonPath jsonPath, JsonValue value, JsonRangeArgs range) { @@ -74,7 +67,7 @@ Command> jsonArrindex(K key, JsonPath jsonPath, JsonValue range.build(args); } - return createCommand(JSON_ARRINDEX, new IntegerListOutput<>(codec), args); + return createCommand(JSON_ARRINDEX, (CommandOutput) new ArrayOutput<>(codec), args); } Command> jsonArrinsert(K key, JsonPath jsonPath, int index, JsonValue... values) { @@ -92,7 +85,7 @@ Command> jsonArrinsert(K key, JsonPath jsonPath, int index, Jso args.add(value.asByteBuffer().array()); } - return createCommand(JSON_ARRINSERT, new IntegerListOutput<>(codec), args); + return createCommand(JSON_ARRINSERT, (CommandOutput) new ArrayOutput<>(codec), args); } Command> jsonArrlen(K key, JsonPath jsonPath) { @@ -103,7 +96,7 @@ Command> jsonArrlen(K key, JsonPath jsonPath) { if (jsonPath != null && !jsonPath.isRootPath()) { args.add(jsonPath.toString()); } - return createCommand(JSON_ARRLEN, new IntegerListOutput<>(codec), args); + return createCommand(JSON_ARRLEN, (CommandOutput) new ArrayOutput<>(codec), args); } Command>> jsonArrpop(K key, JsonPath jsonPath, int index) { @@ -136,7 +129,7 @@ Command> jsonArrtrim(K key, JsonPath jsonPath, JsonRangeArgs ra range.build(args); } - return createCommand(JSON_ARRTRIM, new IntegerListOutput<>(codec), args); + return createCommand(JSON_ARRTRIM, (CommandOutput) new ArrayOutput<>(codec), args); } Command jsonClear(K key, JsonPath jsonPath) { @@ -247,7 +240,7 @@ Command> jsonObjlen(K key, JsonPath jsonPath) { args.add(jsonPath.toString()); } - return createCommand(JSON_OBJLEN, new IntegerListOutput<>(codec), args); + return createCommand(JSON_OBJLEN, (CommandOutput) new ArrayOutput<>(codec), args); } Command jsonSet(K key, JsonPath jsonPath, JsonValue value, JsonSetArgs options) { @@ -277,7 +270,7 @@ Command> jsonStrappend(K key, JsonPath jsonPath, JsonValue(codec), args); + return createCommand(JSON_STRAPPEND, (CommandOutput) new ArrayOutput<>(codec), args); } Command> jsonStrlen(K key, JsonPath jsonPath) { @@ -290,7 +283,7 @@ Command> jsonStrlen(K key, JsonPath jsonPath) { args.add(jsonPath.toString()); } - return createCommand(JSON_STRLEN, new IntegerListOutput<>(codec), args); + return createCommand(JSON_STRLEN, (CommandOutput) new ArrayOutput<>(codec), args); } Command> jsonToggle(K key, JsonPath jsonPath) { @@ -302,7 +295,7 @@ Command> jsonToggle(K key, JsonPath jsonPath) { args.add(jsonPath.toString()); } - return createCommand(JSON_TOGGLE, new IntegerListOutput<>(codec), args); + return createCommand(JSON_TOGGLE, (CommandOutput) new ArrayOutput<>(codec), args); } Command jsonDel(K key, JsonPath jsonPath) { diff --git a/src/test/java/io/lettuce/core/json/RedisJsonIntegrationTests.java b/src/test/java/io/lettuce/core/json/RedisJsonIntegrationTests.java index a39b3eb831..1f0b505440 100644 --- a/src/test/java/io/lettuce/core/json/RedisJsonIntegrationTests.java +++ b/src/test/java/io/lettuce/core/json/RedisJsonIntegrationTests.java @@ -12,7 +12,8 @@ import io.lettuce.core.json.arguments.JsonMsetArgs; import io.lettuce.core.json.arguments.JsonRangeArgs; import io.lettuce.core.json.arguments.JsonSetArgs; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import java.util.List; @@ -20,24 +21,33 @@ public class RedisJsonIntegrationTests extends RedisContainerIntegrationTests { - private static final JsonPath MOUNTAIN_BIKES_PATH = JsonPath.of("$..mountain_bikes"); - private static final String BIKES_INVENTORY = "bikes:inventory"; - @Test - void jsonArrappend() { + private static final String BIKE_COLORS_V1 = "..mountain_bikes[1].colors"; + + private static final String BIKE_COLORS_V2 = "$..mountain_bikes[1].colors"; + + private static final String MOUNTAIN_BIKES_V1 = "..mountain_bikes"; + + private static final String MOUNTAIN_BIKES_V2 = "$..mountain_bikes"; + + @ParameterizedTest(name = "With {0} as path") + @ValueSource(strings = { MOUNTAIN_BIKES_V1, MOUNTAIN_BIKES_V2 }) + void jsonArrappend(String path) { JsonParser parser = redis.getJsonParser(); + JsonPath myPath = JsonPath.of(path); JsonValue element = parser.createJsonValue("\"{id:bike6}\""); - List appendedElements = redis.jsonArrappend(BIKES_INVENTORY, MOUNTAIN_BIKES_PATH, element); + List appendedElements = redis.jsonArrappend(BIKES_INVENTORY, myPath, element); assertThat(appendedElements).hasSize(1); assertThat(appendedElements.get(0)).isEqualTo(4); } - @Test - void jsonArrindex() { + @ParameterizedTest(name = "With {0} as path") + @ValueSource(strings = { BIKE_COLORS_V1, BIKE_COLORS_V2 }) + void jsonArrindex(String path) { JsonParser parser = redis.getJsonParser(); - JsonPath myPath = JsonPath.of("$..mountain_bikes[1].colors"); + JsonPath myPath = JsonPath.of(path); JsonValue element = parser.createJsonValue("\"white\""); List arrayIndex = redis.jsonArrindex(BIKES_INVENTORY, myPath, element, null); @@ -46,10 +56,11 @@ void jsonArrindex() { assertThat(arrayIndex.get(0).longValue()).isEqualTo(1L); } - @Test - void jsonArrinsert() { + @ParameterizedTest(name = "With {0} as path") + @ValueSource(strings = { BIKE_COLORS_V1, BIKE_COLORS_V2 }) + void jsonArrinsert(String path) { JsonParser parser = redis.getJsonParser(); - JsonPath myPath = JsonPath.of("$..mountain_bikes[1].colors"); + JsonPath myPath = JsonPath.of(path); JsonValue element = parser.createJsonValue("\"ultramarine\""); List arrayIndex = redis.jsonArrinsert(BIKES_INVENTORY, myPath, 1, element); @@ -58,24 +69,31 @@ void jsonArrinsert() { assertThat(arrayIndex.get(0).longValue()).isEqualTo(3L); } - @Test - void jsonArrlen() { - List poppedJson = redis.jsonArrlen(BIKES_INVENTORY, MOUNTAIN_BIKES_PATH); + @ParameterizedTest(name = "With {0} as path") + @ValueSource(strings = { MOUNTAIN_BIKES_V1, MOUNTAIN_BIKES_V2 }) + void jsonArrlen(String path) { + JsonPath myPath = JsonPath.of(path); + + List poppedJson = redis.jsonArrlen(BIKES_INVENTORY, myPath); assertThat(poppedJson).hasSize(1); assertThat(poppedJson.get(0).longValue()).isEqualTo(3); } - @Test - void jsonArrpop() { - List> poppedJson = redis.jsonArrpop(BIKES_INVENTORY, MOUNTAIN_BIKES_PATH, -1); + @ParameterizedTest(name = "With {0} as path") + @ValueSource(strings = { MOUNTAIN_BIKES_V1, MOUNTAIN_BIKES_V2 }) + void jsonArrpop(String path) { + JsonPath myPath = JsonPath.of(path); + + List> poppedJson = redis.jsonArrpop(BIKES_INVENTORY, myPath, -1); assertThat(poppedJson).hasSize(1); assertThat(poppedJson.get(0).toValue()).contains( "{\"id\":\"bike:3\",\"model\":\"Weywot\",\"description\":\"This bike gives kids aged six years and old"); } - @Test - void jsonArrtrim() { - JsonPath myPath = JsonPath.of("$..mountain_bikes[1].colors"); + @ParameterizedTest(name = "With {0} as path") + @ValueSource(strings = { BIKE_COLORS_V1, BIKE_COLORS_V2 }) + void jsonArrtrim(String path) { + JsonPath myPath = JsonPath.of(path); JsonRangeArgs range = JsonRangeArgs.Builder.start(1).stop(2); List arrayIndex = redis.jsonArrtrim(BIKES_INVENTORY, myPath, range); @@ -84,41 +102,53 @@ void jsonArrtrim() { assertThat(arrayIndex.get(0).longValue()).isEqualTo(1L); } - @Test - void jsonClear() { - JsonPath myPath = JsonPath.of("$..mountain_bikes[1].colors"); + @ParameterizedTest(name = "With {0} as path") + @ValueSource(strings = { BIKE_COLORS_V1, BIKE_COLORS_V2 }) + void jsonClear(String path) { + JsonPath myPath = JsonPath.of(path); Long result = redis.jsonClear(BIKES_INVENTORY, myPath); assertThat(result).isNotNull(); assertThat(result).isEqualTo(1L); } - @Test - void jsonGet() { - JsonPath path = JsonPath.of("$..mountain_bikes[0:2].model"); + @ParameterizedTest(name = "With {0} as path") + @ValueSource(strings = { "..mountain_bikes[0:2].model", "$..mountain_bikes[0:2].model" }) + void jsonGet(String path) { + JsonPath myPath = JsonPath.of(path); // Verify codec parsing - List> value = redis.jsonGet(BIKES_INVENTORY, JsonGetArgs.Builder.none(), path); + List> value = redis.jsonGet(BIKES_INVENTORY, JsonGetArgs.Builder.none(), myPath); assertThat(value).hasSize(1); - assertThat(value.get(0).toValue()).isEqualTo("[\"Phoebe\",\"Quaoar\"]"); - - // Verify array parsing - assertThat(value.get(0).isJsonArray()).isTrue(); - assertThat(value.get(0).asJsonArray().size()).isEqualTo(2); - assertThat(value.get(0).asJsonArray().asList().get(0).toValue()).isEqualTo("\"Phoebe\""); - assertThat(value.get(0).asJsonArray().asList().get(1).toValue()).isEqualTo("\"Quaoar\""); - - // Verify String parsing - assertThat(value.get(0).asJsonArray().asList().get(0).isString()).isTrue(); - assertThat(value.get(0).asJsonArray().asList().get(0).asString()).isEqualTo("Phoebe"); - assertThat(value.get(0).asJsonArray().asList().get(1).isString()).isTrue(); - assertThat(value.get(0).asJsonArray().asList().get(1).asString()).isEqualTo("Quaoar"); + + if (path.startsWith("$")) { + assertThat(value.get(0).toValue()).isEqualTo("[\"Phoebe\",\"Quaoar\"]"); + + // Verify array parsing + assertThat(value.get(0).isJsonArray()).isTrue(); + assertThat(value.get(0).asJsonArray().size()).isEqualTo(2); + assertThat(value.get(0).asJsonArray().asList().get(0).toValue()).isEqualTo("\"Phoebe\""); + assertThat(value.get(0).asJsonArray().asList().get(1).toValue()).isEqualTo("\"Quaoar\""); + + // Verify String parsing + assertThat(value.get(0).asJsonArray().asList().get(0).isString()).isTrue(); + assertThat(value.get(0).asJsonArray().asList().get(0).asString()).isEqualTo("Phoebe"); + assertThat(value.get(0).asJsonArray().asList().get(1).isString()).isTrue(); + assertThat(value.get(0).asJsonArray().asList().get(1).asString()).isEqualTo("Quaoar"); + } else { + assertThat(value.get(0).toValue()).isEqualTo("\"Phoebe\""); + + // Verify array parsing + assertThat(value.get(0).isString()).isTrue(); + assertThat(value.get(0).asString()).isEqualTo("Phoebe"); + } } - @Test - void jsonMerge() { + @ParameterizedTest(name = "With {0} as path") + @ValueSource(strings = { MOUNTAIN_BIKES_V1 + "[1]", MOUNTAIN_BIKES_V2 + "[1]" }) + void jsonMerge(String path) { JsonParser parser = redis.getJsonParser(); - JsonPath myPath = JsonPath.of("$..mountain_bikes[1]"); + JsonPath myPath = JsonPath.of(path); JsonValue element = parser.createJsonValue("\"ultramarine\""); String result = redis.jsonMerge(BIKES_INVENTORY, myPath, element); @@ -126,19 +156,25 @@ void jsonMerge() { assertThat(result).isEqualTo("OK"); } - @Test - void jsonMGet() { - JsonPath path = JsonPath.of("$..model"); + @ParameterizedTest(name = "With {0} as path") + @ValueSource(strings = { "..model", "$..model" }) + void jsonMGet(String path) { + JsonPath myPath = JsonPath.of(path); - List> value = redis.jsonMGet(path, BIKES_INVENTORY); + List> value = redis.jsonMGet(myPath, BIKES_INVENTORY); assertThat(value).hasSize(1); - assertThat(value.get(0).toValue()).isEqualTo("[\"Phoebe\",\"Quaoar\",\"Weywot\"]"); + if (path.startsWith("$")) { + assertThat(value.get(0).toValue()).isEqualTo("[\"Phoebe\",\"Quaoar\",\"Weywot\"]"); + } else { + assertThat(value.get(0).toValue()).isEqualTo("\"Phoebe\""); + } } - @Test - void jsonMset() { + @ParameterizedTest(name = "With {0} as path") + @ValueSource(strings = { MOUNTAIN_BIKES_V1 + "[1]", MOUNTAIN_BIKES_V2 + "[1]" }) + void jsonMset(String path) { JsonParser parser = redis.getJsonParser(); - JsonPath myPath = JsonPath.of("$..mountain_bikes[1]"); + JsonPath myPath = JsonPath.of(path); JsonObject bikeRecord = parser.createEmptyJsonObject(); JsonObject bikeSpecs = parser.createEmptyJsonObject(); @@ -177,18 +213,20 @@ void jsonMset() { assertThat(result).isEqualTo("OK"); } - @Test - void jsonNumincrby() { - JsonPath path = JsonPath.of("$..mountain_bikes[0:1].price"); + @ParameterizedTest(name = "With {0} as path") + @ValueSource(strings = { "$..mountain_bikes[0:1].price", "..mountain_bikes[0:1].price" }) + void jsonNumincrby(String path) { + JsonPath myPath = JsonPath.of(path); - List value = redis.jsonNumincrby(BIKES_INVENTORY, path, 5L); + List value = redis.jsonNumincrby(BIKES_INVENTORY, myPath, 5L); assertThat(value).hasSize(1); assertThat(value.get(0).longValue()).isEqualTo(1933L); } - @Test - void jsonObjkeys() { - JsonPath myPath = JsonPath.of("$..mountain_bikes[1]"); + @ParameterizedTest(name = "With {0} as path") + @ValueSource(strings = { MOUNTAIN_BIKES_V1 + "[1]", MOUNTAIN_BIKES_V2 + "[1]" }) + void jsonObjkeys(String path) { + JsonPath myPath = JsonPath.of(path); List result = redis.jsonObjkeys(BIKES_INVENTORY, myPath); assertThat(result).isNotNull(); @@ -196,9 +234,10 @@ void jsonObjkeys() { assertThat(result).contains("id", "model", "description", "price", "specs", "colors"); } - @Test - void jsonObjlen() { - JsonPath myPath = JsonPath.of("$..mountain_bikes[1]"); + @ParameterizedTest(name = "With {0} as path") + @ValueSource(strings = { MOUNTAIN_BIKES_V1 + "[1]", MOUNTAIN_BIKES_V2 + "[1]" }) + void jsonObjlen(String path) { + JsonPath myPath = JsonPath.of(path); List result = redis.jsonObjlen(BIKES_INVENTORY, myPath); assertThat(result).isNotNull(); @@ -206,8 +245,11 @@ void jsonObjlen() { assertThat(result.get(0)).isEqualTo(6L); } - @Test - void jsonSet() { + @ParameterizedTest(name = "With {0} as path") + @ValueSource(strings = { MOUNTAIN_BIKES_V1, MOUNTAIN_BIKES_V2 }) + void jsonSet(String path) { + JsonPath myPath = JsonPath.of(path); + JsonParser parser = redis.getJsonParser(); JsonObject bikeRecord = parser.createEmptyJsonObject(); JsonObject bikeSpecs = parser.createEmptyJsonObject(); @@ -228,14 +270,15 @@ void jsonSet() { JsonSetArgs args = JsonSetArgs.Builder.none(); - String result = redis.jsonSet(BIKES_INVENTORY, MOUNTAIN_BIKES_PATH, bikeRecord, args); + String result = redis.jsonSet(BIKES_INVENTORY, myPath, bikeRecord, args); assertThat(result).isEqualTo("OK"); } - @Test - void jsonStrappend() { + @ParameterizedTest(name = "With {0} as path") + @ValueSource(strings = { "..mountain_bikes[1].colors[1]", "$..mountain_bikes[1].colors[1]" }) + void jsonStrappend(String path) { JsonParser parser = redis.getJsonParser(); - JsonPath myPath = JsonPath.of("$..mountain_bikes[1].colors[1]"); + JsonPath myPath = JsonPath.of(path); JsonValue element = parser.createJsonValue("\"-light\""); List result = redis.jsonStrappend(BIKES_INVENTORY, myPath, element); @@ -244,10 +287,10 @@ void jsonStrappend() { assertThat(result.get(0)).isEqualTo(11L); } - @Test - void jsonStrlen() { - JsonParser parser = redis.getJsonParser(); - JsonPath myPath = JsonPath.of("$..mountain_bikes[1].colors[1]"); + @ParameterizedTest(name = "With {0} as path") + @ValueSource(strings = { BIKE_COLORS_V1 + "[1]", BIKE_COLORS_V2 + "[1]" }) + void jsonStrlen(String path) { + JsonPath myPath = JsonPath.of(path); List result = redis.jsonStrlen(BIKES_INVENTORY, myPath); assertThat(result).isNotNull(); @@ -255,28 +298,38 @@ void jsonStrlen() { assertThat(result.get(0)).isEqualTo(5L); } - @Test - void jsonToggle() { - JsonParser parser = redis.getJsonParser(); - JsonPath myPath = JsonPath.of("$..complete"); + @ParameterizedTest(name = "With {0} as path") + @ValueSource(strings = { "$..complete", "..complete" }) + void jsonToggle(String path) { + JsonPath myPath = JsonPath.of(path); List result = redis.jsonToggle(BIKES_INVENTORY, myPath); assertThat(result).isNotNull(); assertThat(result).hasSize(1); - assertThat(result.get(0)).isEqualTo(1L); + if (path.startsWith("$")) { + assertThat(result.get(0)).isEqualTo(1L); + } else { + // seems that for JSON.TOGGLE when we use a V1 path the resulting value is a list of string values and not a + // list of integer values as per the documentation + assertThat(result).isNotEmpty(); + } } - @Test - void jsonDel() { - JsonPath path = JsonPath.of("$..mountain_bikes[2:3]"); + @ParameterizedTest(name = "With {0} as path") + @ValueSource(strings = { MOUNTAIN_BIKES_V1 + "[2:3]", MOUNTAIN_BIKES_V2 + "[2:3]" }) + void jsonDel(String path) { + JsonPath myPath = JsonPath.of(path); - Long value = redis.jsonDel(BIKES_INVENTORY, path); + Long value = redis.jsonDel(BIKES_INVENTORY, myPath); assertThat(value).isEqualTo(1); } - @Test - void jsonType() { - String jsonType = redis.jsonType(BIKES_INVENTORY, MOUNTAIN_BIKES_PATH).get(0); + @ParameterizedTest(name = "With {0} as path") + @ValueSource(strings = { MOUNTAIN_BIKES_V1, MOUNTAIN_BIKES_V2 }) + void jsonType(String path) { + JsonPath myPath = JsonPath.of(path); + + String jsonType = redis.jsonType(BIKES_INVENTORY, myPath).get(0); assertThat(jsonType).isEqualTo("array"); }