//! Integration tests for the `stringscan` command. use std::path::PathBuf; use assert_cmd::Command; use predicates::prelude::*; fn cargo_command() -> Command { Command::cargo_bin("stringscan").expect("binary") } fn workspace_root() -> PathBuf { PathBuf::from(env!("CARGO_MANIFEST_DIR")) .join("..") .join("..") .canonicalize() .expect("workspace root") } fn fixture_relative(path: &str) -> PathBuf { PathBuf::from("fixtures").join(path) } fn fixture(path: &str) -> PathBuf { workspace_root().join(fixture_relative(path)) } fn relative_to_workspace(path: &str) -> String { fixture_relative(path).display().to_string() } fn pwsh_command(script: impl AsRef) -> Command { let mut command = Command::new("pwsh"); command .arg("-NoProfile") .arg("-Command") .arg(script.as_ref()); command } #[test] fn summarizes_high_signal_categories_in_text_mode() { let mut command = cargo_command(); command .current_dir(workspace_root()) .arg(fixture("binaries/stringscan-sample.bin")) .assert() .success() .stdout(predicate::str::contains("binary=true")) .stdout(predicate::str::contains( "categories=bepinex,dll,dotnet,il2cpp,namespace,path,unity,url", )) .stdout(predicate::str::contains("matches=")); } #[test] fn filters_detail_output_by_kind() { let mut command = cargo_command(); command .current_dir(workspace_root()) .arg("--details") .arg("--kind") .arg("bepinex") .arg("--limit") .arg("2") .arg(fixture("binaries/stringscan-sample.bin")) .assert() .success() .stdout(predicate::str::contains("kind=bepinex")) .stdout(predicate::str::contains("BepInEx.Core")) .stdout(predicate::str::contains("Doorstop.Entrypoint")) .stdout(predicate::str::contains("kind=unity").not()); } #[test] fn emits_json_output_shape_for_filtered_matches() { let mut command = cargo_command(); command .current_dir(workspace_root()) .arg("--json") .arg("--kind") .arg("dll") .arg("--limit") .arg("1") .arg(fixture("binaries/stringscan-sample.bin")) .assert() .success() .stdout(predicate::str::contains("\"is_binary\":true")) .stdout(predicate::str::contains("\"string_count\":")) .stdout(predicate::str::contains("\"categories\":[")) .stdout(predicate::str::contains("\"kind\":\"dll\"")) .stdout(predicate::str::contains("\"value\":\"winhttp.dll\"")) .stdout(predicate::str::contains("\"encoding\":\"ascii\"")); } #[test] fn supports_powershell_path_pipeline() { let binary = assert_cmd::cargo::cargo_bin("stringscan"); let input = relative_to_workspace("binaries/stringscan-sample.bin"); let script = format!("'{input}' | & '{}' --json --kind unity", binary.display()); let mut command = pwsh_command(script); command .current_dir(workspace_root()) .assert() .success() .stdout(predicate::str::contains("\"kind\":\"unity\"")) .stdout(predicate::str::contains( "\"value\":\"UnityEngine.CoreModule\"", )); } #[test] fn help_includes_detail_and_powershell_examples() { let mut command = cargo_command(); command .arg("--help") .assert() .success() .stdout(predicate::str::contains("--details")) .stdout(predicate::str::contains("ConvertFrom-Json")) .stdout(predicate::str::contains( "stringscan .\\fixtures\\binaries\\stringscan-sample.bin", )); }