#include #include #include #include #include #include #include #include #include #include #include namespace lcamera_dev { namespace { constexpr const char *hilEnvVar = "LCAMERADEV_HIL"; constexpr const char *machineEnvVar = "LCAMERADEV_MACHINE"; constexpr const char *defaultMachineTag = "dell-laptop"; bool hilTestsEnabled() { const char *value = std::getenv(hilEnvVar); return value != nullptr && std::string(value) == "1"; } std::string machineTagFromEnvironment() { const char *value = std::getenv(machineEnvVar); if (value != nullptr && std::string(value).size() > 0) { return value; } return defaultMachineTag; } sscl::co::NonViralNonPostingInvoker enumerateCamerasCInd( std::exception_ptr& exceptionStorage, std::function callerLambda, std::vector& enumeratedCameras) { (void)exceptionStorage; (void)callerLambda; enumeratedCameras = co_await lcameraDev_enumerateCamerasCReq(); co_return; } sscl::co::NonViralNonPostingInvoker getOrCreateCInd( std::exception_ptr& exceptionStorage, std::function callerLambda, const char *deviceSelector, lcamera_dev::LcameraDevGetOrCreateResult& createResult) { (void)exceptionStorage; (void)callerLambda; createResult = co_await lcameraDev_getOrCreateDeviceCReq(deviceSelector); co_return; } sscl::co::NonViralNonPostingInvoker releaseCInd( std::exception_ptr& exceptionStorage, std::function callerLambda, const std::shared_ptr& deviceSession) { (void)exceptionStorage; (void)callerLambda; co_await lcameraDev_releaseDeviceCReq(deviceSession); co_return; } sscl::co::NonViralNonPostingInvoker resolveSelectorCInd( std::exception_ptr &, std::function, const char *deviceSelector, lcamera_dev::CameraIdentityRecord& resolvedIdentity) { resolvedIdentity = co_await lcameraDev_resolveDeviceSelectorCReq(deviceSelector); co_return; } void runLcameraDevMainAndNurseryTask( const std::function&)>& work) { sscl::tests::ProbeComponentThreadHarness harness("lcameraDev-hil"); harness.runSync( [&work](const std::shared_ptr& componentThread) { lcameraDev_main(componentThread); work(componentThread); lcameraDev_exit(); }); } class LcameraDevHilTest : public ::testing::Test { protected: void SetUp() override { if (!hilTestsEnabled()) { GTEST_SKIP() << "Set " << hilEnvVar << "=1 to run hardware tests"; } machineTag = machineTagFromEnvironment(); requiredProfiles = sscl::tests::requiredProfilesForMachine(machineTag.c_str()); if (requiredProfiles.empty()) { GTEST_SKIP() << "No baked profiles for machine tag " << machineTag; } } std::string machineTag; std::vector requiredProfiles; }; TEST_F(LcameraDevHilTest, EnumerateMatchesBakedCatalog) { std::vector enumeratedCameras; runLcameraDevMainAndNurseryTask( [&enumeratedCameras]( const std::shared_ptr& componentThread) { sscl::tests::runNonViralNurseryOnComponentThread( componentThread, [&enumeratedCameras]( sscl::co::NonViralTaskNursery::Slot::Lease& lease) { return enumerateCamerasCInd( lease.getExceptionStorage(), lease.getCallerLambda(), enumeratedCameras); }); }); EXPECT_GE(enumeratedCameras.size(), requiredProfiles.size()); for (const test_fixtures::BakedCameraProfile *profile : requiredProfiles) { bool found = false; for (const lcamera_dev::LcameraDevCameraInfo& camera : enumeratedCameras) { if (camera.id == profile->libcameraId) { found = true; break; } } EXPECT_TRUE(found) << "Missing baked profile camera id=" << profile->libcameraId; } } TEST_F(LcameraDevHilTest, GetOrCreateByBakedSelector) { runLcameraDevMainAndNurseryTask( [this](const std::shared_ptr& componentThread) { for (const test_fixtures::BakedCameraProfile *profile : requiredProfiles) { lcamera_dev::LcameraDevGetOrCreateResult createResult; sscl::tests::runNonViralNurseryOnComponentThread( componentThread, [profile, &createResult]( sscl::co::NonViralTaskNursery::Slot::Lease& lease) { return getOrCreateCInd( lease.getExceptionStorage(), lease.getCallerLambda(), profile->exampleSelector, createResult); }); EXPECT_TRUE(createResult.deviceSession != nullptr) << profile->profileTag; EXPECT_EQ( createResult.resolvedIdentity.id, profile->libcameraId) << profile->profileTag; sscl::tests::runNonViralNurseryOnComponentThread( componentThread, [&createResult]( sscl::co::NonViralTaskNursery::Slot::Lease& lease) { return releaseCInd( lease.getExceptionStorage(), lease.getCallerLambda(), createResult.deviceSession); }); } }); } TEST_F(LcameraDevHilTest, ResolveDeviceSelectorMatchesGetOrCreateIdentity) { runLcameraDevMainAndNurseryTask( [this](const std::shared_ptr& componentThread) { for (const test_fixtures::BakedCameraProfile *profile : requiredProfiles) { lcamera_dev::CameraIdentityRecord resolvedIdentity; lcamera_dev::LcameraDevGetOrCreateResult createResult; sscl::tests::runNonViralNurseryOnComponentThread( componentThread, [profile, &resolvedIdentity]( sscl::co::NonViralTaskNursery::Slot::Lease& lease) { return resolveSelectorCInd( lease.getExceptionStorage(), lease.getCallerLambda(), profile->exampleSelector, resolvedIdentity); }); EXPECT_EQ(resolvedIdentity.id, profile->libcameraId) << profile->profileTag; sscl::tests::runNonViralNurseryOnComponentThread( componentThread, [profile, &createResult]( sscl::co::NonViralTaskNursery::Slot::Lease& lease) { return getOrCreateCInd( lease.getExceptionStorage(), lease.getCallerLambda(), profile->exampleSelector, createResult); }); EXPECT_EQ( createResult.resolvedIdentity.id, resolvedIdentity.id) << profile->profileTag; sscl::tests::runNonViralNurseryOnComponentThread( componentThread, [&createResult]( sscl::co::NonViralTaskNursery::Slot::Lease& lease) { return releaseCInd( lease.getExceptionStorage(), lease.getCallerLambda(), createResult.deviceSession); }); } }); } } // namespace } // namespace lcamera_dev