use std::fmt::Display;
use crate::{db::async_db::AsyncConnection, error::DBError};
#[tokio::test]
async fn open_in_memory_test() -> Result<(), DBError> {
let conn = AsyncConnection::open_in_memory().await;
assert!(conn.is_ok());
Ok(())
}
#[tokio::test]
async fn call_success_test() -> Result<(), DBError> {
let conn = AsyncConnection::open_in_memory().await?;
let result = conn
.call(|conn| {
conn.execute(
"CREATE TABLE person(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL);",
[],
)
.map_err(|e| e.into())
})
.await;
assert_eq!(0, result.unwrap());
Ok(())
}
#[tokio::test]
async fn call_unwrap_success_test() -> Result<(), DBError> {
let conn = AsyncConnection::open_in_memory().await?;
let result = conn
.call_unwrap(|conn| {
conn.execute(
"CREATE TABLE person(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL);",
[],
)
.unwrap()
})
.await;
assert_eq!(0, result);
Ok(())
}
#[tokio::test]
async fn call_failure_test() -> Result<(), DBError> {
let conn = AsyncConnection::open_in_memory().await?;
let result = conn
.call(|conn| conn.execute("Invalid sql", []).map_err(|e| e.into()))
.await;
assert!(match result.unwrap_err() {
crate::Error::Rusqlite(e) => {
e == rusqlite::Error::SqlInputError {
error: ffi::Error {
code: ErrorCode::Unknown,
extended_code: 1,
},
msg: "near \"Invalid\": syntax error".to_string(),
sql: "Invalid sql".to_string(),
offset: 0,
}
}
_ => false,
});
Ok(())
}
#[tokio::test]
async fn close_success_test() -> Result<(), DBError> {
let conn = AsyncConnection::open_in_memory().await?;
assert!(conn.close().await.is_ok());
Ok(())
}
#[tokio::test]
async fn double_close_test() -> Result<(), DBError> {
let conn = AsyncConnection::open_in_memory().await?;
let conn2 = conn.clone();
assert!(conn.close().await.is_ok());
assert!(conn2.close().await.is_ok());
Ok(())
}
#[tokio::test]
async fn close_call_test() -> Result<(), DBError> {
let conn = AsyncConnection::open_in_memory().await?;
let conn2 = conn.clone();
assert!(conn.close().await.is_ok());
let result = conn2
.call(|conn| conn.execute("SELECT 1;", []).map_err(|e| e.into()))
.await;
assert!(matches!(
result.unwrap_err(),
crate::Error::ConnectionClosed
));
Ok(())
}
#[tokio::test]
#[should_panic]
async fn close_call_unwrap_test() {
let conn = AsyncConnection::open_in_memory().await.unwrap();
let conn2 = conn.clone();
assert!(conn.close().await.is_ok());
conn2
.call_unwrap(|conn| conn.execute("SELECT 1;", []))
.await
.unwrap();
}
#[tokio::test]
async fn close_failure_test() -> Result<(), DBError> {
let conn = AsyncConnection::open_in_memory().await?;
conn.call(|conn| {
conn.execute(
"CREATE TABLE person(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL);",
[],
)
.map_err(|e| e.into())
})
.await?;
conn.call(|conn| {
let stmt = Box::new(conn.prepare("INSERT INTO person VALUES (1, ?1);").unwrap());
Box::leak(stmt);
Ok(())
})
.await?;
assert!(match conn.close().await.unwrap_err() {
crate::Error::Close((_, e)) => {
e == rusqlite::Error::SqliteFailure(
ffi::Error {
code: ErrorCode::DatabaseBusy,
extended_code: 5,
},
Some(
"unable to close due to unfinalized statements or unfinished backups"
.to_string(),
),
)
}
_ => false,
});
Ok(())
}
#[tokio::test]
async fn debug_format_test() -> Result<(), DBError> {
let conn = AsyncConnection::open_in_memory().await?;
assert_eq!("Connection".to_string(), format!("{conn:?}"));
Ok(())
}
fn failable_func(_: &rusqlite::Connection) -> std::result::Result<(), MyError> {
Err(MyError::MySpecificError)
}
#[tokio::test]
async fn test_ergonomic_errors() -> Result<(), DBError> {
let conn = AsyncConnection::open_in_memory().await?;
let res = conn
.call(|conn| failable_func(conn).map_err(|e| DBError::Other(format!("{}", e))))
.await
.unwrap_err();
let err = std::error::Error::source(&res)
.and_then(|e| e.downcast_ref::<MyError>())
.unwrap();
assert!(matches!(err, MyError::MySpecificError));
Ok(())
}
#[derive(Debug)]
enum MyError {
MySpecificError,
}
impl Display for MyError {
fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Ok(())
}
}
impl std::error::Error for MyError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
None
}
}