This is an automated email from the ASF dual-hosted git repository.
jensdeppe pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode.git
The following commit(s) were added to refs/heads/develop by this push:
new 3ddd9da Geode-8853: DUNIT tests for HSTRLEN command (#5939)
3ddd9da is described below
commit 3ddd9dae75b1cc5b0f3ed45148be225542eb4f57
Author: Ray Ingles <[email protected]>
AuthorDate: Tue Jan 26 09:11:59 2021 -0500
Geode-8853: DUNIT tests for HSTRLEN command (#5939)
- test the error messages for hgetall and hstrlen more specifically
- fix an hgetall test that was testing the wrong command
Co-authored-by: Ray Ingles <[email protected]>
Co-authored-by: Helena A. Bales <[email protected]>
---
.../tools_modules/redis_api_for_geode.html.md.erb | 5 +-
geode-redis/README.md | 88 ++++++++++----------
.../internal/executor/hash/HstrlenDUnitTest.java | 96 ++++++++++++++++++++++
.../hash/AbstractHashesIntegrationTest.java | 22 +++--
4 files changed, 158 insertions(+), 53 deletions(-)
diff --git a/geode-docs/tools_modules/redis_api_for_geode.html.md.erb
b/geode-docs/tools_modules/redis_api_for_geode.html.md.erb
index c4327a4..16a034f 100644
--- a/geode-docs/tools_modules/redis_api_for_geode.html.md.erb
+++ b/geode-docs/tools_modules/redis_api_for_geode.html.md.erb
@@ -68,7 +68,7 @@ The Redis API for <%=vars.product_name%> currently supports
the following comman
**Note**: These commands are supported for Redis 5.
- **Connection**: AUTH, PING, QUIT
-- **Hashes**: HGETALL, HMGET, HMSET, HSET, HVALS
+- **Hashes**: HGETALL, HMGET, HMSET, HSET, HSTRLEN, HVALS
- **Keys**: DEL, EXISTS, EXPIRE, EXPIREAT, KEYS, PERSIST, PEXPIRE,
PEXPIREAT, PTTL, RENAME, TTL,
TYPE
- **Publish/Subscribe**: PUBLISH, PSUBSCRIBE, PUNSUBSCRIBE, SUBSCRIBE,
UNSUBSCRIBE
@@ -80,8 +80,7 @@ commands are available to use, but have not been fully
tested. There is no guara
exactly as expected.
- **Connection**: ECHO, SELECT
-- **Hashes**: HDEL, HEXISTS, HGET, HINCRBY, HINCRBYFLOAT, HKEYS, HLEN,
HSCAN, HSETNX,
- HSTRLEN
+- **Hashes**: HDEL, HEXISTS, HGET, HINCRBY, HINCRBYFLOAT, HKEYS, HLEN,
HSCAN, HSETNX
- **Keys**: SCAN, UNLINK
- **Server**: DBSIZE, FLUSHALL (no async option), FLUSHDB (no async option),
INFO, SHUTDOWN,
SLOWLOG, TIME
diff --git a/geode-redis/README.md b/geode-redis/README.md
index f690001..b8fd770 100644
--- a/geode-redis/README.md
+++ b/geode-redis/README.md
@@ -165,51 +165,51 @@ start server \
| EXPIREAT | DECRBY
| ACL LIST |
| GET | ECHO
| ACL LOAD |
| HGETALL | FLUSHALL
| ACL LOG |
-| HMGET | FLUSHDB
| ACL SAVE |
+| HMGET | FLUSHDB
| ACL SAVE |
| HMSET | GETBIT
| ACL SETUSER |
-| HSET | GETRANGE
| ACL USERS |
-| HVALS | GETSET
| ACL WHOAMI |
-| KEYS | HDEL
| BGREWRITEAOF |
-| PERSIST | HEXISTS
| BGSAVE |
-| PEXPIRE | HGET
| BITFIELD |
-| PEXPIREAT | HINCRBY
| BLPOP |
-| PING | HINCRBYFLOAT
| BRPOP |
-| PSUBSCRIBE | HKEYS
| BRPOPLPUSH |
-| PTTL | HLEN
| BZPOPMAX |
-| PUBLISH | HSCAN
| BZPOPMIN |
-| PUNSUBSCRIBE | HSETNX
| CLIENT CACHING |
-| QUIT | HSTRLEN
| CLIENT GETNAME |
-| RENAME | INCR
| CLIENT GETREDIR |
-| SADD | INCRBY
| CLIENT ID |
-| SET | INCRBYFLOAT
| CLIENT KILL |
-| SMEMBERS | INFO
| CLIENT LIST |
-| SREM | MGET
| CLIENT PAUSE |
-| SUBSCRIBE | MSET
| CLIENT REPLY |
-| TTL | MSETNX
| CLIENT SETNAME |
-| TYPE | PSETEX
| CLIENT TRACKING |
-| UNSUBSCRIBE | SCAN
| CLIENT UNBLOCK |
-| | SCARD
| CLUSTER ADDSLOTS |
-| | SDIFF
| CLUSTER BUMPEPOCH |
-| | SDIFFSTORE
| CLUSTER COUNT-FAILURE-REPORTS |
-| | SELECT
| CLUSTER COUNTKEYSINSLOT |
-| | SETBIT
| CLUSTER DELSLOTS |
-| | SETEX
| CLUSTER FAILOVER |
-| | SETNX
| CLUSTER FLUSHSLOTS |
-| | SETRANGE
| CLUSTER FORGET |
-| | SHUTDOWN
| CLUSTER GETKEYSINSLOT |
-| | SINTER
| CLUSTER INFO |
-| | SINTERSTORE
| CLUSTER KEYSLOT |
-| | SISMEMBER
| CLUSTER MEET |
-| | SLOWLOG
| CLUSTER MYID |
-| | SMOVE
| CLUSTER NODES |
-| | SPOP
| CLUSTER REPLICAS |
-| | SRANDMEMBER
| CLUSTER REPLICATE |
-| | SSCAN
| CLUSTER RESET |
-| | STRLEN
| CLUSTER SAVECONFIG |
-| | SUNION
| CLUSTER SET-CONFIG-EPOCH |
-| | SUNIONSTORE
| CLUSTER SETSLOT |
-| | TIME
| CLUSTER SLAVES |
-| | UNLINK [1]
| CLUSTER SLOTS |
+| HSET | GETRANGE
| ACL USERS |
+| HSTRLEN | GETSET
| ACL WHOAMI |
+| HVALS | HDEL
| BGREWRITEAOF |
+| KEYS | HEXISTS
| BGSAVE |
+| PERSIST | HGET
| BITFIELD |
+| PEXPIRE | HINCRBY
| BLPOP |
+| PEXPIREAT | HINCRBYFLOAT
| BRPOP |
+| PING | HKEYS
| BRPOPLPUSH |
+| PSUBSCRIBE | HLEN
| BZPOPMAX |
+| PTTL | HSCAN
| BZPOPMIN |
+| PUBLISH | HSETNX
| CLIENT CACHING |
+| PUNSUBSCRIBE | INCR
| CLIENT GETNAME |
+| QUIT | INCRBY
| CLIENT GETREDIR |
+| RENAME | INCRBYFLOAT
| CLIENT ID |
+| SADD | INFO
| CLIENT KILL |
+| SET | MGET
| CLIENT LIST |
+| SMEMBERS | MSET
| CLIENT PAUSE |
+| SREM | MSETNX
| CLIENT REPLY |
+| SUBSCRIBE | PSETEX
| CLIENT SETNAME |
+| TTL | SCAN
| CLIENT TRACKING |
+| TYPE | SCARD
| CLIENT UNBLOCK |
+| UNSUBSCRIBE | SDIFF
| CLUSTER ADDSLOTS |
+| | SDIFFSTORE
| CLUSTER BUMPEPOCH |
+| | SELECT
| CLUSTER COUNT-FAILURE-REPORTS |
+| | SETBIT
| CLUSTER COUNTKEYSINSLOT |
+| | SETEX
| CLUSTER DELSLOTS |
+| | SETNX
| CLUSTER FAILOVER |
+| | SETRANGE
| CLUSTER FLUSHSLOTS |
+| | SHUTDOWN
| CLUSTER FORGET |
+| | SINTER
| CLUSTER GETKEYSINSLOT |
+| | SINTERSTORE
| CLUSTER INFO |
+| | SISMEMBER
| CLUSTER KEYSLOT |
+| | SLOWLOG
| CLUSTER MEET |
+| | SMOVE
| CLUSTER MYID |
+| | SPOP
| CLUSTER NODES |
+| | SRANDMEMBER
| CLUSTER REPLICAS |
+| | SSCAN
| CLUSTER REPLICATE |
+| | STRLEN
| CLUSTER RESET |
+| | SUNION
| CLUSTER SAVECONFIG |
+| | SUNIONSTORE
| CLUSTER SET-CONFIG-EPOCH |
+| | TIME
| CLUSTER SETSLOT |
+| | UNLINK [1]
| CLUSTER SLAVES |
+| |
| CLUSTER SLOTS |
| |
| COMMAND |
| |
| COMMAND COUNT |
| |
| COMMAND GETKEYS |
diff --git
a/geode-redis/src/distributedTest/java/org/apache/geode/redis/internal/executor/hash/HstrlenDUnitTest.java
b/geode-redis/src/distributedTest/java/org/apache/geode/redis/internal/executor/hash/HstrlenDUnitTest.java
new file mode 100644
index 0000000..9fecd73
--- /dev/null
+++
b/geode-redis/src/distributedTest/java/org/apache/geode/redis/internal/executor/hash/HstrlenDUnitTest.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
contributor license
+ * agreements. See the NOTICE file distributed with this work for additional
information regarding
+ * copyright ownership. The ASF licenses this file to You 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
+ *
+ * http://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 org.apache.geode.redis.internal.executor.hash;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.Random;
+
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Test;
+import redis.clients.jedis.Jedis;
+
+import org.apache.geode.redis.ConcurrentLoopingThreads;
+import org.apache.geode.test.awaitility.GeodeAwaitility;
+import org.apache.geode.test.dunit.rules.MemberVM;
+import org.apache.geode.test.dunit.rules.RedisClusterStartupRule;
+
+public class HstrlenDUnitTest {
+
+ @ClassRule
+ public static RedisClusterStartupRule clusterStartUp = new
RedisClusterStartupRule(4);
+
+ private static final String LOCAL_HOST = "127.0.0.1";
+ private static final int JEDIS_TIMEOUT =
+ Math.toIntExact(GeodeAwaitility.getTimeout().toMillis());
+ private static Jedis jedis1;
+ private static Jedis jedis2;
+ private static Jedis jedis3;
+
+ @BeforeClass
+ public static void classSetup() {
+ MemberVM locator = clusterStartUp.startLocatorVM(0);
+ clusterStartUp.startRedisVM(1, locator.getPort());
+ clusterStartUp.startRedisVM(2, locator.getPort());
+
+ int redisServerPort1 = clusterStartUp.getRedisPort(1);
+ int redisServerPort2 = clusterStartUp.getRedisPort(2);
+
+ jedis1 = new Jedis(LOCAL_HOST, redisServerPort1, JEDIS_TIMEOUT);
+ jedis2 = new Jedis(LOCAL_HOST, redisServerPort2, JEDIS_TIMEOUT);
+ jedis3 = new Jedis(LOCAL_HOST, redisServerPort1, JEDIS_TIMEOUT);
+ }
+
+ @Before
+ public void testSetup() {
+ jedis1.flushAll();
+ }
+
+ @Test
+ public void hstrlenDoesNotCorruptData_whileHashIsConcurrentlyUpdated() {
+ String key = "key";
+ String field = "field";
+ int iterations = 10000;
+ Random rand = new Random();
+
+ jedis1.hset(key, field, "22");
+
+ new ConcurrentLoopingThreads(iterations,
+ (i) -> {
+ int newLength = rand.nextInt(9) + 1;
+ String newVal = makeStringOfRepeatedDigits(newLength);
+ jedis1.hset(key, field, newVal);
+ },
+ (i) -> assertThat(jedis2.hstrlen(key, field)).isBetween(1L, 9L),
+ (i) -> assertThat(jedis3.hstrlen(key, field)).isBetween(1L, 9L))
+ .run();
+
+ String value = jedis1.hget(key, field);
+ String encodedStringLength = Character.toString(value.charAt(0));
+ int expectedLength = Integer.parseInt(encodedStringLength);
+ assertThat(jedis2.hstrlen(key, field)).isEqualTo(expectedLength);
+ }
+
+ private String makeStringOfRepeatedDigits(int newLength) {
+ String stringOfRepeatedDigits = "";
+ for (int i = 0; i < newLength; i++) {
+ stringOfRepeatedDigits += newLength;
+ }
+ return stringOfRepeatedDigits;
+ }
+}
diff --git
a/geode-redis/src/integrationTest/java/org/apache/geode/redis/internal/executor/hash/AbstractHashesIntegrationTest.java
b/geode-redis/src/integrationTest/java/org/apache/geode/redis/internal/executor/hash/AbstractHashesIntegrationTest.java
index f0c3f2c..7c0de65 100755
---
a/geode-redis/src/integrationTest/java/org/apache/geode/redis/internal/executor/hash/AbstractHashesIntegrationTest.java
+++
b/geode-redis/src/integrationTest/java/org/apache/geode/redis/internal/executor/hash/AbstractHashesIntegrationTest.java
@@ -97,8 +97,8 @@ public abstract class AbstractHashesIntegrationTest
implements RedisPortSupplier
public void testHGetall_givenWrongNumberOfArguments() {
assertThatThrownBy(() -> jedis.sendCommand(Protocol.Command.HGETALL))
.hasMessage("ERR wrong number of arguments for 'hgetall' command");
- assertThatThrownBy(() -> jedis.sendCommand(Protocol.Command.HMSET, "1",
"2"))
- .hasMessage("ERR wrong number of arguments for 'hmset' command");
+ assertThatThrownBy(() -> jedis.sendCommand(Protocol.Command.HGETALL, "1",
"2"))
+ .hasMessage("ERR wrong number of arguments for 'hgetall' command");
}
@Test
@@ -250,6 +250,16 @@ public abstract class AbstractHashesIntegrationTest
implements RedisPortSupplier
}
@Test
+ public void testHStrlen_givenWrongNumberOfArguments() {
+ assertThatThrownBy(() -> jedis.sendCommand(Protocol.Command.HSTRLEN))
+ .hasMessageContaining("ERR wrong number of arguments for 'hstrlen'
command");
+ assertThatThrownBy(() -> jedis.sendCommand(Protocol.Command.HSTRLEN, "1"))
+ .hasMessageContaining("ERR wrong number of arguments for 'hstrlen'
command");
+ assertThatThrownBy(() -> jedis.sendCommand(Protocol.Command.HSTRLEN, "1",
"2", "3"))
+ .hasMessageContaining("ERR wrong number of arguments for 'hstrlen'
command");
+ }
+
+ @Test
public void testHkeys() {
String key = "key";
Map<String, String> hash = new HashMap<String, String>();
@@ -440,13 +450,13 @@ public abstract class AbstractHashesIntegrationTest
implements RedisPortSupplier
@Test
public void hsetnx_shouldThrowError_givenWrongNumberOfArguments() {
assertThatThrownBy(() -> jedis.sendCommand(Protocol.Command.HSETNX))
- .hasMessageContaining("wrong number of arguments");
+ .hasMessageContaining("ERR wrong number of arguments for 'hsetnx'
command");
assertThatThrownBy(() -> jedis.sendCommand(Protocol.Command.HSETNX, "1"))
- .hasMessageContaining("wrong number of arguments");
+ .hasMessageContaining("ERR wrong number of arguments for 'hsetnx'
command");
assertThatThrownBy(() -> jedis.sendCommand(Protocol.Command.HSETNX, "1",
"2"))
- .hasMessageContaining("wrong number of arguments");
+ .hasMessageContaining("ERR wrong number of arguments for 'hsetnx'
command");
assertThatThrownBy(() -> jedis.sendCommand(Protocol.Command.HSETNX, "1",
"2", "3", "4"))
- .hasMessageContaining("wrong number of arguments");
+ .hasMessageContaining("ERR wrong number of arguments for 'hsetnx'
command");
}
/**