From ed632bf37ebe94310d15f2ef8d25552fea88bafc Mon Sep 17 00:00:00 2001 From: Jacopo Mondi Date: Fri, 22 Dec 2023 17:22:40 +0100 Subject: apps: lc-compliance: Re-organize source directory Before adding more tests and more helper classes to lc-compliance, reorganize the source tree to split test and helpers in two separate directories. While at it, rename the 'SimpleCapture' class and its derived classes to just 'Capture'. Rename the source files accordingly. Re-sort headers inclusions to please checkstyle.py too. Signed-off-by: Jacopo Mondi Reviewed-by: Kieran Bingham Reviewed-by: Stefan Klug Tested-by: Stefan Klug --- src/apps/lc-compliance/capture_test.cpp | 135 ------------------ src/apps/lc-compliance/helpers/capture.cpp | 196 ++++++++++++++++++++++++++ src/apps/lc-compliance/helpers/capture.h | 66 +++++++++ src/apps/lc-compliance/meson.build | 10 +- src/apps/lc-compliance/simple_capture.cpp | 196 -------------------------- src/apps/lc-compliance/simple_capture.h | 66 --------- src/apps/lc-compliance/tests/capture_test.cpp | 136 ++++++++++++++++++ 7 files changed, 406 insertions(+), 399 deletions(-) delete mode 100644 src/apps/lc-compliance/capture_test.cpp create mode 100644 src/apps/lc-compliance/helpers/capture.cpp create mode 100644 src/apps/lc-compliance/helpers/capture.h delete mode 100644 src/apps/lc-compliance/simple_capture.cpp delete mode 100644 src/apps/lc-compliance/simple_capture.h create mode 100644 src/apps/lc-compliance/tests/capture_test.cpp diff --git a/src/apps/lc-compliance/capture_test.cpp b/src/apps/lc-compliance/capture_test.cpp deleted file mode 100644 index 1dcfcf92..00000000 --- a/src/apps/lc-compliance/capture_test.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2020, Google Inc. - * Copyright (C) 2021, Collabora Ltd. - * - * capture_test.cpp - Test camera capture - */ - -#include - -#include - -#include "environment.h" -#include "simple_capture.h" - -using namespace libcamera; - -const std::vector NUMREQUESTS = { 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 }; -const std::vector ROLES = { - StreamRole::Raw, - StreamRole::StillCapture, - StreamRole::VideoRecording, - StreamRole::Viewfinder -}; - -class SingleStream : public testing::TestWithParam> -{ -public: - static std::string nameParameters(const testing::TestParamInfo &info); - -protected: - void SetUp() override; - void TearDown() override; - - std::shared_ptr camera_; -}; - -/* - * We use gtest's SetUp() and TearDown() instead of constructor and destructor - * in order to be able to assert on them. - */ -void SingleStream::SetUp() -{ - Environment *env = Environment::get(); - - camera_ = env->cm()->get(env->cameraId()); - - ASSERT_EQ(camera_->acquire(), 0); -} - -void SingleStream::TearDown() -{ - if (!camera_) - return; - - camera_->release(); - camera_.reset(); -} - -std::string SingleStream::nameParameters(const testing::TestParamInfo &info) -{ - std::map rolesMap = { - { StreamRole::Raw, "Raw" }, - { StreamRole::StillCapture, "StillCapture" }, - { StreamRole::VideoRecording, "VideoRecording" }, - { StreamRole::Viewfinder, "Viewfinder" } - }; - - std::string roleName = rolesMap[std::get<0>(info.param)]; - std::string numRequestsName = std::to_string(std::get<1>(info.param)); - - return roleName + "_" + numRequestsName; -} - -/* - * Test single capture cycles - * - * Makes sure the camera completes the exact number of requests queued. Example - * failure is a camera that completes less requests than the number of requests - * queued. - */ -TEST_P(SingleStream, Capture) -{ - auto [role, numRequests] = GetParam(); - - SimpleCaptureBalanced capture(camera_); - - capture.configure(role); - - capture.capture(numRequests); -} - -/* - * Test multiple start/stop cycles - * - * Makes sure the camera supports multiple start/stop cycles. Example failure is - * a camera that does not clean up correctly in its error path but is only - * tested by single-capture applications. - */ -TEST_P(SingleStream, CaptureStartStop) -{ - auto [role, numRequests] = GetParam(); - unsigned int numRepeats = 3; - - SimpleCaptureBalanced capture(camera_); - - capture.configure(role); - - for (unsigned int starts = 0; starts < numRepeats; starts++) - capture.capture(numRequests); -} - -/* - * Test unbalanced stop - * - * Makes sure the camera supports a stop with requests queued. Example failure - * is a camera that does not handle cancelation of buffers coming back from the - * video device while stopping. - */ -TEST_P(SingleStream, UnbalancedStop) -{ - auto [role, numRequests] = GetParam(); - - SimpleCaptureUnbalanced capture(camera_); - - capture.configure(role); - - capture.capture(numRequests); -} - -INSTANTIATE_TEST_SUITE_P(CaptureTests, - SingleStream, - testing::Combine(testing::ValuesIn(ROLES), - testing::ValuesIn(NUMREQUESTS)), - SingleStream::nameParameters); diff --git a/src/apps/lc-compliance/helpers/capture.cpp b/src/apps/lc-compliance/helpers/capture.cpp new file mode 100644 index 00000000..5aab973f --- /dev/null +++ b/src/apps/lc-compliance/helpers/capture.cpp @@ -0,0 +1,196 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2020-2021, Google Inc. + * + * simple_capture.cpp - Simple capture helper + */ + +#include "capture.h" + +#include + +using namespace libcamera; + +Capture::Capture(std::shared_ptr camera) + : loop_(nullptr), camera_(camera), + allocator_(std::make_unique(camera)) +{ +} + +Capture::~Capture() +{ + stop(); +} + +void Capture::configure(StreamRole role) +{ + config_ = camera_->generateConfiguration({ role }); + + if (!config_) { + std::cout << "Role not supported by camera" << std::endl; + GTEST_SKIP(); + } + + if (config_->validate() != CameraConfiguration::Valid) { + config_.reset(); + FAIL() << "Configuration not valid"; + } + + if (camera_->configure(config_.get())) { + config_.reset(); + FAIL() << "Failed to configure camera"; + } +} + +void Capture::start() +{ + Stream *stream = config_->at(0).stream(); + int count = allocator_->allocate(stream); + + ASSERT_GE(count, 0) << "Failed to allocate buffers"; + EXPECT_EQ(count, config_->at(0).bufferCount) << "Allocated less buffers than expected"; + + camera_->requestCompleted.connect(this, &Capture::requestComplete); + + ASSERT_EQ(camera_->start(), 0) << "Failed to start camera"; +} + +void Capture::stop() +{ + if (!config_ || !allocator_->allocated()) + return; + + camera_->stop(); + + camera_->requestCompleted.disconnect(this); + + Stream *stream = config_->at(0).stream(); + requests_.clear(); + allocator_->free(stream); +} + +/* CaptureBalanced */ + +CaptureBalanced::CaptureBalanced(std::shared_ptr camera) + : Capture(camera) +{ +} + +void CaptureBalanced::capture(unsigned int numRequests) +{ + start(); + + Stream *stream = config_->at(0).stream(); + const std::vector> &buffers = allocator_->buffers(stream); + + /* No point in testing less requests then the camera depth. */ + if (buffers.size() > numRequests) { + std::cout << "Camera needs " + std::to_string(buffers.size()) + + " requests, can't test only " + + std::to_string(numRequests) << std::endl; + GTEST_SKIP(); + } + + queueCount_ = 0; + captureCount_ = 0; + captureLimit_ = numRequests; + + /* Queue the recommended number of requests. */ + for (const std::unique_ptr &buffer : buffers) { + std::unique_ptr request = camera_->createRequest(); + ASSERT_TRUE(request) << "Can't create request"; + + ASSERT_EQ(request->addBuffer(stream, buffer.get()), 0) << "Can't set buffer for request"; + + ASSERT_EQ(queueRequest(request.get()), 0) << "Failed to queue request"; + + requests_.push_back(std::move(request)); + } + + /* Run capture session. */ + loop_ = new EventLoop(); + loop_->exec(); + stop(); + delete loop_; + + ASSERT_EQ(captureCount_, captureLimit_); +} + +int CaptureBalanced::queueRequest(Request *request) +{ + queueCount_++; + if (queueCount_ > captureLimit_) + return 0; + + return camera_->queueRequest(request); +} + +void CaptureBalanced::requestComplete(Request *request) +{ + EXPECT_EQ(request->status(), Request::Status::RequestComplete) + << "Request didn't complete successfully"; + + captureCount_++; + if (captureCount_ >= captureLimit_) { + loop_->exit(0); + return; + } + + request->reuse(Request::ReuseBuffers); + if (queueRequest(request)) + loop_->exit(-EINVAL); +} + +/* CaptureUnbalanced */ + +CaptureUnbalanced::CaptureUnbalanced(std::shared_ptr camera) + : Capture(camera) +{ +} + +void CaptureUnbalanced::capture(unsigned int numRequests) +{ + start(); + + Stream *stream = config_->at(0).stream(); + const std::vector> &buffers = allocator_->buffers(stream); + + captureCount_ = 0; + captureLimit_ = numRequests; + + /* Queue the recommended number of requests. */ + for (const std::unique_ptr &buffer : buffers) { + std::unique_ptr request = camera_->createRequest(); + ASSERT_TRUE(request) << "Can't create request"; + + ASSERT_EQ(request->addBuffer(stream, buffer.get()), 0) << "Can't set buffer for request"; + + ASSERT_EQ(camera_->queueRequest(request.get()), 0) << "Failed to queue request"; + + requests_.push_back(std::move(request)); + } + + /* Run capture session. */ + loop_ = new EventLoop(); + int status = loop_->exec(); + stop(); + delete loop_; + + ASSERT_EQ(status, 0); +} + +void CaptureUnbalanced::requestComplete(Request *request) +{ + captureCount_++; + if (captureCount_ >= captureLimit_) { + loop_->exit(0); + return; + } + + EXPECT_EQ(request->status(), Request::Status::RequestComplete) + << "Request didn't complete successfully"; + + request->reuse(Request::ReuseBuffers); + if (camera_->queueRequest(request)) + loop_->exit(-EINVAL); +} diff --git a/src/apps/lc-compliance/helpers/capture.h b/src/apps/lc-compliance/helpers/capture.h new file mode 100644 index 00000000..0574ab1c --- /dev/null +++ b/src/apps/lc-compliance/helpers/capture.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2020-2021, Google Inc. + * + * simple_capture.h - Simple capture helper + */ + +#pragma once + +#include + +#include + +#include "../common/event_loop.h" + +class Capture +{ +public: + void configure(libcamera::StreamRole role); + +protected: + Capture(std::shared_ptr camera); + virtual ~Capture(); + + void start(); + void stop(); + + virtual void requestComplete(libcamera::Request *request) = 0; + + EventLoop *loop_; + + std::shared_ptr camera_; + std::unique_ptr allocator_; + std::unique_ptr config_; + std::vector> requests_; +}; + +class CaptureBalanced : public Capture +{ +public: + CaptureBalanced(std::shared_ptr camera); + + void capture(unsigned int numRequests); + +private: + int queueRequest(libcamera::Request *request); + void requestComplete(libcamera::Request *request) override; + + unsigned int queueCount_; + unsigned int captureCount_; + unsigned int captureLimit_; +}; + +class CaptureUnbalanced : public Capture +{ +public: + CaptureUnbalanced(std::shared_ptr camera); + + void capture(unsigned int numRequests); + +private: + void requestComplete(libcamera::Request *request) override; + + unsigned int captureCount_; + unsigned int captureLimit_; +}; diff --git a/src/apps/lc-compliance/meson.build b/src/apps/lc-compliance/meson.build index c792f072..b1f605f3 100644 --- a/src/apps/lc-compliance/meson.build +++ b/src/apps/lc-compliance/meson.build @@ -12,10 +12,15 @@ endif lc_compliance_enabled = true lc_compliance_sources = files([ - 'capture_test.cpp', 'environment.cpp', + 'helpers/capture.cpp', 'main.cpp', - 'simple_capture.cpp', + 'tests/capture_test.cpp', +]) + +lc_compliance_includes = ([ + include_directories('.'), + include_directories('helpers/') ]) lc_compliance = executable('lc-compliance', lc_compliance_sources, @@ -27,5 +32,6 @@ lc_compliance = executable('lc-compliance', lc_compliance_sources, libevent, libgtest, ], + include_directories : lc_compliance_includes, install : true, install_tag : 'bin-devel') diff --git a/src/apps/lc-compliance/simple_capture.cpp b/src/apps/lc-compliance/simple_capture.cpp deleted file mode 100644 index 545b444c..00000000 --- a/src/apps/lc-compliance/simple_capture.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2020-2021, Google Inc. - * - * simple_capture.cpp - Simple capture helper - */ - -#include - -#include "simple_capture.h" - -using namespace libcamera; - -SimpleCapture::SimpleCapture(std::shared_ptr camera) - : loop_(nullptr), camera_(camera), - allocator_(std::make_unique(camera)) -{ -} - -SimpleCapture::~SimpleCapture() -{ - stop(); -} - -void SimpleCapture::configure(StreamRole role) -{ - config_ = camera_->generateConfiguration({ role }); - - if (!config_) { - std::cout << "Role not supported by camera" << std::endl; - GTEST_SKIP(); - } - - if (config_->validate() != CameraConfiguration::Valid) { - config_.reset(); - FAIL() << "Configuration not valid"; - } - - if (camera_->configure(config_.get())) { - config_.reset(); - FAIL() << "Failed to configure camera"; - } -} - -void SimpleCapture::start() -{ - Stream *stream = config_->at(0).stream(); - int count = allocator_->allocate(stream); - - ASSERT_GE(count, 0) << "Failed to allocate buffers"; - EXPECT_EQ(count, config_->at(0).bufferCount) << "Allocated less buffers than expected"; - - camera_->requestCompleted.connect(this, &SimpleCapture::requestComplete); - - ASSERT_EQ(camera_->start(), 0) << "Failed to start camera"; -} - -void SimpleCapture::stop() -{ - if (!config_ || !allocator_->allocated()) - return; - - camera_->stop(); - - camera_->requestCompleted.disconnect(this); - - Stream *stream = config_->at(0).stream(); - requests_.clear(); - allocator_->free(stream); -} - -/* SimpleCaptureBalanced */ - -SimpleCaptureBalanced::SimpleCaptureBalanced(std::shared_ptr camera) - : SimpleCapture(camera) -{ -} - -void SimpleCaptureBalanced::capture(unsigned int numRequests) -{ - start(); - - Stream *stream = config_->at(0).stream(); - const std::vector> &buffers = allocator_->buffers(stream); - - /* No point in testing less requests then the camera depth. */ - if (buffers.size() > numRequests) { - std::cout << "Camera needs " + std::to_string(buffers.size()) - + " requests, can't test only " - + std::to_string(numRequests) << std::endl; - GTEST_SKIP(); - } - - queueCount_ = 0; - captureCount_ = 0; - captureLimit_ = numRequests; - - /* Queue the recommended number of requests. */ - for (const std::unique_ptr &buffer : buffers) { - std::unique_ptr request = camera_->createRequest(); - ASSERT_TRUE(request) << "Can't create request"; - - ASSERT_EQ(request->addBuffer(stream, buffer.get()), 0) << "Can't set buffer for request"; - - ASSERT_EQ(queueRequest(request.get()), 0) << "Failed to queue request"; - - requests_.push_back(std::move(request)); - } - - /* Run capture session. */ - loop_ = new EventLoop(); - loop_->exec(); - stop(); - delete loop_; - - ASSERT_EQ(captureCount_, captureLimit_); -} - -int SimpleCaptureBalanced::queueRequest(Request *request) -{ - queueCount_++; - if (queueCount_ > captureLimit_) - return 0; - - return camera_->queueRequest(request); -} - -void SimpleCaptureBalanced::requestComplete(Request *request) -{ - EXPECT_EQ(request->status(), Request::Status::RequestComplete) - << "Request didn't complete successfully"; - - captureCount_++; - if (captureCount_ >= captureLimit_) { - loop_->exit(0); - return; - } - - request->reuse(Request::ReuseBuffers); - if (queueRequest(request)) - loop_->exit(-EINVAL); -} - -/* SimpleCaptureUnbalanced */ - -SimpleCaptureUnbalanced::SimpleCaptureUnbalanced(std::shared_ptr camera) - : SimpleCapture(camera) -{ -} - -void SimpleCaptureUnbalanced::capture(unsigned int numRequests) -{ - start(); - - Stream *stream = config_->at(0).stream(); - const std::vector> &buffers = allocator_->buffers(stream); - - captureCount_ = 0; - captureLimit_ = numRequests; - - /* Queue the recommended number of requests. */ - for (const std::unique_ptr &buffer : buffers) { - std::unique_ptr request = camera_->createRequest(); - ASSERT_TRUE(request) << "Can't create request"; - - ASSERT_EQ(request->addBuffer(stream, buffer.get()), 0) << "Can't set buffer for request"; - - ASSERT_EQ(camera_->queueRequest(request.get()), 0) << "Failed to queue request"; - - requests_.push_back(std::move(request)); - } - - /* Run capture session. */ - loop_ = new EventLoop(); - int status = loop_->exec(); - stop(); - delete loop_; - - ASSERT_EQ(status, 0); -} - -void SimpleCaptureUnbalanced::requestComplete(Request *request) -{ - captureCount_++; - if (captureCount_ >= captureLimit_) { - loop_->exit(0); - return; - } - - EXPECT_EQ(request->status(), Request::Status::RequestComplete) - << "Request didn't complete successfully"; - - request->reuse(Request::ReuseBuffers); - if (camera_->queueRequest(request)) - loop_->exit(-EINVAL); -} diff --git a/src/apps/lc-compliance/simple_capture.h b/src/apps/lc-compliance/simple_capture.h deleted file mode 100644 index 2911d601..00000000 --- a/src/apps/lc-compliance/simple_capture.h +++ /dev/null @@ -1,66 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2020-2021, Google Inc. - * - * simple_capture.h - Simple capture helper - */ - -#pragma once - -#include - -#include - -#include "../common/event_loop.h" - -class SimpleCapture -{ -public: - void configure(libcamera::StreamRole role); - -protected: - SimpleCapture(std::shared_ptr camera); - virtual ~SimpleCapture(); - - void start(); - void stop(); - - virtual void requestComplete(libcamera::Request *request) = 0; - - EventLoop *loop_; - - std::shared_ptr camera_; - std::unique_ptr allocator_; - std::unique_ptr config_; - std::vector> requests_; -}; - -class SimpleCaptureBalanced : public SimpleCapture -{ -public: - SimpleCaptureBalanced(std::shared_ptr camera); - - void capture(unsigned int numRequests); - -private: - int queueRequest(libcamera::Request *request); - void requestComplete(libcamera::Request *request) override; - - unsigned int queueCount_; - unsigned int captureCount_; - unsigned int captureLimit_; -}; - -class SimpleCaptureUnbalanced : public SimpleCapture -{ -public: - SimpleCaptureUnbalanced(std::shared_ptr camera); - - void capture(unsigned int numRequests); - -private: - void requestComplete(libcamera::Request *request) override; - - unsigned int captureCount_; - unsigned int captureLimit_; -}; diff --git a/src/apps/lc-compliance/tests/capture_test.cpp b/src/apps/lc-compliance/tests/capture_test.cpp new file mode 100644 index 00000000..284d3630 --- /dev/null +++ b/src/apps/lc-compliance/tests/capture_test.cpp @@ -0,0 +1,136 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2020, Google Inc. + * Copyright (C) 2021, Collabora Ltd. + * + * capture_test.cpp - Test camera capture + */ + +#include "capture.h" + +#include + +#include + +#include "environment.h" + +using namespace libcamera; + +const std::vector NUMREQUESTS = { 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 }; +const std::vector ROLES = { + StreamRole::Raw, + StreamRole::StillCapture, + StreamRole::VideoRecording, + StreamRole::Viewfinder +}; + +class SingleStream : public testing::TestWithParam> +{ +public: + static std::string nameParameters(const testing::TestParamInfo &info); + +protected: + void SetUp() override; + void TearDown() override; + + std::shared_ptr camera_; +}; + +/* + * We use gtest's SetUp() and TearDown() instead of constructor and destructor + * in order to be able to assert on them. + */ +void SingleStream::SetUp() +{ + Environment *env = Environment::get(); + + camera_ = env->cm()->get(env->cameraId()); + + ASSERT_EQ(camera_->acquire(), 0); +} + +void SingleStream::TearDown() +{ + if (!camera_) + return; + + camera_->release(); + camera_.reset(); +} + +std::string SingleStream::nameParameters(const testing::TestParamInfo &info) +{ + std::map rolesMap = { + { StreamRole::Raw, "Raw" }, + { StreamRole::StillCapture, "StillCapture" }, + { StreamRole::VideoRecording, "VideoRecording" }, + { StreamRole::Viewfinder, "Viewfinder" } + }; + + std::string roleName = rolesMap[std::get<0>(info.param)]; + std::string numRequestsName = std::to_string(std::get<1>(info.param)); + + return roleName + "_" + numRequestsName; +} + +/* + * Test single capture cycles + * + * Makes sure the camera completes the exact number of requests queued. Example + * failure is a camera that completes less requests than the number of requests + * queued. + */ +TEST_P(SingleStream, Capture) +{ + auto [role, numRequests] = GetParam(); + + CaptureBalanced capture(camera_); + + capture.configure(role); + + capture.capture(numRequests); +} + +/* + * Test multiple start/stop cycles + * + * Makes sure the camera supports multiple start/stop cycles. Example failure is + * a camera that does not clean up correctly in its error path but is only + * tested by single-capture applications. + */ +TEST_P(SingleStream, CaptureStartStop) +{ + auto [role, numRequests] = GetParam(); + unsigned int numRepeats = 3; + + CaptureBalanced capture(camera_); + + capture.configure(role); + + for (unsigned int starts = 0; starts < numRepeats; starts++) + capture.capture(numRequests); +} + +/* + * Test unbalanced stop + * + * Makes sure the camera supports a stop with requests queued. Example failure + * is a camera that does not handle cancelation of buffers coming back from the + * video device while stopping. + */ +TEST_P(SingleStream, UnbalancedStop) +{ + auto [role, numRequests] = GetParam(); + + CaptureUnbalanced capture(camera_); + + capture.configure(role); + + capture.capture(numRequests); +} + +INSTANTIATE_TEST_SUITE_P(CaptureTests, + SingleStream, + testing::Combine(testing::ValuesIn(ROLES), + testing::ValuesIn(NUMREQUESTS)), + SingleStream::nameParameters); -- cgit v1.2.1