codegen.rs 3.8 KB

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