Skip to content

refactor: extract CLI tests from main.rs into integration tests #61

@unclesp1d3r

Description

@unclesp1d3r

Summary

src/main.rs is 1,647 lines, of which ~1,100 are colocated #[cfg(test)] tests. The CLI tests use low-level Unix fd manipulation (dup, dup2 via nix crate) for stdin mocking, which is fragile -- evidenced by the LLVM_PROFILE_FILE workaround that skips these tests under llvm-cov instrumentation.

Current Problems

  1. File size: main.rs is 2.7x the 500-600 line guideline
  2. Fragile fd manipulation: dup2_stdin, dup2_stdout, dup2_stderr operations are process-wide and not thread-safe (requires FD_MUTEX and --test-threads=1)
  3. Coverage gaps: Several tests are skipped under llvm-cov due to fd interference
  4. Coupling: Tests directly call internal functions (process_file, validate_arguments) rather than testing the binary interface

Proposal

  1. Extract CLI integration tests into tests/cli_integration.rs using assert_cmd crate
  2. Test the rmagic binary as a subprocess (natural process isolation)
  3. Keep only unit tests for pure functions (e.g., output_format(), validate_arguments()) in main.rs
  4. Use assert_cmd's write_stdin() for stdin testing (no fd manipulation needed)

Example

use assert_cmd::Command;

#[test]
fn test_builtin_elf_detection() {
    Command::cargo_bin("rmagic")
        .unwrap()
        .args(["--use-builtin", "tests/fixtures/sample.elf"])
        .assert()
        .success()
        .stdout(predicates::str::contains("ELF"));
}

#[test]
fn test_stdin_input() {
    Command::cargo_bin("rmagic")
        .unwrap()
        .args(["--use-builtin", "-"])
        .write_stdin(b"\x7fELF")
        .assert()
        .success()
        .stdout(predicates::str::contains("ELF"));
}

Acceptance Criteria

  • main.rs under 600 lines
  • CLI behavior tests moved to tests/cli_integration.rs
  • Stdin tests work reliably under llvm-cov (no LLVM_PROFILE_FILE skip)
  • nix dev-dependency removed (or only used where truly needed)
  • FD_MUTEX and fd manipulation removed
  • All existing test coverage preserved or improved

Metadata

Metadata

Assignees

Labels

cliCommand-line interface and toolsenhancementNew feature or requestpriority:lowNice to have, can defersize:MThis PR changes 30-99 lines, ignoring generated files.testingTest infrastructure and coverage

Type

No fields configured for Task.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions