2018-10-07 00:24:11 +00:00
|
|
|
#[cfg(all(feature = "diesel_sqlite_pool", feature = "diesel_postgres_pool"))]
|
2018-07-21 22:11:08 +00:00
|
|
|
mod databases_tests {
|
|
|
|
use rocket_contrib::databases::{database, diesel};
|
|
|
|
|
|
|
|
#[database("foo")]
|
|
|
|
struct TempStorage(diesel::SqliteConnection);
|
|
|
|
|
|
|
|
#[database("bar")]
|
|
|
|
struct PrimaryDb(diesel::PgConnection);
|
|
|
|
}
|
2018-12-12 20:23:06 +00:00
|
|
|
|
|
|
|
#[cfg(all(feature = "databases", feature = "sqlite_pool"))]
|
|
|
|
#[cfg(test)]
|
|
|
|
mod rusqlite_integration_test {
|
|
|
|
use rocket_contrib::database;
|
2020-09-03 05:41:31 +00:00
|
|
|
use rocket_contrib::databases::rusqlite;
|
2018-12-12 20:23:06 +00:00
|
|
|
|
2019-06-13 02:17:59 +00:00
|
|
|
use rusqlite::types::ToSql;
|
2019-01-27 15:52:03 +00:00
|
|
|
|
2018-12-12 20:23:06 +00:00
|
|
|
#[database("test_db")]
|
|
|
|
struct SqliteDb(pub rusqlite::Connection);
|
|
|
|
|
2020-07-11 18:17:43 +00:00
|
|
|
// Test to ensure that multiple databases of the same type can be used
|
|
|
|
#[database("test_db_2")]
|
|
|
|
struct SqliteDb2(pub rusqlite::Connection);
|
2018-12-12 20:23:06 +00:00
|
|
|
|
2020-06-14 15:57:53 +00:00
|
|
|
#[rocket::async_test]
|
2020-07-11 18:17:43 +00:00
|
|
|
async fn test_db() {
|
2020-09-03 05:41:31 +00:00
|
|
|
use rocket::figment::{Figment, util::map};
|
|
|
|
|
|
|
|
let options = map!["url" => ":memory:"];
|
|
|
|
let config = Figment::from(rocket::Config::default())
|
|
|
|
.merge(("databases", map!["test_db" => &options]))
|
|
|
|
.merge(("databases", map!["test_db_2" => &options]));
|
|
|
|
|
2020-10-22 10:27:04 +00:00
|
|
|
let rocket = rocket::custom(config)
|
2020-09-03 05:41:31 +00:00
|
|
|
.attach(SqliteDb::fairing())
|
Remove 'attach' fairings. Add 'liftoff' fairings.
Launch fairings are now fallible and take the place of attach fairings,
but they are only run, as the name implies, at launch time.
This is is a fundamental shift from eager execution of set-up routines,
including the now defunct attach fairings, to lazy execution,
precipitated by the transition to `async`. The previous functionality,
while simple, caused grave issues:
1. A instance of 'Rocket' with async attach fairings requires an async
runtime to be constructed.
2. The instance is accessible in non-async contexts.
3. The async attach fairings have no runtime in which to be run.
Here's an example:
```rust
let rocket = rocket::ignite()
.attach(AttachFairing::from(|rocket| async {
Ok(rocket.manage(load_from_network::<T>().await))
}));
let state = rocket.state::<T>();
```
This had no real meaning previously yet was accepted by running the
attach fairing future in an isolated runtime. In isolation, this causes
no issue, but when attach fairing futures share reactor state with other
futures in Rocket, panics ensue.
The new Rocket application lifecycle is this:
* Build - A Rocket instance is constructed. No fairings are run.
* Ignition - All launch fairings are run.
* Liftoff - If all launch fairings succeeded, the server is started.
New 'liftoff' fairings are run in this third phase.
2021-04-01 19:32:52 +00:00
|
|
|
.attach(SqliteDb2::fairing())
|
|
|
|
._ignite()
|
|
|
|
.await
|
|
|
|
.unwrap();
|
2020-09-03 05:41:31 +00:00
|
|
|
|
2020-10-22 10:27:04 +00:00
|
|
|
let conn = SqliteDb::get_one(&rocket).await
|
2020-09-03 05:41:31 +00:00
|
|
|
.expect("unable to get connection");
|
2020-07-11 18:17:43 +00:00
|
|
|
|
|
|
|
// Rusqlite's `transaction()` method takes `&mut self`; this tests that
|
|
|
|
// the &mut method can be called inside the closure passed to `run()`.
|
|
|
|
conn.run(|conn| {
|
|
|
|
let tx = conn.transaction().unwrap();
|
2020-10-22 10:27:04 +00:00
|
|
|
let _: i32 = tx.query_row(
|
|
|
|
"SELECT 1", &[] as &[&dyn ToSql], |row| row.get(0)
|
|
|
|
).expect("get row");
|
|
|
|
|
2020-07-11 18:17:43 +00:00
|
|
|
tx.commit().expect("committed transaction");
|
|
|
|
}).await;
|
2018-12-12 20:23:06 +00:00
|
|
|
}
|
|
|
|
}
|
2020-11-05 04:05:31 +00:00
|
|
|
|
|
|
|
#[cfg(feature = "databases")]
|
|
|
|
#[cfg(test)]
|
|
|
|
mod drop_runtime_test {
|
|
|
|
use r2d2::{ManageConnection, Pool};
|
|
|
|
use rocket_contrib::databases::{database, Poolable, PoolResult};
|
|
|
|
use tokio::runtime::Runtime;
|
|
|
|
|
|
|
|
struct ContainsRuntime(Runtime);
|
|
|
|
struct TestConnection;
|
|
|
|
|
|
|
|
impl ManageConnection for ContainsRuntime {
|
|
|
|
type Connection = TestConnection;
|
|
|
|
type Error = std::convert::Infallible;
|
|
|
|
|
|
|
|
fn connect(&self) -> Result<Self::Connection, Self::Error> {
|
|
|
|
Ok(TestConnection)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn is_valid(&self, _conn: &mut Self::Connection) -> Result<(), Self::Error> {
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn has_broken(&self, _conn: &mut Self::Connection) -> bool {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Poolable for TestConnection {
|
|
|
|
type Manager = ContainsRuntime;
|
|
|
|
type Error = ();
|
|
|
|
|
|
|
|
fn pool(_db_name: &str, _rocket: &rocket::Rocket) -> PoolResult<Self> {
|
|
|
|
let manager = ContainsRuntime(tokio::runtime::Runtime::new().unwrap());
|
|
|
|
Ok(Pool::builder().build(manager)?)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[database("test_db")]
|
|
|
|
struct TestDb(TestConnection);
|
|
|
|
|
|
|
|
#[rocket::async_test]
|
|
|
|
async fn test_drop_runtime() {
|
|
|
|
use rocket::figment::{Figment, util::map};
|
|
|
|
|
|
|
|
let config = Figment::from(rocket::Config::default())
|
|
|
|
.merge(("databases", map!["test_db" => map!["url" => ""]]));
|
|
|
|
|
|
|
|
let rocket = rocket::custom(config).attach(TestDb::fairing());
|
|
|
|
drop(rocket);
|
|
|
|
}
|
|
|
|
}
|