diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 99add77..f35e6e0 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,4 +1,4 @@ -name: ci +name: tests on: push: @@ -6,8 +6,8 @@ on: pull_request: jobs: - ci: - name: ci + tests: + name: tests runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -37,7 +37,6 @@ jobs: run: | cargo fmt --all -- --check cargo clippy - + - name: test - run: cargo test --all - + run: cargo test --all -- --skip third_party diff --git a/.github/workflows/third-party-tests.yml b/.github/workflows/third-party-tests.yml new file mode 100644 index 0000000..4dfe2d8 --- /dev/null +++ b/.github/workflows/third-party-tests.yml @@ -0,0 +1,35 @@ +name: third-party + +on: + push: + branches: [main] + pull_request: + +jobs: + third-party-tests: + name: third-party + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + rust: + - 'stable' + os: + - 'ubuntu-latest' + + steps: + - name: checkout + uses: actions/checkout@v3 + + - name: install rust + uses: actions-rs/toolchain@v1 + with: + toolchain: ${{ matrix.rust }} + override: true + components: rustfmt, clippy + + - name: cache + uses: Swatinem/rust-cache@v2.0.0 + + - name: test third-party + run: cargo test third_party diff --git a/tests/third_party_tests.rs b/tests/third_party_tests.rs new file mode 100644 index 0000000..ca3d098 --- /dev/null +++ b/tests/third_party_tests.rs @@ -0,0 +1,91 @@ +use std::env; +use std::fs; +use std::path::PathBuf; +use std::process::Command; + +use php_parser_rs::Lexer; +use php_parser_rs::Parser; + +#[test] +fn third_party_php_standard_library() { + test_repository( + "php-standard-library", + "https://github.com/azjezz/psl.git", + "2.2.x", + &["src", "tests", "examples"], + ); +} + +fn test_repository(name: &str, repository: &str, branch: &str, directories: &[&str]) { + let out_dir = env::var_os("OUT_DIR").expect("failed to get OUT_DIR"); + let out_path = PathBuf::from(out_dir).join(name); + + if !out_path.exists() { + let output = Command::new("git") + .arg("clone") + .arg("--depth") + .arg("1") + .arg("-b") + .arg(branch) + .arg(repository) + .arg(&out_path) + .output() + .expect("failed to run git."); + + if !output.status.success() { + panic!("failed to clone repository: {:#?}", output) + } + } + + for dir in directories { + test_directory(out_path.clone(), out_path.join(dir)); + } +} + +fn test_directory(root: PathBuf, directory: PathBuf) { + let mut entries = fs::read_dir(directory) + .unwrap() + .flatten() + .map(|entry| entry.path()) + .collect::>(); + + entries.sort(); + + for entry in entries { + if entry.is_dir() { + test_directory(root.clone(), entry); + + continue; + } + + if entry.is_file() && entry.extension().unwrap_or_default() == "php" { + let name_entry = entry.clone(); + let fullanme_string = name_entry.to_string_lossy(); + let name = fullanme_string + .strip_prefix(root.to_str().unwrap()) + .unwrap(); + + test_file(name, entry); + } + } +} + +fn test_file(name: &str, filename: PathBuf) { + let code = std::fs::read_to_string(&filename).unwrap(); + + Lexer::new(None) + .tokenize(code.as_bytes()) + .map(|tokens| { + Parser::new(None) + .parse(tokens) + .map(|_| { + println!("✅ successfully parsed file: `\"{}\"`.", name); + }) + .unwrap_or_else(|error| { + panic!("❌ failed to parse file: `\"{name}\"`, error: {error:?}") + }) + }) + .unwrap_or_else(|error| { + panic!("❌ failed to tokenize file: `\"{name}\"`, error: {error:?}") + }); +}