imbajin commented on code in PR #2997:
URL: https://github.com/apache/hugegraph/pull/2997#discussion_r3115722488


##########
hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/cassandra/CassandraTest.java:
##########
@@ -192,4 +198,99 @@ public void 
testParseReplicaWithNetworkTopologyStrategyAndDoubleReplica() {
             Whitebox.invokeStatic(CassandraStore.class, "parseReplica", 
config);
         });
     }
+
+    @Test
+    public void testReconnectOptionsHaveSensibleDefaults() {
+        // Runtime-reconnection options must exist with non-zero defaults so
+        // HugeGraph keeps running when Cassandra restarts (issue #2740).
+        Assert.assertEquals(1000L, (long) CassandraOptions
+                .CASSANDRA_RECONNECT_BASE_DELAY.defaultValue());
+        Assert.assertEquals(60_000L, (long) CassandraOptions
+                .CASSANDRA_RECONNECT_MAX_DELAY.defaultValue());
+        Assert.assertEquals(10, (int) CassandraOptions
+                .CASSANDRA_RECONNECT_MAX_RETRIES.defaultValue());
+        Assert.assertEquals(5000L, (long) CassandraOptions
+                .CASSANDRA_RECONNECT_INTERVAL.defaultValue());
+    }
+
+    @Test
+    public void testReconnectOptionsAreOverridable() {
+        String base = CassandraOptions.CASSANDRA_RECONNECT_BASE_DELAY.name();
+        String max = CassandraOptions.CASSANDRA_RECONNECT_MAX_DELAY.name();
+        String retries = CassandraOptions.CASSANDRA_RECONNECT_MAX_RETRIES
+                                         .name();
+        String interval = CassandraOptions.CASSANDRA_RECONNECT_INTERVAL.name();
+
+        Configuration conf = new PropertiesConfiguration();
+        conf.setProperty(base, 500L);
+        conf.setProperty(max, 30_000L);
+        conf.setProperty(retries, 3);
+        conf.setProperty(interval, 1000L);
+        HugeConfig config = new HugeConfig(conf);
+
+        Assert.assertEquals(500L, (long) config.get(
+                CassandraOptions.CASSANDRA_RECONNECT_BASE_DELAY));
+        Assert.assertEquals(30_000L, (long) config.get(
+                CassandraOptions.CASSANDRA_RECONNECT_MAX_DELAY));
+        Assert.assertEquals(3, (int) config.get(
+                CassandraOptions.CASSANDRA_RECONNECT_MAX_RETRIES));
+        Assert.assertEquals(1000L, (long) config.get(
+                CassandraOptions.CASSANDRA_RECONNECT_INTERVAL));
+    }
+
+    @Test
+    public void testReconnectRetriesCanBeDisabled() {
+        String retries = CassandraOptions.CASSANDRA_RECONNECT_MAX_RETRIES
+                                         .name();
+        Configuration conf = new PropertiesConfiguration();
+        conf.setProperty(retries, 0);
+        HugeConfig config = new HugeConfig(conf);
+        Assert.assertEquals(0, (int) config.get(
+                CassandraOptions.CASSANDRA_RECONNECT_MAX_RETRIES));
+    }
+
+    @Test
+    public void testExecuteWithRetrySucceedsAfterTransientFailures() {
+        Configuration conf = new PropertiesConfiguration();
+        HugeConfig config = new HugeConfig(conf);
+        CassandraSessionPool pool = new CassandraSessionPool(config,

Review Comment:
   โš ๏ธ **Test constructs `CassandraSessionPool` with a blank config โ€” fragile 
setup**
   
   `new HugeConfig(new PropertiesConfiguration())` produces an empty config. 
The constructor calls `config.get(CASSANDRA_RECONNECT_BASE_DELAY)` etc., which 
falls back to option defaults only if `HugeConfig` performs that fallback 
correctly. If any option's `rangeInt` validator is applied to the absent value 
rather than the default, this test will fail with a confusing config error 
instead of a clear assertion.
   
   The fields set via `Whitebox.setInternalState` immediately after 
construction throw away the constructed values anyway, so the constructor call 
is only there to get a valid object โ€” but it's a fragile path.
   
   Suggested fix: explicitly set the required config values so the test is 
self-describing and not dependent on default-fallback behaviour:
   
   ```java
   Configuration conf = new PropertiesConfiguration();
   conf.setProperty(CassandraOptions.CASSANDRA_RECONNECT_BASE_DELAY.name(), 
100L);
   conf.setProperty(CassandraOptions.CASSANDRA_RECONNECT_MAX_DELAY.name(), 
1000L);
   conf.setProperty(CassandraOptions.CASSANDRA_RECONNECT_MAX_RETRIES.name(), 3);
   conf.setProperty(CassandraOptions.CASSANDRA_RECONNECT_INTERVAL.name(), 1L);
   HugeConfig config = new HugeConfig(conf);
   ```
   



##########
hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/cassandra/CassandraTest.java:
##########
@@ -192,4 +198,99 @@ public void 
testParseReplicaWithNetworkTopologyStrategyAndDoubleReplica() {
             Whitebox.invokeStatic(CassandraStore.class, "parseReplica", 
config);
         });
     }
+
+    @Test
+    public void testReconnectOptionsHaveSensibleDefaults() {
+        // Runtime-reconnection options must exist with non-zero defaults so
+        // HugeGraph keeps running when Cassandra restarts (issue #2740).
+        Assert.assertEquals(1000L, (long) CassandraOptions
+                .CASSANDRA_RECONNECT_BASE_DELAY.defaultValue());
+        Assert.assertEquals(60_000L, (long) CassandraOptions
+                .CASSANDRA_RECONNECT_MAX_DELAY.defaultValue());
+        Assert.assertEquals(10, (int) CassandraOptions
+                .CASSANDRA_RECONNECT_MAX_RETRIES.defaultValue());
+        Assert.assertEquals(5000L, (long) CassandraOptions
+                .CASSANDRA_RECONNECT_INTERVAL.defaultValue());
+    }
+
+    @Test
+    public void testReconnectOptionsAreOverridable() {
+        String base = CassandraOptions.CASSANDRA_RECONNECT_BASE_DELAY.name();
+        String max = CassandraOptions.CASSANDRA_RECONNECT_MAX_DELAY.name();
+        String retries = CassandraOptions.CASSANDRA_RECONNECT_MAX_RETRIES
+                                         .name();
+        String interval = CassandraOptions.CASSANDRA_RECONNECT_INTERVAL.name();
+
+        Configuration conf = new PropertiesConfiguration();
+        conf.setProperty(base, 500L);
+        conf.setProperty(max, 30_000L);
+        conf.setProperty(retries, 3);
+        conf.setProperty(interval, 1000L);
+        HugeConfig config = new HugeConfig(conf);
+
+        Assert.assertEquals(500L, (long) config.get(
+                CassandraOptions.CASSANDRA_RECONNECT_BASE_DELAY));
+        Assert.assertEquals(30_000L, (long) config.get(
+                CassandraOptions.CASSANDRA_RECONNECT_MAX_DELAY));
+        Assert.assertEquals(3, (int) config.get(
+                CassandraOptions.CASSANDRA_RECONNECT_MAX_RETRIES));
+        Assert.assertEquals(1000L, (long) config.get(
+                CassandraOptions.CASSANDRA_RECONNECT_INTERVAL));
+    }
+
+    @Test
+    public void testReconnectRetriesCanBeDisabled() {
+        String retries = CassandraOptions.CASSANDRA_RECONNECT_MAX_RETRIES
+                                         .name();
+        Configuration conf = new PropertiesConfiguration();
+        conf.setProperty(retries, 0);
+        HugeConfig config = new HugeConfig(conf);
+        Assert.assertEquals(0, (int) config.get(
+                CassandraOptions.CASSANDRA_RECONNECT_MAX_RETRIES));
+    }
+
+    @Test
+    public void testExecuteWithRetrySucceedsAfterTransientFailures() {
+        Configuration conf = new PropertiesConfiguration();
+        HugeConfig config = new HugeConfig(conf);
+        CassandraSessionPool pool = new CassandraSessionPool(config,
+                                                             "ks", "store");
+        Whitebox.setInternalState(pool, "maxRetries", 3);
+        Whitebox.setInternalState(pool, "retryInterval", 1L);
+        Whitebox.setInternalState(pool, "retryMaxDelay", 10L);
+
+        com.datastax.driver.core.Session driverSession = Mockito.mock(
+                com.datastax.driver.core.Session.class);
+        ResultSet rs = Mockito.mock(ResultSet.class);
+        NoHostAvailableException transientFailure =
+                new NoHostAvailableException(Collections.emptyMap());
+        Mockito.when(driverSession.execute(Mockito.any(Statement.class)))
+               .thenThrow(transientFailure)
+               .thenThrow(transientFailure)
+               .thenReturn(rs);
+
+        CassandraSessionPool.Session session = pool.new Session();
+        Whitebox.setInternalState(session, "session", driverSession);
+
+        ResultSet result = session.execute("SELECT now() FROM system.local");
+        Assert.assertSame(rs, result);
+        Mockito.verify(driverSession, Mockito.times(3))
+               .execute(Mockito.any(Statement.class));
+    }
+
+    @Test
+    public void testReconnectOptionsExposeExpectedKeys() {

Review Comment:
   ๐Ÿงน **`testReconnectOptionsExposeExpectedKeys` only checks string literals โ€” 
low-value test**
   
   This test asserts that a static constant's `.name()` returns the exact 
string that is defined on the next line of the same class. If someone renames 
the key, they update both places together, so this test adds no real safety net.
   
   What is actually worth testing โ€” and not currently covered โ€” is that the 
validators reject out-of-range values, e.g.:
   
   ```java
   // base delay below minimum (100 ms) should be rejected
   Configuration conf = new PropertiesConfiguration();
   conf.setProperty(CassandraOptions.CASSANDRA_RECONNECT_BASE_DELAY.name(), 
50L);
   Assert.assertThrows(/* config validation exception */, () -> new 
HugeConfig(conf));
   
   // max < base should be rejected (the E.checkArgument in the constructor)
   conf.setProperty(CassandraOptions.CASSANDRA_RECONNECT_BASE_DELAY.name(), 
5000L);
   conf.setProperty(CassandraOptions.CASSANDRA_RECONNECT_MAX_DELAY.name(), 
1000L);
   Assert.assertThrows(IllegalArgumentException.class,
                       () -> new CassandraSessionPool(new HugeConfig(conf), 
"ks", "s"));
   ```
   
   Consider replacing or augmenting this test with boundary checks like the 
above.
   



-- 
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.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to