From 8960ef9715cfb38a3b205d7916662f31df5ddd35 Mon Sep 17 00:00:00 2001 From: Umang Jain Date: Tue, 16 Jun 2020 19:45:39 +0000 Subject: 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 Reviewed-by: Laurent Pinchart Signed-off-by: Laurent Pinchart --- test/hotplug-cameras.cpp | 128 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 test/hotplug-cameras.cpp (limited to 'test/hotplug-cameras.cpp') diff --git a/test/hotplug-cameras.cpp b/test/hotplug-cameras.cpp new file mode 100644 index 00000000..6a94535f --- /dev/null +++ b/test/hotplug-cameras.cpp @@ -0,0 +1,128 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2020, Umang Jain + * + * hotplug-cameras.cpp - Test cameraAdded/cameraRemoved signals in CameraManager + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#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 cam) + { + cameraAdded_ = true; + } + + void cameraRemovedHandler(std::shared_ptr 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) -- cgit v1.2.1