Files
ghidra-cli/tests/project_tests.rs
Alexander Kiselev 3db0af7a3c feat: Add comprehensive E2E test suite and fix CLI argument conflicts
Add E2E test infrastructure:
- DaemonTestHarness for managing daemon lifecycle in tests
- Test fixtures and helpers in tests/common/
- Sample binary fixture for integration tests

Add test coverage:
- command_tests.rs: version, doctor, config commands
- project_tests.rs: project create/list/info/delete, import, analyze
- daemon_tests.rs: daemon start/status/ping/stop/clear-cache
- query_tests.rs: function list, strings, memory, decompile, xref
- unimplemented_tests.rs: 39 tests for graceful error messages

Fix CLI bugs:
- DisasmArgs: rename count to num_instructions (--instructions/-n)
  to avoid conflict with QueryOptions.count
- GraphExportArgs: add unique arg id for format positional to avoid
  conflict with QueryOptions.format

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 04:47:22 -08:00

172 lines
3.7 KiB
Rust

//! Tests for project management commands.
use assert_cmd::Command;
use predicates::prelude::*;
use serial_test::serial;
mod common;
/// Generate unique project name for test isolation.
/// UUID prevents collisions in parallel CI runs.
fn unique_project_name(prefix: &str) -> String {
format!("test-{}-{}", prefix, uuid::Uuid::new_v4())
}
#[test]
fn test_project_create() {
let project = unique_project_name("create");
Command::cargo_bin("ghidra")
.unwrap()
.arg("project")
.arg("create")
.arg(&project)
.assert()
.success()
.stdout(predicate::str::contains("Created project"));
// Cleanup
Command::cargo_bin("ghidra")
.unwrap()
.arg("project")
.arg("delete")
.arg(&project)
.assert()
.success();
}
#[test]
fn test_project_list() {
Command::cargo_bin("ghidra")
.unwrap()
.arg("project")
.arg("list")
.assert()
.success();
}
#[test]
fn test_project_info() {
let project = unique_project_name("info");
Command::cargo_bin("ghidra")
.unwrap()
.arg("project")
.arg("create")
.arg(&project)
.assert()
.success();
Command::cargo_bin("ghidra")
.unwrap()
.arg("project")
.arg("info")
.arg(&project)
.assert()
.success();
// Cleanup
Command::cargo_bin("ghidra")
.unwrap()
.arg("project")
.arg("delete")
.arg(&project)
.assert()
.success();
}
#[test]
fn test_project_lifecycle() {
let project = unique_project_name("lifecycle");
Command::cargo_bin("ghidra")
.unwrap()
.arg("project")
.arg("create")
.arg(&project)
.assert()
.success();
Command::cargo_bin("ghidra")
.unwrap()
.arg("project")
.arg("list")
.assert()
.success()
.stdout(predicate::str::contains(&project));
Command::cargo_bin("ghidra")
.unwrap()
.arg("project")
.arg("delete")
.arg(&project)
.assert()
.success();
}
#[test]
#[serial]
fn test_import_binary() {
let project = unique_project_name("import");
let binary = common::fixture_binary();
Command::cargo_bin("ghidra")
.unwrap()
.arg("import")
.arg(binary.to_str().unwrap())
.arg("--project")
.arg(&project)
.arg("--program")
.arg("sample_binary")
.timeout(std::time::Duration::from_secs(300))
.assert()
.success()
.stdout(predicate::str::contains("Successfully imported"));
Command::cargo_bin("ghidra")
.unwrap()
.arg("project")
.arg("delete")
.arg(&project)
.assert()
.success();
}
#[test]
#[serial]
fn test_analyze_program() {
let project = unique_project_name("analyze");
let binary = common::fixture_binary();
Command::cargo_bin("ghidra")
.unwrap()
.arg("import")
.arg(binary.to_str().unwrap())
.arg("--project")
.arg(&project)
.arg("--program")
.arg("sample_binary")
.timeout(std::time::Duration::from_secs(300))
.assert()
.success();
Command::cargo_bin("ghidra")
.unwrap()
.arg("analyze")
.arg("--project")
.arg(&project)
.arg("--program")
.arg("sample_binary")
.timeout(std::time::Duration::from_secs(300))
.assert()
.success();
Command::cargo_bin("ghidra")
.unwrap()
.arg("project")
.arg("delete")
.arg(&project)
.assert()
.success();
}