#![allow(clippy::format_push_string)]
mod common;
use common::connect_test_client;
use fraiseql_wire::client::FraiseClient;
use futures::stream::StreamExt;
#[tokio::test]
async fn test_stress_early_stream_drop() {
println!("Test: Early stream drop (client disconnect)");
let client = connect_test_client().await.expect("failed to connect");
let mut stream = client
.query::<serde_json::Value>("test.v_project")
.execute()
.await
.expect("failed to execute query");
if let Some(result) = stream.next().await {
let _value = result.expect("failed to deserialize");
println!(" Received first row, dropping stream...");
}
drop(stream);
println!(" Stream dropped: ✓");
let client2 = connect_test_client()
.await
.expect("should be able to reconnect");
let mut stream2 = client2
.query::<serde_json::Value>("test.v_project")
.execute()
.await
.expect("failed to execute second query");
if let Some(result) = stream2.next().await {
let _value = result.expect("failed to deserialize");
println!(" Reconnection successful: ✓");
}
}
#[tokio::test]
async fn test_stress_invalid_connection_string() {
println!("Test: Invalid connection string");
let result = FraiseClient::connect("invalid://connection/string").await;
assert!(result.is_err(), "should reject invalid connection string");
println!(" Invalid connection rejected: ✓");
}
#[tokio::test]
async fn test_stress_connection_refused() {
println!("Test: Connection refused (host unreachable)");
let result = FraiseClient::connect("postgres://nonexistent.invalid:5432/test").await;
assert!(result.is_err(), "should fail for unreachable host");
println!(" Connection refused handled: ✓");
}
#[tokio::test]
async fn test_stress_missing_table() {
println!("Test: Missing table");
let client = connect_test_client().await.expect("failed to connect");
let result = client
.query::<serde_json::Value>("nonexistent_table")
.execute()
.await;
assert!(result.is_err(), "should reject missing table");
println!(" Missing table error: ✓");
}
#[tokio::test]
async fn test_stress_invalid_where_clause() {
println!("Test: Invalid WHERE clause");
let client = connect_test_client().await.expect("failed to connect");
let result = client
.query::<serde_json::Value>("test.v_project")
.where_sql("INVALID SQL SYNTAX (((")
.execute()
.await;
assert!(result.is_err(), "should reject invalid SQL");
println!(" Invalid SQL rejected: ✓");
}
#[tokio::test]
async fn test_stress_empty_result_set() {
println!("Test: Empty result set");
let client = connect_test_client().await.expect("failed to connect");
let mut stream = client
.query::<serde_json::Value>("test.v_project")
.where_sql("data->>'name' = 'NonexistentProject12345'")
.execute()
.await
.expect("failed to execute query");
let mut count = 0;
while let Some(result) = stream.next().await {
let _value = result.expect("failed to deserialize");
count += 1;
}
assert_eq!(count, 0, "should return zero rows");
println!(" Empty result set handled: ✓");
}
#[tokio::test]
async fn test_stress_large_where_clause() {
println!("Test: Very large WHERE clause");
let client = connect_test_client().await.expect("failed to connect");
let mut where_clause = "data->>'name' IN (".to_string();
for i in 0..100 {
where_clause.push_str(&format!("'name_{}'", i));
if i < 99 {
where_clause.push(',');
}
}
where_clause.push(')');
let result = client
.query::<serde_json::Value>("test.v_project")
.where_sql(&where_clause)
.execute()
.await;
match result {
Ok(mut stream) => {
let mut count = 0;
while let Some(result) = stream.next().await {
let _value = result.expect("failed to deserialize");
count += 1;
}
println!(" Large WHERE clause executed: {} rows", count);
}
Err(e) => {
println!(" Large WHERE clause error (acceptable): {}", e);
}
}
println!(" Large WHERE clause handled: ✓");
}
#[tokio::test]
async fn test_stress_connection_cycling() {
println!("Test: Rapid connection cycles");
let num_cycles = 10;
for i in 0..num_cycles {
let result = connect_test_client().await;
assert!(result.is_ok(), "cycle {} failed", i);
println!(" Cycle {}: connected", i);
}
println!(" Connection cycling: ✓");
}
#[tokio::test]
async fn test_stress_single_connection_multiple_queries() {
println!("Test: Multiple queries from single connection");
let client = connect_test_client().await.expect("failed to connect");
let mut stream1 = client
.query::<serde_json::Value>("test.v_project")
.execute()
.await
.expect("failed first query");
let row1 = stream1.next().await;
assert!(
row1.is_some(),
"should get at least one row from first query"
);
println!(" First query: received row");
}
#[tokio::test]
async fn test_stress_tiny_chunk_size() {
println!("Test: Very small chunk size");
let client = connect_test_client().await.expect("failed to connect");
let mut stream = client
.query::<serde_json::Value>("test.v_project")
.chunk_size(2) .execute()
.await
.expect("failed to execute");
let mut count = 0;
while let Some(result) = stream.next().await {
let _value = result.expect("failed to deserialize");
count += 1;
}
println!(" Small chunk size (2): {} rows", count);
println!(" Small chunk size handled: ✓");
}
#[tokio::test]
async fn test_stress_huge_chunk_size() {
println!("Test: Very large chunk size");
let client = connect_test_client().await.expect("failed to connect");
let mut stream = client
.query::<serde_json::Value>("test.v_project")
.chunk_size(10000) .execute()
.await
.expect("failed to execute");
let mut count = 0;
while let Some(result) = stream.next().await {
let _value = result.expect("failed to deserialize");
count += 1;
}
println!(" Large chunk size (10000): {} rows", count);
println!(" Large chunk size handled: ✓");
}
#[tokio::test]
async fn test_stress_partial_consumption() {
println!("Test: Partial row consumption");
let client = connect_test_client().await.expect("failed to connect");
let mut stream = client
.query::<serde_json::Value>("test.v_project")
.execute()
.await
.expect("failed to execute");
let mut count = 0;
while let Some(result) = stream.next().await {
let _value = result.expect("failed to deserialize");
count += 1;
if count >= 3 {
break;
}
}
println!(" Consumed {}/all rows", count);
println!(" Partial consumption handled: ✓");
}
#[tokio::test]
async fn test_stress_zero_chunk_size() {
println!("Test: Zero chunk size");
let client = connect_test_client().await.expect("failed to connect");
let result = client
.query::<serde_json::Value>("test.v_project")
.chunk_size(1) .execute()
.await;
match result {
Ok(mut stream) => {
let mut count = 0;
while let Some(result) = stream.next().await {
let _value = result.expect("failed to deserialize");
count += 1;
if count >= 1 {
break;
}
}
println!(" Minimum chunk size (1) handled gracefully");
}
Err(e) => {
println!(" Minimum chunk size error: {}", e);
}
}
println!(" Minimum chunk size: ✓");
}
#[tokio::test]
async fn test_stress_invalid_order_by() {
println!("Test: Invalid ORDER BY");
let client = connect_test_client().await.expect("failed to connect");
let result = client
.query::<serde_json::Value>("test.v_project")
.order_by("INVALID SYNTAX FOR ORDER BY")
.execute()
.await;
assert!(result.is_err(), "should reject invalid ORDER BY");
println!(" Invalid ORDER BY rejected: ✓");
}
#[tokio::test]
async fn test_stress_combined_predicates() {
println!("Test: Combined SQL and Rust predicates");
let client = connect_test_client().await.expect("failed to connect");
let mut stream = client
.query::<serde_json::Value>("test.v_user")
.where_sql("data->>'id' IS NOT NULL")
.where_rust(|json| {
json.get("profile").is_some()
})
.execute()
.await
.expect("failed to execute");
let mut count = 0;
while let Some(result) = stream.next().await {
let _value = result.expect("failed to deserialize");
count += 1;
}
println!(" Combined predicates: {} rows", count);
println!(" Combined predicates: ✓");
}
#[tokio::test]
async fn test_stress_json_validity() {
println!("Test: JSON validity of results");
let client = connect_test_client().await.expect("failed to connect");
let mut stream = client
.query::<serde_json::Value>("test.v_project")
.execute()
.await
.expect("failed to execute");
let mut count = 0;
let mut valid_json = 0;
while let Some(result) = stream.next().await {
let value = result.expect("failed to deserialize");
if value.is_object() || value.is_array() || !value.is_null() {
valid_json += 1;
}
count += 1;
}
println!(" Total rows: {}", count);
println!(" Valid JSON rows: {}", valid_json);
assert_eq!(count, valid_json, "all rows should contain valid JSON");
println!(" JSON validity: ✓");
}
#[tokio::test]
async fn test_stress_complex_order_by() {
println!("Test: Complex ORDER BY expression");
let client = connect_test_client().await.expect("failed to connect");
let result = client
.query::<serde_json::Value>("test.v_project")
.order_by("data->>'name' COLLATE \"C\" DESC")
.execute()
.await;
match result {
Ok(mut stream) => {
let mut count = 0;
while let Some(result) = stream.next().await {
let _value = result.expect("failed to deserialize");
count += 1;
}
println!(" Complex ORDER BY: {} rows", count);
}
Err(e) => {
println!(" Complex ORDER BY error: {}", e);
}
}
println!(" Complex ORDER BY: ✓");
}