build.rs 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. use std::env;
  2. use std::fs::File;
  3. use std::io::Write;
  4. use std::path::Path;
  5. const TEST_PREFIX: &str = "
  6. #[cfg(test)]
  7. use pretty_assertions::assert_eq;
  8. use crate::{grammar,lexer};
  9. use std::collections::BTreeMap;
  10. use std::io::Write;
  11. // to let us use pretty_assertions with strings, we write a newtype
  12. // that delegates Debug to Display
  13. #[derive(PartialEq, Eq)]
  14. struct StringWrapper<'a> {
  15. wrapped: &'a str,
  16. }
  17. impl<'a> core::fmt::Debug for StringWrapper<'a> {
  18. fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
  19. core::fmt::Display::fmt(self.wrapped, f)
  20. }
  21. }
  22. fn assert_eq(x: &str, y: &str) {
  23. assert_eq!(StringWrapper {wrapped: x}, StringWrapper {wrapped: y});
  24. }
  25. fn get_expectations(contents: &str) -> BTreeMap<u64, String> {
  26. let map: BTreeMap<String, String> = serde_yaml::from_str(contents).unwrap();
  27. let mut result = BTreeMap::new();
  28. for (k, v) in map.into_iter() {
  29. result.insert(k.parse().unwrap(), v);
  30. }
  31. result
  32. }
  33. ";
  34. const TEST_TEMPLATE: &str = "
  35. #[test]
  36. fn test_%PREFIX%() {
  37. let state = crate::interp::State::new();
  38. let source = include_str!(\"%ROOT%/tests/%PREFIX%.matzo\");
  39. let lexer = lexer::tokens(source);
  40. let file = state.file_table.borrow_mut().add_file(\"input\".to_string(), source.to_string());
  41. let stmts = grammar::StmtsParser::new().parse(&mut state.get_ast().borrow_mut(), file, lexer);
  42. assert!(stmts.is_ok());
  43. let stmts = stmts.unwrap();
  44. if let Ok(expected) = std::fs::read_to_string(\"%ROOT%/tests/%PREFIX%.parsed\") {
  45. let mut buf = Vec::new();
  46. for s in stmts.iter() {
  47. writeln!(buf, \"{:?}\", s.show(&state.get_ast().borrow())).unwrap();
  48. }
  49. assert_eq(
  50. std::str::from_utf8(&buf).unwrap().trim(),
  51. expected.trim(),
  52. );
  53. }
  54. if let Ok(contents) = std::fs::read_to_string(\"%ROOT%/tests/%PREFIX%.output\") {
  55. let expectations = get_expectations(&contents);
  56. for (seed, expectation) in expectations {
  57. let st = crate::interp::State::new_from_seed(seed);
  58. let mut out = Vec::new();
  59. st.run_with_writer(source, &mut out).unwrap();
  60. assert_eq(
  61. std::str::from_utf8(&out).unwrap().trim(),
  62. expectation.trim(),
  63. );
  64. }
  65. }
  66. }
  67. ";
  68. fn main() -> Result<(), Box<dyn std::error::Error>> {
  69. lalrpop::process_root()?;
  70. for file in ["build.rs", "src/grammar.lalrpop"] {
  71. println!("cargo:rerun-if-changed={}", file);
  72. }
  73. vergen::vergen(vergen::Config::default())?;
  74. let out_dir = env::var("OUT_DIR")?;
  75. let manifest_dir = env::var("CARGO_MANIFEST_DIR")?;
  76. let dest = Path::new(&out_dir).join("exp_tests.rs");
  77. let mut test_file = File::create(&dest)?;
  78. writeln!(test_file, "{}", TEST_PREFIX)?;
  79. for exp in std::fs::read_dir("tests")? {
  80. let exp = exp?.path().canonicalize()?;
  81. let fname = exp.file_name().ok_or("bad file name")?.to_string_lossy();
  82. if let Some(prefix) = fname.strip_suffix(".matzo") {
  83. let test = TEST_TEMPLATE
  84. .replace("%FILE%", &fname)
  85. .replace("%PREFIX%", prefix)
  86. .replace("%ROOT%", &manifest_dir);
  87. writeln!(test_file, "{}", test)?;
  88. }
  89. }
  90. Ok(())
  91. }