#include #include #include #include #include #include namespace lcamera_dev { namespace { static CameraIdentityRecord makeRecord( const std::string& id, const std::string& model = "", const std::string& locationLabel = "") { CameraIdentityRecord record; record.id = id; record.model = model; record.locationLabel = locationLabel; return record; } static std::vector sampleRecords() { return { makeRecord("/base/cam0", "imx219", "back"), makeRecord("/base/cam1", "Logitech C920", "external"), makeRecord("/base/cam2", "imx219", "front"), }; } TEST(FormatCameraListForDiagnosticsTest, ListsIndexedCameras) { const std::vector records = sampleRecords(); const std::string text = formatCameraListForDiagnostics(records); EXPECT_NE(text.find("Known cameras:"), std::string::npos); EXPECT_NE(text.find("[0] id=/base/cam0"), std::string::npos); EXPECT_NE(text.find("model=imx219"), std::string::npos); EXPECT_NE(text.find("location=external"), std::string::npos); } TEST(ResolveSelectorAgainstRecordsTest, MatchesLibcameraId) { const std::vector records = sampleRecords(); const std::vector criteria = parseDeviceSelector("lcamera-id:/base/cam1"); const CameraIdentityRecord resolved = resolveSelectorAgainstRecords(criteria, records); EXPECT_EQ(resolved.id, "/base/cam1"); } TEST(ResolveSelectorAgainstRecordsTest, MatchesModelSubstrAndLocation) { const std::vector records = sampleRecords(); const std::vector criteria = parseDeviceSelector("model-substr:Logitech;location:EXTERNAL"); const CameraIdentityRecord resolved = resolveSelectorAgainstRecords(criteria, records); EXPECT_EQ(resolved.id, "/base/cam1"); } TEST(ResolveSelectorAgainstRecordsTest, IndexSelectsNthCamera) { const std::vector records = sampleRecords(); const std::vector criteria = parseDeviceSelector("index:2"); const CameraIdentityRecord resolved = resolveSelectorAgainstRecords(criteria, records); EXPECT_EQ(resolved.id, "/base/cam2"); } TEST(ResolveSelectorAgainstRecordsTest, IndexCombinedWithModel) { const std::vector records = sampleRecords(); const std::vector criteria = parseDeviceSelector("index:0;model:imx219"); const CameraIdentityRecord resolved = resolveSelectorAgainstRecords(criteria, records); EXPECT_EQ(resolved.id, "/base/cam0"); } TEST(ResolveSelectorAgainstRecordsTest, ZeroMatchesThrowsWithDiagnostics) { const std::vector records = sampleRecords(); const std::vector criteria = parseDeviceSelector("model:does-not-exist"); try { resolveSelectorAgainstRecords(criteria, records); FAIL() << "Expected std::runtime_error"; } catch (const std::runtime_error& exc) { EXPECT_NE( std::string(exc.what()).find("No camera matches deviceSelector"), std::string::npos); EXPECT_NE( std::string(exc.what()).find("Known cameras:"), std::string::npos); } } TEST(ResolveSelectorAgainstRecordsTest, AmbiguousSelectorThrows) { const std::vector records = sampleRecords(); const std::vector criteria = parseDeviceSelector("model:imx219"); EXPECT_THROW( resolveSelectorAgainstRecords(criteria, records), std::runtime_error); } TEST(ResolveSelectorAgainstRecordsTest, IndexOutOfRangeThrows) { const std::vector records = sampleRecords(); const std::vector criteria = parseDeviceSelector("index:9"); EXPECT_THROW( resolveSelectorAgainstRecords(criteria, records), std::runtime_error); } TEST(ResolveSelectorAgainstRecordsTest, IndexConflictsWithOtherClauses) { const std::vector records = sampleRecords(); const std::vector criteria = parseDeviceSelector("index:0;location:front"); EXPECT_THROW( resolveSelectorAgainstRecords(criteria, records), std::runtime_error); } TEST(ResolveSelectorAgainstRecordsTest, InvalidIndexValueThrows) { const std::vector records = sampleRecords(); const std::vector criteria = parseDeviceSelector("index:not-a-number"); EXPECT_THROW( resolveSelectorAgainstRecords(criteria, records), std::runtime_error); } } // namespace } // namespace lcamera_dev