From 2cbf084542372f08c9261b05c881e16944d72d40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wojciech=20B=C4=85czkowski?= Date: Mon, 6 Oct 2025 17:29:12 +0200 Subject: [PATCH 1/5] Remove superflouous checks in AdvancedShardAwarenessIT These patterns ensure that certain steps were taken, but their end result is already covered by pattern checking that reconnection completed with max total number of channels. --- .../driver/core/pool/AdvancedShardAwarenessIT.java | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/integration-tests/src/test/java/com/datastax/oss/driver/core/pool/AdvancedShardAwarenessIT.java b/integration-tests/src/test/java/com/datastax/oss/driver/core/pool/AdvancedShardAwarenessIT.java index 7886442a70d..808c6a8f893 100644 --- a/integration-tests/src/test/java/com/datastax/oss/driver/core/pool/AdvancedShardAwarenessIT.java +++ b/integration-tests/src/test/java/com/datastax/oss/driver/core/pool/AdvancedShardAwarenessIT.java @@ -95,12 +95,7 @@ public void should_initialize_all_channels(boolean reuseAddress) { Map expectedOccurences = ImmutableMap.of( Pattern.compile(".*\\.2:19042.*Reconnection attempt complete, 6/6 channels.*"), 1, - Pattern.compile(".*\\.1:19042.*Reconnection attempt complete, 6/6 channels.*"), 1, - Pattern.compile(".*Reconnection attempt complete.*"), 2, - Pattern.compile(".*\\.1:19042.*New channel added \\[.*"), 5, - Pattern.compile(".*\\.2:19042.*New channel added \\[.*"), 5, - Pattern.compile(".*\\.1:19042\\] Trying to create 5 missing channels.*"), 1, - Pattern.compile(".*\\.2:19042\\] Trying to create 5 missing channels.*"), 1); + Pattern.compile(".*\\.1:19042.*Reconnection attempt complete, 6/6 channels.*"), 1); DriverConfigLoader loader = SessionUtils.configLoaderBuilder() .withBoolean(DefaultDriverOption.SOCKET_REUSE_ADDRESS, reuseAddress) @@ -203,12 +198,6 @@ public void should_not_struggle_to_fill_pools() { Pattern.compile(".*\\.2:19042.*Reconnection attempt complete, 66/66 channels.*"), 1 * sessions, Pattern.compile(".*\\.1:19042.*Reconnection attempt complete, 66/66 channels.*"), - 1 * sessions, - Pattern.compile(".*Reconnection attempt complete.*"), 2 * sessions, - Pattern.compile(".*.1:19042.*New channel added \\[.*"), 65 * sessions - tolerance, - Pattern.compile(".*.2:19042.*New channel added \\[.*"), 65 * sessions - tolerance, - Pattern.compile(".*.1:19042\\] Trying to create 65 missing channels.*"), 1 * sessions, - Pattern.compile(".*.2:19042\\] Trying to create 65 missing channels.*"), 1 * sessions); expectedOccurences.forEach( (pattern, times) -> assertMatchesAtLeast(pattern, times, appender.list)); From 1177421066b17f247dc3bc7b56a8e3ebef3df9ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wojciech=20B=C4=85czkowski?= Date: Mon, 6 Oct 2025 17:52:19 +0200 Subject: [PATCH 2/5] Add node ips to Patterns in AdvancedShardAwarenessIT Makes Patterns of expected logs more specific so that they can match only logs relevant to the test cluster. --- .../core/pool/AdvancedShardAwarenessIT.java | 44 +++++++++++++++---- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/integration-tests/src/test/java/com/datastax/oss/driver/core/pool/AdvancedShardAwarenessIT.java b/integration-tests/src/test/java/com/datastax/oss/driver/core/pool/AdvancedShardAwarenessIT.java index 808c6a8f893..7591b29e272 100644 --- a/integration-tests/src/test/java/com/datastax/oss/driver/core/pool/AdvancedShardAwarenessIT.java +++ b/integration-tests/src/test/java/com/datastax/oss/driver/core/pool/AdvancedShardAwarenessIT.java @@ -55,9 +55,8 @@ public class AdvancedShardAwarenessIT { Level originalLevelReconnection; private final Pattern shardMismatchPattern = Pattern.compile(".*r configuration of shard aware port.*"); - private final Pattern reconnectionPattern = + private final Pattern generalReconnectionPattern = Pattern.compile(".*Scheduling next reconnection in.*"); - Set forbiddenOccurences = ImmutableSet.of(shardMismatchPattern, reconnectionPattern); @DataProvider public static Object[][] reuseAddressOption() { @@ -92,10 +91,26 @@ public void stopCapturingLogs() { @Test @UseDataProvider("reuseAddressOption") public void should_initialize_all_channels(boolean reuseAddress) { + String node1 = CCM_RULE.getCcmBridge().getNodeIpAddress(1); + String node2 = CCM_RULE.getCcmBridge().getNodeIpAddress(2); + Pattern reconnectionPattern1 = + Pattern.compile(".*" + Pattern.quote(node1) + ".*Scheduling next reconnection in.*"); + Pattern reconnectionPattern2 = + Pattern.compile(".*" + Pattern.quote(node2) + ".*Scheduling next reconnection in.*"); + Set forbiddenOccurences = + ImmutableSet.of(shardMismatchPattern, reconnectionPattern1, reconnectionPattern2); Map expectedOccurences = ImmutableMap.of( - Pattern.compile(".*\\.2:19042.*Reconnection attempt complete, 6/6 channels.*"), 1, - Pattern.compile(".*\\.1:19042.*Reconnection attempt complete, 6/6 channels.*"), 1); + Pattern.compile( + ".*" + + Pattern.quote(node1) + + ":19042.*Reconnection attempt complete, 6/6 channels.*"), + 1, + Pattern.compile( + ".*" + + Pattern.quote(node2) + + ":19042.*Reconnection attempt complete, 6/6 channels.*"), + 1); DriverConfigLoader loader = SessionUtils.configLoaderBuilder() .withBoolean(DefaultDriverOption.SOCKET_REUSE_ADDRESS, reuseAddress) @@ -164,7 +179,7 @@ public void should_struggle_to_fill_pools() { CqlSession session4 = CompletableFutures.getUninterruptibly(stage4); ) { Uninterruptibles.sleepUninterruptibly(20, TimeUnit.SECONDS); assertNoLogMatches(shardMismatchPattern, appender.list); - assertMatchesAtLeast(reconnectionPattern, 8, appender.list); + assertMatchesAtLeast(generalReconnectionPattern, 8, appender.list); } } @@ -193,16 +208,29 @@ public void should_not_struggle_to_fill_pools() { CqlSession session4 = CompletableFutures.getUninterruptibly(stage4); ) { Uninterruptibles.sleepUninterruptibly(8, TimeUnit.SECONDS); int tolerance = 2; // Sometimes socket ends up already in use + String node1 = CCM_RULE.getCcmBridge().getNodeIpAddress(1); + String node2 = CCM_RULE.getCcmBridge().getNodeIpAddress(2); + Pattern reconnectionPattern1 = + Pattern.compile(".*" + Pattern.quote(node1) + ".*Scheduling next reconnection in.*"); + Pattern reconnectionPattern2 = + Pattern.compile(".*" + Pattern.quote(node2) + ".*Scheduling next reconnection in.*"); Map expectedOccurences = ImmutableMap.of( - Pattern.compile(".*\\.2:19042.*Reconnection attempt complete, 66/66 channels.*"), + Pattern.compile( + ".*" + + Pattern.quote(node1) + + ":19042.*Reconnection attempt complete, 66/66 channels.*"), 1 * sessions, - Pattern.compile(".*\\.1:19042.*Reconnection attempt complete, 66/66 channels.*"), + Pattern.compile( + ".*" + + Pattern.quote(node2) + + ":19042.*Reconnection attempt complete, 66/66 channels.*"), 1 * sessions); expectedOccurences.forEach( (pattern, times) -> assertMatchesAtLeast(pattern, times, appender.list)); assertNoLogMatches(shardMismatchPattern, appender.list); - assertMatchesAtMost(reconnectionPattern, tolerance, appender.list); + assertMatchesAtMost(reconnectionPattern1, tolerance, appender.list); + assertMatchesAtMost(reconnectionPattern2, tolerance, appender.list); } } From 0425ad2253a81cd88942657ef9c1e7733c1a1891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wojciech=20B=C4=85czkowski?= Date: Mon, 6 Oct 2025 18:02:01 +0200 Subject: [PATCH 3/5] Operate on immutable copy of logs in AdvancedShardAwarenessIT Not doing so can lead to concurrent modification exception, since the collection may change during the iteration. Those changes itself are not relevant at that point in time. --- .../core/pool/AdvancedShardAwarenessIT.java | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/integration-tests/src/test/java/com/datastax/oss/driver/core/pool/AdvancedShardAwarenessIT.java b/integration-tests/src/test/java/com/datastax/oss/driver/core/pool/AdvancedShardAwarenessIT.java index 7591b29e272..34df0a45436 100644 --- a/integration-tests/src/test/java/com/datastax/oss/driver/core/pool/AdvancedShardAwarenessIT.java +++ b/integration-tests/src/test/java/com/datastax/oss/driver/core/pool/AdvancedShardAwarenessIT.java @@ -17,6 +17,7 @@ import com.datastax.oss.driver.internal.core.pool.ChannelPool; import com.datastax.oss.driver.internal.core.util.concurrent.CompletableFutures; import com.datastax.oss.driver.internal.core.util.concurrent.Reconnection; +import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.util.concurrent.Uninterruptibles; @@ -128,9 +129,10 @@ public void should_initialize_all_channels(boolean reuseAddress) { .withConfigLoader(loader) .build()) { Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); + List logsCopy = ImmutableList.copyOf(appender.list); expectedOccurences.forEach( - (pattern, times) -> assertMatchesExactly(pattern, times, appender.list)); - forbiddenOccurences.forEach(pattern -> assertNoLogMatches(pattern, appender.list)); + (pattern, times) -> assertMatchesExactly(pattern, times, logsCopy)); + forbiddenOccurences.forEach(pattern -> assertNoLogMatches(pattern, logsCopy)); } } @@ -150,7 +152,8 @@ public void should_see_mismatched_shard() { .withConfigLoader(loader) .build()) { Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); - assertMatchesAtLeast(shardMismatchPattern, 5, appender.list); + List logsCopy = ImmutableList.copyOf(appender.list); + assertMatchesAtLeast(shardMismatchPattern, 5, logsCopy); } } @@ -178,8 +181,9 @@ public void should_struggle_to_fill_pools() { CqlSession session3 = CompletableFutures.getUninterruptibly(stage3); CqlSession session4 = CompletableFutures.getUninterruptibly(stage4); ) { Uninterruptibles.sleepUninterruptibly(20, TimeUnit.SECONDS); - assertNoLogMatches(shardMismatchPattern, appender.list); - assertMatchesAtLeast(generalReconnectionPattern, 8, appender.list); + List logsCopy = ImmutableList.copyOf(appender.list); + assertNoLogMatches(shardMismatchPattern, logsCopy); + assertMatchesAtLeast(generalReconnectionPattern, 8, logsCopy); } } @@ -226,11 +230,12 @@ public void should_not_struggle_to_fill_pools() { + Pattern.quote(node2) + ":19042.*Reconnection attempt complete, 66/66 channels.*"), 1 * sessions); + List logsCopy = ImmutableList.copyOf(appender.list); expectedOccurences.forEach( - (pattern, times) -> assertMatchesAtLeast(pattern, times, appender.list)); - assertNoLogMatches(shardMismatchPattern, appender.list); - assertMatchesAtMost(reconnectionPattern1, tolerance, appender.list); - assertMatchesAtMost(reconnectionPattern2, tolerance, appender.list); + (pattern, times) -> assertMatchesAtLeast(pattern, times, logsCopy)); + assertNoLogMatches(shardMismatchPattern, logsCopy); + assertMatchesAtMost(reconnectionPattern1, tolerance, logsCopy); + assertMatchesAtMost(reconnectionPattern2, tolerance, logsCopy); } } From 65b969fc33a0070f798e0ca3b1c7c066b6d3f4af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wojciech=20B=C4=85czkowski?= Date: Mon, 6 Oct 2025 18:15:04 +0200 Subject: [PATCH 4/5] Use Awaitility instead of `sleepUninterruptibly` Replaces hardcoded sleeps with awaits in AdvancedShardAwarenessIT. Saves some time if the code completes faster. The new awaiting time limit is longer than previous sleeps but it won't be exhausted if everything works. --- .../core/pool/AdvancedShardAwarenessIT.java | 68 +++++++++++++++---- 1 file changed, 56 insertions(+), 12 deletions(-) diff --git a/integration-tests/src/test/java/com/datastax/oss/driver/core/pool/AdvancedShardAwarenessIT.java b/integration-tests/src/test/java/com/datastax/oss/driver/core/pool/AdvancedShardAwarenessIT.java index 34df0a45436..27aafc764ad 100644 --- a/integration-tests/src/test/java/com/datastax/oss/driver/core/pool/AdvancedShardAwarenessIT.java +++ b/integration-tests/src/test/java/com/datastax/oss/driver/core/pool/AdvancedShardAwarenessIT.java @@ -10,28 +10,31 @@ import com.datastax.oss.driver.api.core.CqlSessionBuilder; import com.datastax.oss.driver.api.core.config.DefaultDriverOption; import com.datastax.oss.driver.api.core.config.DriverConfigLoader; -import com.datastax.oss.driver.api.core.session.Session; +import com.datastax.oss.driver.api.core.metadata.Node; import com.datastax.oss.driver.api.testinfra.ScyllaOnly; import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule; import com.datastax.oss.driver.api.testinfra.session.SessionUtils; import com.datastax.oss.driver.internal.core.pool.ChannelPool; +import com.datastax.oss.driver.internal.core.session.DefaultSession; import com.datastax.oss.driver.internal.core.util.concurrent.CompletableFutures; import com.datastax.oss.driver.internal.core.util.concurrent.Reconnection; import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; -import com.google.common.util.concurrent.Uninterruptibles; import com.tngtech.java.junit.dataprovider.DataProvider; import com.tngtech.java.junit.dataprovider.DataProviderRunner; import com.tngtech.java.junit.dataprovider.UseDataProvider; import java.net.InetSocketAddress; import java.time.Duration; +import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.CompletionStage; import java.util.concurrent.TimeUnit; import java.util.regex.Pattern; +import org.awaitility.Awaitility; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; @@ -92,6 +95,7 @@ public void stopCapturingLogs() { @Test @UseDataProvider("reuseAddressOption") public void should_initialize_all_channels(boolean reuseAddress) { + int expectedChannelsPerNode = 6; // Divisible by smp String node1 = CCM_RULE.getCcmBridge().getNodeIpAddress(1); String node2 = CCM_RULE.getCcmBridge().getNodeIpAddress(2); Pattern reconnectionPattern1 = @@ -120,15 +124,19 @@ public void should_initialize_all_channels(boolean reuseAddress) { .withInt(DefaultDriverOption.ADVANCED_SHARD_AWARENESS_PORT_HIGH, 60000) // Due to rounding up the connections per shard this will result in 6 connections per // node - .withInt(DefaultDriverOption.CONNECTION_POOL_LOCAL_SIZE, 4) + .withInt(DefaultDriverOption.CONNECTION_POOL_LOCAL_SIZE, expectedChannelsPerNode) .build(); - try (Session session = + try (CqlSession session = CqlSession.builder() .addContactPoint( new InetSocketAddress(CCM_RULE.getCcmBridge().getNodeIpAddress(1), 19042)) .withConfigLoader(loader) .build()) { - Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); + List allSessions = Collections.singletonList(session); + Awaitility.await() + .atMost(5, TimeUnit.SECONDS) + .pollInterval(500, TimeUnit.MILLISECONDS) + .until(() -> areAllPoolsFullyInitialized(allSessions, expectedChannelsPerNode)); List logsCopy = ImmutableList.copyOf(appender.list); expectedOccurences.forEach( (pattern, times) -> assertMatchesExactly(pattern, times, logsCopy)); @@ -138,20 +146,25 @@ public void should_initialize_all_channels(boolean reuseAddress) { @Test public void should_see_mismatched_shard() { + int expectedChannelsPerNode = 66; // Divisible by smp DriverConfigLoader loader = SessionUtils.configLoaderBuilder() .withBoolean(DefaultDriverOption.CONNECTION_ADVANCED_SHARD_AWARENESS_ENABLED, true) .withInt(DefaultDriverOption.ADVANCED_SHARD_AWARENESS_PORT_LOW, 10000) .withInt(DefaultDriverOption.ADVANCED_SHARD_AWARENESS_PORT_HIGH, 60000) - .withInt(DefaultDriverOption.CONNECTION_POOL_LOCAL_SIZE, 64) + .withInt(DefaultDriverOption.CONNECTION_POOL_LOCAL_SIZE, 66) .build(); - try (Session session = + try (CqlSession session = CqlSession.builder() .addContactPoint( new InetSocketAddress(CCM_RULE.getCcmBridge().getNodeIpAddress(1), 9042)) .withConfigLoader(loader) .build()) { - Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); + List allSessions = Collections.singletonList(session); + Awaitility.await() + .atMost(20, TimeUnit.SECONDS) + .pollInterval(500, TimeUnit.MILLISECONDS) + .until(() -> areAllPoolsFullyInitialized(allSessions, expectedChannelsPerNode)); List logsCopy = ImmutableList.copyOf(appender.list); assertMatchesAtLeast(shardMismatchPattern, 5, logsCopy); } @@ -160,10 +173,11 @@ public void should_see_mismatched_shard() { // There is no need to run this as a test, but it serves as a comparison @SuppressWarnings("unused") public void should_struggle_to_fill_pools() { + int expectedChannelsPerNode = 66; // Divisible by smp DriverConfigLoader loader = SessionUtils.configLoaderBuilder() .withBoolean(DefaultDriverOption.CONNECTION_ADVANCED_SHARD_AWARENESS_ENABLED, false) - .withInt(DefaultDriverOption.CONNECTION_POOL_LOCAL_SIZE, 64) + .withInt(DefaultDriverOption.CONNECTION_POOL_LOCAL_SIZE, 66) .withDuration(DefaultDriverOption.RECONNECTION_BASE_DELAY, Duration.ofMillis(200)) .withDuration(DefaultDriverOption.RECONNECTION_MAX_DELAY, Duration.ofMillis(4000)) .build(); @@ -180,7 +194,11 @@ public void should_struggle_to_fill_pools() { CqlSession session2 = CompletableFutures.getUninterruptibly(stage2); CqlSession session3 = CompletableFutures.getUninterruptibly(stage3); CqlSession session4 = CompletableFutures.getUninterruptibly(stage4); ) { - Uninterruptibles.sleepUninterruptibly(20, TimeUnit.SECONDS); + List allSessions = Arrays.asList(session1, session2, session3, session4); + Awaitility.await() + .atMost(20, TimeUnit.SECONDS) + .pollInterval(500, TimeUnit.MILLISECONDS) + .until(() -> areAllPoolsFullyInitialized(allSessions, expectedChannelsPerNode)); List logsCopy = ImmutableList.copyOf(appender.list); assertNoLogMatches(shardMismatchPattern, logsCopy); assertMatchesAtLeast(generalReconnectionPattern, 8, logsCopy); @@ -189,10 +207,11 @@ public void should_struggle_to_fill_pools() { @Test public void should_not_struggle_to_fill_pools() { + int expectedChannelsPerNode = 66; DriverConfigLoader loader = SessionUtils.configLoaderBuilder() .withBoolean(DefaultDriverOption.CONNECTION_ADVANCED_SHARD_AWARENESS_ENABLED, true) - .withInt(DefaultDriverOption.CONNECTION_POOL_LOCAL_SIZE, 66) + .withInt(DefaultDriverOption.CONNECTION_POOL_LOCAL_SIZE, expectedChannelsPerNode) .withDuration(DefaultDriverOption.RECONNECTION_BASE_DELAY, Duration.ofMillis(10)) .withDuration(DefaultDriverOption.RECONNECTION_MAX_DELAY, Duration.ofMillis(20)) .build(); @@ -210,7 +229,11 @@ public void should_not_struggle_to_fill_pools() { CqlSession session2 = CompletableFutures.getUninterruptibly(stage2); CqlSession session3 = CompletableFutures.getUninterruptibly(stage3); CqlSession session4 = CompletableFutures.getUninterruptibly(stage4); ) { - Uninterruptibles.sleepUninterruptibly(8, TimeUnit.SECONDS); + List allSessions = Arrays.asList(session1, session2, session3, session4); + Awaitility.await() + .atMost(20, TimeUnit.SECONDS) + .pollInterval(500, TimeUnit.MILLISECONDS) + .until(() -> areAllPoolsFullyInitialized(allSessions, expectedChannelsPerNode)); int tolerance = 2; // Sometimes socket ends up already in use String node1 = CCM_RULE.getCcmBridge().getNodeIpAddress(1); String node2 = CCM_RULE.getCcmBridge().getNodeIpAddress(2); @@ -239,6 +262,27 @@ public void should_not_struggle_to_fill_pools() { } } + private boolean areAllPoolsFullyInitialized( + List sessions, int expectedChannelsPerNode) { + for (CqlSession session : sessions) { + DefaultSession defaultSession = (DefaultSession) session; + Map pools = defaultSession.getPools(); + if (pools == null || pools.isEmpty()) { + return false; + } + + for (ChannelPool pool : pools.values()) { + if (pool == null) { + return false; + } + if (pool.size() < expectedChannelsPerNode) { + return false; + } + } + } + return true; + } + private void assertNoLogMatches(Pattern pattern, List logs) { for (ILoggingEvent log : logs) { if (pattern.matcher(log.getFormattedMessage()).matches()) { From 069ca764999764ba7d5574263d65f051d45b1fff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wojciech=20B=C4=85czkowski?= Date: Mon, 6 Oct 2025 20:39:47 +0200 Subject: [PATCH 5/5] Make AdvancedShardAwarenessIT isolated test Moves it to IsolatedTests category for some extra safety --- .../oss/driver/core/pool/AdvancedShardAwarenessIT.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/integration-tests/src/test/java/com/datastax/oss/driver/core/pool/AdvancedShardAwarenessIT.java b/integration-tests/src/test/java/com/datastax/oss/driver/core/pool/AdvancedShardAwarenessIT.java index 27aafc764ad..aeda4a02c7b 100644 --- a/integration-tests/src/test/java/com/datastax/oss/driver/core/pool/AdvancedShardAwarenessIT.java +++ b/integration-tests/src/test/java/com/datastax/oss/driver/core/pool/AdvancedShardAwarenessIT.java @@ -14,6 +14,7 @@ import com.datastax.oss.driver.api.testinfra.ScyllaOnly; import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule; import com.datastax.oss.driver.api.testinfra.session.SessionUtils; +import com.datastax.oss.driver.categories.IsolatedTests; import com.datastax.oss.driver.internal.core.pool.ChannelPool; import com.datastax.oss.driver.internal.core.session.DefaultSession; import com.datastax.oss.driver.internal.core.util.concurrent.CompletableFutures; @@ -39,11 +40,13 @@ import org.junit.Before; import org.junit.ClassRule; import org.junit.Test; +import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.slf4j.LoggerFactory; @ScyllaOnly(description = "Advanced shard awareness relies on ScyllaDB's shard aware port") @RunWith(DataProviderRunner.class) +@Category(IsolatedTests.class) public class AdvancedShardAwarenessIT { @ClassRule