diff --git a/java/client/build.gradle b/java/client/build.gradle
index 0fb95b43ec..6c8bfe0d67 100644
--- a/java/client/build.gradle
+++ b/java/client/build.gradle
@@ -2,6 +2,7 @@ import java.nio.file.Paths
plugins {
id 'java-library'
+ id 'jacoco'
}
repositories {
@@ -103,4 +104,15 @@ tasks.withType(Test) {
showStandardStreams true
}
jvmArgs "-Djava.library.path=${projectDir}/../target/release:${projectDir}/../target/debug"
+ finalizedBy jacocoTestReport, jacocoTestCoverageVerification
}
+
+jacocoTestReport {
+ afterEvaluate {
+ classDirectories.setFrom(files(classDirectories.files.collect {
+ fileTree(dir: it, exclude: ['**/connection_request/**', '**/response/**', '**/redis_request/**'])
+ }))
+ }
+}
+
+
diff --git a/java/client/src/main/java/glide/models/RequestBuilder.java b/java/client/src/main/java/glide/models/RequestBuilder.java
deleted file mode 100644
index cd8e2dc1b6..0000000000
--- a/java/client/src/main/java/glide/models/RequestBuilder.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package glide.models;
-
-import connection_request.ConnectionRequestOuterClass.ConnectionRequest;
-import connection_request.ConnectionRequestOuterClass.NodeAddress;
-import connection_request.ConnectionRequestOuterClass.ReadFrom;
-import connection_request.ConnectionRequestOuterClass.TlsMode;
-import glide.connectors.handlers.CallbackDispatcher;
-import glide.managers.CommandManager;
-import glide.managers.ConnectionManager;
-import java.util.List;
-import redis_request.RedisRequestOuterClass.Command;
-import redis_request.RedisRequestOuterClass.Command.ArgsArray;
-import redis_request.RedisRequestOuterClass.RedisRequest;
-import redis_request.RedisRequestOuterClass.RequestType;
-import redis_request.RedisRequestOuterClass.Routes;
-import redis_request.RedisRequestOuterClass.SimpleRoutes;
-
-public class RequestBuilder {
-
- /**
- * Build a protobuf connection request.
- * Used by {@link ConnectionManager#connectToRedis}.
- */
- // TODO support more parameters and/or configuration object
- public static ConnectionRequest createConnectionRequest(
- String host, int port, boolean useSsl, boolean clusterMode) {
- return ConnectionRequest.newBuilder()
- .addAddresses(NodeAddress.newBuilder().setHost(host).setPort(port).build())
- .setTlsMode(useSsl ? TlsMode.SecureTls : TlsMode.NoTls)
- .setClusterModeEnabled(clusterMode)
- .setReadFrom(ReadFrom.Primary)
- .setDatabaseId(0)
- .build();
- }
-
- /**
- * Build a protobuf command/transaction request draft.
- * Used by {@link CommandManager}.
- *
- * @return An uncompleted request. {@link CallbackDispatcher} is responsible to complete it by
- * adding a callback id.
- */
- public static RedisRequest.Builder prepareRedisRequest(RequestType command, List args) {
- var commandArgs = ArgsArray.newBuilder();
- for (var arg : args) {
- commandArgs.addArgs(arg);
- }
-
- return RedisRequest.newBuilder()
- .setSingleCommand(
- Command.newBuilder().setRequestType(command).setArgsArray(commandArgs.build()).build())
- .setRoute(Routes.newBuilder().setSimpleRoutes(SimpleRoutes.AllNodes).build());
- }
-}
diff --git a/java/client/src/test/java/glide/api/ConfigurationTest.java b/java/client/src/test/java/glide/api/ConfigurationTest.java
new file mode 100644
index 0000000000..f5cd7cdd2d
--- /dev/null
+++ b/java/client/src/test/java/glide/api/ConfigurationTest.java
@@ -0,0 +1,138 @@
+package glide.api;
+
+import static glide.api.models.configuration.NodeAddress.DEFAULT_HOST;
+import static glide.api.models.configuration.NodeAddress.DEFAULT_PORT;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+import glide.api.models.configuration.*;
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.jupiter.api.Test;
+
+public class ConfigurationTest {
+ private static String HOST = "aws.com";
+ private static int PORT = 9999;
+
+ private static String USERNAME = "JohnDoe";
+ private static String PASSWORD = "Password1";
+
+ private static int NUM_OF_RETRIES = 5;
+ private static int FACTOR = 10;
+ private static int EXPONENT_BASE = 50;
+
+ private static int DATABASE_ID = 1;
+
+ private static int REQUEST_TIMEOUT = 3;
+
+ @Test
+ public void NodeAddress_DefaultConfig() {
+ NodeAddress nodeAddress = NodeAddress.builder().build();
+
+ assertEquals(DEFAULT_HOST, nodeAddress.getHost());
+ assertEquals(DEFAULT_PORT, nodeAddress.getPort());
+ }
+
+ @Test
+ public void NodeAddress_CustomConfig() {
+ NodeAddress nodeAddress = NodeAddress.builder().host(HOST).port(PORT).build();
+
+ assertEquals(HOST, nodeAddress.getHost());
+ assertEquals(PORT, nodeAddress.getPort());
+ }
+
+ @Test
+ public void BackoffStrategy_CustomConfig() {
+ BackoffStrategy backoffStrategy =
+ BackoffStrategy.builder()
+ .numOfRetries(NUM_OF_RETRIES)
+ .factor(FACTOR)
+ .exponentBase(EXPONENT_BASE)
+ .build();
+
+ assertEquals(NUM_OF_RETRIES, backoffStrategy.getNumOfRetries());
+ assertEquals(FACTOR, backoffStrategy.getFactor());
+ assertEquals(EXPONENT_BASE, backoffStrategy.getExponentBase());
+ }
+
+ @Test
+ public void RedisCredentials_CustomConfig() {
+ RedisCredentials redisCredentials =
+ RedisCredentials.builder().password(PASSWORD).username(USERNAME).build();
+
+ assertEquals(PASSWORD, redisCredentials.getPassword());
+ assertEquals(USERNAME, redisCredentials.getUsername());
+ }
+
+ @Test
+ public void RedisClientConfiguration_DefaultConfig() {
+ RedisClientConfiguration redisClientConfiguration = RedisClientConfiguration.builder().build();
+
+ assertEquals(new ArrayList(), redisClientConfiguration.getAddresses());
+ assertFalse(redisClientConfiguration.isUseTLS());
+ assertEquals(ReadFrom.PRIMARY, redisClientConfiguration.getReadFrom());
+ assertNull(redisClientConfiguration.getCredentials());
+ assertNull(redisClientConfiguration.getRequestTimeout());
+ assertNull(redisClientConfiguration.getDatabaseId());
+ assertNull(redisClientConfiguration.getReconnectStrategy());
+ }
+
+ @Test
+ public void RedisClientConfiguration_CustomConfig() {
+ RedisClientConfiguration redisClientConfiguration =
+ RedisClientConfiguration.builder()
+ .address(NodeAddress.builder().host(HOST).port(PORT).build())
+ .address(NodeAddress.builder().host(DEFAULT_HOST).port(DEFAULT_PORT).build())
+ .useTLS(true)
+ .readFrom(ReadFrom.PREFER_REPLICA)
+ .credentials(RedisCredentials.builder().username(USERNAME).password(PASSWORD).build())
+ .requestTimeout(REQUEST_TIMEOUT)
+ .reconnectStrategy(
+ BackoffStrategy.builder()
+ .numOfRetries(NUM_OF_RETRIES)
+ .exponentBase(EXPONENT_BASE)
+ .factor(FACTOR)
+ .build())
+ .databaseId(DATABASE_ID)
+ .build();
+
+ List expectedAddresses = new ArrayList<>();
+ NodeAddress address1 = NodeAddress.builder().host(HOST).port(PORT).build();
+ NodeAddress address2 = NodeAddress.builder().host(DEFAULT_HOST).port(DEFAULT_PORT).build();
+ expectedAddresses.add(address1);
+ expectedAddresses.add(address2);
+
+ List actualAddresses = redisClientConfiguration.getAddresses();
+ assertEquals(
+ expectedAddresses.size(), actualAddresses.size(), "Lists should be of the same size");
+ for (int i = 0; i < actualAddresses.size(); i++) {
+ NodeAddress actualNodeAddress = actualAddresses.get(i);
+ NodeAddress expectedNodeAddress = expectedAddresses.get(i);
+ assertAll(
+ "Object fields should match",
+ () -> assertEquals(expectedNodeAddress.getHost(), actualNodeAddress.getHost()),
+ () -> assertEquals(expectedNodeAddress.getPort(), actualNodeAddress.getPort()));
+ }
+ assertTrue(redisClientConfiguration.isUseTLS());
+ assertEquals(ReadFrom.PREFER_REPLICA, redisClientConfiguration.getReadFrom());
+ assertEquals(PASSWORD, redisClientConfiguration.getCredentials().getPassword());
+ assertEquals(USERNAME, redisClientConfiguration.getCredentials().getUsername());
+ assertEquals(REQUEST_TIMEOUT, redisClientConfiguration.getRequestTimeout());
+ assertEquals(NUM_OF_RETRIES, redisClientConfiguration.getReconnectStrategy().getNumOfRetries());
+ assertEquals(FACTOR, redisClientConfiguration.getReconnectStrategy().getFactor());
+ assertEquals(EXPONENT_BASE, redisClientConfiguration.getReconnectStrategy().getExponentBase());
+ assertEquals(DATABASE_ID, redisClientConfiguration.getDatabaseId());
+ }
+
+ @Test
+ public void RedisClusterClientConfiguration_DefaultConfig() {
+ RedisClusterClientConfiguration redisClusterClientConfiguration =
+ RedisClusterClientConfiguration.builder().build();
+
+ assertEquals(new ArrayList(), redisClusterClientConfiguration.getAddresses());
+ assertFalse(redisClusterClientConfiguration.isUseTLS());
+ assertEquals(ReadFrom.PRIMARY, redisClusterClientConfiguration.getReadFrom());
+ assertNull(redisClusterClientConfiguration.getCredentials());
+ assertNull(redisClusterClientConfiguration.getRequestTimeout());
+ }
+}
diff --git a/java/client/src/test/java/glide/handlers/ReadHandlerTest.java b/java/client/src/test/java/glide/handlers/ReadHandlerTest.java
new file mode 100644
index 0000000000..198f9e2d7d
--- /dev/null
+++ b/java/client/src/test/java/glide/handlers/ReadHandlerTest.java
@@ -0,0 +1,72 @@
+package glide.handlers;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import glide.connectors.handlers.CallbackDispatcher;
+import glide.connectors.handlers.ReadHandler;
+import io.netty.channel.embedded.EmbeddedChannel;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import response.ResponseOuterClass;
+
+public class ReadHandlerTest {
+
+ EmbeddedChannel embeddedChannel;
+ ReadHandler readHandler;
+ CallbackDispatcher dispatcher;
+
+ @BeforeEach
+ public void init() {
+ dispatcher = mock(CallbackDispatcher.class);
+ readHandler = new ReadHandler(dispatcher);
+ embeddedChannel = new EmbeddedChannel(readHandler);
+ }
+
+ @AfterEach
+ public void teardown() {
+ embeddedChannel.finishAndReleaseAll();
+ }
+
+ @Test
+ public void readHandlerRead_testInboundProtobufMessages() {
+ ResponseOuterClass.Response msg =
+ ResponseOuterClass.Response.newBuilder()
+ .setConstantResponse(ResponseOuterClass.ConstantResponse.OK)
+ .build();
+
+ assertTrue(embeddedChannel.writeInbound(msg, msg, msg));
+ assertTrue(embeddedChannel.finish());
+
+ verify(dispatcher, times(3)).completeRequest(msg);
+ }
+
+ @Test
+ public void readHandlerRead_testInboundProtobufMessages_invalidMessage() {
+
+ String invalidMsg = "Invalid";
+
+ Exception e =
+ assertThrows(
+ Exception.class,
+ () -> embeddedChannel.writeInbound(invalidMsg, invalidMsg, invalidMsg));
+ assertEquals("Unexpected message in socket", e.getMessage());
+
+ verify(dispatcher, times(0)).completeRequest(any());
+
+ ResponseOuterClass.Response msg =
+ ResponseOuterClass.Response.newBuilder()
+ .setConstantResponse(ResponseOuterClass.ConstantResponse.OK)
+ .build();
+ assertTrue(embeddedChannel.writeInbound(msg));
+ assertTrue(embeddedChannel.finish());
+
+ verify(dispatcher, times(1)).completeRequest(msg);
+ }
+}
diff --git a/java/lombok.config b/java/lombok.config
new file mode 100644
index 0000000000..8f7e8aa1ac
--- /dev/null
+++ b/java/lombok.config
@@ -0,0 +1 @@
+lombok.addLombokGeneratedAnnotation = true
\ No newline at end of file