| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- // SPDX-License-Identifier: Apache-2.0
- use assert_cmd::Command;
- use rayon::prelude::*;
- use std::ffi::OsString;
- use std::fs::File;
- use std::io::{BufRead, BufReader};
- use std::{fs, path::PathBuf};
- #[test]
- fn solidity_testcases() {
- run_test_for_path("./tests/codegen_testcases/solidity/");
- }
- #[test]
- fn yul_testcases() {
- run_test_for_path("./tests/codegen_testcases/yul/")
- }
- fn run_test_for_path(path: &str) {
- let mut tests = Vec::new();
- let ext = OsString::from("sol");
- for entry in fs::read_dir(path).unwrap() {
- let path = entry.unwrap().path();
- if path.is_file() && path.extension() == Some(&ext) {
- tests.push(path);
- }
- }
- tests.into_par_iter().for_each(testcase);
- }
- #[derive(Debug)]
- enum Test {
- Check(String),
- NotCheck(String),
- Fail(String),
- Rewind,
- }
- fn testcase(path: PathBuf) {
- // find the args to run.
- println!("testcase: {}", path.display());
- let file = File::open(&path).unwrap();
- let reader = BufReader::new(file);
- let mut command_line: Option<String> = None;
- let mut checks = Vec::new();
- let mut fails = Vec::new();
- let mut read_from = None;
- for line in reader.lines() {
- let mut line = line.unwrap();
- line = line.trim().parse().unwrap();
- if let Some(args) = line.strip_prefix("// RUN: ") {
- assert_eq!(command_line, None);
- command_line = Some(String::from(args));
- } else if let Some(check) = line.strip_prefix("// READ:") {
- read_from = Some(check.trim().to_string());
- } else if let Some(check) = line.strip_prefix("// CHECK:") {
- checks.push(Test::Check(check.trim().to_string()));
- } else if let Some(fail) = line.strip_prefix("// FAIL:") {
- fails.push(Test::Fail(fail.trim().to_string()));
- } else if let Some(not_check) = line.strip_prefix("// NOT-CHECK:") {
- checks.push(Test::NotCheck(not_check.trim().to_string()));
- } else if let Some(check) = line.strip_prefix("// BEGIN-CHECK:") {
- checks.push(Test::Rewind);
- checks.push(Test::Check(check.trim().to_string()));
- }
- }
- let args = command_line.expect("cannot find RUN: line");
- assert_ne!(checks.len() + fails.len(), 0);
- let mut cmd = Command::cargo_bin("solang").unwrap();
- let assert = cmd
- .arg("compile")
- .args(args.split_whitespace())
- .arg(format!("{}", path.canonicalize().unwrap().display()))
- .assert();
- let output = assert.get_output();
- let stdout = String::from_utf8_lossy(&output.stdout);
- let stderr = String::from_utf8_lossy(&output.stderr);
- let mut current_check = 0;
- let mut current_fail = 0;
- let mut current_line = 0;
- let contents = if let Some(file) = read_from {
- fs::read_to_string(file).unwrap()
- } else {
- stdout.to_string()
- };
- let lines: Vec<&str> = contents.split('\n').chain(stderr.split('\n')).collect();
- while current_line < lines.len() {
- let line = lines[current_line];
- match checks.get(current_check) {
- Some(Test::Check(needle)) => {
- if line.contains(needle) {
- current_check += 1;
- }
- }
- Some(Test::NotCheck(needle)) => {
- if !line.contains(needle) {
- current_check += 1;
- // We should not advance line during a not check
- current_line -= 1;
- }
- }
- Some(Test::Rewind) => {
- current_line = 0;
- current_check += 1;
- continue;
- }
- _ => (),
- }
- if let Some(Test::Fail(needle)) = fails.get(current_fail) {
- if line.contains(needle) {
- current_fail += 1;
- }
- }
- current_line += 1;
- }
- if current_check < checks.len() {
- println!("{stderr}");
- println!("OUTPUT: \n===8<===8<===\n{stdout}===8<===8<===\n");
- panic!(
- "NOT FOUND CHECK: {:?}, {}",
- checks[current_check],
- path.display()
- );
- } else if current_fail < fails.len() {
- println!("STDERR: \n===8<===8<===\n{stderr}===8<===8<===\n");
- panic!("NOT FOUND FAIL: {:?}", fails[current_check]);
- }
- }
|