|
| 1 | +#[cfg(test)] |
| 2 | +mod tests { |
| 3 | + use std::fs; |
| 4 | + use std::path::{Path, PathBuf}; |
| 5 | + use std::collections::HashMap; |
| 6 | + use crate::{try_run, IncludeDetails}; |
| 7 | + |
| 8 | + fn get_project_root() -> PathBuf { |
| 9 | + let current_dir = std::env::current_dir().unwrap(); |
| 10 | + |
| 11 | + // Navigate up from transpiler directory if needed |
| 12 | + if current_dir.ends_with("transpiler") { |
| 13 | + return current_dir.parent().unwrap().to_path_buf(); |
| 14 | + } |
| 15 | + |
| 16 | + current_dir |
| 17 | + } |
| 18 | + |
| 19 | + fn resolve_lib_modules() -> HashMap<String, String> { |
| 20 | + let project_root = get_project_root(); |
| 21 | + let lib_dir = project_root.join("plonk/lib"); |
| 22 | + |
| 23 | + if !lib_dir.exists() { |
| 24 | + panic!("The 'plonk/lib' directory does not exist at path: {}", lib_dir.display()); |
| 25 | + } |
| 26 | + |
| 27 | + let mut modules = HashMap::new(); |
| 28 | + for entry in fs::read_dir(lib_dir).unwrap() { |
| 29 | + let entry = entry.unwrap(); |
| 30 | + let path = entry.path(); |
| 31 | + |
| 32 | + if path.extension().and_then(|s| s.to_str()) == Some("plonk") { |
| 33 | + let code = fs::read_to_string(path.clone()).expect("cannot read library"); |
| 34 | + let name = path.file_stem().unwrap().to_str().unwrap().to_string(); |
| 35 | + modules.insert(name, code); |
| 36 | + } |
| 37 | + } |
| 38 | + modules |
| 39 | + } |
| 40 | + |
| 41 | + fn get_plonk_files() -> Vec<PathBuf> { |
| 42 | + let project_root = get_project_root(); |
| 43 | + let src_dir = project_root.join("plonk/src"); |
| 44 | + |
| 45 | + if !src_dir.exists() { |
| 46 | + panic!("The 'plonk/src' directory does not exist at path: {}", src_dir.display()); |
| 47 | + } |
| 48 | + |
| 49 | + let mut files = Vec::new(); |
| 50 | + for entry in fs::read_dir(src_dir).unwrap() { |
| 51 | + let entry = entry.unwrap(); |
| 52 | + let path = entry.path(); |
| 53 | + |
| 54 | + if path.extension().and_then(|s| s.to_str()) == Some("plonk") { |
| 55 | + files.push(path); |
| 56 | + } |
| 57 | + } |
| 58 | + |
| 59 | + files |
| 60 | + } |
| 61 | + |
| 62 | + fn create_snapshot_dir() -> PathBuf { |
| 63 | + let project_root = get_project_root(); |
| 64 | + let snapshot_dir = project_root.join("transpiler/snapshots"); |
| 65 | + |
| 66 | + if !snapshot_dir.exists() { |
| 67 | + fs::create_dir_all(&snapshot_dir).expect("Failed to create snapshots directory"); |
| 68 | + } |
| 69 | + |
| 70 | + snapshot_dir |
| 71 | + } |
| 72 | + |
| 73 | + fn save_snapshot(file_path: &Path, content: &str) { |
| 74 | + let snapshot_dir = create_snapshot_dir(); |
| 75 | + |
| 76 | + let base_name = file_path |
| 77 | + .file_stem() |
| 78 | + .unwrap() |
| 79 | + .to_string_lossy(); |
| 80 | + |
| 81 | + let snapshot_path = snapshot_dir.join(format!("{}.snapshot", base_name)); |
| 82 | + fs::write(snapshot_path, content).expect("Failed to write snapshot"); |
| 83 | + } |
| 84 | + |
| 85 | + fn compare_with_snapshot(file_path: &Path, content: &str) -> bool { |
| 86 | + let snapshot_dir = create_snapshot_dir(); |
| 87 | + |
| 88 | + let base_name = file_path |
| 89 | + .file_stem() |
| 90 | + .unwrap() |
| 91 | + .to_string_lossy(); |
| 92 | + |
| 93 | + let snapshot_path = snapshot_dir.join(format!("{}.snapshot", base_name)); |
| 94 | + |
| 95 | + if !snapshot_path.exists() { |
| 96 | + return false; |
| 97 | + } |
| 98 | + |
| 99 | + let snapshot_content = fs::read_to_string(snapshot_path) |
| 100 | + .expect("Failed to read snapshot"); |
| 101 | + |
| 102 | + snapshot_content == content |
| 103 | + } |
| 104 | + |
| 105 | + #[test] |
| 106 | + fn test_all_plonk_files() { |
| 107 | + // Create snapshots directory if it doesn't exist |
| 108 | + create_snapshot_dir(); |
| 109 | + |
| 110 | + // Get all plonk files |
| 111 | + let files = get_plonk_files(); |
| 112 | + let modules = resolve_lib_modules(); |
| 113 | + |
| 114 | + // Test each file |
| 115 | + for file_path in files { |
| 116 | + println!("Testing file: {}", file_path.display()); |
| 117 | + |
| 118 | + // Read the file |
| 119 | + let code = fs::read_to_string(&file_path).expect("Failed to read plonk file"); |
| 120 | + |
| 121 | + // Run the transpiler |
| 122 | + let result = try_run( |
| 123 | + code, |
| 124 | + modules.clone(), |
| 125 | + Some(IncludeDetails::TranspiledScript) |
| 126 | + ); |
| 127 | + |
| 128 | + // Check if the transpiler succeeded |
| 129 | + match result { |
| 130 | + Ok(output) => { |
| 131 | + let file_name = file_path.file_name().unwrap().to_string_lossy(); |
| 132 | + println!(" - Transpilation successful for {}", file_name); |
| 133 | + |
| 134 | + // Create a summary of the output for snapshot testing |
| 135 | + let summary = format!( |
| 136 | + "File: {}\nTranspiled Script Length: {} characters\nFirst 100 chars: {}\n", |
| 137 | + file_name, |
| 138 | + output.transpiled_script.len(), |
| 139 | + &output.transpiled_script.chars().take(100).collect::<String>() |
| 140 | + ); |
| 141 | + |
| 142 | + // Check if we need to update the snapshot |
| 143 | + let update_snapshots = std::env::var("UPDATE_SNAPSHOTS").unwrap_or_default() == "1"; |
| 144 | + |
| 145 | + if update_snapshots { |
| 146 | + save_snapshot(&file_path, &summary); |
| 147 | + println!(" - Updated snapshot for {}", file_name); |
| 148 | + } else { |
| 149 | + // Compare with existing snapshot |
| 150 | + let matches = compare_with_snapshot(&file_path, &summary); |
| 151 | + assert!( |
| 152 | + matches, |
| 153 | + "Output for {} doesn't match snapshot. Run with UPDATE_SNAPSHOTS=1 to update.", |
| 154 | + file_name |
| 155 | + ); |
| 156 | + println!(" - Output matches snapshot for {}", file_name); |
| 157 | + } |
| 158 | + }, |
| 159 | + Err(e) => { |
| 160 | + panic!("Transpilation failed for {}: {:?}", file_path.display(), e); |
| 161 | + } |
| 162 | + } |
| 163 | + } |
| 164 | + } |
| 165 | + |
| 166 | + // Individual tests for each plonk file |
| 167 | + macro_rules! generate_test { |
| 168 | + ($test_name:ident, $file_name:expr) => { |
| 169 | + #[test] |
| 170 | + fn $test_name() { |
| 171 | + let project_root = get_project_root(); |
| 172 | + let file_path = project_root.join(format!("plonk/src/{}", $file_name)); |
| 173 | + |
| 174 | + if !file_path.exists() { |
| 175 | + println!("Skipping test for {} as file doesn't exist", $file_name); |
| 176 | + return; |
| 177 | + } |
| 178 | + |
| 179 | + let code = fs::read_to_string(&file_path).expect("Failed to read plonk file"); |
| 180 | + let modules = resolve_lib_modules(); |
| 181 | + |
| 182 | + let result = try_run( |
| 183 | + code, |
| 184 | + modules, |
| 185 | + Some(IncludeDetails::TranspiledScript) |
| 186 | + ); |
| 187 | + |
| 188 | + assert!(result.is_ok(), "Transpilation failed for {}: {:?}", $file_name, result.err()); |
| 189 | + println!("Transpilation successful for {}", $file_name); |
| 190 | + } |
| 191 | + }; |
| 192 | + } |
| 193 | + |
| 194 | + // Generate individual tests for each known file |
| 195 | + generate_test!(test_fibonacci, "fibonacci.plonk"); |
| 196 | + generate_test!(test_mimc5_feistel, "mimc5-feistel.plonk"); |
| 197 | + generate_test!(test_mimc5, "mimc5.plonk"); |
| 198 | + generate_test!(test_poseidon, "poseidon.plonk"); |
| 199 | + generate_test!(test_simple_arith, "simple_arith.plonk"); |
| 200 | + generate_test!(test_simple_demo, "simple_demo.plonk"); |
| 201 | + generate_test!(test_table_simple, "table_simple.plonk"); |
| 202 | +} |
0 commit comments