|
16 | 16 |
|
17 | 17 | #include "cassandra.h"
|
18 | 18 | #include "integration.hpp"
|
| 19 | +#include "objects/error_result.hpp" |
| 20 | +#include "objects/execution_profile.hpp" |
| 21 | +#include "objects/statement.hpp" |
19 | 22 |
|
| 23 | +#include "gtest/gtest.h" |
20 | 24 | #include <algorithm>
|
21 | 25 | #include <iterator>
|
22 | 26 |
|
@@ -56,6 +60,45 @@ class DcAwarePolicyTest : public Integration {
|
56 | 60 | return attempted_hosts;
|
57 | 61 | }
|
58 | 62 |
|
| 63 | + void validate_with_statement(Statement const& statement, bool const expect_no_hosts_available_error, bool const expect_remotes_used) { |
| 64 | + std::vector<std::string> attempted_hosts, temp; |
| 65 | + Result result; |
| 66 | + |
| 67 | + result = session_.execute(statement, !expect_no_hosts_available_error); |
| 68 | + temp = result.attempted_hosts(); |
| 69 | + std::copy(temp.begin(), temp.end(), std::back_inserter(attempted_hosts)); |
| 70 | + |
| 71 | + if (expect_no_hosts_available_error) { |
| 72 | + EXPECT_EQ(result.error_result().error_code(), CASS_ERROR_LIB_NO_HOSTS_AVAILABLE); |
| 73 | + return; // No hosts available, so nothing more to check. |
| 74 | + } else { |
| 75 | + // The query should succeed, so we can check the result. |
| 76 | + EXPECT_EQ(result.first_row().next().as<Varchar>(), Varchar("one")); |
| 77 | + } |
| 78 | + |
| 79 | + if (expect_remotes_used) { |
| 80 | + // Verify that remote DC hosts were used. |
| 81 | + EXPECT_TRUE(contains(ccm_->get_ip_prefix() + "3", attempted_hosts) || |
| 82 | + contains(ccm_->get_ip_prefix() + "4", attempted_hosts)); |
| 83 | + |
| 84 | + // Verify that no local DC hosts where used. |
| 85 | + // |
| 86 | + // Commented out, because I'm not sure if this is guaranteed: |
| 87 | + // the driver may have already noticed that the local DC hosts |
| 88 | + // are down and removed them from the host list. |
| 89 | + // EXPECT_TRUE(!contains(ccm_->get_ip_prefix() + "1", attempted_hosts) && |
| 90 | + // !contains(ccm_->get_ip_prefix() + "2", attempted_hosts)); |
| 91 | + } else { |
| 92 | + // Verify that local DC hosts were used. |
| 93 | + EXPECT_TRUE(contains(ccm_->get_ip_prefix() + "1", attempted_hosts) || |
| 94 | + contains(ccm_->get_ip_prefix() + "2", attempted_hosts)); |
| 95 | + |
| 96 | + // Verify that no remote DC hosts were used. |
| 97 | + EXPECT_TRUE(!contains(ccm_->get_ip_prefix() + "3", attempted_hosts) && |
| 98 | + !contains(ccm_->get_ip_prefix() + "4", attempted_hosts)); |
| 99 | + } |
| 100 | + } |
| 101 | + |
59 | 102 | Statement select_statement(const std::string& key) {
|
60 | 103 | Statement statement(
|
61 | 104 | format_string(CASSANDRA_SELECT_VALUE_FORMAT, table_name_.c_str(), key.c_str()));
|
@@ -119,3 +162,73 @@ CASSANDRA_INTEGRATION_TEST_F(DcAwarePolicyTest, UsedHostsRemoteDc) {
|
119 | 162 | !contains(ccm_->get_ip_prefix() + "2", attempted_hosts));
|
120 | 163 | }
|
121 | 164 | }
|
| 165 | + |
| 166 | +/** |
| 167 | + * Verify that the "allow remote DCs for local CL" setting allows requests that are using |
| 168 | + * a local consistency level to be routed to remote DC nodes when the local DC nodes |
| 169 | + * are unavailable. |
| 170 | + * Also, verify that requests using a local consistency level are not routed to remote DC nodes |
| 171 | + * when the local DC nodes are unavailable if the "allow remote DCs for local CL" setting is false. |
| 172 | + * |
| 173 | + * @test_category load_balancing_policy:dc_aware |
| 174 | + */ |
| 175 | +CASSANDRA_INTEGRATION_TEST_F(DcAwarePolicyTest, AllowRemoteDcsForLocalCl) { |
| 176 | + CHECK_FAILURE |
| 177 | + |
| 178 | + cluster_ = default_cluster(); |
| 179 | + char const *const local_dc = "dc1"; |
| 180 | + cluster_.with_load_balance_dc_aware(local_dc, 42, false); |
| 181 | + |
| 182 | + ExecutionProfile profile_allowing_remote_dcs_for_local_cl = ExecutionProfile::build().with_load_balance_dc_aware(local_dc, 42, true); |
| 183 | + char const *const profile_name = "allow_remote_dcs_for_local_cl"; |
| 184 | + cluster_.with_execution_profile(profile_name, profile_allowing_remote_dcs_for_local_cl); |
| 185 | + |
| 186 | + connect(cluster_); |
| 187 | + |
| 188 | + // Create a test table and add test data to it |
| 189 | + initialize(); |
| 190 | + |
| 191 | + Statement statement_with_nonlocal_consistency = select_statement("1"); |
| 192 | + statement_with_nonlocal_consistency.set_consistency(CASS_CONSISTENCY_TWO); |
| 193 | + |
| 194 | + Statement statement_with_local_consistency = select_statement("1"); |
| 195 | + statement_with_local_consistency.set_consistency(CASS_CONSISTENCY_LOCAL_ONE); |
| 196 | + |
| 197 | + std::cerr << "Testing with `allow_remote_dcs_for_local_cl`=`false`" << std::endl; |
| 198 | + { |
| 199 | + std::cerr << "Running nonlocal statement with local DC available" << std::endl; |
| 200 | + // With local DC available, everything should succeed and only local DC hosts should be used. |
| 201 | + validate_with_statement(statement_with_nonlocal_consistency, false, false); |
| 202 | + |
| 203 | + std::cerr << "Running local statement with local DC available" << std::endl; |
| 204 | + // With local DC available, everything should succeed and only local DC hosts should be used. |
| 205 | + validate_with_statement(statement_with_local_consistency, false, false); |
| 206 | + |
| 207 | + // Stop the whole local DC. |
| 208 | + stop_node(1, true); |
| 209 | + stop_node(2, true); |
| 210 | + |
| 211 | + std::cerr << "Running nonlocal statement with local DC unavailable" << std::endl; |
| 212 | + // With local DC unavailable, remote DC available and nonlocal consistency used, remote hosts should be used and the request should succeed. |
| 213 | + validate_with_statement(statement_with_nonlocal_consistency, false, true); |
| 214 | + |
| 215 | + std::cerr << "Running local statement with local DC unavailable" << std::endl; |
| 216 | + // With local DC unavailable, remote DC available and local consistency used, remote hosts should be forbidden and the request should fail. |
| 217 | + validate_with_statement(statement_with_local_consistency, true, false); |
| 218 | + } |
| 219 | + |
| 220 | + statement_with_local_consistency.set_execution_profile(profile_name); |
| 221 | + statement_with_nonlocal_consistency.set_execution_profile(profile_name); |
| 222 | + std::cerr << "Testing with `allow_remote_dcs_for_local_cl`=`true`" << std::endl; |
| 223 | + { |
| 224 | + // The local DC nodes are still dead. |
| 225 | + |
| 226 | + std::cerr << "Running nonlocal statement with local DC unavailable" << std::endl; |
| 227 | + // With local DC unavailable, remote DC available and nonlocal consistency used, remote hosts should be used and the request should succeed. |
| 228 | + validate_with_statement(statement_with_nonlocal_consistency, false, true); |
| 229 | + |
| 230 | + std::cerr << "Running local statement with local DC unavailable" << std::endl; |
| 231 | + // With local DC unavailable, remote DC available and local consistency used, remote hosts should be used and the request should succeed. |
| 232 | + validate_with_statement(statement_with_local_consistency, false, true); |
| 233 | + } |
| 234 | +} |
0 commit comments