vaultrs_test/
docker.rs

1use dockertest::{Composition, DockerOperations, DockerTest};
2use futures::future::Future;
3
4/// A server configuration which can be converted into a [Composition] to be
5/// ran as a container.
6///
7/// Types implementing this trait should collect all required configuration data
8/// and use [ServerConfig::to_comp] to convert it into a [Composition] to be run
9/// by a [TestInstance]. The associated [Server] for this configuration should
10/// later recieve a copy of this configuration to perform any additional steps
11/// required.
12pub trait ServerConfig {
13    /// Creates a [Composition] from this configuration
14    fn to_comp(&self) -> Composition;
15
16    /// Creates a new [TestInstance] and automatically adds the [Composition]
17    /// from this configuration to it.
18    fn to_instance(&self) -> TestInstance;
19}
20
21/// An instance of a server that is created after it's associated [Composition]
22/// has been brought up.
23///
24/// This trait is the main vehicle for tests to interact with the running
25/// container. It should encompass all logic necessary for tests to successfully
26/// interact with it.
27pub trait Server {
28    type Config;
29    fn new(ops: &DockerOperations, config: &Self::Config) -> Self;
30}
31
32/// A single test instance made up of several [Composition]s which
33/// are brought up for executing tests.
34///
35/// Use the `run` method to run the containers and perform the test logic.
36pub struct TestInstance {
37    pub instance: DockerTest,
38}
39
40impl TestInstance {
41    /// Returns a new [TestInstance] configured with the given [Composition]s.
42    pub fn new(mut servers: Vec<Composition>) -> TestInstance {
43        let mut instance = DockerTest::new();
44        servers.drain(..).for_each(|s| instance.add_composition(s));
45
46        TestInstance { instance }
47    }
48
49    /// Adds a [Composition] to this [TestInstance].
50    pub fn add(&mut self, comp: Composition) {
51        self.instance.add_composition(comp);
52    }
53
54    /// Runs all containers from the associated [Composition]s, verifying they
55    /// are running according to their startup conditions, and then calls the
56    /// passed closure with runtime details.
57    ///
58    /// This is the main method for running the [TestInstance]. All test logic
59    /// should be encompassed within the passed closure. Creating and destroying
60    /// containers happens upon entering/leaving the closure.
61    pub fn run<T, F>(self, fun: T)
62    where
63        T: FnOnce(DockerOperations) -> F + Send + 'static,
64        F: Future<Output = ()> + Send + 'static,
65    {
66        self.instance.run(|ops| async move {
67            (fun)(ops).await;
68        });
69    }
70}