auto_port_demo/
auto_port_demo.rs1use rust_test_harness::{test, run_tests_with_config, TestConfig, ContainerConfig, before_each, after_each};
10use std::time::Duration;
11
12fn main() {
13 println!("๐ Auto-Port and Container Management Demo");
14 println!("==========================================");
15 println!();
16
17 let web_container = ContainerConfig::new("nginx:alpine")
19 .auto_port(80) .env("NGINX_HOST", "localhost")
21 .name("web_service")
22 .ready_timeout(Duration::from_secs(15));
23
24 let db_container = ContainerConfig::new("postgres:13-alpine")
26 .auto_port(5432) .env("POSTGRES_PASSWORD", "testpass")
28 .env("POSTGRES_DB", "testdb")
29 .name("test_database")
30 .ready_timeout(Duration::from_secs(20));
31
32 let redis_container = ContainerConfig::new("redis:6-alpine")
34 .auto_port(6379) .name("test_redis")
36 .ready_timeout(Duration::from_secs(10));
37
38 let mixed_container = ContainerConfig::new("httpd:alpine")
40 .port(8080, 80) .auto_port(443) .env("APACHE_DOCUMENT_ROOT", "/var/www/html")
43 .name("mixed_ports")
44 .ready_timeout(Duration::from_secs(15));
45
46 println!("๐ Container Configurations:");
47 println!("1. Web Service (nginx):");
48 println!(" - Image: {}", web_container.image);
49 println!(" - Auto-ports: {:?}", web_container.auto_ports);
50 println!(" - Auto-cleanup: {}", web_container.auto_cleanup);
51
52 println!("2. Database (postgres):");
53 println!(" - Image: {}", db_container.image);
54 println!(" - Auto-ports: {:?}", db_container.auto_ports);
55 println!(" - Auto-cleanup: {}", db_container.auto_cleanup);
56
57 println!("3. Cache (redis):");
58 println!(" - Image: {}", redis_container.image);
59 println!(" - Auto-ports: {:?}", redis_container.auto_ports);
60 println!(" - Auto-cleanup: {}", redis_container.auto_cleanup);
61
62 println!("4. Mixed (httpd):");
63 println!(" - Image: {}", mixed_container.image);
64 println!(" - Manual ports: {:?}", mixed_container.ports);
65 println!(" - Auto-ports: {:?}", mixed_container.auto_ports);
66 println!(" - Auto-cleanup: {}", mixed_container.auto_cleanup);
67 println!();
68
69 let web_before = web_container.clone();
71 let db_before = db_container.clone();
72 let redis_before = redis_container.clone();
73 let mixed_before = mixed_container.clone();
74
75 before_each(move |ctx| {
77 println!("๐ before_each: Starting all containers...");
78
79 let web_info = web_before.start()
81 .map_err(|e| format!("Failed to start web container: {}", e))?;
82 ctx.set_data("web_container_info", web_info.clone());
83 println!("โ
Web container started: {}", web_info.container_id);
84 println!(" Ports: {}", web_info.ports_summary());
85 if let Some(url) = web_info.primary_url() {
86 println!(" URL: {}", url);
87 }
88
89 let db_info = db_before.start()
91 .map_err(|e| format!("Failed to start db container: {}", e))?;
92 ctx.set_data("db_container_info", db_info.clone());
93 println!("โ
Database container started: {}", db_info.container_id);
94 println!(" Ports: {}", db_info.ports_summary());
95 if let Some(host_port) = db_info.host_port_for(5432) {
96 println!(" PostgreSQL accessible at: localhost:{}", host_port);
97 }
98
99 let redis_info = redis_before.start()
101 .map_err(|e| format!("Failed to start redis container: {}", e))?;
102 ctx.set_data("redis_container_info", redis_info.clone());
103 println!("โ
Redis container started: {}", redis_info.container_id);
104 println!(" Ports: {}", redis_info.ports_summary());
105 if let Some(host_port) = redis_info.host_port_for(6379) {
106 println!(" Redis accessible at: localhost:{}", host_port);
107 }
108
109 let mixed_info = mixed_before.start()
111 .map_err(|e| format!("Failed to start mixed container: {}", e))?;
112 ctx.set_data("mixed_container_info", mixed_info.clone());
113 println!("โ
Mixed container started: {}", mixed_info.container_id);
114 println!(" Ports: {}", mixed_info.ports_summary());
115 if let Some(host_port) = mixed_info.host_port_for(443) {
116 println!(" HTTPS accessible at: localhost:{}", host_port);
117 }
118
119 println!("๐ All containers started successfully!");
120 Ok(())
121 });
122
123 let web_after = web_container.clone();
125 let db_after = db_container.clone();
126 let redis_after = redis_container.clone();
127 let mixed_after = mixed_container.clone();
128
129 after_each(move |ctx| {
130 println!("๐งน after_each: Cleaning up all containers...");
131
132 if let Some(web_info) = ctx.get_data::<rust_test_harness::ContainerInfo>("web_container_info") {
134 let _ = web_after.stop(&web_info.container_id);
135 println!("๐ Stopped web container: {}", web_info.container_id);
136 }
137
138 if let Some(db_info) = ctx.get_data::<rust_test_harness::ContainerInfo>("db_container_info") {
139 let _ = db_after.stop(&db_info.container_id);
140 println!("๐ Stopped database container: {}", db_info.container_id);
141 }
142
143 if let Some(redis_info) = ctx.get_data::<rust_test_harness::ContainerInfo>("redis_container_info") {
144 let _ = redis_after.stop(&redis_info.container_id);
145 println!("๐ Stopped redis container: {}", redis_info.container_id);
146 }
147
148 if let Some(mixed_info) = ctx.get_data::<rust_test_harness::ContainerInfo>("mixed_container_info") {
149 let _ = mixed_after.stop(&mixed_info.container_id);
150 println!("๐ Stopped mixed container: {}", mixed_info.container_id);
151 }
152
153 println!("โ
All containers cleaned up!");
154 Ok(())
155 });
156
157 test("test_web_service_access", |ctx| {
159 println!("๐งช Testing web service access...");
160
161 let web_info = ctx.get_data::<rust_test_harness::ContainerInfo>("web_container_info")
162 .expect("Web container info should be available");
163
164 println!("๐ Web service container: {}", web_info.container_id);
165 println!(" Ports: {}", web_info.ports_summary());
166 println!(" Primary URL: {}", web_info.primary_url().unwrap_or("None"));
167
168 assert!(web_info.host_port_for(80).is_some(), "Web service should have port 80 exposed");
171
172 println!("โ
Web service test passed");
173 Ok(())
174 });
175
176 test("test_database_access", |ctx| {
178 println!("๐งช Testing database access...");
179
180 let db_info = ctx.get_data::<rust_test_harness::ContainerInfo>("db_container_info")
181 .expect("Database container info should be available");
182
183 println!("๐๏ธ Database container: {}", db_info.container_id);
184 println!(" Ports: {}", db_info.ports_summary());
185
186 let postgres_port = db_info.host_port_for(5432)
188 .expect("PostgreSQL port 5432 should be exposed");
189 println!(" PostgreSQL accessible at: localhost:{}", postgres_port);
190
191 assert!(postgres_port > 0, "PostgreSQL port should be valid");
194
195 println!("โ
Database test passed");
196 Ok(())
197 });
198
199 test("test_redis_access", |ctx| {
201 println!("๐งช Testing redis access...");
202
203 let redis_info = ctx.get_data::<rust_test_harness::ContainerInfo>("redis_container_info")
204 .expect("Redis container info should be available");
205
206 println!("๐ด Redis container: {}", redis_info.container_id);
207 println!(" Ports: {}", redis_info.ports_summary());
208
209 let redis_port = redis_info.host_port_for(6379)
211 .expect("Redis port 6379 should be exposed");
212 println!(" Redis accessible at: localhost:{}", redis_port);
213
214 assert!(redis_port > 0, "Redis port should be valid");
217
218 println!("โ
Redis test passed");
219 Ok(())
220 });
221
222 test("test_mixed_port_config", |ctx| {
224 println!("๐งช Testing mixed port configuration...");
225
226 let mixed_info = ctx.get_data::<rust_test_harness::ContainerInfo>("mixed_container_info")
227 .expect("Mixed container info should be available");
228
229 println!("๐ Mixed container: {}", mixed_info.container_id);
230 println!(" Ports: {}", mixed_info.ports_summary());
231
232 let http_port = mixed_info.host_port_for(80)
234 .expect("HTTP port 80 should be exposed");
235 let https_port = mixed_info.host_port_for(443)
236 .expect("HTTPS port 443 should be exposed");
237
238 println!(" HTTP accessible at: localhost:{}", http_port);
239 println!(" HTTPS accessible at: localhost:{}", https_port);
240
241 assert_eq!(http_port, 8080, "Manual port mapping should work");
243
244 assert_ne!(https_port, 8080, "Auto port should be different from manual port");
246
247 println!("โ
Mixed port configuration test passed");
248 Ok(())
249 });
250
251 test("test_container_info_methods", |ctx| {
253 println!("๐งช Testing container info methods...");
254
255 let web_info = ctx.get_data::<rust_test_harness::ContainerInfo>("web_container_info")
256 .expect("Web container info should be available");
257
258 println!("๐ Testing container info methods for: {}", web_info.container_id);
260
261 if let Some(url) = web_info.primary_url() {
263 println!(" Primary URL: {}", url);
264 assert!(url.starts_with("http://localhost:"), "URL should start with http://localhost:");
265 }
266
267 if let Some(url) = web_info.url_for_port(80) {
269 println!(" URL for port 80: {}", url);
270 assert!(url.starts_with("http://localhost:"), "URL should start with http://localhost:");
271 }
272
273 if let Some(host_port) = web_info.host_port_for(80) {
275 println!(" Host port for container port 80: {}", host_port);
276 assert!(host_port > 0, "Host port should be valid");
277 }
278
279 let summary = web_info.ports_summary();
281 println!(" Ports summary: {}", summary);
282 assert!(!summary.is_empty(), "Ports summary should not be empty");
283
284 println!("โ
Container info methods test passed");
285 Ok(())
286 });
287
288 println!("๐ Running tests with auto-port functionality...");
289 println!();
290
291 let config = TestConfig {
293 html_report: Some("auto-port-demo-report.html".to_string()),
294 ..Default::default()
295 };
296
297 let exit_code = run_tests_with_config(config);
298
299 println!();
300 if exit_code == 0 {
301 println!("๐ All tests passed! Auto-port functionality is working correctly.");
302 println!("๐ Check the HTML report for detailed results.");
303 } else {
304 println!("โ Some tests failed. Check the output above for details.");
305 }
306
307 std::process::exit(exit_code);
308}