-
Notifications
You must be signed in to change notification settings - Fork 123
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
test(query_result): cluster state tests #1229
base: branch-hackathon
Are you sure you want to change the base?
test(query_result): cluster state tests #1229
Conversation
|
ae622d4
to
3b444d3
Compare
#[tokio::test] | ||
#[ntest::timeout(60000)] | ||
#[cfg(not(scylla_cloud_tests))] | ||
async fn test_session_should_have_metadata() { | ||
setup_tracing(); | ||
let session = create_new_session_builder().build().await.unwrap(); | ||
let state = session.get_cluster_state(); | ||
let keys = ["SCYLLA_URI", "SCYLLA_URI2", "SCYLLA_URI3"]; | ||
let expected_addresses: HashSet<String> = keys | ||
.iter() | ||
.map(|key| env::var(key).unwrap_or_else(|_| panic!("{} not set", key))) | ||
.collect(); | ||
|
||
let got_addresses: HashSet<String> = state | ||
.get_nodes_info() | ||
.iter() | ||
.map(|node| node.address.to_string()) | ||
.collect(); | ||
|
||
assert_eq!( | ||
got_addresses, expected_addresses, | ||
"Cluster node addresses do not match environment variables" | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this test doesn't fit in the query_result tests. Maybe create a new file for it, like cluster_state_tests
?
If you do, you could also move some tests from scylla/tests/integration/session.rs
into this new file, because they test cluster state too. I'm talking about tests like test_table_partitioner_in_metadata
, test_primary_key_ordering_in_metadata
etc. This could be done in another PR.
#[tokio::test] | ||
async fn test_should_not_have_tracing_id_when_tracing_disabled() { | ||
setup_tracing(); | ||
let session = create_new_session_builder().build().await.unwrap(); | ||
let query: Query = Query::new("SELECT release_version FROM system.local"); | ||
|
||
let result = session.query_unpaged(query, &[]).await.unwrap(); | ||
let tracing_id: Option<Uuid> = result.tracing_id(); | ||
assert!(tracing_id.is_none()); | ||
} | ||
|
||
#[tokio::test] | ||
async fn test_should_fetch_trace_when_tracing_enabled() { | ||
let session = create_new_session_builder().build().await.unwrap(); | ||
|
||
let mut query = Query::from("SELECT release_version FROM system.local"); | ||
query.set_tracing(true); | ||
|
||
let result = session.query_unpaged(query, &[]).await.unwrap(); | ||
let tracing_id: Option<Uuid> = result.tracing_id(); | ||
assert!(tracing_id.is_some()); | ||
let tracing_info: TracingInfo = session | ||
.get_tracing_info(&tracing_id.unwrap()) | ||
.await | ||
.unwrap(); | ||
|
||
// Verify trace information is present and has expected format | ||
assert!(!tracing_info.events.is_empty()); | ||
|
||
// Check if the request type matches | ||
assert_eq!(tracing_info.request.unwrap(), "Execute CQL3 query"); | ||
|
||
// Verify duration is positive | ||
assert!(tracing_info.duration.unwrap() > 0); | ||
|
||
// Verify started_at timestamp is present | ||
assert!(tracing_info.started_at.unwrap().0 > 0); | ||
|
||
// Check parameters | ||
assert!(tracing_info | ||
.parameters | ||
.clone() | ||
.unwrap() | ||
.contains_key("consistency_level")); | ||
assert!(tracing_info.parameters.unwrap().contains_key("query")); | ||
|
||
// Check events | ||
for event in tracing_info.events { | ||
assert!(!event.activity.clone().unwrap().is_empty()); | ||
assert!(event.source.is_some()); | ||
assert!(event.source_elapsed.unwrap() >= 0); | ||
assert!(!event.activity.unwrap().is_empty()); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you look into test_tracing_
tests in integration/session.rs
? It looks to me like those tests mostly duplicate the ones already existing - maybe instead of adding new ones you could improve existing ones with the checks that you wrote?
#[tokio::test] | ||
#[ntest::timeout(60000)] | ||
#[cfg(not(scylla_cloud_tests))] | ||
async fn should_expose_execution_info_on_exceptions() { | ||
setup_tracing(); | ||
let res = test_with_3_node_cluster( | ||
ShardAwareness::Unaware, | ||
|proxy_uris, translation_map, mut running_proxy| async move { | ||
let session: Session = SessionBuilder::new() | ||
.known_node(proxy_uris[0].as_str()) | ||
.address_translator(Arc::new(translation_map)) | ||
.build() | ||
.await | ||
.unwrap(); | ||
|
||
let forge_error_rule = RequestRule(Condition::True, RequestReaction::forge().invalid()); | ||
running_proxy.running_nodes[0] | ||
.change_request_rules(Some(vec![forge_error_rule.clone()])); | ||
running_proxy.running_nodes[1] | ||
.change_request_rules(Some(vec![forge_error_rule.clone()])); | ||
running_proxy.running_nodes[2] | ||
.change_request_rules(Some(vec![forge_error_rule.clone()])); | ||
|
||
let mut query = Query::from("select * from foo"); | ||
let history_listener = Arc::new(HistoryCollector::new()); | ||
query.set_history_listener(history_listener.clone()); | ||
let err = session | ||
.query_unpaged(query, &[]) | ||
.await | ||
.expect_err("expecting error"); | ||
let structured_history: StructuredHistory = history_listener.clone_structured_history(); | ||
|
||
assert_matches!( | ||
err, | ||
ExecutionError::LastAttemptError(RequestAttemptError::DbError(_, _)) | ||
); | ||
assert_eq!(structured_history.requests.len(), 1); | ||
running_proxy | ||
}, | ||
) | ||
.await; | ||
|
||
match res { | ||
Ok(()) => (), | ||
Err(err) => panic!("{}", err), | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't that mostly a history
tests? What does it verify that tests in integration/history.rs
don't?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
basically I wanted to test more details in errors, like Java driver does provide - but Rust driver don't expose them.
Somehow I have problems with finding similar tests - like also tracing tests I didn't notice already exist. Still I'm adapting to new IDE and ctrl+f mislead me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The structure of our tests (which test resides in which file) is unfortunately not the best :( We'd like to improve it - which is why I made my comments.
Feel free to ask if you can't find something that you suspect may already exist.
Nice way is to check for references to the function / method / field etc that you want to use in the test.
For Session::get_tracing_info()
it does correctly find a reference in integration/session.rs
:
specifically, in test_get_tracing_info
. This function is in turn called by test_tracing
in the same file, and there you can see our existing test cases for tracing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mostly my confusion is taken (again) out of python: test files usually start with test_
so when I search for something and I see it in test_xxx
file then I know it's in testing. Here when searching it is shown in session.rs
which mislead me (I missed looking at the directories).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, Rust and Python have vastly different approaches to many topics. In general, in Rust things are usually more explicit, instead of relying on properties like name.
3b444d3
to
9e1ed5a
Compare
@Lorak-mmk I adjusted to your's comments. Other state tests will be moved in different PR. |
9e1ed5a
to
4981fae
Compare
Added tests around query response metadata: 1. initial test for cluster state (node addresses) 2. improved trace_info test with more detailed verification based on: com.datastax.oss.driver.core.metadata.MetadataIT com.datastax.oss.driver.core.cql.QueryTraceIT
4981fae
to
e1254b6
Compare
// Verify duration is positive when Scylla is used | ||
if session | ||
.get_cluster_state() | ||
.get_nodes_info() | ||
.first() | ||
.unwrap() | ||
.sharder() | ||
.is_some() | ||
{ | ||
assert!(tracing_info.duration.unwrap() > 0); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there some Scylla issue about the incompatibility? Or maybe a documentation if the incompatibility is intentional? It should be linked here.
async fn test_session_should_have_metadata() { | ||
setup_tracing(); | ||
let session = create_new_session_builder().build().await.unwrap(); | ||
let state = session.get_cluster_state(); | ||
let keys = ["SCYLLA_URI", "SCYLLA_URI2", "SCYLLA_URI3"]; | ||
let expected_addresses: HashSet<String> = keys | ||
.iter() | ||
.map(|key| env::var(key).unwrap_or_else(|_| panic!("{} not set", key))) | ||
.collect(); | ||
|
||
let got_addresses: HashSet<String> = state | ||
.get_nodes_info() | ||
.iter() | ||
.map(|node| node.address.to_string()) | ||
.collect(); | ||
|
||
assert_eq!( | ||
got_addresses, expected_addresses, | ||
"Cluster node addresses do not match environment variables" | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤔 Maybe: test_session_should_have_metadata
-> test_session_should_have_topology_metadata
? Schema metadata is not checked here at all.
// Check parameters | ||
assert!(tracing_info | ||
.parameters | ||
.clone() | ||
.unwrap() | ||
.contains_key("consistency_level")); | ||
assert!(tracing_info.parameters.unwrap().contains_key("query")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔧 Instead of clone()
ing an Option<T>
in order to unwrap()
it, it's better to use as_ref()
to unwrap()
on a borrowed version of the Option
. See:
// Check parameters | |
assert!(tracing_info | |
.parameters | |
.clone() | |
.unwrap() | |
.contains_key("consistency_level")); | |
assert!(tracing_info.parameters.unwrap().contains_key("query")); | |
// Check parameters | |
assert!(tracing_info | |
.parameters | |
.as_ref() | |
.unwrap() | |
.contains_key("consistency_level")); | |
assert!(tracing_info.parameters.as_ref().unwrap().contains_key("query")); |
assert!(!event.activity.clone().unwrap().is_empty()); | ||
assert!(event.source.is_some()); | ||
assert!(event.source_elapsed.unwrap() >= 0); | ||
assert!(!event.activity.unwrap().is_empty()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assert!(!event.activity.clone().unwrap().is_empty()); | |
assert!(event.source.is_some()); | |
assert!(event.source_elapsed.unwrap() >= 0); | |
assert!(!event.activity.unwrap().is_empty()); | |
assert!(!event.activity.as_ref().unwrap().is_empty()); | |
assert!(event.source.is_some()); | |
assert!(event.source_elapsed.unwrap() >= 0); | |
assert!(!event.activity.as_ref().unwrap().is_empty()); |
Added tests around query response metadata:
based on:
com.datastax.oss.driver.core.metadata.MetadataIT
com.datastax.oss.driver.core.cql.QueryTraceIT
Pre-review checklist
./docs/source/
.Fixes:
annotations to PR description.