mod common;
use common::{connect_test_client, get_test_container};
use fraiseql_wire::FraiseClient;
use futures::StreamExt;
use serde_json::Value;
#[tokio::test]
async fn test_scram_auth_success() {
let _client = connect_test_client()
.await
.expect("SCRAM authentication should succeed");
println!("✓ SCRAM authentication succeeded");
}
#[tokio::test]
async fn test_scram_auth_wrong_password() {
let container = get_test_container().await;
let wrong_url = format!(
"postgres://{}:wrongpassword@127.0.0.1:{}/{}",
container.user, container.port, container.database
);
let result = FraiseClient::connect(&wrong_url).await;
assert!(
result.is_err(),
"Expected authentication to fail with wrong password"
);
if let Err(e) = result {
let error_msg = e.to_string().to_lowercase();
assert!(
error_msg.contains("auth")
|| error_msg.contains("password")
|| error_msg.contains("failed"),
"Error message should indicate authentication failure: {}",
e
);
}
println!("✓ Authentication correctly rejected wrong password");
}
#[tokio::test]
async fn test_scram_auth_different_iterations() {
let client = connect_test_client()
.await
.expect("SCRAM authentication should succeed");
let mut stream = client
.query::<Value>("test.v_project")
.execute()
.await
.expect("query should succeed");
let mut count = 0;
while let Some(result) = stream.next().await {
let _ = result.expect("row should be valid");
count += 1;
if count >= 1 {
break;
}
}
println!("✓ SCRAM authentication succeeded with server-provided iteration count");
}
#[tokio::test]
async fn test_scram_nonce_handling() {
let container = get_test_container().await;
let conn_string = container.connection_string();
let client1 = FraiseClient::connect(&conn_string)
.await
.expect("First connection should succeed");
let client2 = FraiseClient::connect(&conn_string)
.await
.expect("Second connection should succeed");
let result1 = client1.query::<Value>("test.v_project").execute().await;
let result2 = client2.query::<Value>("test.v_project").execute().await;
assert!(result1.is_ok(), "First client query failed");
assert!(result2.is_ok(), "Second client query failed");
println!("✓ Multiple SCRAM authentications succeeded with unique nonces");
}
#[tokio::test]
async fn test_scram_server_verification() {
let client = connect_test_client()
.await
.expect("SCRAM authentication should succeed");
let result = client.query::<Value>("test.v_project").execute().await;
assert!(
result.is_ok(),
"Query execution failed after SCRAM authentication"
);
println!("✓ Server signature verified and mutual authentication succeeded");
}
#[tokio::test]
async fn test_scram_multiple_sequential_connections() {
let container = get_test_container().await;
let conn_string = container.connection_string();
for i in 0..5 {
let client = FraiseClient::connect(&conn_string)
.await
.unwrap_or_else(|e| panic!("Connection {} failed with SCRAM auth: {}", i + 1, e));
let result = client.query::<Value>("test.v_project").execute().await;
assert!(
result.is_ok(),
"Connection {} query failed after SCRAM auth",
i + 1
);
}
println!("✓ SCRAM authentication succeeded for 5 sequential connections");
}
#[tokio::test]
async fn test_scram_with_timeout() {
let client = connect_test_client()
.await
.expect("SCRAM authentication should succeed");
let result = client.query::<Value>("test.v_project").execute().await;
assert!(result.is_ok(), "Query failed after SCRAM auth with timeout");
println!("✓ SCRAM authentication succeeded within timeout");
}