-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathmod.rs
More file actions
143 lines (122 loc) · 4.9 KB
/
mod.rs
File metadata and controls
143 lines (122 loc) · 4.9 KB
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
//! SSH Server Container for Integration Testing
//!
//! This module provides SSH server containers for testing SSH client functionality.
//! Two implementations are available:
//!
//! - `MockSshServerContainer`: Fast mock for tests that don't need real SSH connectivity
//! - `RealSshServerContainer`: Actual Docker SSH server for full integration tests
//!
//! Both implementations provide the same interface through the `SshServerContainer` trait,
//! allowing for polymorphic usage in tests.
use std::net::IpAddr;
mod config;
mod constants;
mod debug;
mod error;
mod mock_container;
mod real_container;
pub use config::{SshServerConfig, SshServerConfigBuilder};
pub use debug::{print_docker_debug_info, ContainerInfo, DockerDebugInfo};
pub use error::SshServerError;
pub use mock_container::MockSshServerContainer;
pub use real_container::RealSshServerContainer;
/// Common interface for SSH server containers (mock and real)
///
/// This trait defines the standard interface that all SSH server container
/// implementations must provide. It enables polymorphic code that works with
/// both mock and real containers.
///
/// # Example
///
/// ```rust
/// use torrust_tracker_deployer_lib::testing::integration::ssh_server::{
/// SshServerContainer, MockSshServerContainer, RealSshServerContainer
/// };
///
/// async fn test_with_container<C: SshServerContainer>(container: &C) {
/// let port = container.ssh_port();
/// let ip = container.host_ip();
/// println!("SSH available at {}:{}", ip, port);
/// }
/// ```
pub trait SshServerContainer {
/// Get the SSH port mapped by the container
///
/// Returns the host port that maps to the container's SSH port (22).
fn ssh_port(&self) -> u16;
/// Get the container's host IP address
///
/// Returns the IP address to connect to the container from the host.
fn host_ip(&self) -> IpAddr;
/// Get the test username configured in the container
fn username(&self) -> &str;
/// Get the test password configured in the container
fn password(&self) -> &str;
}
#[cfg(test)]
mod tests {
use super::*;
use std::net::{IpAddr, Ipv4Addr};
#[tokio::test]
async fn it_should_start_mock_ssh_server_container() {
let container = MockSshServerContainer::start();
match container {
Ok(ssh_container) => {
// Verify basic container properties
let port = ssh_container.ssh_port();
assert!(port > 0, "SSH port should be positive");
let host_ip = ssh_container.host_ip();
assert_eq!(host_ip, IpAddr::V4(Ipv4Addr::LOCALHOST));
assert_eq!(ssh_container.username(), "testuser");
assert_eq!(ssh_container.password(), "testpass");
}
Err(e) => {
panic!("Mock container should always start successfully: {e}");
}
}
}
#[tokio::test]
async fn it_should_start_real_ssh_server_container() {
let container = RealSshServerContainer::start().await;
match container {
Ok(ssh_container) => {
// Verify basic container properties
let port = ssh_container.ssh_port();
assert!(port > 0, "SSH port should be positive");
let host_ip = ssh_container.host_ip();
assert_eq!(host_ip, IpAddr::V4(Ipv4Addr::LOCALHOST));
assert_eq!(ssh_container.username(), "testuser");
assert_eq!(ssh_container.password(), "testpass");
}
Err(e) => {
// Real container start might fail in CI environments without Docker
// or if the SSH server image hasn't been built
println!("Real container start failed (expected in some environments): {e}");
}
}
}
#[tokio::test]
async fn it_should_work_with_trait_object() {
// Test that we can use the trait for polymorphic behavior
let mock = MockSshServerContainer::start()
.expect("Mock container should always start successfully");
// Use trait method through trait object
let container: &dyn SshServerContainer = &mock;
assert!(container.ssh_port() > 0);
assert_eq!(container.host_ip(), IpAddr::V4(Ipv4Addr::LOCALHOST));
assert_eq!(container.username(), "testuser");
assert_eq!(container.password(), "testpass");
}
#[tokio::test]
async fn it_should_enable_generic_code() {
// Helper function that works with any SshServerContainer
fn verify_container<C: SshServerContainer>(container: &C) {
assert!(container.ssh_port() > 0);
assert_eq!(container.username(), "testuser");
}
let mock = MockSshServerContainer::start()
.expect("Mock container should always start successfully");
// Can call generic function with concrete type
verify_container(&mock);
}
}