@@ -271,3 +271,91 @@ fn set_database_password(options: &mut AnyConnectOptions, password: &str) {
271271 unreachable ! ( "Unsupported database type" ) ;
272272 }
273273}
274+
275+ #[ cfg( test) ]
276+ mod tests {
277+ use super :: * ;
278+ use sqlx:: row:: Row ;
279+ use tempfile:: TempDir ;
280+
281+ fn config_in ( dir : & TempDir , database_url : & str ) -> AppConfig {
282+ let mut config = crate :: app_config:: tests:: test_config ( ) ;
283+ config. database_url = database_url. to_owned ( ) ;
284+ config. configuration_directory = dir. path ( ) . to_path_buf ( ) ;
285+ config. max_database_pool_connections = Some ( 1 ) ;
286+ config
287+ }
288+
289+ #[ actix_web:: test]
290+ async fn on_connect_sql_runs_on_new_pool_connections ( ) {
291+ let dir = TempDir :: new ( ) . unwrap ( ) ;
292+ std:: fs:: write (
293+ dir. path ( ) . join ( ON_CONNECT_FILE ) ,
294+ "CREATE TEMPORARY TABLE on_connect_marker(value TEXT);
295+ INSERT INTO on_connect_marker(value) VALUES ('on_connect ran');" ,
296+ )
297+ . unwrap ( ) ;
298+
299+ let db = Database :: init ( & config_in ( & dir, "sqlite::memory:" ) )
300+ . await
301+ . unwrap ( ) ;
302+ let value: String = sqlx:: query:: query ( "SELECT value FROM on_connect_marker" )
303+ . fetch_one ( & db. connection )
304+ . await
305+ . unwrap ( )
306+ . try_get ( 0 )
307+ . unwrap ( ) ;
308+
309+ assert_eq ! ( value, "on_connect ran" ) ;
310+ }
311+
312+ #[ actix_web:: test]
313+ async fn on_reset_sql_runs_when_a_connection_returns_to_the_pool ( ) {
314+ let dir = TempDir :: new ( ) . unwrap ( ) ;
315+ std:: fs:: write (
316+ dir. path ( ) . join ( ON_CONNECT_FILE ) ,
317+ "CREATE TABLE IF NOT EXISTS reset_log(id INTEGER);" ,
318+ )
319+ . unwrap ( ) ;
320+ std:: fs:: write (
321+ dir. path ( ) . join ( ON_RESET_FILE ) ,
322+ "INSERT INTO reset_log(id) VALUES (1);
323+ SELECT 1 AS is_healthy;" ,
324+ )
325+ . unwrap ( ) ;
326+ let db_file = dir. path ( ) . join ( "on_reset.db" ) ;
327+ let config = config_in ( & dir, & format ! ( "sqlite://{}?mode=rwc" , db_file. display( ) ) ) ;
328+
329+ let db = Database :: init ( & config) . await . unwrap ( ) ;
330+ drop ( db. connection . acquire ( ) . await . unwrap ( ) ) ;
331+ let resets: i64 = sqlx:: query:: query ( "SELECT COUNT(*) FROM reset_log" )
332+ . fetch_one ( & db. connection )
333+ . await
334+ . unwrap ( )
335+ . try_get ( 0 )
336+ . unwrap ( ) ;
337+
338+ assert ! ( resets > 0 ) ;
339+ }
340+
341+ #[ tokio:: test( start_paused = true ) ]
342+ async fn connection_retries_wait_five_seconds_before_giving_up ( ) {
343+ for ( retries, expected_wait) in [ ( 0 , Duration :: ZERO ) , ( 2 , Duration :: from_secs ( 10 ) ) ] {
344+ let dir = TempDir :: new ( ) . unwrap ( ) ;
345+ let missing = dir. path ( ) . join ( "nonexistent_directory" ) . join ( "db.sqlite" ) ;
346+ let mut config = config_in ( & dir, & format ! ( "sqlite://{}" , missing. display( ) ) ) ;
347+ config. database_connection_retries = retries;
348+
349+ let start = tokio:: time:: Instant :: now ( ) ;
350+ let Err ( error) = Database :: init ( & config) . await else {
351+ panic ! ( "connecting to a missing database must fail" ) ;
352+ } ;
353+
354+ assert_eq ! ( start. elapsed( ) , expected_wait, "{retries} retries" ) ;
355+ assert ! (
356+ format!( "{error:#}" ) . contains( "Unable to open connection to" ) ,
357+ "{error:#}"
358+ ) ;
359+ }
360+ }
361+ }
0 commit comments