user_specified_ports/
user_specified_ports.rs1use rust_test_harness::{test, before_each, after_each, run_tests_with_config, TestConfig, ContainerConfig};
10use std::time::Duration;
11
12fn main() {
13 println!("๐ง User-Specified Ports Example");
14 println!("==============================");
15 println!();
16
17 let postgres_container = ContainerConfig::new("postgres:13-alpine")
19 .port(5432, 5432) .env("POSTGRES_PASSWORD", "testpass")
21 .env("POSTGRES_DB", "testdb")
22 .name("postgres_test")
23 .ready_timeout(Duration::from_secs(15));
24
25 let web_container = ContainerConfig::new("nginx:alpine")
27 .port(8080, 80) .name("nginx_test")
29 .ready_timeout(Duration::from_secs(10));
30
31 let api_container = ContainerConfig::new("httpd:alpine")
33 .port(3000, 80) .auto_port(443) .auto_port(9090) .name("api_test")
37 .ready_timeout(Duration::from_secs(10));
38
39 println!("๐ Container Configurations:");
40 println!("1. PostgreSQL: Fixed on localhost:5432 (standard PostgreSQL port)");
41 println!("2. Web Service: Fixed on localhost:8080");
42 println!("3. API Service: Fixed localhost:3000, auto-assigned for 443 and 9090");
43 println!();
44
45 let postgres_before = postgres_container.clone();
47 let web_before = web_container.clone();
48 let api_before = api_container.clone();
49
50 before_each(move |ctx| {
52 println!("๐ before_each: Starting containers with specified ports...");
53
54 let postgres_info = postgres_before.start()
56 .map_err(|e| format!("Failed to start PostgreSQL container: {}", e))?;
57 ctx.set_data("postgres_container_info", postgres_info.clone());
58
59 println!("โ
PostgreSQL started: {}", postgres_info.container_id);
60 println!(" ๐ Port mappings: {}", postgres_info.ports_summary());
61 println!(" ๐๏ธ Database URL: postgresql://postgres:testpass@localhost:5432/testdb");
62
63 let web_info = web_before.start()
65 .map_err(|e| format!("Failed to start web container: {}", e))?;
66 ctx.set_data("web_container_info", web_info.clone());
67
68 println!("โ
Web service started: {}", web_info.container_id);
69 println!(" ๐ Port mappings: {}", web_info.ports_summary());
70 println!(" ๐ Web accessible at: http://localhost:8080");
71
72 let api_info = api_before.start()
74 .map_err(|e| format!("Failed to start API container: {}", e))?;
75 ctx.set_data("api_container_info", api_info.clone());
76
77 println!("โ
API service started: {}", api_info.container_id);
78 println!(" ๐ Port mappings: {}", api_info.ports_summary());
79 println!(" ๐ API accessible at: http://localhost:3000");
80 if let Some(https_port) = api_info.host_port_for(443) {
81 println!(" ๐ HTTPS accessible at: https://localhost:{}", https_port);
82 }
83 if let Some(metrics_port) = api_info.host_port_for(9090) {
84 println!(" ๐ Metrics accessible at: http://localhost:{}/metrics", metrics_port);
85 }
86
87 Ok(())
88 });
89
90 let postgres_after = postgres_container.clone();
92 let web_after = web_container.clone();
93 let api_after = api_container.clone();
94
95 after_each(move |ctx| {
96 println!("๐งน after_each: Cleaning up containers...");
97
98 if let Some(postgres_info) = ctx.get_data::<rust_test_harness::ContainerInfo>("postgres_container_info") {
99 let _ = postgres_after.stop(&postgres_info.container_id);
100 println!("๐ Stopped PostgreSQL container");
101 }
102
103 if let Some(web_info) = ctx.get_data::<rust_test_harness::ContainerInfo>("web_container_info") {
104 let _ = web_after.stop(&web_info.container_id);
105 println!("๐ Stopped web container");
106 }
107
108 if let Some(api_info) = ctx.get_data::<rust_test_harness::ContainerInfo>("api_container_info") {
109 let _ = api_after.stop(&api_info.container_id);
110 println!("๐ Stopped API container");
111 }
112
113 println!("โ
All containers cleaned up!");
114 Ok(())
115 });
116
117 test("test_database_connection", |ctx| {
119 println!("๐งช Testing database connection on fixed port 5432...");
120
121 if let Some(postgres_info) = ctx.get_data::<rust_test_harness::ContainerInfo>("postgres_container_info") {
122 assert_eq!(postgres_info.host_port_for(5432), Some(5432));
123 assert_eq!(postgres_info.url_for_port(5432), Some("localhost:5432".to_string()));
124 println!("โ
Database is accessible on the expected port 5432");
125 } else {
126 return Err("PostgreSQL container info not found".into());
127 }
128
129 Ok(())
130 });
131
132 test("test_web_service_fixed_port", |ctx| {
134 println!("๐งช Testing web service on fixed port 8080...");
135
136 if let Some(web_info) = ctx.get_data::<rust_test_harness::ContainerInfo>("web_container_info") {
137 assert_eq!(web_info.host_port_for(80), Some(8080));
138 assert_eq!(web_info.url_for_port(80), Some("localhost:8080".to_string()));
139 println!("โ
Web service is accessible on the expected port 8080");
140 } else {
141 return Err("Web container info not found".into());
142 }
143
144 Ok(())
145 });
146
147 test("test_mixed_port_configuration", |ctx| {
149 println!("๐งช Testing mixed port configuration (fixed + auto)...");
150
151 if let Some(api_info) = ctx.get_data::<rust_test_harness::ContainerInfo>("api_container_info") {
152 assert_eq!(api_info.host_port_for(80), Some(3000));
154 assert_eq!(api_info.url_for_port(80), Some("localhost:3000".to_string()));
155 println!("โ
Fixed port 3000 -> 80 is working");
156
157 if let Some(https_port) = api_info.host_port_for(443) {
159 assert!(https_port > 1024); println!("โ
Auto-assigned HTTPS port: {}", https_port);
161 }
162
163 if let Some(metrics_port) = api_info.host_port_for(9090) {
164 assert!(metrics_port > 1024); println!("โ
Auto-assigned metrics port: {}", metrics_port);
166 }
167
168 println!("โ
Mixed configuration is working correctly");
169 } else {
170 return Err("API container info not found".into());
171 }
172
173 Ok(())
174 });
175
176 println!("๐ Running user-specified ports tests...");
177
178 let config = TestConfig {
179 html_report: Some("user-specified-ports-report.html".to_string()),
180 ..Default::default()
181 };
182
183 let exit_code = run_tests_with_config(config);
184
185 println!();
186 println!("๐ Tests completed!");
187 println!("๐ Check the HTML report for detailed results.");
188 println!();
189 println!("๐ก Key Takeaways:");
190 println!(" โข Use .port(host_port, container_port) for fixed port mappings");
191 println!(" โข Use .auto_port(container_port) for automatic port assignment");
192 println!(" โข Mix both approaches for maximum flexibility");
193 println!(" โข Fixed ports are great for services with standard ports (5432, 3306, etc.)");
194 println!(" โข Auto-ports prevent conflicts in parallel test environments");
195
196 std::process::exit(exit_code);
197}