# Sauna Driver Testing Guide

This guide provides comprehensive information about the testing framework for the Sauna OpenVR driver. It covers the testing philosophy, test categories, how to run tests, and how to add new tests.

## Testing Framework Overview

The Sauna driver includes a comprehensive testing framework to ensure reliability, performance, and correct functionality. The testing framework is designed to validate all aspects of the driver, from individual components to the complete integrated system.

### Testing Philosophy

The testing approach for the Sauna driver follows these principles:

1. **Comprehensive Coverage**: Tests should cover all components and functionality of the driver.
2. **Isolation**: Unit tests should test components in isolation to identify issues at the component level.
3. **Integration**: Integration tests should verify that components work together correctly.
4. **Performance**: Performance tests should ensure the driver has minimal impact on VR performance.
5. **Validation**: Validation tests should verify that the driver meets its requirements, especially providing IMU data when optical tracking is lost.

### Test Categories

The testing framework includes four main categories of tests:

1. **Unit Tests**: Test individual components in isolation
2. **Integration Tests**: Test how components work together and with SteamVR
3. **Performance Tests**: Measure the performance impact of the driver
4. **Validation Tests**: Verify that the driver meets its requirements

### Test Directory Structure

The tests are organized in the `tests` directory as follows:

```
tests/
├── integration_test.cpp       # Integration tests
├── performance_test.cpp       # Performance tests
├── test_imu_data_provider.cpp # Unit tests for IMU data provider
├── test_lighthouse_driver_wrapper.cpp # Unit tests for lighthouse wrapper
├── test_sauna_device_driver.cpp # Unit tests for device driver
├── test_utils.cpp             # Test utilities implementation
├── test_utils.h               # Test utilities interface
├── validation_test.cpp        # Validation tests
├── run_integration_tests.bat  # Script to run integration tests
├── run_performance_tests.bat  # Script to run performance tests
├── run_unit_tests.bat         # Script to run unit tests
├── run_validation_tests.bat   # Script to run validation tests
└── README.md                  # Testing framework documentation
```

## Running Tests

### Prerequisites

Before running the tests, ensure you have the following:

- Visual Studio with C++ development tools installed
- SteamVR installed (for integration and validation tests)
- VR headset connected (for integration and validation tests)
- The Sauna driver built and installed

### Running Unit Tests

Unit tests verify that each component of the driver works correctly in isolation.

To run all unit tests:

1. Open a command prompt in the `drivers\sauna\tests` directory
2. Run the following command:
   ```
   run_unit_tests.bat
   ```

This will build and run all unit tests, which test each component in isolation.

The unit tests include:

- **IMUDataProvider Tests**: Test the IMU data provider functionality
- **LighthouseDriverWrapper Tests**: Test the lighthouse driver wrapper functionality
- **SaunaDeviceDriver Tests**: Test the custom device driver functionality

### Running Integration Tests

Integration tests verify that the complete driver works with SteamVR.

To run integration tests:

1. Ensure SteamVR is installed but not running
2. Open a command prompt in the `drivers\sauna\tests` directory
3. Run the following command:
   ```
   run_integration_tests.bat
   ```

The integration tests will guide you through the process step by step. They verify that:

- The driver can load and initialize
- The driver can communicate with the lighthouse driver
- The driver can register devices
- The driver can expose IMU data

### Running Performance Tests

Performance tests measure the impact of the driver on CPU usage, memory usage, latency, and IMU data throughput.

To run performance tests:

1. Open a command prompt in the `drivers\sauna\tests` directory
2. Run the following command:
   ```
   run_performance_tests.bat
   ```

The performance tests will:

1. Measure CPU usage with and without the driver
2. Measure memory usage with and without the driver
3. Measure latency impact of the driver
4. Measure IMU data throughput

Results will be saved to a performance report file in the `tests` directory.

### Running Validation Tests

Validation tests verify that IMU data is available when optical tracking is lost.

To run validation tests:

1. Ensure SteamVR is installed
2. Connect your VR headset
3. Open a command prompt in the `drivers\sauna\tests` directory
4. Run the following command:
   ```
   run_validation_tests.bat
   ```

The validation tests require manual intervention to simulate tracking loss. You will be guided through the process of:

1. Starting SteamVR
2. Covering the headset sensors to block optical tracking
3. Verifying that IMU data is still available
4. Uncovering the sensors to restore tracking
5. Verifying that normal tracking is restored

## Interpreting Test Results

### Unit Test Results

Unit tests will output pass/fail results for each test case. A successful test run will show:

```
=== Running Test Suite: IMUDataProvider Tests ===
Running test: Initialize... PASSED (5ms)
Running test: RegisterDevice... PASSED (3ms)
Running test: AddAndGetIMUSample... PASSED (4ms)
Running test: QueueBehavior... PASSED (12ms)
Running test: MultipleDevices... PASSED (7ms)
Running test: Shutdown... PASSED (2ms)
=== Test Suite Summary: IMUDataProvider Tests ===
  Total Tests: 6
  Passed: 6
  Failed: 0
```

If a test fails, it will show the reason for the failure:

```
Running test: QueueBehavior... FAILED (15ms)
  Error: Queue behavior incorrect. Expected time: 3.500000, Actual time: 3.000000
```

### Integration Test Results

Integration tests will guide you through the process and report success or failure at each step. A successful integration test will show:

```
=== Running Integration Tests ===
Step 1: Loading driver... PASSED
Step 2: Initializing driver... PASSED
Step 3: Communicating with lighthouse driver... PASSED
Step 4: Registering devices... PASSED
Step 5: Exposing IMU data... PASSED
=== Integration Tests Summary ===
All tests passed!
```

### Performance Test Results

Performance tests will generate a report file with detailed measurements. The report will include:

```
=== Performance Test Results ===
CPU Usage:
  Without driver: 2.5%
  With driver: 2.8%
  Difference: +0.3%

Memory Usage:
  Without driver: 245.6 MB
  With driver: 247.2 MB
  Difference: +1.6 MB

Latency:
  Without driver: 11.2 ms
  With driver: 11.5 ms
  Difference: +0.3 ms

IMU Data Throughput:
  Samples per second: 1000
  Data rate: 48 KB/s
```

### Validation Test Results

Validation tests will report whether IMU data is available during optical tracking loss and whether the driver correctly detects when optical tracking is restored:

```
=== Running Validation Tests ===
Step 1: Starting SteamVR... DONE
Step 2: Please cover the headset sensors to block optical tracking...
Step 3: Checking if IMU data is available... YES
Step 4: Please uncover the sensors to restore tracking...
Step 5: Checking if normal tracking is restored... YES
=== Validation Tests Summary ===
All tests passed!
```

## Test Types

### Unit Tests

Unit tests verify that each component of the driver works correctly in isolation. They are implemented using a simple test framework defined in `test_utils.h`.

#### IMUDataProvider Tests

The IMU data provider tests verify that:

- The provider can initialize and shutdown correctly
- Devices can be registered with the provider
- IMU samples can be added and retrieved
- The queue behavior is correct (limited size, FIFO)
- Multiple devices can be supported
- The provider cleans up correctly on shutdown

#### LighthouseDriverWrapper Tests

The lighthouse driver wrapper tests verify that:

- The wrapper can load the lighthouse driver
- The wrapper can initialize and shutdown correctly
- The wrapper correctly forwards calls to the lighthouse driver
- The wrapper handles errors correctly

#### SaunaDeviceDriver Tests

The custom device driver tests verify that:

- The driver can activate and deactivate correctly
- The driver correctly wraps the original device driver
- The driver can access IMU data
- The driver correctly integrates IMU data when optical tracking is lost
- The driver implements the custom IMU interface correctly

### Integration Tests

Integration tests verify that the complete driver works with SteamVR. They test:

- Loading the driver
- Initializing the driver
- Communication with the lighthouse driver
- Device registration
- IMU data exposure

### Performance Tests

Performance tests measure the impact of the driver on:

- CPU usage
- Memory usage
- Latency
- IMU data throughput

The performance tests use the `PerformanceTimer` and `MemoryTracker` classes defined in `test_utils.h` to measure performance metrics.

### Validation Tests

Validation tests verify that IMU data is available when optical tracking is lost. They require manual intervention to:

1. Cover the headset sensors to block optical tracking
2. Verify that IMU data is still available
3. Uncover the sensors to restore tracking
4. Verify that normal tracking is restored

## Adding New Tests

### Creating Unit Tests

To add a new unit test:

1. Create a new test file or add to an existing one
2. Define a test class with test methods
3. Add the test methods to the test suite
4. Update the `run_unit_tests.bat` script if needed

Example:

```cpp
#include "test_utils.h"
#include "../your_component.h"

using namespace SaunaTest;

class YourComponentTest {
private:
    std::unique_ptr<YourComponent> component;

public:
    YourComponentTest() {
        component = std::make_unique<YourComponent>();
    }

    TestResult testSomeFeature() {
        bool result = component->SomeFeature();
        return assertTrue(result, "Feature failed");
    }

    void runAllTests() {
        TestSuite suite("YourComponent Tests");
        suite.addTest("SomeFeature", [this]() { return testSomeFeature(); });
        suite.runAll();
    }
};

int your_component_test_main(int argc, char** argv) {
    YourComponentTest test;
    test.runAllTests();
    return 0;
}

int main(int argc, char** argv) {
    return your_component_test_main(argc, argv);
}
```

### Creating Integration Tests

To add a new integration test:

1. Add a new test step to `integration_test.cpp`
2. Update the integration test process to include the new step
3. Add appropriate success/failure reporting

Example:

```cpp
bool TestNewFeature() {
    printf("Testing new feature...\n");
    
    // Test implementation
    bool success = true;
    
    if (success) {
        printf("New feature test PASSED\n");
    } else {
        printf("New feature test FAILED\n");
    }
    
    return success;
}

int main(int argc, char** argv) {
    printf("=== Running Integration Tests ===\n");
    
    bool allPassed = true;
    
    // Existing tests
    allPassed &= TestLoadDriver();
    allPassed &= TestInitializeDriver();
    
    // New test
    allPassed &= TestNewFeature();
    
    printf("=== Integration Tests Summary ===\n");
    if (allPassed) {
        printf("All tests passed!\n");
    } else {
        printf("Some tests failed!\n");
    }
    
    return allPassed ? 0 : 1;
}
```

### Creating Performance Tests

To add a new performance test:

1. Add a new test function to `performance_test.cpp`
2. Update the performance test process to include the new test
3. Add appropriate metrics collection and reporting

Example:

```cpp
void TestNewPerformanceMetric() {
    printf("Testing new performance metric...\n");
    
    // Setup
    // ...
    
    // Measure without driver
    {
        PerformanceTimer timer("Without driver");
        // Test code
    }
    double withoutDriver = someMetric;
    
    // Measure with driver
    {
        PerformanceTimer timer("With driver");
        // Test code
    }
    double withDriver = someMetric;
    
    // Report results
    printf("New Metric:\n");
    printf("  Without driver: %.2f\n", withoutDriver);
    printf("  With driver: %.2f\n", withDriver);
    printf("  Difference: %+.2f\n", withDriver - withoutDriver);
}

int main(int argc, char** argv) {
    printf("=== Running Performance Tests ===\n");
    
    // Existing tests
    TestCPUUsage();
    TestMemoryUsage();
    
    // New test
    TestNewPerformanceMetric();
    
    printf("=== Performance Tests Complete ===\n");
    printf("Results saved to performance_report.txt\n");
    
    return 0;
}
```

### Creating Validation Tests

To add a new validation test:

1. Add a new test step to `validation_test.cpp`
2. Update the validation test process to include the new step
3. Add appropriate user instructions and success/failure reporting

Example:

```cpp
bool TestNewValidationScenario() {
    printf("Testing new validation scenario...\n");
    printf("Please perform some specific action...\n");
    
    // Wait for user to perform the action
    printf("Press Enter when ready...\n");
    getchar();
    
    // Test implementation
    bool success = true;
    
    if (success) {
        printf("New validation scenario PASSED\n");
    } else {
        printf("New validation scenario FAILED\n");
    }
    
    return success;
}

int main(int argc, char** argv) {
    printf("=== Running Validation Tests ===\n");
    
    bool allPassed = true;
    
    // Existing tests
    allPassed &= TestIMUDataDuringTrackingLoss();
    
    // New test
    allPassed &= TestNewValidationScenario();
    
    printf("=== Validation Tests Summary ===\n");
    if (allPassed) {
        printf("All tests passed!\n");
    } else {
        printf("Some tests failed!\n");
    }
    
    return allPassed ? 0 : 1;
}
```

## Best Practices

When working with the testing framework, follow these best practices:

1. **Write Tests First**: Consider writing tests before implementing new features (Test-Driven Development).

2. **Test Edge Cases**: Include tests for edge cases and error conditions, not just the happy path.

3. **Keep Tests Independent**: Each test should be independent and not rely on the state from other tests.

4. **Use Descriptive Names**: Use descriptive names for test methods and test cases to make it clear what is being tested.

5. **Check Return Values**: Always check return values and verify that they match the expected results.

6. **Test Performance Impact**: When adding new features, always measure the performance impact.

7. **Automate When Possible**: Automate as much of the testing process as possible to make it easier to run tests regularly.

8. **Document Test Requirements**: Clearly document any special requirements for running tests, such as hardware or software dependencies.

9. **Keep Tests Up to Date**: Update tests when the code changes to ensure they remain valid.

10. **Review Test Results**: Regularly review test results to identify trends or recurring issues.