pg_embedded_setup_unpriv/cluster/
connection.rs1use camino::{Utf8Path, Utf8PathBuf};
3#[cfg(feature = "diesel-support")]
4use color_eyre::eyre::WrapErr;
5use postgresql_embedded::Settings;
6
7use crate::TestBootstrapSettings;
8#[cfg(feature = "diesel-support")]
9use crate::error::BootstrapResult;
10
11#[derive(Debug, Clone)]
25pub struct ConnectionMetadata {
26 settings: Settings,
27 pgpass_file: Utf8PathBuf,
28}
29
30impl ConnectionMetadata {
31 pub(crate) fn from_settings(settings: &TestBootstrapSettings) -> Self {
32 Self {
33 settings: settings.settings.clone(),
34 pgpass_file: settings.environment.pgpass_file.clone(),
35 }
36 }
37
38 #[must_use]
40 pub fn host(&self) -> &str {
41 self.settings.host.as_str()
42 }
43
44 #[must_use]
46 pub const fn port(&self) -> u16 {
47 self.settings.port
48 }
49
50 #[must_use]
52 pub fn superuser(&self) -> &str {
53 self.settings.username.as_str()
54 }
55
56 #[must_use]
58 pub fn password(&self) -> &str {
59 self.settings.password.as_str()
60 }
61
62 #[must_use]
64 pub fn pgpass_file(&self) -> &Utf8Path {
65 self.pgpass_file.as_ref()
66 }
67
68 #[must_use]
71 pub fn database_url(&self, database: &str) -> String {
72 self.settings.url(database)
73 }
74}
75
76#[derive(Debug, Clone)]
93pub struct TestClusterConnection {
94 metadata: ConnectionMetadata,
95}
96
97impl TestClusterConnection {
98 pub(crate) fn new(settings: &TestBootstrapSettings) -> Self {
99 Self {
100 metadata: ConnectionMetadata::from_settings(settings),
101 }
102 }
103
104 #[must_use]
106 pub fn host(&self) -> &str {
107 self.metadata.host()
108 }
109
110 #[must_use]
112 pub const fn port(&self) -> u16 {
113 self.metadata.port()
114 }
115
116 #[must_use]
118 pub fn superuser(&self) -> &str {
119 self.metadata.superuser()
120 }
121
122 #[must_use]
124 pub fn password(&self) -> &str {
125 self.metadata.password()
126 }
127
128 #[must_use]
130 pub fn pgpass_file(&self) -> &Utf8Path {
131 self.metadata.pgpass_file()
132 }
133
134 #[must_use]
136 pub fn metadata(&self) -> ConnectionMetadata {
137 self.metadata.clone()
138 }
139
140 #[must_use]
142 pub fn database_url(&self, database: &str) -> String {
143 self.metadata.database_url(database)
144 }
145
146 #[cfg(feature = "diesel-support")]
151 pub fn diesel_connection(&self, database: &str) -> BootstrapResult<diesel::PgConnection> {
152 use diesel::Connection;
153
154 diesel::PgConnection::establish(&self.database_url(database))
155 .wrap_err(format!("failed to connect to {database} via Diesel"))
156 .map_err(crate::error::BootstrapError::from)
157 }
158}
159
160#[cfg(test)]
161mod tests {
162 use super::*;
163 use crate::TestBootstrapSettings;
164 use crate::bootstrap::{ExecutionMode, ExecutionPrivileges, TestBootstrapEnvironment};
165 use postgresql_embedded::Settings;
166 use std::time::Duration;
167
168 fn sample_settings() -> TestBootstrapSettings {
169 let settings = Settings {
170 host: "127.0.0.1".into(),
171 port: 55_321,
172 username: "fixture_user".into(),
173 password: "fixture_pass".into(),
174 data_dir: "/tmp/cluster-data".into(),
175 installation_dir: "/tmp/cluster-install".into(),
176 ..Settings::default()
177 };
178
179 TestBootstrapSettings {
180 privileges: ExecutionPrivileges::Unprivileged,
181 execution_mode: ExecutionMode::InProcess,
182 settings,
183 environment: TestBootstrapEnvironment {
184 home: Utf8PathBuf::from("/tmp/home"),
185 xdg_cache_home: Utf8PathBuf::from("/tmp/home/cache"),
186 xdg_runtime_dir: Utf8PathBuf::from("/tmp/home/run"),
187 pgpass_file: Utf8PathBuf::from("/tmp/home/.pgpass"),
188 tz_dir: Some(Utf8PathBuf::from("/usr/share/zoneinfo")),
189 timezone: "UTC".into(),
190 },
191 worker_binary: None,
192 setup_timeout: Duration::from_secs(1),
193 start_timeout: Duration::from_secs(1),
194 shutdown_timeout: Duration::from_secs(1),
195 }
196 }
197
198 #[test]
199 fn metadata_reflects_underlying_settings() {
200 let settings = sample_settings();
201 let connection = TestClusterConnection::new(&settings);
202 let metadata = connection.metadata();
203
204 assert_eq!(metadata.host(), "127.0.0.1");
205 assert_eq!(metadata.port(), 55_321);
206 assert_eq!(metadata.superuser(), "fixture_user");
207 assert_eq!(metadata.password(), "fixture_pass");
208 assert_eq!(metadata.pgpass_file(), Utf8Path::new("/tmp/home/.pgpass"));
209 }
210
211 #[test]
212 fn database_url_matches_postgresql_embedded() {
213 let settings = sample_settings();
214 let connection = TestClusterConnection::new(&settings);
215 let expected = settings.settings.url("postgres");
216
217 assert_eq!(connection.database_url("postgres"), expected);
218 }
219}