#![cfg(all(test, feature = "moz_central"))] use ressa::Parser; use resw::{write_str::WriteString, Writer}; use std::path::Path; mod common; #[test] fn moz_central() { pretty_env_logger::try_init().ok(); let moz_central_path = Path::new("./moz-central"); if !moz_central_path.exists() { panic!("Please download the spider monkey JIT Test files to run this test (see CONTRIBUTING.md)"); } let msgs = walk(&moz_central_path); if !msgs.is_empty() { for msg in msgs { eprintln!("{}", msg); } panic!() } } fn walk(path: &Path) -> Vec { let mut ret = vec![]; let files = path .read_dir() .unwrap() .map(|e| e.unwrap().path()) .collect::>(); for path in files { if path.is_file() { if let Some(ext) = path.extension() { if ext == "js" { match run(&path) { Ok(js) => { if let Some(first) = js { match around_once(&first) { Ok(second) => { if let Some(msg) = check_round_trips(&path, &first, &Some(second)) { ret.push(msg); } } Err(e) => { ret.push(format!("{}", e)); if let Some(msg) = check_round_trips(&path, &first, &None) { ret.push(msg) } } } } } Err(e) => { let loc = match &e { common::Error::Ressa( ressa::Error::InvalidGetterParams(ref pos) | ressa::Error::InvalidSetterParams(ref pos) | ressa::Error::NonStrictFeatureInStrictContext(ref pos, _) | ressa::Error::OperationError(ref pos, _) | ressa::Error::Redecl(ref pos, _) | ressa::Error::UnableToReinterpret(ref pos, _, _) | ressa::Error::UnexpectedToken(ref pos, _), ) => { format!("{}:{}:{}", path.display(), pos.line, pos.column) } _ => format!("{}", path.display()), }; log::info!("Failed first pass for\n{}\n{}", loc, e); if let Ok(op) = ::std::process::Command::new("./node_modules/.bin/esparse") .arg(path) .output() { if op.status.success() { ret.push(format!( "1st pass failure parsed by esprima: {}\n\t{}", e, loc )); } } } } } } } else { ret.extend(walk(&path)) } } ret } fn run(file: &Path) -> Result, common::Error> { let contents = ::std::fs::read_to_string(file)?; if contents.starts_with("// |jit-test| error: SyntaxError") || contents.starts_with("|") || contents.starts_with("// |jit-test| error:SyntaxError") { return Ok(None); } if contents.starts_with("// |jit-test| module") { return Ok(None); //these all contain restricted word import as an ident } let ret = around_once(&contents)?; common::round_trip_validate( &contents, false, file.file_stem().unwrap().to_str().unwrap(), )?; Ok(Some(ret)) } fn around_once(js: &str) -> Result { let mut out = WriteString::new(); let mut writer = Writer::new(out.generate_child()); for part in Parser::new(&js)? { let part = part?; writer.write_part(&part).expect("Failed to write part"); } Ok(out .get_string() .expect("invalid utf8 written to write_string")) } fn check_round_trips(path: &Path, first: &str, second: &Option) -> Option { let name = path.file_name().unwrap().to_str().unwrap(); if let Some(ref js) = second { if first != js { common::write_failure(name, first, second); return Some(format!( "Double round trip failed for {0}\ncheck ./{1}.first.js and ./{1}.second.js", path.display(), name )); } } else { common::write_failure(name, first, second); return Some(format!( "Double round trip failed to parse second pass for {}\n chec ./{}.first.js", path.display(), name )); } None }