[
https://issues.apache.org/jira/browse/GEODE-8864?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17273003#comment-17273003
]
ASF GitHub Bot commented on GEODE-8864:
---------------------------------------
jdeppe-pivotal commented on a change in pull request #5954:
URL: https://github.com/apache/geode/pull/5954#discussion_r565469748
##########
File path:
geode-redis/src/integrationTest/java/org/apache/geode/redis/internal/executor/hash/AbstractHScanIntegrationTest.java
##########
@@ -336,48 +418,31 @@ public void
givenMultipleCountsAndMatches_returnsEntriesMatchingLastMatchParamet
}
@Test
- public void givenNegativeCursor_returnsEntriesUsingAbsoluteValueOfCursor() {
+ public void should_notReturnValue_givenValueWasRemovedBeforeHSCANISCalled()
+ throws ExecutionException, InterruptedException {
+
Map<String, String> entryMap = new HashMap<>();
entryMap.put("1", "yellow");
- entryMap.put("2", "green");
- entryMap.put("3", "orange");
+ entryMap.put("12", "green");
+ entryMap.put("3", "grey");
jedis.hmset("colors", entryMap);
+ Future deleteFuture = doAsyncHdel("colors", "3");
+ deleteFuture.get();
Review comment:
I'm not quite sure what this test is trying to show. This async command
ends up simply being synchronous within the flow of the test method and could
be replaced by `jedis.hdel(...`. I think the test should be removed or it
should be clearer what it is testing.
##########
File path:
geode-redis/src/integrationTest/java/org/apache/geode/redis/internal/executor/hash/AbstractHScanIntegrationTest.java
##########
@@ -121,17 +156,10 @@ public void
givenCount_whenCountParameterIsNegative_returnsSyntaxError() {
}
@Test
- public void
givenMultipleCounts_whenAnyCountParameterIsNotAnInteger_returnsNotIntegerError()
{
- jedis.hset("a", "b", "1");
- assertThatThrownBy(() -> jedis.sendCommand(Protocol.Command.HSCAN, "a",
"0", "COUNT", "3",
- "COUNT", "sjlfs", "COUNT", "1"))
- .hasMessageContaining(ERROR_NOT_INTEGER);
- }
+ public void
givenMultipleCounts_whenAnyCountParameterIsLessThanOne_DoesNotError() {
Review comment:
This method name should probably end with `_returnsSyntaxError`
##########
File path:
geode-redis/src/distributedTest/java/org/apache/geode/redis/internal/executor/hash/HScanDunitTest.java
##########
@@ -0,0 +1,178 @@
+/*
+ * 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.apache.geode.distributed.ConfigurationProperties.MAX_WAIT_TIME_RECONNECT;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Test;
+import redis.clients.jedis.Jedis;
+import redis.clients.jedis.ScanResult;
+
+import org.apache.geode.distributed.ConfigurationProperties;
+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 HScanDunitTest {
+ @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;
+
+ private static Properties locatorProperties;
+
+ private static MemberVM locator;
+ private static MemberVM server1;
+ private static MemberVM server2;
+ private static MemberVM server3;
+
+ private static int redisServerPort1;
+ private static int redisServerPort2;
+ private static int redisServerPort3;
+
+ private final int SIZE_OF_INITIAL_HASH_DATA = 1000;
+ private final Map<String, String> INITIAL_HASH_DATA =
makeEntrySet(SIZE_OF_INITIAL_HASH_DATA);
+ final String HASH_KEY = "key";
+ final String BASE_FIELD = "baseField_";
+
+ @BeforeClass
+ public static void classSetup() {
+ locatorProperties = new Properties();
+ locatorProperties.setProperty(MAX_WAIT_TIME_RECONNECT, "15000");
+ locator = clusterStartUp.startLocatorVM(0, locatorProperties);
+ int locatorPort = locator.getPort();
+
+ server1 = clusterStartUp
+ .startRedisVM(1,
+ x ->
x.withProperty(ConfigurationProperties.SERIALIZABLE_OBJECT_FILTER,
+ "org.apache.commons.lang3.tuple.**;org.apache.geode.**")
+ .withConnectionToLocator(locatorPort));
+
+ server2 = clusterStartUp
+ .startRedisVM(2,
+ x ->
x.withProperty(ConfigurationProperties.SERIALIZABLE_OBJECT_FILTER,
+ "org.apache.commons.lang3.tuple.**;org.apache.geode.**")
+ .withConnectionToLocator(locatorPort));
+
+ server3 = clusterStartUp
+ .startRedisVM(3,
+ x ->
x.withProperty(ConfigurationProperties.SERIALIZABLE_OBJECT_FILTER,
+ "org.apache.commons.lang3.tuple.**;org.apache.geode.**")
+ .withConnectionToLocator(locatorPort));
+
+ redisServerPort1 = clusterStartUp.getRedisPort(1);
+ redisServerPort2 = clusterStartUp.getRedisPort(2);
+ redisServerPort3 = clusterStartUp.getRedisPort(3);
+
+ jedis1 = new Jedis(LOCAL_HOST, redisServerPort1, JEDIS_TIMEOUT);
+ jedis2 = new Jedis(LOCAL_HOST, redisServerPort2, JEDIS_TIMEOUT);
+ jedis3 = new Jedis(LOCAL_HOST, redisServerPort3, JEDIS_TIMEOUT);
+ }
+
+ @Before
+ public void testSetup() {
+ jedis1.flushAll();
+ jedis2.flushAll();
+ jedis3.flushAll();
+
+ jedis1.hset(HASH_KEY, INITIAL_HASH_DATA);
+ }
+
+ @AfterClass
+ public static void tearDown() {
+ jedis1.disconnect();
+ jedis2.disconnect();
+ jedis3.disconnect();
+
+ server1.stop();
+ server2.stop();
+ server3.stop();
+ }
+
+ @Test
+ public void
should_notLoseFields_givenConcurrentThreadsDoingHScansAndChangingValues() {
+ final int ITERATION_COUNT = 1000;
+
+ List<Map.Entry<String, String>> allEntries1 = new ArrayList<>();
+ List<Map.Entry<String, String>> allEntries2 = new ArrayList<>();
+
+ new ConcurrentLoopingThreads(ITERATION_COUNT,
+ (i) -> multipleHScanLamba(allEntries1, jedis1),
+ (i) -> multipleHScanLamba(allEntries2, jedis2),
+ (i) -> jedis3.hset(HASH_KEY, BASE_FIELD + i, "new_value_" + i)).run();
+
+ assertThat(allEntries1.size())
+ .isEqualTo(allEntries2.size())
+ .isEqualTo(INITIAL_HASH_DATA.size());
+ }
+
+ @Test
+ public void
should_notLoseDataForConsistentlyPresentFields_givenConcurrentThreadsAddingAndRemovingFields()
{
+ final int ITERATION_COUNT = 1000;
+
+ List<Map.Entry<String, String>> allEntries1 = new ArrayList<>();
+ List<Map.Entry<String, String>> allEntries2 = new ArrayList<>();
+
+ new ConcurrentLoopingThreads(ITERATION_COUNT,
+ (i) -> multipleHScanLamba(allEntries1, jedis1),
+ (i) -> multipleHScanLamba(allEntries2, jedis2),
+ (i) -> {
+ String field = BASE_FIELD + (SIZE_OF_INITIAL_HASH_DATA + i);
+ jedis3.hset(HASH_KEY, field, "whatever");
+ jedis3.hdel(HASH_KEY, field);
+ }).run();
+
+
assertThat(allEntries1).containsOnlyOnceElementsOf(INITIAL_HASH_DATA.entrySet());
Review comment:
Similar problem to the above.
##########
File path:
geode-redis/src/distributedTest/java/org/apache/geode/redis/internal/executor/hash/HScanDunitTest.java
##########
@@ -0,0 +1,178 @@
+/*
+ * 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.apache.geode.distributed.ConfigurationProperties.MAX_WAIT_TIME_RECONNECT;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Test;
+import redis.clients.jedis.Jedis;
+import redis.clients.jedis.ScanResult;
+
+import org.apache.geode.distributed.ConfigurationProperties;
+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 HScanDunitTest {
+ @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;
+
+ private static Properties locatorProperties;
+
+ private static MemberVM locator;
+ private static MemberVM server1;
+ private static MemberVM server2;
+ private static MemberVM server3;
+
+ private static int redisServerPort1;
+ private static int redisServerPort2;
+ private static int redisServerPort3;
+
+ private final int SIZE_OF_INITIAL_HASH_DATA = 1000;
+ private final Map<String, String> INITIAL_HASH_DATA =
makeEntrySet(SIZE_OF_INITIAL_HASH_DATA);
+ final String HASH_KEY = "key";
+ final String BASE_FIELD = "baseField_";
+
+ @BeforeClass
+ public static void classSetup() {
+ locatorProperties = new Properties();
+ locatorProperties.setProperty(MAX_WAIT_TIME_RECONNECT, "15000");
+ locator = clusterStartUp.startLocatorVM(0, locatorProperties);
+ int locatorPort = locator.getPort();
+
+ server1 = clusterStartUp
+ .startRedisVM(1,
+ x ->
x.withProperty(ConfigurationProperties.SERIALIZABLE_OBJECT_FILTER,
+ "org.apache.commons.lang3.tuple.**;org.apache.geode.**")
+ .withConnectionToLocator(locatorPort));
+
+ server2 = clusterStartUp
+ .startRedisVM(2,
+ x ->
x.withProperty(ConfigurationProperties.SERIALIZABLE_OBJECT_FILTER,
+ "org.apache.commons.lang3.tuple.**;org.apache.geode.**")
+ .withConnectionToLocator(locatorPort));
+
+ server3 = clusterStartUp
+ .startRedisVM(3,
+ x ->
x.withProperty(ConfigurationProperties.SERIALIZABLE_OBJECT_FILTER,
+ "org.apache.commons.lang3.tuple.**;org.apache.geode.**")
+ .withConnectionToLocator(locatorPort));
+
+ redisServerPort1 = clusterStartUp.getRedisPort(1);
+ redisServerPort2 = clusterStartUp.getRedisPort(2);
+ redisServerPort3 = clusterStartUp.getRedisPort(3);
+
+ jedis1 = new Jedis(LOCAL_HOST, redisServerPort1, JEDIS_TIMEOUT);
+ jedis2 = new Jedis(LOCAL_HOST, redisServerPort2, JEDIS_TIMEOUT);
+ jedis3 = new Jedis(LOCAL_HOST, redisServerPort3, JEDIS_TIMEOUT);
+ }
+
+ @Before
+ public void testSetup() {
+ jedis1.flushAll();
+ jedis2.flushAll();
+ jedis3.flushAll();
+
+ jedis1.hset(HASH_KEY, INITIAL_HASH_DATA);
+ }
+
+ @AfterClass
+ public static void tearDown() {
+ jedis1.disconnect();
+ jedis2.disconnect();
+ jedis3.disconnect();
+
+ server1.stop();
+ server2.stop();
+ server3.stop();
+ }
+
+ @Test
+ public void
should_notLoseFields_givenConcurrentThreadsDoingHScansAndChangingValues() {
+ final int ITERATION_COUNT = 1000;
+
+ List<Map.Entry<String, String>> allEntries1 = new ArrayList<>();
+ List<Map.Entry<String, String>> allEntries2 = new ArrayList<>();
+
+ new ConcurrentLoopingThreads(ITERATION_COUNT,
+ (i) -> multipleHScanLamba(allEntries1, jedis1),
+ (i) -> multipleHScanLamba(allEntries2, jedis2),
+ (i) -> jedis3.hset(HASH_KEY, BASE_FIELD + i, "new_value_" + i)).run();
+
+ assertThat(allEntries1.size())
Review comment:
I'm not sure this is quite what you want. Since `multipleHScanLamba`
always clears the entries, this assert is only ever checking the result of the
last iteration and not all of them. It might be better it simply count the
results in the lambda and then assert on `ITERATION_COUNT *
SIZE_OF_INITIAL_HASH_DATA`
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]
> finish implementation of Redis HScan Command
> --------------------------------------------
>
> Key: GEODE-8864
> URL: https://issues.apache.org/jira/browse/GEODE-8864
> Project: Geode
> Issue Type: New Feature
> Components: redis
> Reporter: John Hutchison
> Priority: Major
> Labels: pull-request-available
>
--
This message was sent by Atlassian Jira
(v8.3.4#803005)