1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/*
* Copyright 2024 Akash Rawal
*
* This file is part of Disposables.
*
* Disposables is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Disposables is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Disposables. If not, see <https://www.gnu.org/licenses/>.
*/
/*!
* Disposables is a library that runs your test dependencies in containers.
* Once your tests finish running, the containers are automatically cleaned up.
* Disposables works with both Docker and Podman, does not require Docker socket
* access, and works well with user namespaces.
*
* Disposables needs Podman or Docker CLI to work.
*
* Generally, this is how the flow goes:
* 1. Create a container.
* 2. Wait for the container to become ready. This can be done by checking if
* a port is connectable, or certain pattern is found within the container's
* stdout.
* 3. Use the container.
* 4. Drop the container. Once the container struct is dropped, the container
* is terminated.
*
* Sharing one container across multiple tests is possible if you set the struct
* as a static variable, the container is cleaned up after all tests have
* finished.
*
* ```rust
* # use disposables::{ContainerParams, Context};
* # use disposables::util::try_use;
* # use disposables::protocol::V1Event;
* # use std::net::TcpStream;
* # use std::io::{Read, Write};
*
* let mut container = ContainerParams::new("docker.io/nginx:alpine")
* .port(80) //< Port 80 will be exposed
* .wait_for_port(80) //< Wait for port 80 to be connectable
* .file("/usr/share/nginx/html/custom_file.html",
* "<html>Custom file</html>") //< Add this file before starting entrypoint
* .create().unwrap();
*
* let event = container.wait(); //< Wait for container to become ready
* assert!(matches!(event, Ok(V1Event::Ready)),
* "Container start failed: {event:?}, logs: {}", container.logs().unwrap());
*
* //Connect to port 80 of the container
* let mut conn = try_use(container.port(80).unwrap(), TcpStream::connect).unwrap();
*
* //Send request
* write!(conn, "GET /custom_file.html HTTP/1.0\nHost: localhost\n\n").unwrap();
* let mut response_buf = Vec::<u8>::new();
* conn.read_to_end(&mut response_buf).unwrap();
* let response = String::from_utf8(response_buf).unwrap();
* log::info!("Received response {response}"); //< <html>Custom file</html>
* ```
*/
/// Disposables protocol re-exports
pub use Context;
pub use ;