blob: c32cd4e25f22d376091c353ed7d41712d3cd86e0 [file] [log] [blame]
use crate::schema::*;
use diesel::result::Error;
use diesel::*;
#[test]
#[cfg(not(feature = "sqlite"))] // FIXME: This test is only valid when operating on a file and not :memory:
fn transaction_executes_fn_in_a_sql_transaction() {
let conn1 = connection_without_transaction();
let conn2 = connection_without_transaction();
let test_name = "transaction_executes_fn_in_a_sql_transaction";
setup_test_table(&conn1, test_name);
let get_count = |conn| count_test_table(conn, test_name);
conn1
.transaction::<_, Error, _>(|| {
assert_eq!(0, get_count(&conn1));
assert_eq!(0, get_count(&conn2));
conn1.execute(&format!("INSERT INTO {} DEFAULT VALUES", test_name))?;
assert_eq!(1, get_count(&conn1));
assert_eq!(0, get_count(&conn2));
Ok(())
})
.unwrap();
assert_eq!(1, get_count(&conn1));
assert_eq!(1, get_count(&conn2));
drop_test_table(&conn1, test_name);
}
#[test]
fn transaction_returns_the_returned_value() {
let conn1 = connection_without_transaction();
assert_eq!(Ok(1), conn1.transaction::<_, Error, _>(|| Ok(1)));
}
#[test]
fn transaction_is_rolled_back_when_returned_an_error() {
let connection = connection_without_transaction();
let test_name = "transaction_is_rolled_back_when_returned_an_error";
setup_test_table(&connection, test_name);
let get_count = || count_test_table(&connection, test_name);
let _ = connection.transaction::<(), _, _>(|| {
connection
.execute(&format!("INSERT INTO {} DEFAULT VALUES", test_name))
.unwrap();
Err(Error::RollbackTransaction)
});
assert_eq!(0, get_count());
drop_test_table(&connection, test_name);
}
#[test]
fn transactions_can_be_nested() {
let connection = connection_without_transaction();
let test_name = "transactions_can_be_nested";
setup_test_table(&connection, test_name);
let get_count = || count_test_table(&connection, test_name);
let _ = connection.transaction::<(), _, _>(|| {
connection
.execute(&format!("INSERT INTO {} DEFAULT VALUES", test_name))
.unwrap();
assert_eq!(1, get_count());
let _ = connection.transaction::<(), _, _>(|| {
connection
.execute(&format!("INSERT INTO {} DEFAULT VALUES", test_name))
.unwrap();
assert_eq!(2, get_count());
Err(Error::RollbackTransaction)
});
assert_eq!(1, get_count());
let _ = connection.transaction::<(), Error, _>(|| {
connection
.execute(&format!("INSERT INTO {} DEFAULT VALUES", test_name))
.unwrap();
assert_eq!(2, get_count());
Ok(())
});
assert_eq!(2, get_count());
Err(Error::RollbackTransaction)
});
assert_eq!(0, get_count());
drop_test_table(&connection, test_name);
}
#[test]
fn test_transaction_always_rolls_back() {
let connection = connection_without_transaction();
let test_name = "test_transaction_always_rolls_back";
setup_test_table(&connection, test_name);
let result = connection.test_transaction::<_, Error, _>(|| {
connection.execute(&format!("INSERT INTO {} DEFAULT VALUES", test_name))?;
assert_eq!(1, count_test_table(&connection, test_name));
Ok("success")
});
assert_eq!(0, count_test_table(&connection, test_name));
assert_eq!("success", result);
drop_test_table(&connection, test_name);
}
#[test]
#[should_panic(expected = "Transaction did not succeed")]
fn test_transaction_panics_on_error() {
let connection = connection_without_transaction();
connection.test_transaction::<(), _, _>(|| Err(()));
}
fn setup_test_table(connection: &TestConnection, table_name: &str) {
use crate::schema_dsl::*;
create_table(table_name, (integer("id").primary_key().auto_increment(),))
.execute(connection)
.unwrap();
}
fn drop_test_table(connection: &TestConnection, table_name: &str) {
connection
.execute(&format!("DROP TABLE {}", table_name))
.unwrap();
}
fn count_test_table(connection: &TestConnection, table_name: &str) -> i64 {
use diesel::dsl::sql;
select(sql::<sql_types::BigInt>(&format!(
"COUNT(*) FROM {}",
table_name
)))
.first(connection)
.unwrap()
}