1use std::path::Path;
2use std::thread;
3
4pub struct TestMysqlDatabase {
5 db_name: String,
6 connection_url: String,
7 addr: String,
8}
9
10impl TestMysqlDatabase {
11 pub fn new(db_name: String, addr: &str, ssl: bool, ssl_ca: Option<&Path>) -> Self {
12 let addr_c = addr.to_string();
13 let db_name_clone = db_name.clone();
14 let _ = thread::spawn(move || {
15 let rt = match tokio::runtime::Runtime::new() {
16 Ok(rt) => rt,
17 Err(_) => return,
18 };
19
20 rt.block_on(async {
21 use sqlx::mysql::MySqlPoolOptions;
22
23 let pool = match MySqlPoolOptions::new()
24 .connect(&format!("mysql://root:mysql@{addr_c}/mysql"))
25 .await
26 {
27 Ok(pool) => pool,
28 Err(_) => return,
29 };
30
31 let _ = sqlx::query(&format!("CREATE DATABASE {db_name_clone}"))
32 .execute(&pool)
33 .await;
34 });
35 })
36 .join();
37
38 let ssl = if ssl { "?ssl-mode=VERIFY_IDENTITY" } else { "" };
39
40 let ssl_ca = match (!ssl.is_empty(), ssl_ca) {
41 (true, Some(ssl_ca)) => format!("&ssl-ca={}", ssl_ca.to_string_lossy()),
42 (_, _) => "".to_string(),
43 };
44
45 let connection_url = format!("mysql://root:mysql@{addr}/{db_name}{ssl}{ssl_ca}");
46 Self {
47 db_name,
48 connection_url,
49 addr: addr.to_string(),
50 }
51 }
52
53 pub fn connection_url(&self) -> &str {
54 &self.connection_url
55 }
56}
57
58impl Drop for TestMysqlDatabase {
59 fn drop(&mut self) {
60 let db_name = self.db_name.clone();
61 let addr = self.addr.clone();
62 let _ = thread::spawn(move || {
63 let rt = match tokio::runtime::Runtime::new() {
64 Ok(rt) => rt,
65 Err(_) => return,
66 };
67
68 rt.block_on(async {
69 use sqlx::mysql::MySqlPoolOptions;
70
71 let pool = match MySqlPoolOptions::new()
72 .connect(&format!("mysql://root:mysql@{addr}/mysql"))
73 .await
74 {
75 Ok(pool) => pool,
76 Err(_) => return,
77 };
78
79 let _ = sqlx::query(&format!("DROP DATABASE IF EXISTS {db_name}"))
80 .execute(&pool)
81 .await;
82 });
83 })
84 .join();
85 }
86}
87
88pub struct TestPostgresDatabase {
89 db_name: String,
90 connection_url: String,
91 addr: String,
92}
93
94impl TestPostgresDatabase {
95 pub fn new(db_name: String, addr: &str, ssl: bool, ssl_root_cert: Option<&Path>) -> Self {
96 let db_name_clone = db_name.clone();
97 let addr_c = addr.to_string();
98 let _ = thread::spawn(move || {
99 let rt = match tokio::runtime::Runtime::new() {
100 Ok(rt) => rt,
101 Err(_) => return,
102 };
103
104 rt.block_on(async {
105 use sqlx::postgres::PgPoolOptions;
106
107 let pool = match PgPoolOptions::new()
108 .connect(&format!("postgres://postgres:postgres@{addr_c}/postgres"))
109 .await
110 {
111 Ok(pool) => pool,
112 Err(_) => return,
113 };
114
115 let _ = sqlx::query(&format!("CREATE DATABASE {db_name_clone}"))
116 .execute(&pool)
117 .await;
118 });
119 })
120 .join();
121
122 let ssl = if ssl { "?sslmode=verify-full" } else { "" };
123
124 let ssl_root_cert = match (!ssl.is_empty(), ssl_root_cert) {
125 (true, Some(ssl_root_cert)) => {
126 format!("&sslrootcert={}", ssl_root_cert.to_string_lossy())
127 }
128 (_, _) => "".to_string(),
129 };
130
131 let connection_url =
132 format!("postgres://postgres:postgres@{addr}/{db_name}{ssl}{ssl_root_cert}");
133
134 Self {
135 db_name,
136 connection_url,
137 addr: addr.to_string(),
138 }
139 }
140
141 pub fn connection_url(&self) -> &str {
142 &self.connection_url
143 }
144}
145
146impl Drop for TestPostgresDatabase {
147 fn drop(&mut self) {
148 let db_name = self.db_name.clone();
149 let addr = self.addr.clone();
150 let _ = thread::spawn(move || {
151 let rt = match tokio::runtime::Runtime::new() {
152 Ok(rt) => rt,
153 Err(_) => return,
154 };
155
156 rt.block_on(async {
157 use sqlx::postgres::PgPoolOptions;
158
159 let pool = match PgPoolOptions::new()
160 .connect(&format!("postgres://postgres:postgres@{addr}/postgres"))
161 .await
162 {
163 Ok(pool) => pool,
164 Err(_) => return,
165 };
166
167 let _ = sqlx::query(&format!("SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '{db_name}' AND pid <> pg_backend_pid()"))
168 .execute(&pool).await;
169
170 let _ = sqlx::query(&format!("DROP DATABASE IF EXISTS {db_name}"))
171 .execute(&pool)
172 .await;
173 });
174 })
175 .join();
176 }
177}