|
1 | 1 | use super::expression_eval::{eval, ExpressionResult}; |
2 | 2 | use crate::environment::environment::Environment; |
| 3 | +use crate::environment::environment::TestResult; |
3 | 4 | use crate::ir::ast::{Expression, Statement}; |
4 | 5 |
|
5 | 6 | pub enum Computation { |
@@ -32,6 +33,42 @@ pub fn run( |
32 | 33 | } |
33 | 34 | } |
34 | 35 |
|
| 36 | +pub fn run_tests(stmt: &Statement) -> Result<Vec<TestResult>, String> { |
| 37 | + let env = match run(stmt.clone(), &Environment::new()) { |
| 38 | + Ok(env) => env, |
| 39 | + Err(e) => return Err(e), |
| 40 | + }; |
| 41 | + |
| 42 | + let mut results = Vec::new(); |
| 43 | + |
| 44 | + for test in env.scrape_tests() { |
| 45 | + let test_env = env.clone(); |
| 46 | + |
| 47 | + let stmt = match &test.body { |
| 48 | + Some(body) => *body.clone(), |
| 49 | + None => continue, |
| 50 | + }; |
| 51 | + |
| 52 | + match execute(stmt, &test_env) { |
| 53 | + Ok(Computation::Continue(_)) | Ok(Computation::Return(_, _)) => { |
| 54 | + results.push(TestResult::new(test.name.clone(), true, None)); |
| 55 | + } |
| 56 | + Err(e) => { |
| 57 | + results.push(TestResult::new(test.name.clone(), false, Some(e))); |
| 58 | + } |
| 59 | + Ok(Computation::PropagateError(e, _)) => { |
| 60 | + results.push(TestResult::new( |
| 61 | + test.name.clone(), |
| 62 | + false, |
| 63 | + Some(format!("Propagated error: {:?}", e)), |
| 64 | + )); |
| 65 | + } |
| 66 | + } |
| 67 | + } |
| 68 | + |
| 69 | + Ok(results) |
| 70 | +} |
| 71 | + |
35 | 72 | pub fn execute(stmt: Statement, env: &Environment<Expression>) -> Result<Computation, String> { |
36 | 73 | let mut new_env = env.clone(); |
37 | 74 |
|
@@ -1127,4 +1164,173 @@ mod tests { |
1127 | 1164 | } |
1128 | 1165 | } |
1129 | 1166 | } |
| 1167 | + mod run_tests_tests { |
| 1168 | + |
| 1169 | + use super::*; |
| 1170 | + |
| 1171 | + #[test] |
| 1172 | + fn test_run_tests() { |
| 1173 | + let test_def = Statement::TestDef(Function { |
| 1174 | + name: "test_example".to_string(), |
| 1175 | + kind: Type::TVoid, |
| 1176 | + params: Vec::new(), |
| 1177 | + body: Some(Box::new(Statement::Block(vec![Statement::Assert( |
| 1178 | + Box::new(Expression::CTrue), |
| 1179 | + Box::new(Expression::CString("Test passed".to_string())), |
| 1180 | + )]))), |
| 1181 | + }); |
| 1182 | + let programa = Statement::Block(vec![test_def.clone()]); |
| 1183 | + match run_tests(&programa) { |
| 1184 | + Ok(resultados) => { |
| 1185 | + assert_eq!(resultados.len(), 1); |
| 1186 | + assert_eq!(resultados[0].name, "test_example"); |
| 1187 | + assert!(resultados[0].result); |
| 1188 | + assert!(resultados[0].error.is_none()); |
| 1189 | + } |
| 1190 | + _ => panic!("Test execution failed"), |
| 1191 | + } |
| 1192 | + } |
| 1193 | + |
| 1194 | + #[test] |
| 1195 | + fn test_run_tests_scope() { |
| 1196 | + let test_def = Statement::TestDef(Function { |
| 1197 | + name: "test_example".to_string(), |
| 1198 | + kind: Type::TVoid, |
| 1199 | + params: Vec::new(), |
| 1200 | + body: Some(Box::new(Statement::Block(vec![Statement::Assert( |
| 1201 | + Box::new(Expression::CTrue), |
| 1202 | + Box::new(Expression::CString("Test passed".to_string())), |
| 1203 | + )]))), |
| 1204 | + }); |
| 1205 | + |
| 1206 | + let teste_def2 = Statement::TestDef(Function { |
| 1207 | + name: "test_example2".to_string(), |
| 1208 | + kind: Type::TVoid, |
| 1209 | + params: Vec::new(), |
| 1210 | + body: Some(Box::new(Statement::Block(vec![Statement::Assert( |
| 1211 | + Box::new(Expression::CTrue), |
| 1212 | + Box::new(Expression::CString("Test 2 passed".to_string())), |
| 1213 | + )]))), |
| 1214 | + }); |
| 1215 | + |
| 1216 | + let assign1 = Statement::Assignment("x".to_string(), Box::new(Expression::CInt(10))); |
| 1217 | + let assign2 = Statement::Assignment("y".to_string(), Box::new(Expression::CInt(20))); |
| 1218 | + |
| 1219 | + let ifelse = Statement::IfThenElse( |
| 1220 | + Box::new(Expression::CTrue), |
| 1221 | + Box::new(test_def), |
| 1222 | + Some(Box::new(teste_def2)), |
| 1223 | + ); |
| 1224 | + |
| 1225 | + let programa = Statement::Block(vec![assign1, assign2, ifelse]); |
| 1226 | + |
| 1227 | + let resultado_final = match run_tests(&programa) { |
| 1228 | + Ok(resultados) => resultados, |
| 1229 | + Err(e) => panic!("Test execution failed: {}", e), |
| 1230 | + }; |
| 1231 | + |
| 1232 | + assert_eq!(resultado_final.len(), 1); |
| 1233 | + assert_eq!(resultado_final[0].name, "test_example"); |
| 1234 | + assert_eq!(resultado_final[0].result, true); |
| 1235 | + } |
| 1236 | + |
| 1237 | + #[test] |
| 1238 | + fn test_run_tests_with_assert_fail() { |
| 1239 | + let teste1 = Statement::TestDef(Function { |
| 1240 | + name: "test_fail".to_string(), |
| 1241 | + kind: Type::TVoid, |
| 1242 | + params: Vec::new(), |
| 1243 | + body: Some(Box::new(Statement::Block(vec![Statement::Assert( |
| 1244 | + Box::new(Expression::CFalse), |
| 1245 | + Box::new(Expression::CString("This test should fail".to_string())), |
| 1246 | + )]))), |
| 1247 | + }); |
| 1248 | + let programa = Statement::Block(vec![teste1]); |
| 1249 | + match run_tests(&programa) { |
| 1250 | + Ok(resultados) => { |
| 1251 | + assert_eq!(resultados.len(), 1); |
| 1252 | + assert_eq!(resultados[0].name, "test_fail"); |
| 1253 | + assert!(!resultados[0].result); |
| 1254 | + assert_eq!( |
| 1255 | + resultados[0].error, |
| 1256 | + Some("This test should fail".to_string()) |
| 1257 | + ); |
| 1258 | + } |
| 1259 | + Err(e) => panic!("Test execution failed: {}", e), |
| 1260 | + } |
| 1261 | + } |
| 1262 | + |
| 1263 | + #[test] |
| 1264 | + fn test_run_tests_without_asserts() { |
| 1265 | + let teste = Statement::TestDef(Function { |
| 1266 | + name: "test_no_assert".to_string(), |
| 1267 | + kind: Type::TVoid, |
| 1268 | + params: Vec::new(), |
| 1269 | + body: Some(Box::new(Statement::Block(vec![Statement::VarDeclaration( |
| 1270 | + "x".to_string(), |
| 1271 | + Box::new(Expression::CInt(42)), |
| 1272 | + )]))), |
| 1273 | + }); |
| 1274 | + let programa = Statement::Block(vec![teste]); |
| 1275 | + match run_tests(&programa) { |
| 1276 | + Ok(resultados) => { |
| 1277 | + assert_eq!(resultados.len(), 1); |
| 1278 | + assert_eq!(resultados[0].name, "test_no_assert"); |
| 1279 | + assert!(resultados[0].result); |
| 1280 | + assert!(resultados[0].error.is_none()); |
| 1281 | + } |
| 1282 | + Err(e) => panic!("Test execution failed: {}", e), |
| 1283 | + } |
| 1284 | + } |
| 1285 | + |
| 1286 | + #[test] |
| 1287 | + fn test_run_tests_with_multiple_tests() { |
| 1288 | + let teste1 = Statement::TestDef(Function { |
| 1289 | + name: "test_one".to_string(), |
| 1290 | + kind: Type::TVoid, |
| 1291 | + params: Vec::new(), |
| 1292 | + body: Some(Box::new(Statement::Block(vec![Statement::Assert( |
| 1293 | + Box::new(Expression::CTrue), |
| 1294 | + Box::new(Expression::CString("Test one passed".to_string())), |
| 1295 | + )]))), |
| 1296 | + }); |
| 1297 | + let teste2 = Statement::TestDef(Function { |
| 1298 | + name: "test_two".to_string(), |
| 1299 | + kind: Type::TVoid, |
| 1300 | + params: Vec::new(), |
| 1301 | + body: Some(Box::new(Statement::Block(vec![Statement::Assert( |
| 1302 | + Box::new(Expression::CFalse), |
| 1303 | + Box::new(Expression::CString("Test two failed".to_string())), |
| 1304 | + )]))), |
| 1305 | + }); |
| 1306 | + let teste3 = Statement::TestDef(Function { |
| 1307 | + name: "test_three".to_string(), |
| 1308 | + kind: Type::TVoid, |
| 1309 | + params: Vec::new(), |
| 1310 | + body: Some(Box::new(Statement::Block(vec![Statement::Assert( |
| 1311 | + Box::new(Expression::CTrue), |
| 1312 | + Box::new(Expression::CString("Test three passed".to_string())), |
| 1313 | + )]))), |
| 1314 | + }); |
| 1315 | + let programa = Statement::Block(vec![teste1, teste2, teste3]); |
| 1316 | + |
| 1317 | + match run_tests(&programa) { |
| 1318 | + Ok(resultados) => { |
| 1319 | + assert_eq!(resultados.len(), 3); |
| 1320 | + assert_eq!(resultados[0].name, "test_one"); |
| 1321 | + assert!(resultados[0].result); |
| 1322 | + assert!(resultados[0].error.is_none()); |
| 1323 | + |
| 1324 | + assert_eq!(resultados[1].name, "test_two"); |
| 1325 | + assert!(!resultados[1].result); |
| 1326 | + assert_eq!(resultados[1].error, Some("Test two failed".to_string())); |
| 1327 | + |
| 1328 | + assert_eq!(resultados[2].name, "test_three"); |
| 1329 | + assert!(resultados[2].result); |
| 1330 | + assert!(resultados[2].error.is_none()); |
| 1331 | + } |
| 1332 | + Err(e) => panic!("Test execution failed: {}", e), |
| 1333 | + } |
| 1334 | + } |
| 1335 | + } |
1130 | 1336 | } |
0 commit comments