diff --git a/Makefile b/Makefile index 9a4b58bd..dc4d021f 100644 --- a/Makefile +++ b/Makefile @@ -13,6 +13,7 @@ SCYLLA_TEST_FILTER := $(subst ${SPACE},${EMPTY},ClusterTests.*\ :PreparedTests.*\ :NamedParametersTests.*\ :CassandraTypes/CassandraTypesTests/*.Integration_Cassandra_*\ +:ControlConnectionTests.*\ :BatchSingleNodeClusterTests*:BatchCounterSingleNodeClusterTests*:BatchCounterThreeNodeClusterTests*\ :ErrorTests.*\ :SslNoClusterTests*:SslNoSslOnClusterTests*\ @@ -25,6 +26,9 @@ SCYLLA_TEST_FILTER := $(subst ${SPACE},${EMPTY},ClusterTests.*\ :UseKeyspaceCaseSensitiveTests.*\ :-PreparedTests.Integration_Cassandra_PreparedIDUnchangedDuringReprepare\ :HeartbeatTests.Integration_Cassandra_HeartbeatFailed\ +:ControlConnectionTests.Integration_Cassandra_TopologyChange\ +:ControlConnectionTests.Integration_Cassandra_FullOutage\ +:ControlConnectionTests.Integration_Cassandra_TerminatedUsingMultipleIoThreadsWithError\ :ExecutionProfileTest.InvalidName\ :*NoCompactEnabledConnection\ :PreparedMetadataTests.Integration_Cassandra_AlterProperlyUpdatesColumnCount\ @@ -43,6 +47,7 @@ CASSANDRA_TEST_FILTER := $(subst ${SPACE},${EMPTY},ClusterTests.*\ :PreparedTests.*\ :NamedParametersTests.*\ :CassandraTypes/CassandraTypesTests/*.Integration_Cassandra_*\ +:ControlConnectionTests.*\ :ErrorTests.*\ :SslClientAuthenticationTests*:SslNoClusterTests*:SslNoSslOnClusterTests*:SslTests*\ :SchemaMetadataTest.*KeyspaceMetadata:SchemaMetadataTest.*MetadataIterator:SchemaMetadataTest.*View*\ @@ -55,6 +60,9 @@ CASSANDRA_TEST_FILTER := $(subst ${SPACE},${EMPTY},ClusterTests.*\ :-PreparedTests.Integration_Cassandra_PreparedIDUnchangedDuringReprepare\ :PreparedTests.Integration_Cassandra_FailFastWhenPreparedIDChangesDuringReprepare\ :HeartbeatTests.Integration_Cassandra_HeartbeatFailed\ +:ControlConnectionTests.Integration_Cassandra_TopologyChange\ +:ControlConnectionTests.Integration_Cassandra_FullOutage\ +:ControlConnectionTests.Integration_Cassandra_TerminatedUsingMultipleIoThreadsWithError\ :SslTests.Integration_Cassandra_ReconnectAfterClusterCrashAndRestart\ :ExecutionProfileTest.InvalidName\ :*NoCompactEnabledConnection\ diff --git a/scylla-rust-wrapper/src/cass_error.rs b/scylla-rust-wrapper/src/cass_error.rs index c7d8d3e1..188af9cb 100644 --- a/scylla-rust-wrapper/src/cass_error.rs +++ b/scylla-rust-wrapper/src/cass_error.rs @@ -33,7 +33,7 @@ impl ToCassError for ExecutionError { ExecutionError::BadQuery(bad_query) => bad_query.to_cass_error(), ExecutionError::RequestTimeout(_) => CassError::CASS_ERROR_LIB_REQUEST_TIMED_OUT, ExecutionError::EmptyPlan => CassError::CASS_ERROR_LIB_INVALID_STATE, - ExecutionError::MetadataError(_) => CassError::CASS_ERROR_LIB_INVALID_STATE, + ExecutionError::MetadataError(e) => e.to_cass_error(), ExecutionError::ConnectionPoolError(e) => e.to_cass_error(), ExecutionError::PrepareError(e) => e.to_cass_error(), ExecutionError::LastAttemptError(e) => e.to_cass_error(), @@ -47,11 +47,7 @@ impl ToCassError for ExecutionError { impl ToCassError for ConnectionPoolError { fn to_cass_error(&self) -> CassError { - // I know that TranslationError (corresponding to CASS_ERROR_LIB_HOST_RESOLUTION) - // is hidden under the ConnectionPoolError. - // However, we still have a lot work to do when it comes to error conversion. - // I will address it, once we start resolving all issues related to error conversion. - CassError::CASS_ERROR_LIB_UNABLE_TO_CONNECT + CassError::CASS_ERROR_LIB_NO_HOSTS_AVAILABLE } } @@ -79,7 +75,7 @@ impl ToCassError for RequestAttemptError { } RequestAttemptError::UnableToAllocStreamId => CassError::CASS_ERROR_LIB_NO_STREAMS, RequestAttemptError::BrokenConnectionError(_) => { - CassError::CASS_ERROR_LIB_UNABLE_TO_CONNECT + CassError::CASS_ERROR_LIB_NO_HOSTS_AVAILABLE } RequestAttemptError::BodyExtensionsParseError(_) => { CassError::CASS_ERROR_LIB_MESSAGE_ENCODE @@ -164,7 +160,7 @@ impl ToCassError for NewSessionError { CassError::CASS_ERROR_LIB_NO_HOSTS_AVAILABLE } NewSessionError::EmptyKnownNodesList => CassError::CASS_ERROR_LIB_NO_HOSTS_AVAILABLE, - NewSessionError::MetadataError(_) => CassError::CASS_ERROR_LIB_INVALID_STATE, + NewSessionError::MetadataError(e) => e.to_cass_error(), NewSessionError::UseKeyspaceError(_) => { CassError::CASS_ERROR_LIB_UNABLE_TO_SET_KEYSPACE } @@ -174,6 +170,36 @@ impl ToCassError for NewSessionError { } } +impl ToCassError for MetadataError { + fn to_cass_error(&self) -> CassError { + match self { + MetadataError::ConnectionPoolError(e) => e.to_cass_error(), + MetadataError::FetchError(e) => match &e.error { + // Server bug - invalid CQL type in system table. + MetadataFetchErrorKind::InvalidColumnType(_) => { + CassError::CASS_ERROR_LIB_UNEXPECTED_RESPONSE + } + MetadataFetchErrorKind::PrepareError(e) => e.to_cass_error(), + MetadataFetchErrorKind::SerializationError(e) => e.to_cass_error(), + MetadataFetchErrorKind::NextRowError(_) => { + CassError::CASS_ERROR_LIB_UNEXPECTED_RESPONSE + } + + // non_exhaustive + _ => CassError::CASS_ERROR_LAST_ENTRY, + }, + // Remaining errors indicate a serious server bug - e.g. all peers have empty token lists. + MetadataError::Keyspaces(_) + | MetadataError::Peers(_) + | MetadataError::Tables(_) + | MetadataError::Udts(_) => CassError::CASS_ERROR_LIB_UNEXPECTED_RESPONSE, + + // non_exhaustive + _ => CassError::CASS_ERROR_LAST_ENTRY, + } + } +} + impl ToCassError for BadKeyspaceName { fn to_cass_error(&self) -> CassError { match self { diff --git a/tests/src/integration/tests/test_control_connection.cpp b/tests/src/integration/tests/test_control_connection.cpp index 5abbc50d..d110b33a 100644 --- a/tests/src/integration/tests/test_control_connection.cpp +++ b/tests/src/integration/tests/test_control_connection.cpp @@ -132,9 +132,9 @@ CASSANDRA_INTEGRATION_TEST_F(ControlConnectionTests, ConnectUsingInvalidIpAddres CHECK_FAILURE; // Attempt to connect to the server using an invalid IP address - logger_.add_critera("Unable to establish a control connection to host " - "1.1.1.1 because of the following error: Underlying " - "connection error: Connection timeout"); + logger_.add_critera("Could not fetch metadata, error: " + "Control connection pool error: The pool is broken; " + "Last connection failed with: Connect timeout elapsed"); Cluster cluster = Cluster::build().with_contact_points("1.1.1.1"); try { cluster.connect(); @@ -185,7 +185,7 @@ CASSANDRA_INTEGRATION_TEST_F(ControlConnectionTests, ConnectUsingUnresolvableLoc // Attempt to connect to the server using an unresolvable local IP address Cluster cluster = default_cluster(); - EXPECT_EQ(CASS_ERROR_LIB_HOST_RESOLUTION, + EXPECT_EQ(CASS_ERROR_LIB_BAD_PARAMS, cass_cluster_set_local_address(cluster.get(), "unknown.invalid")); } @@ -204,7 +204,9 @@ CASSANDRA_INTEGRATION_TEST_F(ControlConnectionTests, ConnectUsingUnbindableLocal CHECK_FAILURE; // Attempt to connect to the server using an unbindable local IP address - logger_.add_critera("Unable to bind local address: address not available"); + logger_.add_critera("Could not fetch metadata, error: " + "Control connection pool error: The pool is broken; " + "Last connection failed with: Cannot assign requested address"); Cluster cluster = default_cluster().with_local_address("1.1.1.1"); try { cluster.connect(); @@ -234,8 +236,9 @@ CASSANDRA_INTEGRATION_TEST_F(ControlConnectionTests, // Attempt to connect to the server using an valid local IP address // but invalid remote address. The specified remote is not routable // from the specified local. - logger_.add_critera("Unable to establish a control connection to host " - "1.1.1.1 because of the following error:"); + logger_.add_critera("Could not fetch metadata, error: " + "Control connection pool error: The pool is broken; " + "Last connection failed with: Invalid argument"); Cluster cluster = Cluster::build().with_contact_points("1.1.1.1").with_local_address("127.0.0.1"); try { cluster.connect();