sqlx_database_tester/
lib.rs1#![doc = include_str!("../README.md")]
2use std::{env, str::FromStr};
3
4pub use dotenv;
5pub use sqlx_database_tester_macros::test;
6
7const DATABASE_ENV_VAR: &str = "DATABASE_URL";
9#[doc(hidden)]
10pub fn derive_db_prefix(uri: &str) -> Result<Option<String>, sqlx::Error> {
12 Ok(sqlx::postgres::PgConnectOptions::from_str(uri)?.get_database().map(str::to_owned))
13}
14
15#[doc(hidden)]
16pub fn derive_db_name(uri: &str) -> Result<String, sqlx::Error> {
19 let random_part = uuid::Uuid::new_v4().simple().to_string();
20
21 Ok(if let Some(prefix) = derive_db_prefix(uri)? {
22 format!("{}_{}", prefix, random_part)
23 } else {
24 random_part
25 })
26}
27
28#[must_use]
30pub fn connect_options(
31 database_name: &str,
32 #[allow(unused_variables)] level: &str,
33) -> sqlx::postgres::PgConnectOptions {
34 #[allow(clippy::expect_used)]
35 let mut options = sqlx::postgres::PgConnectOptions::from_str(&get_database_uri())
36 .expect("Failed to parse database URI");
37 options = options.database(database_name);
38 #[cfg(feature = "sqlx-log")]
39 if let Ok(filter) = log::LevelFilter::from_str(level) {
40 use sqlx::ConnectOptions;
41 options.log_statements(filter);
42 }
43 options
44}
45
46#[doc(hidden)]
47#[must_use]
48pub fn get_database_uri() -> String {
50 env::var(DATABASE_ENV_VAR)
51 .unwrap_or_else(|_| panic!("The env variable {} needs to be set", DATABASE_ENV_VAR))
52}
53
54#[cfg(test)]
55#[allow(clippy::unwrap_used)]
56mod tests {
57 use std::env;
58
59 use crate::{connect_options, derive_db_name, derive_db_prefix, get_database_uri};
60
61 #[test]
62 fn test_db_prefix() {
63 assert_eq!(derive_db_prefix("postgresql:///").unwrap(), None);
64 assert_eq!(derive_db_prefix("postgres://").unwrap(), None);
65 assert_eq!(derive_db_prefix("postgresql://localhost:5433").unwrap(), None);
66 assert_eq!(
67 derive_db_prefix("postgresql:///mydb?host=localhost&port=5433").unwrap(),
68 Some("mydb".to_owned())
69 );
70 assert_eq!(derive_db_prefix("postgresql://workflow-engine:password@%2Fopt%2Fpostgresql%2Fsockets/workflow-engine").unwrap(), Some("workflow-engine".to_owned()));
71 assert_eq!(
72 derive_db_prefix(
73 "postgresql://other@localhost/otherdb?connect_timeout=10&application_name=myapp"
74 )
75 .unwrap(),
76 Some("otherdb".to_owned())
77 );
78 }
79
80 #[test]
81 fn test_derive_db_name() {
82 assert!(derive_db_name("postgresql:///mydb?host=localhost&port=5433")
83 .unwrap()
84 .starts_with("mydb_"));
85 assert_eq!(
86 derive_db_name("postgresql:///mydb?host=localhost&port=5433").unwrap().len(),
87 37
88 );
89
90 assert_eq!(derive_db_name("postgresql:///").unwrap().len(), 32);
91 }
92
93 #[test]
94 fn test_connect_options() {
95 env::set_var("DATABASE_URL", "postgresql:///");
96 assert_eq!(
97 connect_options("test_database", "info").get_database().unwrap(),
98 "test_database"
99 );
100
101 env::set_var(
102 "DATABASE_URL",
103 "postgresql://workflow-engine:password@%2Fopt%2Fpostgresql%2Fsockets/workflow-engine",
104 );
105 assert_eq!(
106 connect_options("test_database", "info").get_database().unwrap(),
107 "test_database"
108 );
109
110 env::remove_var("DATABASE_URL");
111 }
112
113 #[test]
114 fn test_get_database_uri() {
115 env::set_var(
116 "DATABASE_URL",
117 "postgresql://workflow-engine:password@%2Fopt%2Fpostgresql%2Fsockets/workflow-engine",
118 );
119 assert_eq!(
120 get_database_uri(),
121 "postgresql://workflow-engine:password@%2Fopt%2Fpostgresql%2Fsockets/workflow-engine"
122 );
123
124 env::remove_var("DATABASE_URL");
125 }
126
127 #[test]
128 #[should_panic(expected = "The env variable DATABASE_URL needs to be set")]
129 fn test_get_database_uri_panic() {
130 env::remove_var("DATABASE_URL");
131 let _ = get_database_uri();
132 }
133}