This is an automated email from the ASF dual-hosted git repository.

absurdfarce pushed a commit to branch 4.x
in repository https://gitbox.apache.org/repos/asf/cassandra-java-driver.git


The following commit(s) were added to refs/heads/4.x by this push:
     new 7eec03e56 Refactor integration tests to support multiple C* 
distributions. Test with DataStax HCD 1.0.0
7eec03e56 is described below

commit 7eec03e56848b30a3c422f7d89337255478a494e
Author: Lukasz Antoniak <lukasz.anton...@gmail.com>
AuthorDate: Sun Sep 8 15:06:53 2024 +0200

    Refactor integration tests to support multiple C* distributions. Test with 
DataStax HCD 1.0.0
---
 Jenkinsfile-datastax                               |  34 +++-
 .../com/datastax/oss/driver/api/core/Version.java  |   1 +
 .../core/cql/continuous/ContinuousPagingIT.java    |   8 +-
 .../graph/remote/GraphTraversalRemoteITBase.java   |   5 +-
 .../core/graph/statement/GraphTraversalITBase.java |   5 +-
 .../metadata/schema/DseAggregateMetadataIT.java    |   6 +-
 .../metadata/schema/DseFunctionMetadataIT.java     |   6 +-
 .../core/compression/DirectCompressionIT.java      |   6 +-
 .../driver/core/compression/HeapCompressionIT.java |   3 +-
 .../datastax/oss/driver/core/cql/QueryTraceIT.java |   3 +-
 .../oss/driver/core/metadata/DescribeIT.java       |  28 ++--
 .../oss/driver/core/metadata/NodeMetadataIT.java   |   7 +-
 .../oss/driver/core/metadata/SchemaChangesIT.java  |   5 +-
 .../oss/driver/core/metadata/SchemaIT.java         |   8 +-
 .../oss/driver/mapper/DeleteReactiveIT.java        |   5 +-
 .../oss/driver/mapper/InventoryITBase.java         |  11 +-
 .../src/test/resources/DescribeIT/hcd/1.0.cql      | 186 +++++++++++++++++++++
 osgi-tests/README.md                               |   4 +-
 .../internal/osgi/support/CcmStagedReactor.java    |   8 +-
 test-infra/revapi.json                             |  21 +++
 .../oss/driver/api/testinfra/ccm/BaseCcmRule.java  |  24 ++-
 .../oss/driver/api/testinfra/ccm/CcmBridge.java    |  83 ++++-----
 .../ccm/DefaultCcmBridgeBuilderCustomizer.java     |   8 +-
 .../ccm/DistributionCassandraVersions.java         |  57 +++++++
 .../requirement/BackendRequirementRule.java        |   2 +-
 .../api/testinfra/requirement/BackendType.java     |  13 +-
 .../driver/api/testinfra/session/SessionRule.java  |  13 +-
 27 files changed, 439 insertions(+), 121 deletions(-)

diff --git a/Jenkinsfile-datastax b/Jenkinsfile-datastax
index 4cc20d796..af3faafee 100644
--- a/Jenkinsfile-datastax
+++ b/Jenkinsfile-datastax
@@ -61,7 +61,7 @@ def initializeEnvironment() {
     . ${JABBA_SHELL}
     jabba which 1.8''', returnStdout: true).trim()
 
-  sh label: 'Download Apache CassandraⓇ or DataStax Enterprise',script: 
'''#!/bin/bash -le
+  sh label: 'Download Apache CassandraⓇ, DataStax Enterprise or DataStax HCD 
',script: '''#!/bin/bash -le
     . ${JABBA_SHELL}
     jabba use 1.8
     . ${CCM_ENVIRONMENT_SHELL} ${SERVER_VERSION}
@@ -75,13 +75,26 @@ CCM_CASSANDRA_VERSION=${DSE_FIXED_VERSION} # maintain for 
backwards compatibilit
 CCM_VERSION=${DSE_FIXED_VERSION}
 CCM_SERVER_TYPE=dse
 DSE_VERSION=${DSE_FIXED_VERSION}
-CCM_IS_DSE=true
 CCM_BRANCH=${DSE_FIXED_VERSION}
 DSE_BRANCH=${DSE_FIXED_VERSION}
 ENVIRONMENT_EOF
       '''
   }
 
+  if (env.SERVER_VERSION.split('-')[0] == 'hcd') {
+    env.HCD_FIXED_VERSION = env.SERVER_VERSION.split('-')[1]
+    sh label: 'Update environment for DataStax HCD', script: '''#!/bin/bash -le
+        cat >> ${HOME}/environment.txt << ENVIRONMENT_EOF
+CCM_CASSANDRA_VERSION=${HCD_FIXED_VERSION} # maintain for backwards 
compatibility
+CCM_VERSION=${HCD_FIXED_VERSION}
+CCM_SERVER_TYPE=hcd
+HCD_VERSION=${HCD_FIXED_VERSION}
+CCM_BRANCH=${HCD_FIXED_VERSION}
+HCD_BRANCH=${HCD_FIXED_VERSION}
+ENVIRONMENT_EOF
+      '''
+  }
+
   sh label: 'Display Java and environment information',script: '''#!/bin/bash 
-le
     # Load CCM environment variables
     set -o allexport
@@ -144,7 +157,7 @@ def executeTests() {
       -Dmaven.test.failure.ignore=true \
       -Dmaven.javadoc.skip=${SKIP_JAVADOCS} \
       -Dccm.version=${CCM_CASSANDRA_VERSION} \
-      -Dccm.dse=${CCM_IS_DSE} \
+      -Dccm.distribution=${CCM_SERVER_TYPE:cassandra} \
       -Dproxy.path=${HOME}/proxy \
       ${SERIAL_ITS_ARGUMENT} \
       ${ISOLATED_ITS_ARGUMENT} \
@@ -269,6 +282,7 @@ pipeline {
                 'dse-6.7.17',   // Previous DataStax Enterprise
                 'dse-6.8.30',   // Current DataStax Enterprise
                 'dse-6.9.0',    // Current DataStax Enterprise
+                'hcd-1.0.0',    // Current DataStax HCD
                 'ALL'],
       description: '''Apache Cassandra&reg; and DataStax Enterprise server 
version to use for adhoc <b>BUILD-AND-EXECUTE-TESTS</b> builds
                       <table style="width:100%">
@@ -330,6 +344,10 @@ pipeline {
                           <td><strong>dse-6.9.0</strong></td>
                           <td>DataStax Enterprise v6.9.x</td>
                         </tr>
+                        <tr>
+                          <td><strong>hcd-1.0.0</strong></td>
+                          <td>DataStax HCD v1.0.x</td>
+                        </tr>
                       </table>''')
     choice(
       name: 'ADHOC_BUILD_AND_EXECUTE_TESTS_JABBA_VERSION',
@@ -421,9 +439,9 @@ pipeline {
       H 2 * * 0 %CI_SCHEDULE=WEEKENDS;CI_SCHEDULE_SERVER_VERSIONS=2.1 3.0 4.0 
dse-4.8.16 dse-5.0.15 dse-5.1.35 dse-6.0.18 
dse-6.7.17;CI_SCHEDULE_JABBA_VERSION=1.8
       # Every weeknight (Monday - Friday) around 12:00 PM noon
       ### JDK11 tests against 3.11, 4.1, 5.0-beta1 and DSE 6.8
-      H 12 * * 1-5 %CI_SCHEDULE=WEEKNIGHTS;CI_SCHEDULE_SERVER_VERSIONS=3.11 
4.1 5.0-beta1 dse-6.8.30 dse-6.9.0;CI_SCHEDULE_JABBA_VERSION=openjdk@1.11
+      H 12 * * 1-5 %CI_SCHEDULE=WEEKNIGHTS;CI_SCHEDULE_SERVER_VERSIONS=3.11 
4.1 5.0-beta1 dse-6.8.30 dse-6.9.0 
hcd-1.0.0;CI_SCHEDULE_JABBA_VERSION=openjdk@1.11
       ### JDK17 tests against 3.11, 4.1, 5.0-beta1 and DSE 6.8
-      H 12 * * 1-5 %CI_SCHEDULE=WEEKNIGHTS;CI_SCHEDULE_SERVER_VERSIONS=3.11 
4.1 5.0-beta1 dse-6.8.30 dse-6.9.0;CI_SCHEDULE_JABBA_VERSION=openjdk@1.17
+      H 12 * * 1-5 %CI_SCHEDULE=WEEKNIGHTS;CI_SCHEDULE_SERVER_VERSIONS=3.11 
4.1 5.0-beta1 dse-6.8.30 dse-6.9.0 
hcd-1.0.0;CI_SCHEDULE_JABBA_VERSION=openjdk@1.17
     """ : "")
   }
 
@@ -460,7 +478,8 @@ pipeline {
             values '3.11',       // Latest stable Apache CassandraⓇ
                    '4.1',        // Development Apache CassandraⓇ
                    'dse-6.8.30', // Current DataStax Enterprise
-                   'dse-6.9.0'   // Current DataStax Enterprise
+                   'dse-6.9.0',  // Current DataStax Enterprise
+                   'hcd-1.0.0'   // Current DataStax HCD
           }
           axis {
             name 'JABBA_VERSION'
@@ -578,7 +597,8 @@ pipeline {
                    'dse-6.0.18',   // Previous DataStax Enterprise
                    'dse-6.7.17',   // Previous DataStax Enterprise
                    'dse-6.8.30',   // Current DataStax Enterprise
-                   'dse-6.9.0'     // Current DataStax Enterprise
+                   'dse-6.9.0',    // Current DataStax Enterprise
+                   'hcd-1.0.0'     // Current DataStax HCD
           }
         }
         when {
diff --git a/core/src/main/java/com/datastax/oss/driver/api/core/Version.java 
b/core/src/main/java/com/datastax/oss/driver/api/core/Version.java
index 4de006da2..52751e029 100644
--- a/core/src/main/java/com/datastax/oss/driver/api/core/Version.java
+++ b/core/src/main/java/com/datastax/oss/driver/api/core/Version.java
@@ -48,6 +48,7 @@ public class Version implements Comparable<Version>, 
Serializable {
 
   private static final Pattern pattern = Pattern.compile(VERSION_REGEXP);
 
+  @NonNull public static final Version V1_0_0 = 
Objects.requireNonNull(parse("1.0.0"));
   @NonNull public static final Version V2_1_0 = 
Objects.requireNonNull(parse("2.1.0"));
   @NonNull public static final Version V2_2_0 = 
Objects.requireNonNull(parse("2.2.0"));
   @NonNull public static final Version V3_0_0 = 
Objects.requireNonNull(parse("3.0.0"));
diff --git 
a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/cql/continuous/ContinuousPagingIT.java
 
b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/cql/continuous/ContinuousPagingIT.java
index 24ee5c037..45cc84f07 100644
--- 
a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/cql/continuous/ContinuousPagingIT.java
+++ 
b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/cql/continuous/ContinuousPagingIT.java
@@ -46,7 +46,6 @@ import java.nio.ByteBuffer;
 import java.time.Duration;
 import java.util.Collections;
 import java.util.Iterator;
-import java.util.Objects;
 import java.util.concurrent.CancellationException;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.CompletionStage;
@@ -281,11 +280,8 @@ public class ContinuousPagingIT extends 
ContinuousPagingITBase {
       // dropped.
       Row row = it.next();
       assertThat(row.getString("k")).isNotNull();
-      if (ccmRule
-              .getDseVersion()
-              .orElseThrow(IllegalStateException::new)
-              .compareTo(Objects.requireNonNull(Version.parse("6.0.0")))
-          >= 0) {
+      if (ccmRule.isDistributionOf(
+          BackendType.DSE, (dist, cass) -> 
dist.compareTo(Version.parse("6.0.0")) >= 0)) {
         // DSE 6 only, v should be null here since dropped.
         // Not reliable for 5.1 since we may have gotten page queued before 
schema changed.
         assertThat(row.isNull("v")).isTrue();
diff --git 
a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/remote/GraphTraversalRemoteITBase.java
 
b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/remote/GraphTraversalRemoteITBase.java
index 699499513..3db8a7d1a 100644
--- 
a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/remote/GraphTraversalRemoteITBase.java
+++ 
b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/remote/GraphTraversalRemoteITBase.java
@@ -30,6 +30,7 @@ import com.datastax.dse.driver.api.core.graph.__;
 import com.datastax.oss.driver.api.core.CqlSession;
 import com.datastax.oss.driver.api.core.Version;
 import com.datastax.oss.driver.api.core.servererrors.InvalidQueryException;
+import com.datastax.oss.driver.api.testinfra.ccm.CcmBridge;
 import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule;
 import com.datastax.oss.driver.api.testinfra.requirement.BackendRequirement;
 import com.datastax.oss.driver.api.testinfra.requirement.BackendType;
@@ -643,9 +644,9 @@ public abstract class GraphTraversalRemoteITBase {
    */
   @Test
   public void should_return_correct_results_when_bulked() {
-    Optional<Version> dseVersion = ccmRule().getCcmBridge().getDseVersion();
     Assumptions.assumeThat(
-            dseVersion.isPresent() && 
dseVersion.get().compareTo(Version.parse("5.1.2")) > 0)
+            CcmBridge.isDistributionOf(
+                BackendType.DSE, (dist, cass) -> 
dist.compareTo(Version.parse("5.1.2")) > 0))
         .isTrue();
 
     List<String> results = 
graphTraversalSource().E().label().barrier().toList();
diff --git 
a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/GraphTraversalITBase.java
 
b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/GraphTraversalITBase.java
index 98d9ccf1b..5bcb01bc1 100644
--- 
a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/GraphTraversalITBase.java
+++ 
b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/graph/statement/GraphTraversalITBase.java
@@ -36,7 +36,9 @@ import com.datastax.oss.driver.api.core.CqlSession;
 import com.datastax.oss.driver.api.core.Version;
 import com.datastax.oss.driver.api.core.servererrors.InvalidQueryException;
 import com.datastax.oss.driver.api.core.type.reflect.GenericType;
+import com.datastax.oss.driver.api.testinfra.ccm.CcmBridge;
 import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule;
+import com.datastax.oss.driver.api.testinfra.requirement.BackendType;
 import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableList;
 import com.datastax.oss.driver.shaded.guava.common.collect.Lists;
 import java.util.List;
@@ -598,7 +600,8 @@ public abstract class GraphTraversalITBase {
   @Test
   public void should_return_correct_results_when_bulked() {
     Assumptions.assumeThat(
-            
ccmRule().getCcmBridge().getDseVersion().get().compareTo(Version.parse("5.1.2"))
 > 0)
+            CcmBridge.isDistributionOf(
+                BackendType.DSE, (dist, cass) -> 
dist.compareTo(Version.parse("5.1.2")) > 0))
         .isTrue();
 
     GraphResultSet rs =
diff --git 
a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/metadata/schema/DseAggregateMetadataIT.java
 
b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/metadata/schema/DseAggregateMetadataIT.java
index b0e989e86..4c899fa5e 100644
--- 
a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/metadata/schema/DseAggregateMetadataIT.java
+++ 
b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/metadata/schema/DseAggregateMetadataIT.java
@@ -106,9 +106,9 @@ public class DseAggregateMetadataIT extends 
AbstractMetadataIT {
   }
 
   private static boolean isDse6OrHigher() {
-    assumeThat(CCM_RULE.getDseVersion())
+    assumeThat(CCM_RULE.isDistributionOf(BackendType.DSE))
         .describedAs("DSE required for DseFunctionMetadata tests")
-        .isPresent();
-    return CCM_RULE.getDseVersion().get().compareTo(DSE_6_0_0) >= 0;
+        .isTrue();
+    return CCM_RULE.getDistributionVersion().compareTo(DSE_6_0_0) >= 0;
   }
 }
diff --git 
a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/metadata/schema/DseFunctionMetadataIT.java
 
b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/metadata/schema/DseFunctionMetadataIT.java
index 53e2d1be8..53559a66b 100644
--- 
a/integration-tests/src/test/java/com/datastax/dse/driver/api/core/metadata/schema/DseFunctionMetadataIT.java
+++ 
b/integration-tests/src/test/java/com/datastax/dse/driver/api/core/metadata/schema/DseFunctionMetadataIT.java
@@ -233,9 +233,9 @@ public class DseFunctionMetadataIT extends 
AbstractMetadataIT {
   }
 
   private static boolean isDse6OrHigher() {
-    assumeThat(CCM_RULE.getDseVersion())
+    assumeThat(CCM_RULE.isDistributionOf(BackendType.DSE))
         .describedAs("DSE required for DseFunctionMetadata tests")
-        .isPresent();
-    return CCM_RULE.getDseVersion().get().compareTo(DSE_6_0_0) >= 0;
+        .isTrue();
+    return CCM_RULE.getDistributionVersion().compareTo(DSE_6_0_0) >= 0;
   }
 }
diff --git 
a/integration-tests/src/test/java/com/datastax/oss/driver/core/compression/DirectCompressionIT.java
 
b/integration-tests/src/test/java/com/datastax/oss/driver/core/compression/DirectCompressionIT.java
index 51f71f85b..3dad08f4d 100644
--- 
a/integration-tests/src/test/java/com/datastax/oss/driver/core/compression/DirectCompressionIT.java
+++ 
b/integration-tests/src/test/java/com/datastax/oss/driver/core/compression/DirectCompressionIT.java
@@ -29,6 +29,7 @@ import com.datastax.oss.driver.api.core.cql.ResultSet;
 import com.datastax.oss.driver.api.core.cql.Row;
 import com.datastax.oss.driver.api.core.cql.SimpleStatement;
 import com.datastax.oss.driver.api.testinfra.ccm.CcmRule;
+import com.datastax.oss.driver.api.testinfra.requirement.BackendType;
 import com.datastax.oss.driver.api.testinfra.session.SessionRule;
 import com.datastax.oss.driver.api.testinfra.session.SessionUtils;
 import com.datastax.oss.driver.categories.ParallelizableTests;
@@ -75,8 +76,9 @@ public class DirectCompressionIT {
   public void should_execute_queries_with_snappy_compression() throws 
Exception {
     Assume.assumeTrue(
         "Snappy is not supported in OSS C* 4.0+ with protocol v5",
-        CCM_RULE.getDseVersion().isPresent()
-            || 
CCM_RULE.getCassandraVersion().nextStable().compareTo(Version.V4_0_0) < 0);
+        !CCM_RULE.isDistributionOf(BackendType.HCD)
+            && (CCM_RULE.isDistributionOf(BackendType.DSE)
+                || 
CCM_RULE.getCassandraVersion().nextStable().compareTo(Version.V4_0_0) < 0));
     createAndCheckCluster("snappy");
   }
 
diff --git 
a/integration-tests/src/test/java/com/datastax/oss/driver/core/compression/HeapCompressionIT.java
 
b/integration-tests/src/test/java/com/datastax/oss/driver/core/compression/HeapCompressionIT.java
index 466a9d87a..a14c3b29b 100644
--- 
a/integration-tests/src/test/java/com/datastax/oss/driver/core/compression/HeapCompressionIT.java
+++ 
b/integration-tests/src/test/java/com/datastax/oss/driver/core/compression/HeapCompressionIT.java
@@ -29,6 +29,7 @@ import com.datastax.oss.driver.api.core.cql.ResultSet;
 import com.datastax.oss.driver.api.core.cql.Row;
 import com.datastax.oss.driver.api.core.cql.SimpleStatement;
 import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule;
+import com.datastax.oss.driver.api.testinfra.requirement.BackendType;
 import com.datastax.oss.driver.api.testinfra.session.SessionRule;
 import com.datastax.oss.driver.api.testinfra.session.SessionUtils;
 import com.datastax.oss.driver.categories.IsolatedTests;
@@ -79,7 +80,7 @@ public class HeapCompressionIT {
   public void should_execute_queries_with_snappy_compression() throws 
Exception {
     Assume.assumeTrue(
         "Snappy is not supported in OSS C* 4.0+ with protocol v5",
-        CCM_RULE.getDseVersion().isPresent()
+        CCM_RULE.isDistributionOf(BackendType.DSE)
             || 
CCM_RULE.getCassandraVersion().nextStable().compareTo(Version.V4_0_0) < 0);
     createAndCheckCluster("snappy");
   }
diff --git 
a/integration-tests/src/test/java/com/datastax/oss/driver/core/cql/QueryTraceIT.java
 
b/integration-tests/src/test/java/com/datastax/oss/driver/core/cql/QueryTraceIT.java
index f4ac85d66..37a600efb 100644
--- 
a/integration-tests/src/test/java/com/datastax/oss/driver/core/cql/QueryTraceIT.java
+++ 
b/integration-tests/src/test/java/com/datastax/oss/driver/core/cql/QueryTraceIT.java
@@ -28,6 +28,7 @@ import com.datastax.oss.driver.api.core.cql.Row;
 import com.datastax.oss.driver.api.core.cql.SimpleStatement;
 import com.datastax.oss.driver.api.core.metadata.EndPoint;
 import com.datastax.oss.driver.api.testinfra.ccm.CcmRule;
+import com.datastax.oss.driver.api.testinfra.requirement.BackendType;
 import com.datastax.oss.driver.api.testinfra.session.SessionRule;
 import com.datastax.oss.driver.categories.ParallelizableTests;
 import java.net.InetAddress;
@@ -82,7 +83,7 @@ public class QueryTraceIT {
     InetAddress nodeAddress = ((InetSocketAddress) 
contactPoint.resolve()).getAddress();
     boolean expectPorts =
         CCM_RULE.getCassandraVersion().nextStable().compareTo(Version.V4_0_0) 
>= 0
-            && !CCM_RULE.getDseVersion().isPresent();
+            && !CCM_RULE.isDistributionOf(BackendType.DSE);
 
     QueryTrace queryTrace = executionInfo.getQueryTrace();
     
assertThat(queryTrace.getTracingId()).isEqualTo(executionInfo.getTracingId());
diff --git 
a/integration-tests/src/test/java/com/datastax/oss/driver/core/metadata/DescribeIT.java
 
b/integration-tests/src/test/java/com/datastax/oss/driver/core/metadata/DescribeIT.java
index 9fbf5e355..4d6c2a7a3 100644
--- 
a/integration-tests/src/test/java/com/datastax/oss/driver/core/metadata/DescribeIT.java
+++ 
b/integration-tests/src/test/java/com/datastax/oss/driver/core/metadata/DescribeIT.java
@@ -29,6 +29,7 @@ import 
com.datastax.oss.driver.api.core.metadata.schema.KeyspaceMetadata;
 import com.datastax.oss.driver.api.core.metadata.schema.TableMetadata;
 import com.datastax.oss.driver.api.testinfra.ccm.CcmRule;
 import com.datastax.oss.driver.api.testinfra.ccm.SchemaChangeSynchronizer;
+import com.datastax.oss.driver.api.testinfra.requirement.BackendType;
 import com.datastax.oss.driver.api.testinfra.session.SessionRule;
 import com.datastax.oss.driver.api.testinfra.session.SessionUtils;
 import com.datastax.oss.driver.categories.ParallelizableTests;
@@ -37,12 +38,14 @@ import 
com.datastax.oss.driver.internal.core.metadata.schema.DefaultKeyspaceMeta
 import 
com.datastax.oss.driver.internal.core.metadata.schema.DefaultTableMetadata;
 import com.datastax.oss.driver.shaded.guava.common.base.Charsets;
 import com.datastax.oss.driver.shaded.guava.common.base.Splitter;
+import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableMap;
 import com.google.common.io.Files;
 import java.io.File;
 import java.io.IOException;
 import java.net.URL;
 import java.time.Duration;
 import java.util.List;
+import java.util.Map;
 import java.util.Optional;
 import java.util.regex.Pattern;
 import org.junit.BeforeClass;
@@ -79,17 +82,23 @@ public class DescribeIT {
       Splitter.on(Pattern.compile(";\n")).omitEmptyStrings();
 
   private static Version serverVersion;
-  private static boolean isDse;
+
+  private static final Map<BackendType, String> scriptFileForBackend =
+      ImmutableMap.<BackendType, String>builder()
+          .put(BackendType.CASSANDRA, "DescribeIT/oss")
+          .put(BackendType.DSE, "DescribeIT/dse")
+          .put(BackendType.HCD, "DescribeIT/hcd")
+          .build();
 
   private static File scriptFile;
   private static String scriptContents;
 
   @BeforeClass
   public static void setup() {
-    Optional<Version> dseVersion = CCM_RULE.getDseVersion();
-    isDse = dseVersion.isPresent();
     serverVersion =
-        isDse ? dseVersion.get().nextStable() : 
CCM_RULE.getCassandraVersion().nextStable();
+        CCM_RULE.isDistributionOf(BackendType.CASSANDRA)
+            ? CCM_RULE.getCassandraVersion().nextStable()
+            : CCM_RULE.getDistributionVersion().nextStable();
 
     scriptFile = getScriptFile();
     assertThat(scriptFile).exists();
@@ -114,12 +123,12 @@ public class DescribeIT {
             "Describe output doesn't match create statements, "
                 + "maybe you need to add a new script in 
integration-tests/src/test/resources. "
                 + "Server version = %s %s, used script = %s",
-            isDse ? "DSE" : "Cassandra", serverVersion, scriptFile)
+            CCM_RULE.getDistribution(), serverVersion, scriptFile)
         .isEqualTo(scriptContents);
   }
 
   private boolean atLeastVersion(Version dseVersion, Version ossVersion) {
-    Version comparison = isDse ? dseVersion : ossVersion;
+    Version comparison = CCM_RULE.isDistributionOf(BackendType.DSE) ? 
dseVersion : ossVersion;
     return serverVersion.compareTo(comparison) >= 0;
   }
 
@@ -138,11 +147,9 @@ public class DescribeIT {
     assertThat(ks.getUserDefinedTypes()).isNotEmpty();
     assertThat(ks.getTables()).isNotEmpty();
     if (atLeastVersion(Version.V5_0_0, Version.V3_0_0)) {
-
       assertThat(ks.getViews()).isNotEmpty();
     }
     if (atLeastVersion(Version.V5_0_0, Version.V2_2_0)) {
-
       assertThat(ks.getFunctions()).isNotEmpty();
       assertThat(ks.getAggregates()).isNotEmpty();
     }
@@ -177,7 +184,7 @@ public class DescribeIT {
           logbackTestUrl);
     }
     File resourcesDir = new File(logbackTestUrl.getFile()).getParentFile();
-    File scriptsDir = new File(resourcesDir, isDse ? "DescribeIT/dse" : 
"DescribeIT/oss");
+    File scriptsDir = new File(resourcesDir, 
scriptFileForBackend.get(CCM_RULE.getDistribution()));
     LOG.debug("Looking for a matching script in directory {}", scriptsDir);
 
     File[] candidates = scriptsDir.listFiles();
@@ -204,8 +211,7 @@ public class DescribeIT {
         .as("Could not find create script with version <= %s in %s", 
serverVersion, scriptsDir)
         .isNotNull();
 
-    LOG.info(
-        "Using {} to test against {} {}", bestFile, isDse ? "DSE" : 
"Cassandra", serverVersion);
+    LOG.info("Using {} to test against {} {}", bestFile, 
CCM_RULE.getDistribution(), serverVersion);
     return bestFile;
   }
 
diff --git 
a/integration-tests/src/test/java/com/datastax/oss/driver/core/metadata/NodeMetadataIT.java
 
b/integration-tests/src/test/java/com/datastax/oss/driver/core/metadata/NodeMetadataIT.java
index c7b51c040..8f5680ff4 100644
--- 
a/integration-tests/src/test/java/com/datastax/oss/driver/core/metadata/NodeMetadataIT.java
+++ 
b/integration-tests/src/test/java/com/datastax/oss/driver/core/metadata/NodeMetadataIT.java
@@ -62,8 +62,9 @@ public class NodeMetadataIT {
       
assertThat(node.getListenAddress().get().getAddress()).isEqualTo(connectAddress.getAddress());
       assertThat(node.getDatacenter()).isEqualTo("dc1");
       assertThat(node.getRack()).isEqualTo("r1");
-      if (!CcmBridge.DSE_ENABLEMENT) {
-        // CcmBridge does not report accurate C* versions for DSE, only 
approximated values
+      if (CcmBridge.isDistributionOf(BackendType.CASSANDRA)) {
+        // CcmBridge does not report accurate C* versions for other 
distributions (e.g. DSE), only
+        // approximated values
         
assertThat(node.getCassandraVersion()).isEqualTo(ccmRule.getCassandraVersion());
       }
       assertThat(node.getState()).isSameAs(NodeState.UP);
@@ -106,7 +107,7 @@ public class NodeMetadataIT {
               DseNodeProperties.DSE_WORKLOADS,
               DseNodeProperties.SERVER_ID);
       assertThat(node.getExtras().get(DseNodeProperties.DSE_VERSION))
-          .isEqualTo(ccmRule.getDseVersion().get());
+          .isEqualTo(ccmRule.getDistributionVersion());
       
assertThat(node.getExtras().get(DseNodeProperties.SERVER_ID)).isInstanceOf(String.class);
       
assertThat(node.getExtras().get(DseNodeProperties.DSE_WORKLOADS)).isInstanceOf(Set.class);
     }
diff --git 
a/integration-tests/src/test/java/com/datastax/oss/driver/core/metadata/SchemaChangesIT.java
 
b/integration-tests/src/test/java/com/datastax/oss/driver/core/metadata/SchemaChangesIT.java
index 6f1dcb791..85fcfc02c 100644
--- 
a/integration-tests/src/test/java/com/datastax/oss/driver/core/metadata/SchemaChangesIT.java
+++ 
b/integration-tests/src/test/java/com/datastax/oss/driver/core/metadata/SchemaChangesIT.java
@@ -33,6 +33,7 @@ import 
com.datastax.oss.driver.api.core.metadata.schema.SchemaChangeListener;
 import com.datastax.oss.driver.api.core.type.DataTypes;
 import com.datastax.oss.driver.api.testinfra.ccm.CcmBridge;
 import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule;
+import com.datastax.oss.driver.api.testinfra.requirement.BackendType;
 import com.datastax.oss.driver.api.testinfra.session.SessionRule;
 import com.datastax.oss.driver.api.testinfra.session.SessionUtils;
 import com.google.common.collect.ImmutableList;
@@ -54,8 +55,8 @@ public class SchemaChangesIT {
 
   static {
     CustomCcmRule.Builder builder = CustomCcmRule.builder();
-    if (!CcmBridge.DSE_ENABLEMENT
-        && CcmBridge.VERSION.nextStable().compareTo(Version.V4_0_0) >= 0) {
+    if (!CcmBridge.isDistributionOf(
+        BackendType.DSE, (dist, cass) -> 
cass.nextStable().compareTo(Version.V4_0_0) >= 0)) {
       builder.withCassandraConfiguration("enable_materialized_views", true);
     }
     CCM_RULE = builder.build();
diff --git 
a/integration-tests/src/test/java/com/datastax/oss/driver/core/metadata/SchemaIT.java
 
b/integration-tests/src/test/java/com/datastax/oss/driver/core/metadata/SchemaIT.java
index 805b2d970..df5571974 100644
--- 
a/integration-tests/src/test/java/com/datastax/oss/driver/core/metadata/SchemaIT.java
+++ 
b/integration-tests/src/test/java/com/datastax/oss/driver/core/metadata/SchemaIT.java
@@ -335,11 +335,9 @@ public class SchemaIT {
 
   private void skipIfDse60() {
     // Special case: DSE 6.0 reports C* 4.0 but does not support virtual tables
-    if (ccmRule.getDseVersion().isPresent()) {
-      Version dseVersion = ccmRule.getDseVersion().get();
-      if (dseVersion.compareTo(DSE_MIN_VIRTUAL_TABLES) < 0) {
-        throw new AssumptionViolatedException("DSE 6.0 does not support 
virtual tables");
-      }
+    if (!ccmRule.isDistributionOf(
+        BackendType.DSE, (dist, cass) -> 
dist.compareTo(DSE_MIN_VIRTUAL_TABLES) >= 0)) {
+      throw new AssumptionViolatedException("DSE 6.0 does not support virtual 
tables");
     }
   }
 }
diff --git 
a/integration-tests/src/test/java/com/datastax/oss/driver/mapper/DeleteReactiveIT.java
 
b/integration-tests/src/test/java/com/datastax/oss/driver/mapper/DeleteReactiveIT.java
index 3a418c736..2eb898021 100644
--- 
a/integration-tests/src/test/java/com/datastax/oss/driver/mapper/DeleteReactiveIT.java
+++ 
b/integration-tests/src/test/java/com/datastax/oss/driver/mapper/DeleteReactiveIT.java
@@ -37,6 +37,7 @@ import com.datastax.oss.driver.api.mapper.annotations.Select;
 import com.datastax.oss.driver.api.mapper.entity.saving.NullSavingStrategy;
 import com.datastax.oss.driver.api.testinfra.ccm.CcmBridge;
 import com.datastax.oss.driver.api.testinfra.ccm.CustomCcmRule;
+import com.datastax.oss.driver.api.testinfra.requirement.BackendType;
 import com.datastax.oss.driver.api.testinfra.session.SessionRule;
 import io.reactivex.Flowable;
 import java.util.UUID;
@@ -57,8 +58,8 @@ public class DeleteReactiveIT extends InventoryITBase {
   @ClassRule public static TestRule chain = 
RuleChain.outerRule(ccmRule).around(sessionRule);
 
   private static CustomCcmRule.Builder configureCcm(CustomCcmRule.Builder 
builder) {
-    if (!CcmBridge.DSE_ENABLEMENT
-        && CcmBridge.VERSION.nextStable().compareTo(Version.V4_0_0) >= 0) {
+    if (!CcmBridge.isDistributionOf(
+        BackendType.DSE, (dist, cass) -> 
cass.nextStable().compareTo(Version.V4_0_0) >= 0)) {
       builder.withCassandraConfiguration("enable_sasi_indexes", true);
     }
     return builder;
diff --git 
a/integration-tests/src/test/java/com/datastax/oss/driver/mapper/InventoryITBase.java
 
b/integration-tests/src/test/java/com/datastax/oss/driver/mapper/InventoryITBase.java
index 9495003ae..1bd899e45 100644
--- 
a/integration-tests/src/test/java/com/datastax/oss/driver/mapper/InventoryITBase.java
+++ 
b/integration-tests/src/test/java/com/datastax/oss/driver/mapper/InventoryITBase.java
@@ -23,10 +23,10 @@ import 
com.datastax.oss.driver.api.mapper.annotations.ClusteringColumn;
 import com.datastax.oss.driver.api.mapper.annotations.Entity;
 import com.datastax.oss.driver.api.mapper.annotations.PartitionKey;
 import com.datastax.oss.driver.api.testinfra.ccm.BaseCcmRule;
+import com.datastax.oss.driver.api.testinfra.requirement.BackendType;
 import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableList;
 import java.util.List;
 import java.util.Objects;
-import java.util.Optional;
 import java.util.UUID;
 
 /** Factors common code for mapper tests that rely on a simple inventory 
model. */
@@ -93,13 +93,14 @@ public abstract class InventoryITBase {
     return builder.build();
   }
 
-  private static final Version MINIMUM_SASI_VERSION = Version.parse("3.4.0");
-  private static final Version BROKEN_SASI_VERSION = Version.parse("6.8.0");
+  private static final Version MINIMUM_SASI_VERSION =
+      Objects.requireNonNull(Version.parse("3.4.0"));
+  private static final Version BROKEN_SASI_VERSION = 
Objects.requireNonNull(Version.parse("6.8.0"));
 
   protected static boolean isSasiBroken(BaseCcmRule ccmRule) {
-    Optional<Version> dseVersion = ccmRule.getDseVersion();
     // creating SASI indexes is broken in DSE 6.8.0
-    return dseVersion.isPresent() && 
dseVersion.get().compareTo(BROKEN_SASI_VERSION) == 0;
+    return ccmRule.isDistributionOf(
+        BackendType.DSE, (dist, cass) -> dist.compareTo(BROKEN_SASI_VERSION) 
== 0);
   }
 
   protected static boolean supportsSASI(BaseCcmRule ccmRule) {
diff --git a/integration-tests/src/test/resources/DescribeIT/hcd/1.0.cql 
b/integration-tests/src/test/resources/DescribeIT/hcd/1.0.cql
new file mode 100644
index 000000000..abc707282
--- /dev/null
+++ b/integration-tests/src/test/resources/DescribeIT/hcd/1.0.cql
@@ -0,0 +1,186 @@
+
+CREATE KEYSPACE ks_0 WITH replication = { 'class' : 
'org.apache.cassandra.locator.SimpleStrategy', 'replication_factor': '1' } AND 
durable_writes = true;
+
+CREATE TYPE ks_0.btype (
+    a text
+);
+
+CREATE TYPE ks_0.xtype (
+    d text
+);
+
+CREATE TYPE ks_0.ztype (
+    c text,
+    a int
+);
+
+CREATE TYPE ks_0.ctype (
+    z frozen<ks_0.ztype>,
+    x frozen<ks_0.xtype>
+);
+
+CREATE TYPE ks_0.atype (
+    c frozen<ks_0.ctype>
+);
+
+CREATE TABLE ks_0.cyclist_mv (
+    cid uuid,
+    age int,
+    birthday date,
+    country text,
+    name text,
+    PRIMARY KEY (cid)
+) WITH additional_write_policy = '99p'
+    AND bloom_filter_fp_chance = 0.01
+    AND caching = {'keys':'ALL','rows_per_partition':'NONE'}
+    AND comment = ''
+    AND compaction = 
{'class':'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy','max_threshold':'32','min_threshold':'4'}
+    AND compression = 
{'chunk_length_in_kb':'64','class':'org.apache.cassandra.io.compress.LZ4Compressor'}
+    AND crc_check_chance = 1.0
+    AND default_time_to_live = 0
+    AND extensions = {}
+    AND gc_grace_seconds = 864000
+    AND max_index_interval = 2048
+    AND memtable_flush_period_in_ms = 0
+    AND min_index_interval = 128
+    AND read_repair = 'BLOCKING'
+    AND speculative_retry = '99p';
+
+CREATE INDEX cyclist_by_country ON ks_0.cyclist_mv (country);
+
+CREATE TABLE ks_0.rank_by_year_and_name (
+    race_year int,
+    race_name text,
+    rank int,
+    cyclist_name text,
+    PRIMARY KEY ((race_year, race_name), rank)
+) WITH CLUSTERING ORDER BY (rank DESC)
+    AND additional_write_policy = '99p'
+    AND bloom_filter_fp_chance = 0.01
+    AND caching = {'keys':'ALL','rows_per_partition':'NONE'}
+    AND comment = ''
+    AND compaction = 
{'class':'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy','max_threshold':'32','min_threshold':'4'}
+    AND compression = 
{'chunk_length_in_kb':'64','class':'org.apache.cassandra.io.compress.LZ4Compressor'}
+    AND crc_check_chance = 1.0
+    AND default_time_to_live = 0
+    AND extensions = {}
+    AND gc_grace_seconds = 864000
+    AND max_index_interval = 2048
+    AND memtable_flush_period_in_ms = 0
+    AND min_index_interval = 128
+    AND read_repair = 'BLOCKING'
+    AND speculative_retry = '99p';
+
+CREATE INDEX rrank ON ks_0.rank_by_year_and_name (rank);
+
+CREATE INDEX ryear ON ks_0.rank_by_year_and_name (race_year);
+
+CREATE TABLE ks_0.ztable (
+    zkey text,
+    a frozen<ks_0.atype>,
+    PRIMARY KEY (zkey)
+) WITH additional_write_policy = '99p'
+    AND bloom_filter_fp_chance = 0.1
+    AND caching = {'keys':'ALL','rows_per_partition':'NONE'}
+    AND comment = ''
+    AND compaction = 
{'class':'org.apache.cassandra.db.compaction.LeveledCompactionStrategy','max_threshold':'32','min_threshold':'4','sstable_size_in_mb':'95'}
+    AND compression = 
{'chunk_length_in_kb':'64','class':'org.apache.cassandra.io.compress.LZ4Compressor'}
+    AND crc_check_chance = 1.0
+    AND default_time_to_live = 0
+    AND extensions = {}
+    AND gc_grace_seconds = 864000
+    AND max_index_interval = 2048
+    AND memtable_flush_period_in_ms = 0
+    AND min_index_interval = 128
+    AND read_repair = 'BLOCKING'
+    AND speculative_retry = '99p';
+
+CREATE MATERIALIZED VIEW ks_0.cyclist_by_a_age AS
+SELECT * FROM ks_0.cyclist_mv
+WHERE age IS NOT NULL AND cid IS NOT NULL
+PRIMARY KEY (age, cid) WITH additional_write_policy = '99p'
+    AND bloom_filter_fp_chance = 0.01
+    AND caching = {'keys':'ALL','rows_per_partition':'NONE'}
+    AND comment = ''
+    AND compaction = 
{'class':'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy','max_threshold':'32','min_threshold':'4'}
+    AND compression = 
{'chunk_length_in_kb':'64','class':'org.apache.cassandra.io.compress.LZ4Compressor'}
+    AND crc_check_chance = 1.0
+    AND extensions = {}
+    AND gc_grace_seconds = 864000
+    AND max_index_interval = 2048
+    AND memtable_flush_period_in_ms = 0
+    AND min_index_interval = 128
+    AND read_repair = 'BLOCKING'
+    AND speculative_retry = '99p';
+
+CREATE MATERIALIZED VIEW ks_0.cyclist_by_age AS
+SELECT
+    age,
+    cid,
+    birthday,
+    country,
+    name
+FROM ks_0.cyclist_mv
+WHERE age IS NOT NULL AND cid IS NOT NULL
+PRIMARY KEY (age, cid) WITH additional_write_policy = '99p'
+    AND bloom_filter_fp_chance = 0.01
+    AND caching = {'keys':'ALL','rows_per_partition':'NONE'}
+    AND comment = 'simple view'
+    AND compaction = 
{'class':'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy','max_threshold':'32','min_threshold':'4'}
+    AND compression = 
{'chunk_length_in_kb':'64','class':'org.apache.cassandra.io.compress.LZ4Compressor'}
+    AND crc_check_chance = 1.0
+    AND extensions = {}
+    AND gc_grace_seconds = 864000
+    AND max_index_interval = 2048
+    AND memtable_flush_period_in_ms = 0
+    AND min_index_interval = 128
+    AND read_repair = 'BLOCKING'
+    AND speculative_retry = '99p';
+
+CREATE MATERIALIZED VIEW ks_0.cyclist_by_r_age AS
+SELECT
+    age,
+    cid,
+    birthday,
+    country,
+    name
+FROM ks_0.cyclist_mv
+WHERE age IS NOT NULL AND cid IS NOT NULL
+PRIMARY KEY (age, cid) WITH additional_write_policy = '99p'
+    AND bloom_filter_fp_chance = 0.01
+    AND caching = {'keys':'ALL','rows_per_partition':'NONE'}
+    AND comment = ''
+    AND compaction = 
{'class':'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy','max_threshold':'32','min_threshold':'4'}
+    AND compression = 
{'chunk_length_in_kb':'64','class':'org.apache.cassandra.io.compress.LZ4Compressor'}
+    AND crc_check_chance = 1.0
+    AND extensions = {}
+    AND gc_grace_seconds = 864000
+    AND max_index_interval = 2048
+    AND memtable_flush_period_in_ms = 0
+    AND min_index_interval = 128
+    AND read_repair = 'BLOCKING'
+    AND speculative_retry = '99p';
+
+CREATE FUNCTION ks_0.avgfinal(state tuple<int, bigint>)
+    CALLED ON NULL INPUT
+    RETURNS double
+    LANGUAGE java
+    AS 'double r = 0; if (state.getInt(0) == 0) return null; r = 
state.getLong(1); r /= state.getInt(0); return Double.valueOf(r);';
+
+CREATE FUNCTION ks_0.avgstate(state tuple<int, bigint>,val int)
+    CALLED ON NULL INPUT
+    RETURNS tuple<int, bigint>
+    LANGUAGE java
+    AS 'if (val !=null) { state.setInt(0, state.getInt(0)+1); state.setLong(1, 
state.getLong(1)+val.intValue()); } return state;';
+
+CREATE AGGREGATE ks_0.average(int)
+    SFUNC avgstate
+    STYPE tuple<int, bigint>
+    FINALFUNC avgfinal
+    INITCOND (0,0);
+
+CREATE AGGREGATE ks_0.mean(int)
+    SFUNC avgstate
+    STYPE tuple<int, bigint>
+    FINALFUNC avgfinal
+    INITCOND (0,0);
diff --git a/osgi-tests/README.md b/osgi-tests/README.md
index 89ad0ba27..1ca6211d4 100644
--- a/osgi-tests/README.md
+++ b/osgi-tests/README.md
@@ -53,8 +53,8 @@ OSGi ones, you can do so as follows:
 You can pass the following system properties to your tests:
 
 1. `ccm.version`: the CCM version to use
-2. `ccm.dse`: whether to use DSE
-3. `osgi.debug`: whether to enable remote debugging of the OSGi container (see 
+2. `ccm.distribution`: choose target backend type (e.g. DSE, HCD)
+3. `osgi.debug`: whether to enable remote debugging of the OSGi container (see
    below).
    
 ## Debugging OSGi tests
diff --git 
a/osgi-tests/src/test/java/com/datastax/oss/driver/internal/osgi/support/CcmStagedReactor.java
 
b/osgi-tests/src/test/java/com/datastax/oss/driver/internal/osgi/support/CcmStagedReactor.java
index 8b1409308..ce4d90953 100644
--- 
a/osgi-tests/src/test/java/com/datastax/oss/driver/internal/osgi/support/CcmStagedReactor.java
+++ 
b/osgi-tests/src/test/java/com/datastax/oss/driver/internal/osgi/support/CcmStagedReactor.java
@@ -19,6 +19,7 @@ package com.datastax.oss.driver.internal.osgi.support;
 
 import com.datastax.oss.driver.api.core.Version;
 import com.datastax.oss.driver.api.testinfra.ccm.CcmBridge;
+import com.datastax.oss.driver.api.testinfra.requirement.BackendType;
 import java.util.List;
 import java.util.Objects;
 import net.jcip.annotations.GuardedBy;
@@ -38,7 +39,7 @@ public class CcmStagedReactor extends 
AllConfinedStagedReactor {
 
   static {
     CcmBridge.Builder builder = CcmBridge.builder().withNodes(1);
-    if (CcmBridge.DSE_ENABLEMENT && CcmBridge.VERSION.compareTo(DSE_5_0) >= 0) 
{
+    if (CcmBridge.isDistributionOf(BackendType.DSE, (dist, cass) -> 
dist.compareTo(DSE_5_0) >= 0)) {
       builder.withDseWorkloads("graph");
     }
     CCM_BRIDGE = builder.build();
@@ -54,11 +55,10 @@ public class CcmStagedReactor extends 
AllConfinedStagedReactor {
   @Override
   public synchronized void beforeSuite() {
     if (!running) {
-      boolean dse = CCM_BRIDGE.getDseVersion().isPresent();
       LOGGER.info(
           "Starting CCM, running {} version {}",
-          dse ? "DSE" : "Cassandra",
-          dse ? CCM_BRIDGE.getDseVersion().get() : 
CCM_BRIDGE.getCassandraVersion());
+          CcmBridge.DISTRIBUTION,
+          CcmBridge.getDistributionVersion());
       CCM_BRIDGE.create();
       CCM_BRIDGE.start();
       LOGGER.info("CCM started");
diff --git a/test-infra/revapi.json b/test-infra/revapi.json
index 3cfbc8b53..c75a98cb4 100644
--- a/test-infra/revapi.json
+++ b/test-infra/revapi.json
@@ -171,6 +171,27 @@
         "code": "java.method.removed",
         "old": "method void 
com.datastax.oss.driver.api.testinfra.ccm.CcmRule::reloadCore(int, 
java.lang.String, java.lang.String, boolean)",
         "justification": "Modifying the state of a globally shared CCM 
instance is dangerous"
+      },
+      {
+        "code": "java.method.removed",
+        "old": "method 
java.util.Optional<com.datastax.oss.driver.api.core.Version> 
com.datastax.oss.driver.api.testinfra.ccm.BaseCcmRule::getDseVersion()",
+        "justification": "Method has been replaced with more generic 
isDistributionOf(BackendType) and getDistributionVersion()"
+      },
+      {
+        "code": "java.field.removed",
+        "old": "field 
com.datastax.oss.driver.api.testinfra.ccm.CcmBridge.DSE_ENABLEMENT",
+        "justification": "Method has been replaced with more generic 
isDistributionOf(BackendType) and getDistributionVersion()"
+      },
+      {
+        "code": "java.method.nowStatic",
+        "old": "method com.datastax.oss.driver.api.core.Version 
com.datastax.oss.driver.api.testinfra.ccm.CcmBridge::getCassandraVersion()",
+        "new": "method com.datastax.oss.driver.api.core.Version 
com.datastax.oss.driver.api.testinfra.ccm.CcmBridge::getCassandraVersion()",
+        "justification": "Previous and current implemntation do not relay on 
non-static fields"
+      },
+      {
+        "code": "java.method.removed",
+        "old": "method 
java.util.Optional<com.datastax.oss.driver.api.core.Version> 
com.datastax.oss.driver.api.testinfra.ccm.CcmBridge::getDseVersion()",
+        "justification": "Method has been replaced with more generic 
isDistributionOf(BackendType) and getDistributionVersion()"
       }
     ]
   }
diff --git 
a/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/ccm/BaseCcmRule.java
 
b/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/ccm/BaseCcmRule.java
index 65210acd2..882cd55b9 100644
--- 
a/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/ccm/BaseCcmRule.java
+++ 
b/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/ccm/BaseCcmRule.java
@@ -22,7 +22,7 @@ import com.datastax.oss.driver.api.core.ProtocolVersion;
 import com.datastax.oss.driver.api.core.Version;
 import com.datastax.oss.driver.api.testinfra.CassandraResourceRule;
 import 
com.datastax.oss.driver.api.testinfra.requirement.BackendRequirementRule;
-import java.util.Optional;
+import com.datastax.oss.driver.api.testinfra.requirement.BackendType;
 import org.junit.AssumptionViolatedException;
 import org.junit.runner.Description;
 import org.junit.runners.model.Statement;
@@ -72,17 +72,29 @@ public abstract class BaseCcmRule extends 
CassandraResourceRule {
     }
   }
 
-  public Version getCassandraVersion() {
-    return ccmBridge.getCassandraVersion();
+  public BackendType getDistribution() {
+    return CcmBridge.DISTRIBUTION;
+  }
+
+  public boolean isDistributionOf(BackendType type) {
+    return CcmBridge.isDistributionOf(type);
+  }
+
+  public boolean isDistributionOf(BackendType type, 
CcmBridge.VersionComparator comparator) {
+    return CcmBridge.isDistributionOf(type, comparator);
+  }
+
+  public Version getDistributionVersion() {
+    return CcmBridge.getDistributionVersion();
   }
 
-  public Optional<Version> getDseVersion() {
-    return ccmBridge.getDseVersion();
+  public Version getCassandraVersion() {
+    return CcmBridge.getCassandraVersion();
   }
 
   @Override
   public ProtocolVersion getHighestProtocolVersion() {
-    if (ccmBridge.getCassandraVersion().compareTo(Version.V2_2_0) >= 0) {
+    if (CcmBridge.getCassandraVersion().compareTo(Version.V2_2_0) >= 0) {
       return DefaultProtocolVersion.V4;
     } else {
       return DefaultProtocolVersion.V3;
diff --git 
a/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/ccm/CcmBridge.java
 
b/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/ccm/CcmBridge.java
index 5b0c114a5..f0ce6bc5b 100644
--- 
a/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/ccm/CcmBridge.java
+++ 
b/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/ccm/CcmBridge.java
@@ -18,6 +18,7 @@
 package com.datastax.oss.driver.api.testinfra.ccm;
 
 import com.datastax.oss.driver.api.core.Version;
+import com.datastax.oss.driver.api.testinfra.requirement.BackendType;
 import com.datastax.oss.driver.shaded.guava.common.base.Joiner;
 import com.datastax.oss.driver.shaded.guava.common.io.Resources;
 import java.io.File;
@@ -54,6 +55,9 @@ public class CcmBridge implements AutoCloseable {
 
   private static final Logger LOG = LoggerFactory.getLogger(CcmBridge.class);
 
+  public static BackendType DISTRIBUTION =
+      BackendType.valueOf(
+          System.getProperty("ccm.distribution", 
BackendType.CASSANDRA.name()).toUpperCase());
   public static final Version VERSION =
       Objects.requireNonNull(Version.parse(System.getProperty("ccm.version", 
"4.0.0")));
 
@@ -61,8 +65,6 @@ public class CcmBridge implements AutoCloseable {
 
   public static final String BRANCH = System.getProperty("ccm.branch");
 
-  public static final Boolean DSE_ENABLEMENT = Boolean.getBoolean("ccm.dse");
-
   public static final String CLUSTER_NAME = "ccm_1";
 
   public static final String DEFAULT_CLIENT_TRUSTSTORE_PASSWORD = 
"fakePasswordForTests";
@@ -101,22 +103,21 @@ public class CcmBridge implements AutoCloseable {
       createTempStore(DEFAULT_SERVER_LOCALHOST_KEYSTORE_PATH);
 
   // major DSE versions
-  private static final Version V6_0_0 = Version.parse("6.0.0");
-  private static final Version V5_1_0 = Version.parse("5.1.0");
-  private static final Version V5_0_0 = Version.parse("5.0.0");
+  public static final Version V6_0_0 = Version.parse("6.0.0");
+  public static final Version V5_1_0 = Version.parse("5.1.0");
+  public static final Version V5_0_0 = Version.parse("5.0.0");
 
   // mapped C* versions from DSE versions
-  private static final Version V4_0_0 = Version.parse("4.0.0");
-  private static final Version V3_10 = Version.parse("3.10");
-  private static final Version V3_0_15 = Version.parse("3.0.15");
-  private static final Version V2_1_19 = Version.parse("2.1.19");
+  public static final Version V4_0_0 = Version.parse("4.0.0");
+  public static final Version V3_10 = Version.parse("3.10");
+  public static final Version V3_0_15 = Version.parse("3.0.15");
+  public static final Version V2_1_19 = Version.parse("2.1.19");
+
+  // mapped C* versions from HCD versions
+  public static final Version V4_0_11 = Version.parse("4.0.11");
 
   static {
-    if (DSE_ENABLEMENT) {
-      LOG.info("CCM Bridge configured with DSE version {}", VERSION);
-    } else {
-      LOG.info("CCM Bridge configured with Apache Cassandra version {}", 
VERSION);
-    }
+    LOG.info("CCM Bridge configured with {} version {}", 
DISTRIBUTION.getFriendlyName(), VERSION);
   }
 
   private final int[] nodes;
@@ -175,25 +176,24 @@ public class CcmBridge implements AutoCloseable {
     return System.getProperty("os.name", 
"").toLowerCase(Locale.US).contains("win");
   }
 
-  public Optional<Version> getDseVersion() {
-    return DSE_ENABLEMENT ? Optional.of(VERSION) : Optional.empty();
+  public static boolean isDistributionOf(BackendType type) {
+    return DISTRIBUTION == type;
+  }
+
+  public static boolean isDistributionOf(BackendType type, VersionComparator 
comparator) {
+    return isDistributionOf(type)
+        && comparator.accept(getDistributionVersion(), getCassandraVersion());
+  }
+
+  public static Version getDistributionVersion() {
+    return VERSION;
   }
 
-  public Version getCassandraVersion() {
-    if (!DSE_ENABLEMENT) {
+  public static Version getCassandraVersion() {
+    if (isDistributionOf(BackendType.CASSANDRA)) {
       return VERSION;
-    } else {
-      Version stableVersion = VERSION.nextStable();
-      if (stableVersion.compareTo(V6_0_0) >= 0) {
-        return V4_0_0;
-      } else if (stableVersion.compareTo(V5_1_0) >= 0) {
-        return V3_10;
-      } else if (stableVersion.compareTo(V5_0_0) >= 0) {
-        return V3_0_15;
-      } else {
-        return V2_1_19;
-      }
     }
+    return DistributionCassandraVersions.getCassandraVersion(DISTRIBUTION, 
VERSION);
   }
 
   private String getCcmVersionString(Version version) {
@@ -225,9 +225,7 @@ public class CcmBridge implements AutoCloseable {
       } else {
         createOptions.add("-v " + getCcmVersionString(VERSION));
       }
-      if (DSE_ENABLEMENT) {
-        createOptions.add("--dse");
-      }
+      createOptions.addAll(Arrays.asList(DISTRIBUTION.getCcmOptions()));
       execute(
           "create",
           CLUSTER_NAME,
@@ -252,7 +250,7 @@ public class CcmBridge implements AutoCloseable {
       // If we're dealing with anything more recent than 2.2 explicitly enable 
UDF... but run it
       // through our conversion process to make
       // sure more recent versions don't have a problem.
-      if (cassandraVersion.compareTo(Version.V2_2_0) >= 0) {
+      if (cassandraVersion.compareTo(Version.V2_2_0) >= 0 || 
isDistributionOf(BackendType.HCD)) {
         String originalKey = "enable_user_defined_functions";
         Object originalValue = "true";
         execute(
@@ -264,7 +262,7 @@ public class CcmBridge implements AutoCloseable {
       }
 
       // Note that we aren't performing any substitution on DSE key/value 
props (at least for now)
-      if (DSE_ENABLEMENT) {
+      if (isDistributionOf(BackendType.DSE)) {
         for (Map.Entry<String, Object> conf : dseConfiguration.entrySet()) {
           execute("updatedseconf", String.format("%s:%s", conf.getKey(), 
conf.getValue()));
         }
@@ -338,11 +336,10 @@ public class CcmBridge implements AutoCloseable {
   }
 
   public void add(int n, String dc) {
-    if (getDseVersion().isPresent()) {
-      execute("add", "-i", ipPrefix + n, "-d", dc, "node" + n, "--dse");
-    } else {
-      execute("add", "-i", ipPrefix + n, "-d", dc, "node" + n);
-    }
+    List<String> addOptions = new ArrayList<>();
+    addOptions.addAll(Arrays.asList("add", "-i", ipPrefix + n, "-d", dc, 
"node" + n));
+    addOptions.addAll(Arrays.asList(DISTRIBUTION.getCcmOptions()));
+    execute(addOptions.toArray(new String[0]));
     start(n);
   }
 
@@ -475,11 +472,11 @@ public class CcmBridge implements AutoCloseable {
       return Optional.empty();
     }
 
-    if (!DSE_ENABLEMENT || !getDseVersion().isPresent()) {
+    if (!isDistributionOf(BackendType.DSE)) {
       return Optional.empty();
     }
 
-    if (getDseVersion().get().compareTo(Version.V6_9_0) >= 0) {
+    if (getDistributionVersion().compareTo(Version.V6_9_0) >= 0) {
       // DSE 6.9.0 supports only JVM 11 onwards (also with graph workload)
       return Optional.empty();
     }
@@ -641,4 +638,8 @@ public class CcmBridge implements AutoCloseable {
           dseWorkloads);
     }
   }
+
+  public interface VersionComparator {
+    boolean accept(Version distribution, Version cassandra);
+  }
 }
diff --git 
a/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/ccm/DefaultCcmBridgeBuilderCustomizer.java
 
b/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/ccm/DefaultCcmBridgeBuilderCustomizer.java
index ac2507cec..0819f7854 100644
--- 
a/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/ccm/DefaultCcmBridgeBuilderCustomizer.java
+++ 
b/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/ccm/DefaultCcmBridgeBuilderCustomizer.java
@@ -18,18 +18,20 @@
 package com.datastax.oss.driver.api.testinfra.ccm;
 
 import com.datastax.oss.driver.api.core.Version;
+import com.datastax.oss.driver.api.testinfra.requirement.BackendType;
 
 /** @see CcmRule */
 @SuppressWarnings("unused")
 public class DefaultCcmBridgeBuilderCustomizer {
 
   public static CcmBridge.Builder configureBuilder(CcmBridge.Builder builder) {
-    if (!CcmBridge.DSE_ENABLEMENT
-        && CcmBridge.VERSION.nextStable().compareTo(Version.V4_0_0) >= 0) {
+    if (!CcmBridge.isDistributionOf(
+            BackendType.DSE, (dist, cass) -> 
dist.nextStable().compareTo(Version.V4_0_0) >= 0)
+        || CcmBridge.isDistributionOf(BackendType.HCD)) {
       builder.withCassandraConfiguration("enable_materialized_views", true);
       builder.withCassandraConfiguration("enable_sasi_indexes", true);
     }
-    if (CcmBridge.VERSION.nextStable().compareTo(Version.V3_0_0) >= 0) {
+    if 
(CcmBridge.getDistributionVersion().nextStable().compareTo(Version.V3_0_0) >= 
0) {
       builder.withJvmArgs("-Dcassandra.superuser_setup_delay_ms=0");
       builder.withJvmArgs("-Dcassandra.skip_wait_for_gossip_to_settle=0");
       builder.withCassandraConfiguration("num_tokens", "1");
diff --git 
a/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/ccm/DistributionCassandraVersions.java
 
b/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/ccm/DistributionCassandraVersions.java
new file mode 100644
index 000000000..9f7634d1b
--- /dev/null
+++ 
b/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/ccm/DistributionCassandraVersions.java
@@ -0,0 +1,57 @@
+/*
+ * 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 com.datastax.oss.driver.api.testinfra.ccm;
+
+import com.datastax.oss.driver.api.core.Version;
+import com.datastax.oss.driver.api.testinfra.requirement.BackendType;
+import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableSortedMap;
+import java.util.HashMap;
+import java.util.Map;
+
+/** Defines mapping of various distributions to shipped Apache Cassandra 
version. */
+public abstract class DistributionCassandraVersions {
+  private static final Map<BackendType, ImmutableSortedMap<Version, Version>> 
mappings =
+      new HashMap<>();
+
+  static {
+    {
+      // DSE
+      ImmutableSortedMap<Version, Version> dse =
+          ImmutableSortedMap.of(
+              Version.V1_0_0, CcmBridge.V2_1_19,
+              Version.V5_0_0, CcmBridge.V3_0_15,
+              CcmBridge.V5_1_0, CcmBridge.V3_10,
+              CcmBridge.V6_0_0, CcmBridge.V4_0_0);
+      mappings.put(BackendType.DSE, dse);
+    }
+    {
+      // HCD
+      ImmutableSortedMap<Version, Version> hcd =
+          ImmutableSortedMap.of(Version.V1_0_0, CcmBridge.V4_0_11);
+      mappings.put(BackendType.HCD, hcd);
+    }
+  }
+
+  public static Version getCassandraVersion(BackendType type, Version version) 
{
+    ImmutableSortedMap<Version, Version> mapping = mappings.get(type);
+    if (mapping == null) {
+      return null;
+    }
+    return mapping.floorEntry(version).getValue();
+  }
+}
diff --git 
a/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/requirement/BackendRequirementRule.java
 
b/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/requirement/BackendRequirementRule.java
index 6c59e2166..343861571 100644
--- 
a/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/requirement/BackendRequirementRule.java
+++ 
b/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/requirement/BackendRequirementRule.java
@@ -41,7 +41,7 @@ public class BackendRequirementRule extends ExternalResource {
   }
 
   protected static BackendType getBackendType() {
-    return CcmBridge.DSE_ENABLEMENT ? BackendType.DSE : BackendType.CASSANDRA;
+    return CcmBridge.DISTRIBUTION;
   }
 
   protected static Version getVersion() {
diff --git 
a/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/requirement/BackendType.java
 
b/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/requirement/BackendType.java
index 1683dd861..e0058ca32 100644
--- 
a/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/requirement/BackendType.java
+++ 
b/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/requirement/BackendType.java
@@ -18,9 +18,9 @@
 package com.datastax.oss.driver.api.testinfra.requirement;
 
 public enum BackendType {
-  CASSANDRA("C*"),
-  DSE("Dse"),
-  ;
+  CASSANDRA("Apache Cassandra"),
+  DSE("DSE"),
+  HCD("HCD");
 
   final String friendlyName;
 
@@ -31,4 +31,11 @@ public enum BackendType {
   public String getFriendlyName() {
     return friendlyName;
   }
+
+  public String[] getCcmOptions() {
+    if (this == CASSANDRA) {
+      return new String[0];
+    }
+    return new String[] {"--" + name().toLowerCase()};
+  }
 }
diff --git 
a/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/session/SessionRule.java
 
b/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/session/SessionRule.java
index 5396e5c6c..3b7923747 100644
--- 
a/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/session/SessionRule.java
+++ 
b/test-infra/src/main/java/com/datastax/oss/driver/api/testinfra/session/SessionRule.java
@@ -29,10 +29,11 @@ import 
com.datastax.oss.driver.api.core.metadata.schema.SchemaChangeListener;
 import com.datastax.oss.driver.api.core.session.Session;
 import com.datastax.oss.driver.api.testinfra.CassandraResourceRule;
 import com.datastax.oss.driver.api.testinfra.ccm.BaseCcmRule;
+import com.datastax.oss.driver.api.testinfra.ccm.CcmBridge;
 import com.datastax.oss.driver.api.testinfra.ccm.SchemaChangeSynchronizer;
+import com.datastax.oss.driver.api.testinfra.requirement.BackendType;
 import com.datastax.oss.driver.api.testinfra.simulacron.SimulacronRule;
 import java.util.Objects;
-import java.util.Optional;
 import org.junit.rules.ExternalResource;
 
 /**
@@ -154,14 +155,12 @@ public class SessionRule<SessionT extends Session> 
extends ExternalResource {
           Statement.SYNC);
     }
     if (graphName != null) {
-      Optional<Version> dseVersion =
-          (cassandraResource instanceof BaseCcmRule)
-              ? ((BaseCcmRule) cassandraResource).getDseVersion()
-              : Optional.empty();
-      if (!dseVersion.isPresent()) {
+      BaseCcmRule rule =
+          (cassandraResource instanceof BaseCcmRule) ? ((BaseCcmRule) 
cassandraResource) : null;
+      if (rule == null || !CcmBridge.isDistributionOf(BackendType.DSE)) {
         throw new IllegalArgumentException("DseSessionRule should work with 
DSE.");
       }
-      if (dseVersion.get().compareTo(V6_8_0) >= 0) {
+      if (rule.getDistributionVersion().compareTo(V6_8_0) >= 0) {
         session()
             .execute(
                 ScriptGraphStatement.newInstance(


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org
For additional commands, e-mail: commits-h...@cassandra.apache.org

Reply via email to