diff --git a/.gitignore b/.gitignore
index 0060e3e0f..1f0e09213 100644
--- a/.gitignore
+++ b/.gitignore
@@ -62,6 +62,7 @@ docs
.#*
#*
.clang_complete
+.idea
# OSX
.DS_Store
diff --git a/Jenkinsfile b/Jenkinsfile
index f34417270..0417d56b4 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -329,8 +329,10 @@ pipeline {
name: 'ADHOC_BUILD_AND_EXECUTE_TESTS_SERVER_VERSION',
choices: [
'3.0', // Previous Apache Cassandra
- '3.11', // Current Apache Cassandra
- '4.0', // Development Apache Cassandra
+ '3.11', // Previous Apache Cassandra
+ '4.0', // Previous Apache Cassandra
+ '4.1', // Previous Apache Cassandra
+ '5.0', // Current Apache Cassandra
'dse-5.1.35', // Legacy DataStax Enterprise
'dse-6.8.30', // Development DataStax Enterprise
'ALL'],
@@ -352,7 +354,15 @@ pipeline {
| 4.0 |
- Apache Cassandra® v4.x (CURRENTLY UNDER DEVELOPMENT) |
+ Apache Cassandra® v4.0.x |
+
+
+ | 4.1 |
+ Apache Cassandra® v4.1.x |
+
+
+ | 5.0 |
+ Apache Cassandra® v5.0.x |
| dse-5.1 |
@@ -360,7 +370,7 @@ pipeline {
| dse-6.8 |
- DataStax Enterprise v6.8.x (CURRENTLY UNDER DEVELOPMENT) |
+ DataStax Enterprise v6.8.x |
''')
choice(
@@ -548,8 +558,10 @@ pipeline {
axis {
name 'SERVER_VERSION'
values '3.0', // Previous Apache Cassandra
- '3.11', // Current Apache Cassandra
- '4.0', // Development Apache Cassandra
+ '3.11', // Previous Apache Cassandra
+ '4.0', // Previous Apache Cassandra
+ '4.1', // Previous Apache Cassandra
+ '5.0', // Current Apache Cassandra
'dse-5.1.35', // Legacy DataStax Enterprise
'dse-6.8.30' // Development DataStax Enterprise
}
diff --git a/tests/src/integration/ccm/bridge.cpp b/tests/src/integration/ccm/bridge.cpp
index 35a06e53d..3a262207c 100644
--- a/tests/src/integration/ccm/bridge.cpp
+++ b/tests/src/integration/ccm/bridge.cpp
@@ -1488,19 +1488,58 @@ CCM::Bridge::generate_create_updateconf_command(CassVersion cassandra_version) {
updateconf_command.push_back("enable_user_defined_functions:true");
}
- // Create Cassandra version specific updated (C* 3.0+)
- if (cassandra_version >= "3.0.0") {
- updateconf_command.push_back("enable_scripted_user_defined_functions:true");
- }
-
if (cassandra_version >= "4.0.0" && !is_dse()) {
updateconf_command.push_back("enable_materialized_views:true");
updateconf_command.push_back("enable_user_defined_functions:true");
}
+ for (size_t i = 0; i < updateconf_command.size(); ++i) {
+ updateconf_command[i] = translate_config_for_version(updateconf_command[i], cassandra_version);
+ }
+
return updateconf_command;
}
+std::string CCM::Bridge::translate_config_for_version(const std::string& key_value,
+ CassVersion cassandra_version) {
+ if (cassandra_version < "4.1.0") {
+ return key_value;
+ }
+
+ std::size_t separator = key_value.find(':');
+ if (separator == std::string::npos) {
+ return key_value;
+ }
+
+ std::string key = key_value.substr(0, separator);
+ std::string value = key_value.substr(separator + 1);
+
+ if (key.find('.') != std::string::npos) {
+ return key_value;
+ }
+
+ static const char* SUFFIXES[][2] = {
+ { "_in_ms", "ms" },
+ { "_in_mb", "MiB" },
+ { "_mb_per_sec", "MiB/s" }
+ };
+
+ for (const auto& i : SUFFIXES) {
+ std::string suffix = i[0];
+ if (key.size() >= suffix.size() &&
+ key.compare(key.size() - suffix.size(), suffix.size(), suffix) == 0) {
+ return key.substr(0, key.size() - suffix.size()) + ":" + value + i[1];
+ }
+ }
+
+ std::string enable_prefix = "enable_";
+ if (key.compare(0, enable_prefix.size(), enable_prefix) == 0) {
+ return key.substr(enable_prefix.size()) + "_enabled:" + value;
+ }
+
+ return key_value;
+}
+
std::string CCM::Bridge::generate_dse_workloads(std::vector workloads) {
std::string dse_workloads;
for (std::vector::iterator iterator = workloads.begin(); iterator != workloads.end();
diff --git a/tests/src/integration/ccm/bridge.hpp b/tests/src/integration/ccm/bridge.hpp
index 6901a19da..9b214bad9 100644
--- a/tests/src/integration/ccm/bridge.hpp
+++ b/tests/src/integration/ccm/bridge.hpp
@@ -947,6 +947,22 @@ class Bridge {
*/
std::vector generate_create_updateconf_command(CassVersion cassandra_version);
+ /**
+ * Translate a cassandra.yaml "key:value" update pair to the format Cassandra 4.1
+ * introduced (ignoring nested keys)
+ *
+ * Transformations include:
+ * - "_in_*"/"_*_per_sec" suffix -> appending "*[/s]" to the value
+ * - "enable_" prefix -> "_enabled" suffix
+ *
+ * @param key_value Original "key:value" pair
+ * @param cassandra_version Cassandra version being used
+ * @return The pair translated if renamed and cassandra_version >= 4.1.0;
+ * otherwise key_value unchanged
+ */
+ std::string translate_config_for_version(const std::string& key_value,
+ CassVersion cassandra_version);
+
/**
* Generate the command separated list for have a single or multiple
* workloads for the CCM setworkload command
diff --git a/tests/src/integration/tests/test_schema_metadata.cpp b/tests/src/integration/tests/test_schema_metadata.cpp
index 68821b6d5..78317022d 100644
--- a/tests/src/integration/tests/test_schema_metadata.cpp
+++ b/tests/src/integration/tests/test_schema_metadata.cpp
@@ -155,8 +155,13 @@ CASSANDRA_INTEGRATION_TEST_F(SchemaMetadataTest, VirtualMetadata) {
ASSERT_TRUE(table_meta);
EXPECT_TRUE(table_meta.is_virtual());
+ // Cassandra 4.1 added a `sstables` column and changed `task_id`'s type;
+ // later 5.0.x patches add more columns to this table, so for future compatibility,
+ // column count is a floor, not an exact match, from 4.1 onward
+ bool is_4_1_or_later = server_version_ >= "4.1.0";
+
// Verify virtual table's metadata
- EXPECT_EQ(cass_table_meta_column_count(table_meta.get()), 8u);
+ EXPECT_GE(cass_table_meta_column_count(table_meta.get()), is_4_1_or_later ? 9u : 8u);
EXPECT_EQ(cass_table_meta_index_count(table_meta.get()), 0u);
EXPECT_EQ(cass_table_meta_materialized_view_count(table_meta.get()), 0u);
@@ -178,7 +183,8 @@ CASSANDRA_INTEGRATION_TEST_F(SchemaMetadataTest, VirtualMetadata) {
column_meta = cass_table_meta_column_by_name(table_meta.get(), "task_id");
ASSERT_TRUE(column_meta);
- EXPECT_EQ(cass_data_type_type(cass_column_meta_data_type(column_meta)), CASS_VALUE_TYPE_UUID);
+ EXPECT_EQ(cass_data_type_type(cass_column_meta_data_type(column_meta)),
+ is_4_1_or_later ? CASS_VALUE_TYPE_TIMEUUID : CASS_VALUE_TYPE_UUID);
column_meta = cass_table_meta_column_by_name(table_meta.get(), "kind");
ASSERT_TRUE(column_meta);
@@ -195,4 +201,10 @@ CASSANDRA_INTEGRATION_TEST_F(SchemaMetadataTest, VirtualMetadata) {
column_meta = cass_table_meta_column_by_name(table_meta.get(), "unit");
ASSERT_TRUE(column_meta);
EXPECT_EQ(cass_data_type_type(cass_column_meta_data_type(column_meta)), CASS_VALUE_TYPE_TEXT);
+
+ if (is_4_1_or_later) {
+ column_meta = cass_table_meta_column_by_name(table_meta.get(), "sstables");
+ ASSERT_TRUE(column_meta);
+ EXPECT_EQ(cass_data_type_type(cass_column_meta_data_type(column_meta)), CASS_VALUE_TYPE_INT);
+ }
}