use crate::query::query_state::{QueryState, ResultType};
fn wait_for_completion(state: &mut QueryState, timeout_secs: u64) -> bool {
let timeout = std::time::Instant::now();
while state.is_pending() && timeout.elapsed() < std::time::Duration::from_secs(timeout_secs) {
let _ = state.poll_response();
std::thread::sleep(std::time::Duration::from_millis(10));
}
!state.is_pending()
}
#[test]
fn test_async_multiple_nulls_preserves_cache() {
let json = r#"{"services": [{"name": "a"}, {"name": "b"}]}"#;
let mut state = QueryState::new(json.to_string());
state.execute_async(".services[]");
assert!(wait_for_completion(&mut state, 2));
let cached_base = state.base_query_for_suggestions.clone();
let cached_type = state.base_type_for_suggestions.clone();
let cached_parsed = state.last_successful_result_parsed.clone();
assert_eq!(cached_base, Some(".services[]".to_string()));
state.execute_async(".services[].nonexistent");
assert!(wait_for_completion(&mut state, 2));
let result = state.result.as_ref().unwrap();
assert!(result.contains("null"), "Query should return null values");
assert_eq!(
state.base_query_for_suggestions, cached_base,
"base_query should be preserved for multiple nulls"
);
assert_eq!(
state.base_type_for_suggestions, cached_type,
"base_type should be preserved for multiple nulls"
);
assert_eq!(
state.last_successful_result_parsed, cached_parsed,
"parsed result should be preserved for multiple nulls"
);
}
#[test]
fn test_async_non_null_updates_cache() {
let json = r#"{"name": "Alice", "age": 30}"#;
let mut state = QueryState::new(json.to_string());
assert_eq!(state.base_query_for_suggestions, Some(".".to_string()));
state.execute_async(".name");
assert!(wait_for_completion(&mut state, 2));
let result = state.result.as_ref().unwrap();
assert!(result.contains("Alice"));
assert_eq!(
state.base_query_for_suggestions,
Some(".name".to_string()),
"base_query should be updated for non-null result"
);
assert_eq!(
state.base_type_for_suggestions,
Some(ResultType::String),
"base_type should be updated for non-null result"
);
assert!(
state.last_successful_result_parsed.is_some(),
"parsed result should be cached"
);
}
#[test]
fn test_async_line_count_not_cached_for_null() {
let json = r#"{"services": [{"a": 1}, {"b": 2}, {"c": 3}]}"#;
let mut state = QueryState::new(json.to_string());
state.execute_async(".services[]");
assert!(wait_for_completion(&mut state, 2));
let cached_line_count = state.line_count();
assert!(cached_line_count >= 3, "Should have at least 3 lines");
state.execute_async(".services[].nonexistent");
assert!(wait_for_completion(&mut state, 2));
assert_eq!(
state.line_count(),
cached_line_count,
"Line count should be preserved for null results"
);
}
#[test]
fn test_async_cancellation_during_preprocessing() {
let json = "{}".to_string();
let mut state = QueryState::new(json);
state.execute_async(".");
state.cancel_in_flight();
let _ = state.poll_response();
assert!(!state.is_pending(), "Should not be pending after cancel");
}
#[test]
fn test_async_updates_context_cache() {
let json = r#"{"name": "test", "value": 42}"#;
let mut state = QueryState::new(json.to_string());
let initial_context_cache = state.last_successful_result_for_context.clone();
assert!(initial_context_cache.is_some());
state.execute_async(".name");
assert!(wait_for_completion(&mut state, 2));
let updated_context_cache = state.last_successful_result_for_context.clone();
assert!(updated_context_cache.is_some());
assert_ne!(
initial_context_cache, updated_context_cache,
"Async execution should update context cache"
);
}
#[test]
fn test_async_null_preserves_context_cache() {
let json = r#"{"services": [{"name": "a"}, {"name": "b"}]}"#;
let mut state = QueryState::new(json.to_string());
state.execute_async(".services[]");
assert!(wait_for_completion(&mut state, 2));
let cached_context = state.last_successful_result_for_context.clone();
assert!(cached_context.is_some());
state.execute_async(".services[].nonexistent");
assert!(wait_for_completion(&mut state, 2));
assert_eq!(
state.last_successful_result_for_context, cached_context,
"Async null results should preserve context cache"
);
}