use deadpool_oracle::{ConfigExt, PoolBuilder};
use oracle_rs::Config;
use std::time::Duration;
fn get_test_config() -> Option<Config> {
let host = std::env::var("ORACLE_HOST").unwrap_or_else(|_| "localhost".to_string());
let port: u16 = std::env::var("ORACLE_PORT")
.ok()
.and_then(|p| p.parse().ok())
.unwrap_or(1521);
let service = std::env::var("ORACLE_SERVICE").unwrap_or_else(|_| "FREEPDB1".to_string());
let username = std::env::var("ORACLE_USER").unwrap_or_else(|_| "system".to_string());
let password = std::env::var("ORACLE_PASSWORD").unwrap_or_else(|_| "testpass".to_string());
if std::env::var("ORACLE_TEST_URL").is_err() {
return None;
}
let mut config = Config::new(&host, port, &service, &username, &password);
config.set_password(&password);
Some(config)
}
#[tokio::test]
#[ignore = "requires Oracle database"]
async fn test_pool_basic() {
let config = get_test_config().expect("ORACLE_TEST_URL not set");
let pool = PoolBuilder::new(config)
.max_size(2)
.build()
.expect("Failed to build pool");
let conn = pool.get().await.expect("Failed to get connection");
let result = conn
.query("SELECT 1 FROM DUAL", &[])
.await
.expect("Query failed");
assert_eq!(result.row_count(), 1);
let status = pool.status();
println!("Pool status: size={}, available={}", status.size, status.available);
assert_eq!(status.size, 1); assert_eq!(status.available, 0);
drop(conn);
let status = pool.status();
assert_eq!(status.available, 1); }
#[tokio::test]
#[ignore = "requires Oracle database"]
async fn test_pool_reuse() {
let config = get_test_config().expect("ORACLE_TEST_URL not set");
let pool = PoolBuilder::new(config)
.max_size(1)
.build()
.expect("Failed to build pool");
{
let conn = pool.get().await.expect("Failed to get connection");
conn.query("SELECT 1 FROM DUAL", &[]).await.expect("Query failed");
}
{
let conn = pool.get().await.expect("Failed to get connection");
conn.query("SELECT 2 FROM DUAL", &[]).await.expect("Query failed");
}
let status = pool.status();
assert_eq!(status.size, 1);
assert_eq!(status.available, 1);
}
#[tokio::test]
#[ignore = "requires Oracle database"]
async fn test_pool_concurrent() {
let config = get_test_config().expect("ORACLE_TEST_URL not set");
let pool = PoolBuilder::new(config)
.max_size(3)
.build()
.expect("Failed to build pool");
let mut handles = vec![];
for i in 0..5 {
let pool = pool.clone();
let handle = tokio::spawn(async move {
let conn = pool.get().await.expect("Failed to get connection");
let result = conn
.query(&format!("SELECT {} FROM DUAL", i), &[])
.await
.expect("Query failed");
assert_eq!(result.row_count(), 1);
tokio::time::sleep(Duration::from_millis(50)).await;
});
handles.push(handle);
}
for handle in handles {
handle.await.expect("Task panicked");
}
let status = pool.status();
assert!(status.size <= 3);
println!("Final pool size: {}", status.size);
}
#[tokio::test]
#[ignore = "requires Oracle database"]
async fn test_pool_transaction_rollback() {
let config = get_test_config().expect("ORACLE_TEST_URL not set");
let pool = PoolBuilder::new(config)
.max_size(1)
.build()
.expect("Failed to build pool");
{
let conn = pool.get().await.expect("Failed to get connection");
conn.execute(
"BEGIN EXECUTE IMMEDIATE 'CREATE TABLE pool_test (id NUMBER)'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;",
&[]
).await.expect("Failed to create table");
conn.execute("DELETE FROM pool_test", &[]).await.ok();
conn.commit().await.expect("Failed to commit");
}
{
let conn = pool.get().await.expect("Failed to get connection");
conn.execute("INSERT INTO pool_test (id) VALUES (1)", &[])
.await
.expect("Insert failed");
}
{
let conn = pool.get().await.expect("Failed to get connection");
let result = conn
.query("SELECT COUNT(*) FROM pool_test", &[])
.await
.expect("Query failed");
let row = &result.rows[0];
match &row.values()[0] {
oracle_rs::Value::String(s) => assert_eq!(s, "0"),
oracle_rs::Value::Integer(i) => assert_eq!(*i, 0),
other => panic!("Unexpected value: {:?}", other),
}
}
{
let conn = pool.get().await.expect("Failed to get connection");
conn.execute("DROP TABLE pool_test", &[]).await.ok();
conn.commit().await.ok();
}
}
#[tokio::test]
#[ignore = "requires Oracle database"]
async fn test_pool_config_ext_trait() {
let config = get_test_config().expect("ORACLE_TEST_URL not set");
let pool = config.into_pool_with_size(5).expect("Failed to create pool");
let conn = pool.get().await.expect("Failed to get connection");
let result = conn
.query("SELECT 1 FROM DUAL", &[])
.await
.expect("Query failed");
assert_eq!(result.row_count(), 1);
}
#[tokio::test]
#[ignore = "requires Oracle database"]
async fn test_pool_timeout_configuration() {
let config = get_test_config().expect("ORACLE_TEST_URL not set");
let pool = PoolBuilder::new(config)
.max_size(2)
.wait_timeout(Some(Duration::from_secs(5)))
.create_timeout(Some(Duration::from_secs(10)))
.recycle_timeout(Some(Duration::from_secs(3)))
.build()
.expect("Failed to build pool");
let conn = pool.get().await.expect("Failed to get connection");
conn.query("SELECT 1 FROM DUAL", &[]).await.expect("Query failed");
}
#[test]
fn test_pool_builder_no_db() {
let config = Config::new("localhost", 1521, "FREEPDB1", "test", "test");
let pool = PoolBuilder::new(config)
.max_size(10)
.wait_timeout(Some(Duration::from_secs(30)))
.create_timeout(Some(Duration::from_secs(30)))
.recycle_timeout(Some(Duration::from_secs(5)))
.build();
match &pool {
Ok(_) => {}
Err(e) => {
println!("Pool build error: {:?}", e);
}
}
assert!(pool.is_ok(), "Pool build failed");
let pool = pool.unwrap();
let status = pool.status();
assert_eq!(status.size, 0);
assert_eq!(status.available, 0);
}