codegen.rs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. // SPDX-License-Identifier: Apache-2.0
  2. use assert_cmd::Command;
  3. use rayon::prelude::*;
  4. use std::ffi::OsString;
  5. use std::fs::File;
  6. use std::io::{BufRead, BufReader};
  7. use std::{fs, path::PathBuf};
  8. #[test]
  9. fn solidity_testcases() {
  10. run_test_for_path("./tests/codegen_testcases/solidity/");
  11. }
  12. #[test]
  13. fn yul_testcases() {
  14. run_test_for_path("./tests/codegen_testcases/yul/")
  15. }
  16. fn run_test_for_path(path: &str) {
  17. let mut tests = Vec::new();
  18. let ext = OsString::from("sol");
  19. for entry in fs::read_dir(path).unwrap() {
  20. let path = entry.unwrap().path();
  21. if path.is_file() && path.extension() == Some(&ext) {
  22. tests.push(path);
  23. }
  24. }
  25. tests.into_par_iter().for_each(testcase);
  26. }
  27. #[derive(Debug)]
  28. enum Test {
  29. Check(String),
  30. NotCheck(String),
  31. Fail(String),
  32. Rewind,
  33. }
  34. fn testcase(path: PathBuf) {
  35. // find the args to run.
  36. println!("testcase: {}", path.display());
  37. let file = File::open(&path).unwrap();
  38. let reader = BufReader::new(file);
  39. let mut command_line: Option<String> = None;
  40. let mut checks = Vec::new();
  41. let mut fails = Vec::new();
  42. let mut read_from = None;
  43. for line in reader.lines() {
  44. let mut line = line.unwrap();
  45. line = line.trim().parse().unwrap();
  46. if let Some(args) = line.strip_prefix("// RUN: ") {
  47. assert_eq!(command_line, None);
  48. command_line = Some(String::from(args));
  49. } else if let Some(check) = line.strip_prefix("// READ:") {
  50. read_from = Some(check.trim().to_string());
  51. } else if let Some(check) = line.strip_prefix("// CHECK:") {
  52. checks.push(Test::Check(check.trim().to_string()));
  53. } else if let Some(fail) = line.strip_prefix("// FAIL:") {
  54. fails.push(Test::Fail(fail.trim().to_string()));
  55. } else if let Some(not_check) = line.strip_prefix("// NOT-CHECK:") {
  56. checks.push(Test::NotCheck(not_check.trim().to_string()));
  57. } else if let Some(check) = line.strip_prefix("// BEGIN-CHECK:") {
  58. checks.push(Test::Rewind);
  59. checks.push(Test::Check(check.trim().to_string()));
  60. }
  61. }
  62. let args = command_line.expect("cannot find RUN: line");
  63. assert_ne!(checks.len() + fails.len(), 0);
  64. let mut cmd = Command::cargo_bin("solang").unwrap();
  65. let assert = cmd
  66. .arg("compile")
  67. .args(args.split_whitespace())
  68. .arg(format!("{}", path.canonicalize().unwrap().display()))
  69. .assert();
  70. let output = assert.get_output();
  71. let stdout = String::from_utf8_lossy(&output.stdout);
  72. let stderr = String::from_utf8_lossy(&output.stderr);
  73. let mut current_check = 0;
  74. let mut current_fail = 0;
  75. let mut current_line = 0;
  76. let contents = if let Some(file) = read_from {
  77. fs::read_to_string(file).unwrap()
  78. } else {
  79. stdout.to_string()
  80. };
  81. let lines: Vec<&str> = contents.split('\n').chain(stderr.split('\n')).collect();
  82. while current_line < lines.len() {
  83. let line = lines[current_line];
  84. match checks.get(current_check) {
  85. Some(Test::Check(needle)) => {
  86. if line.contains(needle) {
  87. current_check += 1;
  88. }
  89. }
  90. Some(Test::NotCheck(needle)) => {
  91. if !line.contains(needle) {
  92. current_check += 1;
  93. // We should not advance line during a not check
  94. current_line -= 1;
  95. }
  96. }
  97. Some(Test::Rewind) => {
  98. current_line = 0;
  99. current_check += 1;
  100. continue;
  101. }
  102. _ => (),
  103. }
  104. if let Some(Test::Fail(needle)) = fails.get(current_fail) {
  105. if line.contains(needle) {
  106. current_fail += 1;
  107. }
  108. }
  109. current_line += 1;
  110. }
  111. if current_check < checks.len() {
  112. println!("{stderr}");
  113. println!("OUTPUT: \n===8<===8<===\n{stdout}===8<===8<===\n");
  114. panic!("NOT FOUND CHECK: {:?}", checks[current_check]);
  115. } else if current_fail < fails.len() {
  116. println!("STDERR: \n===8<===8<===\n{stderr}===8<===8<===\n");
  117. panic!("NOT FOUND FAIL: {:?}", fails[current_check]);
  118. }
  119. }