Documents
Testing
Testing
Type
External
Status
Published
Created
Mar 8, 2026
Updated
Apr 3, 2026
Updated by
Dosu Bot

This document provides comprehensive testing strategies and guidelines for DaemonEye, covering unit testing, integration testing, performance testing, and security testing.

Testing Philosophy#

DaemonEye follows a comprehensive testing strategy that ensures:

  • Reliability: Robust error handling and edge case coverage
  • Performance: Meets performance requirements under load
  • Security: Validates security controls and prevents vulnerabilities
  • Maintainability: Easy to understand and modify tests
  • Coverage: High test coverage across all components

Testing Strategy#

Three-Tier Testing Architecture#

  1. Unit Tests: Test individual components in isolation
  2. Integration Tests: Test component interactions and data flow
  3. End-to-End Tests: Test complete workflows and user scenarios

Testing Pyramid#

┌─────────────────┐
E2E Tests │ Few, slow, expensive
 (Manual)├─────────────────┤
│ Integration │ Some, medium speed
│ Tests │
├─────────────────┤
│ Unit Tests │ Many, fast, cheap
 (Automated)└─────────────────┘

Unit Testing#

Core Testing Framework#

DaemonEye uses Rust's built-in testing framework with additional crates like insta for snapshot testing, tempfile for temporary directories, mockall for mocking, and proptest for property-based testing.
Key test patterns include:

  • Process Collection Tests: Verify process enumeration works correctly
  • Database Operation Tests: Test CRUD operations with in-memory SQLite
  • Serialization Tests: Ensure ProcessInfo round-trips through serde correctly

Mocking and Test Doubles#

Use mockall for external dependencies. Mock the ProcessCollectionService trait to test the agent independently of actual system processes.

Property-Based Testing#

Use proptest for testing complex logic with random inputs, such as verifying serialization round-trips and SQL query validation.

Integration Testing#

Database Integration Tests#

Test database operations with real SQLite including schema creation, data insertion, retrieval, and query execution using TempDir for isolation.

IPC Integration Tests#

Test inter-process communication between server and client components using Unix domain sockets.

Alert Delivery Integration Tests#

Test alert delivery through multiple sinks (syslog, webhook) with realistic alert data.

End-to-End Testing#

CLI Testing#

Use assert_cmd and insta for snapshot testing CLI output:

#[test]
fn test_cli_help() {
    let mut cmd = Command::cargo_bin("daemoneye-cli").unwrap();
    cmd.assert()
        .success()
        .stdout(predicate::str::contains("DaemonEye CLI"));
}

#[test]
fn test_cli_query() {
    let mut cmd = Command::cargo_bin("daemoneye-cli").unwrap();
    cmd.args(&["query", "SELECT * FROM processes LIMIT 1"])
        .assert()
        .success();
}

Full System Testing#

Test complete system workflows by starting procmond and daemoneye-agent, then verifying CLI operations against the running system.

Performance Testing#

Load Testing with Criterion#

use criterion::{Criterion, black_box, criterion_group, criterion_main};

fn benchmark_process_collection(c: &mut Criterion) {
    let mut group = c.benchmark_group("process_collection");
    group.bench_function("collect_processes", |b| {
        b.iter(|| {
            let collector = ProcessCollector::new();
            black_box(collector.collect_processes())
        })
    });
    group.finish();
}

Memory Testing#

Verify that repeated operations do not leak memory by comparing RSS before and after 1000 collection cycles. Memory increase should stay under 10MB.

Stress Testing#

Run collection continuously for 60 seconds to verify system stability under sustained load.

Security Testing#

Fuzz Testing#

Use cargo-fuzz to test ProcessInfo deserialization and SQL query validation with random inputs.

SQL Injection Prevention Testing#

Test various SQL injection attempts against the database layer. Verify that malicious queries are either rejected or executed safely without causing damage.

Security Boundary Testing#

Test privilege dropping to verify the system correctly transitions from elevated to reduced privileges while maintaining core functionality.

Input Validation Testing#

Test both valid and invalid ProcessInfo structures to ensure the validation layer catches issues like empty names, negative CPU usage, and overly long command lines.

Test Configuration#

# test-config.yaml
app:
  log_level: debug
  scan_interval_ms: 1000
  batch_size: 10

database:
  path: ':memory:'
  max_connections: 5
  retention_days: 1

alerting:
  enabled: false

testing:
  enable_mocks: true
  mock_external_services: true
  test_data_dir: /tmp/daemoneye-test
  cleanup_after_tests: true

Continuous Integration#

GitHub Actions Workflow#

name: Tests
on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        rust: [1.87, stable, beta]
        os: [ubuntu-latest, macos-latest, windows-latest]
    steps:
      - uses: actions/checkout@v3
      - name: Install Rust
        uses: actions-rs/toolchain@v1
        with:
          toolchain: ${{ matrix.rust }}
          override: true
      - name: Run tests
        run: |
          cargo test --verbose
          cargo test --verbose --features integration-tests
      - name: Run benchmarks
        run: cargo bench --verbose
      - name: Generate coverage report
        run: |
          cargo install cargo-tarpaulin
          cargo tarpaulin --out Html --output-dir coverage

Test Organization#

tests/
├── unit/
│ ├── collector_tests.rs
│ ├── database_tests.rs
│ └── alert_tests.rs
├── integration/
│ ├── ipc_tests.rs
│ ├── database_tests.rs
│ └── alert_delivery_tests.rs
├── e2e/
│ ├── cli_tests.rs
│ └── system_tests.rs
└── common/
    ├── test_helpers.rs
    └── test_data.rs

This testing documentation provides comprehensive guidance for testing DaemonEye. For additional testing information, consult the specific test files or contact the development team.