codegen.rs 4.1 KB

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