Add env-gated lcameraBuff configure HIL tests on baked USB profile.
HIL attaches Y/U/V channels, verifies shared producer state, and detaches using an alternate selector string for the U channel quale. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -27,3 +27,33 @@ target_link_libraries(lcameraBuff_unit_tests
|
||||
add_dependencies(lcameraBuff_unit_tests gtest_main spinscale_test_support)
|
||||
|
||||
add_test(NAME lcameraBuff_unit_tests COMMAND lcameraBuff_unit_tests)
|
||||
|
||||
add_executable(lcameraBuff_configure_hil_tests
|
||||
lcameraBuff_configure_hil_tests.cpp
|
||||
hilSmoCallbacksStub.cpp
|
||||
)
|
||||
|
||||
target_include_directories(lcameraBuff_configure_hil_tests PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_SOURCE_DIR}/stimBuffApis/lcameraBuff
|
||||
${CMAKE_SOURCE_DIR}/commonLibs/lcameraDev
|
||||
${CMAKE_SOURCE_DIR}/libspinscale/tests
|
||||
${CMAKE_SOURCE_DIR}/tests/fixtures
|
||||
${CMAKE_SOURCE_DIR}/include
|
||||
${CMAKE_BINARY_DIR}/include
|
||||
)
|
||||
|
||||
target_link_libraries(lcameraBuff_configure_hil_tests
|
||||
gtest_main
|
||||
lcameraBuff
|
||||
lcameraDev
|
||||
spinscale_test_support
|
||||
smocore
|
||||
${Boost_LIBRARIES}
|
||||
${OPENCL_LIBRARIES}
|
||||
)
|
||||
|
||||
add_dependencies(lcameraBuff_configure_hil_tests gtest_main spinscale_test_support)
|
||||
|
||||
add_test(NAME lcameraBuff_configure_hil_tests COMMAND lcameraBuff_configure_hil_tests)
|
||||
set_tests_properties(lcameraBuff_configure_hil_tests PROPERTIES LABELS "HIL")
|
||||
|
||||
@@ -0,0 +1,327 @@
|
||||
#include <boostAsioLinkageFix.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <hilSmoCallbacksStub.h>
|
||||
#include <lcameraBuffInternal.h>
|
||||
#include <lcameraBuffParams.h>
|
||||
#include <support/bakedDeviceCatalog.h>
|
||||
#include <support/probeComponentThread.h>
|
||||
#include <user/deviceAttachmentSpec.h>
|
||||
#include <user/senseApiDesc.h>
|
||||
#include <yuvCaptureLayout.h>
|
||||
#include <pixelAndColorFormatDecisions.h>
|
||||
#include <yuvChannelStimulusBuffer.h>
|
||||
#include <yuvStimProducer.h>
|
||||
#include <spinscale/co/nonViralTaskNursery.h>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace lcamera_buff_tests {
|
||||
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;
|
||||
}
|
||||
|
||||
std::shared_ptr<smo::device::DeviceAttachmentSpec> makeAttachSpec(
|
||||
const test_fixtures::BakedCameraProfile *profile,
|
||||
const char *qualeIfaceApi)
|
||||
{
|
||||
auto spec = std::make_shared<smo::device::DeviceAttachmentSpec>();
|
||||
spec->deviceIdentifier = "cam0";
|
||||
spec->sensorType = 'e';
|
||||
spec->qualeIfaceApi = qualeIfaceApi;
|
||||
spec->stimBuffApi = "lcameraBuff";
|
||||
spec->provider = "lcameraDev";
|
||||
spec->deviceSelector = profile->exampleSelector;
|
||||
spec->stimBuffApiParams = {
|
||||
{"v-res", "480p"},
|
||||
{"colour-space", "yuv"},
|
||||
{"opt-planar", ""},
|
||||
};
|
||||
return spec;
|
||||
}
|
||||
|
||||
std::shared_ptr<smo::device::DeviceAttachmentSpec> makeDetachSpec(
|
||||
const test_fixtures::BakedCameraProfile *profile,
|
||||
const char *qualeIfaceApi,
|
||||
const char *deviceSelectorOverride)
|
||||
{
|
||||
auto spec = makeAttachSpec(profile, qualeIfaceApi);
|
||||
spec->deviceSelector = deviceSelectorOverride;
|
||||
return spec;
|
||||
}
|
||||
|
||||
sscl::co::NonViralNonPostingInvoker initializeBuffCInd(
|
||||
std::exception_ptr& exceptionStorage,
|
||||
std::function<void()> callerLambda)
|
||||
{
|
||||
(void)exceptionStorage;
|
||||
(void)callerLambda;
|
||||
|
||||
co_await smo::stim_buff::lcamera_buff::lcameraBuff_initializeCInd();
|
||||
co_return;
|
||||
}
|
||||
|
||||
sscl::co::NonViralNonPostingInvoker finalizeBuffCInd(
|
||||
std::exception_ptr& exceptionStorage,
|
||||
std::function<void()> callerLambda)
|
||||
{
|
||||
(void)exceptionStorage;
|
||||
(void)callerLambda;
|
||||
|
||||
co_await smo::stim_buff::lcamera_buff::lcameraBuff_finalizeCInd();
|
||||
co_return;
|
||||
}
|
||||
|
||||
sscl::co::NonViralNonPostingInvoker attachDeviceCInd(
|
||||
std::exception_ptr& exceptionStorage,
|
||||
std::function<void()> callerLambda,
|
||||
const std::shared_ptr<smo::device::DeviceAttachmentSpec>& spec,
|
||||
const std::shared_ptr<sscl::ComponentThread>& componentThread,
|
||||
smo::stim_buff::StimBuffDeviceOpResult& result)
|
||||
{
|
||||
(void)exceptionStorage;
|
||||
(void)callerLambda;
|
||||
|
||||
result = co_await smo::stim_buff::lcamera_buff::lcameraBuff_attachDeviceCReq(
|
||||
sscl::co::ExplicitPostTarget(componentThread->getIoContext()),
|
||||
spec,
|
||||
componentThread);
|
||||
|
||||
co_return;
|
||||
}
|
||||
|
||||
sscl::co::NonViralNonPostingInvoker detachDeviceCInd(
|
||||
std::exception_ptr& exceptionStorage,
|
||||
std::function<void()> callerLambda,
|
||||
const std::shared_ptr<smo::device::DeviceAttachmentSpec>& spec,
|
||||
smo::stim_buff::StimBuffDeviceOpResult& result)
|
||||
{
|
||||
(void)exceptionStorage;
|
||||
(void)callerLambda;
|
||||
|
||||
result = co_await smo::stim_buff::lcamera_buff::lcameraBuff_detachDeviceCReq(
|
||||
sscl::co::ExplicitPostTarget(
|
||||
smo::stim_buff::lcamera_buff::lcameraBuffThreadingModelDesc
|
||||
.componentThread->getIoContext()),
|
||||
spec);
|
||||
|
||||
co_return;
|
||||
}
|
||||
|
||||
void runOnProbeThread(
|
||||
const std::function<void(
|
||||
const std::shared_ptr<sscl::ComponentThread>&)>& work)
|
||||
{
|
||||
sscl::tests::ProbeComponentThreadHarness harness("lcameraBuff-configure-hil");
|
||||
harness.runSync(work);
|
||||
}
|
||||
|
||||
class LcameraBuffConfigureHilTest : 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;
|
||||
}
|
||||
|
||||
const test_fixtures::BakedCameraProfile *profile =
|
||||
findProfile("usb_hdmi_camera");
|
||||
if (!profile) {
|
||||
GTEST_SKIP() << "usb_hdmi_camera profile not available";
|
||||
}
|
||||
|
||||
usbProfile = profile;
|
||||
}
|
||||
|
||||
const test_fixtures::BakedCameraProfile *findProfile(
|
||||
const char *profileTag) const
|
||||
{
|
||||
for (const test_fixtures::BakedCameraProfile *profile :
|
||||
requiredProfiles)
|
||||
{
|
||||
if (std::string(profile->profileTag) == profileTag) {
|
||||
return profile;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string machineTag;
|
||||
std::vector<const test_fixtures::BakedCameraProfile *> requiredProfiles;
|
||||
const test_fixtures::BakedCameraProfile *usbProfile = nullptr;
|
||||
};
|
||||
|
||||
TEST_F(LcameraBuffConfigureHilTest, AttachThreeYuvChannelsWithOptPlanar480p)
|
||||
{
|
||||
const char *libPathEnv = std::getenv("LCAMERADEV_LIB_PATH");
|
||||
if (libPathEnv == nullptr || std::string(libPathEnv).empty())
|
||||
{
|
||||
GTEST_SKIP() << "Set LCAMERADEV_LIB_PATH to liblcameraDev.so for HIL attach";
|
||||
}
|
||||
|
||||
runOnProbeThread(
|
||||
[this](const std::shared_ptr<sscl::ComponentThread>& componentThread)
|
||||
{
|
||||
smo::stim_buff::lcamera_buff::lcameraBuffSmoHooksPtr =
|
||||
&hilSmoCallbacksStub();
|
||||
smo::stim_buff::lcamera_buff::lcameraBuffThreadingModelDesc
|
||||
.componentThread = componentThread;
|
||||
|
||||
sscl::tests::runNonViralNurseryOnComponentThread(
|
||||
componentThread,
|
||||
[](sscl::co::NonViralTaskNursery::Slot::Lease& lease)
|
||||
{
|
||||
return initializeBuffCInd(
|
||||
lease.getExceptionStorage(),
|
||||
lease.getCallerLambda());
|
||||
});
|
||||
|
||||
std::shared_ptr<smo::stim_buff::lcamera_buff::YuvStimProducer>
|
||||
producer;
|
||||
size_t expectedBufferCount = 0;
|
||||
|
||||
for (const char *qualeIfaceApi :
|
||||
{"colour-yuv-y", "colour-yuv-u", "colour-yuv-v"})
|
||||
{
|
||||
const std::shared_ptr<smo::device::DeviceAttachmentSpec> spec =
|
||||
makeAttachSpec(usbProfile, qualeIfaceApi);
|
||||
|
||||
smo::stim_buff::StimBuffDeviceOpResult attachResult;
|
||||
sscl::tests::runNonViralNurseryOnComponentThread(
|
||||
componentThread,
|
||||
[&spec, &componentThread, &attachResult](
|
||||
sscl::co::NonViralTaskNursery::Slot::Lease& lease)
|
||||
{
|
||||
return attachDeviceCInd(
|
||||
lease.getExceptionStorage(),
|
||||
lease.getCallerLambda(),
|
||||
spec,
|
||||
componentThread,
|
||||
attachResult);
|
||||
});
|
||||
|
||||
ASSERT_TRUE(attachResult.success);
|
||||
++expectedBufferCount;
|
||||
|
||||
ASSERT_EQ(
|
||||
smo::stim_buff::lcamera_buff::attachedStimulusProducers.size(),
|
||||
1u);
|
||||
producer = smo::stim_buff::lcamera_buff
|
||||
::attachedStimulusProducers.front();
|
||||
ASSERT_TRUE(producer != nullptr);
|
||||
EXPECT_EQ(
|
||||
producer->attachedStimulusBuffers.size(),
|
||||
expectedBufferCount);
|
||||
}
|
||||
|
||||
ASSERT_TRUE(producer != nullptr);
|
||||
EXPECT_EQ(
|
||||
producer->configuredMode.pixelFormatName,
|
||||
"YUYV");
|
||||
EXPECT_EQ(
|
||||
producer->layoutPath,
|
||||
smo::stim_buff::lcamera_buff::YuvCaptureLayoutPath
|
||||
::PackedDeinterleave);
|
||||
EXPECT_EQ(
|
||||
producer->chromaSubsampling,
|
||||
smo::stim_buff::lcamera_buff::YuvChromaSubsampling::Yuv422);
|
||||
|
||||
const size_t expectedUBytes =
|
||||
smo::stim_buff::lcamera_buff
|
||||
::computeDeinterleavedChannelByteSize(
|
||||
smo::stim_buff::lcamera_buff::YuvChannelKind::U,
|
||||
producer->configuredMode.width,
|
||||
producer->configuredMode.height,
|
||||
smo::stim_buff::lcamera_buff
|
||||
::YuvChromaSubsampling::Yuv422);
|
||||
EXPECT_EQ(expectedUBytes, 320u * 480u);
|
||||
|
||||
for (const std::shared_ptr<smo::stim_buff::StimulusBuffer>& bufferBase :
|
||||
producer->attachedStimulusBuffers)
|
||||
{
|
||||
auto channelBuffer =
|
||||
std::dynamic_pointer_cast<
|
||||
smo::stim_buff::lcamera_buff::YuvChannelStimulusBuffer>(
|
||||
bufferBase);
|
||||
ASSERT_TRUE(channelBuffer != nullptr);
|
||||
|
||||
if (channelBuffer->channelKind
|
||||
== smo::stim_buff::lcamera_buff::YuvChannelKind::U
|
||||
|| channelBuffer->channelKind
|
||||
== smo::stim_buff::lcamera_buff::YuvChannelKind::V)
|
||||
{
|
||||
EXPECT_EQ(channelBuffer->channelByteSize, expectedUBytes);
|
||||
}
|
||||
}
|
||||
|
||||
for (const char *qualeIfaceApi :
|
||||
{"colour-yuv-v", "colour-yuv-u", "colour-yuv-y"})
|
||||
{
|
||||
const std::shared_ptr<smo::device::DeviceAttachmentSpec> spec =
|
||||
(std::string(qualeIfaceApi) == "colour-yuv-u")
|
||||
? makeDetachSpec(
|
||||
usbProfile,
|
||||
qualeIfaceApi,
|
||||
"model-substr:HDMI USB Camera;location:external")
|
||||
: makeAttachSpec(usbProfile, qualeIfaceApi);
|
||||
|
||||
smo::stim_buff::StimBuffDeviceOpResult detachResult;
|
||||
sscl::tests::runNonViralNurseryOnComponentThread(
|
||||
componentThread,
|
||||
[&spec, &detachResult](
|
||||
sscl::co::NonViralTaskNursery::Slot::Lease& lease)
|
||||
{
|
||||
return detachDeviceCInd(
|
||||
lease.getExceptionStorage(),
|
||||
lease.getCallerLambda(),
|
||||
spec,
|
||||
detachResult);
|
||||
});
|
||||
|
||||
ASSERT_TRUE(detachResult.success);
|
||||
}
|
||||
|
||||
sscl::tests::runNonViralNurseryOnComponentThread(
|
||||
componentThread,
|
||||
[](sscl::co::NonViralTaskNursery::Slot::Lease& lease)
|
||||
{
|
||||
return finalizeBuffCInd(
|
||||
lease.getExceptionStorage(),
|
||||
lease.getCallerLambda());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace lcamera_buff_tests
|
||||
Reference in New Issue
Block a user