Files
salmanoff/commonLibs/lcameraDev/tests/selectorResolve_tests.cpp
T
hayodea 7af684039d lcameraDev: add resolve-only deviceSelector API and deduplicate resolve paths.
Export lcameraDev_resolveDeviceSelectorCReq for attach-identity consumers,
factor live-camera snapshot helpers, and share resolveDeviceSelectorAgainstRecords
with get-or-create session acquisition.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-14 11:02:11 -04:00

227 lines
6.6 KiB
C++

#include <gtest/gtest.h>
#include <catalogHelpers.h>
#include <selectorParse.h>
#include <selectorResolve.h>
#include <stdexcept>
#include <string>
#include <vector>
namespace lcamera_dev {
namespace {
constexpr const char *dellLaptopMachineTag = "dell-laptop";
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<CameraIdentityRecord> syntheticAmbiguityRecords()
{
return {
makeRecord("/base/cam0", "imx219", "back"),
makeRecord("/base/cam1", "Logitech C920", "external"),
makeRecord("/base/cam2", "imx219", "front"),
};
}
TEST(FormatCameraListForDiagnosticsTest, ListsIndexedCameras)
{
const std::vector<CameraIdentityRecord> records =
tests::bakedProfilesAsRecords(dellLaptopMachineTag);
const std::string text = formatCameraListForDiagnostics(records);
EXPECT_NE(text.find("Known cameras:"), std::string::npos);
EXPECT_NE(text.find("HDMI USB Camera"), std::string::npos);
EXPECT_NE(text.find("location=external"), std::string::npos);
EXPECT_NE(text.find("Integrated_Webcam_HD"), std::string::npos);
EXPECT_NE(text.find("location=front"), std::string::npos);
}
TEST(ResolveDeviceSelectorAgainstRecordsTest, BakedUsbHdmiCameraMatchesExampleSelector)
{
const std::vector<CameraIdentityRecord> records =
tests::bakedProfilesAsRecords(dellLaptopMachineTag);
const CameraIdentityRecord resolved =
resolveDeviceSelectorAgainstRecords(
"model-substr:HDMI;location:EXTERNAL",
records);
EXPECT_EQ(
resolved.id,
"\\_SB_.PCI0.XHC_.RHUB.HS01-1:1.0-32e4:9415");
EXPECT_EQ(resolved.locationLabel, "external");
}
TEST(ResolveSelectorAgainstRecordsTest, BakedUsbHdmiCameraMatchesExampleSelector)
{
const std::vector<CameraIdentityRecord> records =
tests::bakedProfilesAsRecords(dellLaptopMachineTag);
const std::vector<SelectorCriterion> criteria =
parseDeviceSelector("model-substr:HDMI;location:EXTERNAL");
const CameraIdentityRecord resolved =
resolveSelectorAgainstRecords(criteria, records);
EXPECT_EQ(
resolved.id,
"\\_SB_.PCI0.XHC_.RHUB.HS01-1:1.0-32e4:9415");
EXPECT_EQ(resolved.locationLabel, "external");
}
TEST(ResolveSelectorAgainstRecordsTest, BakedIntegratedWebcamMatchesExampleSelector)
{
const std::vector<CameraIdentityRecord> records =
tests::bakedProfilesAsRecords(dellLaptopMachineTag);
const std::vector<SelectorCriterion> criteria =
parseDeviceSelector("model-substr:Integrated;location:front");
const CameraIdentityRecord resolved =
resolveSelectorAgainstRecords(criteria, records);
EXPECT_EQ(
resolved.id,
"\\_SB_.PCI0.XHC_.RHUB.HS04-4:1.0-1bcf:2b8a");
EXPECT_EQ(resolved.locationLabel, "front");
}
TEST(ResolveSelectorAgainstRecordsTest, BakedUsbCameraMatchesLibcameraId)
{
const std::vector<CameraIdentityRecord> records =
tests::bakedProfilesAsRecords(dellLaptopMachineTag);
const std::vector<SelectorCriterion> criteria =
parseDeviceSelector(
"lcamera-id:\\_SB_.PCI0.XHC_.RHUB.HS01-1:1.0-32e4:9415");
const CameraIdentityRecord resolved =
resolveSelectorAgainstRecords(criteria, records);
EXPECT_EQ(
resolved.id,
"\\_SB_.PCI0.XHC_.RHUB.HS01-1:1.0-32e4:9415");
}
TEST(ResolveSelectorAgainstRecordsTest, MatchesLibcameraId)
{
const std::vector<CameraIdentityRecord> records = syntheticAmbiguityRecords();
const std::vector<SelectorCriterion> criteria =
parseDeviceSelector("lcamera-id:/base/cam1");
const CameraIdentityRecord resolved =
resolveSelectorAgainstRecords(criteria, records);
EXPECT_EQ(resolved.id, "/base/cam1");
}
TEST(ResolveSelectorAgainstRecordsTest, MatchesModelSubstrAndLocation)
{
const std::vector<CameraIdentityRecord> records = syntheticAmbiguityRecords();
const std::vector<SelectorCriterion> 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<CameraIdentityRecord> records = syntheticAmbiguityRecords();
const std::vector<SelectorCriterion> criteria =
parseDeviceSelector("index:2");
const CameraIdentityRecord resolved =
resolveSelectorAgainstRecords(criteria, records);
EXPECT_EQ(resolved.id, "/base/cam2");
}
TEST(ResolveSelectorAgainstRecordsTest, IndexCombinedWithModel)
{
const std::vector<CameraIdentityRecord> records = syntheticAmbiguityRecords();
const std::vector<SelectorCriterion> criteria =
parseDeviceSelector("index:0;model:imx219");
const CameraIdentityRecord resolved =
resolveSelectorAgainstRecords(criteria, records);
EXPECT_EQ(resolved.id, "/base/cam0");
}
TEST(ResolveSelectorAgainstRecordsTest, ZeroMatchesThrowsWithDiagnostics)
{
const std::vector<CameraIdentityRecord> records = syntheticAmbiguityRecords();
const std::vector<SelectorCriterion> 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<CameraIdentityRecord> records = syntheticAmbiguityRecords();
const std::vector<SelectorCriterion> criteria =
parseDeviceSelector("model:imx219");
EXPECT_THROW(
resolveSelectorAgainstRecords(criteria, records),
std::runtime_error);
}
TEST(ResolveSelectorAgainstRecordsTest, IndexOutOfRangeThrows)
{
const std::vector<CameraIdentityRecord> records = syntheticAmbiguityRecords();
const std::vector<SelectorCriterion> criteria =
parseDeviceSelector("index:9");
EXPECT_THROW(
resolveSelectorAgainstRecords(criteria, records),
std::runtime_error);
}
TEST(ResolveSelectorAgainstRecordsTest, IndexConflictsWithOtherClauses)
{
const std::vector<CameraIdentityRecord> records = syntheticAmbiguityRecords();
const std::vector<SelectorCriterion> criteria =
parseDeviceSelector("index:0;location:front");
EXPECT_THROW(
resolveSelectorAgainstRecords(criteria, records),
std::runtime_error);
}
TEST(ResolveSelectorAgainstRecordsTest, InvalidIndexValueThrows)
{
const std::vector<CameraIdentityRecord> records = syntheticAmbiguityRecords();
const std::vector<SelectorCriterion> criteria =
parseDeviceSelector("index:not-a-number");
EXPECT_THROW(
resolveSelectorAgainstRecords(criteria, records),
std::runtime_error);
}
} // namespace
} // namespace lcamera_dev