Skip to content

Commit

Permalink
Introducing test containers to the testing fw
Browse files Browse the repository at this point in the history
  • Loading branch information
tishun committed Aug 9, 2024
1 parent fc5d14b commit 0a4e38c
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 77 deletions.
15 changes: 15 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,21 @@
<scope>test</scope>
</dependency>

<!-- TEST CONTAINERS -->

<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>1.20.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<version>1.20.1</version>
<scope>test</scope>
</dependency>

</dependencies>

<build>
Expand Down
4 changes: 1 addition & 3 deletions src/main/java/io/lettuce/core/RedisJsonCommandBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -255,9 +255,7 @@ Command<K, V, String> jsonSet(K key, JsonPath jsonPath, JsonValue<K, V> value, J

CommandArgs<K, V> args = new CommandArgs<>(codec).addKey(key);

if (jsonPath != null && !jsonPath.isRootPath()) {
args.add(jsonPath.toString());
}
args.add(jsonPath.toString());

args.add(value.asByteBuffer().array());

Expand Down
75 changes: 44 additions & 31 deletions src/test/java/io/lettuce/core/RedisContainerIntegrationTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,52 +3,65 @@
* All rights reserved.
*
* Licensed under the MIT License.
*
* This file contains contributions from third-party contributors
* licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.lettuce.core;

import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.async.RedisAsyncCommands;
import io.lettuce.core.api.sync.RedisCommands;
import io.lettuce.core.json.JsonPath;
import io.lettuce.core.json.JsonValue;
import io.lettuce.core.json.arguments.JsonSetArgs;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.utility.DockerImageName;

import java.time.Duration;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

@Testcontainers
public class RedisContainerIntegrationTests {

// TODO use https://java.testcontainers.org/supported_docker_environment/
protected static RedisAsyncCommands<String, String> redis;
@Container
public GenericContainer redisContainer = new GenericContainer(image).withExposedPorts(6379).withReuse(true);;

private static DockerImageName image = DockerImageName.parse("redis/redis-stack:latest");

private static RedisClient client;

protected static RedisCommands<String, String> redis;

@BeforeEach
public void prepare() throws IOException {
if (!redisContainer.isRunning()) {
redisContainer.start();
}

String address = redisContainer.getHost();
Integer port = redisContainer.getFirstMappedPort();
RedisURI redisURI = RedisURI.Builder.redis(address).withPort(port).build();

client = RedisClient.create(redisURI);
redis = client.connect().sync();

redis.flushall();

protected static RedisClient redisClient;
Path path = Paths.get("src/test/resources/bike-inventory.json");
String read = String.join("", Files.readAllLines(path));
JsonValue<String, String> value = redis.getJsonParser().createJsonValue(read);

@BeforeAll
static void setup() {
RedisURI redisURI = RedisURI.Builder.redis("").withPort(19897)
.withPassword("").withTimeout(Duration.ofSeconds(30)).build();
redisClient = RedisClient.create(redisURI);
StatefulRedisConnection<String, String> connect = redisClient.connect();
redis = connect.async();
redis.jsonSet("bikes:inventory", JsonPath.ROOT_PATH, value, JsonSetArgs.Builder.none());
}

@AfterAll
static void teardown() {
if (redis != null)
redis.getStatefulConnection().close();
if (redisClient != null)
redisClient.shutdown();
if (client != null) {
client.shutdown();
}
}

}
61 changes: 18 additions & 43 deletions src/test/java/io/lettuce/core/json/RedisJsonIntegrationTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,12 @@
* All rights reserved.
*
* Licensed under the MIT License.
*
* This file contains contributions from third-party contributors
* licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.lettuce.core.json;

import io.lettuce.core.RedisContainerIntegrationTests;
import io.lettuce.core.json.arguments.JsonGetArgs;
import io.lettuce.core.json.arguments.JsonRangeArgs;
import io.lettuce.core.json.arguments.JsonSetArgs;
import org.junit.jupiter.api.Test;

Expand All @@ -44,23 +30,17 @@ void jsonArrappend() throws ExecutionException, InterruptedException {
JsonParser<String, String> parser = redis.getJsonParser();

JsonValue<String, String> element = parser.createJsonValue("\"{id:bike6}\"");
List<Long> appendedElements = redis.jsonArrappend(BIKES_INVENTORY, MOUNTAIN_BIKES_PATH, element).get();
List<Long> appendedElements = redis.jsonArrappend(BIKES_INVENTORY, MOUNTAIN_BIKES_PATH, element);
assertThat(appendedElements).hasSize(1);
assertThat(appendedElements.get(0)).isEqualTo(5);

// Cleanup

List<JsonValue<String, String>> poppedJson = redis.jsonArrpop(BIKES_INVENTORY, MOUNTAIN_BIKES_PATH, -1).get();
assertThat(poppedJson).hasSize(1);
assertThat(poppedJson.get(0).toValue()).isEqualTo("\"{id:bike6}\"");
assertThat(appendedElements.get(0)).isEqualTo(4);
}

@Test
void jsonArrindex() throws ExecutionException, InterruptedException {
JsonParser<String, String> parser = redis.getJsonParser();
JsonValue<String, String> element = parser.createJsonValue("\"{id:bike6}\"");
JsonValue<String, String> element = parser.createJsonValue("\"id\": \"bike:2\"");

List<Long> arrayIndex = redis.jsonArrindex(BIKES_INVENTORY, MOUNTAIN_BIKES_PATH, element, null).get();
List<Long> arrayIndex = redis.jsonArrindex(BIKES_INVENTORY, MOUNTAIN_BIKES_PATH, element, null);
assertThat(arrayIndex).isNotNull();
assertThat(arrayIndex.get(0).longValue()).isEqualTo(3L);
}
Expand All @@ -72,18 +52,17 @@ void jsonArrinsert() {

@Test
void jsonArrlen() throws ExecutionException, InterruptedException {
List<Long> poppedJson = redis.jsonArrlen(BIKES_INVENTORY, MOUNTAIN_BIKES_PATH).get();
List<Long> poppedJson = redis.jsonArrlen(BIKES_INVENTORY, MOUNTAIN_BIKES_PATH);
assertThat(poppedJson).hasSize(1);
assertThat(poppedJson.get(0).longValue()).isEqualTo(5);
assertThat(poppedJson.get(0).longValue()).isEqualTo(3);
}

@Test
void jsonArrpop() throws ExecutionException, InterruptedException {
List<JsonValue<String, String>> poppedJson = redis.jsonArrpop(BIKES_INVENTORY, MOUNTAIN_BIKES_PATH, -1).get();
List<JsonValue<String, String>> poppedJson = redis.jsonArrpop(BIKES_INVENTORY, MOUNTAIN_BIKES_PATH, -1);
assertThat(poppedJson).hasSize(1);
assertThat(poppedJson.get(0).toValue()).isEqualTo("\"{id:bike6}\"");

throw new RuntimeException("Missing cleanup");
assertThat(poppedJson.get(0).toValue()).contains(
"{\"id\":\"bike:3\",\"model\":\"Weywot\",\"description\":\"This bike gives kids aged six years and old");
}

@Test
Expand All @@ -101,7 +80,7 @@ void jsonGet() throws ExecutionException, InterruptedException {
JsonPath path = JsonPath.of("$..mountain_bikes[0:2].model");

// Verify codec parsing
List<JsonValue<String, String>> value = redis.jsonGet(BIKES_INVENTORY, JsonGetArgs.Builder.none(), path).get();
List<JsonValue<String, String>> value = redis.jsonGet(BIKES_INVENTORY, JsonGetArgs.Builder.none(), path);
assertThat(value).hasSize(1);
assertThat(value.get(0).toValue()).isEqualTo("[\"Phoebe\",\"Quaoar\"]");

Expand All @@ -127,9 +106,9 @@ void jsonMerge() throws ExecutionException, InterruptedException {
void jsonMGet() throws ExecutionException, InterruptedException {
JsonPath path = JsonPath.of("$..model");

List<JsonValue<String, String>> value = redis.jsonMGet(path, BIKES_INVENTORY).get();
List<JsonValue<String, String>> value = redis.jsonMGet(path, BIKES_INVENTORY);
assertThat(value).hasSize(1);
assertThat(value.get(0).toValue()).isEqualTo("[\"Phoebe\",\"Quaoar\",\"Weywot\",\"Salacia\",\"Mimas\"]");
assertThat(value.get(0).toValue()).isEqualTo("[\"Phoebe\",\"Quaoar\",\"Weywot\"]");
}

@Test
Expand All @@ -141,13 +120,9 @@ void jsonMset() throws ExecutionException, InterruptedException {
void jsonNumincrby() throws ExecutionException, InterruptedException {
JsonPath path = JsonPath.of("$..mountain_bikes[0:1].price");

List<Number> value = redis.jsonNumincrby(BIKES_INVENTORY, path, 5L).get();
assertThat(value).hasSize(1);
assertThat(value.get(0).longValue()).isEqualTo(1930L);

value = redis.jsonNumincrby(BIKES_INVENTORY, path, -5L).get();
List<Number> value = redis.jsonNumincrby(BIKES_INVENTORY, path, 5L);
assertThat(value).hasSize(1);
assertThat(value.get(0).longValue()).isEqualTo(1925L);
assertThat(value.get(0).longValue()).isEqualTo(1933L);
}

@Test
Expand Down Expand Up @@ -182,7 +157,7 @@ void jsonSet() throws ExecutionException, InterruptedException {

JsonSetArgs args = JsonSetArgs.Builder.none();

String result = redis.jsonSet(BIKES_INVENTORY, JsonPath.of(COMMUTER_BIKES), bikeRecord, args).get();
String result = redis.jsonSet(BIKES_INVENTORY, MOUNTAIN_BIKES_PATH, bikeRecord, args);
assertThat(result).isEqualTo("OK");
}

Expand All @@ -203,15 +178,15 @@ void jsonToggle() throws ExecutionException, InterruptedException {

@Test
void jsonDel() throws ExecutionException, InterruptedException {
JsonPath path = JsonPath.of("$..mountain_bikes[3:4]");
JsonPath path = JsonPath.of("$..mountain_bikes[2:3]");

Long value = redis.jsonDel(BIKES_INVENTORY, path).get();
Long value = redis.jsonDel(BIKES_INVENTORY, path);
assertThat(value).isEqualTo(1);
}

@Test
void jsonType() throws ExecutionException, InterruptedException {
String jsonType = redis.jsonType(BIKES_INVENTORY, JsonPath.of(COMMUTER_BIKES)).get().get(0);
String jsonType = redis.jsonType(BIKES_INVENTORY, MOUNTAIN_BIKES_PATH).get(0);
assertThat(jsonType).isEqualTo("array");
}

Expand Down
44 changes: 44 additions & 0 deletions src/test/resources/bike-inventory.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"inventory": {
"mountain_bikes": [
{
"id": "bike:1",
"model": "Phoebe",
"description": "This is a mid-travel trail slayer that is a fantastic daily driver or one bike quiver. The Shimano Claris 8-speed groupset gives plenty of gear range to tackle hills and there's room for mudguards and a rack too. This is the bike for the rider who wants trail manners with low fuss ownership.",
"price": 1928,
"specs": {
"material": "carbon",
"weight": 13.1
},
"colors": [
"black",
"silver"
]
},
{
"id": "bike:2",
"model": "Quaoar",
"description": "Redesigned for the 2020 model year, this bike impressed our testers and is the best all-around trail bike we've ever tested. The Shimano gear system effectively does away with an external cassette, so is super low maintenance in terms of wear and tear. All in all it's an impressive package for the price, making it very competitive.",
"price": 2072,
"specs": {
"material": "aluminium",
"weight": 7.9
},
"colors": [
"black",
"white"
]
},
{
"id": "bike:3",
"model": "Weywot",
"description": "This bike gives kids aged six years and older a durable and uberlight mountain bike for their first experience on tracks and easy cruising through forests and fields. A set of powerful Shimano hydraulic disc brakes provide ample stopping ability. If you're after a budget option, this is one of the best bikes you could get.",
"price": 3264,
"specs": {
"material": "alloy",
"weight": 13.8
}
}
]
}
}

0 comments on commit 0a4e38c

Please sign in to comment.