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); + } }