GEODE-8794: Support redis 6 HELLO command (#5856)

- This deals with some specfics related to how the lettuce v6 client
  determines what protocol to use when authentication is also enabled.

Co-authored-by: Sarah <sabbey@pivotal.io>
diff --git a/geode-redis/src/integrationTest/java/org/apache/geode/redis/internal/executor/connection/AuthIntegrationTest.java b/geode-redis/src/integrationTest/java/org/apache/geode/redis/internal/executor/connection/AuthIntegrationTest.java
index 14393e5..f7c8cad 100644
--- a/geode-redis/src/integrationTest/java/org/apache/geode/redis/internal/executor/connection/AuthIntegrationTest.java
+++ b/geode-redis/src/integrationTest/java/org/apache/geode/redis/internal/executor/connection/AuthIntegrationTest.java
@@ -20,6 +20,8 @@
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
+import io.lettuce.core.RedisClient;
+import io.lettuce.core.RedisURI;
 import org.junit.After;
 import org.junit.Test;
 import redis.clients.jedis.Jedis;
@@ -137,4 +139,25 @@
     authorizedJedis.close();
     nonAuthorizedJedis.close();
   }
+
+  @Test
+  public void lettuceAuthClient_withLettuceVersion6() {
+    setupCacheWithPassword();
+
+    RedisURI uri = RedisURI.create(String.format("redis://%s@localhost:%d", PASSWORD, getPort()));
+    RedisClient client = RedisClient.create(uri);
+
+    client.connect().sync().ping();
+  }
+
+  @Test
+  public void lettuceAuthClient_withLettuceVersion6_andNoAuthentication() {
+    setupCacheWithoutPassword();
+
+    RedisURI uri = RedisURI.create(String.format("redis://%s@localhost:%d", PASSWORD, getPort()));
+    RedisClient client = RedisClient.create(uri);
+
+    assertThatThrownBy(() -> client.connect().sync().ping())
+        .hasRootCauseMessage("ERR Client sent AUTH, but no password is set");
+  }
 }
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/RedisCommandSupportLevel.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/RedisCommandSupportLevel.java
index bdfd81f..3971e31 100644
--- a/geode-redis/src/main/java/org/apache/geode/redis/internal/RedisCommandSupportLevel.java
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/RedisCommandSupportLevel.java
@@ -19,5 +19,6 @@
 public enum RedisCommandSupportLevel {
   SUPPORTED,
   UNSUPPORTED,
-  UNIMPLEMENTED
+  UNIMPLEMENTED,
+  UNKNOWN
 }
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/RedisCommandType.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/RedisCommandType.java
index b2aa735..0bf44cd 100755
--- a/geode-redis/src/main/java/org/apache/geode/redis/internal/RedisCommandType.java
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/RedisCommandType.java
@@ -174,8 +174,6 @@
   PUNSUBSCRIBE(new PunsubscribeExecutor(), SUPPORTED, new MinimumParameterRequirements(1)),
   UNSUBSCRIBE(new UnsubscribeExecutor(), SUPPORTED, new MinimumParameterRequirements(1)),
 
-  UNKNOWN(new UnknownExecutor(), SUPPORTED),
-
   /***************************************
    *** Unsupported Commands ***
    ***************************************/
@@ -379,7 +377,12 @@
   ZREVRANK(null, UNIMPLEMENTED),
   ZSCORE(null, UNIMPLEMENTED),
   ZUNIONSCORE(null, UNIMPLEMENTED),
-  ZSCAN(null, UNIMPLEMENTED);
+  ZSCAN(null, UNIMPLEMENTED),
+
+  /***************************************
+   *** Unknown Commands ***
+   ***************************************/
+  UNKNOWN(new UnknownExecutor(), RedisCommandSupportLevel.UNKNOWN);
 
   private final Executor executor;
   private final ParameterRequirements parameterRequirements;
@@ -416,6 +419,10 @@
     return supportLevel == UNIMPLEMENTED;
   }
 
+  public boolean isUnknown() {
+    return supportLevel == RedisCommandSupportLevel.UNKNOWN;
+  }
+
   public boolean isAllowedWhileSubscribed() {
     switch (this) {
       case SUBSCRIBE:
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/netty/Command.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/netty/Command.java
index 1be6134..6aa154b 100755
--- a/geode-redis/src/main/java/org/apache/geode/redis/internal/netty/Command.java
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/netty/Command.java
@@ -80,6 +80,10 @@
     return commandType.isUnimplemented();
   }
 
+  public boolean isUnknown() {
+    return commandType.isUnknown();
+  }
+
   /**
    * Used to get the command element list
    *
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/netty/ExecutionHandlerContext.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/netty/ExecutionHandlerContext.java
index de3ba83..68e3811 100644
--- a/geode-redis/src/main/java/org/apache/geode/redis/internal/netty/ExecutionHandlerContext.java
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/netty/ExecutionHandlerContext.java
@@ -281,6 +281,11 @@
             channel.remoteAddress().toString());
       }
 
+      if (command.isUnknown()) {
+        writeToChannel(command.execute(this));
+        return;
+      }
+
       if (!isAuthenticated()) {
         writeToChannel(handleUnAuthenticatedCommand(command));
         return;
diff --git a/geode-redis/src/test/java/org/apache/geode/redis/internal/SupportedCommandsJUnitTest.java b/geode-redis/src/test/java/org/apache/geode/redis/internal/SupportedCommandsJUnitTest.java
index fa2872e..a6bd34f 100644
--- a/geode-redis/src/test/java/org/apache/geode/redis/internal/SupportedCommandsJUnitTest.java
+++ b/geode-redis/src/test/java/org/apache/geode/redis/internal/SupportedCommandsJUnitTest.java
@@ -58,7 +58,6 @@
       "SUBSCRIBE",
       "TTL",
       "TYPE",
-      "UNKNOWN",
       "UNSUBSCRIBE",
   };
 
@@ -231,6 +230,10 @@
       "ZSCAN"
   };
 
+  private final String[] unknownCommands = new String[] {
+      "UNKNOWN"
+  };
+
   @Test
   public void crossCheckAllUnsupportedCommands_areMarkedUnsupported() {
     for (String commandName : unSupportedCommands) {
@@ -278,8 +281,9 @@
     List<String> allCommands = new ArrayList<>(asList(supportedCommands));
     allCommands.addAll(asList(unSupportedCommands));
 
-    List<String> implementedCommands =
-        getAllImplementedCommands().stream().map(Enum::name).collect(Collectors.toList());
+    List<String> implementedCommands = getAllImplementedCommands().stream()
+        .filter(c -> !c.isUnknown())
+        .map(Enum::name).collect(Collectors.toList());
 
     assertThat(implementedCommands).containsExactlyInAnyOrderElementsOf(allCommands);
   }
@@ -289,6 +293,7 @@
     List<String> allCommands = new ArrayList<>(asList(supportedCommands));
     allCommands.addAll(asList(unSupportedCommands));
     allCommands.addAll(asList(unImplementedCommands));
+    allCommands.addAll(asList(unknownCommands));
 
     List<String> definedCommands =
         Arrays.stream(RedisCommandType.values()).map(Enum::name).collect(Collectors.toList());