|
1 | 1 | use crate::lexer::Lexer;
|
2 | 2 | use crate::pt::*;
|
3 | 3 | use crate::solidity;
|
| 4 | +use std::sync::mpsc; |
| 5 | +use std::time::Duration; |
| 6 | +use std::{fs, path::Path, thread}; |
| 7 | +use walkdir::WalkDir; |
4 | 8 |
|
5 | 9 | #[test]
|
6 | 10 | fn parse_test() {
|
@@ -1003,3 +1007,113 @@ contract C {
|
1003 | 1007 | let (actual_parse_tree, _) = crate::parse(src, 0).unwrap();
|
1004 | 1008 | assert_eq!(actual_parse_tree.0.len(), 1);
|
1005 | 1009 | }
|
| 1010 | + |
| 1011 | +#[test] |
| 1012 | +fn test_libsolidity() { |
| 1013 | + fn timeout_after<T, F>(d: Duration, f: F) -> Result<T, String> |
| 1014 | + where |
| 1015 | + T: Send + 'static, |
| 1016 | + F: FnOnce() -> T, |
| 1017 | + F: Send + 'static, |
| 1018 | + { |
| 1019 | + let (done_tx, done_rx) = mpsc::channel(); |
| 1020 | + let handle = thread::spawn(move || { |
| 1021 | + let val = f(); |
| 1022 | + done_tx.send(()).expect("Unable to send completion signal"); |
| 1023 | + val |
| 1024 | + }); |
| 1025 | + |
| 1026 | + match done_rx.recv_timeout(d) { |
| 1027 | + Ok(_) => Ok(handle.join().expect("Thread panicked")), |
| 1028 | + Err(_) => Err(format!("Thread timeout-ed after {d:?}")), |
| 1029 | + } |
| 1030 | + } |
| 1031 | + |
| 1032 | + let source_delimiter = regex::Regex::new(r"====.*====").unwrap(); |
| 1033 | + let error_matcher = regex::Regex::new(r"// ----\r?\n// \w+( \d+)?:").unwrap(); |
| 1034 | + |
| 1035 | + let semantic_tests = WalkDir::new( |
| 1036 | + Path::new(env!("CARGO_MANIFEST_DIR")) |
| 1037 | + .join("testdata/solidity/test/libsolidity/semanticTests"), |
| 1038 | + ) |
| 1039 | + .into_iter() |
| 1040 | + .collect::<Result<Vec<_>, _>>() |
| 1041 | + .unwrap() |
| 1042 | + .into_iter() |
| 1043 | + .map(|entry| (false, entry)); |
| 1044 | + |
| 1045 | + let syntax_tests = WalkDir::new( |
| 1046 | + Path::new(env!("CARGO_MANIFEST_DIR")) |
| 1047 | + .join("testdata/solidity/test/libsolidity/syntaxTests"), |
| 1048 | + ) |
| 1049 | + .into_iter() |
| 1050 | + .collect::<Result<Vec<_>, _>>() |
| 1051 | + .unwrap() |
| 1052 | + .into_iter() |
| 1053 | + .map(|entry| (true, entry)); |
| 1054 | + |
| 1055 | + let errors = semantic_tests |
| 1056 | + .into_iter() |
| 1057 | + .chain(syntax_tests) |
| 1058 | + .map::<Result<_, String>, _>(|(syntax_test, entry)| { |
| 1059 | + if entry.file_name().to_string_lossy().ends_with(".sol") { |
| 1060 | + let source = match fs::read_to_string(entry.path()) { |
| 1061 | + Ok(source) => source, |
| 1062 | + Err(err) if matches!(err.kind(), std::io::ErrorKind::InvalidData) => { |
| 1063 | + return Ok(vec![]) |
| 1064 | + } |
| 1065 | + Err(err) => return Err(err.to_string()), |
| 1066 | + }; |
| 1067 | + |
| 1068 | + let expect_error = syntax_test && error_matcher.is_match(&source); |
| 1069 | + |
| 1070 | + Ok(source_delimiter |
| 1071 | + .split(&source) |
| 1072 | + .filter(|source_part| !source_part.is_empty()) |
| 1073 | + .map(|part| { |
| 1074 | + ( |
| 1075 | + entry.path().to_string_lossy().to_string(), |
| 1076 | + expect_error, |
| 1077 | + part.to_string(), |
| 1078 | + ) |
| 1079 | + }) |
| 1080 | + .collect::<Vec<_>>()) |
| 1081 | + } else { |
| 1082 | + Ok(vec![]) |
| 1083 | + } |
| 1084 | + }) |
| 1085 | + .collect::<Result<Vec<_>, _>>() |
| 1086 | + .unwrap() |
| 1087 | + .into_iter() |
| 1088 | + .flatten() |
| 1089 | + .filter_map(|(path, expect_error, source_part)| { |
| 1090 | + let result = match timeout_after(Duration::from_secs(5), move || { |
| 1091 | + crate::parse(&source_part, 0) |
| 1092 | + }) { |
| 1093 | + Ok(result) => result, |
| 1094 | + Err(err) => return Some(format!("{:?}: \n\t{}", path, err)), |
| 1095 | + }; |
| 1096 | + |
| 1097 | + if let (Err(err), false) = ( |
| 1098 | + result.map_err(|diags| { |
| 1099 | + format!( |
| 1100 | + "{:?}:\n\t{}", |
| 1101 | + path, |
| 1102 | + diags |
| 1103 | + .iter() |
| 1104 | + .map(|diag| format!("{diag:?}")) |
| 1105 | + .collect::<Vec<_>>() |
| 1106 | + .join("\n\t") |
| 1107 | + ) |
| 1108 | + }), |
| 1109 | + expect_error, |
| 1110 | + ) { |
| 1111 | + return Some(err); |
| 1112 | + } |
| 1113 | + |
| 1114 | + None |
| 1115 | + }) |
| 1116 | + .collect::<Vec<_>>(); |
| 1117 | + |
| 1118 | + assert!(errors.is_empty(), "{}", errors.join("\n")); |
| 1119 | +} |
0 commit comments