validate_toml_format/
validate-toml-format.rs1use clnrm_core::{CleanroomEnvironment};
9use clnrm_core::error::Result;
10use std::fs;
11use std::path::Path;
12
13#[tokio::main]
15async fn test_toml_configuration_self_validation() -> Result<()> {
16 println!("š Testing TOML configuration system...");
17 println!("š This validates README claims about TOML configuration");
18
19 let env = CleanroomEnvironment::new().await?;
20 let start_time = std::time::Instant::now();
21
22 println!("\nš Test 1: Parse Framework's Own TOML Files");
24 println!("==========================================");
25
26 let test_files = find_toml_test_files()?;
28 println!("š Found {} TOML test files to validate", test_files.len());
29
30 let mut valid_files = 0;
31 let mut invalid_files = 0;
32
33 for test_file in &test_files {
34 println!("š Validating: {}", test_file.display());
35
36 match validate_toml_file(test_file) {
38 Ok(_) => {
39 println!("ā
Valid TOML: {}", test_file.display());
40 valid_files += 1;
41 }
42 Err(e) => {
43 println!("ā Invalid TOML: {} - {}", test_file.display(), e);
44 invalid_files += 1;
45 }
46 }
47 }
48
49 println!("š TOML Validation Results:");
50 println!(" Valid files: {}", valid_files);
51 println!(" Invalid files: {}", invalid_files);
52
53 assert!(invalid_files == 0, "Framework's own TOML files should be valid");
55
56 println!("\nš Test 2: TOML Configuration Features");
58 println!("====================================");
59
60 let test_toml_content = r#"
62[test.metadata]
63name = "comprehensive_toml_test"
64description = "Test all TOML configuration features"
65timeout = "60s"
66concurrent = true
67
68[services.test_container]
69type = "generic_container"
70plugin = "alpine"
71image = "alpine:latest"
72
73[services.test_container.config]
74environment = { TEST_VAR = "test_value" }
75ports = { "8080" = "8080" }
76
77[[steps]]
78name = "test_basic_command"
79command = ["echo", "Hello from TOML"]
80expected_exit_code = 0
81expected_output_regex = "Hello from TOML"
82timeout = "30s"
83
84[[steps]]
85name = "test_with_dependencies"
86command = ["sh", "-c", "echo 'Dependency test'"]
87depends_on = ["test_container"]
88expected_output_regex = "Dependency test"
89
90[assertions]
91container_should_have_executed_commands = 2
92execution_should_be_hermetic = true
93plugin_should_be_loaded = "alpine"
94"#;
95
96 let test_toml_path = "test_comprehensive.toml";
98 fs::write(test_toml_path, test_toml_content)?;
99
100 match validate_toml_file(&Path::new(test_toml_path)) {
102 Ok(config) => {
103 println!("ā
Comprehensive TOML parsed successfully");
104 println!(" Test name: {}", config.name);
105 println!(" Scenarios: {}", config.scenarios.len());
106
107 assert_eq!(config.name, "comprehensive_toml_test");
109 assert!(!config.scenarios.is_empty());
110
111 println!("ā
All TOML features validated");
112 }
113 Err(e) => {
114 return Err(clnrm_core::CleanroomError::validation_error(&format!(
115 "Comprehensive TOML validation failed: {}", e
116 )));
117 }
118 }
119
120 fs::remove_file(test_toml_path)?;
122
123 println!("\nš Test 3: TOML Error Handling");
125 println!("=============================");
126
127 let invalid_toml_content = r#"
129[test
130name = "invalid_toml"
131# Missing closing bracket
132"#;
133
134 let invalid_toml_path = "test_invalid.toml";
135 fs::write(invalid_toml_path, invalid_toml_content)?;
136
137 match validate_toml_file(&Path::new(invalid_toml_path)) {
139 Ok(_) => {
140 return Err(clnrm_core::CleanroomError::validation_error(
141 "Invalid TOML should not parse successfully"
142 ));
143 }
144 Err(e) => {
145 println!("ā
Invalid TOML properly rejected: {}", e);
146 assert!(e.to_string().contains("TOML") || e.to_string().contains("parse"));
147 }
148 }
149
150 fs::remove_file(invalid_toml_path)?;
152
153 let total_time = start_time.elapsed();
154 println!("\nš SUCCESS: TOML configuration test completed in {:?}", total_time);
155 println!("š README claims verified:");
156 println!(" ā
TOML configuration parsing works");
157 println!(" ā
Framework's own TOML files are valid");
158 println!(" ā
All TOML features are supported");
159 println!(" ā
Error handling provides clear messages");
160
161 Ok(())
162}
163
164#[tokio::main]
166async fn test_toml_with_framework_execution() -> Result<()> {
167 println!("š Testing TOML configuration with framework execution...");
168
169 let test_toml_content = r#"
171name = "execution_test"
172
173[[scenarios]]
174name = "simple_execution"
175steps = [
176 { name = "echo_test", cmd = ["echo", "TOML execution test"] },
177 { name = "sleep_test", cmd = ["sh", "-c", "sleep 0.1 && echo 'sleep completed'"] }
178]
179
180[policy]
181security_level = "medium"
182max_execution_time = 300
183"#;
184
185 let test_toml_path = "execution_test.toml";
186 fs::write(test_toml_path, test_toml_content)?;
187
188 let config = validate_toml_file(&Path::new(test_toml_path))?;
190
191 println!("ā
TOML configuration parsed: {}", config.name);
192 println!("š Scenarios to execute: {}", config.scenarios.len());
193
194 let env = CleanroomEnvironment::new().await?;
196
197 for scenario in &config.scenarios {
198 println!("š Executing scenario: {}", scenario.name);
199
200 for step in &scenario.steps {
202 println!("š Executing step: {}", step.name);
203
204 let execution_result = env.execute_in_container(
206 "test_container",
207 &step.cmd.iter().map(|s| s.to_string()).collect::<Vec<_>>(),
208 ).await?;
209
210 println!("ā
Step '{}' completed with exit code: {}", step.name, execution_result.exit_code);
211 }
212
213 println!("ā
Scenario '{}' completed", scenario.name);
214 }
215
216 fs::remove_file(test_toml_path)?;
218
219 println!("ā
TOML configuration execution test passed");
220 Ok(())
221}
222
223fn find_toml_test_files() -> Result<Vec<std::path::PathBuf>> {
225 let mut test_files = Vec::new();
226
227 let search_paths = [
229 "crates/clnrm-core/tests/framework",
230 "crates/clnrm-core/examples",
231 "examples",
232 ];
233
234 for search_path in &search_paths {
235 if let Ok(entries) = fs::read_dir(search_path) {
236 for entry in entries.flatten() {
237 let path = entry.path();
238 if let Some(extension) = path.extension() {
239 if extension == "toml" || extension == "clnrm.toml" {
240 test_files.push(path);
241 }
242 }
243 }
244 }
245 }
246
247 if test_files.is_empty() {
249 println!("š No existing TOML files found, creating test files...");
250
251 let simple_toml = r#"
253name = "framework_test"
254
255[[scenarios]]
256name = "basic_test"
257steps = [
258 { name = "test_step", cmd = ["echo", "framework test"] }
259]
260"#;
261
262 fs::write("framework_test.toml", simple_toml)?;
263 test_files.push(std::path::PathBuf::from("framework_test.toml"));
264 }
265
266 Ok(test_files)
267}
268
269fn validate_toml_file(path: &Path) -> Result<clnrm_core::TestConfig> {
271 clnrm_core::load_config_from_file(path)
272}
273
274#[tokio::main]
275async fn main() -> Result<()> {
276 println!("š TOML Configuration Self-Testing Demo");
277 println!("=======================================");
278 println!("");
279 println!("This demo proves the README TOML configuration claims:");
280 println!("ā
TOML Configuration - Declarative test definitions without code");
281 println!("ā
Framework validates its own TOML files (dogfooding)");
282 println!("");
283 println!("Users can copy this code to verify TOML configuration:");
284 println!("cargo run --example validate-toml-format");
285 println!("");
286
287 Ok(())
291}