#include "../lighthouse_driver_wrapper.h" #include "../imu_data_provider.h" #include "../sauna_device_driver.h" #include "test_utils.h" #include #include #include #include #include using namespace SaunaTest; using namespace sauna; // Integration test for the complete sauna driver class SaunaDriverIntegrationTest { private: std::unique_ptr lighthouseWrapper; std::unique_ptr imuProvider; public: SaunaDriverIntegrationTest() { lighthouseWrapper = std::make_unique(); imuProvider = std::make_unique(); } ~SaunaDriverIntegrationTest() { // Clean up lighthouseWrapper->Shutdown(); imuProvider->Shutdown(); } TestResult testDriverInitialization() { // Initialize the components bool lighthouseInitResult = lighthouseWrapper->Initialize(); bool imuInitResult = imuProvider->Initialize(); if (!lighthouseInitResult) { std::cout << "Lighthouse driver initialization failed - this may be expected if the driver is not installed" << std::endl; return TestResult(true, "Lighthouse initialization test skipped"); } if (!imuInitResult) { return TestResult(false, "IMU data provider initialization failed"); } return TestResult(true, "Driver initialization succeeded"); } TestResult testDeviceRegistration() { // Initialize the components bool lighthouseInitResult = lighthouseWrapper->Initialize(); bool imuInitResult = imuProvider->Initialize(); if (!lighthouseInitResult) { std::cout << "Lighthouse driver initialization failed - skipping test" << std::endl; return TestResult(true, "Device registration test skipped"); } // Get the lighthouse driver provider vr::IServerTrackedDeviceProvider* provider = lighthouseWrapper->GetDriverProvider(); if (!provider) { return TestResult(false, "Failed to get lighthouse driver provider"); } // Run a frame to let the lighthouse driver discover devices lighthouseWrapper->RunFrame(); // Wait a bit for devices to be discovered std::this_thread::sleep_for(std::chrono::milliseconds(500)); // Run another frame lighthouseWrapper->RunFrame(); // Check if any devices were discovered // Note: This is a basic check and may not be reliable in all environments bool devicesDiscovered = false; // We can't directly check for devices, but we can run some operations // that would fail if no devices were present try { // Run a few more frames for (int i = 0; i < 10; i++) { lighthouseWrapper->RunFrame(); std::this_thread::sleep_for(std::chrono::milliseconds(10)); } // If we got here without exceptions, assume devices were discovered devicesDiscovered = true; } catch (const std::exception& e) { std::cout << "Exception during device discovery: " << e.what() << std::endl; } if (!devicesDiscovered) { std::cout << "No devices were discovered - this may be expected in some environments" << std::endl; return TestResult(true, "Device discovery test skipped"); } return TestResult(true, "Device registration succeeded"); } TestResult testIMUDataAccess() { // Initialize the components bool lighthouseInitResult = lighthouseWrapper->Initialize(); bool imuInitResult = imuProvider->Initialize(); if (!lighthouseInitResult) { std::cout << "Lighthouse driver initialization failed - skipping test" << std::endl; return TestResult(true, "IMU data access test skipped"); } // Run a frame to let the lighthouse driver discover devices lighthouseWrapper->RunFrame(); // Wait a bit for devices to be discovered std::this_thread::sleep_for(std::chrono::milliseconds(500)); // Register a test device with the IMU provider uint32_t testDeviceId = 0; // HMD is usually device 0 imuProvider->RegisterDevice(testDeviceId); // Add a synthetic IMU sample vr::ImuSample_t sample; sample.fSampleTime = 1.0; sample.vAccel.v[0] = 0.0f; sample.vAccel.v[1] = 9.81f; // Gravity sample.vAccel.v[2] = 0.0f; sample.vGyro.v[0] = 0.0f; sample.vGyro.v[1] = 0.0f; sample.vGyro.v[2] = 0.0f; imuProvider->AddIMUSample(testDeviceId, sample); // Check if the IMU data is available bool dataAvailable = imuProvider->IsIMUDataAvailable(testDeviceId); if (!dataAvailable) { return TestResult(false, "IMU data should be available"); } // Get the IMU sample vr::ImuSample_t retrievedSample; bool result = imuProvider->GetLatestIMUSample(testDeviceId, &retrievedSample); if (!result) { return TestResult(false, "Failed to get IMU sample"); } // Verify the sample data if (retrievedSample.fSampleTime != sample.fSampleTime || retrievedSample.vAccel.v[1] != sample.vAccel.v[1]) { return TestResult(false, "IMU sample data mismatch"); } return TestResult(true, "IMU data access succeeded"); } TestResult testOpticalTrackingLoss() { // This test is more conceptual since we can't easily simulate optical tracking loss // in an integration test without actual hardware std::cout << "Note: This test is conceptual and doesn't fully simulate optical tracking loss" << std::endl; // Initialize the components bool lighthouseInitResult = lighthouseWrapper->Initialize(); bool imuInitResult = imuProvider->Initialize(); if (!lighthouseInitResult) { std::cout << "Lighthouse driver initialization failed - skipping test" << std::endl; return TestResult(true, "Optical tracking loss test skipped"); } // Register a test device with the IMU provider uint32_t testDeviceId = 0; // HMD is usually device 0 imuProvider->RegisterDevice(testDeviceId); // Add several IMU samples for (int i = 0; i < 10; i++) { vr::ImuSample_t sample; sample.fSampleTime = static_cast(i) * 0.01f; sample.vAccel.v[0] = 0.0f; sample.vAccel.v[1] = 9.81f; // Gravity sample.vAccel.v[2] = 0.0f; sample.vGyro.v[0] = static_cast(i) * 0.01f; // Small rotation sample.vGyro.v[1] = 0.0f; sample.vGyro.v[2] = 0.0f; imuProvider->AddIMUSample(testDeviceId, sample); } // Check if IMU data is available bool dataAvailable = imuProvider->IsIMUDataAvailable(testDeviceId); if (!dataAvailable) { return TestResult(false, "IMU data should be available"); } // In a real scenario with actual hardware, we would: // 1. Create a SaunaDeviceDriver wrapping the real device driver // 2. Simulate optical tracking loss (e.g., by covering the sensors) // 3. Verify that the driver continues to provide pose updates using IMU data // For this integration test, we'll just verify that we can access IMU data // which would be used during optical tracking loss return TestResult(true, "Optical tracking loss test conceptually succeeded"); } void runAllTests() { TestSuite suite("Sauna Driver Integration Tests"); suite.addTest("DriverInitialization", [this]() { return testDriverInitialization(); }); suite.addTest("DeviceRegistration", [this]() { return testDeviceRegistration(); }); suite.addTest("IMUDataAccess", [this]() { return testIMUDataAccess(); }); suite.addTest("OpticalTrackingLoss", [this]() { return testOpticalTrackingLoss(); }); suite.runAll(); } }; int main(int argc, char** argv) { std::cout << "Running Sauna Driver Integration Tests..." << std::endl; std::cout << "Note: These tests require SteamVR to be installed but not running" << std::endl; SaunaDriverIntegrationTest test; test.runAllTests(); return 0; }