GEODE-8855: fix hitmiss and stats integration tests (#5937)
GEODE-8855: improve RedisInfoStatsIntegrationTest
- organize tests
- remove tests that don't belong in this class
- fix a formatting issue in RedisCommandType
- make the RedisInfoStatsIntegrationTest run against our redis and native redis
- test all the stats in info
- add and use getExposedPort() so tests work in docker
- make hincrby behavior match that of native
redis
Co-authored-by: Jens Deppe <jdeppe@pivotal.io>
diff --git a/geode-redis/src/acceptanceTest/java/org/apache/geode/redis/internal/executor/server/InfoNativeRedisAcceptanceTest.java b/geode-redis/src/acceptanceTest/java/org/apache/geode/redis/internal/executor/server/InfoNativeRedisAcceptanceTest.java
index 4b07949..3157e03 100644
--- a/geode-redis/src/acceptanceTest/java/org/apache/geode/redis/internal/executor/server/InfoNativeRedisAcceptanceTest.java
+++ b/geode-redis/src/acceptanceTest/java/org/apache/geode/redis/internal/executor/server/InfoNativeRedisAcceptanceTest.java
@@ -30,7 +30,7 @@
}
@Override
- int getExposedPort() {
+ public int getExposedPort() {
return redis.getExposedPort();
}
}
diff --git a/geode-redis/src/acceptanceTest/java/org/apache/geode/redis/internal/executor/server/InfoStatsNativeRedisAcceptanceTest.java b/geode-redis/src/acceptanceTest/java/org/apache/geode/redis/internal/executor/server/InfoStatsNativeRedisAcceptanceTest.java
new file mode 100644
index 0000000..c4f56e0
--- /dev/null
+++ b/geode-redis/src/acceptanceTest/java/org/apache/geode/redis/internal/executor/server/InfoStatsNativeRedisAcceptanceTest.java
@@ -0,0 +1,30 @@
+/*
+ * 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.server;
+
+import org.junit.ClassRule;
+
+import org.apache.geode.NativeRedisTestRule;
+
+public class InfoStatsNativeRedisAcceptanceTest extends AbstractRedisInfoStatsIntegrationTest {
+ @ClassRule
+ public static NativeRedisTestRule redis = new NativeRedisTestRule();
+
+ @Override
+ public int getPort() {
+ return redis.getPort();
+ }
+}
diff --git a/geode-redis/src/commonTest/java/org/apache/geode/NativeRedisTestRule.java b/geode-redis/src/commonTest/java/org/apache/geode/NativeRedisTestRule.java
index 5d0710d..fabff75 100644
--- a/geode-redis/src/commonTest/java/org/apache/geode/NativeRedisTestRule.java
+++ b/geode-redis/src/commonTest/java/org/apache/geode/NativeRedisTestRule.java
@@ -34,6 +34,7 @@
private GenericContainer<?> redisContainer;
private final RuleChain delegate;
private final int PORT_TO_EXPOSE = 6379;
+ private int max_clients = 10000;
public NativeRedisTestRule() {
delegate = RuleChain
@@ -50,6 +51,12 @@
return redisContainer.getExposedPorts().get(0);
}
+ public NativeRedisTestRule withMaxConnections(int max_connections) {
+ this.max_clients = max_connections;
+
+ return this;
+ }
+
@Override
public Statement apply(Statement base, Description description) {
Statement containerStatement = new Statement() {
@@ -58,7 +65,8 @@
redisContainer =
new GenericContainer<>("redis:5.0.6")
- .withExposedPorts(PORT_TO_EXPOSE);
+ .withExposedPorts(PORT_TO_EXPOSE)
+ .withCommand("redis-server --maxclients " + max_clients);
redisContainer.start();
logger.info("Started redis container with exposed port {} -> {}", PORT_TO_EXPOSE,
diff --git a/geode-redis/src/integrationTest/java/org/apache/geode/redis/internal/RedisStatsIntegrationTest.java b/geode-redis/src/integrationTest/java/org/apache/geode/redis/internal/RedisStatsIntegrationTest.java
deleted file mode 100644
index 7e3f2b9..0000000
--- a/geode-redis/src/integrationTest/java/org/apache/geode/redis/internal/RedisStatsIntegrationTest.java
+++ /dev/null
@@ -1,617 +0,0 @@
-/*
- * 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;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-import java.time.Duration;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
-
-import com.google.common.util.concurrent.AtomicDouble;
-import org.assertj.core.data.Offset;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.ClassRule;
-import org.junit.Test;
-import redis.clients.jedis.BitOP;
-import redis.clients.jedis.Jedis;
-
-import org.apache.geode.Statistics;
-import org.apache.geode.StatisticsType;
-import org.apache.geode.cache.CacheFactory;
-import org.apache.geode.distributed.internal.InternalDistributedSystem;
-import org.apache.geode.internal.cache.InternalCache;
-import org.apache.geode.internal.statistics.EnabledStatisticsClock;
-import org.apache.geode.internal.statistics.StatisticsClock;
-import org.apache.geode.redis.GeodeRedisServerRule;
-import org.apache.geode.redis.internal.statistics.RedisStats;
-import org.apache.geode.test.awaitility.GeodeAwaitility;
-
-public class RedisStatsIntegrationTest {
-
- private static final int TIMEOUT = (int) GeodeAwaitility.getTimeout().toMillis();
- private static final String EXISTING_HASH_KEY = "Existing_Hash";
- private static final String EXISTING_STRING_KEY = "Existing_String";
- private static final String EXISTING_SET_KEY_1 = "Existing_Set_1";
- private static final String EXISTING_SET_KEY_2 = "Existing_Set_2";
- private static final String NONEXISTENT_KEY = "Nonexistent_Key";
-
- private Jedis jedis;
- private RedisStats redisStats;
- private static long START_TIME;
- private static StatisticsClock statisticsClock;
-
- private long preTestKeySpaceHits = 0;
- private long preTestKeySpaceMisses = 0;
- private long preTestConnectionsReceived = 0;
- private long preTestConnectedClients = 0;
-
- @ClassRule
- public static GeodeRedisServerRule server = new GeodeRedisServerRule();
-
- private static StatsValidator statsValidator;
-
- private static class StatsValidator {
-
- private final RedisStats redisStats;
- private final Statistics geodeStats;
-
- public StatsValidator(GeodeRedisServerRule serverRule) {
- redisStats = serverRule.getServer().getStats();
-
- InternalCache cache = (InternalCache) CacheFactory.getAnyInstance();
- InternalDistributedSystem system = (InternalDistributedSystem) cache.getDistributedSystem();
-
- StatisticsType statSamplerType = system.findType("RedisStats");
- Statistics[] statsArray = system.findStatisticsByType(statSamplerType);
- assertThat(statsArray).hasSize(1);
-
- geodeStats = statsArray[0];
- }
-
- public void validateKeyspaceHits(long before, long delta) {
- assertThat(redisStats.getKeyspaceHits()).isEqualTo(before + delta);
-
- long geodeKeyspaceHits = geodeStats.getLong("keyspaceHits");
- assertThat(geodeKeyspaceHits).isEqualTo(before + delta);
- }
-
- public void validateKeyspaceMisses(long before, long delta) {
- assertThat(redisStats.getKeyspaceMisses()).isEqualTo(before + delta);
-
- long geodeKeyspaceMisses = geodeStats.getLong("keyspaceMisses");
- assertThat(geodeKeyspaceMisses).isEqualTo(before + delta);
- }
-
- public void validateCommandsProcessed(long before, long delta) {
- GeodeAwaitility.await().atMost(Duration.ofSeconds(5))
- .untilAsserted(() -> assertThat(redisStats.getCommandsProcessed())
- .isEqualTo(before + delta));
-
- GeodeAwaitility.await().atMost(Duration.ofSeconds(5))
- .untilAsserted(() -> {
- long geodeCommandsProcessed = geodeStats.getLong("commandsProcessed");
- assertThat(geodeCommandsProcessed).isEqualTo(before + delta);
- });
- }
-
- public void validateNetworkBytesRead(long before, long delta) {
- assertThat(redisStats.getTotalNetworkBytesRead()).isEqualTo(before + delta);
-
- long geodeNetworkBytesRead = geodeStats.getLong("totalNetworkBytesRead");
- assertThat(geodeNetworkBytesRead).isEqualTo(before + delta);
- }
-
- public void validateConnectedClients(long before, long delta) {
- GeodeAwaitility.await().atMost(Duration.ofSeconds(2))
- .untilAsserted(() -> {
- assertThat(redisStats.getConnectedClients()).isEqualTo(before + delta);
- });
-
- GeodeAwaitility.await().atMost(Duration.ofSeconds(2))
- .untilAsserted(() -> {
- long geodeConnectedClients = geodeStats.getLong("connectedClients");
- assertThat(geodeConnectedClients).isEqualTo(before + delta);
- });
- }
-
- public void validateConnectionsReceived(long before, long delta) {
- assertThat(redisStats.getTotalConnectionsReceived()).isEqualTo(before + delta);
-
- long geodeConnectionsReceived = geodeStats.getLong("totalConnectionsReceived");
- assertThat(geodeConnectionsReceived).isEqualTo(before + delta);
- }
-
- }
-
- @BeforeClass
- public static void beforeClass() {
- statisticsClock = new EnabledStatisticsClock();
- START_TIME = statisticsClock.getTime();
-
- statsValidator = new StatsValidator(server);
- }
-
- @Before
- public void before() {
- jedis = new Jedis("localhost", server.getPort(), TIMEOUT);
-
- redisStats = server.getServer().getStats();
-
- long preSetupCommandsProcessed = redisStats.getCommandsProcessed();
-
- jedis.set(EXISTING_STRING_KEY, "A_Value");
- jedis.hset(EXISTING_HASH_KEY, "Field1", "Value1");
- jedis.sadd(EXISTING_SET_KEY_1, "m1", "m2", "m3");
- jedis.sadd(EXISTING_SET_KEY_2, "m4", "m5", "m6");
-
- GeodeAwaitility.await().atMost(Duration.ofSeconds(2))
- .untilAsserted(() -> assertThat(redisStats.getCommandsProcessed())
- .isEqualTo(preSetupCommandsProcessed + 4));
-
- preTestKeySpaceHits = redisStats.getKeyspaceHits();
- preTestKeySpaceMisses = redisStats.getKeyspaceMisses();
- preTestConnectionsReceived = redisStats.getTotalConnectionsReceived();
- preTestConnectedClients = redisStats.getConnectedClients();
- }
-
- @After
- public void after() {
- jedis.flushAll();
- jedis.close();
- GeodeAwaitility.await().atMost(Duration.ofSeconds(2))
- .untilAsserted(() -> assertThat(redisStats.getConnectedClients())
- .isEqualTo(0));
- }
-
- // #############Stats Section###################################
-
- @Test
- public void keyspaceHitsStat_shouldIncrement_whenKeyAccessed() {
- jedis.get(EXISTING_STRING_KEY);
-
- statsValidator.validateKeyspaceHits(preTestKeySpaceHits, 1);
- statsValidator.validateKeyspaceMisses(preTestKeySpaceMisses, 0);
- }
-
- @Test
- public void keyspaceHitsStat_shouldNotIncrement_whenNonexistentKeyAccessed() {
- jedis.get("Nonexistent_Key");
-
- statsValidator.validateKeyspaceHits(preTestKeySpaceHits, 0);
- statsValidator.validateKeyspaceMisses(preTestKeySpaceMisses, 1);
- }
-
- @Test
- public void keyspaceStats_setCommand_existingKey() {
- jedis.set(EXISTING_STRING_KEY, "New_Value");
-
- statsValidator.validateKeyspaceHits(preTestKeySpaceHits, 0);
- statsValidator.validateKeyspaceMisses(preTestKeySpaceMisses, 0);
- }
-
- @Test
- public void keyspaceStats_setCommand_nonexistentKey() {
- jedis.set("Another_Key", "Another_Value");
-
- statsValidator.validateKeyspaceHits(preTestKeySpaceHits, 0);
- statsValidator.validateKeyspaceMisses(preTestKeySpaceMisses, 0);
- }
-
- @Test
- public void keyspaceStats_getBitCommand_existingKey() {
- jedis.getbit(EXISTING_STRING_KEY, 0);
-
- statsValidator.validateKeyspaceHits(preTestKeySpaceHits, 1);
- statsValidator.validateKeyspaceMisses(preTestKeySpaceMisses, 0);
- }
-
- @Test
- public void keyspaceStats_getBitCommand_nonexistentKey() {
- jedis.getbit("Nonexistent_Key", 0);
-
- statsValidator.validateKeyspaceHits(preTestKeySpaceHits, 0);
- statsValidator.validateKeyspaceMisses(preTestKeySpaceMisses, 1);
- }
-
- @Test
- public void keyspaceStats_getRangeCommand_existingKey() {
- jedis.getrange(EXISTING_STRING_KEY, 0, 1);
-
- statsValidator.validateKeyspaceHits(preTestKeySpaceHits, 1);
- statsValidator.validateKeyspaceMisses(preTestKeySpaceMisses, 0);
- }
-
- @Test
- public void keyspaceStats_getRangeCommand_nonexistentKey() {
- jedis.getrange("Nonexistent_Key", 0, 1);
-
- statsValidator.validateKeyspaceHits(preTestKeySpaceHits, 0);
- statsValidator.validateKeyspaceMisses(preTestKeySpaceMisses, 1);
- }
-
- @Test
- public void keyspaceStats_getSetCommand_existingKey() {
- jedis.getSet(EXISTING_STRING_KEY, "New_Value");
-
- statsValidator.validateKeyspaceHits(preTestKeySpaceHits, 1);
- statsValidator.validateKeyspaceMisses(preTestKeySpaceMisses, 0);
- }
-
- @Test
- public void keyspaceStats_getSetCommand_nonexistentKey() {
- jedis.getSet("Nonexistent_Key", "FakeValue");
-
- statsValidator.validateKeyspaceHits(preTestKeySpaceHits, 0);
- statsValidator.validateKeyspaceMisses(preTestKeySpaceMisses, 1);
- }
-
- @Test
- public void keyspaceStats_strlenCommand_existingKey() {
- jedis.strlen(EXISTING_STRING_KEY);
-
- statsValidator.validateKeyspaceHits(preTestKeySpaceHits, 1);
- statsValidator.validateKeyspaceMisses(preTestKeySpaceMisses, 0);
- }
-
- @Test
- public void keyspaceStats_strlenCommand_nonexistentKey() {
- jedis.strlen(NONEXISTENT_KEY);
-
- statsValidator.validateKeyspaceHits(preTestKeySpaceHits, 0);
- statsValidator.validateKeyspaceMisses(preTestKeySpaceMisses, 1);
- }
-
- @Test
- public void keyspaceStats_mgetCommand() {
- jedis.mget(EXISTING_STRING_KEY, "Nonexistent_Key");
-
- statsValidator.validateKeyspaceHits(preTestKeySpaceHits, 1);
- statsValidator.validateKeyspaceMisses(preTestKeySpaceMisses, 1);
- }
-
- @Test
- public void keyspaceStats_bitopCommand_existingKey() {
- jedis.bitop(BitOP.AND, EXISTING_STRING_KEY, EXISTING_STRING_KEY, "Nonexistent_Key");
-
- statsValidator.validateKeyspaceHits(preTestKeySpaceHits, 1);
- statsValidator.validateKeyspaceMisses(preTestKeySpaceMisses, 1);
- }
-
- @Test
- public void keyspaceStats_bitopCommand_newKey() {
- jedis.bitop(BitOP.AND, "destination-key", EXISTING_STRING_KEY, "Nonexistent_Key");
-
- statsValidator.validateKeyspaceHits(preTestKeySpaceHits, 1);
- statsValidator.validateKeyspaceMisses(preTestKeySpaceMisses, 1);
- }
-
- @Test
- public void keyspaceStats_bitcountCommand_existingKey() {
- jedis.bitcount(EXISTING_STRING_KEY);
-
- statsValidator.validateKeyspaceHits(preTestKeySpaceHits, 1);
- statsValidator.validateKeyspaceMisses(preTestKeySpaceMisses, 0);
- }
-
- @Test
- public void keyspaceStats_bitcountCommand_nonexistentKey() {
- jedis.bitcount("Nonexistent_Key");
-
- statsValidator.validateKeyspaceHits(preTestKeySpaceHits, 0);
- statsValidator.validateKeyspaceMisses(preTestKeySpaceMisses, 1);
- }
-
- @Test
- public void keyspaceStats_bitposCommand_existingKey() {
- jedis.bitpos(EXISTING_STRING_KEY, true);
-
- statsValidator.validateKeyspaceHits(preTestKeySpaceHits, 1);
- statsValidator.validateKeyspaceMisses(preTestKeySpaceMisses, 0);
- }
-
- @Test
- public void keyspaceStats_bitposCommand_nonexistentKey() {
- jedis.bitpos("Nonexistent_Key", true);
-
- statsValidator.validateKeyspaceHits(preTestKeySpaceHits, 0);
- statsValidator.validateKeyspaceMisses(preTestKeySpaceMisses, 1);
- }
-
- @Test
- public void keyspaceStats_hgetCommand_existingKey() {
- jedis.hget(EXISTING_HASH_KEY, "Field1");
-
- statsValidator.validateKeyspaceHits(preTestKeySpaceHits, 1);
- statsValidator.validateKeyspaceMisses(preTestKeySpaceMisses, 0);
- }
-
- @Test
- public void keyspaceStats_hgetCommand_nonexistentKey() {
- jedis.hget("Nonexistent_Hash", "Field1");
-
- statsValidator.validateKeyspaceHits(preTestKeySpaceHits, 0);
- statsValidator.validateKeyspaceMisses(preTestKeySpaceMisses, 1);
- }
-
- @Test
- public void keyspaceStats_smembersCommand_existingKey() {
- jedis.smembers(EXISTING_SET_KEY_1);
-
- statsValidator.validateKeyspaceHits(preTestKeySpaceHits, 1);
- statsValidator.validateKeyspaceMisses(preTestKeySpaceMisses, 0);
- }
-
- @Test
- public void keyspaceStats_smembersCommand_nonexistentKey() {
- jedis.smembers("Nonexistent_Set");
-
- statsValidator.validateKeyspaceHits(preTestKeySpaceHits, 0);
- statsValidator.validateKeyspaceMisses(preTestKeySpaceMisses, 1);
- }
-
- @Test
- public void keyspaceStats_sunionstoreCommand_existingKey() {
- jedis.sunionstore(
- EXISTING_SET_KEY_1,
- EXISTING_SET_KEY_1,
- EXISTING_SET_KEY_2,
- "Nonexistent_Set");
-
- statsValidator.validateKeyspaceHits(preTestKeySpaceHits, 0);
- statsValidator.validateKeyspaceMisses(preTestKeySpaceMisses, 0);
- }
-
- @Test
- public void keyspaceStats_sunionstoreCommand_newKey() {
- jedis.sunionstore(
- "New_Set",
- EXISTING_SET_KEY_1,
- EXISTING_SET_KEY_2,
- "Nonexistent_Set");
-
- statsValidator.validateKeyspaceHits(preTestKeySpaceHits, 0);
- statsValidator.validateKeyspaceMisses(preTestKeySpaceMisses, 0);
- }
-
- @Test
- public void keyspaceStats_sdiffstoreCommand_newKey() {
- jedis.sdiffstore(
- "New_Set",
- EXISTING_SET_KEY_1,
- EXISTING_SET_KEY_2,
- "Nonexistent_Set");
-
- statsValidator.validateKeyspaceHits(preTestKeySpaceHits, 0);
- statsValidator.validateKeyspaceMisses(preTestKeySpaceMisses, 0);
- }
-
- @Test
- public void keyspaceStats_sinterstoreCommand_newKey() {
- jedis.sinterstore(
- "New_Set",
- EXISTING_SET_KEY_1,
- EXISTING_SET_KEY_2,
- "Nonexistent_Set");
-
- statsValidator.validateKeyspaceHits(preTestKeySpaceHits, 0);
- statsValidator.validateKeyspaceMisses(preTestKeySpaceMisses, 0);
- }
-
- @Test
- public void keyspaceStats_ExistsCommand_existingKey() {
- jedis.exists(EXISTING_STRING_KEY);
-
- statsValidator.validateKeyspaceHits(preTestKeySpaceHits, 1);
- statsValidator.validateKeyspaceMisses(preTestKeySpaceMisses, 0);
- }
-
- @Test
- public void keyspaceStats_ExistsCommand_nonexistentKey() {
- jedis.exists(NONEXISTENT_KEY);
-
- statsValidator.validateKeyspaceHits(preTestKeySpaceHits, 0);
- statsValidator.validateKeyspaceMisses(preTestKeySpaceMisses, 1);
- }
-
- @Test
- public void keyspaceStats_TypeCommand_existingKey() {
- jedis.type(EXISTING_STRING_KEY);
-
- statsValidator.validateKeyspaceHits(preTestKeySpaceHits, 1);
- statsValidator.validateKeyspaceMisses(preTestKeySpaceMisses, 0);
- }
-
- @Test
- public void keyspaceStats_TypeCommand_nonexistentKey() {
- jedis.type(NONEXISTENT_KEY);
-
- statsValidator.validateKeyspaceHits(preTestKeySpaceHits, 0);
- statsValidator.validateKeyspaceMisses(preTestKeySpaceMisses, 1);
- }
-
- @Test
- public void keyspaceStats_PTTL_TTLCommand_existingKey() {
- jedis.ttl(EXISTING_STRING_KEY);
-
- statsValidator.validateKeyspaceHits(preTestKeySpaceHits, 1);
- statsValidator.validateKeyspaceMisses(preTestKeySpaceMisses, 0);
- }
-
- @Test
- public void keyspaceStats_PTTL_TTL_Command_nonexistentKey() {
- jedis.ttl(NONEXISTENT_KEY);
-
- statsValidator.validateKeyspaceHits(preTestKeySpaceHits, 0);
- statsValidator.validateKeyspaceMisses(preTestKeySpaceMisses, 1);
- }
-
- @Test
- public void commandsProcessed_shouldIncrement_givenSuccessfulCommand() {
- long initialCommandsProcessed = redisStats.getCommandsProcessed();
- jedis.ttl("key");
-
- statsValidator.validateCommandsProcessed(initialCommandsProcessed, 1);
- }
-
- @Test
- public void opsPerformedOverLastSecond_ShouldUpdate_givenOperationsOccurring() {
-
- int NUMBER_SECONDS_TO_RUN = 3;
- AtomicInteger numberOfCommandsExecuted = new AtomicInteger();
- AtomicDouble actual_commandsProcessed = new AtomicDouble();
- GeodeAwaitility
- .await()
- .during(Duration.ofSeconds(NUMBER_SECONDS_TO_RUN))
- .until(() -> {
- jedis.set("key", "value");
- numberOfCommandsExecuted.getAndIncrement();
- actual_commandsProcessed.set(redisStats.getOpsPerformedOverLastSecond());
- return true;
- });
-
- long expected =
- (numberOfCommandsExecuted.get() / NUMBER_SECONDS_TO_RUN);
-
- assertThat(actual_commandsProcessed.get())
- .isCloseTo(expected, Offset.offset(
- getTenPercentOf(actual_commandsProcessed.get())));
-
- // if time passes w/o operations
- GeodeAwaitility
- .await()
- .during(NUMBER_SECONDS_TO_RUN, TimeUnit.SECONDS)
- .until(() -> true);
-
- assertThat(redisStats.getOpsPerformedOverLastSecond())
- .isEqualTo(0);
- }
-
- @Test
- public void networkBytesRead_shouldIncrementBySizeOfCommandSent() {
- long initialNetworkBytesRead = redisStats.getTotalNetworkBytesRead();
- String respCommandString = "*3\r\n$3\r\nset\r\n$3\r\nkey\r\n$5\r\nvalue\r\n";
-
- jedis.set("key", "value");
-
- statsValidator.validateNetworkBytesRead(initialNetworkBytesRead, respCommandString.length());
- }
-
- @Test
- public void networkKiloBytesReadOverLastSecond_shouldReturnCorrectData() {
-
- double REASONABLE_SOUNDING_OFFSET = .8;
- int NUMBER_SECONDS_TO_RUN = 2;
- String RESP_COMMAND_STRING = "*3\r\n$3\r\nset\r\n$3\r\nkey\r\n$5\r\nvalue\r\n";
- int BYTES_SENT_PER_COMMAND = RESP_COMMAND_STRING.length();
- AtomicInteger totalBytesSent = new AtomicInteger();
- AtomicReference<Double> actual_kbs = new AtomicReference<>((double) 0);
-
- GeodeAwaitility
- .await()
- .during(Duration.ofSeconds(NUMBER_SECONDS_TO_RUN))
- .until(() -> {
- jedis.set("key", "value");
- totalBytesSent.addAndGet(BYTES_SENT_PER_COMMAND);
- actual_kbs.set(redisStats.getNetworkKiloBytesReadOverLastSecond());
- return true;
- });
-
- double expectedBytesReceived = totalBytesSent.get() / NUMBER_SECONDS_TO_RUN;
- double expected_kbs = expectedBytesReceived / 1000;
-
- assertThat(actual_kbs.get()).isCloseTo(expected_kbs,
- Offset.offset(REASONABLE_SOUNDING_OFFSET));
-
- // if time passes w/o operations
- GeodeAwaitility
- .await()
- .during(NUMBER_SECONDS_TO_RUN, TimeUnit.SECONDS)
- .until(() -> true);
-
- assertThat(redisStats.getNetworkKiloBytesReadOverLastSecond())
- .isEqualTo(0);
-
- }
-
- // ######################### Clients Section #################################
-
- @Test
- public void clientsStat_withConnectAndClose_isCorrect() {
- Jedis jedis2 = new Jedis("localhost", server.getPort(), TIMEOUT);
- jedis2.ping();
-
- statsValidator.validateConnectedClients(preTestConnectedClients, 1);
-
- jedis2.close();
-
- statsValidator.validateConnectedClients(preTestConnectedClients, 0);
- }
-
- @Test
- public void totalConnectionsReceivedStat_shouldIncrement_whenNewConnectionOccurs() {
- Jedis jedis2 = new Jedis("localhost", server.getPort(), TIMEOUT);
- jedis2.ping();
-
- statsValidator.validateConnectedClients(preTestConnectedClients, 1);
-
- jedis2.close();
-
- statsValidator.validateConnectionsReceived(preTestConnectionsReceived, 1);
- }
-
- // ######################## Server Section ################
-
- @Test
- public void uptimeInSeconds_shouldReturnCorrectValue() {
- long serverUptimeAtStartOfTestInNanos = getCurrentTime();
- long statsUpTimeAtStartOfTest = redisStats.getUptimeInSeconds();
-
- GeodeAwaitility.await().during(Duration.ofSeconds(3)).until(() -> true);
-
- long expectedNanos = getCurrentTime() - serverUptimeAtStartOfTestInNanos;
- long expectedSeconds = TimeUnit.NANOSECONDS.toSeconds(expectedNanos);
-
- assertThat(redisStats.getUptimeInSeconds() - statsUpTimeAtStartOfTest)
- .isCloseTo(expectedSeconds, Offset.offset(1l));
- }
-
- @Test
- public void upTimeInDays_shouldReturnCorrectValue() {
- long startTimeInNanos = getStartTime();
- long currentTimeInNanos = getCurrentTime();
-
- long expectedNanos = currentTimeInNanos - startTimeInNanos;
- long expectedDays = TimeUnit.NANOSECONDS.toDays(expectedNanos);
-
- assertThat(redisStats.getUptimeInDays())
- .isEqualTo(expectedDays);
- }
-
- public long getStartTime() {
- return START_TIME;
- }
-
- public long getCurrentTime() {
- return this.statisticsClock.getTime();
- }
-
- private double getTenPercentOf(Double value) {
- return Math.ceil(value * .1);
- }
-}
diff --git a/geode-redis/src/integrationTest/java/org/apache/geode/redis/internal/executor/server/AbstractHitsMissesIntegrationTest.java b/geode-redis/src/integrationTest/java/org/apache/geode/redis/internal/executor/server/AbstractHitsMissesIntegrationTest.java
index ae7d04d..3bc2ac0a 100644
--- a/geode-redis/src/integrationTest/java/org/apache/geode/redis/internal/executor/server/AbstractHitsMissesIntegrationTest.java
+++ b/geode-redis/src/integrationTest/java/org/apache/geode/redis/internal/executor/server/AbstractHitsMissesIntegrationTest.java
@@ -26,6 +26,7 @@
import org.apache.logging.log4j.util.TriConsumer;
import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import redis.clients.jedis.BitOP;
import redis.clients.jedis.Jedis;
@@ -47,8 +48,10 @@
jedis = new Jedis("localhost", getPort(), REDIS_CLIENT_TIMEOUT);
jedis.set("string", "yarn");
+ jedis.set("int", "5");
jedis.sadd("set", "cotton");
jedis.hset("hash", "green", "eggs");
+ jedis.mset("mapKey1", "fox", "mapKey2", "box");
}
@After
@@ -57,6 +60,9 @@
jedis.close();
}
+ /***********************************************
+ ************* Supported Commands **************
+ **********************************************/
// ------------ Key related commands -----------
@Test
@@ -89,6 +95,11 @@
runCommandAndAssertNoStatUpdates("string", (k, v) -> jedis.rename(k, v));
}
+ @Test
+ public void testDel() {
+ runCommandAndAssertNoStatUpdates("string", k -> jedis.del(k));
+ }
+
// ------------ String related commands -----------
@Test
@@ -97,6 +108,107 @@
}
@Test
+ public void testAppend() {
+ runCommandAndAssertNoStatUpdates("string", (k, v) -> jedis.append(k, v));
+ }
+
+ @Test
+ public void testSet() {
+ runCommandAndAssertNoStatUpdates("string", (k, v) -> jedis.set(k, v));
+ }
+
+ @Test
+ public void testSet_wrongType() {
+ runCommandAndAssertNoStatUpdates("set", (k, v) -> jedis.set(k, v));
+ }
+
+ // ------------ Set related commands -----------
+ @Test
+ public void testSadd() {
+ runCommandAndAssertNoStatUpdates("set", (k, v) -> jedis.sadd(k, v));
+ }
+
+ @Test
+ public void testSrem() {
+ runCommandAndAssertNoStatUpdates("set", (k, v) -> jedis.srem(k, v));
+ }
+
+ @Test
+ public void testSmembers() {
+ runCommandAndAssertHitsAndMisses("set", k -> jedis.smembers(k));
+ }
+
+ // ------------ Hash related commands -----------
+ @Test
+ public void testHset() {
+ runCommandAndAssertNoStatUpdates("hash", (k, v, s) -> jedis.hset(k, v, s));
+ }
+
+ @Test
+ public void testHgetall() {
+ runCommandAndAssertHitsAndMisses("hash", k -> jedis.hgetAll(k));
+ }
+
+ @Test
+ public void testHMSet() {
+ Map<String, String> map = new HashMap<>();
+ map.put("key1", "value1");
+ map.put("key2", "value2");
+
+ runCommandAndAssertNoStatUpdates("key", (k) -> jedis.hmset(k, map));
+ }
+
+ // ------------ Key related commands -----------
+
+ @Test
+ public void testExpire() {
+ runCommandAndAssertNoStatUpdates("hash", (k) -> jedis.expire(k, 5));
+ }
+
+ @Test
+ public void testPassiveExpiration() {
+ runCommandAndAssertNoStatUpdates("hash", (k) -> {
+ jedis.expire(k, 1);
+ GeodeAwaitility.await().during(Duration.ofSeconds(3)).until(() -> true);
+ });
+ }
+
+ @Test
+ public void testExpireAt() {
+ runCommandAndAssertNoStatUpdates("hash", (k) -> jedis.expireAt(k, 2145916800));
+ }
+
+ @Test
+ public void testPExpire() {
+ runCommandAndAssertNoStatUpdates("hash", (k) -> jedis.pexpire(k, 1024));
+ }
+
+ @Test
+ public void testPExpireAt() {
+ runCommandAndAssertNoStatUpdates("hash", (k) -> jedis.pexpireAt(k, 1608247597));
+ }
+
+ @Test
+ public void testPersist() {
+ runCommandAndAssertNoStatUpdates("hash", (k) -> jedis.persist(k));
+ }
+
+ /**********************************************
+ ********** Unsupported Commands **************
+ *********************************************/
+ // ---------- Key related commands -----------
+ @Test
+ public void testScan() {
+ runCommandAndAssertNoStatUpdates("0", k -> jedis.scan(k));
+ }
+
+ @Test
+ public void testUnlink() {
+ runCommandAndAssertNoStatUpdates("string", k -> jedis.unlink(k));
+ }
+
+ // ------------ String related commands -----------
+ @Test
public void testGetset() {
runCommandAndAssertHitsAndMisses("string", (k, v) -> jedis.getSet(k, v));
}
@@ -107,27 +219,68 @@
}
@Test
- public void testDel() {
- runCommandAndAssertNoStatUpdates("string", k -> jedis.del(k));
+ public void testDecr() {
+ runCommandAndAssertNoStatUpdates("int", k -> jedis.decr(k));
}
@Test
- public void testSet() {
- runCommandAndAssertNoStatUpdates("string", (k, v) -> jedis.set(k, v));
+ public void testDecrby() {
+ runCommandAndAssertNoStatUpdates("int", k -> jedis.decrBy(k, 1));
}
@Test
- public void testAppend() {
- runCommandAndAssertNoStatUpdates("string", (k, v) -> jedis.append(k, v));
+ public void testGetrange() {
+ runCommandAndAssertHitsAndMisses("string", k -> jedis.getrange(k, 1l, 2l));
}
@Test
- public void testSetWrongType() {
- runCommandAndAssertNoStatUpdates("set", (k, v) -> jedis.set(k, v));
+ public void testIncr() {
+ runCommandAndAssertNoStatUpdates("int", k -> jedis.incr(k));
+ }
+
+ @Test
+ public void testIncrby() {
+ runCommandAndAssertNoStatUpdates("int", k -> jedis.incrBy(k, 1l));
+ }
+
+ @Test
+ public void testIncrbyfloat() {
+ runCommandAndAssertNoStatUpdates("int", k -> jedis.incrByFloat(k, 1.0));
+ }
+
+ @Test
+ public void testMget() {
+ runCommandAndAssertHitsAndMisses("mapKey1", "mapKey2", (k1, k2) -> jedis.mget(k1, k2));
+ }
+
+ @Test
+ public void testMset() {
+ runCommandAndAssertNoStatUpdates("mapKey1", (k, v) -> jedis.mset(k, v));
+ }
+
+ // todo updates stats when it shouldn't. not implemented in the function executor
+ @Ignore
+ @Test
+ public void testMsetnx() {
+ runCommandAndAssertNoStatUpdates("mapKey1", (k, v) -> jedis.msetnx(k, v));
+ }
+
+ @Test
+ public void testSetex() {
+ runCommandAndAssertNoStatUpdates("string", (k, v) -> jedis.setex(k, 200, v));
+ }
+
+ @Test
+ public void testSetnx() {
+ runCommandAndAssertNoStatUpdates("string", (k, v) -> jedis.setnx(k, v));
+ }
+
+ @Test
+ public void testSetrange() {
+ runCommandAndAssertNoStatUpdates("string", (k, v) -> jedis.setrange(k, 1l, v));
}
// ------------ Bit related commands -----------
-
@Test
public void testBitcount() {
runCommandAndAssertHitsAndMisses("string", k -> jedis.bitcount(k));
@@ -171,6 +324,16 @@
assertThat(info.get(MISSES)).isEqualTo(String.valueOf(currentMisses + 1 + 1));
}
+ @Test
+ public void testGetbit() {
+ runCommandAndAssertHitsAndMisses("string", k -> jedis.getbit(k, 1));
+ }
+
+ @Test
+ public void testSetbit() {
+ runCommandAndAssertNoStatUpdates("int", (k, v) -> jedis.setbit(k, 0l, "1"));
+ }
+
// ------------ Set related commands -----------
// FYI - In Redis 5.x SPOP produces inconsistent results depending on whether a count was given
// or not. In Redis 6.x SPOP does not update any stats.
@@ -180,21 +343,6 @@
}
@Test
- public void testSadd() {
- runCommandAndAssertNoStatUpdates("set", (k, v) -> jedis.sadd(k, v));
- }
-
- @Test
- public void testSrem() {
- runCommandAndAssertNoStatUpdates("set", (k, v) -> jedis.srem(k, v));
- }
-
- @Test
- public void testSmembers() {
- runCommandAndAssertHitsAndMisses("set", k -> jedis.smembers(k));
- }
-
- @Test
public void testSismember() {
runCommandAndAssertHitsAndMisses("set", (k, v) -> jedis.sismember(k, v));
}
@@ -244,29 +392,25 @@
runDiffStoreCommandAndAssertNoStatUpdates("set", (k, v, s) -> jedis.sunionstore(k, v, s));
}
- // ------------ Hash related commands -----------
+ // TODO GEODE-8857: our implementation updates the stats when it shouldn't
+ @Ignore
+ @Test
+ public void testSmove() {
+ runCommandAndAssertNoStatUpdates("set", (k, d, m) -> jedis.smove(k, d, m));
+ }
+ // ------------ Hash related commands -----------
@Test
public void testHdel() {
runCommandAndAssertNoStatUpdates("hash", (k, v) -> jedis.hdel(k, v));
}
@Test
- public void testHset() {
- runCommandAndAssertNoStatUpdates("hash", (k, v, s) -> jedis.hset(k, v, s));
- }
-
- @Test
public void testHget() {
runCommandAndAssertHitsAndMisses("hash", (k, v) -> jedis.hget(k, v));
}
@Test
- public void testHgetall() {
- runCommandAndAssertHitsAndMisses("hash", k -> jedis.hgetAll(k));
- }
-
- @Test
public void testHkeys() {
runCommandAndAssertHitsAndMisses("hash", k -> jedis.hkeys(k));
}
@@ -302,47 +446,18 @@
}
@Test
- public void testHMSet() {
- Map<String, String> map = new HashMap<>();
- map.put("key1", "value1");
- map.put("key2", "value2");
-
- runCommandAndAssertNoStatUpdates("key", (k) -> jedis.hmset(k, map));
- }
-
- // ------------ Key related commands -----------
-
- @Test
- public void testExpire() {
- runCommandAndAssertNoStatUpdates("hash", (k) -> jedis.expire(k, 5));
+ public void testHincrby() {
+ runCommandAndAssertNoStatUpdates("hash", (k, f) -> jedis.hincrBy(k, f, 1l));
}
@Test
- public void testPassiveExpiration() {
- runCommandAndAssertNoStatUpdates("hash", (k) -> {
- jedis.expire(k, 1);
- GeodeAwaitility.await().during(Duration.ofSeconds(3)).until(() -> true);
- });
+ public void testHincrbyfloat() {
+ runCommandAndAssertNoStatUpdates("hash", (k, f) -> jedis.hincrByFloat(k, f, 1.0));
}
@Test
- public void testExpireAt() {
- runCommandAndAssertNoStatUpdates("hash", (k) -> jedis.expireAt(k, 2145916800));
- }
-
- @Test
- public void testPExpire() {
- runCommandAndAssertNoStatUpdates("hash", (k) -> jedis.pexpire(k, 1024));
- }
-
- @Test
- public void testPExpireAt() {
- runCommandAndAssertNoStatUpdates("hash", (k) -> jedis.pexpireAt(k, 1608247597));
- }
-
- @Test
- public void testPersist() {
- runCommandAndAssertNoStatUpdates("hash", (k) -> jedis.persist(k));
+ public void testHsetnx() {
+ runCommandAndAssertNoStatUpdates("hash", (k, f, v) -> jedis.hsetnx(k, f, v));
}
// ------------ Helper Methods -----------
@@ -383,6 +498,19 @@
assertThat(info.get(MISSES)).isEqualTo(String.valueOf(currentMisses + 1));
}
+ private void runCommandAndAssertHitsAndMisses(String key1, String key2,
+ BiConsumer<String, String> command) {
+ Map<String, String> info = getInfo(jedis);
+ Long currentHits = Long.parseLong(info.get(HITS));
+ Long currentMisses = Long.parseLong(info.get(MISSES));
+
+ command.accept(key1, key2);
+ info = getInfo(jedis);
+
+ assertThat(info.get(HITS)).isEqualTo(String.valueOf(currentHits + 2));
+ assertThat(info.get(MISSES)).isEqualTo(String.valueOf(currentMisses));
+ }
+
private void runDiffCommandAndAssertHitsAndMisses(String key,
BiConsumer<String, String> command) {
Map<String, String> info = getInfo(jedis);
diff --git a/geode-redis/src/integrationTest/java/org/apache/geode/redis/internal/executor/server/AbstractRedisInfoStatsIntegrationTest.java b/geode-redis/src/integrationTest/java/org/apache/geode/redis/internal/executor/server/AbstractRedisInfoStatsIntegrationTest.java
new file mode 100644
index 0000000..4e72595
--- /dev/null
+++ b/geode-redis/src/integrationTest/java/org/apache/geode/redis/internal/executor/server/AbstractRedisInfoStatsIntegrationTest.java
@@ -0,0 +1,318 @@
+/*
+ * 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.server;
+
+import static org.apache.geode.test.awaitility.GeodeAwaitility.await;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.time.Duration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+
+import com.google.common.util.concurrent.AtomicDouble;
+import org.assertj.core.data.Offset;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import redis.clients.jedis.Jedis;
+
+import org.apache.geode.internal.statistics.EnabledStatisticsClock;
+import org.apache.geode.internal.statistics.StatisticsClock;
+import org.apache.geode.test.awaitility.GeodeAwaitility;
+import org.apache.geode.test.dunit.rules.RedisPortSupplier;
+
+public abstract class AbstractRedisInfoStatsIntegrationTest implements RedisPortSupplier {
+
+ private static final int TIMEOUT = (int) GeodeAwaitility.getTimeout().toMillis();
+ private static final String EXISTING_HASH_KEY = "Existing_Hash";
+ private static final String EXISTING_STRING_KEY = "Existing_String";
+ private static final String EXISTING_SET_KEY_1 = "Existing_Set_1";
+ private static final String EXISTING_SET_KEY_2 = "Existing_Set_2";
+
+ private Jedis jedis;
+ private static long START_TIME;
+ private static StatisticsClock statisticsClock;
+
+ private long preTestConnectionsReceived = 0;
+ private long preTestConnectedClients = 0;
+
+ private static final String COMMANDS_PROCESSED = "total_commands_processed";
+ private static final String TOTAL_CONNECTIONS_RECEIVED = "total_connections_received";
+ private static final String CONNECTED_CLIENTS = "connected_clients";
+ private static final String OPS_PERFORMED_OVER_LAST_SECOND = "instantaneous_ops_per_sec";
+ private static final String TOTAL_NETWORK_BYTES_READ = "total_net_input_bytes";
+ private static final String NETWORK_KB_READ_OVER_LAST_SECOND = "instantaneous_input_kbps";
+ private static final String UPTIME_IN_DAYS = "uptime_in_days";
+ private static final String UPTIME_IN_SECONDS = "uptime_in_seconds";
+
+ private static final AtomicInteger numInfoCalled = new AtomicInteger(0);
+
+
+ // ------------------- Setup -------------------------- //
+ @BeforeClass
+ public static void beforeClass() {
+ statisticsClock = new EnabledStatisticsClock();
+ START_TIME = statisticsClock.getTime();
+ }
+
+ @Before
+ public void before() {
+ jedis = new Jedis("localhost", getPort(), TIMEOUT);
+ numInfoCalled.set(0);
+
+ long preSetupCommandsProcessed = Long.valueOf(getInfo(jedis).get(COMMANDS_PROCESSED));
+
+ jedis.set(EXISTING_STRING_KEY, "A_Value");
+ jedis.hset(EXISTING_HASH_KEY, "Field1", "Value1");
+ jedis.sadd(EXISTING_SET_KEY_1, "m1", "m2", "m3");
+ jedis.sadd(EXISTING_SET_KEY_2, "m4", "m5", "m6");
+
+ // the info command increments command processed so we need to account for that.
+ // the +1 is needed because info returns the number of commands processed before that call to
+ // info
+ await().atMost(Duration.ofSeconds(2))
+ .untilAsserted(() -> assertThat(
+ Long.valueOf(getInfo(jedis).get(COMMANDS_PROCESSED)) - numInfoCalled.get() + 1)
+ .isEqualTo(preSetupCommandsProcessed + 4));
+
+ preTestConnectionsReceived = Long.valueOf(getInfo(jedis).get(TOTAL_CONNECTIONS_RECEIVED));
+ preTestConnectedClients = Long.valueOf(getInfo(jedis).get(CONNECTED_CLIENTS));
+ numInfoCalled.set(0);
+ }
+
+ @After
+ public void after() {
+ jedis.flushAll();
+ await().atMost(Duration.ofSeconds(5))
+ .untilAsserted(
+ () -> assertThat(Long.valueOf(getInfo(jedis).get(CONNECTED_CLIENTS))).isEqualTo(1));
+ jedis.close();
+ }
+
+ // ------------------- Stats Section -------------------------- //
+
+ // note: see AbstractHitsMissesIntegrationTest for testing of hits/misses
+
+ @Test
+ public void commandsProcessed_shouldIncrement_givenSuccessfulCommand() {
+ long initialCommandsProcessed = Long.valueOf(getInfo(jedis).get(COMMANDS_PROCESSED));
+ jedis.ttl("key");
+
+ validateCommandsProcessed(jedis, initialCommandsProcessed, 1);
+ }
+
+ @Test
+ public void opsPerformedOverLastSecond_ShouldUpdate_givenOperationsOccurring() {
+ int NUMBER_SECONDS_TO_RUN = 3;
+
+ AtomicInteger numberOfCommandsExecuted = new AtomicInteger();
+ AtomicDouble actualCommandsProcessedOverLastSecond = new AtomicDouble();
+
+ await().during(Duration.ofSeconds(NUMBER_SECONDS_TO_RUN)).until(() -> {
+ jedis.set("key", "value");
+ numberOfCommandsExecuted.getAndIncrement();
+ actualCommandsProcessedOverLastSecond.set(
+ Double.valueOf(getInfo(jedis).get(OPS_PERFORMED_OVER_LAST_SECOND)));
+
+ return true;
+ });
+
+ long expected = (numberOfCommandsExecuted.get() + numInfoCalled.get()) / NUMBER_SECONDS_TO_RUN;
+
+ assertThat(actualCommandsProcessedOverLastSecond.get())
+ .isCloseTo(expected,
+ Offset.offset(getTenPercentOf(actualCommandsProcessedOverLastSecond.get())));
+
+ // if time passes w/o operations
+ await().during(NUMBER_SECONDS_TO_RUN, TimeUnit.SECONDS).until(() -> true);
+
+ assertThat(Double.valueOf(getInfo(jedis).get(OPS_PERFORMED_OVER_LAST_SECOND))).isEqualTo(0D);
+ }
+
+ @Test
+ public void networkBytesRead_shouldIncrementBySizeOfCommandSent() {
+ long initialNetworkBytesRead = Long.valueOf(getInfo(jedis).get(TOTAL_NETWORK_BYTES_READ));
+ String infoCommandString = "*3\r\n$3\r\ninfo\r\n";
+ String respCommandString = "*3\r\n$3\r\nset\r\n$3\r\nkey\r\n$5\r\nvalue\r\n";
+
+ jedis.set("key", "value");
+
+ validateNetworkBytesRead(jedis, initialNetworkBytesRead,
+ respCommandString.length() + infoCommandString.length());
+ }
+
+ @Test
+ public void networkKiloBytesReadOverLastSecond_shouldBeCloseToBytesReadOverLastSecond() {
+
+ double REASONABLE_SOUNDING_OFFSET = .8;
+ int NUMBER_SECONDS_TO_RUN = 2;
+ String RESP_COMMAND_STRING = "*3\r\n$3\r\nset\r\n$3\r\nkey\r\n$5\r\nvalue\r\n";
+ int BYTES_SENT_PER_COMMAND = RESP_COMMAND_STRING.length();
+ AtomicInteger totalBytesSent = new AtomicInteger();
+ AtomicReference<Double> actual_kbs = new AtomicReference<>((double) 0);
+
+ await().during(Duration.ofSeconds(NUMBER_SECONDS_TO_RUN)).until(() -> {
+ jedis.set("key", "value");
+ totalBytesSent.addAndGet(BYTES_SENT_PER_COMMAND);
+ actual_kbs.set(Double.valueOf(getInfo(jedis).get(NETWORK_KB_READ_OVER_LAST_SECOND)));
+ return true;
+ });
+
+ double expectedBytesReceived = totalBytesSent.get() / NUMBER_SECONDS_TO_RUN;
+ double expected_kbs = expectedBytesReceived / 1000;
+
+ assertThat(actual_kbs.get()).isCloseTo(expected_kbs, Offset.offset(REASONABLE_SOUNDING_OFFSET));
+
+ // if time passes w/o operations
+ await()
+ .during(NUMBER_SECONDS_TO_RUN, TimeUnit.SECONDS)
+ .until(() -> true);
+
+ assertThat(Double.valueOf(getInfo(jedis).get(NETWORK_KB_READ_OVER_LAST_SECOND))).isEqualTo(0);
+
+ }
+
+ // todo test rejected connections
+ @Test
+ public void should_UpdateRejectedConnections() {
+ Jedis jedis2 = new Jedis("localhost", getPort(), TIMEOUT);
+ Jedis jedis3 = new Jedis("localhost", getPort(), TIMEOUT);
+
+ jedis2.ping();
+ jedis3.ping();
+
+ validateConnectedClients(jedis, preTestConnectedClients, 2);
+
+ jedis2.close();
+ jedis3.close();
+
+ validateConnectedClients(jedis, preTestConnectedClients, 0);
+ }
+
+ // ------------------- Clients Section -------------------------- //
+
+ @Test
+ public void connectedClients_incrAndDecrWhenClientConnectsAndDisconnects() {
+ Jedis jedis2 = new Jedis("localhost", getPort(), TIMEOUT);
+ jedis2.ping();
+
+ validateConnectedClients(jedis, preTestConnectedClients, 1);
+
+ jedis2.close();
+
+ validateConnectedClients(jedis, preTestConnectedClients, 0);
+ }
+
+ @Test
+ public void totalConnectionsReceivedStat_shouldIncrement_whenNewConnectionOccurs() {
+ Jedis jedis2 = new Jedis("localhost", getPort(), TIMEOUT);
+ jedis2.ping();
+
+ validateConnectionsReceived(jedis, preTestConnectionsReceived, 1);
+
+ jedis2.close();
+
+ validateConnectedClients(jedis, preTestConnectedClients, 0);
+ }
+
+ // ------------------- Server Section -------------------------- //
+
+ @Test
+ public void upTimeInDays_shouldBeEqualToTimeSinceStartInDays() {
+ long startTimeInNanos = getStartTime();
+ long currentTimeInNanos = getCurrentTime();
+
+ long expectedNanos = currentTimeInNanos - startTimeInNanos;
+ long expectedDays = TimeUnit.NANOSECONDS.toDays(expectedNanos);
+
+ assertThat(Long.valueOf(getInfo(jedis).get(UPTIME_IN_DAYS))).isEqualTo(expectedDays);
+ }
+
+ @Test
+ public void uptimeInSeconds_shouldReturnTimeSinceStartInSeconds() {
+ long serverUptimeAtStartOfTestInNanos = getCurrentTime();
+ long statsUpTimeAtStartOfTest = Long.valueOf(getInfo(jedis).get(UPTIME_IN_SECONDS));
+
+ await().during(Duration.ofSeconds(3)).until(() -> true);
+
+ long expectedNanos = getCurrentTime() - serverUptimeAtStartOfTestInNanos;
+ long expectedSeconds = TimeUnit.NANOSECONDS.toSeconds(expectedNanos);
+
+ assertThat(Long.valueOf(getInfo(jedis).get(UPTIME_IN_SECONDS)) - statsUpTimeAtStartOfTest)
+ .isCloseTo(expectedSeconds, Offset.offset(1l));
+ }
+
+ // ------------------- Helper Methods ----------------------------- //
+ public long getStartTime() {
+ return START_TIME;
+ }
+
+ public long getCurrentTime() {
+ return this.statisticsClock.getTime();
+ }
+
+ private double getTenPercentOf(Double value) {
+ return Math.ceil(value * .1);
+ }
+
+ /**
+ * Convert the values returned by the INFO command into a basic param:value map.
+ */
+ static synchronized Map<String, String> getInfo(Jedis jedis) {
+ Map<String, String> results = new HashMap<>();
+ String rawInfo = jedis.info();
+ numInfoCalled.incrementAndGet();
+
+ for (String line : rawInfo.split("\r\n")) {
+ int colonIndex = line.indexOf(":");
+ if (colonIndex > 0) {
+ String key = line.substring(0, colonIndex);
+ String value = line.substring(colonIndex + 1);
+ results.put(key, value);
+ }
+ }
+
+ return results;
+ }
+
+ private void validateNetworkBytesRead(Jedis jedis, long initialNetworkBytesRead,
+ int responseLength) {
+ await().atMost(Duration.ofSeconds(2)).untilAsserted(
+ () -> assertThat(Long.valueOf(getInfo(jedis).get(TOTAL_NETWORK_BYTES_READ)))
+ .isEqualTo(initialNetworkBytesRead + responseLength));
+ }
+
+ private void validateCommandsProcessed(Jedis jedis, long initialCommandsProcessed, int diff) {
+ await().atMost(Duration.ofSeconds(2)).untilAsserted(
+ () -> assertThat(
+ Long.valueOf(getInfo(jedis).get(COMMANDS_PROCESSED)) - numInfoCalled.get() + 1)
+ .isEqualTo(initialCommandsProcessed + diff));
+ }
+
+ private void validateConnectedClients(Jedis jedis, long initialConnectedClients, int diff) {
+ await().atMost(Duration.ofSeconds(2)).untilAsserted(
+ () -> assertThat(Long.valueOf(getInfo(jedis).get(CONNECTED_CLIENTS)))
+ .isEqualTo(initialConnectedClients + diff));
+ }
+
+ private void validateConnectionsReceived(Jedis jedis, long initialConnectionsReceived, int diff) {
+ assertThat(Long.valueOf(getInfo(jedis).get(TOTAL_CONNECTIONS_RECEIVED)))
+ .isEqualTo(initialConnectionsReceived + diff);
+ }
+}
diff --git a/geode-redis/src/integrationTest/java/org/apache/geode/redis/internal/executor/server/InfoStatsIntegrationTest.java b/geode-redis/src/integrationTest/java/org/apache/geode/redis/internal/executor/server/InfoStatsIntegrationTest.java
new file mode 100644
index 0000000..979a129
--- /dev/null
+++ b/geode-redis/src/integrationTest/java/org/apache/geode/redis/internal/executor/server/InfoStatsIntegrationTest.java
@@ -0,0 +1,30 @@
+/*
+ * 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.server;
+
+import org.junit.ClassRule;
+
+import org.apache.geode.redis.GeodeRedisServerRule;
+
+public class InfoStatsIntegrationTest extends AbstractRedisInfoStatsIntegrationTest {
+ @ClassRule
+ public static GeodeRedisServerRule server = new GeodeRedisServerRule();
+
+ @Override
+ public int getPort() {
+ return server.getPort();
+ }
+}
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 044a1d1..4efdb0c 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
@@ -176,8 +176,7 @@
UNSUBSCRIBE(new UnsubscribeExecutor(), SUPPORTED, new MinimumParameterRequirements(1)),
/***************************************
- ********** Internal Commands **********
- * /
+ ********* Internal Commands ***********
***************************************/
// do not call these directly, only to be used in other commands
INTERNALPTTL(null, INTERNAL, new ExactParameterRequirements(2)),
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/data/RedisHashCommandsFunctionExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/data/RedisHashCommandsFunctionExecutor.java
index 4fc72c6..c621034 100644
--- a/geode-redis/src/main/java/org/apache/geode/redis/internal/data/RedisHashCommandsFunctionExecutor.java
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/data/RedisHashCommandsFunctionExecutor.java
@@ -102,14 +102,14 @@
@Override
public long hincrby(ByteArrayWrapper key, ByteArrayWrapper field, long increment) {
return stripedExecute(key,
- () -> getRedisHash(key, true)
+ () -> getRedisHash(key, false)
.hincrby(getRegion(), key, field, increment));
}
@Override
public double hincrbyfloat(ByteArrayWrapper key, ByteArrayWrapper field, double increment) {
return stripedExecute(key,
- () -> getRedisHash(key, true)
+ () -> getRedisHash(key, false)
.hincrbyfloat(getRegion(), key, field, increment));
}
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/data/RedisStringCommandsFunctionExecutor.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/data/RedisStringCommandsFunctionExecutor.java
index 38643f0..f162bc0 100644
--- a/geode-redis/src/main/java/org/apache/geode/redis/internal/data/RedisStringCommandsFunctionExecutor.java
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/data/RedisStringCommandsFunctionExecutor.java
@@ -64,12 +64,12 @@
@Override
public long incr(ByteArrayWrapper key) {
- return stripedExecute(key, () -> getRedisString(key, true).incr(getRegion(), key));
+ return stripedExecute(key, () -> getRedisString(key, false).incr(getRegion(), key));
}
@Override
public long decr(ByteArrayWrapper key) {
- return stripedExecute(key, () -> getRedisString(key, true).decr(getRegion(), key));
+ return stripedExecute(key, () -> getRedisString(key, false).decr(getRegion(), key));
}
@Override
@@ -81,13 +81,13 @@
@Override
public long incrby(ByteArrayWrapper key, long increment) {
return stripedExecute(key,
- () -> getRedisString(key, true).incrby(getRegion(), key, increment));
+ () -> getRedisString(key, false).incrby(getRegion(), key, increment));
}
@Override
public double incrbyfloat(ByteArrayWrapper key, double increment) {
return stripedExecute(key,
- () -> getRedisString(key, true)
+ () -> getRedisString(key, false)
.incrbyfloat(getRegion(), key, increment));
}
@@ -100,7 +100,7 @@
@Override
public long decrby(ByteArrayWrapper key, long decrement) {
return stripedExecute(key,
- () -> getRedisString(key, true).decrby(getRegion(), key, decrement));
+ () -> getRedisString(key, false).decrby(getRegion(), key, decrement));
}
@Override
@@ -111,7 +111,7 @@
@Override
public int setrange(ByteArrayWrapper key, int offset, byte[] value) {
return stripedExecute(key,
- () -> getRedisString(key, true)
+ () -> getRedisString(key, false)
.setrange(getRegion(), key, offset, value));
}
@@ -147,7 +147,7 @@
int byteIndex = (int) (offset / 8);
byte bitIndex = (byte) (offset % 8);
return stripedExecute(key,
- () -> getRedisString(key, true)
+ () -> getRedisString(key, false)
.setbit(getRegion(), key, value, byteIndex, bitIndex));
}
diff --git a/geode-redis/src/main/java/org/apache/geode/redis/internal/statistics/RedisStats.java b/geode-redis/src/main/java/org/apache/geode/redis/internal/statistics/RedisStats.java
index fbaa99e..9ec23d5 100644
--- a/geode-redis/src/main/java/org/apache/geode/redis/internal/statistics/RedisStats.java
+++ b/geode-redis/src/main/java/org/apache/geode/redis/internal/statistics/RedisStats.java
@@ -44,6 +44,7 @@
private final GeodeRedisStats geodeRedisStats;
private final long START_TIME_IN_NANOS;
+
public RedisStats(StatisticsClock clock,
GeodeRedisStats geodeRedisStats) {
@@ -53,7 +54,6 @@
START_TIME_IN_NANOS = clock.getTime();
}
-
public void incCommandsProcessed() {
commandsProcessed.incrementAndGet();
geodeRedisStats.incrementCommandsProcessed();
@@ -197,8 +197,7 @@
private void updateOpsPerformedOverLastSecond() {
long totalOpsPerformed = getCommandsProcessed();
- long opsPerformedThisTick = totalOpsPerformed - opsPerformedLastTick;
- opsPerformedOverLastSecond = opsPerformedThisTick;
+ opsPerformedOverLastSecond = totalOpsPerformed - opsPerformedLastTick;
opsPerformedLastTick = getCommandsProcessed();
}
}