From a8fe28a3792353129a76682d6714e33d6ce95ca2 Mon Sep 17 00:00:00 2001 From: Alexander Szyrej Date: Wed, 30 Sep 2026 16:36:29 -0300 Subject: [PATCH] adding password option to reflection based redis client --- .../internal/db/redis/RedisHandler.java | 15 +++++++-- .../redis/ReflectionBasedRedisClient.java | 33 +++++++++++++++---- 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/client-java/controller/src/main/java/org/evomaster/client/java/controller/internal/db/redis/RedisHandler.java b/client-java/controller/src/main/java/org/evomaster/client/java/controller/internal/db/redis/RedisHandler.java index 3e9abc7a1c..07843a944f 100644 --- a/client-java/controller/src/main/java/org/evomaster/client/java/controller/internal/db/redis/RedisHandler.java +++ b/client-java/controller/src/main/java/org/evomaster/client/java/controller/internal/db/redis/RedisHandler.java @@ -96,9 +96,18 @@ public List getEvaluatedRedisCommands() { operations.stream() .filter(command -> command.getType().shouldCalculateHeuristic()) .forEach(redisCommand -> { - RedisDistanceWithMetrics distanceWithMetrics = computeDistance(redisCommand, redisClient); - evaluatedRedisCommands.add(new RedisCommandEvaluation(redisCommand, distanceWithMetrics)); - registerFailedCommand(redisCommand, distanceWithMetrics.getDistance()); + try { + RedisDistanceWithMetrics distanceWithMetrics = computeDistance(redisCommand, redisClient); + evaluatedRedisCommands.add(new RedisCommandEvaluation(redisCommand, distanceWithMetrics)); + registerFailedCommand(redisCommand, distanceWithMetrics.getDistance()); + } catch (Exception e) { + // A single command must never take down the whole test evaluation: this is + // reported here (rather than left to computeDistance's own catch) because it + // also covers registerFailedCommand/createFailedCommand, which parse whatever + // query string the SUT happened to build, including malformed ones no grammar + // here accounts for. + SimpleLogger.warn("Could not evaluate Redis command " + redisCommand + ": " + e, e); + } }); operations.clear(); diff --git a/client-java/controller/src/main/java/org/evomaster/client/java/controller/redis/ReflectionBasedRedisClient.java b/client-java/controller/src/main/java/org/evomaster/client/java/controller/redis/ReflectionBasedRedisClient.java index 1d35495ac8..4d1f8e063a 100644 --- a/client-java/controller/src/main/java/org/evomaster/client/java/controller/redis/ReflectionBasedRedisClient.java +++ b/client-java/controller/src/main/java/org/evomaster/client/java/controller/redis/ReflectionBasedRedisClient.java @@ -55,12 +55,24 @@ public class ReflectionBasedRedisClient { * @param keyspace Logical database index. Default is 0. */ public ReflectionBasedRedisClient(String host, int port, int keyspace) { + this(host, port, keyspace, null); + } + + /** + * Creates the Redis connection. + * @param host Redis database host. + * @param port Redis database port. + * @param keyspace Logical database index. Default is 0. + * @param password password to authenticate with, as set by {@code requirepass}. Null or empty + * if the server does not require authentication. + */ + public ReflectionBasedRedisClient(String host, int port, int keyspace, String password) { try { Class redisClientClass = Class.forName("io.lettuce.core.RedisClient"); Class redisURIClass = Class.forName("io.lettuce.core.RedisURI"); Method createUri = redisURIClass.getMethod(CREATE_METHOD, String.class); - Object uri = createUri.invoke(null, "redis://" + host + ":" + port + "/" + keyspace); + Object uri = createUri.invoke(null, buildRedisUrl(host, port, keyspace, password)); Method createClient = redisClientClass.getMethod(CREATE_METHOD, redisURIClass); this.lettuceClient = createClient.invoke(null, uri); @@ -76,7 +88,16 @@ public ReflectionBasedRedisClient(String host, int port, int keyspace) { throw new RuntimeException("Failed to initialize Lettuce Redis client via reflection", e); } - this.jedisClient = createJedisClient(host, port); + this.jedisClient = createJedisClient(host, port, password); + } + + /** + * Builds a standard {@code redis://[:password@]host:port/keyspace} URL, understood by both + * Lettuce's {@code RedisURI.create} and Jedis's {@code UnifiedJedis(String)} constructor. + */ + private static String buildRedisUrl(String host, int port, int keyspace, String password) { + String auth = (password != null && !password.isEmpty()) ? ":" + password + "@" : ""; + return "redis://" + auth + host + ":" + port + "/" + keyspace; } /** @@ -84,13 +105,11 @@ public ReflectionBasedRedisClient(String host, int port, int keyspace) { * Unlike the Lettuce connection above, its absence does not prevent the rest of this client * from working, since plain Redis heuristics have no need for it. */ - private static Object createJedisClient(String host, int port) { + private static Object createJedisClient(String host, int port, String password) { try { - Class hostAndPortClass = Class.forName("redis.clients.jedis.HostAndPort"); - Object hostAndPort = hostAndPortClass.getConstructor(String.class, int.class).newInstance(host, port); - Class unifiedJedisClass = Class.forName("redis.clients.jedis.UnifiedJedis"); - return unifiedJedisClass.getConstructor(hostAndPortClass).newInstance(hostAndPort); + return unifiedJedisClass.getConstructor(String.class) + .newInstance(buildRedisUrl(host, port, 0, password)); } catch (Exception e) { return null; }