tests: Introduce hotplug hot-unplug unit test
This test checks the code-paths for camera's hotplugged and unplugged support. It is based on bind/unbind of a UVC device from sysfs. Hence, this test requires root permissions to run and should have at least one already bound UVC device present in the system. Signed-off-by: Umang Jain <email@uajain.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
parent
7055e96ecc
commit
8960ef9715
2 changed files with 129 additions and 0 deletions
128
test/hotplug-cameras.cpp
Normal file
128
test/hotplug-cameras.cpp
Normal file
|
@ -0,0 +1,128 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (C) 2020, Umang Jain <email@uajain.com>
|
||||
*
|
||||
* hotplug-cameras.cpp - Test cameraAdded/cameraRemoved signals in CameraManager
|
||||
*/
|
||||
|
||||
#include <dirent.h>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <libcamera/camera.h>
|
||||
#include <libcamera/camera_manager.h>
|
||||
#include <libcamera/event_dispatcher.h>
|
||||
#include <libcamera/timer.h>
|
||||
|
||||
#include "libcamera/internal/file.h"
|
||||
#include "libcamera/internal/thread.h"
|
||||
|
||||
#include "test.h"
|
||||
|
||||
using namespace libcamera;
|
||||
|
||||
class HotplugTest : public Test
|
||||
{
|
||||
protected:
|
||||
void cameraAddedHandler(std::shared_ptr<Camera> cam)
|
||||
{
|
||||
cameraAdded_ = true;
|
||||
}
|
||||
|
||||
void cameraRemovedHandler(std::shared_ptr<Camera> cam)
|
||||
{
|
||||
cameraRemoved_ = true;
|
||||
}
|
||||
|
||||
int init()
|
||||
{
|
||||
if (!File::exists("/sys/module/uvcvideo")) {
|
||||
std::cout << "uvcvideo driver is not loaded, skipping" << std::endl;
|
||||
return TestSkip;
|
||||
}
|
||||
|
||||
if (geteuid() != 0) {
|
||||
std::cout << "This test requires root permissions, skipping" << std::endl;
|
||||
return TestSkip;
|
||||
}
|
||||
|
||||
cm_ = new CameraManager();
|
||||
if (cm_->start()) {
|
||||
std::cout << "Failed to start camera manager" << std::endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
cameraAdded_ = false;
|
||||
cameraRemoved_ = false;
|
||||
|
||||
cm_->cameraAdded.connect(this, &HotplugTest::cameraAddedHandler);
|
||||
cm_->cameraRemoved.connect(this, &HotplugTest::cameraRemovedHandler);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int run()
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *dirent;
|
||||
std::string uvcDeviceDir;
|
||||
|
||||
dir = opendir(uvcDriverDir_.c_str());
|
||||
/* Find a UVC device directory, which we can bind/unbind. */
|
||||
while ((dirent = readdir(dir)) != nullptr) {
|
||||
if (!File::exists(uvcDriverDir_ + dirent->d_name + "/video4linux"))
|
||||
continue;
|
||||
|
||||
uvcDeviceDir = dirent->d_name;
|
||||
break;
|
||||
}
|
||||
closedir(dir);
|
||||
|
||||
/* If no UVC device found, skip the test. */
|
||||
if (uvcDeviceDir.empty())
|
||||
return TestSkip;
|
||||
|
||||
/* Unbind a camera and process events. */
|
||||
std::ofstream(uvcDriverDir_ + "unbind", std::ios::binary)
|
||||
<< uvcDeviceDir;
|
||||
Timer timer;
|
||||
timer.start(1000);
|
||||
while (timer.isRunning() && !cameraRemoved_)
|
||||
Thread::current()->eventDispatcher()->processEvents();
|
||||
if (!cameraRemoved_) {
|
||||
std::cout << "Camera unplug not detected" << std::endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
/* Bind the camera again and process events. */
|
||||
std::ofstream(uvcDriverDir_ + "bind", std::ios::binary)
|
||||
<< uvcDeviceDir;
|
||||
timer.start(1000);
|
||||
while (timer.isRunning() && !cameraAdded_)
|
||||
Thread::current()->eventDispatcher()->processEvents();
|
||||
if (!cameraAdded_) {
|
||||
std::cout << "Camera plug not detected" << std::endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
return TestPass;
|
||||
}
|
||||
|
||||
void cleanup()
|
||||
{
|
||||
cm_->stop();
|
||||
delete cm_;
|
||||
}
|
||||
|
||||
private:
|
||||
CameraManager *cm_;
|
||||
static const std::string uvcDriverDir_;
|
||||
bool cameraRemoved_;
|
||||
bool cameraAdded_;
|
||||
};
|
||||
|
||||
const std::string HotplugTest::uvcDriverDir_ = "/sys/bus/usb/drivers/uvcvideo/";
|
||||
|
||||
TEST_REGISTER(HotplugTest)
|
Loading…
Add table
Add a link
Reference in a new issue