testcontainers_modules/cratedb/
mod.rs

1use std::{borrow::Cow, collections::HashMap};
2
3use testcontainers::{core::WaitFor, Image};
4
5const NAME: &str = "crate";
6const TAG: &str = "5.10.6";
7
8/// Represents a CrateDB docker instance.
9/// It is based on the official [`crate` docker image](https://hub.docker.com/_/crate)
10///
11/// Defaults are not modified:
12/// - `super_user`: `crate`
13/// - `password`: <empty>
14/// - `pg_port`: `5432`
15/// - `http_port`: `4200`
16///
17/// You can connect run instructions by sending an HTTP call to /_sql in port 4200.
18/// [`crate http interface`]
19///
20/// or using the postgres wire compatible protocol at port 5432.
21///
22/// # Example of postgres wire protocol.
23/// ```rust
24/// use testcontainers_modules::{cratedb, testcontainers::runners::SyncRunner};
25///
26/// let postgres_instance = cratedb::CrateDB::default().start().unwrap();
27///
28/// let connection_string = format!(
29///     "postgres://crate@{}:{}/postgres",
30///     postgres_instance.get_host().unwrap(),
31///     postgres_instance.get_host_port_ipv4(5432).unwrap()
32/// );
33///
34/// let mut conn = postgres::Client::connect(&connection_string, postgres::NoTls).unwrap();
35/// let rows = conn.query("SELECT 1 + 1", &[]).unwrap();
36/// assert_eq!(rows.len(), 1);
37/// ```
38///
39/// [`crate docker image`]: https://hub.docker.com/_/crate
40/// [`crate http interface`]: https://cratedb.com/docs/crate/reference/en/latest/interfaces/http.html
41#[derive(Debug, Clone)]
42pub struct CrateDB {
43    env_vars: HashMap<String, String>,
44}
45
46impl CrateDB {
47    /// Sets CrateDB's heap size
48    ///
49    /// You may need to increase this if you are testing high volumes of data.
50    pub fn with_heap_size(mut self, ram_gb: usize) -> Self {
51        self.env_vars
52            .insert("CRATE_HEAP_SIZE".to_string(), format!("{ram_gb}g"));
53        self
54    }
55}
56impl Default for CrateDB {
57    fn default() -> Self {
58        let mut env_vars = HashMap::new();
59        env_vars.insert("CRATE_HEAP_SIZE".to_string(), "1g".to_string());
60        Self { env_vars }
61    }
62}
63
64impl Image for CrateDB {
65    fn name(&self) -> &str {
66        NAME
67    }
68
69    fn tag(&self) -> &str {
70        TAG
71    }
72
73    fn ready_conditions(&self) -> Vec<WaitFor> {
74        vec![WaitFor::message_on_stdout("started")]
75    }
76
77    fn env_vars(
78        &self,
79    ) -> impl IntoIterator<Item = (impl Into<Cow<'_, str>>, impl Into<Cow<'_, str>>)> {
80        &self.env_vars
81    }
82}
83
84#[cfg(test)]
85mod tests {
86    use super::CrateDB;
87    use crate::testcontainers::{runners::SyncRunner, ImageExt};
88
89    #[test]
90    fn cratedb_one_pls_one() -> Result<(), Box<dyn std::error::Error + 'static>> {
91        let crate_image = CrateDB::default();
92
93        let node = crate_image.start()?;
94        let connection_string = &format!(
95            "postgres://crate@{}:{}/postgres",
96            node.get_host()?,
97            node.get_host_port_ipv4(5432)?
98        );
99
100        let mut conn = postgres::Client::connect(connection_string, postgres::NoTls).unwrap();
101        let rows = conn.query("SELECT 1 + 1", &[]).unwrap();
102        assert_eq!(rows.len(), 1);
103
104        let first_row = &rows[0];
105        let first_column: i32 = first_row.get(0);
106        assert_eq!(first_column, 2);
107
108        Ok(())
109    }
110
111    #[test]
112    fn cratedb_custom_version() -> Result<(), Box<dyn std::error::Error + 'static>> {
113        let node = CrateDB::default().with_tag("5.4.3").start()?;
114
115        let connection_string = &format!(
116            "postgres://crate:crate@{}:{}/postgres",
117            node.get_host()?,
118            node.get_host_port_ipv4(5432)?
119        );
120        let mut conn = postgres::Client::connect(connection_string, postgres::NoTls).unwrap();
121
122        let rows = conn.query("SELECT version()", &[]).unwrap();
123        assert_eq!(rows.len(), 1);
124
125        let first_row = &rows[0];
126        let first_column: String = first_row.get(0);
127        assert!(first_column.contains("5.4.3"));
128        Ok(())
129    }
130}